xref: /haiku/src/add-ons/kernel/file_systems/ntfs/libntfs/lcnalloc.c (revision b6b0567fbd186f8ce8a0c90bdc7a7b5b4c649678)
1 /**
2  * lcnalloc.c - Cluster (de)allocation code. Originated from the Linux-NTFS project.
3  *
4  * Copyright (c) 2002-2004 Anton Altaparmakov
5  * Copyright (c) 2004 Yura Pakhuchiy
6  * Copyright (c) 2004-2008 Szabolcs Szakacsits
7  *
8  * This program/include file is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as published
10  * by the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program/include file is distributed in the hope that it will be
14  * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
15  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program (in the main directory of the NTFS-3G
20  * distribution in the file COPYING); if not, write to the Free Software
21  * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  */
23 
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27 
28 #ifdef HAVE_STDLIB_H
29 #include <stdlib.h>
30 #endif
31 #ifdef HAVE_STDIO_H
32 #include <stdio.h>
33 #endif
34 #ifdef HAVE_ERRNO_H
35 #include <errno.h>
36 #endif
37 
38 #include "types.h"
39 #include "attrib.h"
40 #include "bitmap.h"
41 #include "debug.h"
42 #include "runlist.h"
43 #include "volume.h"
44 #include "lcnalloc.h"
45 #include "logging.h"
46 #include "misc.h"
47 
48 /*
49  * Plenty possibilities for big optimizations all over in the cluster
50  * allocation, however at the moment the dominant bottleneck (~ 90%) is
51  * the update of the mapping pairs which converges to the cubic Faulhaber's
52  * formula as the function of the number of extents (fragments, runs).
53  */
54 #define NTFS_LCNALLOC_BSIZE 4096
55 #define NTFS_LCNALLOC_SKIP  NTFS_LCNALLOC_BSIZE
56 
57 static void ntfs_cluster_set_zone_pos(LCN start, LCN end, LCN *pos, LCN tc)
58 {
59 	ntfs_log_trace("pos: %lld  tc: %lld\n", (long long)*pos, (long long)tc);
60 
61 	if (tc >= end)
62 		*pos = start;
63 	else if (tc >= start)
64 		*pos = tc;
65 }
66 
67 static void ntfs_cluster_update_zone_pos(ntfs_volume *vol, u8 zone, LCN tc)
68 {
69 	ntfs_log_trace("tc = %lld, zone = %d\n", (long long)tc, zone);
70 
71 	if (zone == 1)
72 		ntfs_cluster_set_zone_pos(vol->mft_lcn, vol->mft_zone_end,
73 					  &vol->mft_zone_pos, tc);
74 	else if (zone == 2)
75 		ntfs_cluster_set_zone_pos(vol->mft_zone_end, vol->nr_clusters,
76 					  &vol->data1_zone_pos, tc);
77 	else /* zone == 4 */
78 		ntfs_cluster_set_zone_pos(0, vol->mft_zone_start,
79 					  &vol->data2_zone_pos, tc);
80 }
81 
82 static s64 max_empty_bit_range(unsigned char *buf, int size)
83 {
84 	int i, j, run = 0;
85 	int max_range = 0;
86 	s64 start_pos = -1;
87 
88 	ntfs_log_trace("Entering\n");
89 
90 	for (i = 0; i < size; i++, buf++) {
91 
92 		if (*buf == 0) {
93 			run += 8;
94 			continue;
95 		}
96 
97 		for (j = 0; j < 8; j++) {
98 
99 			int bit = *buf & (1 << j);
100 
101 			if (bit) {
102 				if (run > max_range) {
103 					max_range = run;
104 					start_pos = i * 8 + j - run;
105 				}
106 				run = 0;
107 			} else
108 				run++;
109 		}
110 	}
111 
112 	if (run > max_range)
113 		start_pos = i * 8 - run;
114 
115 	return start_pos;
116 }
117 
118 static int bitmap_writeback(ntfs_volume *vol, s64 pos, s64 size, void *b,
119 			    u8 *writeback)
120 {
121 	s64 written;
122 
123 	ntfs_log_trace("Entering\n");
124 
125 	if (!*writeback)
126 		return 0;
127 
128 	*writeback = 0;
129 
130 	written = ntfs_attr_pwrite(vol->lcnbmp_na, pos, size, b);
131 	if (written != size) {
132 		if (!written)
133 			errno = EIO;
134 		ntfs_log_perror("Bitmap write error (%lld, %lld)",
135 				(long long)pos, (long long)size);
136 		return -1;
137 	}
138 
139 	return 0;
140 }
141 
142 /**
143  * ntfs_cluster_alloc - allocate clusters on an ntfs volume
144  * @vol:	mounted ntfs volume on which to allocate the clusters
145  * @start_vcn:	vcn to use for the first allocated cluster
146  * @count:	number of clusters to allocate
147  * @start_lcn:	starting lcn at which to allocate the clusters (or -1 if none)
148  * @zone:	zone from which to allocate the clusters
149  *
150  * Allocate @count clusters preferably starting at cluster @start_lcn or at the
151  * current allocator position if @start_lcn is -1, on the mounted ntfs volume
152  * @vol. @zone is either DATA_ZONE for allocation of normal clusters and
153  * MFT_ZONE for allocation of clusters for the master file table, i.e. the
154  * $MFT/$DATA attribute.
155  *
156  * On success return a runlist describing the allocated cluster(s).
157  *
158  * On error return NULL with errno set to the error code.
159  *
160  * Notes on the allocation algorithm
161  * =================================
162  *
163  * There are two data zones. First is the area between the end of the mft zone
164  * and the end of the volume, and second is the area between the start of the
165  * volume and the start of the mft zone. On unmodified/standard NTFS 1.x
166  * volumes, the second data zone doesn't exist due to the mft zone being
167  * expanded to cover the start of the volume in order to reserve space for the
168  * mft bitmap attribute.
169  *
170  * The complexity stems from the need of implementing the mft vs data zoned
171  * approach and from the fact that we have access to the lcn bitmap via up to
172  * NTFS_LCNALLOC_BSIZE bytes at a time, so we need to cope with crossing over
173  * boundaries of two buffers. Further, the fact that the allocator allows for
174  * caller supplied hints as to the location of where allocation should begin
175  * and the fact that the allocator keeps track of where in the data zones the
176  * next natural allocation should occur, contribute to the complexity of the
177  * function. But it should all be worthwhile, because this allocator:
178  *   1) implements MFT zone reservation
179  *   2) causes reduction in fragmentation.
180  * The code is not optimized for speed.
181  */
182 runlist *ntfs_cluster_alloc(ntfs_volume *vol, VCN start_vcn, s64 count,
183 		LCN start_lcn, const NTFS_CLUSTER_ALLOCATION_ZONES zone)
184 {
185 	LCN zone_start, zone_end;  /* current search range */
186 	LCN last_read_pos, lcn;
187 	LCN bmp_pos;		/* current bit position inside the bitmap */
188 	LCN prev_lcn = 0, prev_run_len = 0;
189 	s64 clusters, br;
190 	runlist *rl = NULL, *trl;
191 	u8 *buf, *byte, bit, writeback;
192 	u8 pass = 1; 	/* 1: inside zone;  2: start of zone */
193 	u8 search_zone; /* 4: data2 (start) 1: mft (middle) 2: data1 (end) */
194 	u8 done_zones = 0;
195 	u8 has_guess, used_zone_pos;
196 	int err = 0, rlpos, rlsize, buf_size;
197 
198 	ntfs_log_enter("Entering with count = 0x%llx, start_lcn = 0x%llx, "
199 		       "zone = %s_ZONE.\n", (long long)count, (long long)
200 		       start_lcn, zone == MFT_ZONE ? "MFT" : "DATA");
201 
202 	if (!vol || count < 0 || start_lcn < -1 || !vol->lcnbmp_na ||
203 			(s8)zone < FIRST_ZONE || zone > LAST_ZONE) {
204 		errno = EINVAL;
205 		ntfs_log_perror("%s: vcn: %lld, count: %lld, lcn: %lld",
206 				__FUNCTION__, (long long)start_vcn,
207 				(long long)count, (long long)start_lcn);
208 		goto out;
209 	}
210 
211 	/* Return empty runlist if @count == 0 */
212 	if (!count) {
213 		rl = ntfs_malloc(0x1000);
214 		if (rl) {
215 			rl[0].vcn = start_vcn;
216 			rl[0].lcn = LCN_RL_NOT_MAPPED;
217 			rl[0].length = 0;
218 		}
219 		goto out;
220 	}
221 
222 	buf = ntfs_malloc(NTFS_LCNALLOC_BSIZE);
223 	if (!buf)
224 		goto out;
225 	/*
226 	 * If no @start_lcn was requested, use the current zone
227 	 * position otherwise use the requested @start_lcn.
228 	 */
229 	has_guess = 1;
230 	zone_start = start_lcn;
231 
232 	if (zone_start < 0) {
233 		if (zone == DATA_ZONE)
234 			zone_start = vol->data1_zone_pos;
235 		else
236 			zone_start = vol->mft_zone_pos;
237 		has_guess = 0;
238 	}
239 
240 	used_zone_pos = has_guess ? 0 : 1;
241 
242 	if (!zone_start || zone_start == vol->mft_zone_start ||
243 			zone_start == vol->mft_zone_end)
244 		pass = 2;
245 
246 	if (zone_start < vol->mft_zone_start) {
247 		zone_end = vol->mft_zone_start;
248 		search_zone = 4;
249 	} else if (zone_start < vol->mft_zone_end) {
250 		zone_end = vol->mft_zone_end;
251 		search_zone = 1;
252 	} else {
253 		zone_end = vol->nr_clusters;
254 		search_zone = 2;
255 	}
256 
257 	bmp_pos = zone_start;
258 
259 	/* Loop until all clusters are allocated. */
260 	clusters = count;
261 	rlpos = rlsize = 0;
262 	while (1) {
263 		last_read_pos = bmp_pos >> 3;
264 		br = ntfs_attr_pread(vol->lcnbmp_na, last_read_pos,
265 				     NTFS_LCNALLOC_BSIZE, buf);
266 		if (br <= 0) {
267 			if (!br)
268 				goto zone_pass_done;
269 			err = errno;
270 			ntfs_log_perror("Reading $BITMAP failed");
271 			goto err_ret;
272 		}
273 		/*
274 		 * We might have read less than NTFS_LCNALLOC_BSIZE bytes
275 		 * if we are close to the end of the attribute.
276 		 */
277 		buf_size = (int)br << 3;
278 		lcn = bmp_pos & 7;
279 		bmp_pos &= ~7;
280 		writeback = 0;
281 
282 		while (lcn < buf_size) {
283 			byte = buf + (lcn >> 3);
284 			bit = 1 << (lcn & 7);
285 			if (has_guess) {
286 				if (*byte & bit) {
287 					has_guess = 0;
288 					break;
289 				}
290 			} else {
291 				lcn = max_empty_bit_range(buf, br);
292 				if (lcn < 0)
293 					break;
294 				has_guess = 1;
295 				continue;
296 			}
297 
298 			/* First free bit is at lcn + bmp_pos. */
299 
300 			/* Reallocate memory if necessary. */
301 			if ((rlpos + 2) * (int)sizeof(runlist) >= rlsize) {
302 				rlsize += 4096;
303 				trl = realloc(rl, rlsize);
304 				if (!trl) {
305 					err = ENOMEM;
306 					ntfs_log_perror("realloc() failed");
307 					goto wb_err_ret;
308 				}
309 				rl = trl;
310 			}
311 
312 			/* Allocate the bitmap bit. */
313 			*byte |= bit;
314 			writeback = 1;
315 			if (vol->free_clusters <= 0)
316 				ntfs_log_error("Non-positive free clusters "
317 					       "(%lld)!\n",
318 						(long long)vol->free_clusters);
319 			else
320 				vol->free_clusters--;
321 
322 			/*
323 			 * Coalesce with previous run if adjacent LCNs.
324 			 * Otherwise, append a new run.
325 			 */
326 			if (prev_lcn == lcn + bmp_pos - prev_run_len && rlpos) {
327 				ntfs_log_debug("Cluster coalesce: prev_lcn: "
328 					       "%lld  lcn: %lld  bmp_pos: %lld  "
329 					       "prev_run_len: %lld\n",
330 					       (long long)prev_lcn,
331 					       (long long)lcn, (long long)bmp_pos,
332 					       (long long)prev_run_len);
333 				rl[rlpos - 1].length = ++prev_run_len;
334 			} else {
335 				if (rlpos)
336 					rl[rlpos].vcn = rl[rlpos - 1].vcn +
337 							prev_run_len;
338 				else {
339 					rl[rlpos].vcn = start_vcn;
340 					ntfs_log_debug("Start_vcn: %lld\n",
341 						       (long long)start_vcn);
342 				}
343 
344 				rl[rlpos].lcn = prev_lcn = lcn + bmp_pos;
345 				rl[rlpos].length = prev_run_len = 1;
346 				rlpos++;
347 			}
348 
349 			ntfs_log_debug("RUN:   %-16lld %-16lld %-16lld\n",
350 				       (long long)rl[rlpos - 1].vcn,
351 				       (long long)rl[rlpos - 1].lcn,
352 				       (long long)rl[rlpos - 1].length);
353 			/* Done? */
354 			if (!--clusters) {
355 				if (used_zone_pos)
356 					ntfs_cluster_update_zone_pos(vol,
357 						search_zone, lcn + bmp_pos + 1 +
358 							NTFS_LCNALLOC_SKIP);
359 				goto done_ret;
360 			}
361 
362 			lcn++;
363 		}
364 
365 		if (bitmap_writeback(vol, last_read_pos, br, buf, &writeback)) {
366 			err = errno;
367 			goto err_ret;
368 		}
369 
370 		if (!used_zone_pos) {
371 
372 			used_zone_pos = 1;
373 
374 			if (search_zone == 1)
375 				zone_start = vol->mft_zone_pos;
376 			else if (search_zone == 2)
377 				zone_start = vol->data1_zone_pos;
378 			else
379 				zone_start = vol->data2_zone_pos;
380 
381 			if (!zone_start || zone_start == vol->mft_zone_start ||
382 					zone_start == vol->mft_zone_end)
383 				pass = 2;
384 			bmp_pos = zone_start;
385 		} else
386 			bmp_pos += buf_size;
387 
388 		if (bmp_pos < zone_end)
389 			continue;
390 
391 zone_pass_done:
392 		ntfs_log_trace("Finished current zone pass(%i).\n", pass);
393 		if (pass == 1) {
394 
395 			pass = 2;
396 			zone_end = zone_start;
397 
398 			if (search_zone == 1)
399 				zone_start = vol->mft_zone_start;
400 			else if (search_zone == 2)
401 				zone_start = vol->mft_zone_end;
402 			else
403 				zone_start = 0;
404 
405 			/* Sanity check. */
406 			if (zone_end < zone_start)
407 				zone_end = zone_start;
408 
409 			bmp_pos = zone_start;
410 
411 			continue;
412 		}
413 		/* pass == 2 */
414 done_zones_check:
415 		done_zones |= search_zone;
416 		if (done_zones < 7) {
417 			ntfs_log_trace("Switching zone.\n");
418 			pass = 1;
419 			if (rlpos) {
420 				LCN tc = tc = rl[rlpos - 1].lcn +
421 				      rl[rlpos - 1].length + NTFS_LCNALLOC_SKIP;
422 
423 				if (used_zone_pos)
424 					ntfs_cluster_update_zone_pos(vol,
425 						search_zone, tc);
426 			}
427 
428 			switch (search_zone) {
429 			case 1:
430 				ntfs_log_trace("Zone switch: mft -> data1\n");
431 switch_to_data1_zone:		search_zone = 2;
432 				zone_start = vol->data1_zone_pos;
433 				zone_end = vol->nr_clusters;
434 				if (zone_start == vol->mft_zone_end)
435 					pass = 2;
436 				break;
437 			case 2:
438 				ntfs_log_trace("Zone switch: data1 -> data2\n");
439 				search_zone = 4;
440 				zone_start = vol->data2_zone_pos;
441 				zone_end = vol->mft_zone_start;
442 				if (!zone_start)
443 					pass = 2;
444 				break;
445 			case 4:
446 				if (!(done_zones & 2)) {
447 					ntfs_log_trace("data2 -> data1\n");
448 					goto switch_to_data1_zone;
449 				}
450 				ntfs_log_trace("Zone switch: data2 -> mft\n");
451 				search_zone = 1;
452 				zone_start = vol->mft_zone_pos;
453 				zone_end = vol->mft_zone_end;
454 				if (zone_start == vol->mft_zone_start)
455 					pass = 2;
456 				break;
457 			}
458 
459 			bmp_pos = zone_start;
460 
461 			if (zone_start == zone_end) {
462 				ntfs_log_trace("Empty zone, skipped.\n");
463 				goto done_zones_check;
464 			}
465 
466 			continue;
467 		}
468 
469 		ntfs_log_trace("All zones are finished, no space on device.\n");
470 		err = ENOSPC;
471 		goto err_ret;
472 	}
473 done_ret:
474 	ntfs_log_debug("At done_ret.\n");
475 	/* Add runlist terminator element. */
476 	rl[rlpos].vcn = rl[rlpos - 1].vcn + rl[rlpos - 1].length;
477 	rl[rlpos].lcn = LCN_RL_NOT_MAPPED;
478 	rl[rlpos].length = 0;
479 	if (bitmap_writeback(vol, last_read_pos, br, buf, &writeback)) {
480 		err = errno;
481 		goto err_ret;
482 	}
483 done_err_ret:
484 	free(buf);
485 	if (err) {
486 		errno = err;
487 		ntfs_log_perror("Failed to allocate clusters");
488 		rl = NULL;
489 	}
490 out:
491 	ntfs_log_leave("\n");
492 	return rl;
493 
494 wb_err_ret:
495 	ntfs_log_trace("At wb_err_ret.\n");
496 	if (bitmap_writeback(vol, last_read_pos, br, buf, &writeback))
497 		err = errno;
498 err_ret:
499 	ntfs_log_trace("At err_ret.\n");
500 	if (rl) {
501 		/* Add runlist terminator element. */
502 		rl[rlpos].vcn = rl[rlpos - 1].vcn + rl[rlpos - 1].length;
503 		rl[rlpos].lcn = LCN_RL_NOT_MAPPED;
504 		rl[rlpos].length = 0;
505 		ntfs_debug_runlist_dump(rl);
506 		ntfs_cluster_free_from_rl(vol, rl);
507 		free(rl);
508 		rl = NULL;
509 	}
510 	goto done_err_ret;
511 }
512 
513 /**
514  * ntfs_cluster_free_from_rl - free clusters from runlist
515  * @vol:	mounted ntfs volume on which to free the clusters
516  * @rl:		runlist from which deallocate clusters
517  *
518  * On success return 0 and on error return -1 with errno set to the error code.
519  */
520 int ntfs_cluster_free_from_rl(ntfs_volume *vol, runlist *rl)
521 {
522 	s64 nr_freed = 0;
523 	int ret = -1;
524 
525 	ntfs_log_trace("Entering.\n");
526 
527 	for (; rl->length; rl++) {
528 
529 		ntfs_log_trace("Dealloc lcn 0x%llx, len 0x%llx.\n",
530 			       (long long)rl->lcn, (long long)rl->length);
531 
532 		if (rl->lcn >= 0) {
533 			if (ntfs_bitmap_clear_run(vol->lcnbmp_na, rl->lcn,
534 						  rl->length)) {
535 				ntfs_log_perror("Cluster deallocation failed "
536 					       "(%lld, %lld)",
537 						(long long)rl->lcn,
538 						(long long)rl->length);
539 				goto out;
540 			}
541 			nr_freed += rl->length ;
542 		}
543 	}
544 
545 	ret = 0;
546 out:
547 	vol->free_clusters += nr_freed;
548 	if (vol->free_clusters > vol->nr_clusters)
549 		ntfs_log_error("Too many free clusters (%lld > %lld)!",
550 			       (long long)vol->free_clusters,
551 			       (long long)vol->nr_clusters);
552 	return ret;
553 }
554 
555 /**
556  * ntfs_cluster_free - free clusters on an ntfs volume
557  * @vol:	mounted ntfs volume on which to free the clusters
558  * @na:		attribute whose runlist describes the clusters to free
559  * @start_vcn:	vcn in @rl at which to start freeing clusters
560  * @count:	number of clusters to free or -1 for all clusters
561  *
562  * Free @count clusters starting at the cluster @start_vcn in the runlist
563  * described by the attribute @na from the mounted ntfs volume @vol.
564  *
565  * If @count is -1, all clusters from @start_vcn to the end of the runlist
566  * are deallocated.
567  *
568  * On success return the number of deallocated clusters (not counting sparse
569  * clusters) and on error return -1 with errno set to the error code.
570  */
571 int ntfs_cluster_free(ntfs_volume *vol, ntfs_attr *na, VCN start_vcn, s64 count)
572 {
573 	runlist *rl;
574 	s64 delta, to_free, nr_freed = 0;
575 	int ret = -1;
576 
577 	if (!vol || !vol->lcnbmp_na || !na || start_vcn < 0 ||
578 			(count < 0 && count != -1)) {
579 		ntfs_log_trace("Invalid arguments!\n");
580 		errno = EINVAL;
581 		return -1;
582 	}
583 
584 	ntfs_log_enter("Entering for inode 0x%llx, attr 0x%x, count 0x%llx, "
585 		       "vcn 0x%llx.\n", (unsigned long long)na->ni->mft_no,
586 		       na->type, (long long)count, (long long)start_vcn);
587 
588 	rl = ntfs_attr_find_vcn(na, start_vcn);
589 	if (!rl) {
590 		if (errno == ENOENT)
591 			ret = 0;
592 		goto leave;
593 	}
594 
595 	if (rl->lcn < 0 && rl->lcn != LCN_HOLE) {
596 		errno = EIO;
597 		ntfs_log_perror("%s: Unexpected lcn (%lld)", __FUNCTION__,
598 				(long long)rl->lcn);
599 		goto leave;
600 	}
601 
602 	/* Find the starting cluster inside the run that needs freeing. */
603 	delta = start_vcn - rl->vcn;
604 
605 	/* The number of clusters in this run that need freeing. */
606 	to_free = rl->length - delta;
607 	if (count >= 0 && to_free > count)
608 		to_free = count;
609 
610 	if (rl->lcn != LCN_HOLE) {
611 		/* Do the actual freeing of the clusters in this run. */
612 		if (ntfs_bitmap_clear_run(vol->lcnbmp_na, rl->lcn + delta,
613 					  to_free))
614 			goto leave;
615 		nr_freed = to_free;
616 	}
617 
618 	/* Go to the next run and adjust the number of clusters left to free. */
619 	++rl;
620 	if (count >= 0)
621 		count -= to_free;
622 
623 	/*
624 	 * Loop over the remaining runs, using @count as a capping value, and
625 	 * free them.
626 	 */
627 	for (; rl->length && count != 0; ++rl) {
628 		// FIXME: Need to try ntfs_attr_map_runlist() for attribute
629 		//	  list support! (AIA)
630 		if (rl->lcn < 0 && rl->lcn != LCN_HOLE) {
631 			// FIXME: Eeek! We need rollback! (AIA)
632 			errno = EIO;
633 			ntfs_log_perror("%s: Invalid lcn (%lli)",
634 					__FUNCTION__, (long long)rl->lcn);
635 			goto out;
636 		}
637 
638 		/* The number of clusters in this run that need freeing. */
639 		to_free = rl->length;
640 		if (count >= 0 && to_free > count)
641 			to_free = count;
642 
643 		if (rl->lcn != LCN_HOLE) {
644 			if (ntfs_bitmap_clear_run(vol->lcnbmp_na, rl->lcn,
645 					to_free)) {
646 				// FIXME: Eeek! We need rollback! (AIA)
647 				ntfs_log_perror("%s: Clearing bitmap run failed",
648 						__FUNCTION__);
649 				goto out;
650 			}
651 			nr_freed += to_free;
652 		}
653 
654 		if (count >= 0)
655 			count -= to_free;
656 	}
657 
658 	if (count != -1 && count != 0) {
659 		// FIXME: Eeek! BUG()
660 		errno = EIO;
661 		ntfs_log_perror("%s: count still not zero (%lld)", __FUNCTION__,
662 			       (long long)count);
663 		goto out;
664 	}
665 
666 	ret = nr_freed;
667 out:
668 	vol->free_clusters += nr_freed ;
669 	if (vol->free_clusters > vol->nr_clusters)
670 		ntfs_log_error("Too many free clusters (%lld > %lld)!",
671 			       (long long)vol->free_clusters,
672 			       (long long)vol->nr_clusters);
673 leave:
674 	ntfs_log_leave("\n");
675 	return ret;
676 }
677