All of lore.kernel.org
 help / color / mirror / Atom feed
From: Christoph Hellwig <hch@lst.de>
To: linux-xfs@vger.kernel.org
Cc: Allison Collins <allison.henderson@oracle.com>
Subject: [PATCH 06/33] xfs: merge xfs_attr_remove into xfs_attr_set
Date: Thu, 12 Dec 2019 11:54:06 +0100	[thread overview]
Message-ID: <20191212105433.1692-7-hch@lst.de> (raw)
In-Reply-To: <20191212105433.1692-1-hch@lst.de>

The Linux xattr and acl APIs use a single call for set an remove.  Modify
the high-level XFS API to match that and let xfs_attr_set handle removing
attributes as well.  With a little bit of reordering this removes a lot
of code.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 fs/xfs/libxfs/xfs_attr.c | 173 +++++++++++++--------------------------
 fs/xfs/libxfs/xfs_attr.h |   1 -
 fs/xfs/xfs_acl.c         |  31 +++----
 fs/xfs/xfs_ioctl.c       |   2 +-
 fs/xfs/xfs_xattr.c       |   6 +-
 5 files changed, 72 insertions(+), 141 deletions(-)

diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c
index 2368a1bfe7e8..1ac0d6f0560c 100644
--- a/fs/xfs/libxfs/xfs_attr.c
+++ b/fs/xfs/libxfs/xfs_attr.c
@@ -347,148 +347,92 @@ xfs_attr_set(
 	struct xfs_trans_res	tres;
 	int			rsvd = (flags & ATTR_ROOT) != 0;
 	int			error, local;
-
-	XFS_STATS_INC(mp, xs_attr_set);
+	unsigned int		total;
 
 	if (XFS_FORCED_SHUTDOWN(dp->i_mount))
 		return -EIO;
 
-	error = xfs_attr_args_init(&args, dp, name, flags);
-	if (error)
-		return error;
-
-	args.value = value;
-	args.valuelen = valuelen;
-	args.op_flags = XFS_DA_OP_ADDNAME | XFS_DA_OP_OKNOENT;
-	args.total = xfs_attr_calc_size(&args, &local);
-
 	error = xfs_qm_dqattach(dp);
 	if (error)
 		return error;
 
-	/*
-	 * If the inode doesn't have an attribute fork, add one.
-	 * (inode must not be locked when we call this routine)
-	 */
-	if (XFS_IFORK_Q(dp) == 0) {
-		int sf_size = sizeof(xfs_attr_sf_hdr_t) +
-			XFS_ATTR_SF_ENTSIZE_BYNAME(args.namelen, valuelen);
-
-		error = xfs_bmap_add_attrfork(dp, sf_size, rsvd);
-		if (error)
-			return error;
-	}
-
-	tres.tr_logres = M_RES(mp)->tr_attrsetm.tr_logres +
-			 M_RES(mp)->tr_attrsetrt.tr_logres * args.total;
-	tres.tr_logcount = XFS_ATTRSET_LOG_COUNT;
-	tres.tr_logflags = XFS_TRANS_PERM_LOG_RES;
-
-	/*
-	 * Root fork attributes can use reserved data blocks for this
-	 * operation if necessary
-	 */
-	error = xfs_trans_alloc(mp, &tres, args.total, 0,
-			rsvd ? XFS_TRANS_RESERVE : 0, &args.trans);
+	error = xfs_attr_args_init(&args, dp, name, flags);
 	if (error)
 		return error;
 
-	xfs_ilock(dp, XFS_ILOCK_EXCL);
-	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)
-		goto out_trans_cancel;
-
-	xfs_trans_ijoin(args.trans, dp, 0);
-	error = xfs_attr_set_args(&args);
-	if (error)
-		goto out_trans_cancel;
-	if (!args.trans) {
-		/* shortform attribute has already been committed */
-		goto out_unlock;
-	}
-
-	/*
-	 * 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 ((flags & ATTR_KERNOTIME) == 0)
-		xfs_trans_ichgtime(args.trans, dp, XFS_ICHGTIME_CHG);
+	args.value = value;
+	args.valuelen = valuelen;
 
 	/*
-	 * Commit the last in the sequence of transactions.
+	 * 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
+	 * removal to fail as well.
 	 */
-	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_trans_cancel:
-	if (args.trans)
-		xfs_trans_cancel(args.trans);
-	goto out_unlock;
-}
+	args.op_flags = XFS_DA_OP_OKNOENT;
 
