ext4: Fix return value of ext4_split_unwritten_extents() to fix direct I/O
[safe/jmp/linux-2.6] / fs / ocfs2 / blockcheck.c
index 2bf3d7f..a1163b8 100644 (file)
 #include <linux/crc32.h>
 #include <linux/buffer_head.h>
 #include <linux/bitops.h>
+#include <linux/debugfs.h>
+#include <linux/module.h>
+#include <linux/fs.h>
 #include <asm/byteorder.h>
 
+#include <cluster/masklog.h>
+
 #include "ocfs2.h"
 
 #include "blockcheck.h"
 
 
-
 /*
  * We use the following conventions:
  *
  * p = # parity bits
  * c = # total code bits (d + p)
  */
-static int calc_parity_bits(unsigned int d)
-{
-       unsigned int p;
-
-       /*
-        * Bits required for Single Error Correction is as follows:
-        *
-        * d + p + 1 <= 2^p
-        *
-        * We're restricting ourselves to 31 bits of parity, that should be
-        * sufficient.
-        */
-       for (p = 1; p < 32; p++)
-       {
-               if ((d + p + 1) <= (1 << p))
-                       return p;
-       }
 
-       return 0;
-}
 
 /*
  * Calculate the bit offset in the hamming code buffer based on the bit's
@@ -71,10 +56,14 @@ static int calc_parity_bits(unsigned int d)
  * so it's a parity bit.  2 is a power of two (2^1), so it's a parity bit.
  * 3 is not a power of two.  So bit 1 of the data buffer ends up as bit 3
  * in the code buffer.
+ *
+ * The caller can pass in *p if it wants to keep track of the most recent
+ * number of parity bits added.  This allows the function to start the
+ * calculation at the last place.
  */
-static unsigned int calc_code_bit(unsigned int i)
+static unsigned int calc_code_bit(unsigned int i, unsigned int *p_cache)
 {
-       unsigned int b, p;
+       unsigned int b, p = 0;
 
        /*
         * Data bits are 0-based, but we're talking code bits, which
@@ -82,15 +71,25 @@ static unsigned int calc_code_bit(unsigned int i)
         */
        b = i + 1;
 
+       /* Use the cache if it is there */
+       if (p_cache)
+               p = *p_cache;
+        b += p;
+
        /*
         * For every power of two below our bit number, bump our bit.
         *
-        * We compare with (b + 1) becuase we have to compare with what b
+        * We compare with (b + 1) because we have to compare with what b
         * would be _if_ it were bumped up by the parity bit.  Capice?
+        *
+        * p is set above.
         */
-       for (p = 0; (1 << p) < (b + 1); p++)
+       for (; (1 << p) < (b + 1); p++)
                b++;
 
+       if (p_cache)
+               *p_cache = p;
+
        return b;
 }
 
