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 bitmap
,
75 if (bitmap
->description
)
76 com_err(0, bitmap
->base_error_code
+code
,
77 "#%llu for %s", arg
, bitmap
->description
);
79 com_err(0, bitmap
->base_error_code
+ code
, "#%llu", arg
);
83 #ifdef ENABLE_BMAP_STATS_OPS
84 #define INC_STAT(map, name) map->stats.name
86 #define INC_STAT(map, name) ;;
90 errcode_t
ext2fs_alloc_generic_bmap(ext2_filsys fs
, errcode_t magic
,
91 int type
, __u64 start
, __u64 end
,
94 ext2fs_generic_bitmap
*ret
)
96 ext2fs_generic_bitmap bitmap
;
97 struct ext2_bitmap_ops
*ops
;
102 type
= EXT2FS_BMAP64_BITARRAY
;
105 case EXT2FS_BMAP64_BITARRAY
:
106 ops
= &ext2fs_blkmap64_bitarray
;
108 case EXT2FS_BMAP64_RBTREE
:
109 ops
= &ext2fs_blkmap64_rbtree
;
111 case EXT2FS_BMAP64_AUTODIR
:
112 retval
= ext2fs_get_num_dirs(fs
, &num_dirs
);
113 if (retval
|| num_dirs
> (fs
->super
->s_inodes_count
/ 320))
114 ops
= &ext2fs_blkmap64_bitarray
;
116 ops
= &ext2fs_blkmap64_rbtree
;
122 retval
= ext2fs_get_memzero(sizeof(struct ext2fs_struct_generic_bitmap
),
127 #ifdef ENABLE_BMAP_STATS
128 if (gettimeofday(&bitmap
->stats
.created
,
129 (struct timezone
*) NULL
) == -1) {
130 perror("gettimeofday");
131 ext2fs_free_mem(&bitmap
);
134 bitmap
->stats
.type
= type
;
137 /* XXX factor out, repeated in copy_bmap */
138 bitmap
->magic
= magic
;
140 bitmap
->start
= start
;
142 bitmap
->real_end
= real_end
;
143 bitmap
->bitmap_ops
= ops
;
144 bitmap
->cluster_bits
= 0;
146 case EXT2_ET_MAGIC_INODE_BITMAP64
:
147 bitmap
->base_error_code
= EXT2_ET_BAD_INODE_MARK
;
149 case EXT2_ET_MAGIC_BLOCK_BITMAP64
:
150 bitmap
->base_error_code
= EXT2_ET_BAD_BLOCK_MARK
;
151 bitmap
->cluster_bits
= fs
->cluster_ratio_bits
;
154 bitmap
->base_error_code
= EXT2_ET_BAD_GENERIC_MARK
;
157 retval
= ext2fs_get_mem(strlen(descr
)+1, &bitmap
->description
);
159 ext2fs_free_mem(&bitmap
);
162 strcpy(bitmap
->description
, descr
);
164 bitmap
->description
= 0;
166 retval
= bitmap
->bitmap_ops
->new_bmap(fs
, bitmap
);
168 ext2fs_free_mem(&bitmap
->description
);
169 ext2fs_free_mem(&bitmap
);
177 #ifdef ENABLE_BMAP_STATS
178 static void ext2fs_print_bmap_statistics(ext2fs_generic_bitmap bitmap
)
180 struct ext2_bmap_statistics
*stats
= &bitmap
->stats
;
181 #ifdef ENABLE_BMAP_STATS_OPS
182 float mark_seq_perc
= 0.0, test_seq_perc
= 0.0;
183 float mark_back_perc
= 0.0, test_back_perc
= 0.0;
188 #ifdef ENABLE_BMAP_STATS_OPS
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;
204 if (gettimeofday(&now
, (struct timezone
*) NULL
) == -1) {
205 perror("gettimeofday");
209 inuse
= (double) now
.tv_sec
+ \
210 (((double) now
.tv_usec
) * 0.000001);
211 inuse
-= (double) stats
->created
.tv_sec
+ \
212 (((double) stats
->created
.tv_usec
) * 0.000001);
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 bmap
)
249 if (EXT2FS_IS_32_BITMAP(bmap
)) {
250 ext2fs_free_generic_bitmap(bmap
);
254 if (!EXT2FS_IS_64_BITMAP(bmap
))
257 #ifdef ENABLE_BMAP_STATS
258 if (getenv("E2FSPROGS_BITMAP_STATS")) {
259 ext2fs_print_bmap_statistics(bmap
);
260 bmap
->bitmap_ops
->print_stats(bmap
);
264 bmap
->bitmap_ops
->free_bmap(bmap
);
266 if (bmap
->description
) {
267 ext2fs_free_mem(&bmap
->description
);
268 bmap
->description
= 0;
271 ext2fs_free_mem(&bmap
);
274 errcode_t
ext2fs_copy_generic_bmap(ext2fs_generic_bitmap src
,
275 ext2fs_generic_bitmap
*dest
)
277 char *descr
, *new_descr
;
278 ext2fs_generic_bitmap new_bmap
;
284 if (EXT2FS_IS_32_BITMAP(src
))
285 return ext2fs_copy_generic_bitmap(src
, dest
);
287 if (!EXT2FS_IS_64_BITMAP(src
))
290 /* Allocate a new bitmap struct */
291 retval
= ext2fs_get_memzero(sizeof(struct ext2fs_struct_generic_bitmap
),
297 #ifdef ENABLE_BMAP_STATS_OPS
298 src
->stats
.copy_count
++;
300 #ifdef ENABLE_BMAP_STATS
301 if (gettimeofday(&new_bmap
->stats
.created
,
302 (struct timezone
*) NULL
) == -1) {
303 perror("gettimeofday");
304 ext2fs_free_mem(&new_bmap
);
307 new_bmap
->stats
.type
= src
->stats
.type
;
310 /* Copy all the high-level parts over */
311 new_bmap
->magic
= src
->magic
;
312 new_bmap
->fs
= src
->fs
;
313 new_bmap
->start
= src
->start
;
314 new_bmap
->end
= src
->end
;
315 new_bmap
->real_end
= src
->real_end
;
316 new_bmap
->bitmap_ops
= src
->bitmap_ops
;
317 new_bmap
->base_error_code
= src
->base_error_code
;
318 new_bmap
->cluster_bits
= src
->cluster_bits
;
320 descr
= src
->description
;
322 retval
= ext2fs_get_mem(strlen(descr
)+10, &new_descr
);
324 ext2fs_free_mem(&new_bmap
);
327 strcpy(new_descr
, "copy of ");
328 strcat(new_descr
, descr
);
329 new_bmap
->description
= new_descr
;
332 retval
= src
->bitmap_ops
->copy_bmap(src
, new_bmap
);
334 ext2fs_free_mem(&new_bmap
->description
);
335 ext2fs_free_mem(&new_bmap
);
344 errcode_t
ext2fs_resize_generic_bmap(ext2fs_generic_bitmap bmap
,
351 if (EXT2FS_IS_32_BITMAP(bmap
))
352 return ext2fs_resize_generic_bitmap(bmap
->magic
, new_end
,
355 if (!EXT2FS_IS_64_BITMAP(bmap
))
358 INC_STAT(bmap
, resize_count
);
360 return bmap
->bitmap_ops
->resize_bmap(bmap
, new_end
, new_real_end
);
363 errcode_t
ext2fs_fudge_generic_bmap_end(ext2fs_generic_bitmap bitmap
,
365 __u64 end
, __u64
*oend
)
370 if (EXT2FS_IS_32_BITMAP(bitmap
)) {
374 retval
= ext2fs_fudge_generic_bitmap_end(bitmap
, bitmap
->magic
,
375 neq
, end
, &tmp_oend
);
381 if (!EXT2FS_IS_64_BITMAP(bitmap
))
384 if (end
> bitmap
->real_end
)
392 __u64
ext2fs_get_generic_bmap_start(ext2fs_generic_bitmap bitmap
)
397 if (EXT2FS_IS_32_BITMAP(bitmap
))
398 return ext2fs_get_generic_bitmap_start(bitmap
);
400 if (!EXT2FS_IS_64_BITMAP(bitmap
))
403 return bitmap
->start
;
406 __u64
ext2fs_get_generic_bmap_end(ext2fs_generic_bitmap bitmap
)
411 if (EXT2FS_IS_32_BITMAP(bitmap
))
412 return ext2fs_get_generic_bitmap_end(bitmap
);
414 if (!EXT2FS_IS_64_BITMAP(bitmap
))
420 void ext2fs_clear_generic_bmap(ext2fs_generic_bitmap bitmap
)
422 if (EXT2FS_IS_32_BITMAP(bitmap
))
423 ext2fs_clear_generic_bitmap(bitmap
);
425 bitmap
->bitmap_ops
->clear_bmap (bitmap
);
428 int ext2fs_mark_generic_bmap(ext2fs_generic_bitmap bitmap
,
434 if (EXT2FS_IS_32_BITMAP(bitmap
)) {
435 if (arg
& ~0xffffffffULL
) {
436 ext2fs_warn_bitmap2(bitmap
,
437 EXT2FS_MARK_ERROR
, 0xffffffff);
440 return ext2fs_mark_generic_bitmap(bitmap
, arg
);
443 if (!EXT2FS_IS_64_BITMAP(bitmap
))
446 arg
>>= bitmap
->cluster_bits
;
448 #ifdef ENABLE_BMAP_STATS_OPS
449 if (arg
== bitmap
->stats
.last_marked
+ 1)
450 bitmap
->stats
.mark_seq
++;
451 if (arg
< bitmap
->stats
.last_marked
)
452 bitmap
->stats
.mark_back
++;
453 bitmap
->stats
.last_marked
= arg
;
454 bitmap
->stats
.mark_count
++;
457 if ((arg
< bitmap
->start
) || (arg
> bitmap
->end
)) {
458 warn_bitmap(bitmap
, EXT2FS_MARK_ERROR
, arg
);
462 return bitmap
->bitmap_ops
->mark_bmap(bitmap
, arg
);
465 int ext2fs_unmark_generic_bmap(ext2fs_generic_bitmap bitmap
,
471 if (EXT2FS_IS_32_BITMAP(bitmap
)) {
472 if (arg
& ~0xffffffffULL
) {
473 ext2fs_warn_bitmap2(bitmap
, EXT2FS_UNMARK_ERROR
,
477 return ext2fs_unmark_generic_bitmap(bitmap
, arg
);
480 if (!EXT2FS_IS_64_BITMAP(bitmap
))
483 arg
>>= bitmap
->cluster_bits
;
485 INC_STAT(bitmap
, unmark_count
);
487 if ((arg
< bitmap
->start
) || (arg
> bitmap
->end
)) {
488 warn_bitmap(bitmap
, EXT2FS_UNMARK_ERROR
, arg
);
492 return bitmap
->bitmap_ops
->unmark_bmap(bitmap
, arg
);
495 int ext2fs_test_generic_bmap(ext2fs_generic_bitmap bitmap
,
501 if (EXT2FS_IS_32_BITMAP(bitmap
)) {
502 if (arg
& ~0xffffffffULL
) {
503 ext2fs_warn_bitmap2(bitmap
, EXT2FS_TEST_ERROR
,
507 return ext2fs_test_generic_bitmap(bitmap
, arg
);
510 if (!EXT2FS_IS_64_BITMAP(bitmap
))
513 arg
>>= bitmap
->cluster_bits
;
515 #ifdef ENABLE_BMAP_STATS_OPS
516 bitmap
->stats
.test_count
++;
517 if (arg
== bitmap
->stats
.last_tested
+ 1)
518 bitmap
->stats
.test_seq
++;
519 if (arg
< bitmap
->stats
.last_tested
)
520 bitmap
->stats
.test_back
++;
521 bitmap
->stats
.last_tested
= arg
;
524 if ((arg
< bitmap
->start
) || (arg
> bitmap
->end
)) {
525 warn_bitmap(bitmap
, EXT2FS_TEST_ERROR
, arg
);
529 return bitmap
->bitmap_ops
->test_bmap(bitmap
, arg
);
532 errcode_t
ext2fs_set_generic_bmap_range(ext2fs_generic_bitmap bmap
,
533 __u64 start
, unsigned int num
,
539 if (EXT2FS_IS_32_BITMAP(bmap
)) {
540 if ((start
+num
-1) & ~0xffffffffULL
) {
541 ext2fs_warn_bitmap2(bmap
, EXT2FS_UNMARK_ERROR
,
545 return ext2fs_set_generic_bitmap_range(bmap
, bmap
->magic
,
549 if (!EXT2FS_IS_64_BITMAP(bmap
))
552 INC_STAT(bmap
, set_range_count
);
554 return bmap
->bitmap_ops
->set_bmap_range(bmap
, start
, num
, in
);
557 errcode_t
ext2fs_get_generic_bmap_range(ext2fs_generic_bitmap bmap
,
558 __u64 start
, unsigned int num
,
564 if (EXT2FS_IS_32_BITMAP(bmap
)) {
565 if ((start
+num
-1) & ~0xffffffffULL
) {
566 ext2fs_warn_bitmap2(bmap
,
567 EXT2FS_UNMARK_ERROR
, 0xffffffff);
570 return ext2fs_get_generic_bitmap_range(bmap
, bmap
->magic
,
574 if (!EXT2FS_IS_64_BITMAP(bmap
))
577 INC_STAT(bmap
, get_range_count
);
579 return bmap
->bitmap_ops
->get_bmap_range(bmap
, start
, num
, out
);
582 errcode_t
ext2fs_compare_generic_bmap(errcode_t neq
,
583 ext2fs_generic_bitmap bm1
,
584 ext2fs_generic_bitmap bm2
)
590 if (bm1
->magic
!= bm2
->magic
)
593 /* Now we know both bitmaps have the same magic */
594 if (EXT2FS_IS_32_BITMAP(bm1
))
595 return ext2fs_compare_generic_bitmap(bm1
->magic
, neq
, bm1
, bm2
);
597 if (!EXT2FS_IS_64_BITMAP(bm1
))
600 if ((bm1
->start
!= bm2
->start
) ||
601 (bm1
->end
!= bm2
->end
))
604 for (i
= bm1
->end
- ((bm1
->end
- bm1
->start
) % 8); i
<= bm1
->end
; i
++)
605 if (ext2fs_test_generic_bmap(bm1
, i
) !=
606 ext2fs_test_generic_bmap(bm2
, i
))
612 void ext2fs_set_generic_bmap_padding(ext2fs_generic_bitmap bmap
)
616 if (EXT2FS_IS_32_BITMAP(bmap
)) {
617 ext2fs_set_generic_bitmap_padding(bmap
);
621 start
= bmap
->end
+ 1;
622 num
= bmap
->real_end
- bmap
->end
;
623 bmap
->bitmap_ops
->mark_bmap_extent(bmap
, start
, num
);
624 /* XXX ought to warn on error */
627 int ext2fs_test_block_bitmap_range2(ext2fs_block_bitmap bmap
,
628 blk64_t block
, unsigned int num
)
630 __u64 end
= block
+ num
;
636 return !ext2fs_test_generic_bmap((ext2fs_generic_bitmap
)
639 if (EXT2FS_IS_32_BITMAP(bmap
)) {
640 if ((block
+num
-1) & ~0xffffffffULL
) {
641 ext2fs_warn_bitmap2((ext2fs_generic_bitmap
) bmap
,
642 EXT2FS_UNMARK_ERROR
, 0xffffffff);
645 return ext2fs_test_block_bitmap_range(
646 (ext2fs_generic_bitmap
) bmap
, block
, num
);
649 if (!EXT2FS_IS_64_BITMAP(bmap
))
652 INC_STAT(bmap
, test_ext_count
);
654 /* convert to clusters if necessary */
655 block
>>= bmap
->cluster_bits
;
656 end
+= (1 << bmap
->cluster_bits
) - 1;
657 end
>>= bmap
->cluster_bits
;
660 if ((block
< bmap
->start
) || (block
+num
-1 > bmap
->end
)) {
661 ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_TEST
, block
,
666 return bmap
->bitmap_ops
->test_clear_bmap_extent(bmap
, block
, num
);
669 void ext2fs_mark_block_bitmap_range2(ext2fs_block_bitmap bmap
,
670 blk64_t block
, unsigned int num
)
672 __u64 end
= block
+ num
;
677 if (EXT2FS_IS_32_BITMAP(bmap
)) {
678 if ((block
+num
-1) & ~0xffffffffULL
) {
679 ext2fs_warn_bitmap2((ext2fs_generic_bitmap
) bmap
,
680 EXT2FS_UNMARK_ERROR
, 0xffffffff);
683 ext2fs_mark_block_bitmap_range((ext2fs_generic_bitmap
) bmap
,
687 if (!EXT2FS_IS_64_BITMAP(bmap
))
690 INC_STAT(bmap
, mark_ext_count
);
692 /* convert to clusters if necessary */
693 block
>>= bmap
->cluster_bits
;
694 end
+= (1 << bmap
->cluster_bits
) - 1;
695 end
>>= bmap
->cluster_bits
;
698 if ((block
< bmap
->start
) || (block
+num
-1 > bmap
->end
)) {
699 ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_MARK
, block
,
704 bmap
->bitmap_ops
->mark_bmap_extent(bmap
, block
, num
);
707 void ext2fs_unmark_block_bitmap_range2(ext2fs_block_bitmap bmap
,
708 blk64_t block
, unsigned int num
)
710 __u64 end
= block
+ num
;
715 if (EXT2FS_IS_32_BITMAP(bmap
)) {
716 if ((block
+num
-1) & ~0xffffffffULL
) {
717 ext2fs_warn_bitmap2((ext2fs_generic_bitmap
) bmap
,
718 EXT2FS_UNMARK_ERROR
, 0xffffffff);
721 ext2fs_unmark_block_bitmap_range((ext2fs_generic_bitmap
) bmap
,
725 if (!EXT2FS_IS_64_BITMAP(bmap
))
728 INC_STAT(bmap
, unmark_ext_count
);
730 /* convert to clusters if necessary */
731 block
>>= bmap
->cluster_bits
;
732 end
+= (1 << bmap
->cluster_bits
) - 1;
733 end
>>= bmap
->cluster_bits
;
736 if ((block
< bmap
->start
) || (block
+num
-1 > bmap
->end
)) {
737 ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_UNMARK
, block
,
742 bmap
->bitmap_ops
->unmark_bmap_extent(bmap
, block
, num
);
745 void ext2fs_warn_bitmap32(ext2fs_generic_bitmap bitmap
, const char *func
)
748 if (bitmap
&& bitmap
->description
)
749 com_err(0, EXT2_ET_MAGIC_GENERIC_BITMAP
,
750 "called %s with 64-bit bitmap for %s", func
,
751 bitmap
->description
);
753 com_err(0, EXT2_ET_MAGIC_GENERIC_BITMAP
,
754 "called %s with 64-bit bitmap", func
);
758 errcode_t
ext2fs_convert_subcluster_bitmap(ext2_filsys fs
,
759 ext2fs_block_bitmap
*bitmap
)
761 ext2fs_block_bitmap cmap
, bmap
;
763 blk64_t i
, b_end
, c_end
;
768 if (fs
->cluster_ratio_bits
== ext2fs_get_bitmap_granularity(bmap
))
769 return 0; /* Nothing to do */
771 retval
= ext2fs_allocate_block_bitmap(fs
, "converted cluster bitmap",
778 bmap
->end
= bmap
->real_end
;
780 cmap
->end
= cmap
->real_end
;
782 ratio
= 1 << fs
->cluster_ratio_bits
;
783 while (i
< bmap
->real_end
) {
784 if (ext2fs_test_block_bitmap2(bmap
, i
)) {
785 ext2fs_mark_block_bitmap2(cmap
, i
);
796 ext2fs_free_block_bitmap(bmap
);
801 errcode_t
ext2fs_find_first_zero_generic_bmap(ext2fs_generic_bitmap bitmap
,
802 __u64 start
, __u64 end
, __u64
*out
)
809 if (EXT2FS_IS_64_BITMAP(bitmap
) && bitmap
->bitmap_ops
->find_first_zero
)
810 return bitmap
->bitmap_ops
->find_first_zero(bitmap
, start
,
813 if (EXT2FS_IS_32_BITMAP(bitmap
)) {
817 if (((start
) & ~0xffffffffULL
) ||
818 ((end
) & ~0xffffffffULL
)) {
819 ext2fs_warn_bitmap2(bitmap
, EXT2FS_TEST_ERROR
, start
);
823 retval
= ext2fs_find_first_zero_generic_bitmap(bitmap
, start
,
830 if (!EXT2FS_IS_64_BITMAP(bitmap
))
833 start
>>= bitmap
->cluster_bits
;
834 end
>>= bitmap
->cluster_bits
;
836 if (start
< bitmap
->start
|| end
> bitmap
->end
|| start
> end
) {
837 warn_bitmap(bitmap
, EXT2FS_TEST_ERROR
, start
);
841 while (start
<= end
) {
842 b
= bitmap
->bitmap_ops
->test_bmap(bitmap
, start
);
844 *out
= start
<< bitmap
->cluster_bits
;