]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
ocfs2: Tighten free bit calculation in the global bitmap
authorSunil Mushran <sunil.mushran@oracle.com>
Tue, 8 Nov 2011 21:00:19 +0000 (13:00 -0800)
committerSantosh Shilimkar <santosh.shilimkar@oracle.com>
Mon, 29 Jun 2015 15:30:26 +0000 (08:30 -0700)
When clearing bits in the global bitmap, we do not test the current bit value.
This patch tightens the code by considering the possiblity that the bit being
cleared was already cleared.

Now this should not happen. But we are seeing stray instances in which free
bit count in the global bitmap exceeds the total bit count. In each instance
the bitmap is correct. Only the free bit count is incorrect.

This patch checks the current bit value and increments the free bit count
only if the bit was previously set. It also prints information to allow
us to debug further.

Orabug: 17342255

Signed-off-by: Sunil Mushran <sunil.mushran@oracle.com>
Signed-off-by: Srinivas Eeda <srinivas.eeda@oracle.com>
(cherry picked from commit d1726d8617f7d27c54d12b50c9a20b248ebd0c66)

fs/ocfs2/suballoc.c

index 4479029630bb37bb8a6e4880e94ab8633d967df6..f12fc4a71dab8d444bd563dcca1355188cc2b0f3 100644 (file)
@@ -2394,6 +2394,7 @@ static int ocfs2_block_group_clear_bits(handle_t *handle,
        int status;
        unsigned int tmp;
        struct ocfs2_group_desc *undo_bg = NULL;
+       unsigned int bits_cleared = 0;
 
        /* The caller got this descriptor from
         * ocfs2_read_group_descriptor().  Any corruption is a code bug. */
@@ -2421,13 +2422,27 @@ static int ocfs2_block_group_clear_bits(handle_t *handle,
 
        tmp = num_bits;
        while(tmp--) {
-               ocfs2_clear_bit((bit_off + tmp),
-                               (unsigned long *) bg->bg_bitmap);
+               if (ocfs2_test_bit((bit_off + tmp),
+                                  (unsigned long *) bg->bg_bitmap)) {
+                       ocfs2_clear_bit((bit_off + tmp),
+                                       (unsigned long *) bg->bg_bitmap);
+                       bits_cleared++;
+               }
                if (undo_fn)
                        undo_fn(bit_off + tmp,
                                (unsigned long *) undo_bg->bg_bitmap);
        }
-       le16_add_cpu(&bg->bg_free_bits_count, num_bits);
+
+       le16_add_cpu(&bg->bg_free_bits_count, bits_cleared);
+
+       if (num_bits != bits_cleared) {
+               printk(KERN_NOTICE "ocfs2: Trying to clear %u bits at "
+                      "offset %u in group descriptor # %llu (device %s), "
+                      "needed to clear %u bits\n", num_bits, bit_off,
+                      (unsigned long long)le64_to_cpu(bg->bg_blkno),
+                      alloc_inode->i_sb->s_id, bits_cleared);
+       }
+
        if (le16_to_cpu(bg->bg_free_bits_count) > le16_to_cpu(bg->bg_bits)) {
                ocfs2_error(alloc_inode->i_sb, "Group descriptor # %llu has bit"
                            " count %u but claims %u are freed. num_bits %d",