]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blobdiff - libxfs/xfs_attr.c
xfs: Add helper function xfs_attr_try_sf_addname
[thirdparty/xfsprogs-dev.git] / libxfs / xfs_attr.c
index 0002c3ed82dd9badf588c422ac64d8f359459251..8910d817e330fd4703fce3a892b43848cd4d11d4 100644 (file)
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (c) 2000-2005 Silicon Graphics, Inc.
  * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 #include "libxfs_priv.h"
 #include "xfs_fs.h"
@@ -198,6 +186,33 @@ xfs_attr_calc_size(
        return nblks;
 }
 
+STATIC int
+xfs_attr_try_sf_addname(
+       struct xfs_inode        *dp,
+       struct xfs_da_args      *args)
+{
+
+       struct xfs_mount        *mp = dp->i_mount;
+       int                     error, error2;
+
+       error = xfs_attr_shortform_addname(args);
+       if (error == -ENOSPC)
+               return error;
+
+       /*
+        * Commit the shortform mods, and we're done.
+        * NOTE: this is also the error path (EEXIST, etc).
+        */
+       if (!error && (args->flags & ATTR_KERNOTIME) == 0)
+               xfs_trans_ichgtime(args->trans, dp, XFS_ICHGTIME_CHG);
+
+       if (mp->m_flags & XFS_MOUNT_WSYNC)
+               xfs_trans_set_sync(args->trans);
+
+       error2 = xfs_trans_commit(args->trans);
+       return error ? error : error2;
+}
+
 int
 xfs_attr_set(
        struct xfs_inode        *dp,
@@ -209,11 +224,9 @@ xfs_attr_set(
        struct xfs_mount        *mp = dp->i_mount;
        struct xfs_buf          *leaf_bp = NULL;
        struct xfs_da_args      args;
-       struct xfs_defer_ops    dfops;
        struct xfs_trans_res    tres;
-       xfs_fsblock_t           firstblock;
        int                     rsvd = (flags & ATTR_ROOT) != 0;
-       int                     error, err2, local;
+       int                     error, local;
 
        XFS_STATS_INC(mp, xs_attr_set);
 
@@ -226,12 +239,10 @@ xfs_attr_set(
 
        args.value = value;
        args.valuelen = valuelen;
-       args.firstblock = &firstblock;
-       args.dfops = &dfops;
        args.op_flags = XFS_DA_OP_ADDNAME | XFS_DA_OP_OKNOENT;
        args.total = xfs_attr_calc_size(&args, &local);
 
-       error = xfs_qm_dqattach(dp, 0);
+       error = xfs_qm_dqattach(dp);
        if (error)
                return error;
 
@@ -292,51 +303,28 @@ xfs_attr_set(
                 * Try to add the attr to the attribute list in
                 * the inode.
                 */
-               error = xfs_attr_shortform_addname(&args);
+               error = xfs_attr_try_sf_addname(dp, &args);
                if (error != -ENOSPC) {
-                       /*
-                        * Commit the shortform mods, and we're done.
-                        * NOTE: this is also the error path (EEXIST, etc).
-                        */
-                       ASSERT(args.trans != NULL);
-
-                       /*
-                        * If this is a synchronous mount, make sure that
-                        * the transaction goes to disk before returning
-                        * to the user.
-                        */
-                       if (mp->m_flags & XFS_MOUNT_WSYNC)
-                               xfs_trans_set_sync(args.trans);
-
-                       if (!error && (flags & ATTR_KERNOTIME) == 0) {
-                               xfs_trans_ichgtime(args.trans, dp,
-                                                       XFS_ICHGTIME_CHG);
-                       }
-                       err2 = xfs_trans_commit(args.trans);
                        xfs_iunlock(dp, XFS_ILOCK_EXCL);
-
-                       return error ? error : err2;
+                       return error;
                }
 
                /*
                 * It won't fit in the shortform, transform to a leaf block.
                 * GROT: another possible req'mt for a double-split btree op.
                 */
-               xfs_defer_init(args.dfops, args.firstblock);
                error = xfs_attr_shortform_to_leaf(&args, &leaf_bp);
                if (error)
-                       goto out_defer_cancel;
+                       goto out;
                /*
                 * Prevent the leaf buffer from being unlocked so that a
                 * concurrent AIL push cannot grab the half-baked leaf
                 * buffer and run into problems with the write verifier.
                 */
                xfs_trans_bhold(args.trans, leaf_bp);
-               xfs_defer_bjoin(args.dfops, leaf_bp);
-               xfs_defer_ijoin(args.dfops, dp);
-               error = xfs_defer_finish(&args.trans, args.dfops);
+               error = xfs_defer_finish(&args.trans);
                if (error)
-                       goto out_defer_cancel;
+                       goto out;
 
                /*
                 * Commit the leaf transformation.  We'll need another (linked)
@@ -376,8 +364,6 @@ xfs_attr_set(
 
        return error;
 
-out_defer_cancel:
-       xfs_defer_cancel(&dfops);
 out:
        if (leaf_bp)
                xfs_trans_brelse(args.trans, leaf_bp);
@@ -399,8 +385,6 @@ xfs_attr_remove(
 {
        struct xfs_mount        *mp = dp->i_mount;
        struct xfs_da_args      args;
-       struct xfs_defer_ops    dfops;
-       xfs_fsblock_t           firstblock;
        int                     error;
 
        XFS_STATS_INC(mp, xs_attr_remove);
@@ -412,9 +396,6 @@ xfs_attr_remove(
        if (error)
                return error;
 
-       args.firstblock = &firstblock;
-       args.dfops = &dfops;
-
        /*
         * we have no control over the attribute names that userspace passes us
         * to remove, so we have to allow the name lookup prior to attribute
@@ -422,7 +403,7 @@ xfs_attr_remove(
         */
        args.op_flags = XFS_DA_OP_OKNOENT;
 
-       error = xfs_qm_dqattach(dp, 0);
+       error = xfs_qm_dqattach(dp);
        if (error)
                return error;
 
@@ -543,11 +524,12 @@ xfs_attr_shortform_addname(xfs_da_args_t *args)
  * if bmap_one_block() says there is only one block (ie: no remote blks).
  */
 STATIC int
-xfs_attr_leaf_addname(xfs_da_args_t *args)
+xfs_attr_leaf_addname(
+       struct xfs_da_args      *args)
 {
-       xfs_inode_t *dp;
-       struct xfs_buf *bp;
-       int retval, error, forkoff;
+       struct xfs_inode        *dp;
+       struct xfs_buf          *bp;
+       int                     retval, error, forkoff;
 
        trace_xfs_attr_leaf_addname(args);
 
@@ -605,14 +587,12 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)
                 * Commit that transaction so that the node_addname() call
                 * can manage its own transactions.
                 */
-               xfs_defer_init(args->dfops, args->firstblock);
                error = xfs_attr3_leaf_to_node(args);
                if (error)
-                       goto out_defer_cancel;
-               xfs_defer_ijoin(args->dfops, dp);
-               error = xfs_defer_finish(&args->trans, args->dfops);
+                       return error;
+               error = xfs_defer_finish(&args->trans);
                if (error)
-                       goto out_defer_cancel;
+                       return error;
 
                /*
                 * Commit the current trans (including the inode) and start
@@ -694,15 +674,13 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)
                 * If the result is small enough, shrink it all into the inode.
                 */
                if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) {
-                       xfs_defer_init(args->dfops, args->firstblock);
                        error = xfs_attr3_leaf_to_shortform(bp, args, forkoff);
                        /* bp is gone due to xfs_da_shrink_inode */
                        if (error)
-                               goto out_defer_cancel;
-                       xfs_defer_ijoin(args->dfops, dp);
-                       error = xfs_defer_finish(&args->trans, args->dfops);
+                               return error;
+                       error = xfs_defer_finish(&args->trans);
                        if (error)
-                               goto out_defer_cancel;
+                               return error;
                }
 
                /*
@@ -717,9 +695,6 @@ xfs_attr_leaf_addname(xfs_da_args_t *args)
                error = xfs_attr3_leaf_clearflag(args);
        }
        return error;
-out_defer_cancel:
-       xfs_defer_cancel(args->dfops);
-       return error;
 }
 
 /*
@@ -729,11 +704,12 @@ out_defer_cancel:
  * if bmap_one_block() says there is only one block (ie: no remote blks).
  */
 STATIC int
-xfs_attr_leaf_removename(xfs_da_args_t *args)
+xfs_attr_leaf_removename(
+       struct xfs_da_args      *args)
 {
-       xfs_inode_t *dp;
-       struct xfs_buf *bp;
-       int error, forkoff;
+       struct xfs_inode        *dp;
+       struct xfs_buf          *bp;
+       int                     error, forkoff;
 
        trace_xfs_attr_leaf_removename(args);
 
@@ -758,20 +734,15 @@ xfs_attr_leaf_removename(xfs_da_args_t *args)
         * If the result is small enough, shrink it all into the inode.
         */
        if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) {
-               xfs_defer_init(args->dfops, args->firstblock);
                error = xfs_attr3_leaf_to_shortform(bp, args, forkoff);
                /* bp is gone due to xfs_da_shrink_inode */
                if (error)
-                       goto out_defer_cancel;
-               xfs_defer_ijoin(args->dfops, dp);
-               error = xfs_defer_finish(&args->trans, args->dfops);
+                       return error;
+               error = xfs_defer_finish(&args->trans);
                if (error)
-                       goto out_defer_cancel;
+                       return error;
        }
        return 0;
-out_defer_cancel:
-       xfs_defer_cancel(args->dfops);
-       return error;
 }
 
 /*
@@ -821,13 +792,14 @@ xfs_attr_leaf_get(xfs_da_args_t *args)
  * add a whole extra layer of confusion on top of that.
  */
 STATIC int
-xfs_attr_node_addname(xfs_da_args_t *args)
+xfs_attr_node_addname(
+       struct xfs_da_args      *args)
 {
-       xfs_da_state_t *state;
-       xfs_da_state_blk_t *blk;
-       xfs_inode_t *dp;
-       xfs_mount_t *mp;
-       int retval, error;
+       struct xfs_da_state     *state;
+       struct xfs_da_state_blk *blk;
+       struct xfs_inode        *dp;
+       struct xfs_mount        *mp;
+       int                     retval, error;
 
        trace_xfs_attr_node_addname(args);
 
@@ -886,14 +858,12 @@ restart:
                         */
                        xfs_da_state_free(state);
                        state = NULL;
-                       xfs_defer_init(args->dfops, args->firstblock);
                        error = xfs_attr3_leaf_to_node(args);
                        if (error)
-                               goto out_defer_cancel;
-                       xfs_defer_ijoin(args->dfops, dp);
-                       error = xfs_defer_finish(&args->trans, args->dfops);
+                               goto out;
+                       error = xfs_defer_finish(&args->trans);
                        if (error)
-                               goto out_defer_cancel;
+                               goto out;
 
                        /*
                         * Commit the node conversion and start the next
@@ -912,14 +882,12 @@ restart:
                 * in the index/blkno/rmtblkno/rmtblkcnt fields and
                 * in the index2/blkno2/rmtblkno2/rmtblkcnt2 fields.
                 */
-               xfs_defer_init(args->dfops, args->firstblock);
                error = xfs_da3_split(state);
                if (error)
-                       goto out_defer_cancel;
-               xfs_defer_ijoin(args->dfops, dp);
-               error = xfs_defer_finish(&args->trans, args->dfops);
+                       goto out;
+               error = xfs_defer_finish(&args->trans);
                if (error)
-                       goto out_defer_cancel;
+                       goto out;
        } else {
                /*
                 * Addition succeeded, update Btree hashvals.
@@ -1010,14 +978,12 @@ restart:
                 * Check to see if the tree needs to be collapsed.
                 */
                if (retval && (state->path.active > 1)) {
-                       xfs_defer_init(args->dfops, args->firstblock);
                        error = xfs_da3_join(state);
                        if (error)
-                               goto out_defer_cancel;
-                       xfs_defer_ijoin(args->dfops, dp);
-                       error = xfs_defer_finish(&args->trans, args->dfops);
+                               goto out;
+                       error = xfs_defer_finish(&args->trans);
                        if (error)
-                               goto out_defer_cancel;
+                               goto out;
                }
 
                /*
@@ -1043,9 +1009,6 @@ out:
        if (error)
                return error;
        return retval;
-out_defer_cancel:
-       xfs_defer_cancel(args->dfops);
-       goto out;
 }
 
 /*
@@ -1056,13 +1019,14 @@ out_defer_cancel:
  * the root node (a special case of an intermediate node).
  */
 STATIC int
-xfs_attr_node_removename(xfs_da_args_t *args)
+xfs_attr_node_removename(
+       struct xfs_da_args      *args)
 {
-       xfs_da_state_t *state;
-       xfs_da_state_blk_t *blk;
-       xfs_inode_t *dp;
-       struct xfs_buf *bp;
-       int retval, error, forkoff;
+       struct xfs_da_state     *state;
+       struct xfs_da_state_blk *blk;
+       struct xfs_inode        *dp;
+       struct xfs_buf          *bp;
+       int                     retval, error, forkoff;
 
        trace_xfs_attr_node_removename(args);
 
@@ -1134,14 +1098,12 @@ xfs_attr_node_removename(xfs_da_args_t *args)
         * Check to see if the tree needs to be collapsed.
         */
        if (retval && (state->path.active > 1)) {
-               xfs_defer_init(args->dfops, args->firstblock);
                error = xfs_da3_join(state);
                if (error)
-                       goto out_defer_cancel;
-               xfs_defer_ijoin(args->dfops, dp);
-               error = xfs_defer_finish(&args->trans, args->dfops);
+                       goto out;
+               error = xfs_defer_finish(&args->trans);
                if (error)
-                       goto out_defer_cancel;
+                       goto out;
                /*
                 * Commit the Btree join operation and start a new trans.
                 */
@@ -1166,15 +1128,13 @@ xfs_attr_node_removename(xfs_da_args_t *args)
                        goto out;
 
                if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) {
-                       xfs_defer_init(args->dfops, args->firstblock);
                        error = xfs_attr3_leaf_to_shortform(bp, args, forkoff);
                        /* bp is gone due to xfs_da_shrink_inode */
                        if (error)
-                               goto out_defer_cancel;
-                       xfs_defer_ijoin(args->dfops, dp);
-                       error = xfs_defer_finish(&args->trans, args->dfops);
+                               goto out;
+                       error = xfs_defer_finish(&args->trans);
                        if (error)
-                               goto out_defer_cancel;
+                               goto out;
                } else
                        xfs_trans_brelse(args->trans, bp);
        }
@@ -1183,9 +1143,6 @@ xfs_attr_node_removename(xfs_da_args_t *args)
 out:
        xfs_da_state_free(state);
        return error;
-out_defer_cancel:
-       xfs_defer_cancel(args->dfops);
-       goto out;
 }
 
 /*