xfs: add CRCs to attr leaf blocks
[firefly-linux-kernel-4.4.55.git] / fs / xfs / xfs_attr.c
index 7afef2810e412b76175f85442ac4f807901d14b2..e706875415922c03be70ad682951285079828196 100644 (file)
@@ -819,7 +819,7 @@ xfs_attr_inactive(xfs_inode_t *dp)
                error = 0;
                goto out;
        }
-       error = xfs_attr_root_inactive(&trans, dp);
+       error = xfs_attr3_root_inactive(&trans, dp);
        if (error)
                goto out;
 
@@ -905,7 +905,7 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)
         */
        dp = args->dp;
        args->blkno = 0;
-       error = xfs_attr_leaf_read(args->trans, args->dp, args->blkno, -1, &bp);
+       error = xfs_attr3_leaf_read(args->trans, args->dp, args->blkno, -1, &bp);
        if (error)
                return error;
 
@@ -913,14 +913,14 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)
         * Look up the given attribute in the leaf block.  Figure out if
         * the given flags produce an error or call for an atomic rename.
         */
-       retval = xfs_attr_leaf_lookup_int(bp, args);
+       retval = xfs_attr3_leaf_lookup_int(bp, args);
        if ((args->flags & ATTR_REPLACE) && (retval == ENOATTR)) {
                xfs_trans_brelse(args->trans, bp);
-               return(retval);
+               return retval;
        } else if (retval == EEXIST) {
                if (args->flags & ATTR_CREATE) {        /* pure create op */
                        xfs_trans_brelse(args->trans, bp);
-                       return(retval);
+                       return retval;
                }
 
                trace_xfs_attr_leaf_replace(args);
@@ -936,7 +936,7 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)
         * Add the attribute to the leaf block, transitioning to a Btree
         * if required.
         */
-       retval = xfs_attr_leaf_add(bp, args);
+       retval = xfs_attr3_leaf_add(bp, args);
        if (retval == ENOSPC) {
                /*
                 * Promote the attribute list to the Btree format, then
@@ -944,7 +944,7 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)
                 * can manage its own transactions.
                 */
                xfs_bmap_init(args->flist, args->firstblock);
-               error = xfs_attr_leaf_to_node(args);
+               error = xfs_attr3_leaf_to_node(args);
                if (!error) {
                        error = xfs_bmap_finish(&args->trans, args->flist,
                                                &committed);
@@ -1009,7 +1009,7 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)
                 * In a separate transaction, set the incomplete flag on the
                 * "old" attr and clear the incomplete flag on the "new" attr.
                 */
-               error = xfs_attr_leaf_flipflags(args);
+               error = xfs_attr3_leaf_flipflags(args);
                if (error)
                        return(error);
 
@@ -1031,19 +1031,19 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)
                 * Read in the block containing the "old" attr, then
                 * remove the "old" attr from that block (neat, huh!)
                 */
-               error = xfs_attr_leaf_read(args->trans, args->dp, args->blkno,
+               error = xfs_attr3_leaf_read(args->trans, args->dp, args->blkno,
                                           -1, &bp);
                if (error)
                        return error;
 
-               xfs_attr_leaf_remove(bp, args);
+               xfs_attr3_leaf_remove(bp, args);
 
                /*
                 * If the result is small enough, shrink it all into the inode.
                 */
                if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) {
                        xfs_bmap_init(args->flist, args->firstblock);
-                       error = xfs_attr_leaf_to_shortform(bp, args, forkoff);
+                       error = xfs_attr3_leaf_to_shortform(bp, args, forkoff);
                        /* bp is gone due to xfs_da_shrink_inode */
                        if (!error) {
                                error = xfs_bmap_finish(&args->trans,
@@ -1075,9 +1075,9 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)
                /*
                 * Added a "remote" value, just clear the incomplete flag.
                 */
-               error = xfs_attr_leaf_clearflag(args);
+               error = xfs_attr3_leaf_clearflag(args);
        }
-       return(error);
+       return error;
 }
 
 /*
@@ -1100,24 +1100,24 @@ xfs_attr_leaf_removename(xfs_da_args_t *args)
         */
        dp = args->dp;
        args->blkno = 0;
-       error = xfs_attr_leaf_read(args->trans, args->dp, args->blkno, -1, &bp);
+       error = xfs_attr3_leaf_read(args->trans, args->dp, args->blkno, -1, &bp);
        if (error)
                return error;
 