@@ -107,10 +106,9 @@ static unsigned int calc_code_bit(unsigned int i)
  */
 u32 ocfs2_hamming_encode(u32 parity, void *data, unsigned int d, unsigned int nr)
 {
-       unsigned int p = calc_parity_bits(nr + d);
-       unsigned int i, j, b;
+       unsigned int i, b, p = 0;
 
-       BUG_ON(!p);
+       BUG_ON(!d);
 
        /*
         * b is the hamming code bit number.  Hamming code specifies a
@@ -127,29 +125,25 @@ u32 ocfs2_hamming_encode(u32 parity, void *data, unsigned int d, unsigned int nr
                 * i is the offset in this hunk, nr + i is the total bit
                 * offset.
                 */
-               b = calc_code_bit(nr + i);
+               b = calc_code_bit(nr + i, &p);
 
-               for (j = 0; j < p; j++)
-               {
-                       /*
-                        * Data bits in the resultant code are checked by
-                        * parity bits that are part of the bit number
-                        * representation.  Huh?
-                        *
-                        * <wikipedia href="http://en.wikipedia.org/wiki/Hamming_code">
-                        * In other words, the parity bit at position 2^k
-                        * checks bits in positions having bit k set in
-                        * their binary representation.  Conversely, for
-                        * instance, bit 13, i.e. 1101(2), is checked by
-                        * bits 1000(2) = 8, 0100(2)=4 and 0001(2) = 1.
-                        * </wikipedia>
-                        *
-                        * Note that 'k' is the _code_ bit number.  'b' in
-                        * our loop.
-                        */
-                       if (b & (1 << j))
-                               parity ^= (1 << j);
-               }
+               /*
+                * Data bits in the resultant code are checked by
+                * parity bits that are part of the bit number
+                * representation.  Huh?
+                *
+                * <wikipedia href="http://en.wikipedia.org/wiki/Hamming_code">
+                * In other words, the parity bit at position 2^k
+                * checks bits in positions having bit k set in
+                * their binary representation.  Conversely, for
+                * instance, bit 13, i.e. 1101(2), is checked by
+                * bits 1000(2) = 8, 0100(2)=4 and 0001(2) = 1.
+                * </wikipedia>
+                *
+                * Note that 'k' is the _code_ bit number.  'b' in
+                * our loop.
+                */
+               parity ^= b;
        }
 
        /* While the data buffer was treated as little endian, the
@@ -172,10 +166,9 @@ u32 ocfs2_hamming_encode_block(void *data, unsigned int blocksize)
 void ocfs2_hamming_fix(void *data, unsigned int d, unsigned int nr,
                       unsigned int fix)
 {
-       unsigned int p = calc_parity_bits(nr + d);
        unsigned int i, b;
 
-       BUG_ON(!p);
+       BUG_ON(!d);
 
        /*
         * If the bit to fix has an hweight of 1, it's a parity bit.  One
@@ -188,7 +181,7 @@ void ocfs2_hamming_fix(void *data, unsigned int d, unsigned int nr,
         * nr + d is the bit right past the data hunk we're looking at.
         * If fix after that, nothing to do
         */
-       if (fix >= calc_code_bit(nr + d))
+       if (fix >= calc_code_bit(nr + d, NULL))
                return;
 
        /*
@@ -196,7 +189,7 @@ void ocfs2_hamming_fix(void *data, unsigned int d, unsigned int nr,
         * start b at the offset in the code buffer.  See hamming_encode()
         * for a more detailed description of 'b'.
         */
-       b = calc_code_bit(nr);
+       b = calc_code_bit(nr, NULL);
        /* If the fix is before this hunk, nothing to do */
        if (fix < b)
                return;
@@ -232,6 +225,155 @@ void ocfs2_hamming_fix_block(void *data, unsigned int blocksize,
        ocfs2_hamming_fix(data, blocksize * 8, 0, fix);
 }
 