-/*
- * Generic handler routine to remove a name from an attribute list.
- * Transitions attribute list from Btree to shortform as necessary.
- */
-int
-xfs_attr_remove(
-	struct xfs_inode	*dp,
-	const unsigned char	*name,
-	int			flags)
-{
-	struct xfs_mount	*mp = dp->i_mount;
-	struct xfs_da_args	args;
-	int			error;
+	if (value) {
+		XFS_STATS_INC(mp, xs_attr_set);
 
-	XFS_STATS_INC(mp, xs_attr_remove);
+		args.op_flags |= XFS_DA_OP_ADDNAME;
+		args.total = xfs_attr_calc_size(&args, &local);
 
-	if (XFS_FORCED_SHUTDOWN(dp->i_mount))
-		return -EIO;
+		/*
+		 * If the inode doesn't have an attribute fork, add one.
+		 * (inode must not be locked when we call this routine)
+		 */
+		if (XFS_IFORK_Q(dp) == 0) {
+			int sf_size = sizeof(struct xfs_attr_sf_hdr) +
+				XFS_ATTR_SF_ENTSIZE_BYNAME(args.namelen,
+						valuelen);
 
-	error = xfs_attr_args_init(&args, dp, name, flags);
-	if (error)
-		return error;
+			error = xfs_bmap_add_attrfork(dp, sf_size, rsvd);
+			if (error)
+				return error;
+		}
 
-	/*
-	 * 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
-	 * removal to fail.
-	 */
-	args.op_flags = XFS_DA_OP_OKNOENT;
+		tres.tr_logres = M_RES(mp)->tr_attrsetm.tr_logres +
+				 M_RES(mp)->tr_attrsetrt.tr_logres * args.total;
+		tres.tr_logcount = XFS_ATTRSET_LOG_COUNT;
+		tres.tr_logflags = XFS_TRANS_PERM_LOG_RES;
+		total = args.total;
+	} else {
+		XFS_STATS_INC(mp, xs_attr_remove);
 
-	error = xfs_qm_dqattach(dp);
-	if (error)
-		return error;
+		tres = M_RES(mp)->tr_attrrm;
+		total = XFS_ATTRRM_SPACE_RES(mp);
+	}
 
 	/*
 	 * Root fork attributes can use reserved data blocks for this
 	 * operation if necessary
 	 */
-	error = xfs_trans_alloc(mp, &M_RES(mp)->tr_attrrm,
-			XFS_ATTRRM_SPACE_RES(mp), 0,
-			(flags & ATTR_ROOT) ? XFS_TRANS_RESERVE : 0,
-			&args.trans);
+	error = xfs_trans_alloc(mp, &tres, total, 0,
+			rsvd ? XFS_TRANS_RESERVE : 0, &args.trans);
 	if (error)
 		return error;
 
 	xfs_ilock(dp, XFS_ILOCK_EXCL);
-	/*
-	 * No need to make quota reservations here. We expect to release some
-	 * blocks not allocate in the common case.
-	 */
 	xfs_trans_ijoin(args.trans, dp, 0);
+	if (value) {
+		unsigned int	quota_flags = XFS_QMOPT_RES_REGBLKS;
 
-	error = xfs_attr_remove_args(&args);
-	if (error)
-		goto out;
+		if (rsvd)
+			quota_flags |= XFS_QMOPT_FORCE_RES;
+		error = xfs_trans_reserve_quota_nblks(args.trans, dp,
+				args.total, 0, quota_flags);
+		if (error)
+			goto out_trans_cancel;
+		error = xfs_attr_set_args(&args);
+		if (error)
+			goto out_trans_cancel;
+		/* shortform attribute has already been committed */
+		if (!args.trans)
+			goto out_unlock;
+	} else {
+		error = xfs_attr_remove_args(&args);
+		if (error)
+			goto out_trans_cancel;
+	}
 
 	/*
 	 * If this is a synchronous mount, make sure that the
@@ -505,15 +449,14 @@ xfs_attr_remove(
 	 */
 	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_trans_cancel:
 	if (args.trans)
 		xfs_trans_cancel(args.trans);
-	xfs_iunlock(dp, XFS_ILOCK_EXCL);
-	return error;
+	goto out_unlock;
 }
 
 /*========================================================================
diff --git a/fs/xfs/libxfs/xfs_attr.h b/fs/xfs/libxfs/xfs_attr.h
index 04a628016728..1ffe8653509e 100644
--- a/fs/xfs/libxfs/xfs_attr.h
+++ b/fs/xfs/libxfs/xfs_attr.h
@@ -151,7 +151,6 @@ int xfs_attr_get(struct xfs_inode *ip, const unsigned char *name,
 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);
-int xfs_attr_remove(struct xfs_inode *dp, const unsigned char *name, int flags);
 int xfs_attr_remove_args(struct xfs_da_args *args);
 int xfs_attr_list(struct xfs_inode *dp, char *buffer, int bufsize,
 		  int flags, struct attrlist_cursor_kern *cursor);
diff --git a/fs/xfs/xfs_acl.c b/fs/xfs/xfs_acl.c
index 91693fce34a8..fccaeb3371a4 100644
--- a/fs/xfs/xfs_acl.c
+++ b/fs/xfs/xfs_acl.c
@@ -167,6 +167,8 @@ __xfs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
 {
 	struct xfs_inode *ip = XFS_I(inode);
 	unsigned char *ea_name;
+	struct xfs_acl *xfs_acl = NULL;
+	int len = 0;
 	int error;
 
 	switch (type) {
@@ -183,9 +185,7 @@ __xfs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
 	}
 
 	if (acl) {
-		struct xfs_acl *xfs_acl;
-		int len = XFS_ACL_MAX_SIZE(ip->i_mount);
-
+		len = XFS_ACL_MAX_SIZE(ip->i_mount);
 		xfs_acl = kmem_zalloc_large(len, 0);
 		if (!xfs_acl)
 			return -ENOMEM;
@@ -195,24 +195,17 @@ __xfs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
 		/* subtract away the unused acl entries */
 		len -= sizeof(struct xfs_acl_entry) *
 			 (XFS_ACL_MAX_ENTRIES(ip->i_mount) - acl->a_count);
