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 * Copyright (c) 2008-2009 Jean-Pierre Andre 8 * 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. 13 * 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. 18 * 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 23 */ 24 25 #ifdef HAVE_CONFIG_H 26 #include "config.h" 27 #endif 28 29 #ifdef HAVE_STDLIB_H 30 #include <stdlib.h> 31 #endif 32 #ifdef HAVE_STDIO_H 33 #include <stdio.h> 34 #endif 35 #ifdef HAVE_ERRNO_H 36 #include <errno.h> 37 #endif 38 39 #include "types.h" 40 #include "attrib.h" 41 #include "bitmap.h" 42 #include "debug.h" 43 #include "runlist.h" 44 #include "volume.h" 45 #include "lcnalloc.h" 46 #include "logging.h" 47 #include "misc.h" 48 49 /* 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). 54 */ 55 #define NTFS_LCNALLOC_BSIZE 4096 56 #define NTFS_LCNALLOC_SKIP NTFS_LCNALLOC_BSIZE 57 58 enum { 59 ZONE_MFT = 1, 60 ZONE_DATA1 = 2, 61 ZONE_DATA2 = 4 62 } ; 63 64 static void ntfs_cluster_set_zone_pos(LCN start, LCN end, LCN *pos, LCN tc) 65 { 66 ntfs_log_trace("pos: %lld tc: %lld\n", (long long)*pos, (long long)tc); 67 68 if (tc >= end) 69 *pos = start; 70 else if (tc >= start) 71 *pos = tc; 72 } 73 74 static void ntfs_cluster_update_zone_pos(ntfs_volume *vol, u8 zone, LCN tc) 75 { 76 ntfs_log_trace("tc = %lld, zone = %d\n", (long long)tc, zone); 77 78 if (zone == ZONE_MFT) 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); 87 } 88 89 /* 90 * Unmark full zones when a cluster has been freed in a full zone 91 * 92 * Next allocation will reuse the freed cluster 93 */ 94 95 static void update_full_status(ntfs_volume *vol, LCN lcn) 96 { 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; 101 } 102 } else 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; 107 } 108 } else { 109 if (vol->full_zones & ZONE_MFT) { 110 ntfs_cluster_update_zone_pos(vol, ZONE_MFT, lcn); 111 vol->full_zones &= ~ZONE_MFT; 112 } 113 } 114 } 115 116 static s64 max_empty_bit_range(unsigned char *buf, int size) 117 { 118 int i, j, run = 0; 119 int max_range = 0; 120 s64 start_pos = -1; 121 122 ntfs_log_trace("Entering\n"); 123 124 i = 0; 125 while (i < size) { 126 switch (*buf) { 127 case 0 : 128 do { 129 buf++; 130 run += 8; 131 i++; 132 } while ((i < size) && !*buf); 133 break; 134 case 255 : 135 if (run > max_range) { 136 max_range = run; 137 start_pos = (s64)i * 8 - run; 138 } 139 run = 0; 140 do { 141 buf++; 142 i++; 143 } while ((i < size) && (*buf == 255)); 144 break; 145 default : 146 for (j = 0; j < 8; j++) { 147 148 int bit = *buf & (1 << j); 149 150 if (bit) { 151 if (run > max_range) { 152 max_range = run; 153 start_pos = (s64)i * 8 + (j - run); 154 } 155 run = 0; 156 } else 157 run++; 158 } 159 i++; 160 buf++; 161 162 } 163 } 164 165 if (run > max_range) 166 start_pos = (s64)i * 8 - run; 167 168 return start_pos; 169 } 170 171 static int bitmap_writeback(ntfs_volume *vol, s64 pos, s64 size, void *b, 172 u8 *writeback) 173 { 174 s64 written; 175 176 ntfs_log_trace("Entering\n"); 177 178 if (!*writeback) 179 return 0; 180 181 *writeback = 0; 182 183 written = ntfs_attr_pwrite(vol->lcnbmp_na, pos, size, b); 184 if (written != size) { 185 if (!written) 186 errno = EIO; 187 ntfs_log_perror("Bitmap write error (%lld, %lld)", 188 (long long)pos, (long long)size); 189 return -1; 190 } 191 192 return 0; 193 } 194 195 /** 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 202 * 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. 208 * 209 * On success return a runlist describing the allocated cluster(s). 210 * 211 * On error return NULL with errno set to the error code. 212 * 213 * Notes on the allocation algorithm 214 * ================================= 215 * 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. 222 * 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. 234 */ 235 runlist *ntfs_cluster_alloc(ntfs_volume *vol, VCN start_vcn, s64 count, 236 LCN start_lcn, const NTFS_CLUSTER_ALLOCATION_ZONES zone) 237 { 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; 242 s64 clusters, br; 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) */ 247 u8 done_zones = 0; 248 u8 has_guess, used_zone_pos; 249 int err = 0, rlpos, rlsize, buf_size; 250 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"); 254 255 if (!vol || count < 0 || start_lcn < -1 || !vol->lcnbmp_na || 256 (s8)zone < FIRST_ZONE || zone > LAST_ZONE) { 257 errno = EINVAL; 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); 261 goto out; 262 } 263 264 /* Return empty runlist if @count == 0 */ 265 if (!count) { 266 rl = ntfs_malloc(0x1000); 267 if (rl) { 268 rl[0].vcn = start_vcn; 269 rl[0].lcn = LCN_RL_NOT_MAPPED; 270 rl[0].length = 0; 271 } 272 goto out; 273 } 274 275 buf = ntfs_malloc(NTFS_LCNALLOC_BSIZE); 276 if (!buf) 277 goto out; 278 /* 279 * If no @start_lcn was requested, use the current zone 280 * position otherwise use the requested @start_lcn. 281 */ 282 has_guess = 1; 283 zone_start = start_lcn; 284 285 if (zone_start < 0) { 286 if (zone == DATA_ZONE) 287 zone_start = vol->data1_zone_pos; 288 else 289 zone_start = vol->mft_zone_pos; 290 has_guess = 0; 291 } 292 293 used_zone_pos = has_guess ? 0 : 1; 294 295 if (!zone_start || zone_start == vol->mft_zone_start || 296 zone_start == vol->mft_zone_end) 297 pass = 2; 298 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; 305 } else { 306 zone_end = vol->nr_clusters; 307 search_zone = ZONE_DATA1; 308 } 309 310 bmp_pos = zone_start; 311 312 /* Loop until all clusters are allocated. */ 313 clusters = count; 314 rlpos = rlsize = 0; 315 while (1) { 316 /* check whether we have exhausted the current zone */ 317 if (search_zone & vol->full_zones) 318 goto zone_pass_done; 319 last_read_pos = bmp_pos >> 3; 320 br = ntfs_attr_pread(vol->lcnbmp_na, last_read_pos, 321 NTFS_LCNALLOC_BSIZE, buf); 322 if (br <= 0) { 323 if (!br) 324 goto zone_pass_done; 325 err = errno; 326 ntfs_log_perror("Reading $BITMAP failed"); 327 goto err_ret; 328 } 329 /* 330 * We might have read less than NTFS_LCNALLOC_BSIZE bytes 331 * if we are close to the end of the attribute. 332 */ 333 buf_size = (int)br << 3; 334 lcn = bmp_pos & 7; 335 bmp_pos &= ~7; 336 writeback = 0; 337 338 while (lcn < buf_size) { 339 byte = buf + (lcn >> 3); 340 bit = 1 << (lcn & 7); 341 if (has_guess) { 342 if (*byte & bit) { 343 has_guess = 0; 344 break; 345 } 346 } else { 347 lcn = max_empty_bit_range(buf, br); 348 if (lcn < 0) 349 break; 350 has_guess = 1; 351 continue; 352 } 353 354 /* First free bit is at lcn + bmp_pos. */ 355 356 /* Reallocate memory if necessary. */ 357 if ((rlpos + 2) * (int)sizeof(runlist) >= rlsize) { 358 rlsize += 4096; 359 trl = realloc(rl, rlsize); 360 if (!trl) { 361 err = ENOMEM; 362 ntfs_log_perror("realloc() failed"); 363 goto wb_err_ret; 364 } 365 rl = trl; 366 } 367 368 /* Allocate the bitmap bit. */ 369 *byte |= bit; 370 writeback = 1; 371 if (vol->free_clusters <= 0) 372 ntfs_log_error("Non-positive free clusters " 373 "(%lld)!\n", 374 (long long)vol->free_clusters); 375 else 376 vol->free_clusters--; 377 378 /* 379 * Coalesce with previous run if adjacent LCNs. 380 * Otherwise, append a new run. 381 */ 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", 386 (long long)prev_lcn, 387 (long long)lcn, (long long)bmp_pos, 388 (long long)prev_run_len); 389 rl[rlpos - 1].length = ++prev_run_len; 390 } else { 391 if (rlpos) 392 rl[rlpos].vcn = rl[rlpos - 1].vcn + 393 prev_run_len; 394 else { 395 rl[rlpos].vcn = start_vcn; 396 ntfs_log_debug("Start_vcn: %lld\n", 397 (long long)start_vcn); 398 } 399 400 rl[rlpos].lcn = prev_lcn = lcn + bmp_pos; 401 rl[rlpos].length = prev_run_len = 1; 402 rlpos++; 403 } 404 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); 409 /* Done? */ 410 if (!--clusters) { 411 if (used_zone_pos) 412 ntfs_cluster_update_zone_pos(vol, 413 search_zone, lcn + bmp_pos + 1 + 414 NTFS_LCNALLOC_SKIP); 415 goto done_ret; 416 } 417 418 lcn++; 419 } 420 421 if (bitmap_writeback(vol, last_read_pos, br, buf, &writeback)) { 422 err = errno; 423 goto err_ret; 424 } 425 426 if (!used_zone_pos) { 427 428 used_zone_pos = 1; 429 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; 434 else 435 zone_start = vol->data2_zone_pos; 436 437 if (!zone_start || zone_start == vol->mft_zone_start || 438 zone_start == vol->mft_zone_end) 439 pass = 2; 440 bmp_pos = zone_start; 441 } else 442 bmp_pos += buf_size; 443 444 if (bmp_pos < zone_end) 445 continue; 446 447 zone_pass_done: 448 ntfs_log_trace("Finished current zone pass(%i).\n", pass); 449 if (pass == 1) { 450 pass = 2; 451 zone_end = zone_start; 452 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; 457 else 458 zone_start = 0; 459 460 /* Sanity check. */ 461 if (zone_end < zone_start) 462 zone_end = zone_start; 463 464 bmp_pos = zone_start; 465 466 continue; 467 } 468 /* pass == 2 */ 469 done_zones_check: 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"); 474 pass = 1; 475 if (rlpos) { 476 LCN tc = rl[rlpos - 1].lcn + 477 rl[rlpos - 1].length + NTFS_LCNALLOC_SKIP; 478 479 if (used_zone_pos) 480 ntfs_cluster_update_zone_pos(vol, 481 search_zone, tc); 482 } 483 484 switch (search_zone) { 485 case ZONE_MFT: 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) 491 pass = 2; 492 break; 493 case ZONE_DATA1: 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; 498 if (!zone_start) 499 pass = 2; 500 break; 501 case ZONE_DATA2: 502 if (!(done_zones & ZONE_DATA1)) { 503 ntfs_log_trace("data2 -> data1\n"); 504 goto switch_to_data1_zone; 505 } 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) 511 pass = 2; 512 break; 513 } 514 515 bmp_pos = zone_start; 516 517 if (zone_start == zone_end) { 518 ntfs_log_trace("Empty zone, skipped.\n"); 519 goto done_zones_check; 520 } 521 522 continue; 523 } 524 525 ntfs_log_trace("All zones are finished, no space on device.\n"); 526 err = ENOSPC; 527 goto err_ret; 528 } 529 done_ret: 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)) { 536 err = errno; 537 goto err_ret; 538 } 539 done_err_ret: 540 free(buf); 541 if (err) { 542 errno = err; 543 ntfs_log_perror("Failed to allocate clusters"); 544 rl = NULL; 545 } 546 out: 547 ntfs_log_leave("\n"); 548 return rl; 549 550 wb_err_ret: 551 ntfs_log_trace("At wb_err_ret.\n"); 552 if (bitmap_writeback(vol, last_read_pos, br, buf, &writeback)) 553 err = errno; 554 err_ret: 555 ntfs_log_trace("At err_ret.\n"); 556 if (rl) { 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); 563 free(rl); 564 rl = NULL; 565 } 566 goto done_err_ret; 567 } 568 569 /** 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 573 * 574 * On success return 0 and on error return -1 with errno set to the error code. 575 */ 576 int ntfs_cluster_free_from_rl(ntfs_volume *vol, runlist *rl) 577 { 578 s64 nr_freed = 0; 579 int ret = -1; 580 581 ntfs_log_trace("Entering.\n"); 582 583 for (; rl->length; rl++) { 584 585 ntfs_log_trace("Dealloc lcn 0x%llx, len 0x%llx.\n", 586 (long long)rl->lcn, (long long)rl->length); 587 588 if (rl->lcn >= 0) { 589 update_full_status(vol,rl->lcn); 590 if (ntfs_bitmap_clear_run(vol->lcnbmp_na, rl->lcn, 591 rl->length)) { 592 ntfs_log_perror("Cluster deallocation failed " 593 "(%lld, %lld)", 594 (long long)rl->lcn, 595 (long long)rl->length); 596 goto out; 597 } 598 nr_freed += rl->length ; 599 } 600 } 601 602 ret = 0; 603 out: 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); 609 return ret; 610 } 611 612 /* 613 * Basic cluster run free 614 * Returns 0 if successful 615 */ 616 617 int ntfs_cluster_free_basic(ntfs_volume *vol, s64 lcn, s64 count) 618 { 619 s64 nr_freed = 0; 620 int ret = -1; 621 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); 625 626 if (lcn >= 0) { 627 update_full_status(vol,lcn); 628 if (ntfs_bitmap_clear_run(vol->lcnbmp_na, lcn, 629 count)) { 630 ntfs_log_perror("Cluster deallocation failed " 631 "(%lld, %lld)", 632 (long long)lcn, 633 (long long)count); 634 goto out; 635 } 636 nr_freed += count; 637 } 638 ret = 0; 639 out: 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); 645 return ret; 646 } 647 648 /** 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 654 * 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. 657 * 658 * If @count is -1, all clusters from @start_vcn to the end of the runlist 659 * are deallocated. 660 * 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. 663 */ 664 int ntfs_cluster_free(ntfs_volume *vol, ntfs_attr *na, VCN start_vcn, s64 count) 665 { 666 runlist *rl; 667 s64 delta, to_free, nr_freed = 0; 668 int ret = -1; 669 670 if (!vol || !vol->lcnbmp_na || !na || start_vcn < 0 || 671 (count < 0 && count != -1)) { 672 ntfs_log_trace("Invalid arguments!\n"); 673 errno = EINVAL; 674 return -1; 675 } 676 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); 680 681 rl = ntfs_attr_find_vcn(na, start_vcn); 682 if (!rl) { 683 if (errno == ENOENT) 684 ret = 0; 685 goto leave; 686 } 687 688 if (rl->lcn < 0 && rl->lcn != LCN_HOLE) { 689 errno = EIO; 690 ntfs_log_perror("%s: Unexpected lcn (%lld)", __FUNCTION__, 691 (long long)rl->lcn); 692 goto leave; 693 } 694 695 /* Find the starting cluster inside the run that needs freeing. */ 696 delta = start_vcn - rl->vcn; 697 698 /* The number of clusters in this run that need freeing. */ 699 to_free = rl->length - delta; 700 if (count >= 0 && to_free > count) 701 to_free = count; 702 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, 707 to_free)) 708 goto leave; 709 nr_freed = to_free; 710 } 711 712 /* Go to the next run and adjust the number of clusters left to free. */ 713 ++rl; 714 if (count >= 0) 715 count -= to_free; 716 717 /* 718 * Loop over the remaining runs, using @count as a capping value, and 719 * free them. 720 */ 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) 726 errno = EIO; 727 ntfs_log_perror("%s: Invalid lcn (%lli)", 728 __FUNCTION__, (long long)rl->lcn); 729 goto out; 730 } 731 732 /* The number of clusters in this run that need freeing. */ 733 to_free = rl->length; 734 if (count >= 0 && to_free > count) 735 to_free = count; 736 737 if (rl->lcn != LCN_HOLE) { 738 update_full_status(vol,rl->lcn); 739 if (ntfs_bitmap_clear_run(vol->lcnbmp_na, rl->lcn, 740 to_free)) { 741 // FIXME: Eeek! We need rollback! (AIA) 742 ntfs_log_perror("%s: Clearing bitmap run failed", 743 __FUNCTION__); 744 goto out; 745 } 746 nr_freed += to_free; 747 } 748 749 if (count >= 0) 750 count -= to_free; 751 } 752 753 if (count != -1 && count != 0) { 754 // FIXME: Eeek! BUG() 755 errno = EIO; 756 ntfs_log_perror("%s: count still not zero (%lld)", __FUNCTION__, 757 (long long)count); 758 goto out; 759 } 760 761 ret = nr_freed; 762 out: 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); 768 leave: 769 ntfs_log_leave("\n"); 770 return ret; 771 } 772