]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs: Add attibute set and helper functions
authorAllison Henderson <allison.henderson@oracle.com>
Thu, 15 Nov 2018 19:22:53 +0000 (13:22 -0600)
committerEric Sandeen <sandeen@redhat.com>
Thu, 15 Nov 2018 19:22:53 +0000 (13:22 -0600)
Source kernel commit: 2f3cd8091963810d85e6a5dd6ed1247e10e9e6f2

This patch adds xfs_attr_set_args and xfs_bmap_set_attrforkoff.
These sub-routines set the attributes specified in @args.
We will use this later for setting parent pointers as a deferred
attribute operation.

[dgc: remove attr fork init code from xfs_attr_set_args().]
[dgc: xfs_attr_try_sf_addname() NULLs args.trans after commit.]
[dgc: correct sf add error handling.]

Signed-off-by: Allison Henderson <allison.henderson@oracle.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Dave Chinner <david@fromorbit.com>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
libxfs/xfs_attr.c
libxfs/xfs_attr.h
libxfs/xfs_bmap.c
libxfs/xfs_bmap.h

index 8910d817e330fd4703fce3a892b43848cd4d11d4..ba6c8b9477751d110416fefb4c36e28296e1495d 100644 (file)
@@ -210,9 +210,80 @@ xfs_attr_try_sf_addname(
                xfs_trans_set_sync(args->trans);
 
        error2 = xfs_trans_commit(args->trans);
+       args->trans = NULL;
        return error ? error : error2;
 }
 
