diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h index 68e94a33..fda6adea 100644 --- a/lib/ext2fs/ext2fs.h +++ b/lib/ext2fs/ext2fs.h @@ -1169,6 +1169,9 @@ extern errcode_t ext2fs_set_generic_bitmap_range(ext2fs_generic_bitmap bmap, errcode_t magic, __u32 start, __u32 num, void *in); +extern errcode_t ext2fs_find_first_zero_generic_bitmap(ext2fs_generic_bitmap bitmap, + __u32 start, __u32 end, + __u32 *out); /* gen_bitmap64.c */ diff --git a/lib/ext2fs/gen_bitmap.c b/lib/ext2fs/gen_bitmap.c index 6679bffa..0bff8546 100644 --- a/lib/ext2fs/gen_bitmap.c +++ b/lib/ext2fs/gen_bitmap.c @@ -504,6 +504,30 @@ static int ext2fs_test_clear_generic_bitmap_range(ext2fs_generic_bitmap bitmap, return ext2fs_mem_is_zero(ADDR + start_byte, len_byte); } +errcode_t ext2fs_find_first_zero_generic_bitmap(ext2fs_generic_bitmap bitmap, + __u32 start, __u32 end, + __u32 *out) +{ + blk_t b; + + if (start < bitmap->start || end > bitmap->end || start > end) { + ext2fs_warn_bitmap2(bitmap, EXT2FS_TEST_ERROR, start); + return EINVAL; + } + + while (start <= end) { + b = ext2fs_test_bit(start - bitmap->start, bitmap->bitmap); + if (!b) { + *out = start; + return 0; + } + start++; + } + + return ENOENT; +} + + int ext2fs_test_block_bitmap_range(ext2fs_block_bitmap bitmap, blk_t block, int num) { @@ -558,3 +582,4 @@ void ext2fs_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap, ext2fs_fast_clear_bit(block + i - bitmap->start, bitmap->bitmap); } + diff --git a/lib/ext2fs/gen_bitmap64.c b/lib/ext2fs/gen_bitmap64.c index e765d2cf..07d6d522 100644 --- a/lib/ext2fs/gen_bitmap64.c +++ b/lib/ext2fs/gen_bitmap64.c @@ -770,12 +770,36 @@ errcode_t ext2fs_find_first_zero_generic_bmap(ext2fs_generic_bitmap bitmap, { int b; - if (bitmap->bitmap_ops->find_first_zero) - return bitmap->bitmap_ops->find_first_zero(bitmap, start, end, out); - - if (!bitmap || !EXT2FS_IS_64_BITMAP(bitmap) || bitmap->cluster_bits) + 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)) { + ext2fs_warn_bitmap2(bitmap, EXT2FS_TEST_ERROR, start); + return EINVAL; + } + + retval = ext2fs_find_first_zero_generic_bitmap(bitmap, start, + end, &blk); + if (retval == 0) + *out = blk; + return retval; + } + + if (!EXT2FS_IS_64_BITMAP(bitmap)) + return EINVAL; + + start >>= bitmap->cluster_bits; + end >>= bitmap->cluster_bits; + if (start < bitmap->start || end > bitmap->end || start > end) { warn_bitmap(bitmap, EXT2FS_TEST_ERROR, start); return EINVAL; @@ -784,7 +808,7 @@ errcode_t ext2fs_find_first_zero_generic_bmap(ext2fs_generic_bitmap bitmap, while (start <= end) { b = bitmap->bitmap_ops->test_bmap(bitmap, start); if (!b) { - *out = start; + *out = start << bitmap->cluster_bits; return 0; } start++;