From: Theodore Ts'o Date: Thu, 9 Jul 2009 18:32:52 +0000 (-0400) Subject: libext2fs: Add new function ext2fs_test_inode_bitmap_range() X-Git-Tag: v1.41.8~8 X-Git-Url: https://git.whamcloud.com/?a=commitdiff_plain;h=ef1a526dfbe663bb80ab75c2e7985ae8d9021b76;p=tools%2Fe2fsprogs.git libext2fs: Add new function ext2fs_test_inode_bitmap_range() Optimize ext2fs_test_block_bitmap_range() and add a new function, ext2fs_test_inode_bitmap_range(), which works the same way as ext2fs_block_bitmap_range() but for inode bitmaps. It's needed for some code in the development branch, so let's drop it into the maint branch to make life easier in the future. Signed-off-by: Kazuya Mio Signed-off-by: "Theodore Ts'o" --- diff --git a/debian/e2fslibs.symbols b/debian/e2fslibs.symbols index 3ee0bca..c203f02 100644 --- a/debian/e2fslibs.symbols +++ b/debian/e2fslibs.symbols @@ -330,6 +330,7 @@ libext2fs.so.2 e2fslibs #MINVER# ext2fs_test_bit@Base 1.37 ext2fs_test_block_bitmap@Base 1.37 ext2fs_test_block_bitmap_range@Base 1.37 + ext2fs_test_inode_bitmap_range@Base 1.41.8 ext2fs_test_changed@Base 1.37 ext2fs_test_generic_bitmap@Base 1.37 ext2fs_test_ib_dirty@Base 1.37 diff --git a/lib/ext2fs/bitops.h b/lib/ext2fs/bitops.h index 1d825bb..32111ba 100644 --- a/lib/ext2fs/bitops.h +++ b/lib/ext2fs/bitops.h @@ -96,6 +96,8 @@ extern void ext2fs_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap, blk_t block, int num); extern int ext2fs_test_block_bitmap_range(ext2fs_block_bitmap bitmap, blk_t block, int num); +extern int ext2fs_test_inode_bitmap_range(ext2fs_inode_bitmap bitmap, + ino_t inode, int num); extern void ext2fs_fast_mark_block_bitmap_range(ext2fs_block_bitmap bitmap, blk_t block, int num); extern void ext2fs_fast_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap, diff --git a/lib/ext2fs/gen_bitmap.c b/lib/ext2fs/gen_bitmap.c index a1b1d8f..19caf23 100644 --- a/lib/ext2fs/gen_bitmap.c +++ b/lib/ext2fs/gen_bitmap.c @@ -327,21 +327,129 @@ errcode_t ext2fs_set_generic_bitmap_range(ext2fs_generic_bitmap bmap, return 0; } +/* + * Compare @mem to zero buffer by 256 bytes. + * Return 1 if @mem is zeroed memory, otherwise return 0. + */ +static int mem_is_zero(const char *mem, size_t len) +{ + static const char zero_buf[256]; + + while (len >= sizeof(zero_buf)) { + if (memcmp(mem, zero_buf, sizeof(zero_buf))) + return 0; + len -= sizeof(zero_buf); + mem += sizeof(zero_buf); + } + /* Deal with leftover bytes. */ + if (len) + return !memcmp(mem, zero_buf, len); + return 1; +} + +/* + * Return true if all of the bits in a specified range are clear + */ +static int ext2fs_test_clear_generic_bitmap_range(ext2fs_generic_bitmap bitmap, + unsigned int start, + unsigned int len) +{ + size_t start_byte, len_byte = len >> 3; + int start_bit, len_bit = len % 8; + int first_bit = 0; + int last_bit = 0; + int mark_count = 0; + int mark_bit = 0; + int i; + const char *ADDR = bitmap->bitmap; + + start -= bitmap->start; + start_byte = start >> 3; + start_bit = start % 8; + + if (start_bit != 0) { + /* + * The compared start block number or start inode number + * is not the first bit in a byte. + */ + mark_count = 8 - start_bit; + if (len < 8 - start_bit) { + mark_count = (int)len; + mark_bit = len + start_bit - 1; + } else + mark_bit = 7; + + for (i = mark_count; i > 0; i--, mark_bit--) + first_bit |= 1 << mark_bit; + + /* + * Compare blocks or inodes in the first byte. + * If there is any marked bit, this function returns 0. + */ + if (first_bit & ADDR[start_byte]) + return 0; + else if (len <= 8 - start_bit) + return 1; + + start_byte++; + len_bit = (len - mark_count) % 8; + len_byte = (len - mark_count) >> 3; + } + + /* + * The compared start block number or start inode number is + * the first bit in a byte. + */ + if (len_bit != 0) { + /* + * The compared end block number or end inode number is + * not the last bit in a byte. + */ + for (mark_bit = len_bit - 1; mark_bit >= 0; mark_bit--) + last_bit |= 1 << mark_bit; + + /* + * Compare blocks or inodes in the last byte. + * If there is any marked bit, this function returns 0. + */ + if (last_bit & ADDR[start_byte + len_byte]) + return 0; + else if (len_byte == 0) + return 1; + } + + /* Check whether all bytes are 0 */ + return mem_is_zero(ADDR + start_byte, len_byte); +} + int ext2fs_test_block_bitmap_range(ext2fs_block_bitmap bitmap, blk_t block, int num) { int i; + EXT2_CHECK_MAGIC(bitmap, EXT2_ET_MAGIC_BLOCK_BITMAP); if ((block < bitmap->start) || (block+num-1 > bitmap->real_end)) { ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_TEST, block, bitmap->description); return 0; } - for (i=0; i < num; i++) { - if (ext2fs_fast_test_block_bitmap(bitmap, block+i)) - return 0; + return ext2fs_test_clear_generic_bitmap_range((ext2fs_generic_bitmap) + bitmap, block, num); +} + +int ext2fs_test_inode_bitmap_range(ext2fs_inode_bitmap bitmap, + ino_t inode, int num) +{ + int i; + + EXT2_CHECK_MAGIC(bitmap, EXT2_ET_MAGIC_INODE_BITMAP); + if ((inode < bitmap->start) || (inode+num-1 > bitmap->real_end)) { + ext2fs_warn_bitmap(EXT2_ET_BAD_INODE_TEST, + inode, bitmap->description); + return 0; } - return 1; + return ext2fs_test_clear_generic_bitmap_range((ext2fs_generic_bitmap) + bitmap, inode, num); } void ext2fs_mark_block_bitmap_range(ext2fs_block_bitmap bitmap,