xfs: add CRC checking to dir2 data blocks
authorDave Chinner <dchinner@redhat.com>
Wed, 3 Apr 2013 05:11:22 +0000 (16:11 +1100)
committerBen Myers <bpm@sgi.com>
Sat, 27 Apr 2013 17:00:00 +0000 (12:00 -0500)
This addition follows the same pattern as the dir2 block CRCs.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Ben Myers <bpm@sgi.com>
Signed-off-by: Ben Myers <bpm@sgi.com>
fs/xfs/xfs_dir2_block.c
fs/xfs/xfs_dir2_data.c
fs/xfs/xfs_dir2_format.h
fs/xfs/xfs_dir2_leaf.c
fs/xfs/xfs_dir2_node.c
fs/xfs/xfs_dir2_priv.h
fs/xfs/xfs_file.c

index 79a3f1b..7ec87c2 100644 (file)
@@ -77,7 +77,7 @@ xfs_dir3_block_verify(
                if (hdr3->magic != cpu_to_be32(XFS_DIR2_BLOCK_MAGIC))
                        return false;
        }
-       if (__xfs_dir2_data_check(NULL, bp))
+       if (__xfs_dir3_data_check(NULL, bp))
                return false;
        return true;
 }
@@ -553,7 +553,7 @@ xfs_dir2_block_addname(
                xfs_dir2_data_log_header(tp, bp);
        xfs_dir2_block_log_tail(tp, bp);
        xfs_dir2_data_log_entry(tp, bp, dep);
-       xfs_dir2_data_check(dp, bp);
+       xfs_dir3_data_check(dp, bp);
        return 0;
 }
 
@@ -596,7 +596,7 @@ xfs_dir2_block_getdents(
         */
        wantoff = xfs_dir2_dataptr_to_off(mp, *offset);
        hdr = bp->b_addr;
-       xfs_dir2_data_check(dp, bp);
+       xfs_dir3_data_check(dp, bp);
        /*
         * Set up values for the loop.
         */
@@ -720,7 +720,7 @@ xfs_dir2_block_lookup(
        dp = args->dp;
        mp = dp->i_mount;
        hdr = bp->b_addr;
-       xfs_dir2_data_check(dp, bp);
+       xfs_dir3_data_check(dp, bp);
        btp = xfs_dir2_block_tail_p(mp, hdr);
        blp = xfs_dir2_block_leaf_p(btp);
        /*
@@ -771,7 +771,7 @@ xfs_dir2_block_lookup_int(
                return error;
 
        hdr = bp->b_addr;
-       xfs_dir2_data_check(dp, bp);
+       xfs_dir3_data_check(dp, bp);
        btp = xfs_dir2_block_tail_p(mp, hdr);
        blp = xfs_dir2_block_leaf_p(btp);
        /*
@@ -908,7 +908,7 @@ xfs_dir2_block_removename(
                xfs_dir2_data_freescan(mp, hdr, &needlog);
        if (needlog)
                xfs_dir2_data_log_header(tp, bp);
-       xfs_dir2_data_check(dp, bp);
+       xfs_dir3_data_check(dp, bp);
        /*
         * See if the size as a shortform is good enough.
         */
@@ -965,7 +965,7 @@ xfs_dir2_block_replace(
         */
        dep->inumber = cpu_to_be64(args->inumber);
        xfs_dir2_data_log_entry(args->trans, bp, dep);
-       xfs_dir2_data_check(dp, bp);
+       xfs_dir3_data_check(dp, bp);
        return 0;
 }
 
@@ -1046,12 +1046,14 @@ xfs_dir2_leaf_to_block(
         * Read the data block if we don't already have it, give up if it fails.
         */
        if (!dbp) {
-               error = xfs_dir2_data_read(tp, dp, mp->m_dirdatablk, -1, &dbp);
+               error = xfs_dir3_data_read(tp, dp, mp->m_dirdatablk, -1, &dbp);
                if (error)
                        return error;
        }
        hdr = dbp->b_addr;
-       ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC));
+       ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
+              hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC));
+
        /*
         * Size of the "leaf" area in the block.
         */
@@ -1329,6 +1331,6 @@ xfs_dir2_sf_to_block(
        ASSERT(needscan == 0);
        xfs_dir2_block_log_leaf(tp, bp, 0, be32_to_cpu(btp->count) - 1);
        xfs_dir2_block_log_tail(tp, bp);
-       xfs_dir2_data_check(dp, bp);
+       xfs_dir3_data_check(dp, bp);
        return 0;
 }