-
-		error = xfs_attr_set(ip, ea_name, (unsigned char *)xfs_acl,
-				len, ATTR_ROOT);
-
-		kmem_free(xfs_acl);
-	} else {
-		/*
-		 * A NULL ACL argument means we want to remove the ACL.
-		 */
-		error = xfs_attr_remove(ip, ea_name, ATTR_ROOT);
-
-		/*
-		 * If the attribute didn't exist to start with that's fine.
-		 */
-		if (error == -ENOATTR)
-			error = 0;
 	}
 
+	error = xfs_attr_set(ip, ea_name, (unsigned char *)xfs_acl, len,
+			ATTR_ROOT);
+	kmem_free(xfs_acl);
+
+	/*
+	 * If the attribute didn't exist to start with that's fine.
+	 */
+	if (error == -ENOATTR)
+		error = 0;
 	if (!error)
 		set_cached_acl(inode, type, acl);
 	return error;
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
index f3a53e0db2cf..75ab6e384c16 100644
--- a/fs/xfs/xfs_ioctl.c
+++ b/fs/xfs/xfs_ioctl.c
@@ -413,7 +413,7 @@ xfs_attrmulti_attr_remove(
 
 	if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
 		return -EPERM;
-	error = xfs_attr_remove(XFS_I(inode), name, flags);
+	error = xfs_attr_set(XFS_I(inode), name, NULL, 0, flags);
 	if (!error)
 		xfs_forget_acl(inode, name, flags);
 	return error;
diff --git a/fs/xfs/xfs_xattr.c b/fs/xfs/xfs_xattr.c
index 2288f20ae282..7406b8a49dc7 100644
--- a/fs/xfs/xfs_xattr.c
+++ b/fs/xfs/xfs_xattr.c
@@ -74,14 +74,10 @@ xfs_xattr_set(const struct xattr_handler *handler, struct dentry *unused,
 	if (flags & XATTR_REPLACE)
 		xflags |= ATTR_REPLACE;
 
-	if (value)
-		error = xfs_attr_set(ip, (unsigned char *)name,
+	error = xfs_attr_set(ip, (unsigned char *)name,
 				(void *)value, size, xflags);
-	else
-		error = xfs_attr_remove(ip, (unsigned char *)name, xflags);
 	if (!error)
 		xfs_forget_acl(inode, name, xflags);
-
 	return error;
 }
 
-- 
2.20.1


  parent reply	other threads:[~2019-12-12 10:54 UTC|newest]

Thread overview: 43+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-12-12 10:54 clean up the attr interface Christoph Hellwig
2019-12-12 10:54 ` [PATCH 01/33] xfs: clear kernel only flags in XFS_IOC_ATTRMULTI_BY_HANDLE Christoph Hellwig
2019-12-18 21:26   ` Darrick J. Wong
2019-12-24 11:56     ` Christoph Hellwig
2019-12-12 10:54 ` [PATCH 02/33] xfs: reject invalid flags combinations " Christoph Hellwig
2019-12-18 21:29   ` Darrick J. Wong
2019-12-24 11:56     ` Christoph Hellwig
2019-12-12 10:54 ` [PATCH 03/33] xfs: also remove cached ACLs when removing the underlying attr Christoph Hellwig
2019-12-18 21:31   ` Darrick J. Wong
2019-12-24 11:57     ` Christoph Hellwig
2019-12-12 10:54 ` [PATCH 04/33] xfs: fix misuse of the XFS_ATTR_INCOMPLETE flag Christoph Hellwig
2019-12-18 21:33   ` Darrick J. Wong
2019-12-12 10:54 ` [PATCH 05/33] xfs: remove the ATTR_INCOMPLETE flag Christoph Hellwig
2019-12-18 21:43   ` Darrick J. Wong
2019-12-24 11:59     ` Christoph Hellwig
2019-12-12 10:54 ` Christoph Hellwig [this message]
2019-12-12 10:54 ` [PATCH 07/33] xfs: merge xfs_attrmulti_attr_remove into xfs_attrmulti_attr_set Christoph Hellwig
2019-12-12 10:54 ` [PATCH 08/33] xfs: use strndup_user in XFS_IOC_ATTRMULTI_BY_HANDLE Christoph Hellwig
2019-12-12 10:54 ` [PATCH 09/33] xfs: factour out a helper for a single XFS_IOC_ATTRMULTI_BY_HANDLE op Christoph Hellwig
2019-12-12 10:54 ` [PATCH 10/33] xfs: remove the name == NULL check from xfs_attr_args_init Christoph Hellwig
2019-12-12 10:54 ` [PATCH 11/33] xfs: remove the MAXNAMELEN " Christoph Hellwig
2019-12-12 10:54 ` [PATCH 12/33] xfs: move struct xfs_da_args to xfs_types.h Christoph Hellwig
2019-12-12 10:54 ` [PATCH 13/33] xfs: turn xfs_da_args.value into a void pointer Christoph Hellwig
2019-12-12 10:54 ` [PATCH 14/33] xfs: pass an initialized xfs_da_args structure to xfs_attr_set Christoph Hellwig
2019-12-12 10:54 ` [PATCH 15/33] xfs: pass an initialized xfs_da_args to xfs_attr_get Christoph Hellwig
2019-12-12 10:54 ` [PATCH 16/33] xfs: remove the xfs_inode argument to xfs_attr_get_ilocked Christoph Hellwig
2019-12-12 10:54 ` [PATCH 17/33] xfs: remove ATTR_KERNOVAL Christoph Hellwig
2019-12-12 10:54 ` [PATCH 18/33] xfs: remove ATTR_ALLOC and XFS_DA_OP_ALLOCVAL Christoph Hellwig
2019-12-12 10:54 ` [PATCH 19/33] xfs: replace ATTR_KERNOTIME with XFS_DA_OP_NOTIME Christoph Hellwig
2019-12-12 10:54 ` [PATCH 20/33] xfs: factor out a xfs_attr_match helper Christoph Hellwig
2019-12-12 10:54 ` [PATCH 21/33] xfs: cleanup xfs_attr_list_context Christoph Hellwig
2019-12-12 10:54 ` [PATCH 22/33] xfs: remove the unused ATTR_ENTRY macro Christoph Hellwig
2019-12-12 10:54 ` [PATCH 23/33] xfs: replace ATTR_ENTBASESIZE with offsetoff Christoph Hellwig
2019-12-12 10:54 ` [PATCH 24/33] xfs: move the legacy xfs_attr_list to xfs_ioctl.c Christoph Hellwig
2019-12-12 10:54 ` [PATCH 25/33] xfs: rename xfs_attr_list_int to xfs_attr_list Christoph Hellwig
2019-12-12 10:54 ` [PATCH 26/33] xfs: lift common check into xfs_ioc_attr_list Christoph Hellwig
2019-12-12 10:54 ` [PATCH 27/33] xfs: lift buffer allocation " Christoph Hellwig
2019-12-12 10:54 ` [PATCH 28/33] xfs: lift cursor copy in/out " Christoph Hellwig
2019-12-12 10:54 ` [PATCH 29/33] xfs: improve xfs_forget_acl Christoph Hellwig
2019-12-12 10:54 ` [PATCH 30/33] xfs: clean up the ATTR_REPLACE checks Christoph Hellwig
2019-12-12 10:54 ` [PATCH 31/33] xfs: clean up the attr flag confusion Christoph Hellwig
2019-12-12 10:54 ` [PATCH 32/33] xfs: remove XFS_DA_OP_INCOMPLETE Christoph Hellwig
2019-12-12 10:54 ` [PATCH 33/33] xfs: embedded the attrlist cursor into struct xfs_attr_list_context Christoph Hellwig

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20191212105433.1692-7-hch@lst.de \
    --to=hch@lst.de \
    --cc=allison.henderson@oracle.com \
    --cc=linux-xfs@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.