Whamcloud - gitweb
libext2fs: don't use O_DIRECT for files on tmpfs
[tools/e2fsprogs.git] / lib / ext2fs / gen_bitmap64.c
index d02488c..6e4d8b7 100644 (file)
@@ -68,7 +68,7 @@
  * e2fsck can request an encoding which is optimized for that.
  */
 
-static void warn_bitmap(ext2fs_generic_bitmap bitmap,
+static void warn_bitmap(ext2fs_generic_bitmap_64 bitmap,
                        int code, __u64 arg)
 {
 #ifndef OMIT_COM_ERR
@@ -80,7 +80,7 @@ static void warn_bitmap(ext2fs_generic_bitmap bitmap,
 #endif
 }
 
-#ifdef BMAP_STATS_OPS
+#ifdef ENABLE_BMAP_STATS_OPS
 #define INC_STAT(map, name) map->stats.name
 #else
 #define INC_STAT(map, name) ;;
@@ -93,7 +93,7 @@ errcode_t ext2fs_alloc_generic_bmap(ext2_filsys fs, errcode_t magic,
                                    const char *descr,
                                    ext2fs_generic_bitmap *ret)
 {
-       ext2fs_generic_bitmap   bitmap;
+       ext2fs_generic_bitmap_64 bitmap;
        struct ext2_bitmap_ops  *ops;
        ext2_ino_t num_dirs;
        errcode_t retval;
@@ -119,15 +119,16 @@ errcode_t ext2fs_alloc_generic_bmap(ext2_filsys fs, errcode_t magic,
                return EINVAL;
        }
 
-       retval = ext2fs_get_memzero(sizeof(struct ext2fs_struct_generic_bitmap),
+       retval = ext2fs_get_memzero(sizeof(struct ext2fs_struct_generic_bitmap_64),
                                    &bitmap);
        if (retval)
                return retval;
 
-#ifdef BMAP_STATS
+#ifdef ENABLE_BMAP_STATS
        if (gettimeofday(&bitmap->stats.created,
                         (struct timezone *) NULL) == -1) {
                perror("gettimeofday");
+               ext2fs_free_mem(&bitmap);
                return 1;
        }
        bitmap->stats.type = type;
@@ -169,22 +170,22 @@ errcode_t ext2fs_alloc_generic_bmap(ext2_filsys fs, errcode_t magic,
                return retval;
        }
 
-       *ret = bitmap;
+       *ret = (ext2fs_generic_bitmap) bitmap;
        return 0;
 }
 
-#ifdef BMAP_STATS
-static void ext2fs_print_bmap_statistics(ext2fs_generic_bitmap bitmap)
+#ifdef ENABLE_BMAP_STATS
+static void ext2fs_print_bmap_statistics(ext2fs_generic_bitmap_64 bitmap)
 {
        struct ext2_bmap_statistics *stats = &bitmap->stats;
-#ifdef BMAP_STATS_OPS
+#ifdef ENABLE_BMAP_STATS_OPS
        float mark_seq_perc = 0.0, test_seq_perc = 0.0;
        float mark_back_perc = 0.0, test_back_perc = 0.0;
 #endif
        double inuse;
        struct timeval now;
 
-#ifdef BMAP_STATS_OPS
+#ifdef ENABLE_BMAP_STATS_OPS
        if (stats->test_count) {
                test_seq_perc = ((float)stats->test_seq /
                                 stats->test_count) * 100;
@@ -213,7 +214,7 @@ static void ext2fs_print_bmap_statistics(ext2fs_generic_bitmap bitmap)
        fprintf(stderr, "\n[+] %s bitmap (type %d)\n", bitmap->description,
                stats->type);
        fprintf(stderr, "=================================================\n");
-#ifdef BMAP_STATS_OPS
+#ifdef ENABLE_BMAP_STATS_OPS
        fprintf(stderr, "%16llu bits long\n",
                bitmap->real_end - bitmap->start);
        fprintf(stderr, "%16lu copy_bmap\n%16lu resize_bmap\n",
@@ -236,24 +237,26 @@ static void ext2fs_print_bmap_statistics(ext2fs_generic_bitmap bitmap)
        fprintf(stderr, "%16llu bits marked backwards (%.2f%%)\n"
                "%16.2f seconds in use\n",
                stats->mark_back, mark_back_perc, inuse);
-#endif /* BMAP_STATS_OPS */
+#endif /* ENABLE_BMAP_STATS_OPS */
 }
 #endif
 
-void ext2fs_free_generic_bmap(ext2fs_generic_bitmap bmap)
+void ext2fs_free_generic_bmap(ext2fs_generic_bitmap gen_bmap)
 {
+       ext2fs_generic_bitmap_64 bmap = (ext2fs_generic_bitmap_64) gen_bmap;
+
        if (!bmap)
                return;
 
        if (EXT2FS_IS_32_BITMAP(bmap)) {
-               ext2fs_free_generic_bitmap(bmap);
+               ext2fs_free_generic_bitmap(gen_bmap);
                return;
        }
 
        if (!EXT2FS_IS_64_BITMAP(bmap))
                return;
 
-#ifdef BMAP_STATS
+#ifdef ENABLE_BMAP_STATS
        if (getenv("E2FSPROGS_BITMAP_STATS")) {
                ext2fs_print_bmap_statistics(bmap);
                bmap->bitmap_ops->print_stats(bmap);
@@ -270,36 +273,38 @@ void ext2fs_free_generic_bmap(ext2fs_generic_bitmap bmap)
        ext2fs_free_mem(&bmap);
 }
 
-errcode_t ext2fs_copy_generic_bmap(ext2fs_generic_bitmap src,
+errcode_t ext2fs_copy_generic_bmap(ext2fs_generic_bitmap gen_src,
                                   ext2fs_generic_bitmap *dest)
 {
+       ext2fs_generic_bitmap_64 src = (ext2fs_generic_bitmap_64) gen_src;
        char *descr, *new_descr;
-       ext2fs_generic_bitmap   new_bmap;
+       ext2fs_generic_bitmap_64 new_bmap;
        errcode_t retval;
 
        if (!src)
                return EINVAL;
 
        if (EXT2FS_IS_32_BITMAP(src))
-               return ext2fs_copy_generic_bitmap(src, dest);
+               return ext2fs_copy_generic_bitmap(gen_src, dest);
 
        if (!EXT2FS_IS_64_BITMAP(src))
                return EINVAL;
 
        /* Allocate a new bitmap struct */
-       retval = ext2fs_get_memzero(sizeof(struct ext2fs_struct_generic_bitmap),
+       retval = ext2fs_get_memzero(sizeof(struct ext2fs_struct_generic_bitmap_64),
                                    &new_bmap);
        if (retval)
                return retval;
 
 
-#ifdef BMAP_STATS_OPS
+#ifdef ENABLE_BMAP_STATS_OPS
        src->stats.copy_count++;
 #endif
-#ifdef BMAP_STATS
+#ifdef ENABLE_BMAP_STATS
        if (gettimeofday(&new_bmap->stats.created,
                         (struct timezone *) NULL) == -1) {
                perror("gettimeofday");
+               ext2fs_free_mem(&new_bmap);
                return 1;
        }
        new_bmap->stats.type = src->stats.type;
@@ -322,7 +327,8 @@ errcode_t ext2fs_copy_generic_bmap(ext2fs_generic_bitmap src,
                        ext2fs_free_mem(&new_bmap);
                        return retval;
                }
-               sprintf(new_descr, "copy of %s", descr);
+               strcpy(new_descr, "copy of ");
+               strcat(new_descr, descr);
                new_bmap->description = new_descr;
        }
 
@@ -333,21 +339,23 @@ errcode_t ext2fs_copy_generic_bmap(ext2fs_generic_bitmap src,
                return retval;
        }
 
-       *dest = new_bmap;
+       *dest = (ext2fs_generic_bitmap) new_bmap;
 
        return 0;
 }
 
-errcode_t ext2fs_resize_generic_bmap(ext2fs_generic_bitmap bmap,
+errcode_t ext2fs_resize_generic_bmap(ext2fs_generic_bitmap gen_bmap,
                                     __u64 new_end,
                                     __u64 new_real_end)
 {
+       ext2fs_generic_bitmap_64 bmap = (ext2fs_generic_bitmap_64) gen_bmap;
+
        if (!bmap)
                return EINVAL;
 
        if (EXT2FS_IS_32_BITMAP(bmap))
-               return ext2fs_resize_generic_bitmap(bmap->magic, new_end,
-                                                   new_real_end, bmap);
+               return ext2fs_resize_generic_bitmap(gen_bmap->magic, new_end,
+                                                   new_real_end, gen_bmap);
 
        if (!EXT2FS_IS_64_BITMAP(bmap))
                return EINVAL;
@@ -357,10 +365,12 @@ errcode_t ext2fs_resize_generic_bmap(ext2fs_generic_bitmap bmap,
        return bmap->bitmap_ops->resize_bmap(bmap, new_end, new_real_end);
 }
 
-errcode_t ext2fs_fudge_generic_bmap_end(ext2fs_generic_bitmap bitmap,
+errcode_t ext2fs_fudge_generic_bmap_end(ext2fs_generic_bitmap gen_bitmap,
                                        errcode_t neq,
                                        __u64 end, __u64 *oend)
 {
+       ext2fs_generic_bitmap_64 bitmap = (ext2fs_generic_bitmap_64) gen_bitmap;
+
        if (!bitmap)
                return EINVAL;
 
@@ -368,7 +378,8 @@ errcode_t ext2fs_fudge_generic_bmap_end(ext2fs_generic_bitmap bitmap,
                ext2_ino_t tmp_oend;
                int retval;
 
-               retval = ext2fs_fudge_generic_bitmap_end(bitmap, bitmap->magic,
+               retval = ext2fs_fudge_generic_bitmap_end(gen_bitmap,
+                                                        bitmap->magic,
                                                         neq, end, &tmp_oend);
                if (oend)
                        *oend = tmp_oend;
@@ -386,13 +397,15 @@ errcode_t ext2fs_fudge_generic_bmap_end(ext2fs_generic_bitmap bitmap,
        return 0;
 }
 
-__u64 ext2fs_get_generic_bmap_start(ext2fs_generic_bitmap bitmap)
+__u64 ext2fs_get_generic_bmap_start(ext2fs_generic_bitmap gen_bitmap)
 {
+       ext2fs_generic_bitmap_64 bitmap = (ext2fs_generic_bitmap_64) gen_bitmap;
+
        if (!bitmap)
                return EINVAL;
 
        if (EXT2FS_IS_32_BITMAP(bitmap))
-               return ext2fs_get_generic_bitmap_start(bitmap);
+               return ext2fs_get_generic_bitmap_start(gen_bitmap);
 
        if (!EXT2FS_IS_64_BITMAP(bitmap))
                return EINVAL;
@@ -400,13 +413,15 @@ __u64 ext2fs_get_generic_bmap_start(ext2fs_generic_bitmap bitmap)
        return bitmap->start;
 }
 
-__u64 ext2fs_get_generic_bmap_end(ext2fs_generic_bitmap bitmap)
+__u64 ext2fs_get_generic_bmap_end(ext2fs_generic_bitmap gen_bitmap)
 {
+       ext2fs_generic_bitmap_64 bitmap = (ext2fs_generic_bitmap_64) gen_bitmap;
+
        if (!bitmap)
                return EINVAL;
 
        if (EXT2FS_IS_32_BITMAP(bitmap))
-               return ext2fs_get_generic_bitmap_end(bitmap);
+               return ext2fs_get_generic_bitmap_end(gen_bitmap);
 
        if (!EXT2FS_IS_64_BITMAP(bitmap))
                return EINVAL;
@@ -414,27 +429,31 @@ __u64 ext2fs_get_generic_bmap_end(ext2fs_generic_bitmap bitmap)
        return bitmap->end;
 }
 
-void ext2fs_clear_generic_bmap(ext2fs_generic_bitmap bitmap)
+void ext2fs_clear_generic_bmap(ext2fs_generic_bitmap gen_bitmap)
 {
+       ext2fs_generic_bitmap_64 bitmap = (ext2fs_generic_bitmap_64) gen_bitmap;
+
        if (EXT2FS_IS_32_BITMAP(bitmap))
-               ext2fs_clear_generic_bitmap(bitmap);
+               ext2fs_clear_generic_bitmap(gen_bitmap);
        else
-               bitmap->bitmap_ops->clear_bmap (bitmap);
+               bitmap->bitmap_ops->clear_bmap(bitmap);
 }
 
-int ext2fs_mark_generic_bmap(ext2fs_generic_bitmap bitmap,
+int ext2fs_mark_generic_bmap(ext2fs_generic_bitmap gen_bitmap,
                             __u64 arg)
 {
+       ext2fs_generic_bitmap_64 bitmap = (ext2fs_generic_bitmap_64) gen_bitmap;
+
        if (!bitmap)
                return 0;
 
        if (EXT2FS_IS_32_BITMAP(bitmap)) {
                if (arg & ~0xffffffffULL) {
-                       ext2fs_warn_bitmap2(bitmap,
+                       ext2fs_warn_bitmap2(gen_bitmap,
                                            EXT2FS_MARK_ERROR, 0xffffffff);
                        return 0;
                }
-               return ext2fs_mark_generic_bitmap(bitmap, arg);
+               return ext2fs_mark_generic_bitmap(gen_bitmap, arg);
        }
 
        if (!EXT2FS_IS_64_BITMAP(bitmap))
@@ -442,7 +461,7 @@ int ext2fs_mark_generic_bmap(ext2fs_generic_bitmap bitmap,
 
        arg >>= bitmap->cluster_bits;
 
-#ifdef BMAP_STATS_OPS
+#ifdef ENABLE_BMAP_STATS_OPS
        if (arg == bitmap->stats.last_marked + 1)
                bitmap->stats.mark_seq++;
        if (arg < bitmap->stats.last_marked)
@@ -459,19 +478,21 @@ int ext2fs_mark_generic_bmap(ext2fs_generic_bitmap bitmap,
        return bitmap->bitmap_ops->mark_bmap(bitmap, arg);
 }
 
-int ext2fs_unmark_generic_bmap(ext2fs_generic_bitmap bitmap,
+int ext2fs_unmark_generic_bmap(ext2fs_generic_bitmap gen_bitmap,
                               __u64 arg)
 {
+       ext2fs_generic_bitmap_64 bitmap = (ext2fs_generic_bitmap_64) gen_bitmap;
+
        if (!bitmap)
                return 0;
 
        if (EXT2FS_IS_32_BITMAP(bitmap)) {
                if (arg & ~0xffffffffULL) {
-                       ext2fs_warn_bitmap2(bitmap, EXT2FS_UNMARK_ERROR,
+                       ext2fs_warn_bitmap2(gen_bitmap, EXT2FS_UNMARK_ERROR,
                                            0xffffffff);
                        return 0;
                }
-               return ext2fs_unmark_generic_bitmap(bitmap, arg);
+               return ext2fs_unmark_generic_bitmap(gen_bitmap, arg);
        }
 
        if (!EXT2FS_IS_64_BITMAP(bitmap))
@@ -489,19 +510,20 @@ int ext2fs_unmark_generic_bmap(ext2fs_generic_bitmap bitmap,
        return bitmap->bitmap_ops->unmark_bmap(bitmap, arg);
 }
 
-int ext2fs_test_generic_bmap(ext2fs_generic_bitmap bitmap,
+int ext2fs_test_generic_bmap(ext2fs_generic_bitmap gen_bitmap,
                             __u64 arg)
 {
+       ext2fs_generic_bitmap_64 bitmap = (ext2fs_generic_bitmap_64) gen_bitmap;
        if (!bitmap)
                return 0;
 
        if (EXT2FS_IS_32_BITMAP(bitmap)) {
                if (arg & ~0xffffffffULL) {
-                       ext2fs_warn_bitmap2(bitmap, EXT2FS_TEST_ERROR,
+                       ext2fs_warn_bitmap2(gen_bitmap, EXT2FS_TEST_ERROR,
                                            0xffffffff);
                        return 0;
                }
-               return ext2fs_test_generic_bitmap(bitmap, arg);
+               return ext2fs_test_generic_bitmap(gen_bitmap, arg);
        }
 
        if (!EXT2FS_IS_64_BITMAP(bitmap))
@@ -509,7 +531,7 @@ int ext2fs_test_generic_bmap(ext2fs_generic_bitmap bitmap,
 
        arg >>= bitmap->cluster_bits;
 
-#ifdef BMAP_STATS_OPS
+#ifdef ENABLE_BMAP_STATS_OPS
        bitmap->stats.test_count++;
        if (arg == bitmap->stats.last_tested + 1)
                bitmap->stats.test_seq++;
@@ -526,20 +548,22 @@ int ext2fs_test_generic_bmap(ext2fs_generic_bitmap bitmap,
        return bitmap->bitmap_ops->test_bmap(bitmap, arg);
 }
 
-errcode_t ext2fs_set_generic_bmap_range(ext2fs_generic_bitmap bmap,
+errcode_t ext2fs_set_generic_bmap_range(ext2fs_generic_bitmap gen_bmap,
                                        __u64 start, unsigned int num,
                                        void *in)
 {
+       ext2fs_generic_bitmap_64 bmap = (ext2fs_generic_bitmap_64) gen_bmap;
+
        if (!bmap)
                return EINVAL;
 
        if (EXT2FS_IS_32_BITMAP(bmap)) {
                if ((start+num-1) & ~0xffffffffULL) {
-                       ext2fs_warn_bitmap2(bmap, EXT2FS_UNMARK_ERROR,
+                       ext2fs_warn_bitmap2(gen_bmap, EXT2FS_UNMARK_ERROR,
                                            0xffffffff);
                        return EINVAL;
                }
-               return ext2fs_set_generic_bitmap_range(bmap, bmap->magic,
+               return ext2fs_set_generic_bitmap_range(gen_bmap, bmap->magic,
                                                       start, num, in);
        }
 
@@ -551,20 +575,22 @@ errcode_t ext2fs_set_generic_bmap_range(ext2fs_generic_bitmap bmap,
        return bmap->bitmap_ops->set_bmap_range(bmap, start, num, in);
 }
 
-errcode_t ext2fs_get_generic_bmap_range(ext2fs_generic_bitmap bmap,
+errcode_t ext2fs_get_generic_bmap_range(ext2fs_generic_bitmap gen_bmap,
                                        __u64 start, unsigned int num,
                                        void *out)
 {
+       ext2fs_generic_bitmap_64 bmap = (ext2fs_generic_bitmap_64) gen_bmap;
+
        if (!bmap)
                return EINVAL;
 
        if (EXT2FS_IS_32_BITMAP(bmap)) {
                if ((start+num-1) & ~0xffffffffULL) {
-                       ext2fs_warn_bitmap2(bmap,
+                       ext2fs_warn_bitmap2(gen_bmap,
                                            EXT2FS_UNMARK_ERROR, 0xffffffff);
                        return EINVAL;
                }
-               return ext2fs_get_generic_bitmap_range(bmap, bmap->magic,
+               return ext2fs_get_generic_bitmap_range(gen_bmap, bmap->magic,
                                                       start, num, out);
        }
 
@@ -577,9 +603,11 @@ errcode_t ext2fs_get_generic_bmap_range(ext2fs_generic_bitmap bmap,
 }
 
 errcode_t ext2fs_compare_generic_bmap(errcode_t neq,
-                                     ext2fs_generic_bitmap bm1,
-                                     ext2fs_generic_bitmap bm2)
+                                     ext2fs_generic_bitmap gen_bm1,
+                                     ext2fs_generic_bitmap gen_bm2)
 {
+       ext2fs_generic_bitmap_64 bm1 = (ext2fs_generic_bitmap_64) gen_bm1;
+       ext2fs_generic_bitmap_64 bm2 = (ext2fs_generic_bitmap_64) gen_bm2;
        blk64_t i;
 
        if (!bm1 || !bm2)
@@ -589,7 +617,8 @@ errcode_t ext2fs_compare_generic_bmap(errcode_t neq,
 
        /* Now we know both bitmaps have the same magic */
        if (EXT2FS_IS_32_BITMAP(bm1))
-               return ext2fs_compare_generic_bitmap(bm1->magic, neq, bm1, bm2);
+               return ext2fs_compare_generic_bitmap(bm1->magic, neq,
+                                                    gen_bm1, gen_bm2);
 
        if (!EXT2FS_IS_64_BITMAP(bm1))
                return EINVAL;
@@ -599,19 +628,20 @@ errcode_t ext2fs_compare_generic_bmap(errcode_t neq,
                return neq;
 
        for (i = bm1->end - ((bm1->end - bm1->start) % 8); i <= bm1->end; i++)
-               if (ext2fs_test_generic_bmap(bm1, i) !=
-                   ext2fs_test_generic_bmap(bm2, i))
+               if (ext2fs_test_generic_bmap(gen_bm1, i) !=
+                   ext2fs_test_generic_bmap(gen_bm2, i))
                        return neq;
 
        return 0;
 }
 
-void ext2fs_set_generic_bmap_padding(ext2fs_generic_bitmap bmap)
+void ext2fs_set_generic_bmap_padding(ext2fs_generic_bitmap gen_bmap)
 {
+       ext2fs_generic_bitmap_64 bmap = (ext2fs_generic_bitmap_64) gen_bmap;
        __u64   start, num;
 
        if (EXT2FS_IS_32_BITMAP(bmap)) {
-               ext2fs_set_generic_bitmap_padding(bmap);
+               ext2fs_set_generic_bitmap_padding(gen_bmap);
                return;
        }
 
@@ -621,9 +651,10 @@ void ext2fs_set_generic_bmap_padding(ext2fs_generic_bitmap bmap)
        /* XXX ought to warn on error */
 }
 
-int ext2fs_test_block_bitmap_range2(ext2fs_block_bitmap bmap,
+int ext2fs_test_block_bitmap_range2(ext2fs_block_bitmap gen_bmap,
                                    blk64_t block, unsigned int num)
 {
+       ext2fs_generic_bitmap_64 bmap = (ext2fs_generic_bitmap_64) gen_bmap;
        __u64   end = block + num;
 
        if (!bmap)
@@ -634,7 +665,8 @@ int ext2fs_test_block_bitmap_range2(ext2fs_block_bitmap bmap,
                                                 bmap, block);
 
        if (EXT2FS_IS_32_BITMAP(bmap)) {
-               if ((block+num-1) & ~0xffffffffULL) {
+               if ((block & ~0xffffffffULL) ||
+                   ((block+num-1) & ~0xffffffffULL)) {
                        ext2fs_warn_bitmap2((ext2fs_generic_bitmap) bmap,
                                            EXT2FS_UNMARK_ERROR, 0xffffffff);
                        return EINVAL;
@@ -654,7 +686,8 @@ int ext2fs_test_block_bitmap_range2(ext2fs_block_bitmap bmap,
        end >>= bmap->cluster_bits;
        num = end - block;
 
-       if ((block < bmap->start) || (block+num-1 > bmap->end)) {
+       if ((block < bmap->start) || (block > bmap->end) ||
+           (block+num-1 > bmap->end)) {
                ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_TEST, block,
                                   bmap->description);
                return EINVAL;
@@ -663,16 +696,18 @@ int ext2fs_test_block_bitmap_range2(ext2fs_block_bitmap bmap,
        return bmap->bitmap_ops->test_clear_bmap_extent(bmap, block, num);
 }
 
-void ext2fs_mark_block_bitmap_range2(ext2fs_block_bitmap bmap,
+void ext2fs_mark_block_bitmap_range2(ext2fs_block_bitmap gen_bmap,
                                     blk64_t block, unsigned int num)
 {
+       ext2fs_generic_bitmap_64 bmap = (ext2fs_generic_bitmap_64) gen_bmap;
        __u64   end = block + num;
 
        if (!bmap)
                return;
 
        if (EXT2FS_IS_32_BITMAP(bmap)) {
-               if ((block+num-1) & ~0xffffffffULL) {
+               if ((block & ~0xffffffffULL) ||
+                   ((block+num-1) & ~0xffffffffULL)) {
                        ext2fs_warn_bitmap2((ext2fs_generic_bitmap) bmap,
                                            EXT2FS_UNMARK_ERROR, 0xffffffff);
                        return;
@@ -692,7 +727,8 @@ void ext2fs_mark_block_bitmap_range2(ext2fs_block_bitmap bmap,
        end >>= bmap->cluster_bits;
        num = end - block;
 
-       if ((block < bmap->start) || (block+num-1 > bmap->end)) {
+       if ((block < bmap->start) || (block > bmap->end) ||
+           (block+num-1 > bmap->end)) {
                ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_MARK, block,
                                   bmap->description);
                return;
@@ -701,16 +737,18 @@ void ext2fs_mark_block_bitmap_range2(ext2fs_block_bitmap bmap,
        bmap->bitmap_ops->mark_bmap_extent(bmap, block, num);
 }
 
-void ext2fs_unmark_block_bitmap_range2(ext2fs_block_bitmap bmap,
+void ext2fs_unmark_block_bitmap_range2(ext2fs_block_bitmap gen_bmap,
                                       blk64_t block, unsigned int num)
 {
+       ext2fs_generic_bitmap_64 bmap = (ext2fs_generic_bitmap_64) gen_bmap;
        __u64   end = block + num;
 
        if (!bmap)
                return;
 
        if (EXT2FS_IS_32_BITMAP(bmap)) {
-               if ((block+num-1) & ~0xffffffffULL) {
+               if ((block & ~0xffffffffULL) ||
+                   ((block+num-1) & ~0xffffffffULL)) {
                        ext2fs_warn_bitmap2((ext2fs_generic_bitmap) bmap,
                                            EXT2FS_UNMARK_ERROR, 0xffffffff);
                        return;
@@ -730,7 +768,8 @@ void ext2fs_unmark_block_bitmap_range2(ext2fs_block_bitmap bmap,
        end >>= bmap->cluster_bits;
        num = end - block;
 
-       if ((block < bmap->start) || (block+num-1 > bmap->end)) {
+       if ((block < bmap->start) || (block > bmap->end) ||
+           (block+num-1 > bmap->end)) {
                ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_UNMARK, block,
                                   bmap->description);
                return;
@@ -739,8 +778,10 @@ void ext2fs_unmark_block_bitmap_range2(ext2fs_block_bitmap bmap,
        bmap->bitmap_ops->unmark_bmap_extent(bmap, block, num);
 }
 
-void ext2fs_warn_bitmap32(ext2fs_generic_bitmap bitmap, const char *func)
+void ext2fs_warn_bitmap32(ext2fs_generic_bitmap gen_bitmap, const char *func)
 {
+       ext2fs_generic_bitmap_64 bitmap = (ext2fs_generic_bitmap_64) gen_bitmap;
+
 #ifndef OMIT_COM_ERR
        if (bitmap && bitmap->description)
                com_err(0, EXT2_ET_MAGIC_GENERIC_BITMAP,
@@ -755,21 +796,22 @@ void ext2fs_warn_bitmap32(ext2fs_generic_bitmap bitmap, const char *func)
 errcode_t ext2fs_convert_subcluster_bitmap(ext2_filsys fs,
                                           ext2fs_block_bitmap *bitmap)
 {
-       ext2fs_block_bitmap     cmap, bmap;
+       ext2fs_generic_bitmap_64 bmap, cmap;
+       ext2fs_block_bitmap     gen_bmap = *bitmap, gen_cmap;
        errcode_t               retval;
        blk64_t                 i, b_end, c_end;
        int                     n, ratio;
 
-       bmap = *bitmap;
-
-       if (fs->cluster_ratio_bits == ext2fs_get_bitmap_granularity(bmap))
+       bmap = (ext2fs_generic_bitmap_64) gen_bmap;
+       if (fs->cluster_ratio_bits == ext2fs_get_bitmap_granularity(gen_bmap))
                return 0;       /* Nothing to do */
 
        retval = ext2fs_allocate_block_bitmap(fs, "converted cluster bitmap",
-                                             &cmap);
+                                             &gen_cmap);
        if (retval)
                return retval;
 
+       cmap = (ext2fs_generic_bitmap_64) gen_cmap;
        i = bmap->start;
        b_end = bmap->end;
        bmap->end = bmap->real_end;
@@ -778,8 +820,8 @@ errcode_t ext2fs_convert_subcluster_bitmap(ext2_filsys fs,
        n = 0;
        ratio = 1 << fs->cluster_ratio_bits;
        while (i < bmap->real_end) {
-               if (ext2fs_test_block_bitmap2(bmap, i)) {
-                       ext2fs_mark_block_bitmap2(cmap, i);
+               if (ext2fs_test_block_bitmap2(gen_bmap, i)) {
+                       ext2fs_mark_block_bitmap2(gen_cmap, i);
                        i += ratio - n;
                        n = 0;
                        continue;
@@ -790,26 +832,23 @@ errcode_t ext2fs_convert_subcluster_bitmap(ext2_filsys fs,
        }
        bmap->end = b_end;
        cmap->end = c_end;
-       ext2fs_free_block_bitmap(bmap);
-       *bitmap = cmap;
+       ext2fs_free_block_bitmap(gen_bmap);
+       *bitmap = (ext2fs_block_bitmap) cmap;
        return 0;
 }
 
 errcode_t ext2fs_find_first_zero_generic_bmap(ext2fs_generic_bitmap bitmap,
                                              __u64 start, __u64 end, __u64 *out)
 {
-       int b;
+       ext2fs_generic_bitmap_64 bmap64 = (ext2fs_generic_bitmap_64) bitmap;
+       __u64 cstart, cend, cout;
+       errcode_t retval;
 
        if (!bitmap)
                return EINVAL;
 
-       if (EXT2FS_IS_64_BITMAP(bitmap) && bitmap->bitmap_ops->find_first_zero)
-               return bitmap->bitmap_ops->find_first_zero(bitmap, start,
-                                                          end, out);
-
        if (EXT2FS_IS_32_BITMAP(bitmap)) {
                blk_t blk = 0;
-               errcode_t retval;
 
                if (((start) & ~0xffffffffULL) ||
                    ((end) & ~0xffffffffULL)) {
@@ -827,22 +866,83 @@ errcode_t ext2fs_find_first_zero_generic_bmap(ext2fs_generic_bitmap bitmap,
        if (!EXT2FS_IS_64_BITMAP(bitmap))
                return EINVAL;
 
-       start >>= bitmap->cluster_bits;
-       end >>= bitmap->cluster_bits;
+       cstart = start >> bmap64->cluster_bits;
+       cend = end >> bmap64->cluster_bits;
 
-       if (start < bitmap->start || end > bitmap->end || start > end) {
-               warn_bitmap(bitmap, EXT2FS_TEST_ERROR, start);
+       if (cstart < bmap64->start || cend > bmap64->end || start > end) {
+               warn_bitmap(bmap64, EXT2FS_TEST_ERROR, start);
                return EINVAL;
        }
 
-       while (start <= end) {
-               b = bitmap->bitmap_ops->test_bmap(bitmap, start);
-               if (!b) {
-                       *out = start << bitmap->cluster_bits;
-                       return 0;
+       if (bmap64->bitmap_ops->find_first_zero) {
+               retval = bmap64->bitmap_ops->find_first_zero(bmap64, cstart,
+                                                            cend, &cout);
+               if (retval)
+                       return retval;
+       found:
+               cout <<= bmap64->cluster_bits;
+               *out = (cout >= start) ? cout : start;
+               return 0;
+       }
+
+       for (cout = cstart; cout <= cend; cout++)
+               if (!bmap64->bitmap_ops->test_bmap(bmap64, cout))
+                       goto found;
+
+       return ENOENT;
+}
+
+errcode_t ext2fs_find_first_set_generic_bmap(ext2fs_generic_bitmap bitmap,
+                                            __u64 start, __u64 end, __u64 *out)
+{
+       ext2fs_generic_bitmap_64 bmap64 = (ext2fs_generic_bitmap_64) bitmap;
+       __u64 cstart, cend, cout;
+       errcode_t retval;
+
+       if (!bitmap)
+               return EINVAL;
+
+       if (EXT2FS_IS_32_BITMAP(bitmap)) {
+               blk_t blk = 0;
+
+               if (((start) & ~0xffffffffULL) ||
+                   ((end) & ~0xffffffffULL)) {
+                       ext2fs_warn_bitmap2(bitmap, EXT2FS_TEST_ERROR, start);
+                       return EINVAL;
                }
-               start++;
+
+               retval = ext2fs_find_first_set_generic_bitmap(bitmap, start,
+                                                             end, &blk);
+               if (retval == 0)
+                       *out = blk;
+               return retval;
        }
 
+       if (!EXT2FS_IS_64_BITMAP(bitmap))
+               return EINVAL;
+
+       cstart = start >> bmap64->cluster_bits;
+       cend = end >> bmap64->cluster_bits;
+
+       if (cstart < bmap64->start || cend > bmap64->end || start > end) {
+               warn_bitmap(bmap64, EXT2FS_TEST_ERROR, start);
+               return EINVAL;
+       }
+
+       if (bmap64->bitmap_ops->find_first_set) {
+               retval = bmap64->bitmap_ops->find_first_set(bmap64, cstart,
+                                                           cend, &cout);
+               if (retval)
+                       return retval;
+       found:
+               cout <<= bmap64->cluster_bits;
+               *out = (cout >= start) ? cout : start;
+               return 0;
+       }
+
+       for (cout = cstart; cout <= cend; cout++)
+               if (bmap64->bitmap_ops->test_bmap(bmap64, cout))
+                       goto found;
+
        return ENOENT;
 }