2 * gen_bitmap64.c --- routines to read, write, and manipulate the new qinode and
5 * Copyright (C) 2007, 2008 Theodore Ts'o.
8 * This file may be redistributed under the terms of the GNU Public
26 #include <sys/types.h>
28 #ifdef HAVE_SYS_TIME_H
37 * Design of 64-bit bitmaps
39 * In order maintain ABI compatibility with programs that don't
40 * understand about 64-bit blocks/inodes,
41 * ext2fs_allocate_inode_bitmap() and ext2fs_allocate_block_bitmap()
42 * will create old-style bitmaps unless the application passes the
43 * flag EXT2_FLAG_64BITS to ext2fs_open(). If this flag is
44 * passed, then we know the application has been recompiled, so we can
45 * use the new-style bitmaps. If it is not passed, we have to return
46 * an error if trying to open a filesystem which needs 64-bit bitmaps.
48 * The new bitmaps use a new set of structure magic numbers, so that
49 * both the old-style and new-style interfaces can identify which
50 * version of the data structure was used. Both the old-style and
51 * new-style interfaces will support either type of bitmap, although
52 * of course 64-bit operation will only be possible when both the
53 * new-style interface and the new-style bitmap are used.
55 * For example, the new bitmap interfaces will check the structure
56 * magic numbers and so will be able to detect old-stype bitmap. If
57 * they see an old-style bitmap, they will pass it to the gen_bitmap.c
58 * functions for handling. The same will be true for the old
61 * The new-style interfaces will have several different back-end
62 * implementations, so we can support different encodings that are
63 * appropriate for different applications. In general the default
64 * should be whatever makes sense, and what the application/library
65 * will use. However, e2fsck may need specialized implementations for
66 * its own uses. For example, when doing parent directory pointer
67 * loop detections in pass 3, the bitmap will *always* be sparse, so
68 * e2fsck can request an encoding which is optimized for that.
71 static void warn_bitmap(ext2fs_generic_bitmap_64 bitmap,
75 if (bitmap->description)
76 com_err(0, bitmap->base_error_code+code,
77 "#%llu for %s", (unsigned long long) arg,
80 com_err(0, bitmap->base_error_code + code, "#%llu",
81 (unsigned long long) arg);
85 #ifdef ENABLE_BMAP_STATS_OPS
86 #define INC_STAT(map, name) map->stats.name
88 #define INC_STAT(map, name) ;;
92 errcode_t ext2fs_alloc_generic_bmap(ext2_filsys fs, errcode_t magic,
93 int type, __u64 start, __u64 end,
96 ext2fs_generic_bitmap *ret)
98 ext2fs_generic_bitmap_64 bitmap;
99 struct ext2_bitmap_ops *ops;
104 type = EXT2FS_BMAP64_BITARRAY;
107 case EXT2FS_BMAP64_BITARRAY:
108 ops = &ext2fs_blkmap64_bitarray;
110 case EXT2FS_BMAP64_RBTREE:
111 ops = &ext2fs_blkmap64_rbtree;
113 case EXT2FS_BMAP64_AUTODIR:
114 retval = ext2fs_get_num_dirs(fs, &num_dirs);
115 if (retval || num_dirs > (fs->super->s_inodes_count / 320))
116 ops = &ext2fs_blkmap64_bitarray;
118 ops = &ext2fs_blkmap64_rbtree;
124 retval = ext2fs_get_memzero(sizeof(struct ext2fs_struct_generic_bitmap_64),
129 #ifdef ENABLE_BMAP_STATS
130 if (gettimeofday(&bitmap->stats.created,
131 (struct timezone *) NULL) == -1) {
132 perror("gettimeofday");
133 ext2fs_free_mem(&bitmap);
136 bitmap->stats.type = type;
139 /* XXX factor out, repeated in copy_bmap */
140 bitmap->magic = magic;
142 bitmap->start = start;
144 bitmap->real_end = real_end;
145 bitmap->bitmap_ops = ops;
146 bitmap->cluster_bits = 0;
148 case EXT2_ET_MAGIC_INODE_BITMAP64:
149 bitmap->base_error_code = EXT2_ET_BAD_INODE_MARK;
151 case EXT2_ET_MAGIC_BLOCK_BITMAP64:
152 bitmap->base_error_code = EXT2_ET_BAD_BLOCK_MARK;
153 bitmap->cluster_bits = fs->cluster_ratio_bits;
156 bitmap->base_error_code = EXT2_ET_BAD_GENERIC_MARK;
159 retval = ext2fs_get_mem(strlen(descr)+1, &bitmap->description);
161 ext2fs_free_mem(&bitmap);
164 strcpy(bitmap->description, descr);
166 bitmap->description = 0;
168 retval = bitmap->bitmap_ops->new_bmap(fs, bitmap);
170 ext2fs_free_mem(&bitmap->description);
171 ext2fs_free_mem(&bitmap);
175 *ret = (ext2fs_generic_bitmap) bitmap;
179 #ifdef ENABLE_BMAP_STATS
180 static void ext2fs_print_bmap_statistics(ext2fs_generic_bitmap_64 bitmap)
182 struct ext2_bmap_statistics *stats = &bitmap->stats;
183 #ifdef ENABLE_BMAP_STATS_OPS
184 float mark_seq_perc = 0.0, test_seq_perc = 0.0;
185 float mark_back_perc = 0.0, test_back_perc = 0.0;
189 if (stats->test_count) {
190 test_seq_perc = ((float)stats->test_seq /
191 stats->test_count) * 100;
192 test_back_perc = ((float)stats->test_back /
193 stats->test_count) * 100;
196 if (stats->mark_count) {
197 mark_seq_perc = ((float)stats->mark_seq /
198 stats->mark_count) * 100;
199 mark_back_perc = ((float)stats->mark_back /
200 stats->mark_count) * 100;
203 if (gettimeofday(&now, (struct timezone *) NULL) == -1) {
204 perror("gettimeofday");
208 inuse = (double) now.tv_sec + \
209 (((double) now.tv_usec) * 0.000001);
210 inuse -= (double) stats->created.tv_sec + \
211 (((double) stats->created.tv_usec) * 0.000001);
212 #endif /* ENABLE_BMAP_STATS_OPS */
214 fprintf(stderr, "\n[+] %s bitmap (type %d)\n", bitmap->description,
216 fprintf(stderr, "=================================================\n");
217 #ifdef ENABLE_BMAP_STATS_OPS
218 fprintf(stderr, "%16llu bits long\n",
219 bitmap->real_end - bitmap->start);
220 fprintf(stderr, "%16lu copy_bmap\n%16lu resize_bmap\n",
221 stats->copy_count, stats->resize_count);
222 fprintf(stderr, "%16lu mark bmap\n%16lu unmark_bmap\n",
223 stats->mark_count, stats->unmark_count);
224 fprintf(stderr, "%16lu test_bmap\n%16lu mark_bmap_extent\n",
225 stats->test_count, stats->mark_ext_count);
226 fprintf(stderr, "%16lu unmark_bmap_extent\n"
227 "%16lu test_clear_bmap_extent\n",
228 stats->unmark_ext_count, stats->test_ext_count);
229 fprintf(stderr, "%16lu set_bmap_range\n%16lu set_bmap_range\n",
230 stats->set_range_count, stats->get_range_count);
231 fprintf(stderr, "%16lu clear_bmap\n%16lu contiguous bit test (%.2f%%)\n",
232 stats->clear_count, stats->test_seq, test_seq_perc);
233 fprintf(stderr, "%16lu contiguous bit mark (%.2f%%)\n"
234 "%16llu bits tested backwards (%.2f%%)\n",
235 stats->mark_seq, mark_seq_perc,
236 stats->test_back, test_back_perc);
237 fprintf(stderr, "%16llu bits marked backwards (%.2f%%)\n"
238 "%16.2f seconds in use\n",
239 stats->mark_back, mark_back_perc, inuse);
240 #endif /* ENABLE_BMAP_STATS_OPS */
244 void ext2fs_free_generic_bmap(ext2fs_generic_bitmap gen_bmap)
246 ext2fs_generic_bitmap_64 bmap = (ext2fs_generic_bitmap_64) gen_bmap;
251 if (EXT2FS_IS_32_BITMAP(bmap)) {
252 ext2fs_free_generic_bitmap(gen_bmap);
256 if (!EXT2FS_IS_64_BITMAP(bmap))
259 #ifdef ENABLE_BMAP_STATS
260 if (getenv("E2FSPROGS_BITMAP_STATS")) {
261 ext2fs_print_bmap_statistics(bmap);
262 bmap->bitmap_ops->print_stats(bmap);
266 bmap->bitmap_ops->free_bmap(bmap);
268 if (bmap->description) {
269 ext2fs_free_mem(&bmap->description);
270 bmap->description = 0;
273 ext2fs_free_mem(&bmap);
276 errcode_t ext2fs_copy_generic_bmap(ext2fs_generic_bitmap gen_src,
277 ext2fs_generic_bitmap *dest)
279 ext2fs_generic_bitmap_64 src = (ext2fs_generic_bitmap_64) gen_src;
280 char *descr, *new_descr;
281 ext2fs_generic_bitmap_64 new_bmap;
287 if (EXT2FS_IS_32_BITMAP(src))
288 return ext2fs_copy_generic_bitmap(gen_src, dest);
290 if (!EXT2FS_IS_64_BITMAP(src))
293 /* Allocate a new bitmap struct */
294 retval = ext2fs_get_memzero(sizeof(struct ext2fs_struct_generic_bitmap_64),
300 #ifdef ENABLE_BMAP_STATS_OPS
301 src->stats.copy_count++;
303 #ifdef ENABLE_BMAP_STATS
304 if (gettimeofday(&new_bmap->stats.created,
305 (struct timezone *) NULL) == -1) {
306 perror("gettimeofday");
307 ext2fs_free_mem(&new_bmap);
310 new_bmap->stats.type = src->stats.type;
313 /* Copy all the high-level parts over */
314 new_bmap->magic = src->magic;
315 new_bmap->fs = src->fs;
316 new_bmap->start = src->start;
317 new_bmap->end = src->end;
318 new_bmap->real_end = src->real_end;
319 new_bmap->bitmap_ops = src->bitmap_ops;
320 new_bmap->base_error_code = src->base_error_code;
321 new_bmap->cluster_bits = src->cluster_bits;
323 descr = src->description;
325 retval = ext2fs_get_mem(strlen(descr)+10, &new_descr);
327 ext2fs_free_mem(&new_bmap);
330 strcpy(new_descr, "copy of ");
331 strcat(new_descr, descr);
332 new_bmap->description = new_descr;
335 retval = src->bitmap_ops->copy_bmap(src, new_bmap);
337 ext2fs_free_mem(&new_bmap->description);
338 ext2fs_free_mem(&new_bmap);
342 *dest = (ext2fs_generic_bitmap) new_bmap;
347 errcode_t ext2fs_merge_generic_bmap(ext2fs_generic_bitmap gen_src,
348 ext2fs_generic_bitmap gen_dest,
349 ext2fs_generic_bitmap gen_dup,
350 ext2fs_generic_bitmap gen_dup_allowed)
352 ext2fs_generic_bitmap_64 src = (ext2fs_generic_bitmap_64)gen_src;
353 ext2fs_generic_bitmap_64 dest = (ext2fs_generic_bitmap_64)gen_dest;
354 ext2fs_generic_bitmap_64 dup = (ext2fs_generic_bitmap_64)gen_dup;
355 ext2fs_generic_bitmap_64 dup_allowed = (ext2fs_generic_bitmap_64)gen_dup_allowed;
360 if (!EXT2FS_IS_64_BITMAP(src) || !EXT2FS_IS_64_BITMAP(dest) ||
361 (dup && !EXT2FS_IS_64_BITMAP(dup)) ||
362 (dup_allowed && !EXT2FS_IS_64_BITMAP(dup_allowed)))
365 if (src->bitmap_ops != dest->bitmap_ops ||
366 (dup && src->bitmap_ops != dup->bitmap_ops) ||
367 (dup_allowed && src->bitmap_ops != dup_allowed->bitmap_ops))
370 if (src->bitmap_ops->merge_bmap == NULL)
373 return src->bitmap_ops->merge_bmap(src, dest, dup, dup_allowed);
376 errcode_t ext2fs_resize_generic_bmap(ext2fs_generic_bitmap gen_bmap,
380 ext2fs_generic_bitmap_64 bmap = (ext2fs_generic_bitmap_64) gen_bmap;
385 if (EXT2FS_IS_32_BITMAP(bmap))
386 return ext2fs_resize_generic_bitmap(gen_bmap->magic, new_end,
387 new_real_end, gen_bmap);
389 if (!EXT2FS_IS_64_BITMAP(bmap))
392 INC_STAT(bmap, resize_count);
394 return bmap->bitmap_ops->resize_bmap(bmap, new_end, new_real_end);
397 errcode_t ext2fs_fudge_generic_bmap_end(ext2fs_generic_bitmap gen_bitmap,
399 __u64 end, __u64 *oend)
401 ext2fs_generic_bitmap_64 bitmap = (ext2fs_generic_bitmap_64) gen_bitmap;
406 if (EXT2FS_IS_32_BITMAP(bitmap)) {
410 retval = ext2fs_fudge_generic_bitmap_end(gen_bitmap,
412 neq, end, &tmp_oend);
418 if (!EXT2FS_IS_64_BITMAP(bitmap))
421 if (end > bitmap->real_end)
429 __u64 ext2fs_get_generic_bmap_start(ext2fs_generic_bitmap gen_bitmap)
431 ext2fs_generic_bitmap_64 bitmap = (ext2fs_generic_bitmap_64) gen_bitmap;
436 if (EXT2FS_IS_32_BITMAP(bitmap))
437 return ext2fs_get_generic_bitmap_start(gen_bitmap);
439 if (!EXT2FS_IS_64_BITMAP(bitmap))
442 return bitmap->start;
445 __u64 ext2fs_get_generic_bmap_end(ext2fs_generic_bitmap gen_bitmap)
447 ext2fs_generic_bitmap_64 bitmap = (ext2fs_generic_bitmap_64) gen_bitmap;
452 if (EXT2FS_IS_32_BITMAP(bitmap))
453 return ext2fs_get_generic_bitmap_end(gen_bitmap);
455 if (!EXT2FS_IS_64_BITMAP(bitmap))
461 void ext2fs_clear_generic_bmap(ext2fs_generic_bitmap gen_bitmap)
463 ext2fs_generic_bitmap_64 bitmap = (ext2fs_generic_bitmap_64) gen_bitmap;
465 if (EXT2FS_IS_32_BITMAP(bitmap))
466 ext2fs_clear_generic_bitmap(gen_bitmap);
468 bitmap->bitmap_ops->clear_bmap(bitmap);
471 int ext2fs_mark_generic_bmap(ext2fs_generic_bitmap gen_bitmap,
474 ext2fs_generic_bitmap_64 bitmap = (ext2fs_generic_bitmap_64) gen_bitmap;
479 if (EXT2FS_IS_32_BITMAP(bitmap)) {
480 if (arg & ~0xffffffffULL) {
481 ext2fs_warn_bitmap2(gen_bitmap,
482 EXT2FS_MARK_ERROR, 0xffffffff);
485 return ext2fs_mark_generic_bitmap(gen_bitmap, arg);
488 if (!EXT2FS_IS_64_BITMAP(bitmap))
491 arg >>= bitmap->cluster_bits;
493 #ifdef ENABLE_BMAP_STATS_OPS
494 if (arg == bitmap->stats.last_marked + 1)
495 bitmap->stats.mark_seq++;
496 if (arg < bitmap->stats.last_marked)
497 bitmap->stats.mark_back++;
498 bitmap->stats.last_marked = arg;
499 bitmap->stats.mark_count++;
502 if ((arg < bitmap->start) || (arg > bitmap->end)) {
503 warn_bitmap(bitmap, EXT2FS_MARK_ERROR, arg);
507 return bitmap->bitmap_ops->mark_bmap(bitmap, arg);
510 int ext2fs_unmark_generic_bmap(ext2fs_generic_bitmap gen_bitmap,
513 ext2fs_generic_bitmap_64 bitmap = (ext2fs_generic_bitmap_64) gen_bitmap;
518 if (EXT2FS_IS_32_BITMAP(bitmap)) {
519 if (arg & ~0xffffffffULL) {
520 ext2fs_warn_bitmap2(gen_bitmap, EXT2FS_UNMARK_ERROR,
524 return ext2fs_unmark_generic_bitmap(gen_bitmap, arg);
527 if (!EXT2FS_IS_64_BITMAP(bitmap))
530 arg >>= bitmap->cluster_bits;
532 INC_STAT(bitmap, unmark_count);
534 if ((arg < bitmap->start) || (arg > bitmap->end)) {
535 warn_bitmap(bitmap, EXT2FS_UNMARK_ERROR, arg);
539 return bitmap->bitmap_ops->unmark_bmap(bitmap, arg);
542 int ext2fs_test_generic_bmap(ext2fs_generic_bitmap gen_bitmap,
545 ext2fs_generic_bitmap_64 bitmap = (ext2fs_generic_bitmap_64) gen_bitmap;
549 if (EXT2FS_IS_32_BITMAP(bitmap)) {
550 if (arg & ~0xffffffffULL) {
551 ext2fs_warn_bitmap2(gen_bitmap, EXT2FS_TEST_ERROR,
555 return ext2fs_test_generic_bitmap(gen_bitmap, arg);
558 if (!EXT2FS_IS_64_BITMAP(bitmap))
561 arg >>= bitmap->cluster_bits;
563 #ifdef ENABLE_BMAP_STATS_OPS
564 bitmap->stats.test_count++;
565 if (arg == bitmap->stats.last_tested + 1)
566 bitmap->stats.test_seq++;
567 if (arg < bitmap->stats.last_tested)
568 bitmap->stats.test_back++;
569 bitmap->stats.last_tested = arg;
572 if ((arg < bitmap->start) || (arg > bitmap->end)) {
573 warn_bitmap(bitmap, EXT2FS_TEST_ERROR, arg);
577 return bitmap->bitmap_ops->test_bmap(bitmap, arg);
580 errcode_t ext2fs_set_generic_bmap_range(ext2fs_generic_bitmap gen_bmap,
581 __u64 start, unsigned int num,
584 ext2fs_generic_bitmap_64 bmap = (ext2fs_generic_bitmap_64) gen_bmap;
589 if (EXT2FS_IS_32_BITMAP(bmap)) {
590 if ((start+num-1) & ~0xffffffffULL) {
591 ext2fs_warn_bitmap2(gen_bmap, EXT2FS_UNMARK_ERROR,
595 return ext2fs_set_generic_bitmap_range(gen_bmap, bmap->magic,
599 if (!EXT2FS_IS_64_BITMAP(bmap))
602 INC_STAT(bmap, set_range_count);
604 return bmap->bitmap_ops->set_bmap_range(bmap, start, num, in);
607 errcode_t ext2fs_get_generic_bmap_range(ext2fs_generic_bitmap gen_bmap,
608 __u64 start, unsigned int num,
611 ext2fs_generic_bitmap_64 bmap = (ext2fs_generic_bitmap_64) gen_bmap;
616 if (EXT2FS_IS_32_BITMAP(bmap)) {
617 if ((start+num-1) & ~0xffffffffULL) {
618 ext2fs_warn_bitmap2(gen_bmap,
619 EXT2FS_UNMARK_ERROR, 0xffffffff);
622 return ext2fs_get_generic_bitmap_range(gen_bmap, bmap->magic,
626 if (!EXT2FS_IS_64_BITMAP(bmap))
629 INC_STAT(bmap, get_range_count);
631 return bmap->bitmap_ops->get_bmap_range(bmap, start, num, out);
634 errcode_t ext2fs_compare_generic_bmap(errcode_t neq,
635 ext2fs_generic_bitmap gen_bm1,
636 ext2fs_generic_bitmap gen_bm2)
638 ext2fs_generic_bitmap_64 bm1 = (ext2fs_generic_bitmap_64) gen_bm1;
639 ext2fs_generic_bitmap_64 bm2 = (ext2fs_generic_bitmap_64) gen_bm2;
644 if (bm1->magic != bm2->magic)
647 /* Now we know both bitmaps have the same magic */
648 if (EXT2FS_IS_32_BITMAP(bm1))
649 return ext2fs_compare_generic_bitmap(bm1->magic, neq,
652 if (!EXT2FS_IS_64_BITMAP(bm1))
655 if ((bm1->start != bm2->start) ||
656 (bm1->end != bm2->end))
659 for (i = bm1->start; i < bm1->end; i++) {
661 ret1 = !!ext2fs_test_generic_bmap(gen_bm1, i);
662 ret2 = !!ext2fs_test_generic_bmap(gen_bm2, i);
671 void ext2fs_set_generic_bmap_padding(ext2fs_generic_bitmap gen_bmap)
673 ext2fs_generic_bitmap_64 bmap = (ext2fs_generic_bitmap_64) gen_bmap;
676 if (EXT2FS_IS_32_BITMAP(bmap)) {
677 ext2fs_set_generic_bitmap_padding(gen_bmap);
681 start = bmap->end + 1;
682 num = bmap->real_end - bmap->end;
683 bmap->bitmap_ops->mark_bmap_extent(bmap, start, num);
684 /* XXX ought to warn on error */
687 int ext2fs_test_block_bitmap_range2(ext2fs_block_bitmap gen_bmap,
688 blk64_t block, unsigned int num)
690 ext2fs_generic_bitmap_64 bmap = (ext2fs_generic_bitmap_64) gen_bmap;
691 __u64 end = block + num;
697 return !ext2fs_test_generic_bmap((ext2fs_generic_bitmap)
700 if (EXT2FS_IS_32_BITMAP(bmap)) {
701 if ((block & ~0xffffffffULL) ||
702 ((block+num-1) & ~0xffffffffULL)) {
703 ext2fs_warn_bitmap2((ext2fs_generic_bitmap) bmap,
704 EXT2FS_UNMARK_ERROR, 0xffffffff);
707 return ext2fs_test_block_bitmap_range(
708 (ext2fs_generic_bitmap) bmap, block, num);
711 if (!EXT2FS_IS_64_BITMAP(bmap))
714 INC_STAT(bmap, test_ext_count);
716 /* convert to clusters if necessary */
717 block >>= bmap->cluster_bits;
718 end += (1ULL << bmap->cluster_bits) - 1;
719 end >>= bmap->cluster_bits;
722 if ((block < bmap->start) || (block > bmap->end) ||
723 (block+num-1 > bmap->end)) {
724 ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_TEST, block,
729 return bmap->bitmap_ops->test_clear_bmap_extent(bmap, block, num);
732 int ext2fs_test_block_bitmap_range2_valid(ext2fs_block_bitmap bitmap,
733 blk64_t block, unsigned int num)
735 ext2fs_generic_bitmap_64 bmap = (ext2fs_generic_bitmap_64)bitmap;
736 __u64 end = block + num;
741 if (EXT2FS_IS_32_BITMAP(bmap)) {
742 if ((block & ~0xffffffffULL) ||
743 ((block+num-1) & ~0xffffffffULL)) {
748 if (!EXT2FS_IS_64_BITMAP(bmap))
751 /* convert to clusters if necessary */
752 block >>= bmap->cluster_bits;
753 end += (1 << bmap->cluster_bits) - 1;
754 end >>= bmap->cluster_bits;
757 if ((block < bmap->start) || (block > bmap->end) ||
758 (block+num-1 > bmap->end))
765 void ext2fs_mark_block_bitmap_range2(ext2fs_block_bitmap gen_bmap,
766 blk64_t block, unsigned int num)
768 ext2fs_generic_bitmap_64 bmap = (ext2fs_generic_bitmap_64) gen_bmap;
769 __u64 end = block + num;
774 if (EXT2FS_IS_32_BITMAP(bmap)) {
775 if ((block & ~0xffffffffULL) ||
776 ((block+num-1) & ~0xffffffffULL)) {
777 ext2fs_warn_bitmap2((ext2fs_generic_bitmap) bmap,
778 EXT2FS_UNMARK_ERROR, 0xffffffff);
781 ext2fs_mark_block_bitmap_range((ext2fs_generic_bitmap) bmap,
785 if (!EXT2FS_IS_64_BITMAP(bmap))
788 INC_STAT(bmap, mark_ext_count);
790 /* convert to clusters if necessary */
791 block >>= bmap->cluster_bits;
792 end += (1ULL << bmap->cluster_bits) - 1;
793 end >>= bmap->cluster_bits;
796 if ((block < bmap->start) || (block > bmap->end) ||
797 (block+num-1 > bmap->end)) {
798 ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_MARK, block,
803 bmap->bitmap_ops->mark_bmap_extent(bmap, block, num);
806 void ext2fs_unmark_block_bitmap_range2(ext2fs_block_bitmap gen_bmap,
807 blk64_t block, unsigned int num)
809 ext2fs_generic_bitmap_64 bmap = (ext2fs_generic_bitmap_64) gen_bmap;
810 __u64 end = block + num;
815 if (EXT2FS_IS_32_BITMAP(bmap)) {
816 if ((block & ~0xffffffffULL) ||
817 ((block+num-1) & ~0xffffffffULL)) {
818 ext2fs_warn_bitmap2((ext2fs_generic_bitmap) bmap,
819 EXT2FS_UNMARK_ERROR, 0xffffffff);
822 ext2fs_unmark_block_bitmap_range((ext2fs_generic_bitmap) bmap,
826 if (!EXT2FS_IS_64_BITMAP(bmap))
829 INC_STAT(bmap, unmark_ext_count);
831 /* convert to clusters if necessary */
832 block >>= bmap->cluster_bits;
833 end += (1ULL << bmap->cluster_bits) - 1;
834 end >>= bmap->cluster_bits;
837 if ((block < bmap->start) || (block > bmap->end) ||
838 (block+num-1 > bmap->end)) {
839 ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_UNMARK, block,
844 bmap->bitmap_ops->unmark_bmap_extent(bmap, block, num);
847 void ext2fs_warn_bitmap32(ext2fs_generic_bitmap gen_bitmap, const char *func)
849 ext2fs_generic_bitmap_64 bitmap = (ext2fs_generic_bitmap_64) gen_bitmap;
852 if (bitmap && bitmap->description)
853 com_err(0, EXT2_ET_MAGIC_GENERIC_BITMAP,
854 "called %s with 64-bit bitmap for %s", func,
855 bitmap->description);
857 com_err(0, EXT2_ET_MAGIC_GENERIC_BITMAP,
858 "called %s with 64-bit bitmap", func);
862 errcode_t ext2fs_convert_subcluster_bitmap(ext2_filsys fs,
863 ext2fs_block_bitmap *bitmap)
865 ext2fs_generic_bitmap_64 bmap, cmap;
866 ext2fs_block_bitmap gen_bmap = *bitmap, gen_cmap;
868 blk64_t i, next, b_end, c_end;
870 bmap = (ext2fs_generic_bitmap_64) gen_bmap;
871 if (fs->cluster_ratio_bits == ext2fs_get_bitmap_granularity(gen_bmap))
872 return 0; /* Nothing to do */
874 retval = ext2fs_allocate_block_bitmap(fs, "converted cluster bitmap",
879 cmap = (ext2fs_generic_bitmap_64) gen_cmap;
882 bmap->end = bmap->real_end;
884 cmap->end = cmap->real_end;
885 while (i < bmap->real_end) {
886 retval = ext2fs_find_first_set_block_bitmap2(gen_bmap,
887 i, bmap->real_end, &next);
890 ext2fs_mark_block_bitmap2(gen_cmap, next);
891 i = EXT2FS_C2B(fs, EXT2FS_B2C(fs, next) + 1);
895 ext2fs_free_block_bitmap(gen_bmap);
896 *bitmap = (ext2fs_block_bitmap) cmap;
900 errcode_t ext2fs_find_first_zero_generic_bmap(ext2fs_generic_bitmap bitmap,
901 __u64 start, __u64 end, __u64 *out)
903 ext2fs_generic_bitmap_64 bmap64 = (ext2fs_generic_bitmap_64) bitmap;
904 __u64 cstart, cend, cout;
910 if (EXT2FS_IS_32_BITMAP(bitmap)) {
913 if (((start) & ~0xffffffffULL) ||
914 ((end) & ~0xffffffffULL)) {
915 ext2fs_warn_bitmap2(bitmap, EXT2FS_TEST_ERROR, start);
919 retval = ext2fs_find_first_zero_generic_bitmap(bitmap, start,
926 if (!EXT2FS_IS_64_BITMAP(bitmap))
929 cstart = start >> bmap64->cluster_bits;
930 cend = end >> bmap64->cluster_bits;
932 if (cstart < bmap64->start || cend > bmap64->end || start > end) {
933 warn_bitmap(bmap64, EXT2FS_TEST_ERROR, start);
937 if (bmap64->bitmap_ops->find_first_zero) {
938 retval = bmap64->bitmap_ops->find_first_zero(bmap64, cstart,
943 cout <<= bmap64->cluster_bits;
944 *out = (cout >= start) ? cout : start;
948 for (cout = cstart; cout <= cend; cout++)
949 if (!bmap64->bitmap_ops->test_bmap(bmap64, cout))
955 errcode_t ext2fs_find_first_set_generic_bmap(ext2fs_generic_bitmap bitmap,
956 __u64 start, __u64 end, __u64 *out)
958 ext2fs_generic_bitmap_64 bmap64 = (ext2fs_generic_bitmap_64) bitmap;
959 __u64 cstart, cend, cout;
965 if (EXT2FS_IS_32_BITMAP(bitmap)) {
968 if (((start) & ~0xffffffffULL) ||
969 ((end) & ~0xffffffffULL)) {
970 ext2fs_warn_bitmap2(bitmap, EXT2FS_TEST_ERROR, start);
974 retval = ext2fs_find_first_set_generic_bitmap(bitmap, start,
981 if (!EXT2FS_IS_64_BITMAP(bitmap))
984 cstart = start >> bmap64->cluster_bits;
985 cend = end >> bmap64->cluster_bits;
987 if (cstart < bmap64->start || cend > bmap64->end || start > end) {
988 warn_bitmap(bmap64, EXT2FS_TEST_ERROR, start);
992 if (bmap64->bitmap_ops->find_first_set) {
993 retval = bmap64->bitmap_ops->find_first_set(bmap64, cstart,
998 cout <<= bmap64->cluster_bits;
999 *out = (cout >= start) ? cout : start;
1003 for (cout = cstart; cout <= cend; cout++)
1004 if (bmap64->bitmap_ops->test_bmap(bmap64, cout))
1010 errcode_t ext2fs_count_used_clusters(ext2_filsys fs, blk64_t start,
1011 blk64_t end, blk64_t *out)
1014 blk64_t tot_set = 0;
1015 errcode_t retval = 0;
1017 while (start < end) {
1018 retval = ext2fs_find_first_set_block_bitmap2(fs->block_map,
1021 if (retval == ENOENT)
1027 retval = ext2fs_find_first_zero_block_bitmap2(fs->block_map,
1030 tot_set += next - start;
1032 } else if (retval == ENOENT) {
1034 tot_set += end - start + 1;
1041 *out = EXT2FS_NUM_B2C(fs, tot_set);