index 8484ec4..78320df 100644 (file)
@@ -31,6 +31,8 @@
 #include "xfs_dir2_format.h"
 #include "xfs_dir2_priv.h"
 #include "xfs_error.h"
+#include "xfs_buf_item.h"
+#include "xfs_cksum.h"
 
 STATIC xfs_dir2_data_free_t *
 xfs_dir2_data_freefind(xfs_dir2_data_hdr_t *hdr, xfs_dir2_data_unused_t *dup);
@@ -41,7 +43,7 @@ xfs_dir2_data_freefind(xfs_dir2_data_hdr_t *hdr, xfs_dir2_data_unused_t *dup);
  * Return 0 is the buffer is good, otherwise an error.
  */
 int
-__xfs_dir2_data_check(
+__xfs_dir3_data_check(
        struct xfs_inode        *dp,            /* incore inode pointer */
        struct xfs_buf          *bp)            /* data block's buffer */
 {
@@ -76,6 +78,7 @@ __xfs_dir2_data_check(
                lep = xfs_dir2_block_leaf_p(btp);
                endp = (char *)lep;
                break;
+       case cpu_to_be32(XFS_DIR3_DATA_MAGIC):
        case cpu_to_be32(XFS_DIR2_DATA_MAGIC):
                endp = (char *)hdr + mp->m_dirblksize;
                break;
@@ -189,21 +192,27 @@ __xfs_dir2_data_check(
        return 0;
 }
 
-static void
-xfs_dir2_data_verify(
+static bool
+xfs_dir3_data_verify(
        struct xfs_buf          *bp)
 {
        struct xfs_mount        *mp = bp->b_target->bt_mount;
-       struct xfs_dir2_data_hdr *hdr = bp->b_addr;
-       int                     block_ok = 0;
+       struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr;
 
-       block_ok = hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC);
-       block_ok = block_ok && __xfs_dir2_data_check(NULL, bp) == 0;
-
-       if (!block_ok) {
-               XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, hdr);
-               xfs_buf_ioerror(bp, EFSCORRUPTED);
+       if (xfs_sb_version_hascrc(&mp->m_sb)) {
+               if (hdr3->magic != cpu_to_be32(XFS_DIR3_DATA_MAGIC))
+                       return false;
+               if (!uuid_equal(&hdr3->uuid, &mp->m_sb.sb_uuid))
+                       return false;
+               if (be64_to_cpu(hdr3->blkno) != bp->b_bn)
+                       return false;
+       } else {
+               if (hdr3->magic != cpu_to_be32(XFS_DIR2_DATA_MAGIC))
+                       return false;
        }
+       if (__xfs_dir3_data_check(NULL, bp))
+               return false;
+       return true;
 }
 
 /*
@@ -212,7 +221,7 @@ xfs_dir2_data_verify(
  * format buffer or a data format buffer on readahead.
  */
 static void
-xfs_dir2_data_reada_verify(
+xfs_dir3_data_reada_verify(
        struct xfs_buf          *bp)
 {
        struct xfs_mount        *mp = bp->b_target->bt_mount;
@@ -225,7 +234,8 @@ xfs_dir2_data_reada_verify(
                bp->b_ops->verify_read(bp);
                return;
        case cpu_to_be32(XFS_DIR2_DATA_MAGIC):
-               xfs_dir2_data_verify(bp);
+       case cpu_to_be32(XFS_DIR3_DATA_MAGIC):
+               xfs_dir3_data_verify(bp);
                return;
        default:
                XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, hdr);
@@ -235,32 +245,56 @@ xfs_dir2_data_reada_verify(
 }
 
 static void
-xfs_dir2_data_read_verify(
+xfs_dir3_data_read_verify(
        struct xfs_buf  *bp)
 {
-       xfs_dir2_data_verify(bp);
+       struct xfs_mount        *mp = bp->b_target->bt_mount;
+
+       if ((xfs_sb_version_hascrc(&mp->m_sb) &&
+            !xfs_verify_cksum(bp->b_addr, BBTOB(bp->b_length),
+                                         XFS_DIR3_DATA_CRC_OFF)) ||
+           !xfs_dir3_data_verify(bp)) {
+               XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
+               xfs_buf_ioerror(bp, EFSCORRUPTED);
+       }
 }
 
 static void
-xfs_dir2_data_write_verify(
+xfs_dir3_data_write_verify(
        struct xfs_buf  *bp)
 {
-       xfs_dir2_data_verify(bp);
+       struct xfs_mount        *mp = bp->b_target->bt_mount;
+       struct xfs_buf_log_item *bip = bp->b_fspriv;
+       struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr;
+
+       if (!xfs_dir3_data_verify(bp)) {
+               XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
+               xfs_buf_ioerror(bp, EFSCORRUPTED);
+               return;
+       }
+
+       if (!xfs_sb_version_hascrc(&mp->m_sb))
+               return;
+
+       if (bip)
+               hdr3->lsn = cpu_to_be64(bip->bli_item.li_lsn);
+
+       xfs_update_cksum(bp->b_addr, BBTOB(bp->b_length), XFS_DIR3_DATA_CRC_OFF);
 }
 
-const struct xfs_buf_ops xfs_dir2_data_buf_ops = {
-       .verify_read = xfs_dir2_data_read_verify,
-       .verify_write = xfs_dir2_data_write_verify,
+const struct xfs_buf_ops xfs_dir3_data_buf_ops = {
+       .verify_read = xfs_dir3_data_read_verify,
+       .verify_write = xfs_dir3_data_write_verify,
 };
 
-static const struct xfs_buf_ops xfs_dir2_data_reada_buf_ops = {
-       .verify_read = xfs_dir2_data_reada_verify,
-       .verify_write = xfs_dir2_data_write_verify,
+static const struct xfs_buf_ops xfs_dir3_data_reada_buf_ops = {
+       .verify_read = xfs_dir3_data_reada_verify,
+       .verify_write = xfs_dir3_data_write_verify,
 };
 
 
 int
-xfs_dir2_data_read(
+xfs_dir3_data_read(
        struct xfs_trans        *tp,
        struct xfs_inode        *dp,
        xfs_dablk_t             bno,
@@ -268,18 +302,18 @@ xfs_dir2_data_read(
        struct xfs_buf          **bpp)
 {
        return xfs_da_read_buf(tp, dp, bno, mapped_bno, bpp,
-                               XFS_DATA_FORK, &xfs_dir2_data_buf_ops);
+                               XFS_DATA_FORK, &xfs_dir3_data_buf_ops);
 }
 
 int
-xfs_dir2_data_readahead(
+xfs_dir3_data_readahead(
        struct xfs_trans        *tp,
        struct xfs_inode        *dp,
        xfs_dablk_t             bno,
        xfs_daddr_t             mapped_bno)
 {
        return xfs_da_reada_buf(tp, dp, bno, mapped_bno,
-                               XFS_DATA_FORK, &xfs_dir2_data_reada_buf_ops);
+                               XFS_DATA_FORK, &xfs_dir3_data_reada_buf_ops);
 }
 
 /*
@@ -309,6 +343,7 @@ xfs_dir2_data_freefind(
         * one we're looking for it has to be exact.
         */
        ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
+              hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) ||
               hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) ||
               hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC));
        for (dfp = &bf[0], seenzero = matched = 0;
@@ -458,6 +493,7 @@ xfs_dir2_data_freescan(
        char                    *p;             /* current entry pointer */
 
        ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
+              hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) ||
               hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) ||
               hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC));
 
@@ -534,13 +570,12 @@ xfs_dir3_data_init(
                XFS_DATA_FORK);
        if (error)
                return error;
-       bp->b_ops = &xfs_dir2_data_buf_ops;
+       bp->b_ops = &xfs_dir3_data_buf_ops;
 
        /*
         * Initialize the header.
         */
        hdr = bp->b_addr;
-
        if (xfs_sb_version_hascrc(&mp->m_sb)) {
                struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr;
 
@@ -591,6 +626,7 @@ xfs_dir2_data_log_entry(
        xfs_dir2_data_hdr_t     *hdr = bp->b_addr;
 
        ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
+              hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) ||
               hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) ||
               hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC));
 
@@ -610,6 +646,7 @@ xfs_dir2_data_log_header(
        xfs_dir2_data_hdr_t     *hdr = bp->b_addr;
 
        ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
+              hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) ||
               hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) ||
               hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC));
 
