gen_bitmap64.c revision 9288e3be665bb8d5657d7f710687a50fad859acf
1/* 2 * gen_bitmap64.c --- routines to read, write, and manipulate the new qinode and 3 * block bitmaps. 4 * 5 * Copyright (C) 2007, 2008 Theodore Ts'o. 6 * 7 * %Begin-Header% 8 * This file may be redistributed under the terms of the GNU Public 9 * License. 10 * %End-Header% 11 */ 12 13#include "config.h" 14#include <stdio.h> 15#include <string.h> 16#if HAVE_UNISTD_H 17#include <unistd.h> 18#endif 19#include <fcntl.h> 20#include <time.h> 21#include <errno.h> 22#if HAVE_SYS_STAT_H 23#include <sys/stat.h> 24#endif 25#if HAVE_SYS_TYPES_H 26#include <sys/types.h> 27#endif 28 29#include "ext2_fs.h" 30#include "ext2fsP.h" 31#include "bmap64.h" 32 33/* 34 * Design of 64-bit bitmaps 35 * 36 * In order maintain ABI compatibility with programs that don't 37 * understand about 64-bit blocks/inodes, 38 * ext2fs_allocate_inode_bitmap() and ext2fs_allocate_block_bitmap() 39 * will create old-style bitmaps unless the application passes the 40 * flag EXT2_FLAG_64BITS to ext2fs_open(). If this flag is 41 * passed, then we know the application has been recompiled, so we can 42 * use the new-style bitmaps. If it is not passed, we have to return 43 * an error if trying to open a filesystem which needs 64-bit bitmaps. 44 * 45 * The new bitmaps use a new set of structure magic numbers, so that 46 * both the old-style and new-style interfaces can identify which 47 * version of the data structure was used. Both the old-style and 48 * new-style interfaces will support either type of bitmap, although 49 * of course 64-bit operation will only be possible when both the 50 * new-style interface and the new-style bitmap are used. 51 * 52 * For example, the new bitmap interfaces will check the structure 53 * magic numbers and so will be able to detect old-stype bitmap. If 54 * they see an old-style bitmap, they will pass it to the gen_bitmap.c 55 * functions for handling. The same will be true for the old 56 * interfaces as well. 57 * 58 * The new-style interfaces will have several different back-end 59 * implementations, so we can support different encodings that are 60 * appropriate for different applications. In general the default 61 * should be whatever makes sense, and what the application/library 62 * will use. However, e2fsck may need specialized implementations for 63 * its own uses. For example, when doing parent directory pointer 64 * loop detections in pass 3, the bitmap will *always* be sparse, so 65 * e2fsck can request an encoding which is optimized for that. 66 */ 67 68static void warn_bitmap(ext2fs_generic_bitmap bitmap, 69 int code, __u64 arg) 70{ 71#ifndef OMIT_COM_ERR 72 if (bitmap->description) 73 com_err(0, bitmap->base_error_code+code, 74 "#%llu for %s", arg, bitmap->description); 75 else 76 com_err(0, bitmap->base_error_code + code, "#%llu", arg); 77#endif 78} 79 80#ifdef BMAP_STATS_OPS 81#define INC_STAT(map, name) map->stats.name 82#else 83#define INC_STAT(map, name) ;; 84#endif 85 86 87errcode_t ext2fs_alloc_generic_bmap(ext2_filsys fs, errcode_t magic, 88 int type, __u64 start, __u64 end, 89 __u64 real_end, 90 const char *descr, 91 ext2fs_generic_bitmap *ret) 92{ 93 ext2fs_generic_bitmap bitmap; 94 struct ext2_bitmap_ops *ops; 95 ext2_ino_t num_dirs; 96 errcode_t retval; 97 98 if (!type) 99 type = EXT2FS_BMAP64_BITARRAY; 100 101 switch (type) { 102 case EXT2FS_BMAP64_BITARRAY: 103 ops = &ext2fs_blkmap64_bitarray; 104 break; 105 case EXT2FS_BMAP64_RBTREE: 106 ops = &ext2fs_blkmap64_rbtree; 107 break; 108 case EXT2FS_BMAP64_AUTODIR: 109 retval = ext2fs_get_num_dirs(fs, &num_dirs); 110 if (retval || num_dirs > (fs->super->s_inodes_count / 320)) 111 ops = &ext2fs_blkmap64_bitarray; 112 else 113 ops = &ext2fs_blkmap64_rbtree; 114 break; 115 default: 116 return EINVAL; 117 } 118 119 retval = ext2fs_get_memzero(sizeof(struct ext2fs_struct_generic_bitmap), 120 &bitmap); 121 if (retval) 122 return retval; 123 124#ifdef BMAP_STATS 125 if (gettimeofday(&bitmap->stats.created, 126 (struct timezone *) NULL) == -1) { 127 perror("gettimeofday"); 128 return 1; 129 } 130 bitmap->stats.type = type; 131#endif 132 133 /* XXX factor out, repeated in copy_bmap */ 134 bitmap->magic = magic; 135 bitmap->fs = fs; 136 bitmap->start = start; 137 bitmap->end = end; 138 bitmap->real_end = real_end; 139 bitmap->bitmap_ops = ops; 140 bitmap->cluster_bits = 0; 141 switch (magic) { 142 case EXT2_ET_MAGIC_INODE_BITMAP64: 143 bitmap->base_error_code = EXT2_ET_BAD_INODE_MARK; 144 break; 145 case EXT2_ET_MAGIC_BLOCK_BITMAP64: 146 bitmap->base_error_code = EXT2_ET_BAD_BLOCK_MARK; 147 bitmap->cluster_bits = fs->cluster_ratio_bits; 148 break; 149 default: 150 bitmap->base_error_code = EXT2_ET_BAD_GENERIC_MARK; 151 } 152 if (descr) { 153 retval = ext2fs_get_mem(strlen(descr)+1, &bitmap->description); 154 if (retval) { 155 ext2fs_free_mem(&bitmap); 156 return retval; 157 } 158 strcpy(bitmap->description, descr); 159 } else 160 bitmap->description = 0; 161 162 retval = bitmap->bitmap_ops->new_bmap(fs, bitmap); 163 if (retval) { 164 ext2fs_free_mem(&bitmap->description); 165 ext2fs_free_mem(&bitmap); 166 return retval; 167 } 168 169 *ret = bitmap; 170 return 0; 171} 172 173#ifdef BMAP_STATS 174void ext2fs_print_bmap_statistics(ext2fs_generic_bitmap bitmap) 175{ 176 struct ext2_bmap_statistics *stats = &bitmap->stats; 177 float mark_seq_perc = 0.0, test_seq_perc = 0.0; 178 float mark_back_perc = 0.0, test_back_perc = 0.0; 179 double inuse; 180 struct timeval now; 181 182#ifdef BMAP_STATS_OPS 183 if (stats->test_count) { 184 test_seq_perc = ((float)stats->test_seq / 185 stats->test_count) * 100; 186 test_back_perc = ((float)stats->test_back / 187 stats->test_count) * 100; 188 } 189 190 if (stats->mark_count) { 191 mark_seq_perc = ((float)stats->mark_seq / 192 stats->mark_count) * 100; 193 mark_back_perc = ((float)stats->mark_back / 194 stats->mark_count) * 100; 195 } 196#endif 197 198 if (gettimeofday(&now, (struct timezone *) NULL) == -1) { 199 perror("gettimeofday"); 200 return; 201 } 202 203 inuse = (double) now.tv_sec + \ 204 (((double) now.tv_usec) * 0.000001); 205 inuse -= (double) stats->created.tv_sec + \ 206 (((double) stats->created.tv_usec) * 0.000001); 207 208 fprintf(stderr, "\n[+] %s bitmap (type %d)\n", bitmap->description, 209 stats->type); 210 fprintf(stderr, "=================================================\n"); 211#ifdef BMAP_STATS_OPS 212 fprintf(stderr, "%16llu bits long\n", 213 bitmap->real_end - bitmap->start); 214 fprintf(stderr, "%16lu copy_bmap\n%16lu resize_bmap\n", 215 stats->copy_count, stats->resize_count); 216 fprintf(stderr, "%16lu mark bmap\n%16lu unmark_bmap\n", 217 stats->mark_count, stats->unmark_count); 218 fprintf(stderr, "%16lu test_bmap\n%16lu mark_bmap_extent\n", 219 stats->test_count, stats->mark_ext_count); 220 fprintf(stderr, "%16lu unmark_bmap_extent\n" 221 "%16lu test_clear_bmap_extent\n", 222 stats->unmark_ext_count, stats->test_ext_count); 223 fprintf(stderr, "%16lu set_bmap_range\n%16lu set_bmap_range\n", 224 stats->set_range_count, stats->get_range_count); 225 fprintf(stderr, "%16lu clear_bmap\n%16lu contiguous bit test (%.2f%%)\n", 226 stats->clear_count, stats->test_seq, test_seq_perc); 227 fprintf(stderr, "%16lu contiguous bit mark (%.2f%%)\n" 228 "%16llu bits tested backwards (%.2f%%)\n", 229 stats->mark_seq, mark_seq_perc, 230 stats->test_back, test_back_perc); 231 fprintf(stderr, "%16llu bits marked backwards (%.2f%%)\n" 232 "%16.2f seconds in use\n", 233 stats->mark_back, mark_back_perc, inuse); 234#endif /* BMAP_STATS_OPS */ 235} 236#endif 237 238void ext2fs_free_generic_bmap(ext2fs_generic_bitmap bmap) 239{ 240 if (!bmap) 241 return; 242 243 if (EXT2FS_IS_32_BITMAP(bmap)) { 244 ext2fs_free_generic_bitmap(bmap); 245 return; 246 } 247 248 if (!EXT2FS_IS_64_BITMAP(bmap)) 249 return; 250 251#ifdef BMAP_STATS 252 if (getenv("E2FSPROGS_BITMAP_STATS")) { 253 ext2fs_print_bmap_statistics(bmap); 254 bmap->bitmap_ops->print_stats(bmap); 255 } 256#endif 257 258 bmap->bitmap_ops->free_bmap(bmap); 259 260 if (bmap->description) { 261 ext2fs_free_mem(&bmap->description); 262 bmap->description = 0; 263 } 264 bmap->magic = 0; 265 ext2fs_free_mem(&bmap); 266} 267 268errcode_t ext2fs_copy_generic_bmap(ext2fs_generic_bitmap src, 269 ext2fs_generic_bitmap *dest) 270{ 271 char *descr, *new_descr; 272 ext2fs_generic_bitmap new_bmap; 273 errcode_t retval; 274 275 if (!src) 276 return EINVAL; 277 278 if (EXT2FS_IS_32_BITMAP(src)) 279 return ext2fs_copy_generic_bitmap(src, dest); 280 281 if (!EXT2FS_IS_64_BITMAP(src)) 282 return EINVAL; 283 284 /* Allocate a new bitmap struct */ 285 retval = ext2fs_get_memzero(sizeof(struct ext2fs_struct_generic_bitmap), 286 &new_bmap); 287 if (retval) 288 return retval; 289 290 291#ifdef BMAP_STATS_OPS 292 src->stats.copy_count++; 293#endif 294#ifdef BMAP_STATS 295 if (gettimeofday(&new_bmap->stats.created, 296 (struct timezone *) NULL) == -1) { 297 perror("gettimeofday"); 298 return 1; 299 } 300 new_bmap->stats.type = src->stats.type; 301#endif 302 303 /* Copy all the high-level parts over */ 304 new_bmap->magic = src->magic; 305 new_bmap->fs = src->fs; 306 new_bmap->start = src->start; 307 new_bmap->end = src->end; 308 new_bmap->real_end = src->real_end; 309 new_bmap->bitmap_ops = src->bitmap_ops; 310 new_bmap->base_error_code = src->base_error_code; 311 new_bmap->cluster_bits = src->cluster_bits; 312 313 descr = src->description; 314 if (descr) { 315 retval = ext2fs_get_mem(strlen(descr)+10, &new_descr); 316 if (retval) { 317 ext2fs_free_mem(&new_bmap); 318 return retval; 319 } 320 sprintf(new_descr, "copy of %s", descr); 321 new_bmap->description = new_descr; 322 } 323 324 retval = src->bitmap_ops->copy_bmap(src, new_bmap); 325 if (retval) { 326 ext2fs_free_mem(&new_bmap->description); 327 ext2fs_free_mem(&new_bmap); 328 return retval; 329 } 330 331 *dest = new_bmap; 332 333 return 0; 334} 335 336errcode_t ext2fs_resize_generic_bmap(ext2fs_generic_bitmap bmap, 337 __u64 new_end, 338 __u64 new_real_end) 339{ 340 if (!bmap) 341 return EINVAL; 342 343 if (EXT2FS_IS_32_BITMAP(bmap)) 344 return ext2fs_resize_generic_bitmap(bmap->magic, new_end, 345 new_real_end, bmap); 346 347 if (!EXT2FS_IS_64_BITMAP(bmap)) 348 return EINVAL; 349 350 INC_STAT(bmap, resize_count); 351 352 return bmap->bitmap_ops->resize_bmap(bmap, new_end, new_real_end); 353} 354 355errcode_t ext2fs_fudge_generic_bmap_end(ext2fs_generic_bitmap bitmap, 356 errcode_t neq, 357 __u64 end, __u64 *oend) 358{ 359 if (!bitmap) 360 return EINVAL; 361 362 if (EXT2FS_IS_32_BITMAP(bitmap)) { 363 ext2_ino_t tmp_oend; 364 int retval; 365 366 retval = ext2fs_fudge_generic_bitmap_end(bitmap, bitmap->magic, 367 neq, end, &tmp_oend); 368 if (oend) 369 *oend = tmp_oend; 370 return retval; 371 } 372 373 if (!EXT2FS_IS_64_BITMAP(bitmap)) 374 return EINVAL; 375 376 if (end > bitmap->real_end) 377 return neq; 378 if (oend) 379 *oend = bitmap->end; 380 bitmap->end = end; 381 return 0; 382} 383 384__u64 ext2fs_get_generic_bmap_start(ext2fs_generic_bitmap bitmap) 385{ 386 if (!bitmap) 387 return EINVAL; 388 389 if (EXT2FS_IS_32_BITMAP(bitmap)) 390 return ext2fs_get_generic_bitmap_start(bitmap); 391 392 if (!EXT2FS_IS_64_BITMAP(bitmap)) 393 return EINVAL; 394 395 return bitmap->start; 396} 397 398__u64 ext2fs_get_generic_bmap_end(ext2fs_generic_bitmap bitmap) 399{ 400 if (!bitmap) 401 return EINVAL; 402 403 if (EXT2FS_IS_32_BITMAP(bitmap)) 404 return ext2fs_get_generic_bitmap_end(bitmap); 405 406 if (!EXT2FS_IS_64_BITMAP(bitmap)) 407 return EINVAL; 408 409 return bitmap->end; 410} 411 412void ext2fs_clear_generic_bmap(ext2fs_generic_bitmap bitmap) 413{ 414 if (EXT2FS_IS_32_BITMAP(bitmap)) 415 ext2fs_clear_generic_bitmap(bitmap); 416 else 417 bitmap->bitmap_ops->clear_bmap (bitmap); 418} 419 420int ext2fs_mark_generic_bmap(ext2fs_generic_bitmap bitmap, 421 __u64 arg) 422{ 423 if (!bitmap) 424 return 0; 425 426 if (EXT2FS_IS_32_BITMAP(bitmap)) { 427 if (arg & ~0xffffffffULL) { 428 ext2fs_warn_bitmap2(bitmap, 429 EXT2FS_MARK_ERROR, 0xffffffff); 430 return 0; 431 } 432 return ext2fs_mark_generic_bitmap(bitmap, arg); 433 } 434 435 if (!EXT2FS_IS_64_BITMAP(bitmap)) 436 return 0; 437 438 arg >>= bitmap->cluster_bits; 439 440#ifdef BMAP_STATS_OPS 441 if (arg == bitmap->stats.last_marked + 1) 442 bitmap->stats.mark_seq++; 443 if (arg < bitmap->stats.last_marked) 444 bitmap->stats.mark_back++; 445 bitmap->stats.last_marked = arg; 446 bitmap->stats.mark_count++; 447#endif 448 449 if ((arg < bitmap->start) || (arg > bitmap->end)) { 450 warn_bitmap(bitmap, EXT2FS_MARK_ERROR, arg); 451 return 0; 452 } 453 454 return bitmap->bitmap_ops->mark_bmap(bitmap, arg); 455} 456 457int ext2fs_unmark_generic_bmap(ext2fs_generic_bitmap bitmap, 458 __u64 arg) 459{ 460 if (!bitmap) 461 return 0; 462 463 if (EXT2FS_IS_32_BITMAP(bitmap)) { 464 if (arg & ~0xffffffffULL) { 465 ext2fs_warn_bitmap2(bitmap, EXT2FS_UNMARK_ERROR, 466 0xffffffff); 467 return 0; 468 } 469 return ext2fs_unmark_generic_bitmap(bitmap, arg); 470 } 471 472 if (!EXT2FS_IS_64_BITMAP(bitmap)) 473 return 0; 474 475 arg >>= bitmap->cluster_bits; 476 477 INC_STAT(bitmap, unmark_count); 478 479 if ((arg < bitmap->start) || (arg > bitmap->end)) { 480 warn_bitmap(bitmap, EXT2FS_UNMARK_ERROR, arg); 481 return 0; 482 } 483 484 return bitmap->bitmap_ops->unmark_bmap(bitmap, arg); 485} 486 487int ext2fs_test_generic_bmap(ext2fs_generic_bitmap bitmap, 488 __u64 arg) 489{ 490 if (!bitmap) 491 return 0; 492 493 if (EXT2FS_IS_32_BITMAP(bitmap)) { 494 if (arg & ~0xffffffffULL) { 495 ext2fs_warn_bitmap2(bitmap, EXT2FS_TEST_ERROR, 496 0xffffffff); 497 return 0; 498 } 499 return ext2fs_test_generic_bitmap(bitmap, arg); 500 } 501 502 if (!EXT2FS_IS_64_BITMAP(bitmap)) 503 return 0; 504 505 arg >>= bitmap->cluster_bits; 506 507#ifdef BMAP_STATS_OPS 508 bitmap->stats.test_count++; 509 if (arg == bitmap->stats.last_tested + 1) 510 bitmap->stats.test_seq++; 511 if (arg < bitmap->stats.last_tested) 512 bitmap->stats.test_back++; 513 bitmap->stats.last_tested = arg; 514#endif 515 516 if ((arg < bitmap->start) || (arg > bitmap->end)) { 517 warn_bitmap(bitmap, EXT2FS_TEST_ERROR, arg); 518 return 0; 519 } 520 521 return bitmap->bitmap_ops->test_bmap(bitmap, arg); 522} 523 524errcode_t ext2fs_set_generic_bmap_range(ext2fs_generic_bitmap bmap, 525 __u64 start, unsigned int num, 526 void *in) 527{ 528 if (!bmap) 529 return EINVAL; 530 531 if (EXT2FS_IS_32_BITMAP(bmap)) { 532 if ((start+num-1) & ~0xffffffffULL) { 533 ext2fs_warn_bitmap2(bmap, EXT2FS_UNMARK_ERROR, 534 0xffffffff); 535 return EINVAL; 536 } 537 return ext2fs_set_generic_bitmap_range(bmap, bmap->magic, 538 start, num, in); 539 } 540 541 if (!EXT2FS_IS_64_BITMAP(bmap)) 542 return EINVAL; 543 544 INC_STAT(bmap, set_range_count); 545 546 return bmap->bitmap_ops->set_bmap_range(bmap, start, num, in); 547} 548 549errcode_t ext2fs_get_generic_bmap_range(ext2fs_generic_bitmap bmap, 550 __u64 start, unsigned int num, 551 void *out) 552{ 553 if (!bmap) 554 return EINVAL; 555 556 if (EXT2FS_IS_32_BITMAP(bmap)) { 557 if ((start+num-1) & ~0xffffffffULL) { 558 ext2fs_warn_bitmap2(bmap, 559 EXT2FS_UNMARK_ERROR, 0xffffffff); 560 return EINVAL; 561 } 562 return ext2fs_get_generic_bitmap_range(bmap, bmap->magic, 563 start, num, out); 564 } 565 566 if (!EXT2FS_IS_64_BITMAP(bmap)) 567 return EINVAL; 568 569 INC_STAT(bmap, get_range_count); 570 571 return bmap->bitmap_ops->get_bmap_range(bmap, start, num, out); 572} 573 574errcode_t ext2fs_compare_generic_bmap(errcode_t neq, 575 ext2fs_generic_bitmap bm1, 576 ext2fs_generic_bitmap bm2) 577{ 578 blk64_t i; 579 580 if (!bm1 || !bm2) 581 return EINVAL; 582 if (bm1->magic != bm2->magic) 583 return EINVAL; 584 585 /* Now we know both bitmaps have the same magic */ 586 if (EXT2FS_IS_32_BITMAP(bm1)) 587 return ext2fs_compare_generic_bitmap(bm1->magic, neq, bm1, bm2); 588 589 if (!EXT2FS_IS_64_BITMAP(bm1)) 590 return EINVAL; 591 592 if ((bm1->start != bm2->start) || 593 (bm1->end != bm2->end)) 594 return neq; 595 596 for (i = bm1->end - ((bm1->end - bm1->start) % 8); i <= bm1->end; i++) 597 if (ext2fs_test_generic_bmap(bm1, i) != 598 ext2fs_test_generic_bmap(bm2, i)) 599 return neq; 600 601 return 0; 602} 603 604void ext2fs_set_generic_bmap_padding(ext2fs_generic_bitmap bmap) 605{ 606 __u64 start, num; 607 608 if (EXT2FS_IS_32_BITMAP(bmap)) { 609 ext2fs_set_generic_bitmap_padding(bmap); 610 return; 611 } 612 613 start = bmap->end + 1; 614 num = bmap->real_end - bmap->end; 615 bmap->bitmap_ops->mark_bmap_extent(bmap, start, num); 616 /* XXX ought to warn on error */ 617} 618 619int ext2fs_test_block_bitmap_range2(ext2fs_block_bitmap bmap, 620 blk64_t block, unsigned int num) 621{ 622 if (!bmap) 623 return EINVAL; 624 625 if (num == 1) 626 return !ext2fs_test_generic_bmap((ext2fs_generic_bitmap) 627 bmap, block); 628 629 if (EXT2FS_IS_32_BITMAP(bmap)) { 630 if ((block+num-1) & ~0xffffffffULL) { 631 ext2fs_warn_bitmap2((ext2fs_generic_bitmap) bmap, 632 EXT2FS_UNMARK_ERROR, 0xffffffff); 633 return EINVAL; 634 } 635 return ext2fs_test_block_bitmap_range( 636 (ext2fs_generic_bitmap) bmap, block, num); 637 } 638 639 if (!EXT2FS_IS_64_BITMAP(bmap)) 640 return EINVAL; 641 642 INC_STAT(bmap, test_ext_count); 643 644 return bmap->bitmap_ops->test_clear_bmap_extent(bmap, block, num); 645} 646 647void ext2fs_mark_block_bitmap_range2(ext2fs_block_bitmap bmap, 648 blk64_t block, unsigned int num) 649{ 650 if (!bmap) 651 return; 652 653 if (EXT2FS_IS_32_BITMAP(bmap)) { 654 if ((block+num-1) & ~0xffffffffULL) { 655 ext2fs_warn_bitmap2((ext2fs_generic_bitmap) bmap, 656 EXT2FS_UNMARK_ERROR, 0xffffffff); 657 return; 658 } 659 ext2fs_mark_block_bitmap_range((ext2fs_generic_bitmap) bmap, 660 block, num); 661 } 662 663 if (!EXT2FS_IS_64_BITMAP(bmap)) 664 return; 665 666 INC_STAT(bmap, mark_ext_count); 667 668 if ((block < bmap->start) || (block+num-1 > bmap->end)) { 669 ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_MARK, block, 670 bmap->description); 671 return; 672 } 673 674 bmap->bitmap_ops->mark_bmap_extent(bmap, block, num); 675} 676 677void ext2fs_unmark_block_bitmap_range2(ext2fs_block_bitmap bmap, 678 blk64_t block, unsigned int num) 679{ 680 if (!bmap) 681 return; 682 683 if (EXT2FS_IS_32_BITMAP(bmap)) { 684 if ((block+num-1) & ~0xffffffffULL) { 685 ext2fs_warn_bitmap2((ext2fs_generic_bitmap) bmap, 686 EXT2FS_UNMARK_ERROR, 0xffffffff); 687 return; 688 } 689 ext2fs_unmark_block_bitmap_range((ext2fs_generic_bitmap) bmap, 690 block, num); 691 } 692 693 if (!EXT2FS_IS_64_BITMAP(bmap)) 694 return; 695 696 INC_STAT(bmap, unmark_ext_count); 697 698 if ((block < bmap->start) || (block+num-1 > bmap->end)) { 699 ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_UNMARK, block, 700 bmap->description); 701 return; 702 } 703 704 bmap->bitmap_ops->unmark_bmap_extent(bmap, block, num); 705} 706 707void ext2fs_warn_bitmap32(ext2fs_generic_bitmap bitmap, const char *func) 708{ 709#ifndef OMIT_COM_ERR 710 if (bitmap && bitmap->description) 711 com_err(0, EXT2_ET_MAGIC_GENERIC_BITMAP, 712 "called %s with 64-bit bitmap for %s", func, 713 bitmap->description); 714 else 715 com_err(0, EXT2_ET_MAGIC_GENERIC_BITMAP, 716 "called %s with 64-bit bitmap", func); 717#endif 718} 719 720errcode_t ext2fs_convert_subcluster_bitmap(ext2_filsys fs, 721 ext2fs_block_bitmap *bitmap) 722{ 723 ext2fs_block_bitmap cmap, bmap; 724 errcode_t retval; 725 blk64_t i, b_end, c_end; 726 int n, ratio; 727 728 bmap = *bitmap; 729 730 if (fs->cluster_ratio_bits == ext2fs_get_bitmap_granularity(bmap)) 731 return 0; /* Nothing to do */ 732 733 retval = ext2fs_allocate_block_bitmap(fs, "converted cluster bitmap", 734 &cmap); 735 if (retval) 736 return retval; 737 738 i = bmap->start; 739 b_end = bmap->end; 740 bmap->end = bmap->real_end; 741 c_end = cmap->end; 742 cmap->end = cmap->real_end; 743 n = 0; 744 ratio = 1 << fs->cluster_ratio_bits; 745 while (i < bmap->real_end) { 746 if (ext2fs_test_block_bitmap2(bmap, i)) { 747 ext2fs_mark_block_bitmap2(cmap, i); 748 i += ratio - n; 749 n = 0; 750 continue; 751 } 752 i++; n++; 753 if (n >= ratio) 754 n = 0; 755 } 756 bmap->end = b_end; 757 cmap->end = c_end; 758 ext2fs_free_block_bitmap(bmap); 759 *bitmap = cmap; 760 return 0; 761} 762