1 /* 2 * rw_bitmaps.c --- routines to read and write the inode and block bitmaps. 3 * 4 * Copyright (C) 1993, 1994, 1994, 1996 Theodore Ts'o. 5 * 6 * %Begin-Header% 7 * This file may be redistributed under the terms of the GNU Library 8 * General Public License, version 2. 9 * %End-Header% 10 */ 11 12 #include "config.h" 13 #include <stdio.h> 14 #include <string.h> 15 #if HAVE_UNISTD_H 16 #include <unistd.h> 17 #endif 18 #include <fcntl.h> 19 #include <time.h> 20 #ifdef HAVE_SYS_STAT_H 21 #include <sys/stat.h> 22 #endif 23 #ifdef HAVE_SYS_TYPES_H 24 #include <sys/types.h> 25 #endif 26 #ifdef HAVE_PTHREAD_H 27 #include <pthread.h> 28 #endif 29 30 #include "ext2_fs.h" 31 #include "ext2fs.h" 32 #include "e2image.h" 33 34 #ifdef HAVE_PTHREAD 35 typedef pthread_mutex_t mutex_t; 36 37 static void unix_pthread_mutex_lock(mutex_t *mutex) 38 { 39 if (mutex) 40 pthread_mutex_lock(mutex); 41 } 42 static void unix_pthread_mutex_unlock(mutex_t *mutex) 43 { 44 if (mutex) 45 pthread_mutex_unlock(mutex); 46 } 47 #else 48 typedef int mutex_t; 49 #define unix_pthread_mutex_lock(mutex_t) do {} while (0) 50 #define unix_pthread_mutex_unlock(mutex_t) do {} while (0) 51 #endif 52 53 static errcode_t write_bitmaps(ext2_filsys fs, int do_inode, int do_block) 54 { 55 dgrp_t i; 56 unsigned int j; 57 int block_nbytes, inode_nbytes; 58 unsigned int nbits; 59 errcode_t retval; 60 char *block_buf = NULL, *inode_buf = NULL; 61 int csum_flag; 62 blk64_t blk; 63 blk64_t blk_itr = EXT2FS_B2C(fs, fs->super->s_first_data_block); 64 ext2_ino_t ino_itr = 1; 65 66 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); 67 68 if (!(fs->flags & EXT2_FLAG_RW)) 69 return EXT2_ET_RO_FILSYS; 70 71 csum_flag = ext2fs_has_group_desc_csum(fs); 72 73 inode_nbytes = block_nbytes = 0; 74 if (do_block) { 75 block_nbytes = EXT2_CLUSTERS_PER_GROUP(fs->super) / 8; 76 retval = io_channel_alloc_buf(fs->io, 0, &block_buf); 77 if (retval) 78 goto errout; 79 memset(block_buf, 0xff, fs->blocksize); 80 } 81 if (do_inode) { 82 inode_nbytes = (size_t) 83 ((EXT2_INODES_PER_GROUP(fs->super)+7) / 8); 84 retval = io_channel_alloc_buf(fs->io, 0, &inode_buf); 85 if (retval) 86 goto errout; 87 memset(inode_buf, 0xff, fs->blocksize); 88 } 89 90 for (i = 0; i < fs->group_desc_count; i++) { 91 if (!do_block) 92 goto skip_block_bitmap; 93 94 if (csum_flag && ext2fs_bg_flags_test(fs, i, EXT2_BG_BLOCK_UNINIT) 95 ) 96 goto skip_this_block_bitmap; 97 98 retval = ext2fs_get_block_bitmap_range2(fs->block_map, 99 blk_itr, block_nbytes << 3, block_buf); 100 if (retval) 101 goto errout; 102 103 if (i == fs->group_desc_count - 1) { 104 /* Force bitmap padding for the last group */ 105 nbits = EXT2FS_NUM_B2C(fs, 106 ((ext2fs_blocks_count(fs->super) 107 - (__u64) fs->super->s_first_data_block) 108 % (__u64) EXT2_BLOCKS_PER_GROUP(fs->super))); 109 if (nbits) 110 for (j = nbits; j < fs->blocksize * 8; j++) 111 ext2fs_set_bit(j, block_buf); 112 } 113 114 retval = ext2fs_block_bitmap_csum_set(fs, i, block_buf, 115 block_nbytes); 116 if (retval) 117 return retval; 118 ext2fs_group_desc_csum_set(fs, i); 119 fs->flags |= EXT2_FLAG_DIRTY; 120 121 blk = ext2fs_block_bitmap_loc(fs, i); 122 if (blk) { 123 retval = io_channel_write_blk64(fs->io, blk, 1, 124 block_buf); 125 if (retval) { 126 retval = EXT2_ET_BLOCK_BITMAP_WRITE; 127 goto errout; 128 } 129 } 130 skip_this_block_bitmap: 131 blk_itr += block_nbytes << 3; 132 skip_block_bitmap: 133 134 if (!do_inode) 135 continue; 136 137 if (csum_flag && ext2fs_bg_flags_test(fs, i, EXT2_BG_INODE_UNINIT) 138 ) 139 goto skip_this_inode_bitmap; 140 141 retval = ext2fs_get_inode_bitmap_range2(fs->inode_map, 142 ino_itr, inode_nbytes << 3, inode_buf); 143 if (retval) 144 goto errout; 145 146 retval = ext2fs_inode_bitmap_csum_set(fs, i, inode_buf, 147 inode_nbytes); 148 if (retval) 149 goto errout; 150 ext2fs_group_desc_csum_set(fs, i); 151 fs->flags |= EXT2_FLAG_DIRTY; 152 153 blk = ext2fs_inode_bitmap_loc(fs, i); 154 if (blk) { 155 retval = io_channel_write_blk64(fs->io, blk, 1, 156 inode_buf); 157 if (retval) { 158 retval = EXT2_ET_INODE_BITMAP_WRITE; 159 goto errout; 160 } 161 } 162 skip_this_inode_bitmap: 163 ino_itr += inode_nbytes << 3; 164 165 } 166 if (do_block) { 167 fs->flags &= ~EXT2_FLAG_BB_DIRTY; 168 ext2fs_free_mem(&block_buf); 169 } 170 if (do_inode) { 171 fs->flags &= ~EXT2_FLAG_IB_DIRTY; 172 ext2fs_free_mem(&inode_buf); 173 } 174 return 0; 175 errout: 176 if (inode_buf) 177 ext2fs_free_mem(&inode_buf); 178 if (block_buf) 179 ext2fs_free_mem(&block_buf); 180 return retval; 181 } 182 183 static errcode_t mark_uninit_bg_group_blocks(ext2_filsys fs) 184 { 185 dgrp_t i; 186 blk64_t blk; 187 ext2fs_block_bitmap bmap = fs->block_map; 188 189 for (i = 0; i < fs->group_desc_count; i++) { 190 if (!ext2fs_bg_flags_test(fs, i, EXT2_BG_BLOCK_UNINIT)) 191 continue; 192 193 ext2fs_reserve_super_and_bgd(fs, i, bmap); 194 195 /* 196 * Mark the blocks used for the inode table 197 */ 198 blk = ext2fs_inode_table_loc(fs, i); 199 if (blk) 200 ext2fs_mark_block_bitmap_range2(bmap, blk, 201 fs->inode_blocks_per_group); 202 203 /* 204 * Mark block used for the block bitmap 205 */ 206 blk = ext2fs_block_bitmap_loc(fs, i); 207 if (blk) 208 ext2fs_mark_block_bitmap2(bmap, blk); 209 210 /* 211 * Mark block used for the inode bitmap 212 */ 213 blk = ext2fs_inode_bitmap_loc(fs, i); 214 if (blk) 215 ext2fs_mark_block_bitmap2(bmap, blk); 216 } 217 return 0; 218 } 219 220 static int bitmap_tail_verify(unsigned char *bitmap, int first, int last) 221 { 222 int i; 223 224 for (i = first; i <= last; i++) 225 if (bitmap[i] != 0xff) 226 return 0; 227 return 1; 228 } 229 230 static errcode_t read_bitmaps_range_prepare(ext2_filsys fs, int flags) 231 { 232 errcode_t retval; 233 int block_nbytes = EXT2_CLUSTERS_PER_GROUP(fs->super) / 8; 234 int inode_nbytes = EXT2_INODES_PER_GROUP(fs->super) / 8; 235 char *buf; 236 237 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); 238 239 if ((block_nbytes > (int) fs->blocksize) || 240 (inode_nbytes > (int) fs->blocksize)) 241 return EXT2_ET_CORRUPT_SUPERBLOCK; 242 243 fs->write_bitmaps = ext2fs_write_bitmaps; 244 245 retval = ext2fs_get_mem(strlen(fs->device_name) + 80, &buf); 246 if (retval) 247 return retval; 248 249 if (flags & EXT2FS_BITMAPS_BLOCK) { 250 if (fs->block_map) 251 ext2fs_free_block_bitmap(fs->block_map); 252 strcpy(buf, "block bitmap for "); 253 strcat(buf, fs->device_name); 254 retval = ext2fs_allocate_block_bitmap(fs, buf, &fs->block_map); 255 if (retval) 256 goto cleanup; 257 } 258 259 if (flags & EXT2FS_BITMAPS_INODE) { 260 if (fs->inode_map) 261 ext2fs_free_inode_bitmap(fs->inode_map); 262 strcpy(buf, "inode bitmap for "); 263 strcat(buf, fs->device_name); 264 retval = ext2fs_allocate_inode_bitmap(fs, buf, &fs->inode_map); 265 if (retval) 266 goto cleanup; 267 } 268 ext2fs_free_mem(&buf); 269 return retval; 270 271 cleanup: 272 if (flags & EXT2FS_BITMAPS_BLOCK) { 273 ext2fs_free_block_bitmap(fs->block_map); 274 fs->block_map = 0; 275 } 276 if (flags & EXT2FS_BITMAPS_INODE) { 277 ext2fs_free_inode_bitmap(fs->inode_map); 278 fs->inode_map = 0; 279 } 280 ext2fs_free_mem(&buf); 281 return retval; 282 } 283 284 static errcode_t read_bitmaps_range_start(ext2_filsys fs, int flags, 285 dgrp_t start, dgrp_t end, 286 mutex_t *mutex, 287 int *tail_flags) 288 { 289 dgrp_t i; 290 char *block_bitmap = 0, *inode_bitmap = 0; 291 errcode_t retval = 0; 292 int block_nbytes = EXT2_CLUSTERS_PER_GROUP(fs->super) / 8; 293 int inode_nbytes = EXT2_INODES_PER_GROUP(fs->super) / 8; 294 int csum_flag; 295 unsigned int cnt; 296 blk64_t blk; 297 blk64_t blk_itr = EXT2FS_B2C(fs, fs->super->s_first_data_block); 298 blk64_t blk_cnt; 299 ext2_ino_t ino_itr = 1; 300 ext2_ino_t ino_cnt; 301 302 csum_flag = ext2fs_has_group_desc_csum(fs); 303 304 if (flags & EXT2FS_BITMAPS_BLOCK) { 305 retval = io_channel_alloc_buf(fs->io, 0, &block_bitmap); 306 if (retval) 307 goto cleanup; 308 } else { 309 block_nbytes = 0; 310 } 311 312 if (flags & EXT2FS_BITMAPS_INODE) { 313 retval = io_channel_alloc_buf(fs->io, 0, &inode_bitmap); 314 if (retval) 315 goto cleanup; 316 } else { 317 inode_nbytes = 0; 318 } 319 320 /* io should be null */ 321 if (fs->flags & EXT2_FLAG_IMAGE_FILE) { 322 blk = (ext2fs_le32_to_cpu(fs->image_header->offset_inodemap) / fs->blocksize); 323 ino_cnt = fs->super->s_inodes_count; 324 while (inode_bitmap && ino_cnt > 0) { 325 retval = io_channel_read_blk64(fs->image_io, blk++, 326 1, inode_bitmap); 327 if (retval) 328 goto cleanup; 329 cnt = fs->blocksize << 3; 330 if (cnt > ino_cnt) 331 cnt = ino_cnt; 332 retval = ext2fs_set_inode_bitmap_range2(fs->inode_map, 333 ino_itr, cnt, inode_bitmap); 334 if (retval) 335 goto cleanup; 336 ino_itr += cnt; 337 ino_cnt -= cnt; 338 } 339 blk = (ext2fs_le32_to_cpu(fs->image_header->offset_blockmap) / 340 fs->blocksize); 341 blk_cnt = EXT2_GROUPS_TO_CLUSTERS(fs->super, 342 fs->group_desc_count); 343 while (block_bitmap && blk_cnt > 0) { 344 retval = io_channel_read_blk64(fs->image_io, blk++, 345 1, block_bitmap); 346 if (retval) 347 goto cleanup; 348 cnt = fs->blocksize << 3; 349 if (cnt > blk_cnt) 350 cnt = blk_cnt; 351 retval = ext2fs_set_block_bitmap_range2(fs->block_map, 352 blk_itr, cnt, block_bitmap); 353 if (retval) 354 goto cleanup; 355 blk_itr += cnt; 356 blk_cnt -= cnt; 357 } 358 goto cleanup; 359 } 360 361 blk_itr += ((blk64_t)start * (block_nbytes << 3)); 362 ino_itr += ((blk64_t)start * (inode_nbytes << 3)); 363 for (i = start; i <= end; i++) { 364 if (block_bitmap) { 365 blk = ext2fs_block_bitmap_loc(fs, i); 366 if ((csum_flag && 367 ext2fs_bg_flags_test(fs, i, EXT2_BG_BLOCK_UNINIT) && 368 ext2fs_group_desc_csum_verify(fs, i)) || 369 (blk >= ext2fs_blocks_count(fs->super))) 370 blk = 0; 371 if (blk) { 372 retval = io_channel_read_blk64(fs->io, blk, 373 1, block_bitmap); 374 if (retval) { 375 retval = EXT2_ET_BLOCK_BITMAP_READ; 376 goto cleanup; 377 } 378 /* verify block bitmap checksum */ 379 if (!(fs->flags & 380 EXT2_FLAG_IGNORE_CSUM_ERRORS) && 381 !ext2fs_block_bitmap_csum_verify(fs, i, 382 block_bitmap, block_nbytes)) { 383 retval = 384 EXT2_ET_BLOCK_BITMAP_CSUM_INVALID; 385 goto cleanup; 386 } 387 if (!bitmap_tail_verify((unsigned char *) block_bitmap, 388 block_nbytes, fs->blocksize - 1)) 389 *tail_flags |= EXT2_FLAG_BBITMAP_TAIL_PROBLEM; 390 } else 391 memset(block_bitmap, 0, block_nbytes); 392 cnt = block_nbytes << 3; 393 unix_pthread_mutex_lock(mutex); 394 retval = ext2fs_set_block_bitmap_range2(fs->block_map, 395 blk_itr, cnt, block_bitmap); 396 unix_pthread_mutex_unlock(mutex); 397 if (retval) 398 goto cleanup; 399 blk_itr += block_nbytes << 3; 400 } 401 if (inode_bitmap) { 402 blk = ext2fs_inode_bitmap_loc(fs, i); 403 if ((csum_flag && 404 ext2fs_bg_flags_test(fs, i, EXT2_BG_INODE_UNINIT) && 405 ext2fs_group_desc_csum_verify(fs, i)) || 406 (blk >= ext2fs_blocks_count(fs->super))) 407 blk = 0; 408 if (blk) { 409 retval = io_channel_read_blk64(fs->io, blk, 410 1, inode_bitmap); 411 if (retval) { 412 retval = EXT2_ET_INODE_BITMAP_READ; 413 goto cleanup; 414 } 415 416 /* verify inode bitmap checksum */ 417 if (!(fs->flags & 418 EXT2_FLAG_IGNORE_CSUM_ERRORS) && 419 !ext2fs_inode_bitmap_csum_verify(fs, i, 420 inode_bitmap, inode_nbytes)) { 421 retval = 422 EXT2_ET_INODE_BITMAP_CSUM_INVALID; 423 goto cleanup; 424 } 425 if (!bitmap_tail_verify((unsigned char *) inode_bitmap, 426 inode_nbytes, fs->blocksize - 1)) 427 *tail_flags |= EXT2_FLAG_IBITMAP_TAIL_PROBLEM; 428 } else 429 memset(inode_bitmap, 0, inode_nbytes); 430 cnt = inode_nbytes << 3; 431 unix_pthread_mutex_lock(mutex); 432 retval = ext2fs_set_inode_bitmap_range2(fs->inode_map, 433 ino_itr, cnt, inode_bitmap); 434 unix_pthread_mutex_unlock(mutex); 435 if (retval) 436 goto cleanup; 437 ino_itr += inode_nbytes << 3; 438 } 439 } 440 441 cleanup: 442 if (inode_bitmap) 443 ext2fs_free_mem(&inode_bitmap); 444 if (block_bitmap) 445 ext2fs_free_mem(&block_bitmap); 446 return retval; 447 } 448 449 static errcode_t read_bitmaps_range_end(ext2_filsys fs, int flags, 450 int tail_flags) 451 { 452 errcode_t retval; 453 454 /* Mark group blocks for any BLOCK_UNINIT groups */ 455 if (flags & EXT2FS_BITMAPS_BLOCK) { 456 retval = mark_uninit_bg_group_blocks(fs); 457 if (retval) 458 return retval; 459 fs->flags &= ~EXT2_FLAG_BBITMAP_TAIL_PROBLEM; 460 } 461 if (flags & EXT2FS_BITMAPS_INODE) 462 fs->flags &= ~EXT2_FLAG_IBITMAP_TAIL_PROBLEM; 463 fs->flags |= tail_flags; 464 465 return 0; 466 } 467 468 static void read_bitmaps_cleanup_on_error(ext2_filsys fs, int flags) 469 { 470 if (flags & EXT2FS_BITMAPS_BLOCK) { 471 ext2fs_free_block_bitmap(fs->block_map); 472 fs->block_map = 0; 473 } 474 if (flags & EXT2FS_BITMAPS_INODE) { 475 ext2fs_free_inode_bitmap(fs->inode_map); 476 fs->inode_map = 0; 477 } 478 } 479 480 static errcode_t read_bitmaps_range(ext2_filsys fs, int flags, 481 dgrp_t start, dgrp_t end) 482 { 483 errcode_t retval; 484 int tail_flags = 0; 485 486 retval = read_bitmaps_range_prepare(fs, flags); 487 if (retval) 488 return retval; 489 490 retval = read_bitmaps_range_start(fs, flags, start, end, 491 NULL, &tail_flags); 492 if (retval == 0) 493 retval = read_bitmaps_range_end(fs, flags, tail_flags); 494 if (retval) 495 read_bitmaps_cleanup_on_error(fs, flags); 496 return retval; 497 } 498 499 #ifdef HAVE_PTHREAD 500 struct read_bitmaps_thread_info { 501 ext2_filsys rbt_fs; 502 int rbt_flags; 503 dgrp_t rbt_grp_start; 504 dgrp_t rbt_grp_end; 505 errcode_t rbt_retval; 506 pthread_mutex_t *rbt_mutex; 507 int rbt_tail_flags; 508 }; 509 510 static void *read_bitmaps_thread(void *data) 511 { 512 struct read_bitmaps_thread_info *rbt = data; 513 514 rbt->rbt_retval = read_bitmaps_range_start(rbt->rbt_fs, rbt->rbt_flags, 515 rbt->rbt_grp_start, rbt->rbt_grp_end, 516 rbt->rbt_mutex, &rbt->rbt_tail_flags); 517 return NULL; 518 } 519 #endif 520 521 errcode_t ext2fs_rw_bitmaps(ext2_filsys fs, int flags, int num_threads) 522 { 523 #ifdef HAVE_PTHREAD 524 pthread_attr_t attr; 525 pthread_t *thread_ids = NULL; 526 struct read_bitmaps_thread_info *thread_infos = NULL; 527 pthread_mutex_t rbt_mutex = PTHREAD_MUTEX_INITIALIZER; 528 errcode_t retval; 529 errcode_t rc; 530 unsigned flexbg_size = 1 << fs->super->s_log_groups_per_flex; 531 dgrp_t average_group; 532 int i, tail_flags = 0; 533 #endif 534 535 if (flags & ~EXT2FS_BITMAPS_VALID_FLAGS) 536 return EXT2_ET_INVALID_ARGUMENT; 537 538 if (flags & EXT2FS_BITMAPS_WRITE) 539 return write_bitmaps(fs, flags & EXT2FS_BITMAPS_INODE, 540 flags & EXT2FS_BITMAPS_BLOCK); 541 542 #ifdef HAVE_PTHREAD 543 if (((fs->io->flags & CHANNEL_FLAGS_THREADS) == 0) || 544 (num_threads == 1) || (fs->flags & EXT2_FLAG_IMAGE_FILE)) 545 goto fallback; 546 547 #if defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_CONF) 548 if (num_threads < 0) 549 num_threads = sysconf(_SC_NPROCESSORS_CONF); 550 #endif 551 /* 552 * Guess for now; eventually we should probably define 553 * ext2fs_get_num_cpus() and teach it how to get this info on 554 * MacOS, FreeBSD, etc. 555 * ref: https://stackoverflow.com/questions/150355 556 */ 557 if (num_threads < 0) 558 num_threads = 4; 559 560 if (num_threads > fs->group_desc_count) 561 num_threads = fs->group_desc_count; 562 average_group = fs->group_desc_count / num_threads; 563 if (ext2fs_has_feature_flex_bg(fs->super)) { 564 average_group = (average_group / flexbg_size) * flexbg_size; 565 } 566 if (average_group == 0) 567 goto fallback; 568 569 io_channel_set_options(fs->io, "cache=off"); 570 retval = pthread_attr_init(&attr); 571 if (retval) 572 return retval; 573 574 thread_ids = calloc(sizeof(pthread_t), num_threads); 575 if (!thread_ids) 576 return ENOMEM; 577 578 thread_infos = calloc(sizeof(struct read_bitmaps_thread_info), 579 num_threads); 580 if (!thread_infos) 581 goto out; 582 583 retval = read_bitmaps_range_prepare(fs, flags); 584 if (retval) 585 goto out; 586 587 // fprintf(stdout, "Multiple threads triggered to read bitmaps\n"); 588 for (i = 0; i < num_threads; i++) { 589 thread_infos[i].rbt_fs = fs; 590 thread_infos[i].rbt_flags = flags; 591 thread_infos[i].rbt_mutex = &rbt_mutex; 592 thread_infos[i].rbt_tail_flags = 0; 593 if (i == 0) 594 thread_infos[i].rbt_grp_start = 0; 595 else 596 thread_infos[i].rbt_grp_start = average_group * i + 1; 597 598 if (i == num_threads - 1) 599 thread_infos[i].rbt_grp_end = fs->group_desc_count - 1; 600 else 601 thread_infos[i].rbt_grp_end = average_group * (i + 1); 602 retval = pthread_create(&thread_ids[i], &attr, 603 &read_bitmaps_thread, &thread_infos[i]); 604 if (retval) 605 break; 606 } 607 for (i = 0; i < num_threads; i++) { 608 if (!thread_ids[i]) 609 break; 610 rc = pthread_join(thread_ids[i], NULL); 611 if (rc && !retval) 612 retval = rc; 613 rc = thread_infos[i].rbt_retval; 614 if (rc && !retval) 615 retval = rc; 616 tail_flags |= thread_infos[i].rbt_tail_flags; 617 } 618 out: 619 rc = pthread_attr_destroy(&attr); 620 if (rc && !retval) 621 retval = rc; 622 free(thread_infos); 623 free(thread_ids); 624 625 if (retval == 0) 626 retval = read_bitmaps_range_end(fs, flags, tail_flags); 627 if (retval) 628 read_bitmaps_cleanup_on_error(fs, flags); 629 /* XXX should save and restore cache setting */ 630 io_channel_set_options(fs->io, "cache=on"); 631 return retval; 632 fallback: 633 #endif /* HAVE_PTHREAD */ 634 return read_bitmaps_range(fs, flags, 0, fs->group_desc_count - 1); 635 } 636 637 errcode_t ext2fs_read_inode_bitmap(ext2_filsys fs) 638 { 639 return ext2fs_rw_bitmaps(fs, EXT2FS_BITMAPS_INODE, -1); 640 } 641 642 errcode_t ext2fs_read_block_bitmap(ext2_filsys fs) 643 { 644 return ext2fs_rw_bitmaps(fs, EXT2FS_BITMAPS_BLOCK, -1); 645 } 646 647 errcode_t ext2fs_write_inode_bitmap(ext2_filsys fs) 648 { 649 return write_bitmaps(fs, 1, 0); 650 } 651 652 errcode_t ext2fs_write_block_bitmap (ext2_filsys fs) 653 { 654 return write_bitmaps(fs, 0, 1); 655 } 656 657 errcode_t ext2fs_read_bitmaps(ext2_filsys fs) 658 { 659 int flags = 0; 660 661 if (!fs->inode_map) 662 flags |= EXT2FS_BITMAPS_INODE; 663 if (!fs->block_map) 664 flags |= EXT2FS_BITMAPS_BLOCK; 665 if (flags == 0) 666 return 0; 667 return ext2fs_rw_bitmaps(fs, flags, -1); 668 } 669 670 errcode_t ext2fs_write_bitmaps(ext2_filsys fs) 671 { 672 int do_inode = fs->inode_map && ext2fs_test_ib_dirty(fs); 673 int do_block = fs->block_map && ext2fs_test_bb_dirty(fs); 674 675 if (!do_inode && !do_block) 676 return 0; 677 678 return write_bitmaps(fs, do_inode, do_block); 679 }