@@ -628,6 +665,7 @@ xfs_dir2_data_log_unused(
        xfs_dir2_data_hdr_t     *hdr = bp->b_addr;
 
        ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
+              hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) ||
               hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) ||
               hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC));
 
@@ -675,7 +713,8 @@ xfs_dir2_data_make_free(
        /*
         * Figure out where the end of the data area is.
         */
-       if (hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC))
+       if (hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
+           hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC))
                endptr = (char *)hdr + mp->m_dirblksize;
        else {
                xfs_dir2_block_tail_t   *btp;   /* block tail */
@@ -857,6 +896,7 @@ xfs_dir2_data_use_free(
 
        hdr = bp->b_addr;
        ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
+              hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) ||
               hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) ||
               hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC));
        ASSERT(be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG);
index ec5044a..0ac0950 100644 (file)
@@ -283,7 +283,8 @@ struct xfs_dir3_data_hdr {
 static inline struct xfs_dir2_data_free *
 xfs_dir3_data_bestfree_p(struct xfs_dir2_data_hdr *hdr)
 {
-       if (hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)) {
+       if (hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) ||
+           hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)) {
                struct xfs_dir3_data_hdr *hdr3 = (struct xfs_dir3_data_hdr *)hdr;
                return hdr3->best_free;
        }
@@ -345,17 +346,6 @@ xfs_dir2_data_unused_tag_p(struct xfs_dir2_data_unused *dup)
                        be16_to_cpu(dup->length) - sizeof(__be16));
 }
 
