2 * lcnalloc.c - Cluster (de)allocation code. Originated from the Linux-NTFS project.
4 * Copyright (c) 2002-2004 Anton Altaparmakov
5 * Copyright (c) 2004 Yura Pakhuchiy
6 * Copyright (c) 2004-2008 Szabolcs Szakacsits
7 * Copyright (c) 2008-2009 Jean-Pierre Andre
9 * This program/include file is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as published
11 * by the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program/include file is distributed in the hope that it will be
15 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
16 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program (in the main directory of the NTFS-3G
21 * distribution in the file COPYING); if not, write to the Free Software
22 * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
50 * Plenty possibilities for big optimizations all over in the cluster
51 * allocation, however at the moment the dominant bottleneck (~ 90%) is
52 * the update of the mapping pairs which converges to the cubic Faulhaber's
53 * formula as the function of the number of extents (fragments, runs).
55 #define NTFS_LCNALLOC_BSIZE 4096
56 #define NTFS_LCNALLOC_SKIP NTFS_LCNALLOC_BSIZE
64 static void ntfs_cluster_set_zone_pos(LCN start
, LCN end
, LCN
*pos
, LCN tc
)
66 ntfs_log_trace("pos: %lld tc: %lld\n", (long long)*pos
, (long long)tc
);
74 static void ntfs_cluster_update_zone_pos(ntfs_volume
*vol
, u8 zone
, LCN tc
)
76 ntfs_log_trace("tc = %lld, zone = %d\n", (long long)tc
, zone
);
79 ntfs_cluster_set_zone_pos(vol
->mft_lcn
, vol
->mft_zone_end
,
80 &vol
->mft_zone_pos
, tc
);
81 else if (zone
== ZONE_DATA1
)
82 ntfs_cluster_set_zone_pos(vol
->mft_zone_end
, vol
->nr_clusters
,
83 &vol
->data1_zone_pos
, tc
);
84 else /* zone == ZONE_DATA2 */
85 ntfs_cluster_set_zone_pos(0, vol
->mft_zone_start
,
86 &vol
->data2_zone_pos
, tc
);
90 * Unmark full zones when a cluster has been freed in a full zone
92 * Next allocation will reuse the freed cluster
95 static void update_full_status(ntfs_volume
*vol
, LCN lcn
)
97 if (lcn
>= vol
->mft_zone_end
) {
98 if (vol
->full_zones
& ZONE_DATA1
) {
99 ntfs_cluster_update_zone_pos(vol
, ZONE_DATA1
, lcn
);
100 vol
->full_zones
&= ~ZONE_DATA1
;
103 if (lcn
< vol
->mft_zone_start
) {
104 if (vol
->full_zones
& ZONE_DATA2
) {
105 ntfs_cluster_update_zone_pos(vol
, ZONE_DATA2
, lcn
);
106 vol
->full_zones
&= ~ZONE_DATA2
;
109 if (vol
->full_zones
& ZONE_MFT
) {
110 ntfs_cluster_update_zone_pos(vol
, ZONE_MFT
, lcn
);
111 vol
->full_zones
&= ~ZONE_MFT
;
116 static s64
max_empty_bit_range(unsigned char *buf
, int size
)
122 ntfs_log_trace("Entering\n");
132 } while ((i
< size
) && !*buf
);
135 if (run
> max_range
) {
137 start_pos
= (s64
)i
* 8 - run
;
143 } while ((i
< size
) && (*buf
== 255));
146 for (j
= 0; j
< 8; j
++) {
148 int bit
= *buf
& (1 << j
);
151 if (run
> max_range
) {
153 start_pos
= (s64
)i
* 8 + (j
- run
);
166 start_pos
= (s64
)i
* 8 - run
;
171 static int bitmap_writeback(ntfs_volume
*vol
, s64 pos
, s64 size
, void *b
,
176 ntfs_log_trace("Entering\n");
183 written
= ntfs_attr_pwrite(vol
->lcnbmp_na
, pos
, size
, b
);
184 if (written
!= size
) {
187 ntfs_log_perror("Bitmap write error (%lld, %lld)",
188 (long long)pos
, (long long)size
);
196 * ntfs_cluster_alloc - allocate clusters on an ntfs volume
197 * @vol: mounted ntfs volume on which to allocate the clusters
198 * @start_vcn: vcn to use for the first allocated cluster
199 * @count: number of clusters to allocate
200 * @start_lcn: starting lcn at which to allocate the clusters (or -1 if none)
201 * @zone: zone from which to allocate the clusters
203 * Allocate @count clusters preferably starting at cluster @start_lcn or at the
204 * current allocator position if @start_lcn is -1, on the mounted ntfs volume
205 * @vol. @zone is either DATA_ZONE for allocation of normal clusters and
206 * MFT_ZONE for allocation of clusters for the master file table, i.e. the
207 * $MFT/$DATA attribute.
209 * On success return a runlist describing the allocated cluster(s).
211 * On error return NULL with errno set to the error code.
213 * Notes on the allocation algorithm
214 * =================================
216 * There are two data zones. First is the area between the end of the mft zone
217 * and the end of the volume, and second is the area between the start of the
218 * volume and the start of the mft zone. On unmodified/standard NTFS 1.x
219 * volumes, the second data zone doesn't exist due to the mft zone being
220 * expanded to cover the start of the volume in order to reserve space for the
221 * mft bitmap attribute.
223 * The complexity stems from the need of implementing the mft vs data zoned
224 * approach and from the fact that we have access to the lcn bitmap via up to
225 * NTFS_LCNALLOC_BSIZE bytes at a time, so we need to cope with crossing over
226 * boundaries of two buffers. Further, the fact that the allocator allows for
227 * caller supplied hints as to the location of where allocation should begin
228 * and the fact that the allocator keeps track of where in the data zones the
229 * next natural allocation should occur, contribute to the complexity of the
230 * function. But it should all be worthwhile, because this allocator:
231 * 1) implements MFT zone reservation
232 * 2) causes reduction in fragmentation.
233 * The code is not optimized for speed.
235 runlist
*ntfs_cluster_alloc(ntfs_volume
*vol
, VCN start_vcn
, s64 count
,
236 LCN start_lcn
, const NTFS_CLUSTER_ALLOCATION_ZONES zone
)
238 LCN zone_start
, zone_end
; /* current search range */
239 LCN last_read_pos
, lcn
;
240 LCN bmp_pos
; /* current bit position inside the bitmap */
241 LCN prev_lcn
= 0, prev_run_len
= 0;
243 runlist
*rl
= NULL
, *trl
;
244 u8
*buf
, *byte
, bit
, writeback
;
245 u8 pass
= 1; /* 1: inside zone; 2: start of zone */
246 u8 search_zone
; /* 4: data2 (start) 1: mft (middle) 2: data1 (end) */
248 u8 has_guess
, used_zone_pos
;
249 int err
= 0, rlpos
, rlsize
, buf_size
;
251 ntfs_log_enter("Entering with count = 0x%llx, start_lcn = 0x%llx, "
252 "zone = %s_ZONE.\n", (long long)count
, (long long)
253 start_lcn
, zone
== MFT_ZONE
? "MFT" : "DATA");
255 if (!vol
|| count
< 0 || start_lcn
< -1 || !vol
->lcnbmp_na
||
256 (s8
)zone
< FIRST_ZONE
|| zone
> LAST_ZONE
) {
258 ntfs_log_perror("%s: vcn: %lld, count: %lld, lcn: %lld",
259 __FUNCTION__
, (long long)start_vcn
,
260 (long long)count
, (long long)start_lcn
);
264 /* Return empty runlist if @count == 0 */
266 rl
= ntfs_malloc(0x1000);
268 rl
[0].vcn
= start_vcn
;
269 rl
[0].lcn
= LCN_RL_NOT_MAPPED
;
275 buf
= ntfs_malloc(NTFS_LCNALLOC_BSIZE
);
279 * If no @start_lcn was requested, use the current zone
280 * position otherwise use the requested @start_lcn.
283 zone_start
= start_lcn
;
285 if (zone_start
< 0) {
286 if (zone
== DATA_ZONE
)
287 zone_start
= vol
->data1_zone_pos
;
289 zone_start
= vol
->mft_zone_pos
;
293 used_zone_pos
= has_guess
? 0 : 1;
295 if (!zone_start
|| zone_start
== vol
->mft_zone_start
||
296 zone_start
== vol
->mft_zone_end
)
299 if (zone_start
< vol
->mft_zone_start
) {
300 zone_end
= vol
->mft_zone_start
;
301 search_zone
= ZONE_DATA2
;
302 } else if (zone_start
< vol
->mft_zone_end
) {
303 zone_end
= vol
->mft_zone_end
;
304 search_zone
= ZONE_MFT
;
306 zone_end
= vol
->nr_clusters
;
307 search_zone
= ZONE_DATA1
;
310 bmp_pos
= zone_start
;
312 /* Loop until all clusters are allocated. */
316 /* check whether we have exhausted the current zone */
317 if (search_zone
& vol
->full_zones
)
319 last_read_pos
= bmp_pos
>> 3;
320 br
= ntfs_attr_pread(vol
->lcnbmp_na
, last_read_pos
,
321 NTFS_LCNALLOC_BSIZE
, buf
);
326 ntfs_log_perror("Reading $BITMAP failed");
330 * We might have read less than NTFS_LCNALLOC_BSIZE bytes
331 * if we are close to the end of the attribute.
333 buf_size
= (int)br
<< 3;
338 while (lcn
< buf_size
) {
339 byte
= buf
+ (lcn
>> 3);
340 bit
= 1 << (lcn
& 7);
347 lcn
= max_empty_bit_range(buf
, br
);
354 /* First free bit is at lcn + bmp_pos. */
356 /* Reallocate memory if necessary. */
357 if ((rlpos
+ 2) * (int)sizeof(runlist
) >= rlsize
) {
359 trl
= realloc(rl
, rlsize
);
362 ntfs_log_perror("realloc() failed");
368 /* Allocate the bitmap bit. */
371 if (vol
->free_clusters
<= 0)
372 ntfs_log_error("Non-positive free clusters "
374 (long long)vol
->free_clusters
);
376 vol
->free_clusters
--;
379 * Coalesce with previous run if adjacent LCNs.
380 * Otherwise, append a new run.
382 if (prev_lcn
== lcn
+ bmp_pos
- prev_run_len
&& rlpos
) {
383 ntfs_log_debug("Cluster coalesce: prev_lcn: "
384 "%lld lcn: %lld bmp_pos: %lld "
385 "prev_run_len: %lld\n",
387 (long long)lcn
, (long long)bmp_pos
,
388 (long long)prev_run_len
);
389 rl
[rlpos
- 1].length
= ++prev_run_len
;
392 rl
[rlpos
].vcn
= rl
[rlpos
- 1].vcn
+
395 rl
[rlpos
].vcn
= start_vcn
;
396 ntfs_log_debug("Start_vcn: %lld\n",
397 (long long)start_vcn
);
400 rl
[rlpos
].lcn
= prev_lcn
= lcn
+ bmp_pos
;
401 rl
[rlpos
].length
= prev_run_len
= 1;
405 ntfs_log_debug("RUN: %-16lld %-16lld %-16lld\n",
406 (long long)rl
[rlpos
- 1].vcn
,
407 (long long)rl
[rlpos
- 1].lcn
,
408 (long long)rl
[rlpos
- 1].length
);
412 ntfs_cluster_update_zone_pos(vol
,
413 search_zone
, lcn
+ bmp_pos
+ 1 +
421 if (bitmap_writeback(vol
, last_read_pos
, br
, buf
, &writeback
)) {
426 if (!used_zone_pos
) {
430 if (search_zone
== ZONE_MFT
)
431 zone_start
= vol
->mft_zone_pos
;
432 else if (search_zone
== ZONE_DATA1
)
433 zone_start
= vol
->data1_zone_pos
;
435 zone_start
= vol
->data2_zone_pos
;
437 if (!zone_start
|| zone_start
== vol
->mft_zone_start
||
438 zone_start
== vol
->mft_zone_end
)
440 bmp_pos
= zone_start
;
444 if (bmp_pos
< zone_end
)
448 ntfs_log_trace("Finished current zone pass(%i).\n", pass
);
451 zone_end
= zone_start
;
453 if (search_zone
== ZONE_MFT
)
454 zone_start
= vol
->mft_zone_start
;
455 else if (search_zone
== ZONE_DATA1
)
456 zone_start
= vol
->mft_zone_end
;
461 if (zone_end
< zone_start
)
462 zone_end
= zone_start
;
464 bmp_pos
= zone_start
;
470 done_zones
|= search_zone
;
471 vol
->full_zones
|= search_zone
;
472 if (done_zones
< (ZONE_MFT
+ ZONE_DATA1
+ ZONE_DATA2
)) {
473 ntfs_log_trace("Switching zone.\n");
476 LCN tc
= rl
[rlpos
- 1].lcn
+
477 rl
[rlpos
- 1].length
+ NTFS_LCNALLOC_SKIP
;
480 ntfs_cluster_update_zone_pos(vol
,
484 switch (search_zone
) {
486 ntfs_log_trace("Zone switch: mft -> data1\n");
487 switch_to_data1_zone
: search_zone
= ZONE_DATA1
;
488 zone_start
= vol
->data1_zone_pos
;
489 zone_end
= vol
->nr_clusters
;
490 if (zone_start
== vol
->mft_zone_end
)
494 ntfs_log_trace("Zone switch: data1 -> data2\n");
495 search_zone
= ZONE_DATA2
;
496 zone_start
= vol
->data2_zone_pos
;
497 zone_end
= vol
->mft_zone_start
;
502 if (!(done_zones
& ZONE_DATA1
)) {
503 ntfs_log_trace("data2 -> data1\n");
504 goto switch_to_data1_zone
;
506 ntfs_log_trace("Zone switch: data2 -> mft\n");
507 search_zone
= ZONE_MFT
;
508 zone_start
= vol
->mft_zone_pos
;
509 zone_end
= vol
->mft_zone_end
;
510 if (zone_start
== vol
->mft_zone_start
)
515 bmp_pos
= zone_start
;
517 if (zone_start
== zone_end
) {
518 ntfs_log_trace("Empty zone, skipped.\n");
519 goto done_zones_check
;
525 ntfs_log_trace("All zones are finished, no space on device.\n");
530 ntfs_log_debug("At done_ret.\n");
531 /* Add runlist terminator element. */
532 rl
[rlpos
].vcn
= rl
[rlpos
- 1].vcn
+ rl
[rlpos
- 1].length
;
533 rl
[rlpos
].lcn
= LCN_RL_NOT_MAPPED
;
534 rl
[rlpos
].length
= 0;
535 if (bitmap_writeback(vol
, last_read_pos
, br
, buf
, &writeback
)) {
543 ntfs_log_perror("Failed to allocate clusters");
547 ntfs_log_leave("\n");
551 ntfs_log_trace("At wb_err_ret.\n");
552 if (bitmap_writeback(vol
, last_read_pos
, br
, buf
, &writeback
))
555 ntfs_log_trace("At err_ret.\n");
557 /* Add runlist terminator element. */
558 rl
[rlpos
].vcn
= rl
[rlpos
- 1].vcn
+ rl
[rlpos
- 1].length
;
559 rl
[rlpos
].lcn
= LCN_RL_NOT_MAPPED
;
560 rl
[rlpos
].length
= 0;
561 ntfs_debug_runlist_dump(rl
);
562 ntfs_cluster_free_from_rl(vol
, rl
);
570 * ntfs_cluster_free_from_rl - free clusters from runlist
571 * @vol: mounted ntfs volume on which to free the clusters
572 * @rl: runlist from which deallocate clusters
574 * On success return 0 and on error return -1 with errno set to the error code.
576 int ntfs_cluster_free_from_rl(ntfs_volume
*vol
, runlist
*rl
)
581 ntfs_log_trace("Entering.\n");
583 for (; rl
->length
; rl
++) {
585 ntfs_log_trace("Dealloc lcn 0x%llx, len 0x%llx.\n",
586 (long long)rl
->lcn
, (long long)rl
->length
);
589 update_full_status(vol
,rl
->lcn
);
590 if (ntfs_bitmap_clear_run(vol
->lcnbmp_na
, rl
->lcn
,
592 ntfs_log_perror("Cluster deallocation failed "
595 (long long)rl
->length
);
598 nr_freed
+= rl
->length
;
604 vol
->free_clusters
+= nr_freed
;
605 if (vol
->free_clusters
> vol
->nr_clusters
)
606 ntfs_log_error("Too many free clusters (%lld > %lld)!",
607 (long long)vol
->free_clusters
,
608 (long long)vol
->nr_clusters
);
613 * Basic cluster run free
614 * Returns 0 if successful
617 int ntfs_cluster_free_basic(ntfs_volume
*vol
, s64 lcn
, s64 count
)
622 ntfs_log_trace("Entering.\n");
623 ntfs_log_trace("Dealloc lcn 0x%llx, len 0x%llx.\n",
624 (long long)lcn
, (long long)count
);
627 update_full_status(vol
,lcn
);
628 if (ntfs_bitmap_clear_run(vol
->lcnbmp_na
, lcn
,
630 ntfs_log_perror("Cluster deallocation failed "
640 vol
->free_clusters
+= nr_freed
;
641 if (vol
->free_clusters
> vol
->nr_clusters
)
642 ntfs_log_error("Too many free clusters (%lld > %lld)!",
643 (long long)vol
->free_clusters
,
644 (long long)vol
->nr_clusters
);
649 * ntfs_cluster_free - free clusters on an ntfs volume
650 * @vol: mounted ntfs volume on which to free the clusters
651 * @na: attribute whose runlist describes the clusters to free
652 * @start_vcn: vcn in @rl at which to start freeing clusters
653 * @count: number of clusters to free or -1 for all clusters
655 * Free @count clusters starting at the cluster @start_vcn in the runlist
656 * described by the attribute @na from the mounted ntfs volume @vol.
658 * If @count is -1, all clusters from @start_vcn to the end of the runlist
661 * On success return the number of deallocated clusters (not counting sparse
662 * clusters) and on error return -1 with errno set to the error code.
664 int ntfs_cluster_free(ntfs_volume
*vol
, ntfs_attr
*na
, VCN start_vcn
, s64 count
)
667 s64 delta
, to_free
, nr_freed
= 0;
670 if (!vol
|| !vol
->lcnbmp_na
|| !na
|| start_vcn
< 0 ||
671 (count
< 0 && count
!= -1)) {
672 ntfs_log_trace("Invalid arguments!\n");
677 ntfs_log_enter("Entering for inode 0x%llx, attr 0x%x, count 0x%llx, "
678 "vcn 0x%llx.\n", (unsigned long long)na
->ni
->mft_no
,
679 na
->type
, (long long)count
, (long long)start_vcn
);
681 rl
= ntfs_attr_find_vcn(na
, start_vcn
);
688 if (rl
->lcn
< 0 && rl
->lcn
!= LCN_HOLE
) {
690 ntfs_log_perror("%s: Unexpected lcn (%lld)", __FUNCTION__
,
695 /* Find the starting cluster inside the run that needs freeing. */
696 delta
= start_vcn
- rl
->vcn
;
698 /* The number of clusters in this run that need freeing. */
699 to_free
= rl
->length
- delta
;
700 if (count
>= 0 && to_free
> count
)
703 if (rl
->lcn
!= LCN_HOLE
) {
704 /* Do the actual freeing of the clusters in this run. */
705 update_full_status(vol
,rl
->lcn
+ delta
);
706 if (ntfs_bitmap_clear_run(vol
->lcnbmp_na
, rl
->lcn
+ delta
,
712 /* Go to the next run and adjust the number of clusters left to free. */
718 * Loop over the remaining runs, using @count as a capping value, and
721 for (; rl
->length
&& count
!= 0; ++rl
) {
722 // FIXME: Need to try ntfs_attr_map_runlist() for attribute
723 // list support! (AIA)
724 if (rl
->lcn
< 0 && rl
->lcn
!= LCN_HOLE
) {
725 // FIXME: Eeek! We need rollback! (AIA)
727 ntfs_log_perror("%s: Invalid lcn (%lli)",
728 __FUNCTION__
, (long long)rl
->lcn
);
732 /* The number of clusters in this run that need freeing. */
733 to_free
= rl
->length
;
734 if (count
>= 0 && to_free
> count
)
737 if (rl
->lcn
!= LCN_HOLE
) {
738 update_full_status(vol
,rl
->lcn
);
739 if (ntfs_bitmap_clear_run(vol
->lcnbmp_na
, rl
->lcn
,
741 // FIXME: Eeek! We need rollback! (AIA)
742 ntfs_log_perror("%s: Clearing bitmap run failed",
753 if (count
!= -1 && count
!= 0) {
754 // FIXME: Eeek! BUG()
756 ntfs_log_perror("%s: count still not zero (%lld)", __FUNCTION__
,
763 vol
->free_clusters
+= nr_freed
;
764 if (vol
->free_clusters
> vol
->nr_clusters
)
765 ntfs_log_error("Too many free clusters (%lld > %lld)!",
766 (long long)vol
->free_clusters
,
767 (long long)vol
->nr_clusters
);
769 ntfs_log_leave("\n");