-       error = xfs_attr_leaf_lookup_int(bp, args);
+       error = xfs_attr3_leaf_lookup_int(bp, args);
        if (error == ENOATTR) {
                xfs_trans_brelse(args->trans, bp);
-               return(error);
+               return error;
        }
 
-       xfs_attr_leaf_remove(bp, args);
+       xfs_attr3_leaf_remove(bp, args);
 
        /*
         * If the result is small enough, shrink it all into the inode.
         */
        if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) {
                xfs_bmap_init(args->flist, args->firstblock);
-               error = xfs_attr_leaf_to_shortform(bp, args, forkoff);
+               error = xfs_attr3_leaf_to_shortform(bp, args, forkoff);
                /* bp is gone due to xfs_da_shrink_inode */
                if (!error) {
                        error = xfs_bmap_finish(&args->trans, args->flist,
@@ -1127,7 +1127,7 @@ xfs_attr_leaf_removename(xfs_da_args_t *args)
                        ASSERT(committed);
                        args->trans = NULL;
                        xfs_bmap_cancel(args->flist);
-                       return(error);
+                       return error;
                }
 
                /*
@@ -1137,7 +1137,7 @@ xfs_attr_leaf_removename(xfs_da_args_t *args)
                if (committed)
                        xfs_trans_ijoin(args->trans, dp, 0);
        }
-       return(0);
+       return 0;
 }
 
 /*
@@ -1155,21 +1155,21 @@ xfs_attr_leaf_get(xfs_da_args_t *args)
        trace_xfs_attr_leaf_get(args);
 
        args->blkno = 0;
-       error = xfs_attr_leaf_read(args->trans, args->dp, args->blkno, -1, &bp);
+       error = xfs_attr3_leaf_read(args->trans, args->dp, args->blkno, -1, &bp);
        if (error)
                return error;
 
-       error = xfs_attr_leaf_lookup_int(bp, args);
+       error = xfs_attr3_leaf_lookup_int(bp, args);
        if (error != EEXIST)  {
                xfs_trans_brelse(args->trans, bp);
-               return(error);
+               return error;
        }
-       error = xfs_attr_leaf_getvalue(bp, args);
+       error = xfs_attr3_leaf_getvalue(bp, args);
        xfs_trans_brelse(args->trans, bp);
        if (!error && (args->rmtblkno > 0) && !(args->flags & ATTR_KERNOVAL)) {
                error = xfs_attr_rmtval_get(args);
        }
-       return(error);
+       return error;
 }
 
 /*
@@ -1184,11 +1184,11 @@ xfs_attr_leaf_list(xfs_attr_list_context_t *context)
        trace_xfs_attr_leaf_list(context);
 
        context->cursor->blkno = 0;
-       error = xfs_attr_leaf_read(NULL, context->dp, 0, -1, &bp);
+       error = xfs_attr3_leaf_read(NULL, context->dp, 0, -1, &bp);
        if (error)
                return XFS_ERROR(error);
 
-       error = xfs_attr_leaf_list_int(bp, context);
+       error = xfs_attr3_leaf_list_int(bp, context);
        xfs_trans_brelse(NULL, bp);
        return XFS_ERROR(error);
 }
@@ -1257,7 +1257,7 @@ restart:
                args->rmtblkcnt = 0;
        }
 
-       retval = xfs_attr_leaf_add(blk->bp, state->args);
+       retval = xfs_attr3_leaf_add(blk->bp, state->args);
        if (retval == ENOSPC) {
                if (state->path.active == 1) {
                        /*
@@ -1267,7 +1267,7 @@ restart:
                         */
                        xfs_da_state_free(state);
                        xfs_bmap_init(args->flist, args->firstblock);
-                       error = xfs_attr_leaf_to_node(args);
+                       error = xfs_attr3_leaf_to_node(args);
                        if (!error) {
                                error = xfs_bmap_finish(&args->trans,
                                                        args->flist,
@@ -1369,7 +1369,7 @@ restart:
                 * In a separate transaction, set the incomplete flag on the
                 * "old" attr and clear the incomplete flag on the "new" attr.
                 */
-               error = xfs_attr_leaf_flipflags(args);
+               error = xfs_attr3_leaf_flipflags(args);
                if (error)
                        goto out;
 
@@ -1408,7 +1408,7 @@ restart:
                 */
                blk = &state->path.blk[ state->path.active-1 ];
                ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC);
-               error = xfs_attr_leaf_remove(blk->bp, args);
+               error = xfs_attr3_leaf_remove(blk->bp, args);
                xfs_da3_fixhashpath(state, &state->path);
 
                /*
@@ -1449,7 +1449,7 @@ restart:
                /*
                 * Added a "remote" value, just clear the incomplete flag.
                 */
-               error = xfs_attr_leaf_clearflag(args);
+               error = xfs_attr3_leaf_clearflag(args);
                if (error)
                        goto out;
        }
@@ -1523,7 +1523,7 @@ xfs_attr_node_removename(xfs_da_args_t *args)
                 * Mark the attribute as INCOMPLETE, then bunmapi() the
                 * remote value.
                 */
-               error = xfs_attr_leaf_setflag(args);
+               error = xfs_attr3_leaf_setflag(args);
                if (error)
                        goto out;
                error = xfs_attr_rmtval_remove(args);
@@ -1544,7 +1544,7 @@ xfs_attr_node_removename(xfs_da_args_t *args)
         */
        blk = &state->path.blk[ state->path.active-1 ];
        ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC);
-       retval = xfs_attr_leaf_remove(blk->bp, args);
+       retval = xfs_attr3_leaf_remove(blk->bp, args);
        xfs_da3_fixhashpath(state, &state->path);
 
        /*
@@ -1590,13 +1590,13 @@ xfs_attr_node_removename(xfs_da_args_t *args)
                ASSERT(state->path.blk[0].bp);
                state->path.blk[0].bp = NULL;
 
-               error = xfs_attr_leaf_read(args->trans, args->dp, 0, -1, &bp);
+               error = xfs_attr3_leaf_read(args->trans, args->dp, 0, -1, &bp);
                if (error)
                        goto out;
 
                if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) {
                        xfs_bmap_init(args->flist, args->firstblock);
-                       error = xfs_attr_leaf_to_shortform(bp, args, forkoff);
+                       error = xfs_attr3_leaf_to_shortform(bp, args, forkoff);
                        /* bp is gone due to xfs_da_shrink_inode */
                        if (!error) {
                                error = xfs_bmap_finish(&args->trans,
@@ -1768,7 +1768,7 @@ xfs_attr_node_get(xfs_da_args_t *args)
                /*
                 * Get the value, local or "remote"
                 */
-               retval = xfs_attr_leaf_getvalue(blk->bp, args);
+               retval = xfs_attr3_leaf_getvalue(blk->bp, args);
                if (!retval && (args->rmtblkno > 0)
                    && !(args->flags & ATTR_KERNOVAL)) {
                        retval = xfs_attr_rmtval_get(args);
@@ -1793,7 +1793,9 @@ xfs_attr_node_list(xfs_attr_list_context_t *context)
        attrlist_cursor_kern_t *cursor;
        xfs_attr_leafblock_t *leaf;
        xfs_da_intnode_t *node;
-       xfs_da_node_entry_t *btree;
+       struct xfs_attr3_icleaf_hdr leafhdr;
+       struct xfs_da3_icnode_hdr nodehdr;
+       struct xfs_da_node_entry *btree;
        int error, i;
        struct xfs_buf *bp;
 
@@ -1814,22 +1816,28 @@ xfs_attr_node_list(xfs_attr_list_context_t *context)
                if ((error != 0) && (error != EFSCORRUPTED))
                        return(error);
                if (bp) {
+                       struct xfs_attr_leaf_entry *entries;
+
                        node = bp->b_addr;
                        switch (be16_to_cpu(node->hdr.info.magic)) {
                        case XFS_DA_NODE_MAGIC:
+                       case XFS_DA3_NODE_MAGIC:
                                trace_xfs_attr_list_wrong_blk(context);
                                xfs_trans_brelse(NULL, bp);
                                bp = NULL;
                                break;
                        case XFS_ATTR_LEAF_MAGIC:
+                       case XFS_ATTR3_LEAF_MAGIC:
                                leaf = bp->b_addr;
-                               if (cursor->hashval > be32_to_cpu(leaf->entries[
-                                   be16_to_cpu(leaf->hdr.count)-1].hashval)) {
+                               xfs_attr3_leaf_hdr_from_disk(&leafhdr, leaf);
+                               entries = xfs_attr3_leaf_entryp(leaf);
+                               if (cursor->hashval > be32_to_cpu(
+                                               entries[leafhdr.count - 1].hashval)) {
                                        trace_xfs_attr_list_wrong_blk(context);
                                        xfs_trans_brelse(NULL, bp);
                                        bp = NULL;
-                               } else if (cursor->hashval <=
-                                            be32_to_cpu(leaf->entries[0].hashval)) {
+                               } else if (cursor->hashval <= be32_to_cpu(
+                                               entries[0].hashval)) {
                                        trace_xfs_attr_list_wrong_blk(context);
                                        xfs_trans_brelse(NULL, bp);
                                        bp = NULL;
@@ -1851,27 +1859,31 @@ xfs_attr_node_list(xfs_attr_list_context_t *context)
        if (bp == NULL) {
                cursor->blkno = 0;
                for (;;) {
+                       __uint16_t magic;
+
                        error = xfs_da3_node_read(NULL, context->dp,
                                                      cursor->blkno, -1, &bp,
                                                      XFS_ATTR_FORK);
                        if (error)
                                return(error);
                        node = bp->b_addr;
-                       if (node->hdr.info.magic ==
-                           cpu_to_be16(XFS_ATTR_LEAF_MAGIC))
+                       magic = be16_to_cpu(node->hdr.info.magic);
+                       if (magic == XFS_ATTR_LEAF_MAGIC ||
+                           magic == XFS_ATTR3_LEAF_MAGIC)
                                break;
-                       if (unlikely(node->hdr.info.magic !=
-                                    cpu_to_be16(XFS_DA_NODE_MAGIC))) {
+                       if (magic != XFS_DA_NODE_MAGIC &&
+                           magic != XFS_DA3_NODE_MAGIC) {
                                XFS_CORRUPTION_ERROR("xfs_attr_node_list(3)",
                                                     XFS_ERRLEVEL_LOW,
                                                     context->dp->i_mount,
                                                     node);
                                xfs_trans_brelse(NULL, bp);
-                               return(XFS_ERROR(EFSCORRUPTED));
+                               return XFS_ERROR(EFSCORRUPTED);
                        }
+
+                       xfs_da3_node_hdr_from_disk(&nodehdr, node);
                        btree = xfs_da3_node_tree_p(node);
-                       for (i = 0; i < be16_to_cpu(node->hdr.count);
-                                                               btree++, i++) {
+                       for (i = 0; i < nodehdr.count; btree++, i++) {
                                if (cursor->hashval
                                                <= be32_to_cpu(btree->hashval)) {
                                        cursor->blkno = be32_to_cpu(btree->before);
@@ -1880,9 +1892,9 @@ xfs_attr_node_list(xfs_attr_list_context_t *context)
                                        break;
                                }
                        }
-                       if (i == be16_to_cpu(node->hdr.count)) {
+                       if (i == nodehdr.count) {
                                xfs_trans_brelse(NULL, bp);
-                               return(0);
+                               return 0;
                        }
                        xfs_trans_brelse(NULL, bp);
                }
@@ -1896,22 +1908,23 @@ xfs_attr_node_list(xfs_attr_list_context_t *context)
         */
        for (;;) {
                leaf = bp->b_addr;
-               error = xfs_attr_leaf_list_int(bp, context);
+               error = xfs_attr3_leaf_list_int(bp, context);
                if (error) {
                        xfs_trans_brelse(NULL, bp);
                        return error;
                }
-               if (context->seen_enough || leaf->hdr.info.forw == 0)
+               xfs_attr3_leaf_hdr_from_disk(&leafhdr, leaf);
+               if (context->seen_enough || leafhdr.forw == 0)
                        break;
-               cursor->blkno = be32_to_cpu(leaf->hdr.info.forw);
+               cursor->blkno = leafhdr.forw;
                xfs_trans_brelse(NULL, bp);
-               error = xfs_attr_leaf_read(NULL, context->dp, cursor->blkno, -1,
+               error = xfs_attr3_leaf_read(NULL, context->dp, cursor->blkno, -1,
                                           &bp);
                if (error)
                        return error;
        }
        xfs_trans_brelse(NULL, bp);
-       return(0);
+       return 0;
 }