ocfs2: Add journal_access functions with jbd2 triggers.
[cascardo/linux.git] / fs / ocfs2 / suballoc.c
index 766a00b..7875576 100644 (file)
@@ -35,6 +35,7 @@
 #include "ocfs2.h"
 
 #include "alloc.h"
+#include "blockcheck.h"
 #include "dlmglue.h"
 #include "inode.h"
 #include "journal.h"
@@ -145,14 +146,6 @@ static u32 ocfs2_bits_per_group(struct ocfs2_chain_list *cl)
        return (u32)le16_to_cpu(cl->cl_cpg) * (u32)le16_to_cpu(cl->cl_bpc);
 }
 
-int ocfs2_validate_group_descriptor(struct super_block *sb,
-                                   struct ocfs2_dinode *di,
-                                   struct buffer_head *bh,
-                                   int clean_error)
-{
-       unsigned int max_bits;
-       struct ocfs2_group_desc *gd = (struct ocfs2_group_desc *)bh->b_data;
-
 #define do_error(fmt, ...)                                             \
        do{                                                             \
                if (clean_error)                                        \
@@ -161,6 +154,12 @@ int ocfs2_validate_group_descriptor(struct super_block *sb,
                        ocfs2_error(sb, fmt, ##__VA_ARGS__);            \
        } while (0)
 
+static int ocfs2_validate_gd_self(struct super_block *sb,
+                                 struct buffer_head *bh,
+                                 int clean_error)
+{
+       struct ocfs2_group_desc *gd = (struct ocfs2_group_desc *)bh->b_data;
+
        if (!OCFS2_IS_VALID_GROUP_DESC(gd)) {
                do_error("Group descriptor #%llu has bad signature %.*s",
                         (unsigned long long)bh->b_blocknr, 7,
@@ -184,6 +183,35 @@ int ocfs2_validate_group_descriptor(struct super_block *sb,
                return -EINVAL;
        }
 
+       if (le16_to_cpu(gd->bg_free_bits_count) > le16_to_cpu(gd->bg_bits)) {
+               do_error("Group descriptor #%llu has bit count %u but "
+                        "claims that %u are free",
+                        (unsigned long long)bh->b_blocknr,
+                        le16_to_cpu(gd->bg_bits),
+                        le16_to_cpu(gd->bg_free_bits_count));
+               return -EINVAL;
+       }
+
+       if (le16_to_cpu(gd->bg_bits) > (8 * le16_to_cpu(gd->bg_size))) {
+               do_error("Group descriptor #%llu has bit count %u but "
+                        "max bitmap bits of %u",
+                        (unsigned long long)bh->b_blocknr,
+                        le16_to_cpu(gd->bg_bits),
+                        8 * le16_to_cpu(gd->bg_size));
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int ocfs2_validate_gd_parent(struct super_block *sb,
+                                   struct ocfs2_dinode *di,
+                                   struct buffer_head *bh,
+                                   int clean_error)
+{
+       unsigned int max_bits;
+       struct ocfs2_group_desc *gd = (struct ocfs2_group_desc *)bh->b_data;
+
        if (di->i_blkno != gd->bg_parent_dinode) {
                do_error("Group descriptor #%llu has bad parent "
                         "pointer (%llu, expected %llu)",
@@ -209,26 +237,63 @@ int ocfs2_validate_group_descriptor(struct super_block *sb,
                return -EINVAL;
        }
 
-       if (le16_to_cpu(gd->bg_free_bits_count) > le16_to_cpu(gd->bg_bits)) {
-               do_error("Group descriptor #%llu has bit count %u but "
-                        "claims that %u are free",
-                        (unsigned long long)bh->b_blocknr,
-                        le16_to_cpu(gd->bg_bits),
-                        le16_to_cpu(gd->bg_free_bits_count));
-               return -EINVAL;
-       }
+       return 0;
+}
 
-       if (le16_to_cpu(gd->bg_bits) > (8 * le16_to_cpu(gd->bg_size))) {
-               do_error("Group descriptor #%llu has bit count %u but "
-                        "max bitmap bits of %u",
-                        (unsigned long long)bh->b_blocknr,
-                        le16_to_cpu(gd->bg_bits),
-                        8 * le16_to_cpu(gd->bg_size));
-               return -EINVAL;
-       }
 #undef do_error
 
-       return 0;
+/*
+ * This version only prints errors.  It does not fail the filesystem, and
+ * exists only for resize.
+ */
+int ocfs2_check_group_descriptor(struct super_block *sb,
+                                struct ocfs2_dinode *di,
+                                struct buffer_head *bh)
+{
+       int rc;
+       struct ocfs2_group_desc *gd = (struct ocfs2_group_desc *)bh->b_data;
+
+       BUG_ON(!buffer_uptodate(bh));
+
+       /*
+        * If the ecc fails, we return the error but otherwise
+        * leave the filesystem running.  We know any error is
+        * local to this block.
+        */
+       rc = ocfs2_validate_meta_ecc(sb, bh->b_data, &gd->bg_check);
+       if (!rc)
+               rc = ocfs2_validate_gd_self(sb, bh, 1);
+       if (!rc)
+               rc = ocfs2_validate_gd_parent(sb, di, bh, 1);
+
+       return rc;
+}
+
+static int ocfs2_validate_group_descriptor(struct super_block *sb,
+                                          struct buffer_head *bh)
+{
+       int rc;
+       struct ocfs2_group_desc *gd = (struct ocfs2_group_desc *)bh->b_data;
+
+       mlog(0, "Validating group descriptor %llu\n",
+            (unsigned long long)bh->b_blocknr);
+
+       BUG_ON(!buffer_uptodate(bh));
+
+       /*
+        * If the ecc fails, we return the error but otherwise
+        * leave the filesystem running.  We know any error is
+        * local to this block.
+        */
+       rc = ocfs2_validate_meta_ecc(sb, bh->b_data, &gd->bg_check);
+       if (rc)
+               return rc;
+
+       /*
+        * Errors after here are fatal.
+        */
+
+       return ocfs2_validate_gd_self(sb, bh, 0);
 }
 
 int ocfs2_read_group_descriptor(struct inode *inode, struct ocfs2_dinode *di,
@@ -237,11 +302,12 @@ int ocfs2_read_group_descriptor(struct inode *inode, struct ocfs2_dinode *di,
        int rc;
        struct buffer_head *tmp = *bh;
 
-       rc = ocfs2_read_block(inode, gd_blkno, &tmp);
+       rc = ocfs2_read_block(inode, gd_blkno, &tmp,
+                             ocfs2_validate_group_descriptor);
        if (rc)
                goto out;
 
-       rc = ocfs2_validate_group_descriptor(inode->i_sb, di, tmp, 0);
+       rc = ocfs2_validate_gd_parent(inode->i_sb, di, tmp, 0);
        if (rc) {
                brelse(tmp);
                goto out;