+
+/*
+ * Debugfs handling.
+ */
+
+#ifdef CONFIG_DEBUG_FS
+
+static int blockcheck_u64_get(void *data, u64 *val)
+{
+       *val = *(u64 *)data;
+       return 0;
+}
+DEFINE_SIMPLE_ATTRIBUTE(blockcheck_fops, blockcheck_u64_get, NULL, "%llu\n");
+
+static struct dentry *blockcheck_debugfs_create(const char *name,
+                                               struct dentry *parent,
+                                               u64 *value)
+{
+       return debugfs_create_file(name, S_IFREG | S_IRUSR, parent, value,
+                                  &blockcheck_fops);
+}
+
+static void ocfs2_blockcheck_debug_remove(struct ocfs2_blockcheck_stats *stats)
+{
+       if (stats) {
+               debugfs_remove(stats->b_debug_check);
+               stats->b_debug_check = NULL;
+               debugfs_remove(stats->b_debug_failure);
+               stats->b_debug_failure = NULL;
+               debugfs_remove(stats->b_debug_recover);
+               stats->b_debug_recover = NULL;
+               debugfs_remove(stats->b_debug_dir);
+               stats->b_debug_dir = NULL;
+       }
+}
+
+static int ocfs2_blockcheck_debug_install(struct ocfs2_blockcheck_stats *stats,
+                                         struct dentry *parent)
+{
+       int rc = -EINVAL;
+
+       if (!stats)
+               goto out;
+
+       stats->b_debug_dir = debugfs_create_dir("blockcheck", parent);
+       if (!stats->b_debug_dir)
+               goto out;
+
+       stats->b_debug_check =
+               blockcheck_debugfs_create("blocks_checked",
+                                         stats->b_debug_dir,
+                                         &stats->b_check_count);
+
+       stats->b_debug_failure =
+               blockcheck_debugfs_create("checksums_failed",
+                                         stats->b_debug_dir,
+                                         &stats->b_failure_count);
+
+       stats->b_debug_recover =
+               blockcheck_debugfs_create("ecc_recoveries",
+                                         stats->b_debug_dir,
+                                         &stats->b_recover_count);
+       if (stats->b_debug_check && stats->b_debug_failure &&
+           stats->b_debug_recover)
+               rc = 0;
+
+out:
+       if (rc)
+               ocfs2_blockcheck_debug_remove(stats);
+       return rc;
+}
+#else
+static inline int ocfs2_blockcheck_debug_install(struct ocfs2_blockcheck_stats *stats,
+                                                struct dentry *parent)
+{
+       return 0;
+}
+
+static inline void ocfs2_blockcheck_debug_remove(struct ocfs2_blockcheck_stats *stats)
+{
+}
+#endif  /* CONFIG_DEBUG_FS */
+
+/* Always-called wrappers for starting and stopping the debugfs files */
+int ocfs2_blockcheck_stats_debugfs_install(struct ocfs2_blockcheck_stats *stats,
+                                          struct dentry *parent)
+{
+       return ocfs2_blockcheck_debug_install(stats, parent);
+}
+
+void ocfs2_blockcheck_stats_debugfs_remove(struct ocfs2_blockcheck_stats *stats)
+{
+       ocfs2_blockcheck_debug_remove(stats);
+}
+
+static void ocfs2_blockcheck_inc_check(struct ocfs2_blockcheck_stats *stats)
+{
+       u64 new_count;
+
+       if (!stats)
+               return;
+
+       spin_lock(&stats->b_lock);
+       stats->b_check_count++;
+       new_count = stats->b_check_count;
+       spin_unlock(&stats->b_lock);
+
+       if (!new_count)
+               mlog(ML_NOTICE, "Block check count has wrapped\n");
+}
+
+static void ocfs2_blockcheck_inc_failure(struct ocfs2_blockcheck_stats *stats)
+{
+       u64 new_count;
+
+       if (!stats)
+               return;
+
+       spin_lock(&stats->b_lock);
+       stats->b_failure_count++;
+       new_count = stats->b_failure_count;
+       spin_unlock(&stats->b_lock);
+
+       if (!new_count)
+               mlog(ML_NOTICE, "Checksum failure count has wrapped\n");
+}
+
+static void ocfs2_blockcheck_inc_recover(struct ocfs2_blockcheck_stats *stats)
+{
+       u64 new_count;
+
+       if (!stats)
+               return;
+
+       spin_lock(&stats->b_lock);
+       stats->b_recover_count++;
+       new_count = stats->b_recover_count;
+       spin_unlock(&stats->b_lock);
+
+       if (!new_count)
+               mlog(ML_NOTICE, "ECC recovery count has wrapped\n");
+}
+
+
+
+/*
+ * These are the low-level APIs for using the ocfs2_block_check structure.
+ */
+
 /*
  * This function generates check information for a block.
  * data is the block to be checked.  bc is a pointer to the
@@ -276,12 +418,15 @@ void ocfs2_block_check_compute(void *data, size_t blocksize,
  * Again, the data passed in should be the on-disk endian.
  */
 int ocfs2_block_check_validate(void *data, size_t blocksize,
-                              struct ocfs2_block_check *bc)
+                              struct ocfs2_block_check *bc,
+                              struct ocfs2_blockcheck_stats *stats)
 {
        int rc = 0;
        struct ocfs2_block_check check;
        u32 crc, ecc;
 
+       ocfs2_blockcheck_inc_check(stats);
+
        check.bc_crc32e = le32_to_cpu(bc->bc_crc32e);
        check.bc_ecc = le16_to_cpu(bc->bc_ecc);
 
@@ -292,14 +437,24 @@ int ocfs2_block_check_validate(void *data, size_t blocksize,
        if (crc == check.bc_crc32e)
                goto out;
 
+       ocfs2_blockcheck_inc_failure(stats);
+       mlog(ML_ERROR,
+            "CRC32 failed: stored: %u, computed %u.  Applying ECC.\n",
+            (unsigned int)check.bc_crc32e, (unsigned int)crc);
+
        /* Ok, try ECC fixups */
        ecc = ocfs2_hamming_encode_block(data, blocksize);
        ocfs2_hamming_fix_block(data, blocksize, ecc ^ check.bc_ecc);
 
        /* And check the crc32 again */
        crc = crc32_le(~0, data, blocksize);
-       if (crc == check.bc_crc32e)
+       if (crc == check.bc_crc32e) {
+               ocfs2_blockcheck_inc_recover(stats);
                goto out;
+       }
+
+       mlog(ML_ERROR, "Fixed CRC32 failed: stored: %u, computed %u\n",
+            (unsigned int)check.bc_crc32e, (unsigned int)crc);
 
        rc = -EIO;
 
@@ -369,7 +524,8 @@ void ocfs2_block_check_compute_bhs(struct buffer_head **bhs, int nr,
  * Again, the data passed in should be the on-disk endian.
  */
 int ocfs2_block_check_validate_bhs(struct buffer_head **bhs, int nr,
-                                  struct ocfs2_block_check *bc)
+                                  struct ocfs2_block_check *bc,
+                                  struct ocfs2_blockcheck_stats *stats)
 {
        int i, rc = 0;
        struct ocfs2_block_check check;
@@ -380,6 +536,8 @@ int ocfs2_block_check_validate_bhs(struct buffer_head **bhs, int nr,
        if (!nr)
                return 0;
 
+       ocfs2_blockcheck_inc_check(stats);
+
        check.bc_crc32e = le32_to_cpu(bc->bc_crc32e);
        check.bc_ecc = le16_to_cpu(bc->bc_ecc);
 
@@ -391,6 +549,7 @@ int ocfs2_block_check_validate_bhs(struct buffer_head **bhs, int nr,
        if (crc == check.bc_crc32e)
                goto out;
 
+       ocfs2_blockcheck_inc_failure(stats);
        mlog(ML_ERROR,
             "CRC32 failed: stored: %u, computed %u.  Applying ECC.\n",
             (unsigned int)check.bc_crc32e, (unsigned int)crc);
@@ -419,8 +578,10 @@ int ocfs2_block_check_validate_bhs(struct buffer_head **bhs, int nr,
        /* And check the crc32 again */
        for (i = 0, crc = ~0; i < nr; i++)
                crc = crc32_le(crc, bhs[i]->b_data, bhs[i]->b_size);
-       if (crc == check.bc_crc32e)
+       if (crc == check.bc_crc32e) {
+               ocfs2_blockcheck_inc_recover(stats);
                goto out;
+       }
 
        mlog(ML_ERROR, "Fixed CRC32 failed: stored: %u, computed %u\n",
             (unsigned int)check.bc_crc32e, (unsigned int)crc);
@@ -451,9 +612,11 @@ int ocfs2_validate_meta_ecc(struct super_block *sb, void *data,
                            struct ocfs2_block_check *bc)
 {
        int rc = 0;
+       struct ocfs2_super *osb = OCFS2_SB(sb);
 
-       if (ocfs2_meta_ecc(OCFS2_SB(sb)))
-               rc = ocfs2_block_check_validate(data, sb->s_blocksize, bc);
+       if (ocfs2_meta_ecc(osb))
+               rc = ocfs2_block_check_validate(data, sb->s_blocksize, bc,
+                                               &osb->osb_ecc_stats);
 
        return rc;
 }
@@ -471,9 +634,11 @@ int ocfs2_validate_meta_ecc_bhs(struct super_block *sb,
                                struct ocfs2_block_check *bc)
 {
        int rc = 0;
+       struct ocfs2_super *osb = OCFS2_SB(sb);
 
-       if (ocfs2_meta_ecc(OCFS2_SB(sb)))
-               rc = ocfs2_block_check_validate_bhs(bhs, nr, bc);
+       if (ocfs2_meta_ecc(osb))
+               rc = ocfs2_block_check_validate_bhs(bhs, nr, bc,
+                                                   &osb->osb_ecc_stats);
 
        return rc;
 }