]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - fs/ocfs2/suballoc.c
Merge branch 'master' of /home/davem/src/GIT/linux-2.6/
[linux-2.6-omap-h63xx.git] / fs / ocfs2 / suballoc.c
index 797f509d72500324dbb71a89c08bb4e83a9d01b5..a69628603e18273cdbc3d2b5d7e5a440623c17c8 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,67 @@ 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) {
+               mlog(ML_ERROR,
+                    "Checksum failed for group descriptor %llu\n",
+                    (unsigned long long)bh->b_blocknr);
+       } else
+               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 +306,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;
@@ -277,10 +347,10 @@ static int ocfs2_block_group_fill(handle_t *handle,
                goto bail;
        }
 
-       status = ocfs2_journal_access(handle,
-                                     alloc_inode,
-                                     bg_bh,
-                                     OCFS2_JOURNAL_ACCESS_CREATE);
+       status = ocfs2_journal_access_gd(handle,
+                                        alloc_inode,
+                                        bg_bh,
+                                        OCFS2_JOURNAL_ACCESS_CREATE);
        if (status < 0) {
                mlog_errno(status);
                goto bail;
@@ -410,8 +480,8 @@ static int ocfs2_block_group_alloc(struct ocfs2_super *osb,
 
        bg = (struct ocfs2_group_desc *) bg_bh->b_data;
 
-       status = ocfs2_journal_access(handle, alloc_inode,
-                                     bh, OCFS2_JOURNAL_ACCESS_WRITE);
+       status = ocfs2_journal_access_di(handle, alloc_inode,
+                                        bh, OCFS2_JOURNAL_ACCESS_WRITE);
        if (status < 0) {
                mlog_errno(status);
                goto bail;
@@ -842,10 +912,9 @@ static int ocfs2_block_group_find_clear_bits(struct ocfs2_super *osb,
        int offset, start, found, status = 0;
        struct ocfs2_group_desc *bg = (struct ocfs2_group_desc *) bg_bh->b_data;
 
-       if (!OCFS2_IS_VALID_GROUP_DESC(bg)) {
-               OCFS2_RO_ON_INVALID_GROUP_DESC(osb->sb, bg);
-               return -EIO;
-       }
+       /* Callers got this descriptor from
+        * ocfs2_read_group_descriptor().  Any corruption is a code bug. */
+       BUG_ON(!OCFS2_IS_VALID_GROUP_DESC(bg));
 
        found = start = best_offset = best_size = 0;
        bitmap = bg->bg_bitmap;
@@ -910,11 +979,9 @@ static inline int ocfs2_block_group_set_bits(handle_t *handle,
 
        mlog_entry_void();
 
-       if (!OCFS2_IS_VALID_GROUP_DESC(bg)) {
-               OCFS2_RO_ON_INVALID_GROUP_DESC(alloc_inode->i_sb, bg);
-               status = -EIO;
-               goto bail;
-       }
+       /* All callers get the descriptor via
+        * ocfs2_read_group_descriptor().  Any corruption is a code bug. */
+       BUG_ON(!OCFS2_IS_VALID_GROUP_DESC(bg));
        BUG_ON(le16_to_cpu(bg->bg_free_bits_count) < num_bits);
 
        mlog(0, "block_group_set_bits: off = %u, num = %u\n", bit_off,
@@ -923,10 +990,10 @@ static inline int ocfs2_block_group_set_bits(handle_t *handle,
        if (ocfs2_is_cluster_bitmap(alloc_inode))
                journal_type = OCFS2_JOURNAL_ACCESS_UNDO;
 
-       status = ocfs2_journal_access(handle,
-                                     alloc_inode,
-                                     group_bh,
-                                     journal_type);
+       status = ocfs2_journal_access_gd(handle,
+                                        alloc_inode,
+                                        group_bh,
+                                        journal_type);
        if (status < 0) {
                mlog_errno(status);
                goto bail;
@@ -983,16 +1050,10 @@ static int ocfs2_relink_block_group(handle_t *handle,
        struct ocfs2_group_desc *bg = (struct ocfs2_group_desc *) bg_bh->b_data;
        struct ocfs2_group_desc *prev_bg = (struct ocfs2_group_desc *) prev_bg_bh->b_data;
 
-       if (!OCFS2_IS_VALID_GROUP_DESC(bg)) {
-               OCFS2_RO_ON_INVALID_GROUP_DESC(alloc_inode->i_sb, bg);
-               status = -EIO;
-               goto out;
-       }
-       if (!OCFS2_IS_VALID_GROUP_DESC(prev_bg)) {
-               OCFS2_RO_ON_INVALID_GROUP_DESC(alloc_inode->i_sb, prev_bg);
-               status = -EIO;
-               goto out;
-       }
+       /* The caller got these descriptors from
+        * ocfs2_read_group_descriptor().  Any corruption is a code bug. */
+       BUG_ON(!OCFS2_IS_VALID_GROUP_DESC(bg));
+       BUG_ON(!OCFS2_IS_VALID_GROUP_DESC(prev_bg));
 
        mlog(0, "Suballoc %llu, chain %u, move group %llu to top, prev = %llu\n",
             (unsigned long long)le64_to_cpu(fe->i_blkno), chain,
@@ -1003,8 +1064,8 @@ static int ocfs2_relink_block_group(handle_t *handle,
        bg_ptr = le64_to_cpu(bg->bg_next_group);
        prev_bg_ptr = le64_to_cpu(prev_bg->bg_next_group);
 
-       status = ocfs2_journal_access(handle, alloc_inode, prev_bg_bh,
-                                     OCFS2_JOURNAL_ACCESS_WRITE);
+       status = ocfs2_journal_access_gd(handle, alloc_inode, prev_bg_bh,
+                                        OCFS2_JOURNAL_ACCESS_WRITE);
        if (status < 0) {
                mlog_errno(status);
                goto out_rollback;
@@ -1018,8 +1079,8 @@ static int ocfs2_relink_block_group(handle_t *handle,
                goto out_rollback;
        }
 
-       status = ocfs2_journal_access(handle, alloc_inode, bg_bh,
-                                     OCFS2_JOURNAL_ACCESS_WRITE);
+       status = ocfs2_journal_access_gd(handle, alloc_inode, bg_bh,
+                                        OCFS2_JOURNAL_ACCESS_WRITE);
        if (status < 0) {
                mlog_errno(status);
                goto out_rollback;
@@ -1033,8 +1094,8 @@ static int ocfs2_relink_block_group(handle_t *handle,
                goto out_rollback;
        }
 
-       status = ocfs2_journal_access(handle, alloc_inode, fe_bh,
-                                     OCFS2_JOURNAL_ACCESS_WRITE);
+       status = ocfs2_journal_access_di(handle, alloc_inode, fe_bh,
+                                        OCFS2_JOURNAL_ACCESS_WRITE);
        if (status < 0) {
                mlog_errno(status);
                goto out_rollback;
@@ -1055,7 +1116,7 @@ out_rollback:
                bg->bg_next_group = cpu_to_le64(bg_ptr);
                prev_bg->bg_next_group = cpu_to_le64(prev_bg_ptr);
        }
-out:
+
        mlog_exit(status);
        return status;
 }
@@ -1185,8 +1246,8 @@ static int ocfs2_alloc_dinode_update_counts(struct inode *inode,
        struct ocfs2_dinode *di = (struct ocfs2_dinode *) di_bh->b_data;
        struct ocfs2_chain_list *cl = (struct ocfs2_chain_list *) &di->id2.i_chain;
 
-       ret = ocfs2_journal_access(handle, inode, di_bh,
-                                  OCFS2_JOURNAL_ACCESS_WRITE);
+       ret = ocfs2_journal_access_di(handle, inode, di_bh,
+                                     OCFS2_JOURNAL_ACCESS_WRITE);
        if (ret < 0) {
                mlog_errno(ret);
                goto out;
@@ -1357,10 +1418,10 @@ static int ocfs2_search_chain(struct ocfs2_alloc_context *ac,
 
        /* Ok, claim our bits now: set the info on dinode, chainlist
         * and then the group */
-       status = ocfs2_journal_access(handle,
-                                     alloc_inode,
-                                     ac->ac_bh,
-                                     OCFS2_JOURNAL_ACCESS_WRITE);
+       status = ocfs2_journal_access_di(handle,
+                                        alloc_inode,
+                                        ac->ac_bh,
+                                        OCFS2_JOURNAL_ACCESS_WRITE);
        if (status < 0) {
                mlog_errno(status);
                goto bail;
@@ -1758,19 +1819,17 @@ static inline int ocfs2_block_group_clear_bits(handle_t *handle,
 
        mlog_entry_void();
 
-       if (!OCFS2_IS_VALID_GROUP_DESC(bg)) {
-               OCFS2_RO_ON_INVALID_GROUP_DESC(alloc_inode->i_sb, bg);
-               status = -EIO;
-               goto bail;
-       }
+       /* The caller got this descriptor from
+        * ocfs2_read_group_descriptor().  Any corruption is a code bug. */
+       BUG_ON(!OCFS2_IS_VALID_GROUP_DESC(bg));
 
        mlog(0, "off = %u, num = %u\n", bit_off, num_bits);
 
        if (ocfs2_is_cluster_bitmap(alloc_inode))
                journal_type = OCFS2_JOURNAL_ACCESS_UNDO;
 
-       status = ocfs2_journal_access(handle, alloc_inode, group_bh,
-                                     journal_type);
+       status = ocfs2_journal_access_gd(handle, alloc_inode, group_bh,
+                                        journal_type);
        if (status < 0) {
                mlog_errno(status);
                goto bail;
@@ -1845,8 +1904,8 @@ int ocfs2_free_suballoc_bits(handle_t *handle,
                goto bail;
        }
 
-       status = ocfs2_journal_access(handle, alloc_inode, alloc_bh,
-                                     OCFS2_JOURNAL_ACCESS_WRITE);
+       status = ocfs2_journal_access_di(handle, alloc_inode, alloc_bh,
+                                        OCFS2_JOURNAL_ACCESS_WRITE);
        if (status < 0) {
                mlog_errno(status);
                goto bail;