xfs: add buffer types to directory and attribute buffers
authorDave Chinner <dchinner@redhat.com>
Wed, 3 Apr 2013 05:11:29 +0000 (16:11 +1100)
committerBen Myers <bpm@sgi.com>
Sat, 27 Apr 2013 18:01:06 +0000 (13:01 -0500)
Add buffer types to the buffer log items so that log recovery can
validate the buffers and calculate CRCs correctly after the buffers
are recovered.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Ben Myers <bpm@sgi.com>
Signed-off-by: Ben Myers <bpm@sgi.com>
13 files changed:
fs/xfs/xfs_attr_leaf.c
fs/xfs/xfs_attr_remote.h
fs/xfs/xfs_buf_item.h
fs/xfs/xfs_da_btree.c
fs/xfs/xfs_da_btree.h
fs/xfs/xfs_dir2_block.c
fs/xfs/xfs_dir2_data.c
fs/xfs/xfs_dir2_leaf.c
fs/xfs/xfs_dir2_node.c
fs/xfs/xfs_dir2_priv.h
fs/xfs/xfs_log_recover.c
fs/xfs/xfs_trans.h
fs/xfs/xfs_trans_buf.c

index 287c8089b7055d8a113e3d89bc9a39c148d53535..92cda03d1c016c321342d0525ad24200b72fbce4 100644 (file)
@@ -271,8 +271,13 @@ xfs_attr3_leaf_read(
        xfs_daddr_t             mappedbno,
        struct xfs_buf          **bpp)
 {
-       return xfs_da_read_buf(tp, dp, bno, mappedbno, bpp,
+       int                     err;
+
+       err = xfs_da_read_buf(tp, dp, bno, mappedbno, bpp,
                                XFS_ATTR_FORK, &xfs_attr3_leaf_buf_ops);
+       if (!err && tp)
+               xfs_trans_buf_set_type(tp, *bpp, XFS_BLF_ATTR_LEAF_BUF);
+       return err;
 }
 
 /*========================================================================
@@ -1078,6 +1083,7 @@ xfs_attr3_leaf_to_node(
                goto out;
 
        /* copy leaf to new buffer, update identifiers */
+       xfs_trans_buf_set_type(args->trans, bp2, XFS_BLF_ATTR_LEAF_BUF);
        bp2->b_ops = bp1->b_ops;
        memcpy(bp2->b_addr, bp1->b_addr, XFS_LBSIZE(mp));
        if (xfs_sb_version_hascrc(&mp->m_sb)) {
@@ -1140,6 +1146,7 @@ xfs_attr3_leaf_create(
        if (error)
                return error;
        bp->b_ops = &xfs_attr3_leaf_buf_ops;
+       xfs_trans_buf_set_type(args->trans, bp, XFS_BLF_ATTR_LEAF_BUF);
        leaf = bp->b_addr;
        memset(leaf, 0, XFS_LBSIZE(mp));
 
index 0ca8d9a1fa035d57b416f74c16e28b547ccf8cfc..c7cca60a062a1ab1a45eb7f08632773e54d0a734 100644 (file)
@@ -37,6 +37,8 @@ struct xfs_attr3_rmt_hdr {
        ((bufsize) - (xfs_sb_version_hascrc(&(mp)->m_sb) ? \
                        sizeof(struct xfs_attr3_rmt_hdr) : 0))
 
+extern const struct xfs_buf_ops xfs_attr3_rmt_buf_ops;
+
 int xfs_attr_rmtval_get(struct xfs_da_args *args);
 int xfs_attr_rmtval_set(struct xfs_da_args *args);
 int xfs_attr_rmtval_remove(struct xfs_da_args *args);
index 09cab4ed1065474c7626c473ccccb3609dc22017..640adcfa4143eb0629c773b93294840b65e7361e 100644 (file)
@@ -50,6 +50,14 @@ extern kmem_zone_t   *xfs_buf_item_zone;
 #define XFS_BLF_AGI_BUF                (1<<8)
 #define XFS_BLF_DINO_BUF       (1<<9)
 #define XFS_BLF_SYMLINK_BUF    (1<<10)
+#define XFS_BLF_DIR_BLOCK_BUF  (1<<11)
+#define XFS_BLF_DIR_DATA_BUF   (1<<12)
+#define XFS_BLF_DIR_FREE_BUF   (1<<13)
+#define XFS_BLF_DIR_LEAF1_BUF  (1<<14)
+#define XFS_BLF_DIR_LEAFN_BUF  (1<<15)
+#define XFS_BLF_DA_NODE_BUF    (1<<16)
+#define XFS_BLF_ATTR_LEAF_BUF  (1<<17)
+#define XFS_BLF_ATTR_RMT_BUF   (1<<18)
 
 #define XFS_BLF_TYPE_MASK      \
                (XFS_BLF_UDQUOT_BUF | \
@@ -60,7 +68,15 @@ extern kmem_zone_t   *xfs_buf_item_zone;
                 XFS_BLF_AGFL_BUF | \
                 XFS_BLF_AGI_BUF | \
                 XFS_BLF_DINO_BUF | \
-                XFS_BLF_SYMLINK_BUF)
+                XFS_BLF_SYMLINK_BUF | \
+                XFS_BLF_DIR_BLOCK_BUF | \
+                XFS_BLF_DIR_DATA_BUF | \
+                XFS_BLF_DIR_FREE_BUF | \
+                XFS_BLF_DIR_LEAF1_BUF | \
+                XFS_BLF_DIR_LEAFN_BUF | \
+                XFS_BLF_DA_NODE_BUF | \
+                XFS_BLF_ATTR_LEAF_BUF | \
+                XFS_BLF_ATTR_RMT_BUF)
 
 #define        XFS_BLF_CHUNK           128
 #define        XFS_BLF_SHIFT           7
index 779ecdcdbe02f28a567f4127225e1fd142bd2fab..5aebd9bd44d10decebf11ffff44a4a322e8f6705 100644 (file)
@@ -292,7 +292,6 @@ const struct xfs_buf_ops xfs_da3_node_buf_ops = {
        .verify_write = xfs_da3_node_write_verify,
 };
 
-
 int
 xfs_da3_node_read(
        struct xfs_trans        *tp,
@@ -302,8 +301,35 @@ xfs_da3_node_read(
        struct xfs_buf          **bpp,
        int                     which_fork)
 {
-       return xfs_da_read_buf(tp, dp, bno, mappedbno, bpp,
+       int                     err;
+
+       err = xfs_da_read_buf(tp, dp, bno, mappedbno, bpp,
                                        which_fork, &xfs_da3_node_buf_ops);
+       if (!err && tp) {
+               struct xfs_da_blkinfo   *info = (*bpp)->b_addr;
+               int                     type;
+
+               switch (be16_to_cpu(info->magic)) {
+               case XFS_DA3_NODE_MAGIC:
+               case XFS_DA_NODE_MAGIC:
+                       type = XFS_BLF_DA_NODE_BUF;
+                       break;
+               case XFS_ATTR_LEAF_MAGIC:
+               case XFS_ATTR3_LEAF_MAGIC:
+                       type = XFS_BLF_ATTR_LEAF_BUF;
+                       break;
+               case XFS_DIR2_LEAFN_MAGIC:
+               case XFS_DIR3_LEAFN_MAGIC:
+                       type = XFS_BLF_DIR_LEAFN_BUF;
+                       break;
+               default:
+                       type = 0;
+                       ASSERT(0);
+                       break;
+               }
+               xfs_trans_buf_set_type(tp, *bpp, type);
+       }
+       return err;
 }
 
 /*========================================================================
@@ -334,6 +360,8 @@ xfs_da3_node_create(
        error = xfs_da_get_buf(tp, args->dp, blkno, -1, &bp, whichfork);
        if (error)
                return(error);
+       bp->b_ops = &xfs_da3_node_buf_ops;
+       xfs_trans_buf_set_type(tp, bp, XFS_BLF_DA_NODE_BUF);
        node = bp->b_addr;
 
        if (xfs_sb_version_hascrc(&mp->m_sb)) {
@@ -352,7 +380,6 @@ xfs_da3_node_create(
        xfs_trans_log_buf(tp, bp,
                XFS_DA_LOGRANGE(node, &node->hdr, xfs_da3_node_hdr_size(node)));
 
-       bp->b_ops = &xfs_da3_node_buf_ops;
        *bpp = bp;
        return(0);
 }
@@ -565,6 +592,12 @@ xfs_da3_root_split(
                btree = xfs_da3_node_tree_p(oldroot);
                size = (int)((char *)&btree[nodehdr.count] - (char *)oldroot);
                level = nodehdr.level;
+
+               /*
+                * we are about to copy oldroot to bp, so set up the type
+                * of bp while we know exactly what it will be.
+                */
+               xfs_trans_buf_set_type(tp, bp, XFS_BLF_DA_NODE_BUF);
        } else {
                struct xfs_dir3_icleaf_hdr leafhdr;
                struct xfs_dir2_leaf_entry *ents;
@@ -577,6 +610,12 @@ xfs_da3_root_split(
                       leafhdr.magic == XFS_DIR3_LEAFN_MAGIC);
                size = (int)((char *)&ents[leafhdr.count] - (char *)leaf);
                level = 0;
+
+               /*
+                * we are about to copy oldroot to bp, so set up the type
+                * of bp while we know exactly what it will be.
+                */
+               xfs_trans_buf_set_type(tp, bp, XFS_BLF_DIR_LEAFN_BUF);
        }
 
        /*
@@ -1092,6 +1131,7 @@ xfs_da3_root_join(
         */
        memcpy(root_blk->bp->b_addr, bp->b_addr, state->blocksize);
        root_blk->bp->b_ops = bp->b_ops;
+       xfs_trans_buf_copy_type(root_blk->bp, bp);
        if (oldroothdr.magic == XFS_DA3_NODE_MAGIC) {
                struct xfs_da3_blkinfo *da3 = root_blk->bp->b_addr;
                da3->blkno = cpu_to_be64(root_blk->bp->b_bn);
index 0e8182c5210b7a8c090d8d6f2218d51c36151441..6fb3371c63cf3db535ea84cd6d62c31445b8c4f2 100644 (file)
@@ -301,6 +301,8 @@ int xfs_da3_node_read(struct xfs_trans *tp, struct xfs_inode *dp,
                         xfs_dablk_t bno, xfs_daddr_t mappedbno,
                         struct xfs_buf **bpp, int which_fork);
 
+extern const struct xfs_buf_ops xfs_da3_node_buf_ops;
+
 /*
  * Utility routines.
  */
index d2e445f92ffb0fa189aff66c20ff3397e704f730..58816ecdbba5110a0a21537608327e053f7b4110 100644 (file)
@@ -132,20 +132,26 @@ xfs_dir3_block_read(
        struct xfs_buf          **bpp)
 {
        struct xfs_mount        *mp = dp->i_mount;
+       int                     err;
 
-       return xfs_da_read_buf(tp, dp, mp->m_dirdatablk, -1, bpp,
+       err = xfs_da_read_buf(tp, dp, mp->m_dirdatablk, -1, bpp,
                                XFS_DATA_FORK, &xfs_dir3_block_buf_ops);
+       if (!err && tp)
+               xfs_trans_buf_set_type(tp, *bpp, XFS_BLF_DIR_BLOCK_BUF);
+       return err;
 }
 
 static void
 xfs_dir3_block_init(
        struct xfs_mount        *mp,
+       struct xfs_trans        *tp,
        struct xfs_buf          *bp,
        struct xfs_inode        *dp)
 {
        struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr;
 
        bp->b_ops = &xfs_dir3_block_buf_ops;
+       xfs_trans_buf_set_type(tp, bp, XFS_BLF_DIR_BLOCK_BUF);
 
        if (xfs_sb_version_hascrc(&mp->m_sb)) {
                memset(hdr3, 0, sizeof(*hdr3));
@@ -1080,7 +1086,7 @@ xfs_dir2_leaf_to_block(
        /*
         * Start converting it to block form.
         */
-       xfs_dir3_block_init(mp, dbp, dp);
+       xfs_dir3_block_init(mp, tp, dbp, dp);
 
        needlog = 1;
        needscan = 0;
@@ -1209,7 +1215,7 @@ xfs_dir2_sf_to_block(
                kmem_free(sfp);
                return error;
        }
-       xfs_dir3_block_init(mp, bp, dp);
+       xfs_dir3_block_init(mp, tp, bp, dp);
        hdr = bp->b_addr;
 
        /*
index 78320df3743f66ace56ba3d0913861cc21e3ab09..5e0c711f9af3f5f76fa163c7b22c699248a74b57 100644 (file)
@@ -301,8 +301,13 @@ xfs_dir3_data_read(
        xfs_daddr_t             mapped_bno,
        struct xfs_buf          **bpp)
 {
-       return xfs_da_read_buf(tp, dp, bno, mapped_bno, bpp,
+       int                     err;
+
+       err = xfs_da_read_buf(tp, dp, bno, mapped_bno, bpp,
                                XFS_DATA_FORK, &xfs_dir3_data_buf_ops);
+       if (!err && tp)
+               xfs_trans_buf_set_type(tp, *bpp, XFS_BLF_DIR_DATA_BUF);
+       return err;
 }
 
 int
@@ -571,6 +576,7 @@ xfs_dir3_data_init(
        if (error)
                return error;
        bp->b_ops = &xfs_dir3_data_buf_ops;
+       xfs_trans_buf_set_type(tp, bp, XFS_BLF_DIR_DATA_BUF);
 
        /*
         * Initialize the header.
index 7352e41d2aaaf77f8b47fe92c1b1809063651ad4..84f4c9cfe95a09ffc0135b857b8fed8d152d8298 100644 (file)
@@ -279,7 +279,7 @@ xfs_dir3_leafn_write_verify(
        __write_verify(bp, XFS_DIR2_LEAFN_MAGIC);
 }
 
-static const struct xfs_buf_ops xfs_dir3_leaf1_buf_ops = {
+const struct xfs_buf_ops xfs_dir3_leaf1_buf_ops = {
        .verify_read = xfs_dir3_leaf1_read_verify,
        .verify_write = xfs_dir3_leaf1_write_verify,
 };
@@ -297,8 +297,13 @@ xfs_dir3_leaf_read(
        xfs_daddr_t             mappedbno,
        struct xfs_buf          **bpp)
 {
-       return xfs_da_read_buf(tp, dp, fbno, mappedbno, bpp,
+       int                     err;
+
+       err = xfs_da_read_buf(tp, dp, fbno, mappedbno, bpp,
                                XFS_DATA_FORK, &xfs_dir3_leaf1_buf_ops);
+       if (!err && tp)
+               xfs_trans_buf_set_type(tp, *bpp, XFS_BLF_DIR_LEAF1_BUF);
+       return err;
 }
 
 int
@@ -309,8 +314,13 @@ xfs_dir3_leafn_read(
        xfs_daddr_t             mappedbno,
        struct xfs_buf          **bpp)
 {
-       return xfs_da_read_buf(tp, dp, fbno, mappedbno, bpp,
+       int                     err;
+
+       err = xfs_da_read_buf(tp, dp, fbno, mappedbno, bpp,
                                XFS_DATA_FORK, &xfs_dir3_leafn_buf_ops);
+       if (!err && tp)
+               xfs_trans_buf_set_type(tp, *bpp, XFS_BLF_DIR_LEAFN_BUF);
+       return err;
 }
 
 /*
@@ -319,6 +329,7 @@ xfs_dir3_leafn_read(
 static void
 xfs_dir3_leaf_init(
        struct xfs_mount        *mp,
+       struct xfs_trans        *tp,
        struct xfs_buf          *bp,
        xfs_ino_t               owner,
        __uint16_t              type)
@@ -353,8 +364,11 @@ xfs_dir3_leaf_init(
                ltp = xfs_dir2_leaf_tail_p(mp, leaf);
                ltp->bestcount = 0;
                bp->b_ops = &xfs_dir3_leaf1_buf_ops;
-       } else
+               xfs_trans_buf_set_type(tp, bp, XFS_BLF_DIR_LEAF1_BUF);
+       } else {
                bp->b_ops = &xfs_dir3_leafn_buf_ops;
+               xfs_trans_buf_set_type(tp, bp, XFS_BLF_DIR_LEAFN_BUF);
+       }
 }
 
 int
@@ -379,7 +393,7 @@ xfs_dir3_leaf_get_buf(
        if (error)
                return error;
 
-       xfs_dir3_leaf_init(mp, bp, dp->i_ino, magic);
+       xfs_dir3_leaf_init(mp, tp, bp, dp->i_ino, magic);
        xfs_dir3_leaf_log_header(tp, bp);
        if (magic == XFS_DIR2_LEAF1_MAGIC)
                xfs_dir3_leaf_log_tail(tp, bp);
@@ -474,6 +488,7 @@ xfs_dir2_block_to_leaf(
         * Fix up the block header, make it a data block.
         */
        dbp->b_ops = &xfs_dir3_data_buf_ops;
+       xfs_trans_buf_set_type(tp, dbp, XFS_BLF_DIR_DATA_BUF);
        if (hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC))
                hdr->magic = cpu_to_be32(XFS_DIR2_DATA_MAGIC);
        else
@@ -2182,6 +2197,7 @@ xfs_dir2_node_to_leaf(
                xfs_dir3_leaf_compact(args, &leafhdr, lbp);
 
        lbp->b_ops = &xfs_dir3_leaf1_buf_ops;
+       xfs_trans_buf_set_type(tp, lbp, XFS_BLF_DIR_LEAF1_BUF);
        leafhdr.magic = (leafhdr.magic == XFS_DIR2_LEAFN_MAGIC)
                                        ? XFS_DIR2_LEAF1_MAGIC
                                        : XFS_DIR3_LEAF1_MAGIC;
index 122449b33f5e34bc3afa9dc606c1be87caf6eb1e..1806a22d55933e601806566fcefa3a09e2afde15 100644 (file)
@@ -147,7 +147,7 @@ xfs_dir3_free_write_verify(
        xfs_update_cksum(bp->b_addr, BBTOB(bp->b_length), XFS_DIR3_FREE_CRC_OFF);
 }
 
-static const struct xfs_buf_ops xfs_dir3_free_buf_ops = {
+const struct xfs_buf_ops xfs_dir3_free_buf_ops = {
        .verify_read = xfs_dir3_free_read_verify,
        .verify_write = xfs_dir3_free_write_verify,
 };
@@ -161,8 +161,15 @@ __xfs_dir3_free_read(
        xfs_daddr_t             mappedbno,
        struct xfs_buf          **bpp)
 {
-       return xfs_da_read_buf(tp, dp, fbno, mappedbno, bpp,
+       int                     err;
+
+       err = xfs_da_read_buf(tp, dp, fbno, mappedbno, bpp,
                                XFS_DATA_FORK, &xfs_dir3_free_buf_ops);
+
+       /* try read returns without an error or *bpp if it lands in a hole */
+       if (!err && tp && *bpp)
+               xfs_trans_buf_set_type(tp, *bpp, XFS_BLF_DIR_FREE_BUF);
+       return err;
 }
 
 int
@@ -249,6 +256,7 @@ xfs_dir3_free_get_buf(
        if (error)
                return error;
 
+       xfs_trans_buf_set_type(tp, bp, XFS_BLF_DIR_FREE_BUF);
        bp->b_ops = &xfs_dir3_free_buf_ops;
 
        /*
@@ -396,6 +404,7 @@ xfs_dir2_leaf_to_node(
        else
                leaf->hdr.info.magic = cpu_to_be16(XFS_DIR3_LEAFN_MAGIC);
        lbp->b_ops = &xfs_dir3_leafn_buf_ops;
+       xfs_trans_buf_set_type(tp, lbp, XFS_BLF_DIR_LEAFN_BUF);
        xfs_dir3_leaf_log_header(tp, lbp);
        xfs_dir3_leaf_check(mp, lbp);
        return 0;
@@ -811,6 +820,7 @@ xfs_dir2_leafn_lookup_for_entry(
                                                        (char *)curbp->b_addr);
                        state->extrablk.magic = XFS_DIR2_DATA_MAGIC;
                        curbp->b_ops = &xfs_dir3_data_buf_ops;
+                       xfs_trans_buf_set_type(tp, curbp, XFS_BLF_DIR_DATA_BUF);
                        if (cmp == XFS_CMP_EXACT)
                                return XFS_ERROR(EEXIST);
                }
@@ -825,6 +835,7 @@ xfs_dir2_leafn_lookup_for_entry(
                        state->extrablk.blkno = curdb;
                        state->extrablk.magic = XFS_DIR2_DATA_MAGIC;
                        curbp->b_ops = &xfs_dir3_data_buf_ops;
+                       xfs_trans_buf_set_type(tp, curbp, XFS_BLF_DIR_DATA_BUF);
                } else {
                        /* If the curbp is not the CI match block, drop it */
                        if (state->extrablk.bp != curbp)
index 932565d6ef2a85849a2547e9fbe5c956a3070923..7cf573c88aad5394f977b5b794026159f2248488 100644 (file)
@@ -49,6 +49,7 @@ extern int xfs_dir2_leaf_to_block(struct xfs_da_args *args,
 #endif
 
 extern const struct xfs_buf_ops xfs_dir3_data_buf_ops;
+extern const struct xfs_buf_ops xfs_dir3_free_buf_ops;
 
 extern int __xfs_dir3_data_check(struct xfs_inode *dp, struct xfs_buf *bp);
 extern int xfs_dir3_data_read(struct xfs_trans *tp, struct xfs_inode *dp,
@@ -77,6 +78,7 @@ extern void xfs_dir2_data_use_free(struct xfs_trans *tp, struct xfs_buf *bp,
                xfs_dir2_data_aoff_t len, int *needlogp, int *needscanp);
 
 /* xfs_dir2_leaf.c */
+extern const struct xfs_buf_ops xfs_dir3_leaf1_buf_ops;
 extern const struct xfs_buf_ops xfs_dir3_leafn_buf_ops;
 
 extern int xfs_dir3_leafn_read(struct xfs_trans *tp, struct xfs_inode *dp,
index d1292fd1112a6d103fcd74e1b659c07f933dcd27..00727bc4a9b0a3e27b7045119e2351a7cbb71a8b 100644 (file)
 #include "xfs_cksum.h"
 #include "xfs_trace.h"
 #include "xfs_icache.h"
+
+/* Need all the magic numbers and buffer ops structures from these headers */
 #include "xfs_symlink.h"
+#include "xfs_da_btree.h"
+#include "xfs_dir2_format.h"
+#include "xfs_dir2_priv.h"
+#include "xfs_attr_leaf.h"
+#include "xfs_attr_remote.h"
 
 STATIC int
 xlog_find_zeroed(
@@ -1860,81 +1867,30 @@ xlog_recover_do_inode_buffer(
 }
 
 /*
- * Perform a 'normal' buffer recovery.  Each logged region of the
- * buffer should be copied over the corresponding region in the
- * given buffer.  The bitmap in the buf log format structure indicates
- * where to place the logged data.
+ * Validate the recovered buffer is of the correct type and attach the
+ * appropriate buffer operations to them for writeback. Magic numbers are in a
+ * few places:
+ *     the first 16 bits of the buffer (inode buffer, dquot buffer),
+ *     the first 32 bits of the buffer (most blocks),
+ *     inside a struct xfs_da_blkinfo at the start of the buffer.
  */
-STATIC void
-xlog_recover_do_reg_buffer(
+static void
+xlog_recovery_validate_buf_type(
        struct xfs_mount        *mp,
-       xlog_recover_item_t     *item,
        struct xfs_buf          *bp,
        xfs_buf_log_format_t    *buf_f)
 {
-       int                     i;
-       int                     bit;
-       int                     nbits;
-       int                     error;
-
-       trace_xfs_log_recover_buf_reg_buf(mp->m_log, buf_f);
-
-       bit = 0;
-       i = 1;  /* 0 is the buf format structure */
-       while (1) {
-               bit = xfs_next_bit(buf_f->blf_data_map,
-                                  buf_f->blf_map_size, bit);
-               if (bit == -1)
-                       break;
-               nbits = xfs_contig_bits(buf_f->blf_data_map,
-                                       buf_f->blf_map_size, bit);
-               ASSERT(nbits > 0);
-               ASSERT(item->ri_buf[i].i_addr != NULL);
-               ASSERT(item->ri_buf[i].i_len % XFS_BLF_CHUNK == 0);
-               ASSERT(BBTOB(bp->b_io_length) >=
-                      ((uint)bit << XFS_BLF_SHIFT) + (nbits << XFS_BLF_SHIFT));
-
-               /*
-                * Do a sanity check if this is a dquot buffer. Just checking
-                * the first dquot in the buffer should do. XXXThis is
-                * probably a good thing to do for other buf types also.
-                */
-               error = 0;
-               if (buf_f->blf_flags &
-                  (XFS_BLF_UDQUOT_BUF|XFS_BLF_PDQUOT_BUF|XFS_BLF_GDQUOT_BUF)) {
-                       if (item->ri_buf[i].i_addr == NULL) {
-                               xfs_alert(mp,
-                                       "XFS: NULL dquot in %s.", __func__);
-                               goto next;
-                       }
-                       if (item->ri_buf[i].i_len < sizeof(xfs_disk_dquot_t)) {
-                               xfs_alert(mp,
-                                       "XFS: dquot too small (%d) in %s.",
-                                       item->ri_buf[i].i_len, __func__);
-                               goto next;
-                       }
-                       error = xfs_qm_dqcheck(mp, item->ri_buf[i].i_addr,
-                                              -1, 0, XFS_QMOPT_DOWARN,
-                                              "dquot_buf_recover");
-                       if (error)
-                               goto next;
-               }
-
-               memcpy(xfs_buf_offset(bp,
-                       (uint)bit << XFS_BLF_SHIFT),    /* dest */
-                       item->ri_buf[i].i_addr,         /* source */
-                       nbits<<XFS_BLF_SHIFT);          /* length */
- next:
-               i++;
-               bit += nbits;
-       }
-
-       /* Shouldn't be any more regions */
-       ASSERT(i == item->ri_total);
-
+       struct xfs_da_blkinfo   *info = bp->b_addr;
+       __uint32_t              magic32;
+       __uint16_t              magic16;
+       __uint16_t              magicda;
+
+       magic32 = be32_to_cpu(*(__be32 *)bp->b_addr);
+       magic16 = be16_to_cpu(*(__be16*)bp->b_addr);
+       magicda = be16_to_cpu(info->magic);
        switch (buf_f->blf_flags & XFS_BLF_TYPE_MASK) {
        case XFS_BLF_BTREE_BUF:
-               switch (be32_to_cpu(*(__be32 *)bp->b_addr)) {
+               switch (magic32) {
                case XFS_ABTB_CRC_MAGIC:
                case XFS_ABTC_CRC_MAGIC:
                case XFS_ABTB_MAGIC:
@@ -1956,7 +1912,7 @@ xlog_recover_do_reg_buffer(
                }
                break;
        case XFS_BLF_AGF_BUF:
-               if (*(__be32 *)bp->b_addr != cpu_to_be32(XFS_AGF_MAGIC)) {
+               if (magic32 != XFS_AGF_MAGIC) {
                        xfs_warn(mp, "Bad AGF block magic!");
                        ASSERT(0);
                        break;
@@ -1966,7 +1922,7 @@ xlog_recover_do_reg_buffer(
        case XFS_BLF_AGFL_BUF:
                if (!xfs_sb_version_hascrc(&mp->m_sb))
                        break;
-               if (*(__be32 *)bp->b_addr != cpu_to_be32(XFS_AGFL_MAGIC)) {
+               if (magic32 != XFS_AGFL_MAGIC) {
                        xfs_warn(mp, "Bad AGFL block magic!");
                        ASSERT(0);
                        break;
@@ -1974,7 +1930,7 @@ xlog_recover_do_reg_buffer(
                bp->b_ops = &xfs_agfl_buf_ops;
                break;
        case XFS_BLF_AGI_BUF:
-               if (*(__be32 *)bp->b_addr != cpu_to_be32(XFS_AGI_MAGIC)) {
+               if (magic32 != XFS_AGI_MAGIC) {
                        xfs_warn(mp, "Bad AGI block magic!");
                        ASSERT(0);
                        break;
@@ -1984,7 +1940,7 @@ xlog_recover_do_reg_buffer(
        case XFS_BLF_UDQUOT_BUF:
        case XFS_BLF_PDQUOT_BUF:
        case XFS_BLF_GDQUOT_BUF:
-               if (*(__be16 *)bp->b_addr != cpu_to_be16(XFS_DQUOT_MAGIC)) {
+               if (magic16 != XFS_DQUOT_MAGIC) {
                        xfs_warn(mp, "Bad DQUOT block magic!");
                        ASSERT(0);
                        break;
@@ -1996,7 +1952,7 @@ xlog_recover_do_reg_buffer(
                 * we get here with inode allocation buffers, not buffers that
                 * track unlinked list changes.
                 */
-               if (*(__be16 *)bp->b_addr != cpu_to_be16(XFS_DINODE_MAGIC)) {
+               if (magic16 != XFS_DINODE_MAGIC) {
                        xfs_warn(mp, "Bad INODE block magic!");
                        ASSERT(0);
                        break;
@@ -2004,18 +1960,168 @@ xlog_recover_do_reg_buffer(
                bp->b_ops = &xfs_inode_buf_ops;
                break;
        case XFS_BLF_SYMLINK_BUF:
-               if (*(__be32 *)bp->b_addr != cpu_to_be32(XFS_SYMLINK_MAGIC)) {
+               if (magic32 != XFS_SYMLINK_MAGIC) {
                        xfs_warn(mp, "Bad symlink block magic!");
                        ASSERT(0);
                        break;
                }
                bp->b_ops = &xfs_symlink_buf_ops;
                break;
+       case XFS_BLF_DIR_BLOCK_BUF:
+               if (magic32 != XFS_DIR2_BLOCK_MAGIC &&
+                   magic32 != XFS_DIR3_BLOCK_MAGIC) {
+                       xfs_warn(mp, "Bad dir block magic!");
+                       ASSERT(0);
+                       break;
+               }
+               bp->b_ops = &xfs_dir3_block_buf_ops;
+               break;
+       case XFS_BLF_DIR_DATA_BUF:
+               if (magic32 != XFS_DIR2_DATA_MAGIC &&
+                   magic32 != XFS_DIR3_DATA_MAGIC) {
+                       xfs_warn(mp, "Bad dir data magic!");
+                       ASSERT(0);
+                       break;
+               }
+               bp->b_ops = &xfs_dir3_data_buf_ops;
+               break;
+       case XFS_BLF_DIR_FREE_BUF:
+               if (magic32 != XFS_DIR2_FREE_MAGIC &&
+                   magic32 != XFS_DIR3_FREE_MAGIC) {
+                       xfs_warn(mp, "Bad dir3 free magic!");
+                       ASSERT(0);
+                       break;
+               }
+               bp->b_ops = &xfs_dir3_free_buf_ops;
+               break;
+       case XFS_BLF_DIR_LEAF1_BUF:
+               if (magicda != XFS_DIR2_LEAF1_MAGIC &&
+                   magicda != XFS_DIR3_LEAF1_MAGIC) {
+                       xfs_warn(mp, "Bad dir leaf1 magic!");
+                       ASSERT(0);
+                       break;
+               }
+               bp->b_ops = &xfs_dir3_leaf1_buf_ops;
+               break;
+       case XFS_BLF_DIR_LEAFN_BUF:
+               if (magicda != XFS_DIR2_LEAFN_MAGIC &&
+                   magicda != XFS_DIR3_LEAFN_MAGIC) {
+                       xfs_warn(mp, "Bad dir leafn magic!");
+                       ASSERT(0);
+                       break;
+               }
+               bp->b_ops = &xfs_dir3_leafn_buf_ops;
+               break;
+       case XFS_BLF_DA_NODE_BUF:
+               if (magicda != XFS_DA_NODE_MAGIC &&
+                   magicda != XFS_DA3_NODE_MAGIC) {
+                       xfs_warn(mp, "Bad da node magic!");
+                       ASSERT(0);
+                       break;
+               }
+               bp->b_ops = &xfs_da3_node_buf_ops;
+               break;
+       case XFS_BLF_ATTR_LEAF_BUF:
+               if (magicda != XFS_ATTR_LEAF_MAGIC &&
+                   magicda != XFS_ATTR3_LEAF_MAGIC) {
+                       xfs_warn(mp, "Bad attr leaf magic!");
+                       ASSERT(0);
+                       break;
+               }
+               bp->b_ops = &xfs_attr3_leaf_buf_ops;
+               break;
+       case XFS_BLF_ATTR_RMT_BUF:
+               if (!xfs_sb_version_hascrc(&mp->m_sb))
+                       break;
+               if (magicda != XFS_ATTR3_RMT_MAGIC) {
+                       xfs_warn(mp, "Bad attr remote magic!");
+                       ASSERT(0);
+                       break;
+               }
+               bp->b_ops = &xfs_attr3_rmt_buf_ops;
+               break;
        default:
                break;
        }
 }
 
+/*
+ * Perform a 'normal' buffer recovery.  Each logged region of the
+ * buffer should be copied over the corresponding region in the
+ * given buffer.  The bitmap in the buf log format structure indicates
+ * where to place the logged data.
+ */
+STATIC void
+xlog_recover_do_reg_buffer(
+       struct xfs_mount        *mp,
+       xlog_recover_item_t     *item,
+       struct xfs_buf          *bp,
+       xfs_buf_log_format_t    *buf_f)
+{
+       int                     i;
+       int                     bit;
+       int                     nbits;
+       int                     error;
+
+       trace_xfs_log_recover_buf_reg_buf(mp->m_log, buf_f);
+
+       bit = 0;
+       i = 1;  /* 0 is the buf format structure */
+       while (1) {
+               bit = xfs_next_bit(buf_f->blf_data_map,
+                                  buf_f->blf_map_size, bit);
+               if (bit == -1)
+                       break;
+               nbits = xfs_contig_bits(buf_f->blf_data_map,
+                                       buf_f->blf_map_size, bit);
+               ASSERT(nbits > 0);
+               ASSERT(item->ri_buf[i].i_addr != NULL);
+               ASSERT(item->ri_buf[i].i_len % XFS_BLF_CHUNK == 0);
+               ASSERT(BBTOB(bp->b_io_length) >=
+                      ((uint)bit << XFS_BLF_SHIFT) + (nbits << XFS_BLF_SHIFT));
+
+               /*
+                * Do a sanity check if this is a dquot buffer. Just checking
+                * the first dquot in the buffer should do. XXXThis is
+                * probably a good thing to do for other buf types also.
+                */
+               error = 0;
+               if (buf_f->blf_flags &
+                  (XFS_BLF_UDQUOT_BUF|XFS_BLF_PDQUOT_BUF|XFS_BLF_GDQUOT_BUF)) {
+                       if (item->ri_buf[i].i_addr == NULL) {
+                               xfs_alert(mp,
+                                       "XFS: NULL dquot in %s.", __func__);
+                               goto next;
+                       }
+                       if (item->ri_buf[i].i_len < sizeof(xfs_disk_dquot_t)) {
+                               xfs_alert(mp,
+                                       "XFS: dquot too small (%d) in %s.",
+                                       item->ri_buf[i].i_len, __func__);
+                               goto next;
+                       }
+                       error = xfs_qm_dqcheck(mp, item->ri_buf[i].i_addr,
+                                              -1, 0, XFS_QMOPT_DOWARN,
+                                              "dquot_buf_recover");
+                       if (error)
+                               goto next;
+               }
+
+               memcpy(xfs_buf_offset(bp,
+                       (uint)bit << XFS_BLF_SHIFT),    /* dest */
+                       item->ri_buf[i].i_addr,         /* source */
+                       nbits<<XFS_BLF_SHIFT);          /* length */
+ next:
+               i++;
+               bit += nbits;
+       }
+
+       /* Shouldn't be any more regions */
+       ASSERT(i == item->ri_total);
+
+       xlog_recovery_validate_buf_type(mp, bp, buf_f);
+
+}
+
 /*
  * Do some primitive error checking on ondisk dquot data structures.
  */
index 1b04fe59c60372172529a548bb9b6c427ec420c8..fa78a3f87c6e8c30aad2795dc8157c16af37aa43 100644 (file)
@@ -507,6 +507,8 @@ void                xfs_trans_dquot_buf(xfs_trans_t *, struct xfs_buf *, uint);
 void           xfs_trans_inode_alloc_buf(xfs_trans_t *, struct xfs_buf *);
 void           xfs_trans_buf_set_type(struct xfs_trans *, struct xfs_buf *,
                                       uint);
+void           xfs_trans_buf_copy_type(struct xfs_buf *dst_bp,
+                                       struct xfs_buf *src_bp);
 void           xfs_trans_ichgtime(struct xfs_trans *, struct xfs_inode *, int);
 void           xfs_trans_ijoin(struct xfs_trans *, struct xfs_inode *, uint);
 void           xfs_trans_log_buf(xfs_trans_t *, struct xfs_buf *, uint, uint);
index 8a0f6af512067fe968d09df919dc44cc249ca5c0..40871bf607f0304174ebe98ff9e0e24fa51ebb53 100644 (file)
@@ -768,6 +768,9 @@ xfs_trans_buf_set_type(
 {
        struct xfs_buf_log_item *bip = bp->b_fspriv;
 
+       if (!tp)
+               return;
+
        ASSERT(bp->b_transp == tp);
        ASSERT(bip != NULL);
        ASSERT(atomic_read(&bip->bli_refcount) > 0);
@@ -777,6 +780,20 @@ xfs_trans_buf_set_type(
        bip->__bli_format.blf_flags |= type;
 }
 
+void
+xfs_trans_buf_copy_type(
+       struct xfs_buf          *dst_bp,
+       struct xfs_buf          *src_bp)
+{
+       struct xfs_buf_log_item *sbip = src_bp->b_fspriv;
+       struct xfs_buf_log_item *dbip = dst_bp->b_fspriv;
+       uint                    type;
+
+       type = sbip->__bli_format.blf_flags & XFS_BLF_TYPE_MASK;
+       dbip->__bli_format.blf_flags &= ~XFS_BLF_TYPE_MASK;
+       dbip->__bli_format.blf_flags |= type;
+}
+
 /*
  * Similar to xfs_trans_inode_buf(), this marks the buffer as a cluster of
  * dquots. However, unlike in inode buffer recovery, dquot buffers get