+/*
+ * Set the attribute specified in @args.
+ */
+int
+xfs_attr_set_args(
+       struct xfs_da_args      *args,
+       struct xfs_buf          **leaf_bp)
+{
+       struct xfs_inode        *dp = args->dp;
+       int                     error;
+
+       /*
+        * If the attribute list is non-existent or a shortform list,
+        * upgrade it to a single-leaf-block attribute list.
+        */
+       if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL ||
+           (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS &&
+            dp->i_d.di_anextents == 0)) {
+
+               /*
+                * Build initial attribute list (if required).
+                */
+               if (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS)
+                       xfs_attr_shortform_create(args);
+
+               /*
+                * Try to add the attr to the attribute list in the inode.
+                */
+               error = xfs_attr_try_sf_addname(dp, args);
+               if (error != -ENOSPC)
+                       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.
+                */
+               error = xfs_attr_shortform_to_leaf(args, leaf_bp);
+               if (error)
+                       return error;
+
+               /*
+                * 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);
+
+               error = xfs_defer_finish(&args->trans);
+               if (error)
+                       return error;
+
+               /*
+                * Commit the leaf transformation.  We'll need another
+                * (linked) transaction to add the new attribute to the
+                * leaf.
+                */
+               error = xfs_trans_roll_inode(&args->trans, dp);
+               if (error)
+                       return error;
+               xfs_trans_bjoin(args->trans, *leaf_bp);
+               *leaf_bp = NULL;
+       }
+
+       if (xfs_bmap_one_block(dp, XFS_ATTR_FORK))
+               error = xfs_attr_leaf_addname(args);
+       else
+               error = xfs_attr_node_addname(args);
+       return error;
+}
+
 int
 xfs_attr_set(
        struct xfs_inode        *dp,
@@ -277,73 +348,17 @@ xfs_attr_set(
        error = xfs_trans_reserve_quota_nblks(args.trans, dp, args.total, 0,
                                rsvd ? XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_FORCE_RES :
                                       XFS_QMOPT_RES_REGBLKS);
-       if (error) {
-               xfs_iunlock(dp, XFS_ILOCK_EXCL);
-               xfs_trans_cancel(args.trans);
-               return error;
-       }
+       if (error)
+               goto out_trans_cancel;
 
        xfs_trans_ijoin(args.trans, dp, 0);
-
-       /*
-        * If the attribute list is non-existent or a shortform list,
-        * upgrade it to a single-leaf-block attribute list.
-        */
-       if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL ||
-           (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS &&
-            dp->i_d.di_anextents == 0)) {
-
-               /*
-                * Build initial attribute list (if required).
-                */
-               if (dp->i_d.di_aformat == XFS_DINODE_FMT_EXTENTS)
-                       xfs_attr_shortform_create(&args);
-
-               /*
-                * Try to add the attr to the attribute list in
-                * the inode.
-                */
-               error = xfs_attr_try_sf_addname(dp, &args);
-               if (error != -ENOSPC) {
-                       xfs_iunlock(dp, XFS_ILOCK_EXCL);
-                       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.
-                */
-               error = xfs_attr_shortform_to_leaf(&args, &leaf_bp);
-               if (error)
-                       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);
-               error = xfs_defer_finish(&args.trans);
-               if (error)
-                       goto out;
-
-               /*
-                * Commit the leaf transformation.  We'll need another (linked)
-                * transaction to add the new attribute to the leaf, which
-                * means that we have to hold & join the leaf buffer here too.
-                */
-               error = xfs_trans_roll_inode(&args.trans, dp);
-               if (error)
-                       goto out;
-               xfs_trans_bjoin(args.trans, leaf_bp);
-               leaf_bp = NULL;
-       }
-
-       if (xfs_bmap_one_block(dp, XFS_ATTR_FORK))
-               error = xfs_attr_leaf_addname(&args);
-       else
-               error = xfs_attr_node_addname(&args);
+       error = xfs_attr_set_args(&args, &leaf_bp);
        if (error)
-               goto out;
+               goto out_release_leaf;
+       if (!args.trans) {
+               /* shortform attribute has already been committed */
+               goto out_unlock;
+       }
 
        /*
         * If this is a synchronous mount, make sure that the
@@ -360,17 +375,17 @@ xfs_attr_set(
         */
        xfs_trans_log_inode(args.trans, dp, XFS_ILOG_CORE);
        error = xfs_trans_commit(args.trans);
+out_unlock:
        xfs_iunlock(dp, XFS_ILOCK_EXCL);
-
        return error;
 
-out:
+out_release_leaf:
        if (leaf_bp)
                xfs_trans_brelse(args.trans, leaf_bp);
+out_trans_cancel:
        if (args.trans)
                xfs_trans_cancel(args.trans);
-       xfs_iunlock(dp, XFS_ILOCK_EXCL);
-       return error;
+       goto out_unlock;
 }
 
 /*
index 033ff8c478e2e5d1af9b4656422f02bb278c6dcc..f608ac8f306f9a135a4627e6c2a454bb4b4b9598 100644 (file)
@@ -140,6 +140,7 @@ int xfs_attr_get(struct xfs_inode *ip, const unsigned char *name,
                 unsigned char *value, int *valuelenp, int flags);
 int xfs_attr_set(struct xfs_inode *dp, const unsigned char *name,
                 unsigned char *value, int valuelen, int flags);
+int xfs_attr_set_args(struct xfs_da_args *args, struct xfs_buf **leaf_bp);
 int xfs_attr_remove(struct xfs_inode *dp, const unsigned char *name, int flags);
 int xfs_attr_list(struct xfs_inode *dp, char *buffer, int bufsize,
                  int flags, struct attrlist_cursor_kern *cursor);
index c17d3515cf936728e0c96660d86c94fcd55a77f6..73e58d73bcfdb26d3df83b9627f6d06de7a4a668 100644 (file)
@@ -1010,6 +1010,34 @@ xfs_bmap_add_attrfork_local(
        return -EFSCORRUPTED;
 }
 
+/* Set an inode attr fork off based on the format */
+int
+xfs_bmap_set_attrforkoff(
+       struct xfs_inode        *ip,
+       int                     size,
+       int                     *version)
+{
+       switch (ip->i_d.di_format) {
+       case XFS_DINODE_FMT_DEV:
+               ip->i_d.di_forkoff = roundup(sizeof(xfs_dev_t), 8) >> 3;
+               break;
+       case XFS_DINODE_FMT_LOCAL:
+       case XFS_DINODE_FMT_EXTENTS:
+       case XFS_DINODE_FMT_BTREE:
+               ip->i_d.di_forkoff = xfs_attr_shortform_bytesfit(ip, size);
+               if (!ip->i_d.di_forkoff)
+                       ip->i_d.di_forkoff = xfs_default_attroffset(ip) >> 3;
+               else if ((ip->i_mount->m_flags & XFS_MOUNT_ATTR2) && version)
+                       *version = 2;
+               break;
+       default:
+               ASSERT(0);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
 /*
  * Convert inode from non-attributed to attributed.
  * Must not be in a transaction, ip must not be locked.
@@ -1061,26 +1089,9 @@ xfs_bmap_add_attrfork(
 
        xfs_trans_ijoin(tp, ip, 0);
        xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
-
-       switch (ip->i_d.di_format) {
-       case XFS_DINODE_FMT_DEV:
-               ip->i_d.di_forkoff = roundup(sizeof(xfs_dev_t), 8) >> 3;
-               break;
-       case XFS_DINODE_FMT_LOCAL:
-       case XFS_DINODE_FMT_EXTENTS:
-       case XFS_DINODE_FMT_BTREE:
-               ip->i_d.di_forkoff = xfs_attr_shortform_bytesfit(ip, size);
-               if (!ip->i_d.di_forkoff)
-                       ip->i_d.di_forkoff = xfs_default_attroffset(ip) >> 3;
-               else if (mp->m_flags & XFS_MOUNT_ATTR2)
-                       version = 2;
-               break;
-       default:
-               ASSERT(0);
-               error = -EINVAL;
+       error = xfs_bmap_set_attrforkoff(ip, size, &version);
+       if (error)
                goto trans_cancel;
-       }
-
        ASSERT(ip->i_afp == NULL);
        ip->i_afp = kmem_zone_zalloc(xfs_ifork_zone, KM_SLEEP);
        ip->i_afp->if_flags = XFS_IFEXTENTS;
index b6e9b639e731a1fafd1116b9decb22872dc765af..488dc8860fd7c551b02e21eeae3462b96e268eb8 100644 (file)
@@ -183,6 +183,7 @@ void        xfs_trim_extent(struct xfs_bmbt_irec *irec, xfs_fileoff_t bno,
                xfs_filblks_t len);
 void   xfs_trim_extent_eof(struct xfs_bmbt_irec *, struct xfs_inode *);
 int    xfs_bmap_add_attrfork(struct xfs_inode *ip, int size, int rsvd);
+int    xfs_bmap_set_attrforkoff(struct xfs_inode *ip, int size, int *version);
 void   xfs_bmap_local_to_extents_empty(struct xfs_inode *ip, int whichfork);
 void   __xfs_bmap_add_free(struct xfs_trans *tp, xfs_fsblock_t bno,
                xfs_filblks_t len, struct xfs_owner_info *oinfo,