-static inline struct xfs_dir2_data_unused *
-xfs_dir3_data_unused_p(struct xfs_dir2_data_hdr *hdr)
-{
-       if (hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)) {
-               return (struct xfs_dir2_data_unused *)
-                       ((char *)hdr + sizeof(struct xfs_dir3_data_hdr));
-       }
-       return (struct xfs_dir2_data_unused *)
-               ((char *)hdr + sizeof(struct xfs_dir2_data_hdr));
-}
-
 static inline size_t
 xfs_dir3_data_hdr_size(bool dir3)
 {
@@ -379,6 +369,13 @@ xfs_dir3_data_entry_p(struct xfs_dir2_data_hdr *hdr)
                ((char *)hdr + xfs_dir3_data_entry_offset(hdr));
 }
 
+static inline struct xfs_dir2_data_unused *
+xfs_dir3_data_unused_p(struct xfs_dir2_data_hdr *hdr)
+{
+       return (struct xfs_dir2_data_unused *)
+               ((char *)hdr + xfs_dir3_data_entry_offset(hdr));
+}
+
 /*
  * Offsets of . and .. in data space (always block 0)
  */
index 979735b..c7dca95 100644 (file)
@@ -149,7 +149,7 @@ xfs_dir2_block_to_leaf(
        int                     needlog;        /* need to log block header */
        int                     needscan;       /* need to rescan bestfree */
        xfs_trans_t             *tp;            /* transaction pointer */
-       struct xfs_dir2_data_free       *bf;
+       struct xfs_dir2_data_free *bf;
 
        trace_xfs_dir2_block_to_leaf(args);
 
@@ -175,7 +175,7 @@ xfs_dir2_block_to_leaf(
        ASSERT(lbp != NULL);
        leaf = lbp->b_addr;
        hdr = dbp->b_addr;
-       xfs_dir2_data_check(dp, dbp);
+       xfs_dir3_data_check(dp, dbp);
        btp = xfs_dir2_block_tail_p(mp, hdr);
        blp = xfs_dir2_block_leaf_p(btp);
        bf = xfs_dir3_data_bestfree_p(hdr);
@@ -204,8 +204,12 @@ xfs_dir2_block_to_leaf(
        /*
         * Fix up the block header, make it a data block.
         */
-       dbp->b_ops = &xfs_dir2_data_buf_ops;
-       hdr->magic = cpu_to_be32(XFS_DIR2_DATA_MAGIC);
+       dbp->b_ops = &xfs_dir3_data_buf_ops;
+       if (hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC))
+               hdr->magic = cpu_to_be32(XFS_DIR2_DATA_MAGIC);
+       else
+               hdr->magic = cpu_to_be32(XFS_DIR3_DATA_MAGIC);
+
        if (needscan)
                xfs_dir2_data_freescan(mp, hdr, &needlog);
        /*
@@ -221,7 +225,7 @@ xfs_dir2_block_to_leaf(
        if (needlog)
                xfs_dir2_data_log_header(tp, dbp);
        xfs_dir2_leaf_check(dp, lbp);
-       xfs_dir2_data_check(dp, dbp);
+       xfs_dir3_data_check(dp, dbp);
        xfs_dir2_leaf_log_bests(tp, lbp, 0, 0);
        return 0;
 }
@@ -385,6 +389,7 @@ xfs_dir2_leaf_addname(
        __be16                  *tagp;          /* end of data entry */
        xfs_trans_t             *tp;            /* transaction pointer */
        xfs_dir2_db_t           use_block;      /* data block number */
+       struct xfs_dir2_data_free *bf;          /* bestfree table */
 
        trace_xfs_dir2_leaf_addname(args);
 
@@ -568,14 +573,15 @@ xfs_dir2_leaf_addname(
                else
                        xfs_dir2_leaf_log_bests(tp, lbp, use_block, use_block);
                hdr = dbp->b_addr;
-               bestsp[use_block] = hdr->bestfree[0].length;
+               bf = xfs_dir3_data_bestfree_p(hdr);
+               bestsp[use_block] = bf[0].length;
                grown = 1;
        } else {
                /*
                 * Already had space in some data block.
                 * Just read that one in.
                 */
-               error = xfs_dir2_data_read(tp, dp,
+               error = xfs_dir3_data_read(tp, dp,
                                           xfs_dir2_db_to_da(mp, use_block),
                                           -1, &dbp);
                if (error) {
@@ -583,13 +589,14 @@ xfs_dir2_leaf_addname(
                        return error;
                }
                hdr = dbp->b_addr;
+               bf = xfs_dir3_data_bestfree_p(hdr);
                grown = 0;
        }
        /*
         * Point to the biggest freespace in our data block.
         */
        dup = (xfs_dir2_data_unused_t *)
-             ((char *)hdr + be16_to_cpu(hdr->bestfree[0].offset));
+             ((char *)hdr + be16_to_cpu(bf[0].offset));
        ASSERT(be16_to_cpu(dup->length) >= length);
        needscan = needlog = 0;
        /*
@@ -622,8 +629,8 @@ xfs_dir2_leaf_addname(
         * If the bests table needs to be changed, do it.
         * Log the change unless we've already done that.
         */
-       if (be16_to_cpu(bestsp[use_block]) != be16_to_cpu(hdr->bestfree[0].length)) {
-               bestsp[use_block] = hdr->bestfree[0].length;
+       if (be16_to_cpu(bestsp[use_block]) != be16_to_cpu(bf[0].length)) {
+               bestsp[use_block] = bf[0].length;
                if (!grown)
                        xfs_dir2_leaf_log_bests(tp, lbp, use_block, use_block);
        }
@@ -643,7 +650,7 @@ xfs_dir2_leaf_addname(
        xfs_dir2_leaf_log_header(tp, lbp);
        xfs_dir2_leaf_log_ents(tp, lbp, lfloglow, lfloghigh);
        xfs_dir2_leaf_check(dp, lbp);
-       xfs_dir2_data_check(dp, dbp);
+       xfs_dir3_data_check(dp, dbp);
        return 0;
 }
 
@@ -967,7 +974,7 @@ xfs_dir2_leaf_readbuf(
         * Read the directory block starting at the first mapping.
         */
        mip->curdb = xfs_dir2_da_to_db(mp, map->br_startoff);
-       error = xfs_dir2_data_read(NULL, dp, map->br_startoff,
+       error = xfs_dir3_data_read(NULL, dp, map->br_startoff,
                        map->br_blockcount >= mp->m_dirblkfsbs ?
                            XFS_FSB_TO_DADDR(mp, map->br_startblock) : -1, &bp);
 
@@ -996,7 +1003,7 @@ xfs_dir2_leaf_readbuf(
                 */
                if (i > mip->ra_current &&
                    map[mip->ra_index].br_blockcount >= mp->m_dirblkfsbs) {
-                       xfs_dir2_data_readahead(NULL, dp,
+                       xfs_dir3_data_readahead(NULL, dp,
                                map[mip->ra_index].br_startoff + mip->ra_offset,
                                XFS_FSB_TO_DADDR(mp,
                                        map[mip->ra_index].br_startblock +
@@ -1009,7 +1016,7 @@ xfs_dir2_leaf_readbuf(
                 * use our mapping, but this is a very rare case.
                 */
                else if (i > mip->ra_current) {
-                       xfs_dir2_data_readahead(NULL, dp,
+                       xfs_dir3_data_readahead(NULL, dp,
                                        map[mip->ra_index].br_startoff +
                                                        mip->ra_offset, -1);
                        mip->ra_current = i;
@@ -1135,17 +1142,17 @@ xfs_dir2_leaf_getdents(
                                ASSERT(xfs_dir2_byte_to_db(mp, curoff) ==
                                       map_info->curdb);
                        hdr = bp->b_addr;
-                       xfs_dir2_data_check(dp, bp);
+                       xfs_dir3_data_check(dp, bp);
                        /*
                         * Find our position in the block.
                         */
-                       ptr = (char *)(hdr + 1);
+                       ptr = (char *)xfs_dir3_data_entry_p(hdr);
                        byteoff = xfs_dir2_byte_to_off(mp, curoff);
                        /*
                         * Skip past the header.
                         */
                        if (byteoff == 0)
-                               curoff += (uint)sizeof(*hdr);
+                               curoff += xfs_dir3_data_entry_offset(hdr);
                        /*
                         * Skip past entries until we reach our offset.
                         */
@@ -1481,7 +1488,7 @@ xfs_dir2_leaf_lookup_int(
                if (newdb != curdb) {
                        if (dbp)
                                xfs_trans_brelse(tp, dbp);
-                       error = xfs_dir2_data_read(tp, dp,
+                       error = xfs_dir3_data_read(tp, dp,
                                                   xfs_dir2_db_to_da(mp, newdb),
                                                   -1, &dbp);
                        if (error) {
@@ -1522,7 +1529,7 @@ xfs_dir2_leaf_lookup_int(
                ASSERT(cidb != -1);
                if (cidb != curdb) {
                        xfs_trans_brelse(tp, dbp);
-                       error = xfs_dir2_data_read(tp, dp,
+                       error = xfs_dir3_data_read(tp, dp,
                                                   xfs_dir2_db_to_da(mp, cidb),
                                                   -1, &dbp);
                        if (error) {
@@ -1568,6 +1575,7 @@ xfs_dir2_leaf_removename(
        int                     needscan;       /* need to rescan data frees */
        xfs_dir2_data_off_t     oldbest;        /* old value of best free */
        xfs_trans_t             *tp;            /* transaction pointer */
+       struct xfs_dir2_data_free *bf;          /* bestfree table */
 
        trace_xfs_dir2_leaf_removename(args);
 
@@ -1582,7 +1590,8 @@ xfs_dir2_leaf_removename(
        mp = dp->i_mount;
        leaf = lbp->b_addr;
        hdr = dbp->b_addr;
-       xfs_dir2_data_check(dp, dbp);
+       bf = xfs_dir3_data_bestfree_p(hdr);
+       xfs_dir3_data_check(dp, dbp);
        /*
         * Point to the leaf entry, use that to point to the data entry.
         */
@@ -1591,7 +1600,7 @@ xfs_dir2_leaf_removename(
        dep = (xfs_dir2_data_entry_t *)
              ((char *)hdr + xfs_dir2_dataptr_to_off(mp, be32_to_cpu(lep->address)));
        needscan = needlog = 0;
-       oldbest = be16_to_cpu(hdr->bestfree[0].length);
+       oldbest = be16_to_cpu(bf[0].length);
        ltp = xfs_dir2_leaf_tail_p(mp, leaf);
        bestsp = xfs_dir2_leaf_bests_p(ltp);
        ASSERT(be16_to_cpu(bestsp[db]) == oldbest);
@@ -1620,16 +1629,16 @@ xfs_dir2_leaf_removename(
         * If the longest freespace in the data block has changed,
         * put the new value in the bests table and log that.
         */
-       if (be16_to_cpu(hdr->bestfree[0].length) != oldbest) {
-               bestsp[db] = hdr->bestfree[0].length;
+       if (be16_to_cpu(bf[0].length) != oldbest) {
+               bestsp[db] = bf[0].length;
                xfs_dir2_leaf_log_bests(tp, lbp, db, db);
        }
-       xfs_dir2_data_check(dp, dbp);
+       xfs_dir3_data_check(dp, dbp);
        /*
         * If the data block is now empty then get rid of the data block.
         */
-       if (be16_to_cpu(hdr->bestfree[0].length) ==
-           mp->m_dirblksize - (uint)sizeof(*hdr)) {
+       if (be16_to_cpu(bf[0].length) ==
+                       mp->m_dirblksize - xfs_dir3_data_entry_offset(hdr)) {
                ASSERT(db != mp->m_dirdatablk);
                if ((error = xfs_dir2_shrink_inode(args, db, dbp))) {
                        /*
@@ -1809,7 +1818,7 @@ xfs_dir2_leaf_trim_data(
        /*
         * Read the offending data block.  We need its buffer.
         */
-       error = xfs_dir2_data_read(tp, dp, xfs_dir2_db_to_da(mp, db), -1, &dbp);
+       error = xfs_dir3_data_read(tp, dp, xfs_dir2_db_to_da(mp, db), -1, &dbp);
        if (error)
                return error;
 
@@ -1819,10 +1828,12 @@ xfs_dir2_leaf_trim_data(
 #ifdef DEBUG
 {
        struct xfs_dir2_data_hdr *hdr = dbp->b_addr;
+       struct xfs_dir2_data_free *bf = xfs_dir3_data_bestfree_p(hdr);
 
-       ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC));
-       ASSERT(be16_to_cpu(hdr->bestfree[0].length) ==
-              mp->m_dirblksize - (uint)sizeof(*hdr));
+       ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
+              hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC));
+       ASSERT(be16_to_cpu(bf[0].length) ==
+              mp->m_dirblksize - xfs_dir3_data_entry_offset(hdr));
        ASSERT(db == be32_to_cpu(ltp->bestcount) - 1);
 }
 #endif
index 0fe39b9..abf617d 100644 (file)
@@ -753,13 +753,13 @@ xfs_dir2_leafn_lookup_for_entry(
                                ASSERT(state->extravalid);
                                curbp = state->extrablk.bp;
                        } else {
-                               error = xfs_dir2_data_read(tp, dp,
+                               error = xfs_dir3_data_read(tp, dp,
                                                xfs_dir2_db_to_da(mp, newdb),
                                                -1, &curbp);
                                if (error)
                                        return error;
                        }
-                       xfs_dir2_data_check(dp, curbp);
+                       xfs_dir3_data_check(dp, curbp);
                        curdb = newdb;
                }
                /*
@@ -787,7 +787,7 @@ xfs_dir2_leafn_lookup_for_entry(
                        state->extrablk.index = (int)((char *)dep -
                                                        (char *)curbp->b_addr);
                        state->extrablk.magic = XFS_DIR2_DATA_MAGIC;
-                       curbp->b_ops = &xfs_dir2_data_buf_ops;
+                       curbp->b_ops = &xfs_dir3_data_buf_ops;
                        if (cmp == XFS_CMP_EXACT)
                                return XFS_ERROR(EEXIST);
                }
@@ -802,7 +802,7 @@ xfs_dir2_leafn_lookup_for_entry(
                        state->extrablk.index = -1;
                        state->extrablk.blkno = curdb;
                        state->extrablk.magic = XFS_DIR2_DATA_MAGIC;
-                       curbp->b_ops = &xfs_dir2_data_buf_ops;
+                       curbp->b_ops = &xfs_dir3_data_buf_ops;
                } else {
                        /* If the curbp is not the CI match block, drop it */
                        if (state->extrablk.bp != curbp)
@@ -1152,6 +1152,7 @@ xfs_dir2_leafn_remove(
        int                     needlog;        /* need to log data header */
        int                     needscan;       /* need to rescan data frees */
        xfs_trans_t             *tp;            /* transaction pointer */
+       struct xfs_dir2_data_free *bf;          /* bestfree table */
 
        trace_xfs_dir2_leafn_remove(args, index);
 
@@ -1186,7 +1187,8 @@ xfs_dir2_leafn_remove(
        dbp = dblk->bp;
        hdr = dbp->b_addr;
        dep = (xfs_dir2_data_entry_t *)((char *)hdr + off);
-       longest = be16_to_cpu(hdr->bestfree[0].length);
+       bf = xfs_dir3_data_bestfree_p(hdr);
+       longest = be16_to_cpu(bf[0].length);
        needlog = needscan = 0;
        xfs_dir2_data_make_free(tp, dbp, off,
                xfs_dir2_data_entsize(dep->namelen), &needlog, &needscan);
@@ -1198,12 +1200,12 @@ xfs_dir2_leafn_remove(
                xfs_dir2_data_freescan(mp, hdr, &needlog);
        if (needlog)
                xfs_dir2_data_log_header(tp, dbp);
-       xfs_dir2_data_check(dp, dbp);
+       xfs_dir3_data_check(dp, dbp);
        /*
         * If the longest data block freespace changes, need to update
         * the corresponding freeblock entry.
         */
-       if (longest < be16_to_cpu(hdr->bestfree[0].length)) {
+       if (longest < be16_to_cpu(bf[0].length)) {
                int             error;          /* error return value */
                struct xfs_buf  *fbp;           /* freeblock buffer */
                xfs_dir2_db_t   fdb;            /* freeblock block number */
@@ -1232,12 +1234,13 @@ xfs_dir2_leafn_remove(
                 * Calculate which entry we need to fix.
                 */
                findex = xfs_dir2_db_to_fdindex(mp, db);
-               longest = be16_to_cpu(hdr->bestfree[0].length);
+               longest = be16_to_cpu(bf[0].length);
                /*
                 * If the data block is now empty we can get rid of it
                 * (usually).
                 */
-               if (longest == mp->m_dirblksize - (uint)sizeof(*hdr)) {
+               if (longest == mp->m_dirblksize -
+                              xfs_dir3_data_entry_offset(hdr)) {
                        /*
                         * Try to punch out the data block.
                         */
@@ -1611,6 +1614,7 @@ xfs_dir2_node_addname_int(
        xfs_trans_t             *tp;            /* transaction pointer */
        __be16                  *bests;
        struct xfs_dir3_icfree_hdr freehdr;
+       struct xfs_dir2_data_free *bf;
 
        dp = args->dp;
        mp = dp->i_mount;
@@ -1868,7 +1872,8 @@ xfs_dir2_node_addname_int(
                 * change again.
                 */
                hdr = dbp->b_addr;
-               bests[findex] = hdr->bestfree[0].length;
+               bf = xfs_dir3_data_bestfree_p(hdr);
+               bests[findex] = bf[0].length;
                logfree = 1;
        }
        /*
@@ -1884,19 +1889,20 @@ xfs_dir2_node_addname_int(
                /*
                 * Read the data block in.
                 */
-               error = xfs_dir2_data_read(tp, dp, xfs_dir2_db_to_da(mp, dbno),
+               error = xfs_dir3_data_read(tp, dp, xfs_dir2_db_to_da(mp, dbno),
                                           -1, &dbp);
                if (error)
                        return error;
                hdr = dbp->b_addr;
+               bf = xfs_dir3_data_bestfree_p(hdr);
                logfree = 0;
        }
-       ASSERT(be16_to_cpu(hdr->bestfree[0].length) >= length);
+       ASSERT(be16_to_cpu(bf[0].length) >= length);
        /*
         * Point to the existing unused space.
         */
        dup = (xfs_dir2_data_unused_t *)
-             ((char *)hdr + be16_to_cpu(hdr->bestfree[0].offset));
+             ((char *)hdr + be16_to_cpu(bf[0].offset));
        needscan = needlog = 0;
        /*
         * Mark the first part of the unused space, inuse for us.
@@ -1928,8 +1934,8 @@ xfs_dir2_node_addname_int(
         * If the freespace entry is now wrong, update it.
         */
        bests = xfs_dir3_free_bests_p(mp, free); /* gcc is so stupid */
-       if (be16_to_cpu(bests[findex]) != be16_to_cpu(hdr->bestfree[0].length)) {
-               bests[findex] = hdr->bestfree[0].length;
+       if (be16_to_cpu(bests[findex]) != be16_to_cpu(bf[0].length)) {
+               bests[findex] = bf[0].length;
                logfree = 1;
        }
        /*
@@ -2119,7 +2125,8 @@ xfs_dir2_node_replace(
                 * Point to the data entry.
                 */
                hdr = state->extrablk.bp->b_addr;
-               ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC));
+               ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
+                      hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC));
                dep = (xfs_dir2_data_entry_t *)
                      ((char *)hdr +
                       xfs_dir2_dataptr_to_off(state->mp, be32_to_cpu(lep->address)));
index e6f2e0a..910e644 100644 (file)
@@ -43,17 +43,17 @@ extern int xfs_dir2_leaf_to_block(struct xfs_da_args *args,
 
 /* xfs_dir2_data.c */
 #ifdef DEBUG
-#define        xfs_dir2_data_check(dp,bp) __xfs_dir2_data_check(dp, bp);
+#define        xfs_dir3_data_check(dp,bp) __xfs_dir3_data_check(dp, bp);
 #else
-#define        xfs_dir2_data_check(dp,bp)
+#define        xfs_dir3_data_check(dp,bp)
 #endif
 
-extern const struct xfs_buf_ops xfs_dir2_data_buf_ops;
+extern const struct xfs_buf_ops xfs_dir3_data_buf_ops;
 
-extern int __xfs_dir2_data_check(struct xfs_inode *dp, struct xfs_buf *bp);
-extern int xfs_dir2_data_read(struct xfs_trans *tp, struct xfs_inode *dp,
+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,
                xfs_dablk_t bno, xfs_daddr_t mapped_bno, struct xfs_buf **bpp);
-extern int xfs_dir2_data_readahead(struct xfs_trans *tp, struct xfs_inode *dp,
+extern int xfs_dir3_data_readahead(struct xfs_trans *tp, struct xfs_inode *dp,
                xfs_dablk_t bno, xfs_daddr_t mapped_bno);
 
 extern struct xfs_dir2_data_free *
index f03bf1a..cf6eacd 100644 (file)
@@ -893,7 +893,7 @@ xfs_dir_open(
         */
        mode = xfs_ilock_map_shared(ip);
        if (ip->i_d.di_nextents > 0)
-               xfs_dir2_data_readahead(NULL, ip, 0, -1);
+               xfs_dir3_data_readahead(NULL, ip, 0, -1);
        xfs_iunlock(ip, mode);
        return 0;
 }