Whamcloud - gitweb
libext2fs: Add new function ext2fs_test_inode_bitmap_range()
authorTheodore Ts'o <tytso@mit.edu>
Thu, 9 Jul 2009 18:32:52 +0000 (14:32 -0400)
committerTheodore Ts'o <tytso@mit.edu>
Thu, 9 Jul 2009 18:32:52 +0000 (14:32 -0400)
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 <k-mio@sx.jp.nec.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
debian/e2fslibs.symbols
lib/ext2fs/bitops.h
lib/ext2fs/gen_bitmap.c

index 3ee0bca..c203f02 100644 (file)
@@ -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
index 1d825bb..32111ba 100644 (file)
@@ -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,
index a1b1d8f..19caf23 100644 (file)
@@ -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,