All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/06] fid refcounting improvements and fixes
@ 2022-06-12  8:53 Dominique Martinet
  2022-06-12  8:53 ` [PATCH 01/06] 9p: fix fid refcount leak in v9fs_vfs_atomic_open_dotl Dominique Martinet
                   ` (6 more replies)
  0 siblings, 7 replies; 28+ messages in thread
From: Dominique Martinet @ 2022-06-12  8:53 UTC (permalink / raw)
  To: Christian Schoenebeck, Tyler Hicks
  Cc: v9fs-developer, linux-kernel, Dominique Martinet

So:
 - I could reproduce Tyler's generic 531 leak, fixed it by the first
   commit in v9fs_vfs_atomic_open_dotl
 - Found another less likely leak while reworking code
 - Christian's comment that it's not obvious that clunk is just a
   refcount decrease was very true: I think it's worth the churn,
   so I've rename this all through a new helper...
 - ... with the not-so-hidden intent to improve debugging by adding
   a tracepoint for them, which I have also done.

I've also taken my comment in the other thread further and went ahead
and made it in its own commit. Tyler, if you're ok with this I'll just
squash it up. You can see rebased patches here:
https://github.com/martinetd/linux/

Note that I also took the permission to add back '/* clone */' as a
comment to your changing p9_client_walk's arguments: while I can agree
variables are hard to track, figuring out what the heck that boolean
argument means is much harder to me and I honestly preferred the
variable.
Having both through a comment is good enough for me if you'll accept
this:
----
@@ -222,7 +221,8 @@ static struct p9_fid *v9fs_fid_lookup_with_uid(struct dentry *dentry,
                 * We need to hold rename lock when doing a multipath
                 * walk to ensure none of the patch component change
                 */
-               fid = p9_client_walk(old_fid, l, &wnames[i], clone);
+               fid = p9_client_walk(old_fid, l, &wnames[i],
+                                    old_fid == root_fid /* clone */);
                /* non-cloning walk will return the same fid */
                if (fid != old_fid) {
                        p9_client_clunk(old_fid);
----


The last commit is just cleanups and should be no real change.

Dominique Martinet (6):
  9p: fix fid refcount leak in v9fs_vfs_atomic_open_dotl
  9p: fix fid refcount leak in v9fs_vfs_get_link
  9p: v9fs_fid_lookup_with_uid fix's fix suggestion
  9p fid refcount: add p9_fid_get/put wrappers
  9p fid refcount: add a 9p_fid_ref tracepoint
  9p fid refcount: cleanup p9_fid_put calls


(diff stats include Tyler's commits)

 fs/9p/fid.c               | 71 +++++++++++++++-------------
 fs/9p/fid.h               |  6 +--
 fs/9p/vfs_addr.c          |  4 +-
 fs/9p/vfs_dentry.c        |  4 +-
 fs/9p/vfs_dir.c           |  2 +-
 fs/9p/vfs_file.c          |  9 ++--
 fs/9p/vfs_inode.c         | 97 +++++++++++++++++----------------------
 fs/9p/vfs_inode_dotl.c    | 79 ++++++++++++-------------------
 fs/9p/vfs_super.c         |  8 ++--
 fs/9p/xattr.c             |  8 ++--
 include/net/9p/client.h   |  3 ++
 include/trace/events/9p.h | 48 +++++++++++++++++++
 net/9p/client.c           | 42 +++++++++++------
 13 files changed, 211 insertions(+), 170 deletions(-)

-- 
2.35.1


^ permalink raw reply	[flat|nested] 28+ messages in thread

* [PATCH 01/06] 9p: fix fid refcount leak in v9fs_vfs_atomic_open_dotl
  2022-06-12  8:53 [PATCH 00/06] fid refcounting improvements and fixes Dominique Martinet
@ 2022-06-12  8:53 ` Dominique Martinet
  2022-06-13 16:27   ` Tyler Hicks
  2022-06-14 13:17   ` Christian Schoenebeck
  2022-06-12  8:53 ` [PATCH 02/06] 9p: fix fid refcount leak in v9fs_vfs_get_link Dominique Martinet
                   ` (5 subsequent siblings)
  6 siblings, 2 replies; 28+ messages in thread
From: Dominique Martinet @ 2022-06-12  8:53 UTC (permalink / raw)
  To: Christian Schoenebeck, Tyler Hicks, Eric Van Hensbergen,
	Latchesar Ionkov, Dominique Martinet, Jianyong Wu
  Cc: v9fs-developer, linux-kernel, stable

We need to release directory fid if we fail halfway through open

This fixes fid leaking with xfstests generic 531

Fixes: 6636b6dcc3db ("9p: add refcount to p9_fid struct")
Cc: stable@vger.kernel.org
Reported-by: Tyler Hicks <tyhicks@linux.microsoft.com>
Signed-off-by: Dominique Martinet <asmadeus@codewreck.org>
---
 fs/9p/vfs_inode_dotl.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c
index d17502a738a9..b6eb1160296c 100644
--- a/fs/9p/vfs_inode_dotl.c
+++ b/fs/9p/vfs_inode_dotl.c
@@ -274,6 +274,7 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
 	if (IS_ERR(ofid)) {
 		err = PTR_ERR(ofid);
 		p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err);
+		p9_client_clunk(dfid);
 		goto out;
 	}
 
@@ -285,6 +286,7 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
 	if (err) {
 		p9_debug(P9_DEBUG_VFS, "Failed to get acl values in creat %d\n",
 			 err);
+		p9_client_clunk(dfid);
 		goto error;
 	}
 	err = p9_client_create_dotl(ofid, name, v9fs_open_to_dotl_flags(flags),
@@ -292,6 +294,7 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
 	if (err < 0) {
 		p9_debug(P9_DEBUG_VFS, "p9_client_open_dotl failed in creat %d\n",
 			 err);
+		p9_client_clunk(dfid);
 		goto error;
 	}
 	v9fs_invalidate_inode_attr(dir);
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 02/06] 9p: fix fid refcount leak in v9fs_vfs_get_link
  2022-06-12  8:53 [PATCH 00/06] fid refcounting improvements and fixes Dominique Martinet
  2022-06-12  8:53 ` [PATCH 01/06] 9p: fix fid refcount leak in v9fs_vfs_atomic_open_dotl Dominique Martinet
@ 2022-06-12  8:53 ` Dominique Martinet
  2022-06-13 16:29   ` Tyler Hicks
  2022-06-14 13:19   ` Christian Schoenebeck
  2022-06-12  8:53 ` [PATCH 03/06] 9p: v9fs_fid_lookup_with_uid fix's fix suggestion Dominique Martinet
                   ` (4 subsequent siblings)
  6 siblings, 2 replies; 28+ messages in thread
From: Dominique Martinet @ 2022-06-12  8:53 UTC (permalink / raw)
  To: Christian Schoenebeck, Tyler Hicks, Eric Van Hensbergen,
	Latchesar Ionkov, Dominique Martinet, Jianyong Wu
  Cc: v9fs-developer, linux-kernel, stable

we check for protocol version later than required, after a fid has
been obtained. Just move the version check earlier.

Fixes: 6636b6dcc3db ("9p: add refcount to p9_fid struct")
Cc: stable@vger.kernel.org
Signed-off-by: Dominique Martinet <asmadeus@codewreck.org>
---
 fs/9p/vfs_inode.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index 55367ecb9442..18c780ffd4b5 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -1250,15 +1250,15 @@ static const char *v9fs_vfs_get_link(struct dentry *dentry,
 		return ERR_PTR(-ECHILD);
 
 	v9ses = v9fs_dentry2v9ses(dentry);
-	fid = v9fs_fid_lookup(dentry);
+	if (!v9fs_proto_dotu(v9ses))
+		return ERR_PTR(-EBADF);
+
 	p9_debug(P9_DEBUG_VFS, "%pd\n", dentry);
+	fid = v9fs_fid_lookup(dentry);
 
 	if (IS_ERR(fid))
 		return ERR_CAST(fid);
 
-	if (!v9fs_proto_dotu(v9ses))
-		return ERR_PTR(-EBADF);
-
 	st = p9_client_stat(fid);
 	p9_client_clunk(fid);
 	if (IS_ERR(st))
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 03/06] 9p: v9fs_fid_lookup_with_uid fix's fix suggestion
  2022-06-12  8:53 [PATCH 00/06] fid refcounting improvements and fixes Dominique Martinet
  2022-06-12  8:53 ` [PATCH 01/06] 9p: fix fid refcount leak in v9fs_vfs_atomic_open_dotl Dominique Martinet
  2022-06-12  8:53 ` [PATCH 02/06] 9p: fix fid refcount leak in v9fs_vfs_get_link Dominique Martinet
@ 2022-06-12  8:53 ` Dominique Martinet
  2022-06-13 20:08   ` Tyler Hicks
  2022-06-12  8:53 ` [PATCH 04/06] 9p fid refcount: add p9_fid_get/put wrappers Dominique Martinet
                   ` (3 subsequent siblings)
  6 siblings, 1 reply; 28+ messages in thread
From: Dominique Martinet @ 2022-06-12  8:53 UTC (permalink / raw)
  To: Christian Schoenebeck, Tyler Hicks, Eric Van Hensbergen,
	Latchesar Ionkov, Dominique Martinet
  Cc: v9fs-developer, linux-kernel

Tyler, I can just squash this in your commit if you're ok with this,
as I've already rebased the other patches on top of it.

Cc: Tyler Hicks <tyhicks@linux.microsoft.com>
Signed-off-by: Dominique Martinet <asmadeus@codewreck.org>
---
 fs/9p/fid.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/fs/9p/fid.c b/fs/9p/fid.c
index 5a469b79c1ee..baf2b152229e 100644
--- a/fs/9p/fid.c
+++ b/fs/9p/fid.c
@@ -221,12 +221,15 @@ static struct p9_fid *v9fs_fid_lookup_with_uid(struct dentry *dentry,
 		 * walk to ensure none of the patch component change
 		 */
 		fid = p9_client_walk(fid, l, &wnames[i], clone);
-		p9_client_clunk(old_fid);
+		/* non-cloning walk will return the same fid */
+		if (fid != old_fid) {
+			p9_client_clunk(old_fid);
+			old_fid = fid;
+		}
 		if (IS_ERR(fid)) {
 			kfree(wnames);
 			goto err_out;
 		}
-		old_fid = fid;
 		i += l;
 		clone = 0;
 	}
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 04/06] 9p fid refcount: add p9_fid_get/put wrappers
  2022-06-12  8:53 [PATCH 00/06] fid refcounting improvements and fixes Dominique Martinet
                   ` (2 preceding siblings ...)
  2022-06-12  8:53 ` [PATCH 03/06] 9p: v9fs_fid_lookup_with_uid fix's fix suggestion Dominique Martinet
@ 2022-06-12  8:53 ` Dominique Martinet
  2022-06-12 23:45   ` [PATCH v2 " Dominique Martinet
  2022-06-12  8:53 ` [PATCH 05/06] 9p fid refcount: add a 9p_fid_ref tracepoint Dominique Martinet
                   ` (2 subsequent siblings)
  6 siblings, 1 reply; 28+ messages in thread
From: Dominique Martinet @ 2022-06-12  8:53 UTC (permalink / raw)
  To: Christian Schoenebeck, Tyler Hicks, Eric Van Hensbergen,
	Latchesar Ionkov, Dominique Martinet, David S. Miller,
	Jakub Kicinski, Paolo Abeni
  Cc: v9fs-developer, linux-kernel, netdev

I was recently reminded that it is not clear that p9_client_clunk()
was actually just decrementing refcount and clunking only when that
reaches zero: make it clear through a set of helpers.

This will also allow instrumenting refcounting better for debugging
next patch, which is the reason these are not defined as static inline:
we won't be able to add trace events there...

Signed-off-by: Dominique Martinet <asmadeus@codewreck.org>
---

I've kept this commit after the other commits despite the churn so the
stable commits are easily backportable.

 fs/9p/fid.c             | 18 ++++++++--------
 fs/9p/fid.h             |  2 +-
 fs/9p/vfs_addr.c        |  4 ++--
 fs/9p/vfs_dentry.c      |  4 ++--
 fs/9p/vfs_dir.c         |  2 +-
 fs/9p/vfs_file.c        |  4 ++--
 fs/9p/vfs_inode.c       | 48 ++++++++++++++++++++---------------------
 fs/9p/vfs_inode_dotl.c  | 42 ++++++++++++++++++------------------
 fs/9p/vfs_super.c       |  6 +++---
 fs/9p/xattr.c           |  8 +++----
 include/net/9p/client.h |  3 +++
 net/9p/client.c         | 36 ++++++++++++++++++++-----------
 12 files changed, 96 insertions(+), 81 deletions(-)

diff --git a/fs/9p/fid.c b/fs/9p/fid.c
index e8fad28fc5bd..d792499349c4 100644
--- a/fs/9p/fid.c
+++ b/fs/9p/fid.c
@@ -56,7 +56,7 @@ static struct p9_fid *v9fs_fid_find_inode(struct inode *inode, kuid_t uid)
 	h = (struct hlist_head *)&inode->i_private;
 	hlist_for_each_entry(fid, h, ilist) {
 		if (uid_eq(fid->uid, uid)) {
-			refcount_inc(&fid->count);
+			p9_fid_get(fid);
 			ret = fid;
 			break;
 		}
@@ -104,7 +104,7 @@ static struct p9_fid *v9fs_fid_find(struct dentry *dentry, kuid_t uid, int any)
 		hlist_for_each_entry(fid, h, dlist) {
 			if (any || uid_eq(fid->uid, uid)) {
 				ret = fid;
-				refcount_inc(&ret->count);
+				p9_fid_get(ret);
 				break;
 			}
 		}
@@ -172,7 +172,7 @@ static struct p9_fid *v9fs_fid_lookup_with_uid(struct dentry *dentry,
 		old_fid = fid;
 
 		fid = p9_client_walk(old_fid, 1, &dentry->d_name.name, 1);
-		p9_client_clunk(old_fid);
+		p9_fid_put(old_fid);
 		goto fid_out;
 	}
 	up_read(&v9ses->rename_sem);
@@ -194,7 +194,7 @@ static struct p9_fid *v9fs_fid_lookup_with_uid(struct dentry *dentry,
 		if (IS_ERR(root_fid))
 			return root_fid;
 
-		refcount_inc(&root_fid->count);
+		p9_fid_get(root_fid);
 		v9fs_fid_add(dentry->d_sb->s_root, root_fid);
 	}
 	/* If we are root ourself just return that */
@@ -225,7 +225,7 @@ static struct p9_fid *v9fs_fid_lookup_with_uid(struct dentry *dentry,
 				     old_fid == root_fid /* clone */);
 		/* non-cloning walk will return the same fid */
 		if (fid != old_fid) {
-			p9_client_clunk(old_fid);
+			p9_fid_put(old_fid);
 			old_fid = fid;
 		}
 		if (IS_ERR(fid)) {
@@ -240,11 +240,11 @@ static struct p9_fid *v9fs_fid_lookup_with_uid(struct dentry *dentry,
 		spin_lock(&dentry->d_lock);
 		if (d_unhashed(dentry)) {
 			spin_unlock(&dentry->d_lock);
-			p9_client_clunk(fid);
+			p9_fid_put(fid);
 			fid = ERR_PTR(-ENOENT);
 		} else {
 			__add_fid(dentry, fid);
-			refcount_inc(&fid->count);
+			p9_fid_get(fid);
 			spin_unlock(&dentry->d_lock);
 		}
 	}
@@ -301,7 +301,7 @@ struct p9_fid *v9fs_writeback_fid(struct dentry *dentry)
 	fid = clone_fid(ofid);
 	if (IS_ERR(fid))
 		goto error_out;
-	p9_client_clunk(ofid);
+	p9_fid_put(ofid);
 	/*
 	 * writeback fid will only be used to write back the
 	 * dirty pages. We always request for the open fid in read-write
@@ -310,7 +310,7 @@ struct p9_fid *v9fs_writeback_fid(struct dentry *dentry)
 	 */
 	err = p9_client_open(fid, O_RDWR);
 	if (err < 0) {
-		p9_client_clunk(fid);
+		p9_fid_put(fid);
 		fid = ERR_PTR(err);
 		goto error_out;
 	}
diff --git a/fs/9p/fid.h b/fs/9p/fid.h
index f7f33509e169..3168dfad510e 100644
--- a/fs/9p/fid.h
+++ b/fs/9p/fid.h
@@ -29,7 +29,7 @@ static inline struct p9_fid *v9fs_fid_clone(struct dentry *dentry)
 		return fid;
 
 	nfid = clone_fid(fid);
-	p9_client_clunk(fid);
+	p9_fid_put(fid);
 	return nfid;
 }
 #endif
diff --git a/fs/9p/vfs_addr.c b/fs/9p/vfs_addr.c
index 8ce82ff1e40a..ed598160e0c6 100644
--- a/fs/9p/vfs_addr.c
+++ b/fs/9p/vfs_addr.c
@@ -60,7 +60,7 @@ static int v9fs_init_request(struct netfs_io_request *rreq, struct file *file)
 {
 	struct p9_fid *fid = file->private_data;
 
-	refcount_inc(&fid->count);
+	p9_fid_get(fid);
 	rreq->netfs_priv = fid;
 	return 0;
 }
@@ -74,7 +74,7 @@ static void v9fs_req_cleanup(struct address_space *mapping, void *priv)
 {
 	struct p9_fid *fid = priv;
 
-	p9_client_clunk(fid);
+	p9_fid_put(fid);
 }
 
 /**
diff --git a/fs/9p/vfs_dentry.c b/fs/9p/vfs_dentry.c
index 1c609e99d280..f89f01734587 100644
--- a/fs/9p/vfs_dentry.c
+++ b/fs/9p/vfs_dentry.c
@@ -54,7 +54,7 @@ static void v9fs_dentry_release(struct dentry *dentry)
 	p9_debug(P9_DEBUG_VFS, " dentry: %pd (%p)\n",
 		 dentry, dentry);
 	hlist_for_each_safe(p, n, (struct hlist_head *)&dentry->d_fsdata)
-		p9_client_clunk(hlist_entry(p, struct p9_fid, dlist));
+		p9_fid_put(hlist_entry(p, struct p9_fid, dlist));
 	dentry->d_fsdata = NULL;
 }
 
@@ -85,7 +85,7 @@ static int v9fs_lookup_revalidate(struct dentry *dentry, unsigned int flags)
 			retval = v9fs_refresh_inode_dotl(fid, inode);
 		else
 			retval = v9fs_refresh_inode(fid, inode);
-		p9_client_clunk(fid);
+		p9_fid_put(fid);
 
 		if (retval == -ENOENT)
 			return 0;
diff --git a/fs/9p/vfs_dir.c b/fs/9p/vfs_dir.c
index 958680f7f23e..000fbaae9b18 100644
--- a/fs/9p/vfs_dir.c
+++ b/fs/9p/vfs_dir.c
@@ -218,7 +218,7 @@ int v9fs_dir_release(struct inode *inode, struct file *filp)
 		spin_lock(&inode->i_lock);
 		hlist_del(&fid->ilist);
 		spin_unlock(&inode->i_lock);
-		p9_client_clunk(fid);
+		p9_fid_put(fid);
 	}
 
 	if ((filp->f_mode & FMODE_WRITE)) {
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c
index 2573c08f335c..8276f3af35d7 100644
--- a/fs/9p/vfs_file.c
+++ b/fs/9p/vfs_file.c
@@ -63,7 +63,7 @@ int v9fs_file_open(struct inode *inode, struct file *file)
 
 		err = p9_client_open(fid, omode);
 		if (err < 0) {
-			p9_client_clunk(fid);
+			p9_fid_put(fid);
 			return err;
 		}
 		if ((file->f_flags & O_APPEND) &&
@@ -98,7 +98,7 @@ int v9fs_file_open(struct inode *inode, struct file *file)
 	v9fs_open_fid_add(inode, fid);
 	return 0;
 out_error:
-	p9_client_clunk(file->private_data);
+	p9_fid_put(file->private_data);
 	file->private_data = NULL;
 	return err;
 }
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index 18c780ffd4b5..38186d1a1440 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -399,7 +399,7 @@ void v9fs_evict_inode(struct inode *inode)
 	fscache_relinquish_cookie(v9fs_inode_cookie(v9inode), false);
 	/* clunk the fid stashed in writeback_fid */
 	if (v9inode->writeback_fid) {
-		p9_client_clunk(v9inode->writeback_fid);
+		p9_fid_put(v9inode->writeback_fid);
 		v9inode->writeback_fid = NULL;
 	}
 }
@@ -568,7 +568,7 @@ static int v9fs_remove(struct inode *dir, struct dentry *dentry, int flags)
 	if (v9fs_proto_dotl(v9ses))
 		retval = p9_client_unlinkat(dfid, dentry->d_name.name,
 					    v9fs_at_to_dotl_flags(flags));
-	p9_client_clunk(dfid);
+	p9_fid_put(dfid);
 	if (retval == -EOPNOTSUPP) {
 		/* Try the one based on path */
 		v9fid = v9fs_fid_clone(dentry);
@@ -632,14 +632,14 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,
 	if (IS_ERR(ofid)) {
 		err = PTR_ERR(ofid);
 		p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err);
-		p9_client_clunk(dfid);
+		p9_fid_put(dfid);
 		return ERR_PTR(err);
 	}
 
 	err = p9_client_fcreate(ofid, name, perm, mode, extension);
 	if (err < 0) {
 		p9_debug(P9_DEBUG_VFS, "p9_client_fcreate failed %d\n", err);
-		p9_client_clunk(dfid);
+		p9_fid_put(dfid);
 		goto error;
 	}
 
@@ -651,7 +651,7 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,
 			p9_debug(P9_DEBUG_VFS,
 				   "p9_client_walk failed %d\n", err);
 			fid = NULL;
-			p9_client_clunk(dfid);
+			p9_fid_put(dfid);
 			goto error;
 		}
 		/*
@@ -662,20 +662,20 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,
 			err = PTR_ERR(inode);
 			p9_debug(P9_DEBUG_VFS,
 				   "inode creation failed %d\n", err);
-			p9_client_clunk(dfid);
+			p9_fid_put(dfid);
 			goto error;
 		}
 		v9fs_fid_add(dentry, fid);
 		d_instantiate(dentry, inode);
 	}
-	p9_client_clunk(dfid);
+	p9_fid_put(dfid);
 	return ofid;
 error:
 	if (ofid)
-		p9_client_clunk(ofid);
+		p9_fid_put(ofid);
 
 	if (fid)
-		p9_client_clunk(fid);
+		p9_fid_put(fid);
 
 	return ERR_PTR(err);
 }
@@ -707,7 +707,7 @@ v9fs_vfs_create(struct user_namespace *mnt_userns, struct inode *dir,
 		return PTR_ERR(fid);
 
 	v9fs_invalidate_inode_attr(dir);
-	p9_client_clunk(fid);
+	p9_fid_put(fid);
 
 	return 0;
 }
@@ -743,7 +743,7 @@ static int v9fs_vfs_mkdir(struct user_namespace *mnt_userns, struct inode *dir,
 	}
 
 	if (fid)
-		p9_client_clunk(fid);
+		p9_fid_put(fid);
 
 	return err;
 }
@@ -784,7 +784,7 @@ struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
 	 */
 	name = dentry->d_name.name;
 	fid = p9_client_walk(dfid, 1, &name, 1);
-	p9_client_clunk(dfid);
+	p9_fid_put(dfid);
 	if (fid == ERR_PTR(-ENOENT))
 		inode = NULL;
 	else if (IS_ERR(fid))
@@ -807,7 +807,7 @@ struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
 		else if (!IS_ERR(res))
 			v9fs_fid_add(res, fid);
 		else
-			p9_client_clunk(fid);
+			p9_fid_put(fid);
 	}
 	return res;
 }
@@ -890,7 +890,7 @@ v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry,
 
 error:
 	if (fid)
-		p9_client_clunk(fid);
+		p9_fid_put(fid);
 	goto out;
 }
 
@@ -958,7 +958,7 @@ v9fs_vfs_rename(struct user_namespace *mnt_userns, struct inode *old_dir,
 	dfid = v9fs_parent_fid(old_dentry);
 	olddirfid = clone_fid(dfid);
 	if (dfid && !IS_ERR(dfid))
-		p9_client_clunk(dfid);
+		p9_fid_put(dfid);
 
 	if (IS_ERR(olddirfid)) {
 		retval = PTR_ERR(olddirfid);
@@ -967,7 +967,7 @@ v9fs_vfs_rename(struct user_namespace *mnt_userns, struct inode *old_dir,
 
 	dfid = v9fs_parent_fid(new_dentry);
 	newdirfid = clone_fid(dfid);
-	p9_client_clunk(dfid);
+	p9_fid_put(dfid);
 
 	if (IS_ERR(newdirfid)) {
 		retval = PTR_ERR(newdirfid);
@@ -1019,13 +1019,13 @@ v9fs_vfs_rename(struct user_namespace *mnt_userns, struct inode *old_dir,
 		d_move(old_dentry, new_dentry);
 	}
 	up_write(&v9ses->rename_sem);
-	p9_client_clunk(newdirfid);
+	p9_fid_put(newdirfid);
 
 clunk_olddir:
-	p9_client_clunk(olddirfid);
+	p9_fid_put(olddirfid);
 
 done:
-	p9_client_clunk(oldfid);
+	p9_fid_put(oldfid);
 	return retval;
 }
 
@@ -1059,7 +1059,7 @@ v9fs_vfs_getattr(struct user_namespace *mnt_userns, const struct path *path,
 		return PTR_ERR(fid);
 
 	st = p9_client_stat(fid);
-	p9_client_clunk(fid);
+	p9_fid_put(fid);
 	if (IS_ERR(st))
 		return PTR_ERR(st);
 
@@ -1135,7 +1135,7 @@ static int v9fs_vfs_setattr(struct user_namespace *mnt_userns,
 	retval = p9_client_wstat(fid, &wstat);
 
 	if (use_dentry)
-		p9_client_clunk(fid);
+		p9_fid_put(fid);
 
 	if (retval < 0)
 		return retval;
@@ -1260,7 +1260,7 @@ static const char *v9fs_vfs_get_link(struct dentry *dentry,
 		return ERR_CAST(fid);
 
 	st = p9_client_stat(fid);
-	p9_client_clunk(fid);
+	p9_fid_put(fid);
 	if (IS_ERR(st))
 		return ERR_CAST(st);
 
@@ -1307,7 +1307,7 @@ static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry,
 		return PTR_ERR(fid);
 
 	v9fs_invalidate_inode_attr(dir);
-	p9_client_clunk(fid);
+	p9_fid_put(fid);
 	return 0;
 }
 
@@ -1363,7 +1363,7 @@ v9fs_vfs_link(struct dentry *old_dentry, struct inode *dir,
 		v9fs_refresh_inode(oldfid, d_inode(old_dentry));
 		v9fs_invalidate_inode_attr(dir);
 	}
-	p9_client_clunk(oldfid);
+	p9_fid_put(oldfid);
 	return retval;
 }
 
diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c
index b6eb1160296c..09b124fe349c 100644
--- a/fs/9p/vfs_inode_dotl.c
+++ b/fs/9p/vfs_inode_dotl.c
@@ -274,7 +274,7 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
 	if (IS_ERR(ofid)) {
 		err = PTR_ERR(ofid);
 		p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err);
-		p9_client_clunk(dfid);
+		p9_fid_put(dfid);
 		goto out;
 	}
 
@@ -286,7 +286,7 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
 	if (err) {
 		p9_debug(P9_DEBUG_VFS, "Failed to get acl values in creat %d\n",
 			 err);
-		p9_client_clunk(dfid);
+		p9_fid_put(dfid);
 		goto error;
 	}
 	err = p9_client_create_dotl(ofid, name, v9fs_open_to_dotl_flags(flags),
@@ -294,14 +294,14 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
 	if (err < 0) {
 		p9_debug(P9_DEBUG_VFS, "p9_client_open_dotl failed in creat %d\n",
 			 err);
-		p9_client_clunk(dfid);
+		p9_fid_put(dfid);
 		goto error;
 	}
 	v9fs_invalidate_inode_attr(dir);
 
 	/* instantiate inode and assign the unopened fid to the dentry */
 	fid = p9_client_walk(dfid, 1, &name, 1);
-	p9_client_clunk(dfid);
+	p9_fid_put(dfid);
 	if (IS_ERR(fid)) {
 		err = PTR_ERR(fid);
 		p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err);
@@ -358,10 +358,10 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
 
 error:
 	if (fid)
-		p9_client_clunk(fid);
+		p9_fid_put(fid);
 err_clunk_old_fid:
 	if (ofid)
-		p9_client_clunk(ofid);
+		p9_fid_put(ofid);
 	goto out;
 }
 
@@ -458,9 +458,9 @@ static int v9fs_vfs_mkdir_dotl(struct user_namespace *mnt_userns,
 	v9fs_invalidate_inode_attr(dir);
 error:
 	if (fid)
-		p9_client_clunk(fid);
+		p9_fid_put(fid);
 	v9fs_put_acl(dacl, pacl);
-	p9_client_clunk(dfid);
+	p9_fid_put(dfid);
 	return err;
 }
 
@@ -489,7 +489,7 @@ v9fs_vfs_getattr_dotl(struct user_namespace *mnt_userns,
 	 */
 
 	st = p9_client_getattr_dotl(fid, P9_STATS_ALL);
-	p9_client_clunk(fid);
+	p9_fid_put(fid);
 	if (IS_ERR(st))
 		return PTR_ERR(st);
 
@@ -603,7 +603,7 @@ int v9fs_vfs_setattr_dotl(struct user_namespace *mnt_userns,
 	retval = p9_client_setattr(fid, &p9attr);
 	if (retval < 0) {
 		if (use_dentry)
-			p9_client_clunk(fid);
+			p9_fid_put(fid);
 		return retval;
 	}
 
@@ -619,12 +619,12 @@ int v9fs_vfs_setattr_dotl(struct user_namespace *mnt_userns,
 		retval = v9fs_acl_chmod(inode, fid);
 		if (retval < 0) {
 			if (use_dentry)
-				p9_client_clunk(fid);
+				p9_fid_put(fid);
 			return retval;
 		}
 	}
 	if (use_dentry)
-		p9_client_clunk(fid);
+		p9_fid_put(fid);
 
 	return 0;
 }
@@ -771,9 +771,9 @@ v9fs_vfs_symlink_dotl(struct user_namespace *mnt_userns, struct inode *dir,
 
 error:
 	if (fid)
-		p9_client_clunk(fid);
+		p9_fid_put(fid);
 
-	p9_client_clunk(dfid);
+	p9_fid_put(dfid);
 	return err;
 }
 
@@ -803,14 +803,14 @@ v9fs_vfs_link_dotl(struct dentry *old_dentry, struct inode *dir,
 
 	oldfid = v9fs_fid_lookup(old_dentry);
 	if (IS_ERR(oldfid)) {
-		p9_client_clunk(dfid);
+		p9_fid_put(dfid);
 		return PTR_ERR(oldfid);
 	}
 
 	err = p9_client_link(dfid, oldfid, dentry->d_name.name);
 
-	p9_client_clunk(dfid);
-	p9_client_clunk(oldfid);
+	p9_fid_put(dfid);
+	p9_fid_put(oldfid);
 	if (err < 0) {
 		p9_debug(P9_DEBUG_VFS, "p9_client_link failed %d\n", err);
 		return err;
@@ -826,7 +826,7 @@ v9fs_vfs_link_dotl(struct dentry *old_dentry, struct inode *dir,
 			return PTR_ERR(fid);
 
 		v9fs_refresh_inode_dotl(fid, d_inode(old_dentry));
-		p9_client_clunk(fid);
+		p9_fid_put(fid);
 	}
 	ihold(d_inode(old_dentry));
 	d_instantiate(dentry, d_inode(old_dentry));
@@ -924,9 +924,9 @@ v9fs_vfs_mknod_dotl(struct user_namespace *mnt_userns, struct inode *dir,
 	}
 error:
 	if (fid)
-		p9_client_clunk(fid);
+		p9_fid_put(fid);
 	v9fs_put_acl(dacl, pacl);
-	p9_client_clunk(dfid);
+	p9_fid_put(dfid);
 
 	return err;
 }
@@ -956,7 +956,7 @@ v9fs_vfs_get_link_dotl(struct dentry *dentry,
 	if (IS_ERR(fid))
 		return ERR_CAST(fid);
 	retval = p9_client_readlink(fid, &target);
-	p9_client_clunk(fid);
+	p9_fid_put(fid);
 	if (retval)
 		return ERR_PTR(retval);
 	set_delayed_call(done, kfree_link, target);
diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c
index 97e23b4e6982..bf350fad9500 100644
--- a/fs/9p/vfs_super.c
+++ b/fs/9p/vfs_super.c
@@ -190,7 +190,7 @@ static struct dentry *v9fs_mount(struct file_system_type *fs_type, int flags,
 	return dget(sb->s_root);
 
 clunk_fid:
-	p9_client_clunk(fid);
+	p9_fid_put(fid);
 	v9fs_session_close(v9ses);
 free_session:
 	kfree(v9ses);
@@ -203,7 +203,7 @@ static struct dentry *v9fs_mount(struct file_system_type *fs_type, int flags,
 	 * attached the fid to dentry so it won't get clunked
 	 * automatically.
 	 */
-	p9_client_clunk(fid);
+	p9_fid_put(fid);
 	deactivate_locked_super(sb);
 	return ERR_PTR(retval);
 }
@@ -270,7 +270,7 @@ static int v9fs_statfs(struct dentry *dentry, struct kstatfs *buf)
 	}
 	res = simple_statfs(dentry, buf);
 done:
-	p9_client_clunk(fid);
+	p9_fid_put(fid);
 	return res;
 }
 
diff --git a/fs/9p/xattr.c b/fs/9p/xattr.c
index a824441b95a2..1f9298a4bd42 100644
--- a/fs/9p/xattr.c
+++ b/fs/9p/xattr.c
@@ -44,7 +44,7 @@ ssize_t v9fs_fid_xattr_get(struct p9_fid *fid, const char *name,
 		if (err)
 			retval = err;
 	}
-	p9_client_clunk(attr_fid);
+	p9_fid_put(attr_fid);
 	return retval;
 }
 
@@ -71,7 +71,7 @@ ssize_t v9fs_xattr_get(struct dentry *dentry, const char *name,
 	if (IS_ERR(fid))
 		return PTR_ERR(fid);
 	ret = v9fs_fid_xattr_get(fid, name, buffer, buffer_size);
-	p9_client_clunk(fid);
+	p9_fid_put(fid);
 
 	return ret;
 }
@@ -98,7 +98,7 @@ int v9fs_xattr_set(struct dentry *dentry, const char *name,
 	if (IS_ERR(fid))
 		return PTR_ERR(fid);
 	ret = v9fs_fid_xattr_set(fid, name, value, value_len, flags);
-	p9_client_clunk(fid);
+	p9_fid_put(fid);
 	return ret;
 }
 
@@ -128,7 +128,7 @@ int v9fs_fid_xattr_set(struct p9_fid *fid, const char *name,
 			 retval);
 	else
 		p9_client_write(fid, 0, &from, &retval);
-	err = p9_client_clunk(fid);
+	err = p9_fid_put(fid);
 	if (!retval && err)
 		retval = err;
 	return retval;
diff --git a/include/net/9p/client.h b/include/net/9p/client.h
index ec1d1706f43c..55587ce88181 100644
--- a/include/net/9p/client.h
+++ b/include/net/9p/client.h
@@ -237,6 +237,9 @@ static inline int p9_req_try_get(struct p9_req_t *r)
 
 int p9_req_put(struct p9_req_t *r);
 
+struct p9_fid *p9_fid_get(struct p9_fid *fid);
+int p9_fid_put(struct p9_fid *fid);
+
 void p9_client_cb(struct p9_client *c, struct p9_req_t *req, int status);
 
 int p9_parse_header(struct p9_fcall *pdu, int32_t *size, int8_t *type,
diff --git a/net/9p/client.c b/net/9p/client.c
index 8bba0d9cf975..3e1cda4a8328 100644
--- a/net/9p/client.c
+++ b/net/9p/client.c
@@ -928,6 +928,27 @@ static void p9_fid_destroy(struct p9_fid *fid)
 	kfree(fid);
 }
 
+/* these unfortunately can't be declared as static inline in client.h
+ * because trace_* functions can't be used there easily
+ */
+struct p9_fid *p9_fid_get(struct p9_fid *fid) {
+	refcount_inc(&fid->count);
+
+	return fid;
+}
+EXPORT_SYMBOL(p9_fid_get);
+
+int p9_fid_put(struct p9_fid *fid) {
+	if (!fid || IS_ERR(fid))
+		return 0;
+
+        if (!refcount_dec_and_test(&fid->count))
+                return 0;
+
+	return p9_client_clunk(fid);
+}
+EXPORT_SYMBOL(p9_fid_put);
+
 static int p9_client_version(struct p9_client *c)
 {
 	int err = 0;
@@ -1228,7 +1249,7 @@ struct p9_fid *p9_client_walk(struct p9_fid *oldfid, uint16_t nwname,
 
 clunk_fid:
 	kfree(wqids);
-	p9_client_clunk(fid);
+	p9_fid_put(fid);
 	fid = NULL;
 
 error:
@@ -1459,15 +1480,6 @@ int p9_client_clunk(struct p9_fid *fid)
 	struct p9_req_t *req;
 	int retries = 0;
 
-	if (!fid || IS_ERR(fid)) {
-		pr_warn("%s (%d): Trying to clunk with invalid fid\n",
-			__func__, task_pid_nr(current));
-		dump_stack();
-		return 0;
-	}
-	if (!refcount_dec_and_test(&fid->count))
-		return 0;
-
 again:
 	p9_debug(P9_DEBUG_9P, ">>> TCLUNK fid %d (try %d)\n",
 		 fid->fid, retries);
@@ -1519,7 +1531,7 @@ int p9_client_remove(struct p9_fid *fid)
 	p9_tag_remove(clnt, req);
 error:
 	if (err == -ERESTARTSYS)
-		p9_client_clunk(fid);
+		p9_fid_put(fid);
 	else
 		p9_fid_destroy(fid);
 	return err;
@@ -2042,7 +2054,7 @@ struct p9_fid *p9_client_xattrwalk(struct p9_fid *file_fid,
 		 attr_fid->fid, *attr_size);
 	return attr_fid;
 clunk_fid:
-	p9_client_clunk(attr_fid);
+	p9_fid_put(attr_fid);
 	attr_fid = NULL;
 error:
 	if (attr_fid && attr_fid != file_fid)
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 05/06] 9p fid refcount: add a 9p_fid_ref tracepoint
  2022-06-12  8:53 [PATCH 00/06] fid refcounting improvements and fixes Dominique Martinet
                   ` (3 preceding siblings ...)
  2022-06-12  8:53 ` [PATCH 04/06] 9p fid refcount: add p9_fid_get/put wrappers Dominique Martinet
@ 2022-06-12  8:53 ` Dominique Martinet
  2022-06-12 22:46   ` Steven Rostedt
  2022-06-12  8:53 ` [PATCH 06/06] 9p fid refcount: cleanup p9_fid_put calls Dominique Martinet
  2022-06-13 20:20 ` [PATCH 00/06] fid refcounting improvements and fixes Tyler Hicks
  6 siblings, 1 reply; 28+ messages in thread
From: Dominique Martinet @ 2022-06-12  8:53 UTC (permalink / raw)
  To: Christian Schoenebeck, Tyler Hicks, Eric Van Hensbergen,
	Latchesar Ionkov, Dominique Martinet, Steven Rostedt,
	Ingo Molnar, David S. Miller, Jakub Kicinski, Paolo Abeni
  Cc: v9fs-developer, linux-kernel, netdev

Signed-off-by: Dominique Martinet <asmadeus@codewreck.org>
---

This is the first time I add a tracepoint, so if anyone has time to
check I didn't make something too stupid please have a look.
I've mostly copied from netfs'.

Also, a question if someone has time: I'd have liked to use the
tracepoint in static inline wrappers for getref/putref, but it's not
good to add the tracepoints to a .h, right?
Especially with the CREATE_TRACE_POINTS macro...
How do people usually go about that, just bite the bullet and make it
a real function?


 include/trace/events/9p.h | 48 +++++++++++++++++++++++++++++++++++++++
 net/9p/client.c           |  9 +++++++-
 2 files changed, 56 insertions(+), 1 deletion(-)

diff --git a/include/trace/events/9p.h b/include/trace/events/9p.h
index 78c5608a1648..4dfa6d7f83ba 100644
--- a/include/trace/events/9p.h
+++ b/include/trace/events/9p.h
@@ -77,6 +77,13 @@
 		EM( P9_TWSTAT,		"P9_TWSTAT" )			\
 		EMe(P9_RWSTAT,		"P9_RWSTAT" )
 
+
+#define P9_FID_REFTYPE							\
+		EM( P9_FID_REF_CREATE,	"create " )			\
+		EM( P9_FID_REF_GET,	"get    " )			\
+		EM( P9_FID_REF_PUT,	"put    " )			\
+		EMe(P9_FID_REF_DESTROY,	"destroy" )
+
 /* Define EM() to export the enums to userspace via TRACE_DEFINE_ENUM() */
 #undef EM
 #undef EMe
@@ -84,6 +91,21 @@
 #define EMe(a, b)	TRACE_DEFINE_ENUM(a);
 
 P9_MSG_T
+P9_FID_REFTYPE
+
+/* And also use EM/EMe to define helper enums -- once */
+#ifndef __9P_DECLARE_TRACE_ENUMS_ONLY_ONCE
+#define __9P_DECLARE_TRACE_ENUMS_ONLY_ONCE
+#undef EM
+#undef EMe
+#define EM(a, b)	a,
+#define EMe(a, b)	a
+
+enum p9_fid_reftype {
+	P9_FID_REFTYPE
+} __mode(byte);
+
+#endif
 
 /*
  * Now redefine the EM() and EMe() macros to map the enums to the strings
@@ -96,6 +118,8 @@ P9_MSG_T
 
 #define show_9p_op(type)						\
 	__print_symbolic(type, P9_MSG_T)
+#define show_9p_fid_reftype(type)					\
+	__print_symbolic(type, P9_FID_REFTYPE)
 
 TRACE_EVENT(9p_client_req,
 	    TP_PROTO(struct p9_client *clnt, int8_t type, int tag),
@@ -168,6 +192,30 @@ TRACE_EVENT(9p_protocol_dump,
 		      __entry->tag, 0, __entry->line, 16, __entry->line + 16)
  );
 
+
+TRACE_EVENT(9p_fid_ref,
+	    TP_PROTO(struct p9_fid *fid, __u8 type),
+
+	    TP_ARGS(fid, type),
+
+	    TP_STRUCT__entry(
+		    __field(	int,	fid		)
+		    __field(	int,	refcount	)
+		    __field(	__u8, type	)
+		    ),
+
+	    TP_fast_assign(
+		    __entry->fid = fid->fid;
+		    __entry->refcount = refcount_read(&fid->count);
+		    __entry->type = type;
+		    ),
+
+	    TP_printk("%s fid %d, refcount %d",
+		      show_9p_fid_reftype(__entry->type),
+		      __entry->fid, __entry->refcount)
+);
+
+
 #endif /* _TRACE_9P_H */
 
 /* This part must be outside protection */
diff --git a/net/9p/client.c b/net/9p/client.c
index 5531b31e0fb2..fdeeda0a811d 100644
--- a/net/9p/client.c
+++ b/net/9p/client.c
@@ -907,8 +907,10 @@ static struct p9_fid *p9_fid_create(struct p9_client *clnt)
 			    GFP_NOWAIT);
 	spin_unlock_irq(&clnt->lock);
 	idr_preload_end();
-	if (!ret)
+	if (!ret) {
+		trace_9p_fid_ref(fid, P9_FID_REF_CREATE);
 		return fid;
+	}
 
 	kfree(fid);
 	return NULL;
@@ -920,6 +922,7 @@ static void p9_fid_destroy(struct p9_fid *fid)
 	unsigned long flags;
 
 	p9_debug(P9_DEBUG_FID, "fid %d\n", fid->fid);
+	trace_9p_fid_ref(fid, P9_FID_REF_DESTROY);
 	clnt = fid->clnt;
 	spin_lock_irqsave(&clnt->lock, flags);
 	idr_remove(&clnt->fids, fid->fid);
@@ -932,6 +935,8 @@ static void p9_fid_destroy(struct p9_fid *fid)
  * because trace_* functions can't be used there easily
  */
 struct p9_fid *p9_fid_get(struct p9_fid *fid) {
+	trace_9p_fid_ref(fid, P9_FID_REF_GET);
+
 	refcount_inc(&fid->count);
 
 	return fid;
@@ -941,6 +946,8 @@ int p9_fid_put(struct p9_fid *fid) {
 	if (!fid || IS_ERR(fid))
 		return 0;
 
+	trace_9p_fid_ref(fid, P9_FID_REF_PUT);
+
         if (!refcount_dec_and_test(&fid->count))
                 return 0;
 
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 06/06] 9p fid refcount: cleanup p9_fid_put calls
  2022-06-12  8:53 [PATCH 00/06] fid refcounting improvements and fixes Dominique Martinet
                   ` (4 preceding siblings ...)
  2022-06-12  8:53 ` [PATCH 05/06] 9p fid refcount: add a 9p_fid_ref tracepoint Dominique Martinet
@ 2022-06-12  8:53 ` Dominique Martinet
  2022-06-13 17:55   ` Tyler Hicks
  2022-06-13 20:20 ` [PATCH 00/06] fid refcounting improvements and fixes Tyler Hicks
  6 siblings, 1 reply; 28+ messages in thread
From: Dominique Martinet @ 2022-06-12  8:53 UTC (permalink / raw)
  To: Christian Schoenebeck, Tyler Hicks, Eric Van Hensbergen,
	Latchesar Ionkov, Dominique Martinet
  Cc: v9fs-developer, linux-kernel

Simplify p9_fid_put cleanup path in many 9p functions since the function
is noop on null or error fids.

Also make the *_add_fid() helpers "steal" the fid by nulling its
pointer, so put after them will be noop.

This should lead to no change of behaviour

Signed-off-by: Dominique Martinet <asmadeus@codewreck.org>
---
 fs/9p/fid.c            | 24 +++++++++++------
 fs/9p/fid.h            |  4 +--
 fs/9p/vfs_file.c       |  5 ++--
 fs/9p/vfs_inode.c      | 61 +++++++++++++++++-------------------------
 fs/9p/vfs_inode_dotl.c | 58 +++++++++++++--------------------------
 fs/9p/vfs_super.c      |  2 +-
 6 files changed, 64 insertions(+), 90 deletions(-)

diff --git a/fs/9p/fid.c b/fs/9p/fid.c
index d792499349c4..289a85eae2ae 100644
--- a/fs/9p/fid.c
+++ b/fs/9p/fid.c
@@ -31,11 +31,15 @@ static inline void __add_fid(struct dentry *dentry, struct p9_fid *fid)
  * @fid: fid to add
  *
  */
-void v9fs_fid_add(struct dentry *dentry, struct p9_fid *fid)
+void v9fs_fid_add(struct dentry *dentry, struct p9_fid **pfid)
 {
+	struct p9_fid *fid = *pfid;
+
 	spin_lock(&dentry->d_lock);
 	__add_fid(dentry, fid);
 	spin_unlock(&dentry->d_lock);
+
+	*pfid = NULL;
 }
 
 /**
@@ -72,11 +76,15 @@ static struct p9_fid *v9fs_fid_find_inode(struct inode *inode, kuid_t uid)
  *
  */
 
-void v9fs_open_fid_add(struct inode *inode, struct p9_fid *fid)
+void v9fs_open_fid_add(struct inode *inode, struct p9_fid **pfid)
 {
+	struct p9_fid *fid = *pfid;
+
 	spin_lock(&inode->i_lock);
 	hlist_add_head(&fid->ilist, (struct hlist_head *)&inode->i_private);
 	spin_unlock(&inode->i_lock);
+
+	*pfid = NULL;
 }
 
 
@@ -189,13 +197,13 @@ static struct p9_fid *v9fs_fid_lookup_with_uid(struct dentry *dentry,
 		else
 			uname = v9ses->uname;
 
-		root_fid = p9_client_attach(v9ses->clnt, NULL, uname, uid,
-					    v9ses->aname);
-		if (IS_ERR(root_fid))
-			return root_fid;
+		fid = p9_client_attach(v9ses->clnt, NULL, uname, uid,
+				       v9ses->aname);
+		if (IS_ERR(fid))
+			return fid;
 
-		p9_fid_get(root_fid);
-		v9fs_fid_add(dentry->d_sb->s_root, root_fid);
+		root_fid = p9_fid_get(fid);
+		v9fs_fid_add(dentry->d_sb->s_root, &fid);
 	}
 	/* If we are root ourself just return that */
 	if (dentry->d_sb->s_root == dentry)
diff --git a/fs/9p/fid.h b/fs/9p/fid.h
index 3168dfad510e..8a4e8cd12ca2 100644
--- a/fs/9p/fid.h
+++ b/fs/9p/fid.h
@@ -13,9 +13,9 @@ static inline struct p9_fid *v9fs_parent_fid(struct dentry *dentry)
 {
 	return v9fs_fid_lookup(dentry->d_parent);
 }
-void v9fs_fid_add(struct dentry *dentry, struct p9_fid *fid);
+void v9fs_fid_add(struct dentry *dentry, struct p9_fid **fid);
 struct p9_fid *v9fs_writeback_fid(struct dentry *dentry);
-void v9fs_open_fid_add(struct inode *inode, struct p9_fid *fid);
+void v9fs_open_fid_add(struct inode *inode, struct p9_fid **fid);
 static inline struct p9_fid *clone_fid(struct p9_fid *fid)
 {
 	return IS_ERR(fid) ? fid :  p9_client_walk(fid, 0, NULL, 1);
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c
index 8276f3af35d7..aec43ba83799 100644
--- a/fs/9p/vfs_file.c
+++ b/fs/9p/vfs_file.c
@@ -69,9 +69,10 @@ int v9fs_file_open(struct inode *inode, struct file *file)
 		if ((file->f_flags & O_APPEND) &&
 			(!v9fs_proto_dotu(v9ses) && !v9fs_proto_dotl(v9ses)))
 			generic_file_llseek(file, 0, SEEK_END);
+
+		file->private_data = fid;
 	}
 
-	file->private_data = fid;
 	mutex_lock(&v9inode->v_mutex);
 	if ((v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) &&
 	    !v9inode->writeback_fid &&
@@ -95,7 +96,7 @@ int v9fs_file_open(struct inode *inode, struct file *file)
 	if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE)
 		fscache_use_cookie(v9fs_inode_cookie(v9inode),
 				   file->f_mode & FMODE_WRITE);
-	v9fs_open_fid_add(inode, fid);
+	v9fs_open_fid_add(inode, &fid);
 	return 0;
 out_error:
 	p9_fid_put(file->private_data);
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index 38186d1a1440..1b11a92208fd 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -398,10 +398,8 @@ void v9fs_evict_inode(struct inode *inode)
 
 	fscache_relinquish_cookie(v9fs_inode_cookie(v9inode), false);
 	/* clunk the fid stashed in writeback_fid */
-	if (v9inode->writeback_fid) {
-		p9_fid_put(v9inode->writeback_fid);
-		v9inode->writeback_fid = NULL;
-	}
+	p9_fid_put(v9inode->writeback_fid);
+	v9inode->writeback_fid = NULL;
 }
 
 static int v9fs_test_inode(struct inode *inode, void *data)
@@ -632,14 +630,12 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,
 	if (IS_ERR(ofid)) {
 		err = PTR_ERR(ofid);
 		p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err);
-		p9_fid_put(dfid);
-		return ERR_PTR(err);
+		goto error;
 	}
 
 	err = p9_client_fcreate(ofid, name, perm, mode, extension);
 	if (err < 0) {
 		p9_debug(P9_DEBUG_VFS, "p9_client_fcreate failed %d\n", err);
-		p9_fid_put(dfid);
 		goto error;
 	}
 
@@ -650,8 +646,6 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,
 			err = PTR_ERR(fid);
 			p9_debug(P9_DEBUG_VFS,
 				   "p9_client_walk failed %d\n", err);
-			fid = NULL;
-			p9_fid_put(dfid);
 			goto error;
 		}
 		/*
@@ -662,21 +656,17 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,
 			err = PTR_ERR(inode);
 			p9_debug(P9_DEBUG_VFS,
 				   "inode creation failed %d\n", err);
-			p9_fid_put(dfid);
 			goto error;
 		}
-		v9fs_fid_add(dentry, fid);
+		v9fs_fid_add(dentry, &fid);
 		d_instantiate(dentry, inode);
 	}
 	p9_fid_put(dfid);
 	return ofid;
 error:
-	if (ofid)
-		p9_fid_put(ofid);
-
-	if (fid)
-		p9_fid_put(fid);
-
+	p9_fid_put(dfid);
+	p9_fid_put(ofid);
+	p9_fid_put(fid);
 	return ERR_PTR(err);
 }
 
@@ -803,9 +793,9 @@ struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
 	res = d_splice_alias(inode, dentry);
 	if (!IS_ERR(fid)) {
 		if (!res)
-			v9fs_fid_add(dentry, fid);
+			v9fs_fid_add(dentry, &fid);
 		else if (!IS_ERR(res))
-			v9fs_fid_add(res, fid);
+			v9fs_fid_add(res, &fid);
 		else
 			p9_fid_put(fid);
 	}
@@ -846,7 +836,6 @@ v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry,
 						v9fs_proto_dotu(v9ses)));
 	if (IS_ERR(fid)) {
 		err = PTR_ERR(fid);
-		fid = NULL;
 		goto error;
 	}
 
@@ -881,7 +870,7 @@ v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry,
 	if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE)
 		fscache_use_cookie(v9fs_inode_cookie(v9inode),
 				   file->f_mode & FMODE_WRITE);
-	v9fs_open_fid_add(inode, fid);
+	v9fs_open_fid_add(inode, &fid);
 
 	file->f_mode |= FMODE_CREATED;
 out:
@@ -889,8 +878,7 @@ v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry,
 	return err;
 
 error:
-	if (fid)
-		p9_fid_put(fid);
+	p9_fid_put(fid);
 	goto out;
 }
 
@@ -938,9 +926,9 @@ v9fs_vfs_rename(struct user_namespace *mnt_userns, struct inode *old_dir,
 	struct inode *old_inode;
 	struct inode *new_inode;
 	struct v9fs_session_info *v9ses;
-	struct p9_fid *oldfid, *dfid;
-	struct p9_fid *olddirfid;
-	struct p9_fid *newdirfid;
+	struct p9_fid *oldfid = NULL, *dfid = NULL;
+	struct p9_fid *olddirfid = NULL;
+	struct p9_fid *newdirfid = NULL;
 	struct p9_wstat wstat;
 
 	if (flags)
@@ -957,21 +945,22 @@ v9fs_vfs_rename(struct user_namespace *mnt_userns, struct inode *old_dir,
 
 	dfid = v9fs_parent_fid(old_dentry);
 	olddirfid = clone_fid(dfid);
-	if (dfid && !IS_ERR(dfid))
-		p9_fid_put(dfid);
+	p9_fid_put(dfid);
+	dfid = NULL;
 
 	if (IS_ERR(olddirfid)) {
 		retval = PTR_ERR(olddirfid);
-		goto done;
+		goto error;
 	}
 
 	dfid = v9fs_parent_fid(new_dentry);
 	newdirfid = clone_fid(dfid);
 	p9_fid_put(dfid);
+	dfid = NULL;
 
 	if (IS_ERR(newdirfid)) {
 		retval = PTR_ERR(newdirfid);
-		goto clunk_olddir;
+		goto error;
 	}
 
 	down_write(&v9ses->rename_sem);
@@ -982,7 +971,7 @@ v9fs_vfs_rename(struct user_namespace *mnt_userns, struct inode *old_dir,
 			retval = p9_client_rename(oldfid, newdirfid,
 						  new_dentry->d_name.name);
 		if (retval != -EOPNOTSUPP)
-			goto clunk_newdir;
+			goto error_locked;
 	}
 	if (old_dentry->d_parent != new_dentry->d_parent) {
 		/*
@@ -991,14 +980,14 @@ v9fs_vfs_rename(struct user_namespace *mnt_userns, struct inode *old_dir,
 
 		p9_debug(P9_DEBUG_ERROR, "old dir and new dir are different\n");
 		retval = -EXDEV;
-		goto clunk_newdir;
+		goto error_locked;
 	}
 	v9fs_blank_wstat(&wstat);
 	wstat.muid = v9ses->uname;
 	wstat.name = new_dentry->d_name.name;
 	retval = p9_client_wstat(oldfid, &wstat);
 
-clunk_newdir:
+error_locked:
 	if (!retval) {
 		if (new_inode) {
 			if (S_ISDIR(new_inode->i_mode))
@@ -1019,12 +1008,10 @@ v9fs_vfs_rename(struct user_namespace *mnt_userns, struct inode *old_dir,
 		d_move(old_dentry, new_dentry);
 	}
 	up_write(&v9ses->rename_sem);
+
+error:
 	p9_fid_put(newdirfid);
-
-clunk_olddir:
 	p9_fid_put(olddirfid);
-
-done:
 	p9_fid_put(oldfid);
 	return retval;
 }
diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c
index 09b124fe349c..5cfa4b4f070f 100644
--- a/fs/9p/vfs_inode_dotl.c
+++ b/fs/9p/vfs_inode_dotl.c
@@ -238,7 +238,7 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
 	struct inode *inode;
 	struct p9_fid *fid = NULL;
 	struct v9fs_inode *v9inode;
-	struct p9_fid *dfid, *ofid, *inode_fid;
+	struct p9_fid *dfid = NULL, *ofid = NULL, *inode_fid = NULL;
 	struct v9fs_session_info *v9ses;
 	struct posix_acl *pacl = NULL, *dacl = NULL;
 	struct dentry *res = NULL;
@@ -274,7 +274,6 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
 	if (IS_ERR(ofid)) {
 		err = PTR_ERR(ofid);
 		p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err);
-		p9_fid_put(dfid);
 		goto out;
 	}
 
@@ -286,38 +285,34 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
 	if (err) {
 		p9_debug(P9_DEBUG_VFS, "Failed to get acl values in creat %d\n",
 			 err);
-		p9_fid_put(dfid);
-		goto error;
+		goto out;
 	}
 	err = p9_client_create_dotl(ofid, name, v9fs_open_to_dotl_flags(flags),
 				    mode, gid, &qid);
 	if (err < 0) {
 		p9_debug(P9_DEBUG_VFS, "p9_client_open_dotl failed in creat %d\n",
 			 err);
-		p9_fid_put(dfid);
-		goto error;
+		goto out;
 	}
 	v9fs_invalidate_inode_attr(dir);
 
 	/* instantiate inode and assign the unopened fid to the dentry */
 	fid = p9_client_walk(dfid, 1, &name, 1);
-	p9_fid_put(dfid);
 	if (IS_ERR(fid)) {
 		err = PTR_ERR(fid);
 		p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err);
-		fid = NULL;
-		goto error;
+		goto out;
 	}
 	inode = v9fs_get_new_inode_from_fid(v9ses, fid, dir->i_sb);
 	if (IS_ERR(inode)) {
 		err = PTR_ERR(inode);
 		p9_debug(P9_DEBUG_VFS, "inode creation failed %d\n", err);
-		goto error;
+		goto out;
 	}
 	/* Now set the ACL based on the default value */
 	v9fs_set_create_acl(inode, fid, dacl, pacl);
 
-	v9fs_fid_add(dentry, fid);
+	v9fs_fid_add(dentry, &fid);
 	d_instantiate(dentry, inode);
 
 	v9inode = V9FS_I(inode);
@@ -336,7 +331,7 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
 		if (IS_ERR(inode_fid)) {
 			err = PTR_ERR(inode_fid);
 			mutex_unlock(&v9inode->v_mutex);
-			goto err_clunk_old_fid;
+			goto out;
 		}
 		v9inode->writeback_fid = (void *) inode_fid;
 	}
@@ -344,25 +339,20 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
 	/* Since we are opening a file, assign the open fid to the file */
 	err = finish_open(file, dentry, generic_file_open);
 	if (err)
-		goto err_clunk_old_fid;
+		goto out;
 	file->private_data = ofid;
 	if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE)
 		fscache_use_cookie(v9fs_inode_cookie(v9inode),
 				   file->f_mode & FMODE_WRITE);
-	v9fs_open_fid_add(inode, ofid);
+	v9fs_open_fid_add(inode, &ofid);
 	file->f_mode |= FMODE_CREATED;
 out:
+	p9_fid_put(dfid);
+	p9_fid_put(ofid);
+	p9_fid_put(fid);
 	v9fs_put_acl(dacl, pacl);
 	dput(res);
 	return err;
-
-error:
-	if (fid)
-		p9_fid_put(fid);
-err_clunk_old_fid:
-	if (ofid)
-		p9_fid_put(ofid);
-	goto out;
 }
 
 /**
@@ -400,7 +390,6 @@ static int v9fs_vfs_mkdir_dotl(struct user_namespace *mnt_userns,
 	if (IS_ERR(dfid)) {
 		err = PTR_ERR(dfid);
 		p9_debug(P9_DEBUG_VFS, "fid lookup failed %d\n", err);
-		dfid = NULL;
 		goto error;
 	}
 
@@ -422,7 +411,6 @@ static int v9fs_vfs_mkdir_dotl(struct user_namespace *mnt_userns,
 		err = PTR_ERR(fid);
 		p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n",
 			 err);
-		fid = NULL;
 		goto error;
 	}
 
@@ -435,10 +423,9 @@ static int v9fs_vfs_mkdir_dotl(struct user_namespace *mnt_userns,
 				 err);
 			goto error;
 		}
-		v9fs_fid_add(dentry, fid);
+		v9fs_fid_add(dentry, &fid);
 		v9fs_set_create_acl(inode, fid, dacl, pacl);
 		d_instantiate(dentry, inode);
-		fid = NULL;
 		err = 0;
 	} else {
 		/*
@@ -457,8 +444,7 @@ static int v9fs_vfs_mkdir_dotl(struct user_namespace *mnt_userns,
 	inc_nlink(dir);
 	v9fs_invalidate_inode_attr(dir);
 error:
-	if (fid)
-		p9_fid_put(fid);
+	p9_fid_put(fid);
 	v9fs_put_acl(dacl, pacl);
 	p9_fid_put(dfid);
 	return err;
@@ -743,7 +729,6 @@ v9fs_vfs_symlink_dotl(struct user_namespace *mnt_userns, struct inode *dir,
 			err = PTR_ERR(fid);
 			p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n",
 				 err);
-			fid = NULL;
 			goto error;
 		}
 
@@ -755,9 +740,8 @@ v9fs_vfs_symlink_dotl(struct user_namespace *mnt_userns, struct inode *dir,
 				 err);
 			goto error;
 		}
-		v9fs_fid_add(dentry, fid);
+		v9fs_fid_add(dentry, &fid);
 		d_instantiate(dentry, inode);
-		fid = NULL;
 		err = 0;
 	} else {
 		/* Not in cached mode. No need to populate inode with stat */
@@ -770,9 +754,7 @@ v9fs_vfs_symlink_dotl(struct user_namespace *mnt_userns, struct inode *dir,
 	}
 
 error:
-	if (fid)
-		p9_fid_put(fid);
-
+	p9_fid_put(fid);
 	p9_fid_put(dfid);
 	return err;
 }
@@ -866,7 +848,6 @@ v9fs_vfs_mknod_dotl(struct user_namespace *mnt_userns, struct inode *dir,
 	if (IS_ERR(dfid)) {
 		err = PTR_ERR(dfid);
 		p9_debug(P9_DEBUG_VFS, "fid lookup failed %d\n", err);
-		dfid = NULL;
 		goto error;
 	}
 
@@ -891,7 +872,6 @@ v9fs_vfs_mknod_dotl(struct user_namespace *mnt_userns, struct inode *dir,
 		err = PTR_ERR(fid);
 		p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n",
 			 err);
-		fid = NULL;
 		goto error;
 	}
 
@@ -905,9 +885,8 @@ v9fs_vfs_mknod_dotl(struct user_namespace *mnt_userns, struct inode *dir,
 			goto error;
 		}
 		v9fs_set_create_acl(inode, fid, dacl, pacl);
-		v9fs_fid_add(dentry, fid);
+		v9fs_fid_add(dentry, &fid);
 		d_instantiate(dentry, inode);
-		fid = NULL;
 		err = 0;
 	} else {
 		/*
@@ -923,8 +902,7 @@ v9fs_vfs_mknod_dotl(struct user_namespace *mnt_userns, struct inode *dir,
 		d_instantiate(dentry, inode);
 	}
 error:
-	if (fid)
-		p9_fid_put(fid);
+	p9_fid_put(fid);
 	v9fs_put_acl(dacl, pacl);
 	p9_fid_put(dfid);
 
diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c
index bf350fad9500..2d9ee073d12c 100644
--- a/fs/9p/vfs_super.c
+++ b/fs/9p/vfs_super.c
@@ -184,7 +184,7 @@ static struct dentry *v9fs_mount(struct file_system_type *fs_type, int flags,
 	retval = v9fs_get_acl(inode, fid);
 	if (retval)
 		goto release_sb;
-	v9fs_fid_add(root, fid);
+	v9fs_fid_add(root, &fid);
 
 	p9_debug(P9_DEBUG_VFS, " simple set mount, return 0\n");
 	return dget(sb->s_root);
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* Re: [PATCH 05/06] 9p fid refcount: add a 9p_fid_ref tracepoint
  2022-06-12  8:53 ` [PATCH 05/06] 9p fid refcount: add a 9p_fid_ref tracepoint Dominique Martinet
@ 2022-06-12 22:46   ` Steven Rostedt
  2022-06-12 23:46     ` [PATCH v2 " Dominique Martinet
  0 siblings, 1 reply; 28+ messages in thread
From: Steven Rostedt @ 2022-06-12 22:46 UTC (permalink / raw)
  To: Dominique Martinet
  Cc: Christian Schoenebeck, Tyler Hicks, Eric Van Hensbergen,
	Latchesar Ionkov, Ingo Molnar, David S. Miller, Jakub Kicinski,
	Paolo Abeni, v9fs-developer, linux-kernel, netdev

On Sun, 12 Jun 2022 17:53:28 +0900
Dominique Martinet <asmadeus@codewreck.org> wrote:

This needs to have a change log. A tracepoint should never be added
without explaining why it is being added and its purpose.

> Signed-off-by: Dominique Martinet <asmadeus@codewreck.org>
> ---
> 
> This is the first time I add a tracepoint, so if anyone has time to
> check I didn't make something too stupid please have a look.
> I've mostly copied from netfs'.
> 
> Also, a question if someone has time: I'd have liked to use the
> tracepoint in static inline wrappers for getref/putref, but it's not
> good to add the tracepoints to a .h, right?

Correct, because it can have unexpected side effects. Thus it is best
to call a wrapper function that is defined in a C file that will then
call the tracepoint. To avoid the overhead of the function call when
tracing is not enabled, you should use (in the header):

  #include <linux/tracepoint-defs.h>

  DECLARE_TRACEPOINT(<tracepoint-name>);

  if (tracepoint_enabled(<tracepoint-name>))
	do_<tracepoint-name>(...);

and in the C file have:

  void do_<tracepoint-name>(...)
  {
	trace_<tracepoint-name>(...);
  }

that calls the tracepoint. The tracepoint_enabled(<tracepoint-name>)()
is another special function that is created by the TRACE_EVENT() macro
to use, that is a static branch and not a real if statement. That is, it
is a nop that skips calling the wrapper function when not enabled, and
a jmp to call the wrapper function when the tracepoint is enabled.

How to do this is described in include/linux/tracepoint-defs.h and
there's an example of this use case in include/linux/mmap_lock.h.

> Especially with the CREATE_TRACE_POINTS macro...
> How do people usually go about that, just bite the bullet and make it
> a real function?
> 
> 
>  include/trace/events/9p.h | 48 +++++++++++++++++++++++++++++++++++++++
>  net/9p/client.c           |  9 +++++++-
>  2 files changed, 56 insertions(+), 1 deletion(-)
> 
> diff --git a/include/trace/events/9p.h b/include/trace/events/9p.h
> index 78c5608a1648..4dfa6d7f83ba 100644
> --- a/include/trace/events/9p.h
> +++ b/include/trace/events/9p.h
> @@ -77,6 +77,13 @@
>  		EM( P9_TWSTAT,		"P9_TWSTAT" )			\
>  		EMe(P9_RWSTAT,		"P9_RWSTAT" )
>  
> +
> +#define P9_FID_REFTYPE							\
> +		EM( P9_FID_REF_CREATE,	"create " )			\
> +		EM( P9_FID_REF_GET,	"get    " )			\
> +		EM( P9_FID_REF_PUT,	"put    " )			\
> +		EMe(P9_FID_REF_DESTROY,	"destroy" )
> +
>  /* Define EM() to export the enums to userspace via TRACE_DEFINE_ENUM() */
>  #undef EM
>  #undef EMe
> @@ -84,6 +91,21 @@
>  #define EMe(a, b)	TRACE_DEFINE_ENUM(a);
>  
>  P9_MSG_T
> +P9_FID_REFTYPE
> +
> +/* And also use EM/EMe to define helper enums -- once */
> +#ifndef __9P_DECLARE_TRACE_ENUMS_ONLY_ONCE
> +#define __9P_DECLARE_TRACE_ENUMS_ONLY_ONCE
> +#undef EM
> +#undef EMe
> +#define EM(a, b)	a,
> +#define EMe(a, b)	a
> +
> +enum p9_fid_reftype {
> +	P9_FID_REFTYPE
> +} __mode(byte);
> +
> +#endif
>  
>  /*
>   * Now redefine the EM() and EMe() macros to map the enums to the strings
> @@ -96,6 +118,8 @@ P9_MSG_T
>  
>  #define show_9p_op(type)						\
>  	__print_symbolic(type, P9_MSG_T)
> +#define show_9p_fid_reftype(type)					\
> +	__print_symbolic(type, P9_FID_REFTYPE)
>  
>  TRACE_EVENT(9p_client_req,
>  	    TP_PROTO(struct p9_client *clnt, int8_t type, int tag),
> @@ -168,6 +192,30 @@ TRACE_EVENT(9p_protocol_dump,
>  		      __entry->tag, 0, __entry->line, 16, __entry->line + 16)
>   );
>  
> +
> +TRACE_EVENT(9p_fid_ref,
> +	    TP_PROTO(struct p9_fid *fid, __u8 type),
> +
> +	    TP_ARGS(fid, type),
> +
> +	    TP_STRUCT__entry(
> +		    __field(	int,	fid		)
> +		    __field(	int,	refcount	)
> +		    __field(	__u8, type	)
> +		    ),
> +
> +	    TP_fast_assign(
> +		    __entry->fid = fid->fid;
> +		    __entry->refcount = refcount_read(&fid->count);
> +		    __entry->type = type;
> +		    ),
> +
> +	    TP_printk("%s fid %d, refcount %d",
> +		      show_9p_fid_reftype(__entry->type),
> +		      __entry->fid, __entry->refcount)
> +);
> +
> +
>  #endif /* _TRACE_9P_H */
>  
>  /* This part must be outside protection */
> diff --git a/net/9p/client.c b/net/9p/client.c
> index 5531b31e0fb2..fdeeda0a811d 100644
> --- a/net/9p/client.c
> +++ b/net/9p/client.c
> @@ -907,8 +907,10 @@ static struct p9_fid *p9_fid_create(struct p9_client *clnt)
>  			    GFP_NOWAIT);
>  	spin_unlock_irq(&clnt->lock);
>  	idr_preload_end();
> -	if (!ret)
> +	if (!ret) {
> +		trace_9p_fid_ref(fid, P9_FID_REF_CREATE);
>  		return fid;
> +	}
>  
>  	kfree(fid);
>  	return NULL;
> @@ -920,6 +922,7 @@ static void p9_fid_destroy(struct p9_fid *fid)
>  	unsigned long flags;
>  
>  	p9_debug(P9_DEBUG_FID, "fid %d\n", fid->fid);
> +	trace_9p_fid_ref(fid, P9_FID_REF_DESTROY);
>  	clnt = fid->clnt;
>  	spin_lock_irqsave(&clnt->lock, flags);
>  	idr_remove(&clnt->fids, fid->fid);
> @@ -932,6 +935,8 @@ static void p9_fid_destroy(struct p9_fid *fid)
>   * because trace_* functions can't be used there easily
>   */
>  struct p9_fid *p9_fid_get(struct p9_fid *fid) {
> +	trace_9p_fid_ref(fid, P9_FID_REF_GET);
> +
>  	refcount_inc(&fid->count);
>  
>  	return fid;
> @@ -941,6 +946,8 @@ int p9_fid_put(struct p9_fid *fid) {
>  	if (!fid || IS_ERR(fid))
>  		return 0;
>  
> +	trace_9p_fid_ref(fid, P9_FID_REF_PUT);
> +
>          if (!refcount_dec_and_test(&fid->count))
>                  return 0;
>  

Nothing stands out to me that would be wrong with the above.

-- Steve


^ permalink raw reply	[flat|nested] 28+ messages in thread

* [PATCH v2 04/06] 9p fid refcount: add p9_fid_get/put wrappers
  2022-06-12  8:53 ` [PATCH 04/06] 9p fid refcount: add p9_fid_get/put wrappers Dominique Martinet
@ 2022-06-12 23:45   ` Dominique Martinet
  2022-06-13 17:31     ` Tyler Hicks
  2022-06-14 13:55     ` Christian Schoenebeck
  0 siblings, 2 replies; 28+ messages in thread
From: Dominique Martinet @ 2022-06-12 23:45 UTC (permalink / raw)
  To: Christian Schoenebeck, Tyler Hicks, Eric Van Hensbergen,
	Latchesar Ionkov, Dominique Martinet, David S. Miller,
	Jakub Kicinski, Paolo Abeni
  Cc: v9fs-developer, linux-kernel, netdev

I was recently reminded that it is not clear that p9_client_clunk()
was actually just decrementing refcount and clunking only when that
reaches zero: make it clear through a set of helpers.

This will also allow instrumenting refcounting better for debugging
next patch, which is the reason these are not defined as static inline:
we won't be able to add trace events there...

Signed-off-by: Dominique Martinet <asmadeus@codewreck.org>
---
v1 -> v2: p9_fid_get/put are now static inline in .h

 fs/9p/fid.c             | 18 ++++++++--------
 fs/9p/fid.h             |  2 +-
 fs/9p/vfs_addr.c        |  4 ++--
 fs/9p/vfs_dentry.c      |  4 ++--
 fs/9p/vfs_dir.c         |  2 +-
 fs/9p/vfs_file.c        |  4 ++--
 fs/9p/vfs_inode.c       | 48 ++++++++++++++++++++---------------------
 fs/9p/vfs_inode_dotl.c  | 42 ++++++++++++++++++------------------
 fs/9p/vfs_super.c       |  6 +++---
 fs/9p/xattr.c           |  8 +++----
 include/net/9p/client.h | 18 ++++++++++++++++
 net/9p/client.c         | 15 +++----------
 12 files changed, 90 insertions(+), 81 deletions(-)

diff --git a/fs/9p/fid.c b/fs/9p/fid.c
index e8fad28fc5bd..d792499349c4 100644
--- a/fs/9p/fid.c
+++ b/fs/9p/fid.c
@@ -56,7 +56,7 @@ static struct p9_fid *v9fs_fid_find_inode(struct inode *inode, kuid_t uid)
 	h = (struct hlist_head *)&inode->i_private;
 	hlist_for_each_entry(fid, h, ilist) {
 		if (uid_eq(fid->uid, uid)) {
-			refcount_inc(&fid->count);
+			p9_fid_get(fid);
 			ret = fid;
 			break;
 		}
@@ -104,7 +104,7 @@ static struct p9_fid *v9fs_fid_find(struct dentry *dentry, kuid_t uid, int any)
 		hlist_for_each_entry(fid, h, dlist) {
 			if (any || uid_eq(fid->uid, uid)) {
 				ret = fid;
-				refcount_inc(&ret->count);
+				p9_fid_get(ret);
 				break;
 			}
 		}
@@ -172,7 +172,7 @@ static struct p9_fid *v9fs_fid_lookup_with_uid(struct dentry *dentry,
 		old_fid = fid;
 
 		fid = p9_client_walk(old_fid, 1, &dentry->d_name.name, 1);
-		p9_client_clunk(old_fid);
+		p9_fid_put(old_fid);
 		goto fid_out;
 	}
 	up_read(&v9ses->rename_sem);
@@ -194,7 +194,7 @@ static struct p9_fid *v9fs_fid_lookup_with_uid(struct dentry *dentry,
 		if (IS_ERR(root_fid))
 			return root_fid;
 
-		refcount_inc(&root_fid->count);
+		p9_fid_get(root_fid);
 		v9fs_fid_add(dentry->d_sb->s_root, root_fid);
 	}
 	/* If we are root ourself just return that */
@@ -225,7 +225,7 @@ static struct p9_fid *v9fs_fid_lookup_with_uid(struct dentry *dentry,
 				     old_fid == root_fid /* clone */);
 		/* non-cloning walk will return the same fid */
 		if (fid != old_fid) {
-			p9_client_clunk(old_fid);
+			p9_fid_put(old_fid);
 			old_fid = fid;
 		}
 		if (IS_ERR(fid)) {
@@ -240,11 +240,11 @@ static struct p9_fid *v9fs_fid_lookup_with_uid(struct dentry *dentry,
 		spin_lock(&dentry->d_lock);
 		if (d_unhashed(dentry)) {
 			spin_unlock(&dentry->d_lock);
-			p9_client_clunk(fid);
+			p9_fid_put(fid);
 			fid = ERR_PTR(-ENOENT);
 		} else {
 			__add_fid(dentry, fid);
-			refcount_inc(&fid->count);
+			p9_fid_get(fid);
 			spin_unlock(&dentry->d_lock);
 		}
 	}
@@ -301,7 +301,7 @@ struct p9_fid *v9fs_writeback_fid(struct dentry *dentry)
 	fid = clone_fid(ofid);
 	if (IS_ERR(fid))
 		goto error_out;
-	p9_client_clunk(ofid);
+	p9_fid_put(ofid);
 	/*
 	 * writeback fid will only be used to write back the
 	 * dirty pages. We always request for the open fid in read-write
@@ -310,7 +310,7 @@ struct p9_fid *v9fs_writeback_fid(struct dentry *dentry)
 	 */
 	err = p9_client_open(fid, O_RDWR);
 	if (err < 0) {
-		p9_client_clunk(fid);
+		p9_fid_put(fid);
 		fid = ERR_PTR(err);
 		goto error_out;
 	}
diff --git a/fs/9p/fid.h b/fs/9p/fid.h
index f7f33509e169..3168dfad510e 100644
--- a/fs/9p/fid.h
+++ b/fs/9p/fid.h
@@ -29,7 +29,7 @@ static inline struct p9_fid *v9fs_fid_clone(struct dentry *dentry)
 		return fid;
 
 	nfid = clone_fid(fid);
-	p9_client_clunk(fid);
+	p9_fid_put(fid);
 	return nfid;
 }
 #endif
diff --git a/fs/9p/vfs_addr.c b/fs/9p/vfs_addr.c
index 8ce82ff1e40a..ed598160e0c6 100644
--- a/fs/9p/vfs_addr.c
+++ b/fs/9p/vfs_addr.c
@@ -60,7 +60,7 @@ static int v9fs_init_request(struct netfs_io_request *rreq, struct file *file)
 {
 	struct p9_fid *fid = file->private_data;
 
-	refcount_inc(&fid->count);
+	p9_fid_get(fid);
 	rreq->netfs_priv = fid;
 	return 0;
 }
@@ -74,7 +74,7 @@ static void v9fs_req_cleanup(struct address_space *mapping, void *priv)
 {
 	struct p9_fid *fid = priv;
 
-	p9_client_clunk(fid);
+	p9_fid_put(fid);
 }
 
 /**
diff --git a/fs/9p/vfs_dentry.c b/fs/9p/vfs_dentry.c
index 1c609e99d280..f89f01734587 100644
--- a/fs/9p/vfs_dentry.c
+++ b/fs/9p/vfs_dentry.c
@@ -54,7 +54,7 @@ static void v9fs_dentry_release(struct dentry *dentry)
 	p9_debug(P9_DEBUG_VFS, " dentry: %pd (%p)\n",
 		 dentry, dentry);
 	hlist_for_each_safe(p, n, (struct hlist_head *)&dentry->d_fsdata)
-		p9_client_clunk(hlist_entry(p, struct p9_fid, dlist));
+		p9_fid_put(hlist_entry(p, struct p9_fid, dlist));
 	dentry->d_fsdata = NULL;
 }
 
@@ -85,7 +85,7 @@ static int v9fs_lookup_revalidate(struct dentry *dentry, unsigned int flags)
 			retval = v9fs_refresh_inode_dotl(fid, inode);
 		else
 			retval = v9fs_refresh_inode(fid, inode);
-		p9_client_clunk(fid);
+		p9_fid_put(fid);
 
 		if (retval == -ENOENT)
 			return 0;
diff --git a/fs/9p/vfs_dir.c b/fs/9p/vfs_dir.c
index 958680f7f23e..000fbaae9b18 100644
--- a/fs/9p/vfs_dir.c
+++ b/fs/9p/vfs_dir.c
@@ -218,7 +218,7 @@ int v9fs_dir_release(struct inode *inode, struct file *filp)
 		spin_lock(&inode->i_lock);
 		hlist_del(&fid->ilist);
 		spin_unlock(&inode->i_lock);
-		p9_client_clunk(fid);
+		p9_fid_put(fid);
 	}
 
 	if ((filp->f_mode & FMODE_WRITE)) {
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c
index 2573c08f335c..8276f3af35d7 100644
--- a/fs/9p/vfs_file.c
+++ b/fs/9p/vfs_file.c
@@ -63,7 +63,7 @@ int v9fs_file_open(struct inode *inode, struct file *file)
 
 		err = p9_client_open(fid, omode);
 		if (err < 0) {
-			p9_client_clunk(fid);
+			p9_fid_put(fid);
 			return err;
 		}
 		if ((file->f_flags & O_APPEND) &&
@@ -98,7 +98,7 @@ int v9fs_file_open(struct inode *inode, struct file *file)
 	v9fs_open_fid_add(inode, fid);
 	return 0;
 out_error:
-	p9_client_clunk(file->private_data);
+	p9_fid_put(file->private_data);
 	file->private_data = NULL;
 	return err;
 }
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index 18c780ffd4b5..38186d1a1440 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -399,7 +399,7 @@ void v9fs_evict_inode(struct inode *inode)
 	fscache_relinquish_cookie(v9fs_inode_cookie(v9inode), false);
 	/* clunk the fid stashed in writeback_fid */
 	if (v9inode->writeback_fid) {
-		p9_client_clunk(v9inode->writeback_fid);
+		p9_fid_put(v9inode->writeback_fid);
 		v9inode->writeback_fid = NULL;
 	}
 }
@@ -568,7 +568,7 @@ static int v9fs_remove(struct inode *dir, struct dentry *dentry, int flags)
 	if (v9fs_proto_dotl(v9ses))
 		retval = p9_client_unlinkat(dfid, dentry->d_name.name,
 					    v9fs_at_to_dotl_flags(flags));
-	p9_client_clunk(dfid);
+	p9_fid_put(dfid);
 	if (retval == -EOPNOTSUPP) {
 		/* Try the one based on path */
 		v9fid = v9fs_fid_clone(dentry);
@@ -632,14 +632,14 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,
 	if (IS_ERR(ofid)) {
 		err = PTR_ERR(ofid);
 		p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err);
-		p9_client_clunk(dfid);
+		p9_fid_put(dfid);
 		return ERR_PTR(err);
 	}
 
 	err = p9_client_fcreate(ofid, name, perm, mode, extension);
 	if (err < 0) {
 		p9_debug(P9_DEBUG_VFS, "p9_client_fcreate failed %d\n", err);
-		p9_client_clunk(dfid);
+		p9_fid_put(dfid);
 		goto error;
 	}
 
@@ -651,7 +651,7 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,
 			p9_debug(P9_DEBUG_VFS,
 				   "p9_client_walk failed %d\n", err);
 			fid = NULL;
-			p9_client_clunk(dfid);
+			p9_fid_put(dfid);
 			goto error;
 		}
 		/*
@@ -662,20 +662,20 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,
 			err = PTR_ERR(inode);
 			p9_debug(P9_DEBUG_VFS,
 				   "inode creation failed %d\n", err);
-			p9_client_clunk(dfid);
+			p9_fid_put(dfid);
 			goto error;
 		}
 		v9fs_fid_add(dentry, fid);
 		d_instantiate(dentry, inode);
 	}
-	p9_client_clunk(dfid);
+	p9_fid_put(dfid);
 	return ofid;
 error:
 	if (ofid)
-		p9_client_clunk(ofid);
+		p9_fid_put(ofid);
 
 	if (fid)
-		p9_client_clunk(fid);
+		p9_fid_put(fid);
 
 	return ERR_PTR(err);
 }
@@ -707,7 +707,7 @@ v9fs_vfs_create(struct user_namespace *mnt_userns, struct inode *dir,
 		return PTR_ERR(fid);
 
 	v9fs_invalidate_inode_attr(dir);
-	p9_client_clunk(fid);
+	p9_fid_put(fid);
 
 	return 0;
 }
@@ -743,7 +743,7 @@ static int v9fs_vfs_mkdir(struct user_namespace *mnt_userns, struct inode *dir,
 	}
 
 	if (fid)
-		p9_client_clunk(fid);
+		p9_fid_put(fid);
 
 	return err;
 }
@@ -784,7 +784,7 @@ struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
 	 */
 	name = dentry->d_name.name;
 	fid = p9_client_walk(dfid, 1, &name, 1);
-	p9_client_clunk(dfid);
+	p9_fid_put(dfid);
 	if (fid == ERR_PTR(-ENOENT))
 		inode = NULL;
 	else if (IS_ERR(fid))
@@ -807,7 +807,7 @@ struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
 		else if (!IS_ERR(res))
 			v9fs_fid_add(res, fid);
 		else
-			p9_client_clunk(fid);
+			p9_fid_put(fid);
 	}
 	return res;
 }
@@ -890,7 +890,7 @@ v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry,
 
 error:
 	if (fid)
-		p9_client_clunk(fid);
+		p9_fid_put(fid);
 	goto out;
 }
 
@@ -958,7 +958,7 @@ v9fs_vfs_rename(struct user_namespace *mnt_userns, struct inode *old_dir,
 	dfid = v9fs_parent_fid(old_dentry);
 	olddirfid = clone_fid(dfid);
 	if (dfid && !IS_ERR(dfid))
-		p9_client_clunk(dfid);
+		p9_fid_put(dfid);
 
 	if (IS_ERR(olddirfid)) {
 		retval = PTR_ERR(olddirfid);
@@ -967,7 +967,7 @@ v9fs_vfs_rename(struct user_namespace *mnt_userns, struct inode *old_dir,
 
 	dfid = v9fs_parent_fid(new_dentry);
 	newdirfid = clone_fid(dfid);
-	p9_client_clunk(dfid);
+	p9_fid_put(dfid);
 
 	if (IS_ERR(newdirfid)) {
 		retval = PTR_ERR(newdirfid);
@@ -1019,13 +1019,13 @@ v9fs_vfs_rename(struct user_namespace *mnt_userns, struct inode *old_dir,
 		d_move(old_dentry, new_dentry);
 	}
 	up_write(&v9ses->rename_sem);
-	p9_client_clunk(newdirfid);
+	p9_fid_put(newdirfid);
 
 clunk_olddir:
-	p9_client_clunk(olddirfid);
+	p9_fid_put(olddirfid);
 
 done:
-	p9_client_clunk(oldfid);
+	p9_fid_put(oldfid);
 	return retval;
 }
 
@@ -1059,7 +1059,7 @@ v9fs_vfs_getattr(struct user_namespace *mnt_userns, const struct path *path,
 		return PTR_ERR(fid);
 
 	st = p9_client_stat(fid);
-	p9_client_clunk(fid);
+	p9_fid_put(fid);
 	if (IS_ERR(st))
 		return PTR_ERR(st);
 
@@ -1135,7 +1135,7 @@ static int v9fs_vfs_setattr(struct user_namespace *mnt_userns,
 	retval = p9_client_wstat(fid, &wstat);
 
 	if (use_dentry)
-		p9_client_clunk(fid);
+		p9_fid_put(fid);
 
 	if (retval < 0)
 		return retval;
@@ -1260,7 +1260,7 @@ static const char *v9fs_vfs_get_link(struct dentry *dentry,
 		return ERR_CAST(fid);
 
 	st = p9_client_stat(fid);
-	p9_client_clunk(fid);
+	p9_fid_put(fid);
 	if (IS_ERR(st))
 		return ERR_CAST(st);
 
@@ -1307,7 +1307,7 @@ static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry,
 		return PTR_ERR(fid);
 
 	v9fs_invalidate_inode_attr(dir);
-	p9_client_clunk(fid);
+	p9_fid_put(fid);
 	return 0;
 }
 
@@ -1363,7 +1363,7 @@ v9fs_vfs_link(struct dentry *old_dentry, struct inode *dir,
 		v9fs_refresh_inode(oldfid, d_inode(old_dentry));
 		v9fs_invalidate_inode_attr(dir);
 	}
-	p9_client_clunk(oldfid);
+	p9_fid_put(oldfid);
 	return retval;
 }
 
diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c
index b6eb1160296c..09b124fe349c 100644
--- a/fs/9p/vfs_inode_dotl.c
+++ b/fs/9p/vfs_inode_dotl.c
@@ -274,7 +274,7 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
 	if (IS_ERR(ofid)) {
 		err = PTR_ERR(ofid);
 		p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err);
-		p9_client_clunk(dfid);
+		p9_fid_put(dfid);
 		goto out;
 	}
 
@@ -286,7 +286,7 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
 	if (err) {
 		p9_debug(P9_DEBUG_VFS, "Failed to get acl values in creat %d\n",
 			 err);
-		p9_client_clunk(dfid);
+		p9_fid_put(dfid);
 		goto error;
 	}
 	err = p9_client_create_dotl(ofid, name, v9fs_open_to_dotl_flags(flags),
@@ -294,14 +294,14 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
 	if (err < 0) {
 		p9_debug(P9_DEBUG_VFS, "p9_client_open_dotl failed in creat %d\n",
 			 err);
-		p9_client_clunk(dfid);
+		p9_fid_put(dfid);
 		goto error;
 	}
 	v9fs_invalidate_inode_attr(dir);
 
 	/* instantiate inode and assign the unopened fid to the dentry */
 	fid = p9_client_walk(dfid, 1, &name, 1);
-	p9_client_clunk(dfid);
+	p9_fid_put(dfid);
 	if (IS_ERR(fid)) {
 		err = PTR_ERR(fid);
 		p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err);
@@ -358,10 +358,10 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
 
 error:
 	if (fid)
-		p9_client_clunk(fid);
+		p9_fid_put(fid);
 err_clunk_old_fid:
 	if (ofid)
-		p9_client_clunk(ofid);
+		p9_fid_put(ofid);
 	goto out;
 }
 
@@ -458,9 +458,9 @@ static int v9fs_vfs_mkdir_dotl(struct user_namespace *mnt_userns,
 	v9fs_invalidate_inode_attr(dir);
 error:
 	if (fid)
-		p9_client_clunk(fid);
+		p9_fid_put(fid);
 	v9fs_put_acl(dacl, pacl);
-	p9_client_clunk(dfid);
+	p9_fid_put(dfid);
 	return err;
 }
 
@@ -489,7 +489,7 @@ v9fs_vfs_getattr_dotl(struct user_namespace *mnt_userns,
 	 */
 
 	st = p9_client_getattr_dotl(fid, P9_STATS_ALL);
-	p9_client_clunk(fid);
+	p9_fid_put(fid);
 	if (IS_ERR(st))
 		return PTR_ERR(st);
 
@@ -603,7 +603,7 @@ int v9fs_vfs_setattr_dotl(struct user_namespace *mnt_userns,
 	retval = p9_client_setattr(fid, &p9attr);
 	if (retval < 0) {
 		if (use_dentry)
-			p9_client_clunk(fid);
+			p9_fid_put(fid);
 		return retval;
 	}
 
@@ -619,12 +619,12 @@ int v9fs_vfs_setattr_dotl(struct user_namespace *mnt_userns,
 		retval = v9fs_acl_chmod(inode, fid);
 		if (retval < 0) {
 			if (use_dentry)
-				p9_client_clunk(fid);
+				p9_fid_put(fid);
 			return retval;
 		}
 	}
 	if (use_dentry)
-		p9_client_clunk(fid);
+		p9_fid_put(fid);
 
 	return 0;
 }
@@ -771,9 +771,9 @@ v9fs_vfs_symlink_dotl(struct user_namespace *mnt_userns, struct inode *dir,
 
 error:
 	if (fid)
-		p9_client_clunk(fid);
+		p9_fid_put(fid);
 
-	p9_client_clunk(dfid);
+	p9_fid_put(dfid);
 	return err;
 }
 
@@ -803,14 +803,14 @@ v9fs_vfs_link_dotl(struct dentry *old_dentry, struct inode *dir,
 
 	oldfid = v9fs_fid_lookup(old_dentry);
 	if (IS_ERR(oldfid)) {
-		p9_client_clunk(dfid);
+		p9_fid_put(dfid);
 		return PTR_ERR(oldfid);
 	}
 
 	err = p9_client_link(dfid, oldfid, dentry->d_name.name);
 
-	p9_client_clunk(dfid);
-	p9_client_clunk(oldfid);
+	p9_fid_put(dfid);
+	p9_fid_put(oldfid);
 	if (err < 0) {
 		p9_debug(P9_DEBUG_VFS, "p9_client_link failed %d\n", err);
 		return err;
@@ -826,7 +826,7 @@ v9fs_vfs_link_dotl(struct dentry *old_dentry, struct inode *dir,
 			return PTR_ERR(fid);
 
 		v9fs_refresh_inode_dotl(fid, d_inode(old_dentry));
-		p9_client_clunk(fid);
+		p9_fid_put(fid);
 	}
 	ihold(d_inode(old_dentry));
 	d_instantiate(dentry, d_inode(old_dentry));
@@ -924,9 +924,9 @@ v9fs_vfs_mknod_dotl(struct user_namespace *mnt_userns, struct inode *dir,
 	}
 error:
 	if (fid)
-		p9_client_clunk(fid);
+		p9_fid_put(fid);
 	v9fs_put_acl(dacl, pacl);
-	p9_client_clunk(dfid);
+	p9_fid_put(dfid);
 
 	return err;
 }
@@ -956,7 +956,7 @@ v9fs_vfs_get_link_dotl(struct dentry *dentry,
 	if (IS_ERR(fid))
 		return ERR_CAST(fid);
 	retval = p9_client_readlink(fid, &target);
-	p9_client_clunk(fid);
+	p9_fid_put(fid);
 	if (retval)
 		return ERR_PTR(retval);
 	set_delayed_call(done, kfree_link, target);
diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c
index 97e23b4e6982..bf350fad9500 100644
--- a/fs/9p/vfs_super.c
+++ b/fs/9p/vfs_super.c
@@ -190,7 +190,7 @@ static struct dentry *v9fs_mount(struct file_system_type *fs_type, int flags,
 	return dget(sb->s_root);
 
 clunk_fid:
-	p9_client_clunk(fid);
+	p9_fid_put(fid);
 	v9fs_session_close(v9ses);
 free_session:
 	kfree(v9ses);
@@ -203,7 +203,7 @@ static struct dentry *v9fs_mount(struct file_system_type *fs_type, int flags,
 	 * attached the fid to dentry so it won't get clunked
 	 * automatically.
 	 */
-	p9_client_clunk(fid);
+	p9_fid_put(fid);
 	deactivate_locked_super(sb);
 	return ERR_PTR(retval);
 }
@@ -270,7 +270,7 @@ static int v9fs_statfs(struct dentry *dentry, struct kstatfs *buf)
 	}
 	res = simple_statfs(dentry, buf);
 done:
-	p9_client_clunk(fid);
+	p9_fid_put(fid);
 	return res;
 }
 
diff --git a/fs/9p/xattr.c b/fs/9p/xattr.c
index a824441b95a2..1f9298a4bd42 100644
--- a/fs/9p/xattr.c
+++ b/fs/9p/xattr.c
@@ -44,7 +44,7 @@ ssize_t v9fs_fid_xattr_get(struct p9_fid *fid, const char *name,
 		if (err)
 			retval = err;
 	}
-	p9_client_clunk(attr_fid);
+	p9_fid_put(attr_fid);
 	return retval;
 }
 
@@ -71,7 +71,7 @@ ssize_t v9fs_xattr_get(struct dentry *dentry, const char *name,
 	if (IS_ERR(fid))
 		return PTR_ERR(fid);
 	ret = v9fs_fid_xattr_get(fid, name, buffer, buffer_size);
-	p9_client_clunk(fid);
+	p9_fid_put(fid);
 
 	return ret;
 }
@@ -98,7 +98,7 @@ int v9fs_xattr_set(struct dentry *dentry, const char *name,
 	if (IS_ERR(fid))
 		return PTR_ERR(fid);
 	ret = v9fs_fid_xattr_set(fid, name, value, value_len, flags);
-	p9_client_clunk(fid);
+	p9_fid_put(fid);
 	return ret;
 }
 
@@ -128,7 +128,7 @@ int v9fs_fid_xattr_set(struct p9_fid *fid, const char *name,
 			 retval);
 	else
 		p9_client_write(fid, 0, &from, &retval);
-	err = p9_client_clunk(fid);
+	err = p9_fid_put(fid);
 	if (!retval && err)
 		retval = err;
 	return retval;
diff --git a/include/net/9p/client.h b/include/net/9p/client.h
index ec1d1706f43c..9fd38d674057 100644
--- a/include/net/9p/client.h
+++ b/include/net/9p/client.h
@@ -237,6 +237,24 @@ static inline int p9_req_try_get(struct p9_req_t *r)
 
 int p9_req_put(struct p9_req_t *r);
 
+static inline struct p9_fid *p9_fid_get(struct p9_fid *fid)
+{
+	refcount_inc(&fid->count);
+
+	return fid;
+}
+
+static inline int p9_fid_put(struct p9_fid *fid)
+{
+	if (!fid || IS_ERR(fid))
+		return 0;
+
+	if (!refcount_dec_and_test(&fid->count))
+		return 0;
+
+	return p9_client_clunk(fid);
+}
+
 void p9_client_cb(struct p9_client *c, struct p9_req_t *req, int status);
 
 int p9_parse_header(struct p9_fcall *pdu, int32_t *size, int8_t *type,
diff --git a/net/9p/client.c b/net/9p/client.c
index 8bba0d9cf975..f3eb280c7d9d 100644
--- a/net/9p/client.c
+++ b/net/9p/client.c
@@ -1228,7 +1228,7 @@ struct p9_fid *p9_client_walk(struct p9_fid *oldfid, uint16_t nwname,
 
 clunk_fid:
 	kfree(wqids);
-	p9_client_clunk(fid);
+	p9_fid_put(fid);
 	fid = NULL;
 
 error:
@@ -1459,15 +1459,6 @@ int p9_client_clunk(struct p9_fid *fid)
 	struct p9_req_t *req;
 	int retries = 0;
 
-	if (!fid || IS_ERR(fid)) {
-		pr_warn("%s (%d): Trying to clunk with invalid fid\n",
-			__func__, task_pid_nr(current));
-		dump_stack();
-		return 0;
-	}
-	if (!refcount_dec_and_test(&fid->count))
-		return 0;
-
 again:
 	p9_debug(P9_DEBUG_9P, ">>> TCLUNK fid %d (try %d)\n",
 		 fid->fid, retries);
@@ -1519,7 +1510,7 @@ int p9_client_remove(struct p9_fid *fid)
 	p9_tag_remove(clnt, req);
 error:
 	if (err == -ERESTARTSYS)
-		p9_client_clunk(fid);
+		p9_fid_put(fid);
 	else
 		p9_fid_destroy(fid);
 	return err;
@@ -2042,7 +2033,7 @@ struct p9_fid *p9_client_xattrwalk(struct p9_fid *file_fid,
 		 attr_fid->fid, *attr_size);
 	return attr_fid;
 clunk_fid:
-	p9_client_clunk(attr_fid);
+	p9_fid_put(attr_fid);
 	attr_fid = NULL;
 error:
 	if (attr_fid && attr_fid != file_fid)
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH v2 05/06] 9p fid refcount: add a 9p_fid_ref tracepoint
  2022-06-12 22:46   ` Steven Rostedt
@ 2022-06-12 23:46     ` Dominique Martinet
  2022-06-13  7:00       ` Dominique Martinet
  0 siblings, 1 reply; 28+ messages in thread
From: Dominique Martinet @ 2022-06-12 23:46 UTC (permalink / raw)
  To: Christian Schoenebeck, Tyler Hicks, Eric Van Hensbergen,
	Latchesar Ionkov, Dominique Martinet, David S. Miller,
	Jakub Kicinski, Paolo Abeni, Steven Rostedt, Ingo Molnar
  Cc: v9fs-developer, linux-kernel, netdev

This adds a tracepoint event for 9p fid lifecycle tracing: when a fid
is created, its reference count increased/decreased, and freed.
The new 9p_fid_ref tracepoint should help anyone wishing to debug any
fid problem such as missing clunk (destroy) or use-after-free.

Signed-off-by: Dominique Martinet <asmadeus@codewreck.org>
---

Steven, thank you for the review!

By changelog, is the commit message enough?

I've applied your suggestion to use DECLARE_TRACEPOINT + enable checks,
it doesn't seem to have many users but it looks good to me.

v1-v2:
 - added rationale to commit message
 - adjusted to use DECLARE_TRACEPOINT + tracepoint_enable() in header

 include/net/9p/client.h   | 13 +++++++++++
 include/trace/events/9p.h | 48 +++++++++++++++++++++++++++++++++++++++
 net/9p/client.c           | 17 +++++++++++++-
 3 files changed, 77 insertions(+), 1 deletion(-)

diff --git a/include/net/9p/client.h b/include/net/9p/client.h
index 9fd38d674057..6f347983705d 100644
--- a/include/net/9p/client.h
+++ b/include/net/9p/client.h
@@ -11,6 +11,7 @@
 
 #include <linux/utsname.h>
 #include <linux/idr.h>
+#include <linux/tracepoint-defs.h>
 
 /* Number of requests per row */
 #define P9_ROW_MAXTAG 255
@@ -237,8 +238,17 @@ static inline int p9_req_try_get(struct p9_req_t *r)
 
 int p9_req_put(struct p9_req_t *r);
 
+/* We cannot have the real tracepoints in header files,
+ * use a wrapper function */
+DECLARE_TRACEPOINT(9p_fid_ref);
+void do_trace_9p_fid_get(struct p9_fid *fid);
+void do_trace_9p_fid_put(struct p9_fid *fid);
+
 static inline struct p9_fid *p9_fid_get(struct p9_fid *fid)
 {
+	if (tracepoint_enabled(9p_fid_ref))
+		do_trace_9p_fid_get(fid);
+
 	refcount_inc(&fid->count);
 
 	return fid;
@@ -249,6 +259,9 @@ static inline int p9_fid_put(struct p9_fid *fid)
 	if (!fid || IS_ERR(fid))
 		return 0;
 
+	if (tracepoint_enabled(9p_fid_ref))
+		do_trace_9p_fid_put(fid);
+
 	if (!refcount_dec_and_test(&fid->count))
 		return 0;
 
diff --git a/include/trace/events/9p.h b/include/trace/events/9p.h
index 78c5608a1648..4dfa6d7f83ba 100644
--- a/include/trace/events/9p.h
+++ b/include/trace/events/9p.h
@@ -77,6 +77,13 @@
 		EM( P9_TWSTAT,		"P9_TWSTAT" )			\
 		EMe(P9_RWSTAT,		"P9_RWSTAT" )
 
+
+#define P9_FID_REFTYPE							\
+		EM( P9_FID_REF_CREATE,	"create " )			\
+		EM( P9_FID_REF_GET,	"get    " )			\
+		EM( P9_FID_REF_PUT,	"put    " )			\
+		EMe(P9_FID_REF_DESTROY,	"destroy" )
+
 /* Define EM() to export the enums to userspace via TRACE_DEFINE_ENUM() */
 #undef EM
 #undef EMe
@@ -84,6 +91,21 @@
 #define EMe(a, b)	TRACE_DEFINE_ENUM(a);
 
 P9_MSG_T
+P9_FID_REFTYPE
+
+/* And also use EM/EMe to define helper enums -- once */
+#ifndef __9P_DECLARE_TRACE_ENUMS_ONLY_ONCE
+#define __9P_DECLARE_TRACE_ENUMS_ONLY_ONCE
+#undef EM
+#undef EMe
+#define EM(a, b)	a,
+#define EMe(a, b)	a
+
+enum p9_fid_reftype {
+	P9_FID_REFTYPE
+} __mode(byte);
+
+#endif
 
 /*
  * Now redefine the EM() and EMe() macros to map the enums to the strings
@@ -96,6 +118,8 @@ P9_MSG_T
 
 #define show_9p_op(type)						\
 	__print_symbolic(type, P9_MSG_T)
+#define show_9p_fid_reftype(type)					\
+	__print_symbolic(type, P9_FID_REFTYPE)
 
 TRACE_EVENT(9p_client_req,
 	    TP_PROTO(struct p9_client *clnt, int8_t type, int tag),
@@ -168,6 +192,30 @@ TRACE_EVENT(9p_protocol_dump,
 		      __entry->tag, 0, __entry->line, 16, __entry->line + 16)
  );
 
+
+TRACE_EVENT(9p_fid_ref,
+	    TP_PROTO(struct p9_fid *fid, __u8 type),
+
+	    TP_ARGS(fid, type),
+
+	    TP_STRUCT__entry(
+		    __field(	int,	fid		)
+		    __field(	int,	refcount	)
+		    __field(	__u8, type	)
+		    ),
+
+	    TP_fast_assign(
+		    __entry->fid = fid->fid;
+		    __entry->refcount = refcount_read(&fid->count);
+		    __entry->type = type;
+		    ),
+
+	    TP_printk("%s fid %d, refcount %d",
+		      show_9p_fid_reftype(__entry->type),
+		      __entry->fid, __entry->refcount)
+);
+
+
 #endif /* _TRACE_9P_H */
 
 /* This part must be outside protection */
diff --git a/net/9p/client.c b/net/9p/client.c
index f3eb280c7d9d..06d67a02d431 100644
--- a/net/9p/client.c
+++ b/net/9p/client.c
@@ -907,8 +907,10 @@ static struct p9_fid *p9_fid_create(struct p9_client *clnt)
 			    GFP_NOWAIT);
 	spin_unlock_irq(&clnt->lock);
 	idr_preload_end();
-	if (!ret)
+	if (!ret) {
+		trace_9p_fid_ref(fid, P9_FID_REF_CREATE);
 		return fid;
+	}
 
 	kfree(fid);
 	return NULL;
@@ -920,6 +922,7 @@ static void p9_fid_destroy(struct p9_fid *fid)
 	unsigned long flags;
 
 	p9_debug(P9_DEBUG_FID, "fid %d\n", fid->fid);
+	trace_9p_fid_ref(fid, P9_FID_REF_DESTROY);
 	clnt = fid->clnt;
 	spin_lock_irqsave(&clnt->lock, flags);
 	idr_remove(&clnt->fids, fid->fid);
@@ -928,6 +931,18 @@ static void p9_fid_destroy(struct p9_fid *fid)
 	kfree(fid);
 }
 
+void do_trace_9p_fid_get(struct p9_fid *fid)
+{
+	trace_9p_fid_ref(fid, P9_FID_REF_GET);
+}
+EXPORT_SYMBOL(do_trace_9p_fid_get);
+
+void do_trace_9p_fid_put(struct p9_fid *fid)
+{
+	trace_9p_fid_ref(fid, P9_FID_REF_PUT);
+}
+EXPORT_SYMBOL(do_trace_9p_fid_put);
+
 static int p9_client_version(struct p9_client *c)
 {
 	int err = 0;
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* Re: [PATCH v2 05/06] 9p fid refcount: add a 9p_fid_ref tracepoint
  2022-06-12 23:46     ` [PATCH v2 " Dominique Martinet
@ 2022-06-13  7:00       ` Dominique Martinet
  0 siblings, 0 replies; 28+ messages in thread
From: Dominique Martinet @ 2022-06-13  7:00 UTC (permalink / raw)
  Cc: v9fs-developer, linux-kernel, netdev, Christian Schoenebeck,
	Tyler Hicks, Eric Van Hensbergen, Latchesar Ionkov,
	David S. Miller, Jakub Kicinski, Paolo Abeni, Ingo Molnar,
	Steven Rostedt

Dominique Martinet wrote on Mon, Jun 13, 2022 at 08:46:34AM +0900:
> I've applied your suggestion to use DECLARE_TRACEPOINT + enable checks,
> it doesn't seem to have many users but it looks good to me.
>
> diff --git a/include/net/9p/client.h b/include/net/9p/client.h
> index 9fd38d674057..6f347983705d 100644
> --- a/include/net/9p/client.h
> +++ b/include/net/9p/client.h
> @@ -237,8 +238,17 @@ static inline int p9_req_try_get(struct p9_req_t *r)
>  
>  int p9_req_put(struct p9_req_t *r);
>  
> +/* We cannot have the real tracepoints in header files,
> + * use a wrapper function */
> +DECLARE_TRACEPOINT(9p_fid_ref);
> +void do_trace_9p_fid_get(struct p9_fid *fid);
> +void do_trace_9p_fid_put(struct p9_fid *fid);
> +
>  static inline struct p9_fid *p9_fid_get(struct p9_fid *fid)
>  {
> +	if (tracepoint_enabled(9p_fid_ref))

This here requires __tracepoint_9p_fid_ref exported...

> diff --git a/net/9p/client.c b/net/9p/client.c
> index f3eb280c7d9d..06d67a02d431 100644
> --- a/net/9p/client.c
> +++ b/net/9p/client.c
> @@ -928,6 +931,18 @@ static void p9_fid_destroy(struct p9_fid *fid)
>  	kfree(fid);
>  }
>  

So I've also added this here:

+/* We also need to export tracepoint symbols for tracepoint_enabled() */
+EXPORT_TRACEPOINT_SYMBOL(9p_fid_ref);
+

Which looks frequent enough to probably be the right thing to do?

(It's small enough that I won't bother repost a v3 unless something else
comes up)

> +void do_trace_9p_fid_get(struct p9_fid *fid)
> +{
> +	trace_9p_fid_ref(fid, P9_FID_REF_GET);
> +}
> +EXPORT_SYMBOL(do_trace_9p_fid_get);
> +
> +void do_trace_9p_fid_put(struct p9_fid *fid)
> +{
> +	trace_9p_fid_ref(fid, P9_FID_REF_PUT);
> +}
> +EXPORT_SYMBOL(do_trace_9p_fid_put);
> +
>  static int p9_client_version(struct p9_client *c)
>  {
>  	int err = 0;

-- 
Dominique

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 01/06] 9p: fix fid refcount leak in v9fs_vfs_atomic_open_dotl
  2022-06-12  8:53 ` [PATCH 01/06] 9p: fix fid refcount leak in v9fs_vfs_atomic_open_dotl Dominique Martinet
@ 2022-06-13 16:27   ` Tyler Hicks
  2022-06-14 13:17   ` Christian Schoenebeck
  1 sibling, 0 replies; 28+ messages in thread
From: Tyler Hicks @ 2022-06-13 16:27 UTC (permalink / raw)
  To: Dominique Martinet
  Cc: Christian Schoenebeck, Eric Van Hensbergen, Latchesar Ionkov,
	Jianyong Wu, v9fs-developer, linux-kernel, stable

On 2022-06-12 17:53:24, Dominique Martinet wrote:
> We need to release directory fid if we fail halfway through open
> 
> This fixes fid leaking with xfstests generic 531
> 
> Fixes: 6636b6dcc3db ("9p: add refcount to p9_fid struct")
> Cc: stable@vger.kernel.org
> Reported-by: Tyler Hicks <tyhicks@linux.microsoft.com>

Reviewed-by: Tyler Hicks <tyhicks@linux.microsoft.com>

Tyler

> Signed-off-by: Dominique Martinet <asmadeus@codewreck.org>
> ---
>  fs/9p/vfs_inode_dotl.c | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c
> index d17502a738a9..b6eb1160296c 100644
> --- a/fs/9p/vfs_inode_dotl.c
> +++ b/fs/9p/vfs_inode_dotl.c
> @@ -274,6 +274,7 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
>  	if (IS_ERR(ofid)) {
>  		err = PTR_ERR(ofid);
>  		p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err);
> +		p9_client_clunk(dfid);
>  		goto out;
>  	}
>  
> @@ -285,6 +286,7 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
>  	if (err) {
>  		p9_debug(P9_DEBUG_VFS, "Failed to get acl values in creat %d\n",
>  			 err);
> +		p9_client_clunk(dfid);
>  		goto error;
>  	}
>  	err = p9_client_create_dotl(ofid, name, v9fs_open_to_dotl_flags(flags),
> @@ -292,6 +294,7 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
>  	if (err < 0) {
>  		p9_debug(P9_DEBUG_VFS, "p9_client_open_dotl failed in creat %d\n",
>  			 err);
> +		p9_client_clunk(dfid);
>  		goto error;
>  	}
>  	v9fs_invalidate_inode_attr(dir);
> -- 
> 2.35.1
> 

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 02/06] 9p: fix fid refcount leak in v9fs_vfs_get_link
  2022-06-12  8:53 ` [PATCH 02/06] 9p: fix fid refcount leak in v9fs_vfs_get_link Dominique Martinet
@ 2022-06-13 16:29   ` Tyler Hicks
  2022-06-14 13:19   ` Christian Schoenebeck
  1 sibling, 0 replies; 28+ messages in thread
From: Tyler Hicks @ 2022-06-13 16:29 UTC (permalink / raw)
  To: Dominique Martinet
  Cc: Christian Schoenebeck, Eric Van Hensbergen, Latchesar Ionkov,
	Jianyong Wu, v9fs-developer, linux-kernel, stable

On 2022-06-12 17:53:25, Dominique Martinet wrote:
> we check for protocol version later than required, after a fid has
> been obtained. Just move the version check earlier.
> 
> Fixes: 6636b6dcc3db ("9p: add refcount to p9_fid struct")
> Cc: stable@vger.kernel.org

Reviewed-by: Tyler Hicks <tyhicks@linux.microsoft.com>

Tyler

> Signed-off-by: Dominique Martinet <asmadeus@codewreck.org>
> ---
>  fs/9p/vfs_inode.c | 8 ++++----
>  1 file changed, 4 insertions(+), 4 deletions(-)
> 
> diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
> index 55367ecb9442..18c780ffd4b5 100644
> --- a/fs/9p/vfs_inode.c
> +++ b/fs/9p/vfs_inode.c
> @@ -1250,15 +1250,15 @@ static const char *v9fs_vfs_get_link(struct dentry *dentry,
>  		return ERR_PTR(-ECHILD);
>  
>  	v9ses = v9fs_dentry2v9ses(dentry);
> -	fid = v9fs_fid_lookup(dentry);
> +	if (!v9fs_proto_dotu(v9ses))
> +		return ERR_PTR(-EBADF);
> +
>  	p9_debug(P9_DEBUG_VFS, "%pd\n", dentry);
> +	fid = v9fs_fid_lookup(dentry);
>  
>  	if (IS_ERR(fid))
>  		return ERR_CAST(fid);
>  
> -	if (!v9fs_proto_dotu(v9ses))
> -		return ERR_PTR(-EBADF);
> -
>  	st = p9_client_stat(fid);
>  	p9_client_clunk(fid);
>  	if (IS_ERR(st))
> -- 
> 2.35.1
> 

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH v2 04/06] 9p fid refcount: add p9_fid_get/put wrappers
  2022-06-12 23:45   ` [PATCH v2 " Dominique Martinet
@ 2022-06-13 17:31     ` Tyler Hicks
  2022-06-14 13:55     ` Christian Schoenebeck
  1 sibling, 0 replies; 28+ messages in thread
From: Tyler Hicks @ 2022-06-13 17:31 UTC (permalink / raw)
  To: Dominique Martinet
  Cc: Christian Schoenebeck, Eric Van Hensbergen, Latchesar Ionkov,
	David S. Miller, Jakub Kicinski, Paolo Abeni, v9fs-developer,
	linux-kernel, netdev

On 2022-06-13 08:45:54, Dominique Martinet wrote:
> I was recently reminded that it is not clear that p9_client_clunk()
> was actually just decrementing refcount and clunking only when that
> reaches zero: make it clear through a set of helpers.
> 
> This will also allow instrumenting refcounting better for debugging
> next patch, which is the reason these are not defined as static inline:
> we won't be able to add trace events there...
> 

This is a very nice improvement.

Reviewed-by: Tyler Hicks <tyhicks@linux.microsoft.com>

Tyler

> Signed-off-by: Dominique Martinet <asmadeus@codewreck.org>
> ---
> v1 -> v2: p9_fid_get/put are now static inline in .h
> 
>  fs/9p/fid.c             | 18 ++++++++--------
>  fs/9p/fid.h             |  2 +-
>  fs/9p/vfs_addr.c        |  4 ++--
>  fs/9p/vfs_dentry.c      |  4 ++--
>  fs/9p/vfs_dir.c         |  2 +-
>  fs/9p/vfs_file.c        |  4 ++--
>  fs/9p/vfs_inode.c       | 48 ++++++++++++++++++++---------------------
>  fs/9p/vfs_inode_dotl.c  | 42 ++++++++++++++++++------------------
>  fs/9p/vfs_super.c       |  6 +++---
>  fs/9p/xattr.c           |  8 +++----
>  include/net/9p/client.h | 18 ++++++++++++++++
>  net/9p/client.c         | 15 +++----------
>  12 files changed, 90 insertions(+), 81 deletions(-)
> 
> diff --git a/fs/9p/fid.c b/fs/9p/fid.c
> index e8fad28fc5bd..d792499349c4 100644
> --- a/fs/9p/fid.c
> +++ b/fs/9p/fid.c
> @@ -56,7 +56,7 @@ static struct p9_fid *v9fs_fid_find_inode(struct inode *inode, kuid_t uid)
>  	h = (struct hlist_head *)&inode->i_private;
>  	hlist_for_each_entry(fid, h, ilist) {
>  		if (uid_eq(fid->uid, uid)) {
> -			refcount_inc(&fid->count);
> +			p9_fid_get(fid);
>  			ret = fid;
>  			break;
>  		}
> @@ -104,7 +104,7 @@ static struct p9_fid *v9fs_fid_find(struct dentry *dentry, kuid_t uid, int any)
>  		hlist_for_each_entry(fid, h, dlist) {
>  			if (any || uid_eq(fid->uid, uid)) {
>  				ret = fid;
> -				refcount_inc(&ret->count);
> +				p9_fid_get(ret);
>  				break;
>  			}
>  		}
> @@ -172,7 +172,7 @@ static struct p9_fid *v9fs_fid_lookup_with_uid(struct dentry *dentry,
>  		old_fid = fid;
>  
>  		fid = p9_client_walk(old_fid, 1, &dentry->d_name.name, 1);
> -		p9_client_clunk(old_fid);
> +		p9_fid_put(old_fid);
>  		goto fid_out;
>  	}
>  	up_read(&v9ses->rename_sem);
> @@ -194,7 +194,7 @@ static struct p9_fid *v9fs_fid_lookup_with_uid(struct dentry *dentry,
>  		if (IS_ERR(root_fid))
>  			return root_fid;
>  
> -		refcount_inc(&root_fid->count);
> +		p9_fid_get(root_fid);
>  		v9fs_fid_add(dentry->d_sb->s_root, root_fid);
>  	}
>  	/* If we are root ourself just return that */
> @@ -225,7 +225,7 @@ static struct p9_fid *v9fs_fid_lookup_with_uid(struct dentry *dentry,
>  				     old_fid == root_fid /* clone */);
>  		/* non-cloning walk will return the same fid */
>  		if (fid != old_fid) {
> -			p9_client_clunk(old_fid);
> +			p9_fid_put(old_fid);
>  			old_fid = fid;
>  		}
>  		if (IS_ERR(fid)) {
> @@ -240,11 +240,11 @@ static struct p9_fid *v9fs_fid_lookup_with_uid(struct dentry *dentry,
>  		spin_lock(&dentry->d_lock);
>  		if (d_unhashed(dentry)) {
>  			spin_unlock(&dentry->d_lock);
> -			p9_client_clunk(fid);
> +			p9_fid_put(fid);
>  			fid = ERR_PTR(-ENOENT);
>  		} else {
>  			__add_fid(dentry, fid);
> -			refcount_inc(&fid->count);
> +			p9_fid_get(fid);
>  			spin_unlock(&dentry->d_lock);
>  		}
>  	}
> @@ -301,7 +301,7 @@ struct p9_fid *v9fs_writeback_fid(struct dentry *dentry)
>  	fid = clone_fid(ofid);
>  	if (IS_ERR(fid))
>  		goto error_out;
> -	p9_client_clunk(ofid);
> +	p9_fid_put(ofid);
>  	/*
>  	 * writeback fid will only be used to write back the
>  	 * dirty pages. We always request for the open fid in read-write
> @@ -310,7 +310,7 @@ struct p9_fid *v9fs_writeback_fid(struct dentry *dentry)
>  	 */
>  	err = p9_client_open(fid, O_RDWR);
>  	if (err < 0) {
> -		p9_client_clunk(fid);
> +		p9_fid_put(fid);
>  		fid = ERR_PTR(err);
>  		goto error_out;
>  	}
> diff --git a/fs/9p/fid.h b/fs/9p/fid.h
> index f7f33509e169..3168dfad510e 100644
> --- a/fs/9p/fid.h
> +++ b/fs/9p/fid.h
> @@ -29,7 +29,7 @@ static inline struct p9_fid *v9fs_fid_clone(struct dentry *dentry)
>  		return fid;
>  
>  	nfid = clone_fid(fid);
> -	p9_client_clunk(fid);
> +	p9_fid_put(fid);
>  	return nfid;
>  }
>  #endif
> diff --git a/fs/9p/vfs_addr.c b/fs/9p/vfs_addr.c
> index 8ce82ff1e40a..ed598160e0c6 100644
> --- a/fs/9p/vfs_addr.c
> +++ b/fs/9p/vfs_addr.c
> @@ -60,7 +60,7 @@ static int v9fs_init_request(struct netfs_io_request *rreq, struct file *file)
>  {
>  	struct p9_fid *fid = file->private_data;
>  
> -	refcount_inc(&fid->count);
> +	p9_fid_get(fid);
>  	rreq->netfs_priv = fid;
>  	return 0;
>  }
> @@ -74,7 +74,7 @@ static void v9fs_req_cleanup(struct address_space *mapping, void *priv)
>  {
>  	struct p9_fid *fid = priv;
>  
> -	p9_client_clunk(fid);
> +	p9_fid_put(fid);
>  }
>  
>  /**
> diff --git a/fs/9p/vfs_dentry.c b/fs/9p/vfs_dentry.c
> index 1c609e99d280..f89f01734587 100644
> --- a/fs/9p/vfs_dentry.c
> +++ b/fs/9p/vfs_dentry.c
> @@ -54,7 +54,7 @@ static void v9fs_dentry_release(struct dentry *dentry)
>  	p9_debug(P9_DEBUG_VFS, " dentry: %pd (%p)\n",
>  		 dentry, dentry);
>  	hlist_for_each_safe(p, n, (struct hlist_head *)&dentry->d_fsdata)
> -		p9_client_clunk(hlist_entry(p, struct p9_fid, dlist));
> +		p9_fid_put(hlist_entry(p, struct p9_fid, dlist));
>  	dentry->d_fsdata = NULL;
>  }
>  
> @@ -85,7 +85,7 @@ static int v9fs_lookup_revalidate(struct dentry *dentry, unsigned int flags)
>  			retval = v9fs_refresh_inode_dotl(fid, inode);
>  		else
>  			retval = v9fs_refresh_inode(fid, inode);
> -		p9_client_clunk(fid);
> +		p9_fid_put(fid);
>  
>  		if (retval == -ENOENT)
>  			return 0;
> diff --git a/fs/9p/vfs_dir.c b/fs/9p/vfs_dir.c
> index 958680f7f23e..000fbaae9b18 100644
> --- a/fs/9p/vfs_dir.c
> +++ b/fs/9p/vfs_dir.c
> @@ -218,7 +218,7 @@ int v9fs_dir_release(struct inode *inode, struct file *filp)
>  		spin_lock(&inode->i_lock);
>  		hlist_del(&fid->ilist);
>  		spin_unlock(&inode->i_lock);
> -		p9_client_clunk(fid);
> +		p9_fid_put(fid);
>  	}
>  
>  	if ((filp->f_mode & FMODE_WRITE)) {
> diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c
> index 2573c08f335c..8276f3af35d7 100644
> --- a/fs/9p/vfs_file.c
> +++ b/fs/9p/vfs_file.c
> @@ -63,7 +63,7 @@ int v9fs_file_open(struct inode *inode, struct file *file)
>  
>  		err = p9_client_open(fid, omode);
>  		if (err < 0) {
> -			p9_client_clunk(fid);
> +			p9_fid_put(fid);
>  			return err;
>  		}
>  		if ((file->f_flags & O_APPEND) &&
> @@ -98,7 +98,7 @@ int v9fs_file_open(struct inode *inode, struct file *file)
>  	v9fs_open_fid_add(inode, fid);
>  	return 0;
>  out_error:
> -	p9_client_clunk(file->private_data);
> +	p9_fid_put(file->private_data);
>  	file->private_data = NULL;
>  	return err;
>  }
> diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
> index 18c780ffd4b5..38186d1a1440 100644
> --- a/fs/9p/vfs_inode.c
> +++ b/fs/9p/vfs_inode.c
> @@ -399,7 +399,7 @@ void v9fs_evict_inode(struct inode *inode)
>  	fscache_relinquish_cookie(v9fs_inode_cookie(v9inode), false);
>  	/* clunk the fid stashed in writeback_fid */
>  	if (v9inode->writeback_fid) {
> -		p9_client_clunk(v9inode->writeback_fid);
> +		p9_fid_put(v9inode->writeback_fid);
>  		v9inode->writeback_fid = NULL;
>  	}
>  }
> @@ -568,7 +568,7 @@ static int v9fs_remove(struct inode *dir, struct dentry *dentry, int flags)
>  	if (v9fs_proto_dotl(v9ses))
>  		retval = p9_client_unlinkat(dfid, dentry->d_name.name,
>  					    v9fs_at_to_dotl_flags(flags));
> -	p9_client_clunk(dfid);
> +	p9_fid_put(dfid);
>  	if (retval == -EOPNOTSUPP) {
>  		/* Try the one based on path */
>  		v9fid = v9fs_fid_clone(dentry);
> @@ -632,14 +632,14 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,
>  	if (IS_ERR(ofid)) {
>  		err = PTR_ERR(ofid);
>  		p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err);
> -		p9_client_clunk(dfid);
> +		p9_fid_put(dfid);
>  		return ERR_PTR(err);
>  	}
>  
>  	err = p9_client_fcreate(ofid, name, perm, mode, extension);
>  	if (err < 0) {
>  		p9_debug(P9_DEBUG_VFS, "p9_client_fcreate failed %d\n", err);
> -		p9_client_clunk(dfid);
> +		p9_fid_put(dfid);
>  		goto error;
>  	}
>  
> @@ -651,7 +651,7 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,
>  			p9_debug(P9_DEBUG_VFS,
>  				   "p9_client_walk failed %d\n", err);
>  			fid = NULL;
> -			p9_client_clunk(dfid);
> +			p9_fid_put(dfid);
>  			goto error;
>  		}
>  		/*
> @@ -662,20 +662,20 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,
>  			err = PTR_ERR(inode);
>  			p9_debug(P9_DEBUG_VFS,
>  				   "inode creation failed %d\n", err);
> -			p9_client_clunk(dfid);
> +			p9_fid_put(dfid);
>  			goto error;
>  		}
>  		v9fs_fid_add(dentry, fid);
>  		d_instantiate(dentry, inode);
>  	}
> -	p9_client_clunk(dfid);
> +	p9_fid_put(dfid);
>  	return ofid;
>  error:
>  	if (ofid)
> -		p9_client_clunk(ofid);
> +		p9_fid_put(ofid);
>  
>  	if (fid)
> -		p9_client_clunk(fid);
> +		p9_fid_put(fid);
>  
>  	return ERR_PTR(err);
>  }
> @@ -707,7 +707,7 @@ v9fs_vfs_create(struct user_namespace *mnt_userns, struct inode *dir,
>  		return PTR_ERR(fid);
>  
>  	v9fs_invalidate_inode_attr(dir);
> -	p9_client_clunk(fid);
> +	p9_fid_put(fid);
>  
>  	return 0;
>  }
> @@ -743,7 +743,7 @@ static int v9fs_vfs_mkdir(struct user_namespace *mnt_userns, struct inode *dir,
>  	}
>  
>  	if (fid)
> -		p9_client_clunk(fid);
> +		p9_fid_put(fid);
>  
>  	return err;
>  }
> @@ -784,7 +784,7 @@ struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
>  	 */
>  	name = dentry->d_name.name;
>  	fid = p9_client_walk(dfid, 1, &name, 1);
> -	p9_client_clunk(dfid);
> +	p9_fid_put(dfid);
>  	if (fid == ERR_PTR(-ENOENT))
>  		inode = NULL;
>  	else if (IS_ERR(fid))
> @@ -807,7 +807,7 @@ struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
>  		else if (!IS_ERR(res))
>  			v9fs_fid_add(res, fid);
>  		else
> -			p9_client_clunk(fid);
> +			p9_fid_put(fid);
>  	}
>  	return res;
>  }
> @@ -890,7 +890,7 @@ v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry,
>  
>  error:
>  	if (fid)
> -		p9_client_clunk(fid);
> +		p9_fid_put(fid);
>  	goto out;
>  }
>  
> @@ -958,7 +958,7 @@ v9fs_vfs_rename(struct user_namespace *mnt_userns, struct inode *old_dir,
>  	dfid = v9fs_parent_fid(old_dentry);
>  	olddirfid = clone_fid(dfid);
>  	if (dfid && !IS_ERR(dfid))
> -		p9_client_clunk(dfid);
> +		p9_fid_put(dfid);
>  
>  	if (IS_ERR(olddirfid)) {
>  		retval = PTR_ERR(olddirfid);
> @@ -967,7 +967,7 @@ v9fs_vfs_rename(struct user_namespace *mnt_userns, struct inode *old_dir,
>  
>  	dfid = v9fs_parent_fid(new_dentry);
>  	newdirfid = clone_fid(dfid);
> -	p9_client_clunk(dfid);
> +	p9_fid_put(dfid);
>  
>  	if (IS_ERR(newdirfid)) {
>  		retval = PTR_ERR(newdirfid);
> @@ -1019,13 +1019,13 @@ v9fs_vfs_rename(struct user_namespace *mnt_userns, struct inode *old_dir,
>  		d_move(old_dentry, new_dentry);
>  	}
>  	up_write(&v9ses->rename_sem);
> -	p9_client_clunk(newdirfid);
> +	p9_fid_put(newdirfid);
>  
>  clunk_olddir:
> -	p9_client_clunk(olddirfid);
> +	p9_fid_put(olddirfid);
>  
>  done:
> -	p9_client_clunk(oldfid);
> +	p9_fid_put(oldfid);
>  	return retval;
>  }
>  
> @@ -1059,7 +1059,7 @@ v9fs_vfs_getattr(struct user_namespace *mnt_userns, const struct path *path,
>  		return PTR_ERR(fid);
>  
>  	st = p9_client_stat(fid);
> -	p9_client_clunk(fid);
> +	p9_fid_put(fid);
>  	if (IS_ERR(st))
>  		return PTR_ERR(st);
>  
> @@ -1135,7 +1135,7 @@ static int v9fs_vfs_setattr(struct user_namespace *mnt_userns,
>  	retval = p9_client_wstat(fid, &wstat);
>  
>  	if (use_dentry)
> -		p9_client_clunk(fid);
> +		p9_fid_put(fid);
>  
>  	if (retval < 0)
>  		return retval;
> @@ -1260,7 +1260,7 @@ static const char *v9fs_vfs_get_link(struct dentry *dentry,
>  		return ERR_CAST(fid);
>  
>  	st = p9_client_stat(fid);
> -	p9_client_clunk(fid);
> +	p9_fid_put(fid);
>  	if (IS_ERR(st))
>  		return ERR_CAST(st);
>  
> @@ -1307,7 +1307,7 @@ static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry,
>  		return PTR_ERR(fid);
>  
>  	v9fs_invalidate_inode_attr(dir);
> -	p9_client_clunk(fid);
> +	p9_fid_put(fid);
>  	return 0;
>  }
>  
> @@ -1363,7 +1363,7 @@ v9fs_vfs_link(struct dentry *old_dentry, struct inode *dir,
>  		v9fs_refresh_inode(oldfid, d_inode(old_dentry));
>  		v9fs_invalidate_inode_attr(dir);
>  	}
> -	p9_client_clunk(oldfid);
> +	p9_fid_put(oldfid);
>  	return retval;
>  }
>  
> diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c
> index b6eb1160296c..09b124fe349c 100644
> --- a/fs/9p/vfs_inode_dotl.c
> +++ b/fs/9p/vfs_inode_dotl.c
> @@ -274,7 +274,7 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
>  	if (IS_ERR(ofid)) {
>  		err = PTR_ERR(ofid);
>  		p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err);
> -		p9_client_clunk(dfid);
> +		p9_fid_put(dfid);
>  		goto out;
>  	}
>  
> @@ -286,7 +286,7 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
>  	if (err) {
>  		p9_debug(P9_DEBUG_VFS, "Failed to get acl values in creat %d\n",
>  			 err);
> -		p9_client_clunk(dfid);
> +		p9_fid_put(dfid);
>  		goto error;
>  	}
>  	err = p9_client_create_dotl(ofid, name, v9fs_open_to_dotl_flags(flags),
> @@ -294,14 +294,14 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
>  	if (err < 0) {
>  		p9_debug(P9_DEBUG_VFS, "p9_client_open_dotl failed in creat %d\n",
>  			 err);
> -		p9_client_clunk(dfid);
> +		p9_fid_put(dfid);
>  		goto error;
>  	}
>  	v9fs_invalidate_inode_attr(dir);
>  
>  	/* instantiate inode and assign the unopened fid to the dentry */
>  	fid = p9_client_walk(dfid, 1, &name, 1);
> -	p9_client_clunk(dfid);
> +	p9_fid_put(dfid);
>  	if (IS_ERR(fid)) {
>  		err = PTR_ERR(fid);
>  		p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err);
> @@ -358,10 +358,10 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
>  
>  error:
>  	if (fid)
> -		p9_client_clunk(fid);
> +		p9_fid_put(fid);
>  err_clunk_old_fid:
>  	if (ofid)
> -		p9_client_clunk(ofid);
> +		p9_fid_put(ofid);
>  	goto out;
>  }
>  
> @@ -458,9 +458,9 @@ static int v9fs_vfs_mkdir_dotl(struct user_namespace *mnt_userns,
>  	v9fs_invalidate_inode_attr(dir);
>  error:
>  	if (fid)
> -		p9_client_clunk(fid);
> +		p9_fid_put(fid);
>  	v9fs_put_acl(dacl, pacl);
> -	p9_client_clunk(dfid);
> +	p9_fid_put(dfid);
>  	return err;
>  }
>  
> @@ -489,7 +489,7 @@ v9fs_vfs_getattr_dotl(struct user_namespace *mnt_userns,
>  	 */
>  
>  	st = p9_client_getattr_dotl(fid, P9_STATS_ALL);
> -	p9_client_clunk(fid);
> +	p9_fid_put(fid);
>  	if (IS_ERR(st))
>  		return PTR_ERR(st);
>  
> @@ -603,7 +603,7 @@ int v9fs_vfs_setattr_dotl(struct user_namespace *mnt_userns,
>  	retval = p9_client_setattr(fid, &p9attr);
>  	if (retval < 0) {
>  		if (use_dentry)
> -			p9_client_clunk(fid);
> +			p9_fid_put(fid);
>  		return retval;
>  	}
>  
> @@ -619,12 +619,12 @@ int v9fs_vfs_setattr_dotl(struct user_namespace *mnt_userns,
>  		retval = v9fs_acl_chmod(inode, fid);
>  		if (retval < 0) {
>  			if (use_dentry)
> -				p9_client_clunk(fid);
> +				p9_fid_put(fid);
>  			return retval;
>  		}
>  	}
>  	if (use_dentry)
> -		p9_client_clunk(fid);
> +		p9_fid_put(fid);
>  
>  	return 0;
>  }
> @@ -771,9 +771,9 @@ v9fs_vfs_symlink_dotl(struct user_namespace *mnt_userns, struct inode *dir,
>  
>  error:
>  	if (fid)
> -		p9_client_clunk(fid);
> +		p9_fid_put(fid);
>  
> -	p9_client_clunk(dfid);
> +	p9_fid_put(dfid);
>  	return err;
>  }
>  
> @@ -803,14 +803,14 @@ v9fs_vfs_link_dotl(struct dentry *old_dentry, struct inode *dir,
>  
>  	oldfid = v9fs_fid_lookup(old_dentry);
>  	if (IS_ERR(oldfid)) {
> -		p9_client_clunk(dfid);
> +		p9_fid_put(dfid);
>  		return PTR_ERR(oldfid);
>  	}
>  
>  	err = p9_client_link(dfid, oldfid, dentry->d_name.name);
>  
> -	p9_client_clunk(dfid);
> -	p9_client_clunk(oldfid);
> +	p9_fid_put(dfid);
> +	p9_fid_put(oldfid);
>  	if (err < 0) {
>  		p9_debug(P9_DEBUG_VFS, "p9_client_link failed %d\n", err);
>  		return err;
> @@ -826,7 +826,7 @@ v9fs_vfs_link_dotl(struct dentry *old_dentry, struct inode *dir,
>  			return PTR_ERR(fid);
>  
>  		v9fs_refresh_inode_dotl(fid, d_inode(old_dentry));
> -		p9_client_clunk(fid);
> +		p9_fid_put(fid);
>  	}
>  	ihold(d_inode(old_dentry));
>  	d_instantiate(dentry, d_inode(old_dentry));
> @@ -924,9 +924,9 @@ v9fs_vfs_mknod_dotl(struct user_namespace *mnt_userns, struct inode *dir,
>  	}
>  error:
>  	if (fid)
> -		p9_client_clunk(fid);
> +		p9_fid_put(fid);
>  	v9fs_put_acl(dacl, pacl);
> -	p9_client_clunk(dfid);
> +	p9_fid_put(dfid);
>  
>  	return err;
>  }
> @@ -956,7 +956,7 @@ v9fs_vfs_get_link_dotl(struct dentry *dentry,
>  	if (IS_ERR(fid))
>  		return ERR_CAST(fid);
>  	retval = p9_client_readlink(fid, &target);
> -	p9_client_clunk(fid);
> +	p9_fid_put(fid);
>  	if (retval)
>  		return ERR_PTR(retval);
>  	set_delayed_call(done, kfree_link, target);
> diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c
> index 97e23b4e6982..bf350fad9500 100644
> --- a/fs/9p/vfs_super.c
> +++ b/fs/9p/vfs_super.c
> @@ -190,7 +190,7 @@ static struct dentry *v9fs_mount(struct file_system_type *fs_type, int flags,
>  	return dget(sb->s_root);
>  
>  clunk_fid:
> -	p9_client_clunk(fid);
> +	p9_fid_put(fid);
>  	v9fs_session_close(v9ses);
>  free_session:
>  	kfree(v9ses);
> @@ -203,7 +203,7 @@ static struct dentry *v9fs_mount(struct file_system_type *fs_type, int flags,
>  	 * attached the fid to dentry so it won't get clunked
>  	 * automatically.
>  	 */
> -	p9_client_clunk(fid);
> +	p9_fid_put(fid);
>  	deactivate_locked_super(sb);
>  	return ERR_PTR(retval);
>  }
> @@ -270,7 +270,7 @@ static int v9fs_statfs(struct dentry *dentry, struct kstatfs *buf)
>  	}
>  	res = simple_statfs(dentry, buf);
>  done:
> -	p9_client_clunk(fid);
> +	p9_fid_put(fid);
>  	return res;
>  }
>  
> diff --git a/fs/9p/xattr.c b/fs/9p/xattr.c
> index a824441b95a2..1f9298a4bd42 100644
> --- a/fs/9p/xattr.c
> +++ b/fs/9p/xattr.c
> @@ -44,7 +44,7 @@ ssize_t v9fs_fid_xattr_get(struct p9_fid *fid, const char *name,
>  		if (err)
>  			retval = err;
>  	}
> -	p9_client_clunk(attr_fid);
> +	p9_fid_put(attr_fid);
>  	return retval;
>  }
>  
> @@ -71,7 +71,7 @@ ssize_t v9fs_xattr_get(struct dentry *dentry, const char *name,
>  	if (IS_ERR(fid))
>  		return PTR_ERR(fid);
>  	ret = v9fs_fid_xattr_get(fid, name, buffer, buffer_size);
> -	p9_client_clunk(fid);
> +	p9_fid_put(fid);
>  
>  	return ret;
>  }
> @@ -98,7 +98,7 @@ int v9fs_xattr_set(struct dentry *dentry, const char *name,
>  	if (IS_ERR(fid))
>  		return PTR_ERR(fid);
>  	ret = v9fs_fid_xattr_set(fid, name, value, value_len, flags);
> -	p9_client_clunk(fid);
> +	p9_fid_put(fid);
>  	return ret;
>  }
>  
> @@ -128,7 +128,7 @@ int v9fs_fid_xattr_set(struct p9_fid *fid, const char *name,
>  			 retval);
>  	else
>  		p9_client_write(fid, 0, &from, &retval);
> -	err = p9_client_clunk(fid);
> +	err = p9_fid_put(fid);
>  	if (!retval && err)
>  		retval = err;
>  	return retval;
> diff --git a/include/net/9p/client.h b/include/net/9p/client.h
> index ec1d1706f43c..9fd38d674057 100644
> --- a/include/net/9p/client.h
> +++ b/include/net/9p/client.h
> @@ -237,6 +237,24 @@ static inline int p9_req_try_get(struct p9_req_t *r)
>  
>  int p9_req_put(struct p9_req_t *r);
>  
> +static inline struct p9_fid *p9_fid_get(struct p9_fid *fid)
> +{
> +	refcount_inc(&fid->count);
> +
> +	return fid;
> +}
> +
> +static inline int p9_fid_put(struct p9_fid *fid)
> +{
> +	if (!fid || IS_ERR(fid))
> +		return 0;
> +
> +	if (!refcount_dec_and_test(&fid->count))
> +		return 0;
> +
> +	return p9_client_clunk(fid);
> +}
> +
>  void p9_client_cb(struct p9_client *c, struct p9_req_t *req, int status);
>  
>  int p9_parse_header(struct p9_fcall *pdu, int32_t *size, int8_t *type,
> diff --git a/net/9p/client.c b/net/9p/client.c
> index 8bba0d9cf975..f3eb280c7d9d 100644
> --- a/net/9p/client.c
> +++ b/net/9p/client.c
> @@ -1228,7 +1228,7 @@ struct p9_fid *p9_client_walk(struct p9_fid *oldfid, uint16_t nwname,
>  
>  clunk_fid:
>  	kfree(wqids);
> -	p9_client_clunk(fid);
> +	p9_fid_put(fid);
>  	fid = NULL;
>  
>  error:
> @@ -1459,15 +1459,6 @@ int p9_client_clunk(struct p9_fid *fid)
>  	struct p9_req_t *req;
>  	int retries = 0;
>  
> -	if (!fid || IS_ERR(fid)) {
> -		pr_warn("%s (%d): Trying to clunk with invalid fid\n",
> -			__func__, task_pid_nr(current));
> -		dump_stack();
> -		return 0;
> -	}
> -	if (!refcount_dec_and_test(&fid->count))
> -		return 0;
> -
>  again:
>  	p9_debug(P9_DEBUG_9P, ">>> TCLUNK fid %d (try %d)\n",
>  		 fid->fid, retries);
> @@ -1519,7 +1510,7 @@ int p9_client_remove(struct p9_fid *fid)
>  	p9_tag_remove(clnt, req);
>  error:
>  	if (err == -ERESTARTSYS)
> -		p9_client_clunk(fid);
> +		p9_fid_put(fid);
>  	else
>  		p9_fid_destroy(fid);
>  	return err;
> @@ -2042,7 +2033,7 @@ struct p9_fid *p9_client_xattrwalk(struct p9_fid *file_fid,
>  		 attr_fid->fid, *attr_size);
>  	return attr_fid;
>  clunk_fid:
> -	p9_client_clunk(attr_fid);
> +	p9_fid_put(attr_fid);
>  	attr_fid = NULL;
>  error:
>  	if (attr_fid && attr_fid != file_fid)
> -- 
> 2.35.1
> 

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 06/06] 9p fid refcount: cleanup p9_fid_put calls
  2022-06-12  8:53 ` [PATCH 06/06] 9p fid refcount: cleanup p9_fid_put calls Dominique Martinet
@ 2022-06-13 17:55   ` Tyler Hicks
  2022-06-13 19:50     ` Dominique Martinet
  0 siblings, 1 reply; 28+ messages in thread
From: Tyler Hicks @ 2022-06-13 17:55 UTC (permalink / raw)
  To: Dominique Martinet
  Cc: Christian Schoenebeck, Eric Van Hensbergen, Latchesar Ionkov,
	v9fs-developer, linux-kernel

On 2022-06-12 17:53:29, Dominique Martinet wrote:
> Simplify p9_fid_put cleanup path in many 9p functions since the function
> is noop on null or error fids.
> 
> Also make the *_add_fid() helpers "steal" the fid by nulling its
> pointer, so put after them will be noop.
> 
> This should lead to no change of behaviour

Another really nice cleanup. Only one small comment below.

> 
> Signed-off-by: Dominique Martinet <asmadeus@codewreck.org>
> ---
>  fs/9p/fid.c            | 24 +++++++++++------
>  fs/9p/fid.h            |  4 +--
>  fs/9p/vfs_file.c       |  5 ++--
>  fs/9p/vfs_inode.c      | 61 +++++++++++++++++-------------------------
>  fs/9p/vfs_inode_dotl.c | 58 +++++++++++++--------------------------
>  fs/9p/vfs_super.c      |  2 +-
>  6 files changed, 64 insertions(+), 90 deletions(-)
> 
> diff --git a/fs/9p/fid.c b/fs/9p/fid.c
> index d792499349c4..289a85eae2ae 100644
> --- a/fs/9p/fid.c
> +++ b/fs/9p/fid.c
> @@ -31,11 +31,15 @@ static inline void __add_fid(struct dentry *dentry, struct p9_fid *fid)
>   * @fid: fid to add
>   *
>   */
> -void v9fs_fid_add(struct dentry *dentry, struct p9_fid *fid)
> +void v9fs_fid_add(struct dentry *dentry, struct p9_fid **pfid)
>  {
> +	struct p9_fid *fid = *pfid;
> +
>  	spin_lock(&dentry->d_lock);
>  	__add_fid(dentry, fid);
>  	spin_unlock(&dentry->d_lock);
> +
> +	*pfid = NULL;
>  }
>  
>  /**
> @@ -72,11 +76,15 @@ static struct p9_fid *v9fs_fid_find_inode(struct inode *inode, kuid_t uid)
>   *
>   */
>  
> -void v9fs_open_fid_add(struct inode *inode, struct p9_fid *fid)
> +void v9fs_open_fid_add(struct inode *inode, struct p9_fid **pfid)
>  {
> +	struct p9_fid *fid = *pfid;
> +
>  	spin_lock(&inode->i_lock);
>  	hlist_add_head(&fid->ilist, (struct hlist_head *)&inode->i_private);
>  	spin_unlock(&inode->i_lock);
> +
> +	*pfid = NULL;
>  }
>  
>  
> @@ -189,13 +197,13 @@ static struct p9_fid *v9fs_fid_lookup_with_uid(struct dentry *dentry,
>  		else
>  			uname = v9ses->uname;
>  
> -		root_fid = p9_client_attach(v9ses->clnt, NULL, uname, uid,
> -					    v9ses->aname);
> -		if (IS_ERR(root_fid))
> -			return root_fid;
> +		fid = p9_client_attach(v9ses->clnt, NULL, uname, uid,

To keep the readability benefits in my "9p: Track the root fid with its
own variable during lookups" patch, I think root_fid should be assigned
here and then used in the error check and return statement.

> +				       v9ses->aname);
> +		if (IS_ERR(fid))
> +			return fid;
>  
> -		p9_fid_get(root_fid);
> -		v9fs_fid_add(dentry->d_sb->s_root, root_fid);
> +		root_fid = p9_fid_get(fid);
> +		v9fs_fid_add(dentry->d_sb->s_root, &fid);

root_fid should be used in the two lines above, too.

With these changes, 

Reviewed-by: Tyler Hicks <tyhicks@linux.microsoft.com>

Tyler

>  	}
>  	/* If we are root ourself just return that */
>  	if (dentry->d_sb->s_root == dentry)
> diff --git a/fs/9p/fid.h b/fs/9p/fid.h
> index 3168dfad510e..8a4e8cd12ca2 100644
> --- a/fs/9p/fid.h
> +++ b/fs/9p/fid.h
> @@ -13,9 +13,9 @@ static inline struct p9_fid *v9fs_parent_fid(struct dentry *dentry)
>  {
>  	return v9fs_fid_lookup(dentry->d_parent);
>  }
> -void v9fs_fid_add(struct dentry *dentry, struct p9_fid *fid);
> +void v9fs_fid_add(struct dentry *dentry, struct p9_fid **fid);
>  struct p9_fid *v9fs_writeback_fid(struct dentry *dentry);
> -void v9fs_open_fid_add(struct inode *inode, struct p9_fid *fid);
> +void v9fs_open_fid_add(struct inode *inode, struct p9_fid **fid);
>  static inline struct p9_fid *clone_fid(struct p9_fid *fid)
>  {
>  	return IS_ERR(fid) ? fid :  p9_client_walk(fid, 0, NULL, 1);
> diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c
> index 8276f3af35d7..aec43ba83799 100644
> --- a/fs/9p/vfs_file.c
> +++ b/fs/9p/vfs_file.c
> @@ -69,9 +69,10 @@ int v9fs_file_open(struct inode *inode, struct file *file)
>  		if ((file->f_flags & O_APPEND) &&
>  			(!v9fs_proto_dotu(v9ses) && !v9fs_proto_dotl(v9ses)))
>  			generic_file_llseek(file, 0, SEEK_END);
> +
> +		file->private_data = fid;
>  	}
>  
> -	file->private_data = fid;
>  	mutex_lock(&v9inode->v_mutex);
>  	if ((v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) &&
>  	    !v9inode->writeback_fid &&
> @@ -95,7 +96,7 @@ int v9fs_file_open(struct inode *inode, struct file *file)
>  	if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE)
>  		fscache_use_cookie(v9fs_inode_cookie(v9inode),
>  				   file->f_mode & FMODE_WRITE);
> -	v9fs_open_fid_add(inode, fid);
> +	v9fs_open_fid_add(inode, &fid);
>  	return 0;
>  out_error:
>  	p9_fid_put(file->private_data);
> diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
> index 38186d1a1440..1b11a92208fd 100644
> --- a/fs/9p/vfs_inode.c
> +++ b/fs/9p/vfs_inode.c
> @@ -398,10 +398,8 @@ void v9fs_evict_inode(struct inode *inode)
>  
>  	fscache_relinquish_cookie(v9fs_inode_cookie(v9inode), false);
>  	/* clunk the fid stashed in writeback_fid */
> -	if (v9inode->writeback_fid) {
> -		p9_fid_put(v9inode->writeback_fid);
> -		v9inode->writeback_fid = NULL;
> -	}
> +	p9_fid_put(v9inode->writeback_fid);
> +	v9inode->writeback_fid = NULL;
>  }
>  
>  static int v9fs_test_inode(struct inode *inode, void *data)
> @@ -632,14 +630,12 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,
>  	if (IS_ERR(ofid)) {
>  		err = PTR_ERR(ofid);
>  		p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err);
> -		p9_fid_put(dfid);
> -		return ERR_PTR(err);
> +		goto error;
>  	}
>  
>  	err = p9_client_fcreate(ofid, name, perm, mode, extension);
>  	if (err < 0) {
>  		p9_debug(P9_DEBUG_VFS, "p9_client_fcreate failed %d\n", err);
> -		p9_fid_put(dfid);
>  		goto error;
>  	}
>  
> @@ -650,8 +646,6 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,
>  			err = PTR_ERR(fid);
>  			p9_debug(P9_DEBUG_VFS,
>  				   "p9_client_walk failed %d\n", err);
> -			fid = NULL;
> -			p9_fid_put(dfid);
>  			goto error;
>  		}
>  		/*
> @@ -662,21 +656,17 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,
>  			err = PTR_ERR(inode);
>  			p9_debug(P9_DEBUG_VFS,
>  				   "inode creation failed %d\n", err);
> -			p9_fid_put(dfid);
>  			goto error;
>  		}
> -		v9fs_fid_add(dentry, fid);
> +		v9fs_fid_add(dentry, &fid);
>  		d_instantiate(dentry, inode);
>  	}
>  	p9_fid_put(dfid);
>  	return ofid;
>  error:
> -	if (ofid)
> -		p9_fid_put(ofid);
> -
> -	if (fid)
> -		p9_fid_put(fid);
> -
> +	p9_fid_put(dfid);
> +	p9_fid_put(ofid);
> +	p9_fid_put(fid);
>  	return ERR_PTR(err);
>  }
>  
> @@ -803,9 +793,9 @@ struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
>  	res = d_splice_alias(inode, dentry);
>  	if (!IS_ERR(fid)) {
>  		if (!res)
> -			v9fs_fid_add(dentry, fid);
> +			v9fs_fid_add(dentry, &fid);
>  		else if (!IS_ERR(res))
> -			v9fs_fid_add(res, fid);
> +			v9fs_fid_add(res, &fid);
>  		else
>  			p9_fid_put(fid);
>  	}
> @@ -846,7 +836,6 @@ v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry,
>  						v9fs_proto_dotu(v9ses)));
>  	if (IS_ERR(fid)) {
>  		err = PTR_ERR(fid);
> -		fid = NULL;
>  		goto error;
>  	}
>  
> @@ -881,7 +870,7 @@ v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry,
>  	if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE)
>  		fscache_use_cookie(v9fs_inode_cookie(v9inode),
>  				   file->f_mode & FMODE_WRITE);
> -	v9fs_open_fid_add(inode, fid);
> +	v9fs_open_fid_add(inode, &fid);
>  
>  	file->f_mode |= FMODE_CREATED;
>  out:
> @@ -889,8 +878,7 @@ v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry,
>  	return err;
>  
>  error:
> -	if (fid)
> -		p9_fid_put(fid);
> +	p9_fid_put(fid);
>  	goto out;
>  }
>  
> @@ -938,9 +926,9 @@ v9fs_vfs_rename(struct user_namespace *mnt_userns, struct inode *old_dir,
>  	struct inode *old_inode;
>  	struct inode *new_inode;
>  	struct v9fs_session_info *v9ses;
> -	struct p9_fid *oldfid, *dfid;
> -	struct p9_fid *olddirfid;
> -	struct p9_fid *newdirfid;
> +	struct p9_fid *oldfid = NULL, *dfid = NULL;
> +	struct p9_fid *olddirfid = NULL;
> +	struct p9_fid *newdirfid = NULL;
>  	struct p9_wstat wstat;
>  
>  	if (flags)
> @@ -957,21 +945,22 @@ v9fs_vfs_rename(struct user_namespace *mnt_userns, struct inode *old_dir,
>  
>  	dfid = v9fs_parent_fid(old_dentry);
>  	olddirfid = clone_fid(dfid);
> -	if (dfid && !IS_ERR(dfid))
> -		p9_fid_put(dfid);
> +	p9_fid_put(dfid);
> +	dfid = NULL;
>  
>  	if (IS_ERR(olddirfid)) {
>  		retval = PTR_ERR(olddirfid);
> -		goto done;
> +		goto error;
>  	}
>  
>  	dfid = v9fs_parent_fid(new_dentry);
>  	newdirfid = clone_fid(dfid);
>  	p9_fid_put(dfid);
> +	dfid = NULL;
>  
>  	if (IS_ERR(newdirfid)) {
>  		retval = PTR_ERR(newdirfid);
> -		goto clunk_olddir;
> +		goto error;
>  	}
>  
>  	down_write(&v9ses->rename_sem);
> @@ -982,7 +971,7 @@ v9fs_vfs_rename(struct user_namespace *mnt_userns, struct inode *old_dir,
>  			retval = p9_client_rename(oldfid, newdirfid,
>  						  new_dentry->d_name.name);
>  		if (retval != -EOPNOTSUPP)
> -			goto clunk_newdir;
> +			goto error_locked;
>  	}
>  	if (old_dentry->d_parent != new_dentry->d_parent) {
>  		/*
> @@ -991,14 +980,14 @@ v9fs_vfs_rename(struct user_namespace *mnt_userns, struct inode *old_dir,
>  
>  		p9_debug(P9_DEBUG_ERROR, "old dir and new dir are different\n");
>  		retval = -EXDEV;
> -		goto clunk_newdir;
> +		goto error_locked;
>  	}
>  	v9fs_blank_wstat(&wstat);
>  	wstat.muid = v9ses->uname;
>  	wstat.name = new_dentry->d_name.name;
>  	retval = p9_client_wstat(oldfid, &wstat);
>  
> -clunk_newdir:
> +error_locked:
>  	if (!retval) {
>  		if (new_inode) {
>  			if (S_ISDIR(new_inode->i_mode))
> @@ -1019,12 +1008,10 @@ v9fs_vfs_rename(struct user_namespace *mnt_userns, struct inode *old_dir,
>  		d_move(old_dentry, new_dentry);
>  	}
>  	up_write(&v9ses->rename_sem);
> +
> +error:
>  	p9_fid_put(newdirfid);
> -
> -clunk_olddir:
>  	p9_fid_put(olddirfid);
> -
> -done:
>  	p9_fid_put(oldfid);
>  	return retval;
>  }
> diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c
> index 09b124fe349c..5cfa4b4f070f 100644
> --- a/fs/9p/vfs_inode_dotl.c
> +++ b/fs/9p/vfs_inode_dotl.c
> @@ -238,7 +238,7 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
>  	struct inode *inode;
>  	struct p9_fid *fid = NULL;
>  	struct v9fs_inode *v9inode;
> -	struct p9_fid *dfid, *ofid, *inode_fid;
> +	struct p9_fid *dfid = NULL, *ofid = NULL, *inode_fid = NULL;
>  	struct v9fs_session_info *v9ses;
>  	struct posix_acl *pacl = NULL, *dacl = NULL;
>  	struct dentry *res = NULL;
> @@ -274,7 +274,6 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
>  	if (IS_ERR(ofid)) {
>  		err = PTR_ERR(ofid);
>  		p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err);
> -		p9_fid_put(dfid);
>  		goto out;
>  	}
>  
> @@ -286,38 +285,34 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
>  	if (err) {
>  		p9_debug(P9_DEBUG_VFS, "Failed to get acl values in creat %d\n",
>  			 err);
> -		p9_fid_put(dfid);
> -		goto error;
> +		goto out;
>  	}
>  	err = p9_client_create_dotl(ofid, name, v9fs_open_to_dotl_flags(flags),
>  				    mode, gid, &qid);
>  	if (err < 0) {
>  		p9_debug(P9_DEBUG_VFS, "p9_client_open_dotl failed in creat %d\n",
>  			 err);
> -		p9_fid_put(dfid);
> -		goto error;
> +		goto out;
>  	}
>  	v9fs_invalidate_inode_attr(dir);
>  
>  	/* instantiate inode and assign the unopened fid to the dentry */
>  	fid = p9_client_walk(dfid, 1, &name, 1);
> -	p9_fid_put(dfid);
>  	if (IS_ERR(fid)) {
>  		err = PTR_ERR(fid);
>  		p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err);
> -		fid = NULL;
> -		goto error;
> +		goto out;
>  	}
>  	inode = v9fs_get_new_inode_from_fid(v9ses, fid, dir->i_sb);
>  	if (IS_ERR(inode)) {
>  		err = PTR_ERR(inode);
>  		p9_debug(P9_DEBUG_VFS, "inode creation failed %d\n", err);
> -		goto error;
> +		goto out;
>  	}
>  	/* Now set the ACL based on the default value */
>  	v9fs_set_create_acl(inode, fid, dacl, pacl);
>  
> -	v9fs_fid_add(dentry, fid);
> +	v9fs_fid_add(dentry, &fid);
>  	d_instantiate(dentry, inode);
>  
>  	v9inode = V9FS_I(inode);
> @@ -336,7 +331,7 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
>  		if (IS_ERR(inode_fid)) {
>  			err = PTR_ERR(inode_fid);
>  			mutex_unlock(&v9inode->v_mutex);
> -			goto err_clunk_old_fid;
> +			goto out;
>  		}
>  		v9inode->writeback_fid = (void *) inode_fid;
>  	}
> @@ -344,25 +339,20 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
>  	/* Since we are opening a file, assign the open fid to the file */
>  	err = finish_open(file, dentry, generic_file_open);
>  	if (err)
> -		goto err_clunk_old_fid;
> +		goto out;
>  	file->private_data = ofid;
>  	if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE)
>  		fscache_use_cookie(v9fs_inode_cookie(v9inode),
>  				   file->f_mode & FMODE_WRITE);
> -	v9fs_open_fid_add(inode, ofid);
> +	v9fs_open_fid_add(inode, &ofid);
>  	file->f_mode |= FMODE_CREATED;
>  out:
> +	p9_fid_put(dfid);
> +	p9_fid_put(ofid);
> +	p9_fid_put(fid);
>  	v9fs_put_acl(dacl, pacl);
>  	dput(res);
>  	return err;
> -
> -error:
> -	if (fid)
> -		p9_fid_put(fid);
> -err_clunk_old_fid:
> -	if (ofid)
> -		p9_fid_put(ofid);
> -	goto out;
>  }
>  
>  /**
> @@ -400,7 +390,6 @@ static int v9fs_vfs_mkdir_dotl(struct user_namespace *mnt_userns,
>  	if (IS_ERR(dfid)) {
>  		err = PTR_ERR(dfid);
>  		p9_debug(P9_DEBUG_VFS, "fid lookup failed %d\n", err);
> -		dfid = NULL;
>  		goto error;
>  	}
>  
> @@ -422,7 +411,6 @@ static int v9fs_vfs_mkdir_dotl(struct user_namespace *mnt_userns,
>  		err = PTR_ERR(fid);
>  		p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n",
>  			 err);
> -		fid = NULL;
>  		goto error;
>  	}
>  
> @@ -435,10 +423,9 @@ static int v9fs_vfs_mkdir_dotl(struct user_namespace *mnt_userns,
>  				 err);
>  			goto error;
>  		}
> -		v9fs_fid_add(dentry, fid);
> +		v9fs_fid_add(dentry, &fid);
>  		v9fs_set_create_acl(inode, fid, dacl, pacl);
>  		d_instantiate(dentry, inode);
> -		fid = NULL;
>  		err = 0;
>  	} else {
>  		/*
> @@ -457,8 +444,7 @@ static int v9fs_vfs_mkdir_dotl(struct user_namespace *mnt_userns,
>  	inc_nlink(dir);
>  	v9fs_invalidate_inode_attr(dir);
>  error:
> -	if (fid)
> -		p9_fid_put(fid);
> +	p9_fid_put(fid);
>  	v9fs_put_acl(dacl, pacl);
>  	p9_fid_put(dfid);
>  	return err;
> @@ -743,7 +729,6 @@ v9fs_vfs_symlink_dotl(struct user_namespace *mnt_userns, struct inode *dir,
>  			err = PTR_ERR(fid);
>  			p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n",
>  				 err);
> -			fid = NULL;
>  			goto error;
>  		}
>  
> @@ -755,9 +740,8 @@ v9fs_vfs_symlink_dotl(struct user_namespace *mnt_userns, struct inode *dir,
>  				 err);
>  			goto error;
>  		}
> -		v9fs_fid_add(dentry, fid);
> +		v9fs_fid_add(dentry, &fid);
>  		d_instantiate(dentry, inode);
> -		fid = NULL;
>  		err = 0;
>  	} else {
>  		/* Not in cached mode. No need to populate inode with stat */
> @@ -770,9 +754,7 @@ v9fs_vfs_symlink_dotl(struct user_namespace *mnt_userns, struct inode *dir,
>  	}
>  
>  error:
> -	if (fid)
> -		p9_fid_put(fid);
> -
> +	p9_fid_put(fid);
>  	p9_fid_put(dfid);
>  	return err;
>  }
> @@ -866,7 +848,6 @@ v9fs_vfs_mknod_dotl(struct user_namespace *mnt_userns, struct inode *dir,
>  	if (IS_ERR(dfid)) {
>  		err = PTR_ERR(dfid);
>  		p9_debug(P9_DEBUG_VFS, "fid lookup failed %d\n", err);
> -		dfid = NULL;
>  		goto error;
>  	}
>  
> @@ -891,7 +872,6 @@ v9fs_vfs_mknod_dotl(struct user_namespace *mnt_userns, struct inode *dir,
>  		err = PTR_ERR(fid);
>  		p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n",
>  			 err);
> -		fid = NULL;
>  		goto error;
>  	}
>  
> @@ -905,9 +885,8 @@ v9fs_vfs_mknod_dotl(struct user_namespace *mnt_userns, struct inode *dir,
>  			goto error;
>  		}
>  		v9fs_set_create_acl(inode, fid, dacl, pacl);
> -		v9fs_fid_add(dentry, fid);
> +		v9fs_fid_add(dentry, &fid);
>  		d_instantiate(dentry, inode);
> -		fid = NULL;
>  		err = 0;
>  	} else {
>  		/*
> @@ -923,8 +902,7 @@ v9fs_vfs_mknod_dotl(struct user_namespace *mnt_userns, struct inode *dir,
>  		d_instantiate(dentry, inode);
>  	}
>  error:
> -	if (fid)
> -		p9_fid_put(fid);
> +	p9_fid_put(fid);
>  	v9fs_put_acl(dacl, pacl);
>  	p9_fid_put(dfid);
>  
> diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c
> index bf350fad9500..2d9ee073d12c 100644
> --- a/fs/9p/vfs_super.c
> +++ b/fs/9p/vfs_super.c
> @@ -184,7 +184,7 @@ static struct dentry *v9fs_mount(struct file_system_type *fs_type, int flags,
>  	retval = v9fs_get_acl(inode, fid);
>  	if (retval)
>  		goto release_sb;
> -	v9fs_fid_add(root, fid);
> +	v9fs_fid_add(root, &fid);
>  
>  	p9_debug(P9_DEBUG_VFS, " simple set mount, return 0\n");
>  	return dget(sb->s_root);
> -- 
> 2.35.1
> 

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 06/06] 9p fid refcount: cleanup p9_fid_put calls
  2022-06-13 17:55   ` Tyler Hicks
@ 2022-06-13 19:50     ` Dominique Martinet
  2022-06-13 20:12       ` Tyler Hicks
  0 siblings, 1 reply; 28+ messages in thread
From: Dominique Martinet @ 2022-06-13 19:50 UTC (permalink / raw)
  To: Tyler Hicks
  Cc: Christian Schoenebeck, Eric Van Hensbergen, Latchesar Ionkov,
	v9fs-developer, linux-kernel

Thanks for the reviews,

Tyler Hicks wrote on Mon, Jun 13, 2022 at 12:55:09PM -0500:
> > @@ -189,13 +197,13 @@ static struct p9_fid *v9fs_fid_lookup_with_uid(struct dentry *dentry,
> >  		else
> >  			uname = v9ses->uname;
> >  
> > -		root_fid = p9_client_attach(v9ses->clnt, NULL, uname, uid,
> > -					    v9ses->aname);
> > -		if (IS_ERR(root_fid))
> > -			return root_fid;
> > +		fid = p9_client_attach(v9ses->clnt, NULL, uname, uid,
> 
> To keep the readability benefits in my "9p: Track the root fid with its
> own variable during lookups" patch, I think root_fid should be assigned
> here and then used in the error check and return statement.
> 
> > +				       v9ses->aname);
> > +		if (IS_ERR(fid))
> > +			return fid;
> >  
> > -		p9_fid_get(root_fid);
> > -		v9fs_fid_add(dentry->d_sb->s_root, root_fid);
> > +		root_fid = p9_fid_get(fid);
> > +		v9fs_fid_add(dentry->d_sb->s_root, &fid);
> 
> root_fid should be used in the two lines above, too.

This actually was the only place where we still want to use the root_fid
after calling v9fs_fid_add; if we keep root_fid above we need to do
something like

fid = p9_fid_get(root_fid);
v9fs_Fid_add(dentry->d_sb->s_root, &root_fid);
root_fid = fid;
// fid = NULL; ? not strictly needed as we set it again shortly afterwards

which I wanted to avoid, but I guess I don't mind strongly either way --
pick your poison.
I could also just keep v9fs_fid_add as a non-stealing version, but I
think it's better that way as it strongly signal that we stashed that
ref away and shouldn't use the fid anymore unless another ref was
obtained through fid_get like we do here.
(I was actually tempted to do the same with p9_fid_put, but checking
other kernel "put"s I didn't see any code that does this so I refrained
from that churn)

-- 
Dominique

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 03/06] 9p: v9fs_fid_lookup_with_uid fix's fix suggestion
  2022-06-12  8:53 ` [PATCH 03/06] 9p: v9fs_fid_lookup_with_uid fix's fix suggestion Dominique Martinet
@ 2022-06-13 20:08   ` Tyler Hicks
  0 siblings, 0 replies; 28+ messages in thread
From: Tyler Hicks @ 2022-06-13 20:08 UTC (permalink / raw)
  To: Dominique Martinet
  Cc: Christian Schoenebeck, Eric Van Hensbergen, Latchesar Ionkov,
	v9fs-developer, linux-kernel

On 2022-06-12 17:53:26, Dominique Martinet wrote:
> Tyler, I can just squash this in your commit if you're ok with this,
> as I've already rebased the other patches on top of it.

Yes, that is fine. I've also tested this with my (binary-only)
reproducer and it works as expected.

Thanks!

Tyler

> 
> Cc: Tyler Hicks <tyhicks@linux.microsoft.com>
> Signed-off-by: Dominique Martinet <asmadeus@codewreck.org>
> ---
>  fs/9p/fid.c | 7 +++++--
>  1 file changed, 5 insertions(+), 2 deletions(-)
> 
> diff --git a/fs/9p/fid.c b/fs/9p/fid.c
> index 5a469b79c1ee..baf2b152229e 100644
> --- a/fs/9p/fid.c
> +++ b/fs/9p/fid.c
> @@ -221,12 +221,15 @@ static struct p9_fid *v9fs_fid_lookup_with_uid(struct dentry *dentry,
>  		 * walk to ensure none of the patch component change
>  		 */
>  		fid = p9_client_walk(fid, l, &wnames[i], clone);
> -		p9_client_clunk(old_fid);
> +		/* non-cloning walk will return the same fid */
> +		if (fid != old_fid) {
> +			p9_client_clunk(old_fid);
> +			old_fid = fid;
> +		}
>  		if (IS_ERR(fid)) {
>  			kfree(wnames);
>  			goto err_out;
>  		}
> -		old_fid = fid;
>  		i += l;
>  		clone = 0;
>  	}
> -- 
> 2.35.1
> 

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 06/06] 9p fid refcount: cleanup p9_fid_put calls
  2022-06-13 19:50     ` Dominique Martinet
@ 2022-06-13 20:12       ` Tyler Hicks
  0 siblings, 0 replies; 28+ messages in thread
From: Tyler Hicks @ 2022-06-13 20:12 UTC (permalink / raw)
  To: Dominique Martinet
  Cc: Christian Schoenebeck, Eric Van Hensbergen, Latchesar Ionkov,
	v9fs-developer, linux-kernel

On 2022-06-14 04:50:45, Dominique Martinet wrote:
> Thanks for the reviews,
> 
> Tyler Hicks wrote on Mon, Jun 13, 2022 at 12:55:09PM -0500:
> > > @@ -189,13 +197,13 @@ static struct p9_fid *v9fs_fid_lookup_with_uid(struct dentry *dentry,
> > >  		else
> > >  			uname = v9ses->uname;
> > >  
> > > -		root_fid = p9_client_attach(v9ses->clnt, NULL, uname, uid,
> > > -					    v9ses->aname);
> > > -		if (IS_ERR(root_fid))
> > > -			return root_fid;
> > > +		fid = p9_client_attach(v9ses->clnt, NULL, uname, uid,
> > 
> > To keep the readability benefits in my "9p: Track the root fid with its
> > own variable during lookups" patch, I think root_fid should be assigned
> > here and then used in the error check and return statement.
> > 
> > > +				       v9ses->aname);
> > > +		if (IS_ERR(fid))
> > > +			return fid;
> > >  
> > > -		p9_fid_get(root_fid);
> > > -		v9fs_fid_add(dentry->d_sb->s_root, root_fid);
> > > +		root_fid = p9_fid_get(fid);
> > > +		v9fs_fid_add(dentry->d_sb->s_root, &fid);
> > 
> > root_fid should be used in the two lines above, too.
> 
> This actually was the only place where we still want to use the root_fid
> after calling v9fs_fid_add; if we keep root_fid above we need to do
> something like
> 
> fid = p9_fid_get(root_fid);
> v9fs_Fid_add(dentry->d_sb->s_root, &root_fid);
> root_fid = fid;
> // fid = NULL; ? not strictly needed as we set it again shortly afterwards
> 
> which I wanted to avoid, but I guess I don't mind strongly either way --
> pick your poison.

Ah, very good point. I missed that subtly.

> I could also just keep v9fs_fid_add as a non-stealing version, but I
> think it's better that way as it strongly signal that we stashed that
> ref away and shouldn't use the fid anymore unless another ref was
> obtained through fid_get like we do here.
> (I was actually tempted to do the same with p9_fid_put, but checking
> other kernel "put"s I didn't see any code that does this so I refrained
> from that churn)

I like the stealing version. Lets go with it and keep this patch as-is.

Please feel free to slap this tag on it:

 Reviewed-by: Tyler Hicks <tyhicks@linux.microsoft.com>


Tyler

> 
> -- 
> Dominique
> 

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 00/06] fid refcounting improvements and fixes
  2022-06-12  8:53 [PATCH 00/06] fid refcounting improvements and fixes Dominique Martinet
                   ` (5 preceding siblings ...)
  2022-06-12  8:53 ` [PATCH 06/06] 9p fid refcount: cleanup p9_fid_put calls Dominique Martinet
@ 2022-06-13 20:20 ` Tyler Hicks
  2022-06-13 21:00   ` Dominique Martinet
  6 siblings, 1 reply; 28+ messages in thread
From: Tyler Hicks @ 2022-06-13 20:20 UTC (permalink / raw)
  To: Dominique Martinet; +Cc: Christian Schoenebeck, v9fs-developer, linux-kernel

On 2022-06-12 17:53:23, Dominique Martinet wrote:
> So:
>  - I could reproduce Tyler's generic 531 leak, fixed it by the first
>    commit in v9fs_vfs_atomic_open_dotl
>  - Found another less likely leak while reworking code
>  - Christian's comment that it's not obvious that clunk is just a
>    refcount decrease was very true: I think it's worth the churn,
>    so I've rename this all through a new helper...
>  - ... with the not-so-hidden intent to improve debugging by adding
>    a tracepoint for them, which I have also done.
> 
> I've also taken my comment in the other thread further and went ahead
> and made it in its own commit. Tyler, if you're ok with this I'll just
> squash it up. You can see rebased patches here:
> https://github.com/martinetd/linux/
> 
> Note that I also took the permission to add back '/* clone */' as a
> comment to your changing p9_client_walk's arguments: while I can agree
> variables are hard to track, figuring out what the heck that boolean
> argument means is much harder to me and I honestly preferred the
> variable.
> Having both through a comment is good enough for me if you'll accept
> this:
> ----
> @@ -222,7 +221,8 @@ static struct p9_fid *v9fs_fid_lookup_with_uid(struct dentry *dentry,
>                  * We need to hold rename lock when doing a multipath
>                  * walk to ensure none of the patch component change
>                  */
> -               fid = p9_client_walk(old_fid, l, &wnames[i], clone);
> +               fid = p9_client_walk(old_fid, l, &wnames[i],
> +                                    old_fid == root_fid /* clone */);

This is no problem at all. The rebased patches look good to me. Squash
your fix to my fix and it should be ready to go.

Thanks again!

Tyler

>                 /* non-cloning walk will return the same fid */
>                 if (fid != old_fid) {
>                         p9_client_clunk(old_fid);
> ----
> 
> 
> The last commit is just cleanups and should be no real change.
> 
> Dominique Martinet (6):
>   9p: fix fid refcount leak in v9fs_vfs_atomic_open_dotl
>   9p: fix fid refcount leak in v9fs_vfs_get_link
>   9p: v9fs_fid_lookup_with_uid fix's fix suggestion
>   9p fid refcount: add p9_fid_get/put wrappers
>   9p fid refcount: add a 9p_fid_ref tracepoint
>   9p fid refcount: cleanup p9_fid_put calls
> 
> 
> (diff stats include Tyler's commits)
> 
>  fs/9p/fid.c               | 71 +++++++++++++++-------------
>  fs/9p/fid.h               |  6 +--
>  fs/9p/vfs_addr.c          |  4 +-
>  fs/9p/vfs_dentry.c        |  4 +-
>  fs/9p/vfs_dir.c           |  2 +-
>  fs/9p/vfs_file.c          |  9 ++--
>  fs/9p/vfs_inode.c         | 97 +++++++++++++++++----------------------
>  fs/9p/vfs_inode_dotl.c    | 79 ++++++++++++-------------------
>  fs/9p/vfs_super.c         |  8 ++--
>  fs/9p/xattr.c             |  8 ++--
>  include/net/9p/client.h   |  3 ++
>  include/trace/events/9p.h | 48 +++++++++++++++++++
>  net/9p/client.c           | 42 +++++++++++------
>  13 files changed, 211 insertions(+), 170 deletions(-)
> 
> -- 
> 2.35.1
> 

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 00/06] fid refcounting improvements and fixes
  2022-06-13 20:20 ` [PATCH 00/06] fid refcounting improvements and fixes Tyler Hicks
@ 2022-06-13 21:00   ` Dominique Martinet
  2022-06-14  1:14     ` Tyler Hicks
  0 siblings, 1 reply; 28+ messages in thread
From: Dominique Martinet @ 2022-06-13 21:00 UTC (permalink / raw)
  To: Tyler Hicks; +Cc: Christian Schoenebeck, v9fs-developer, linux-kernel

Tyler Hicks wrote on Mon, Jun 13, 2022 at 03:20:53PM -0500:
> On 2022-06-12 17:53:23, Dominique Martinet wrote:
> > @@ -222,7 +221,8 @@ static struct p9_fid *v9fs_fid_lookup_with_uid(struct dentry *dentry,
> >                  * We need to hold rename lock when doing a multipath
> >                  * walk to ensure none of the patch component change
> >                  */
> > -               fid = p9_client_walk(old_fid, l, &wnames[i], clone);
> > +               fid = p9_client_walk(old_fid, l, &wnames[i],
> > +                                    old_fid == root_fid /* clone */);
> 
> This is no problem at all. The rebased patches look good to me. Squash
> your fix to my fix and it should be ready to go.

Thanks for all your reviews :)
I've rebased my branch if you want to check:
https://github.com/martinetd/linux/commits/9p-next

We've just started a cycle so I'll submit the first three patches (fixes
to stable) next week, and the rest for when 5.20 cycle starts.
Feel free to remind me if it looks like I forgot.
-- 
Dominique

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 00/06] fid refcounting improvements and fixes
  2022-06-13 21:00   ` Dominique Martinet
@ 2022-06-14  1:14     ` Tyler Hicks
  0 siblings, 0 replies; 28+ messages in thread
From: Tyler Hicks @ 2022-06-14  1:14 UTC (permalink / raw)
  To: Dominique Martinet; +Cc: Christian Schoenebeck, v9fs-developer, linux-kernel

On 2022-06-14 06:00:21, Dominique Martinet wrote:
> Tyler Hicks wrote on Mon, Jun 13, 2022 at 03:20:53PM -0500:
> > On 2022-06-12 17:53:23, Dominique Martinet wrote:
> > > @@ -222,7 +221,8 @@ static struct p9_fid *v9fs_fid_lookup_with_uid(struct dentry *dentry,
> > >                  * We need to hold rename lock when doing a multipath
> > >                  * walk to ensure none of the patch component change
> > >                  */
> > > -               fid = p9_client_walk(old_fid, l, &wnames[i], clone);
> > > +               fid = p9_client_walk(old_fid, l, &wnames[i],
> > > +                                    old_fid == root_fid /* clone */);
> > 
> > This is no problem at all. The rebased patches look good to me. Squash
> > your fix to my fix and it should be ready to go.
> 
> Thanks for all your reviews :)
> I've rebased my branch if you want to check:
> https://github.com/martinetd/linux/commits/9p-next

I've diffed the individual patches from before and after the rebase. It
all looks great to me.

> We've just started a cycle so I'll submit the first three patches (fixes
> to stable) next week, and the rest for when 5.20 cycle starts.

That sounds like the right plan to me.

> Feel free to remind me if it looks like I forgot.

Will do!

Tyler

> -- 
> Dominique
> 

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 01/06] 9p: fix fid refcount leak in v9fs_vfs_atomic_open_dotl
  2022-06-12  8:53 ` [PATCH 01/06] 9p: fix fid refcount leak in v9fs_vfs_atomic_open_dotl Dominique Martinet
  2022-06-13 16:27   ` Tyler Hicks
@ 2022-06-14 13:17   ` Christian Schoenebeck
  1 sibling, 0 replies; 28+ messages in thread
From: Christian Schoenebeck @ 2022-06-14 13:17 UTC (permalink / raw)
  To: Tyler Hicks, Eric Van Hensbergen, Latchesar Ionkov,
	Dominique Martinet, Jianyong Wu, Dominique Martinet
  Cc: v9fs-developer, linux-kernel, stable

On Sonntag, 12. Juni 2022 10:53:24 CEST Dominique Martinet wrote:
> We need to release directory fid if we fail halfway through open
> 
> This fixes fid leaking with xfstests generic 531
> 
> Fixes: 6636b6dcc3db ("9p: add refcount to p9_fid struct")
> Cc: stable@vger.kernel.org
> Reported-by: Tyler Hicks <tyhicks@linux.microsoft.com>
> Signed-off-by: Dominique Martinet <asmadeus@codewreck.org>

Reviewed-by: Christian Schoenebeck <linux_oss@crudebyte.com>

> ---
>  fs/9p/vfs_inode_dotl.c | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c
> index d17502a738a9..b6eb1160296c 100644
> --- a/fs/9p/vfs_inode_dotl.c
> +++ b/fs/9p/vfs_inode_dotl.c
> @@ -274,6 +274,7 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct
> dentry *dentry, if (IS_ERR(ofid)) {
>  		err = PTR_ERR(ofid);
>  		p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err);
> +		p9_client_clunk(dfid);
>  		goto out;
>  	}
> 
> @@ -285,6 +286,7 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct
> dentry *dentry, if (err) {
>  		p9_debug(P9_DEBUG_VFS, "Failed to get acl values in creat %d\n",
>  			 err);
> +		p9_client_clunk(dfid);
>  		goto error;
>  	}
>  	err = p9_client_create_dotl(ofid, name, v9fs_open_to_dotl_flags(flags),
> @@ -292,6 +294,7 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct
> dentry *dentry, if (err < 0) {
>  		p9_debug(P9_DEBUG_VFS, "p9_client_open_dotl failed in creat %d\n",
>  			 err);
> +		p9_client_clunk(dfid);
>  		goto error;
>  	}
>  	v9fs_invalidate_inode_attr(dir);





^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 02/06] 9p: fix fid refcount leak in v9fs_vfs_get_link
  2022-06-12  8:53 ` [PATCH 02/06] 9p: fix fid refcount leak in v9fs_vfs_get_link Dominique Martinet
  2022-06-13 16:29   ` Tyler Hicks
@ 2022-06-14 13:19   ` Christian Schoenebeck
  1 sibling, 0 replies; 28+ messages in thread
From: Christian Schoenebeck @ 2022-06-14 13:19 UTC (permalink / raw)
  To: Tyler Hicks, Eric Van Hensbergen, Latchesar Ionkov,
	Dominique Martinet, Jianyong Wu, v9fs-developer
  Cc: linux-kernel, stable

On Sonntag, 12. Juni 2022 10:53:25 CEST Dominique Martinet wrote:
> we check for protocol version later than required, after a fid has
> been obtained. Just move the version check earlier.
> 
> Fixes: 6636b6dcc3db ("9p: add refcount to p9_fid struct")
> Cc: stable@vger.kernel.org
> Signed-off-by: Dominique Martinet <asmadeus@codewreck.org>
> ---

Reviewed-by: Christian Schoenebeck <linux_oss@crudebyte.com>

>  fs/9p/vfs_inode.c | 8 ++++----
>  1 file changed, 4 insertions(+), 4 deletions(-)
> 
> diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
> index 55367ecb9442..18c780ffd4b5 100644
> --- a/fs/9p/vfs_inode.c
> +++ b/fs/9p/vfs_inode.c
> @@ -1250,15 +1250,15 @@ static const char *v9fs_vfs_get_link(struct dentry
> *dentry, return ERR_PTR(-ECHILD);
> 
>  	v9ses = v9fs_dentry2v9ses(dentry);
> -	fid = v9fs_fid_lookup(dentry);
> +	if (!v9fs_proto_dotu(v9ses))
> +		return ERR_PTR(-EBADF);
> +
>  	p9_debug(P9_DEBUG_VFS, "%pd\n", dentry);
> +	fid = v9fs_fid_lookup(dentry);
> 
>  	if (IS_ERR(fid))
>  		return ERR_CAST(fid);
> 
> -	if (!v9fs_proto_dotu(v9ses))
> -		return ERR_PTR(-EBADF);
> -
>  	st = p9_client_stat(fid);
>  	p9_client_clunk(fid);
>  	if (IS_ERR(st))





^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH v2 04/06] 9p fid refcount: add p9_fid_get/put wrappers
  2022-06-12 23:45   ` [PATCH v2 " Dominique Martinet
  2022-06-13 17:31     ` Tyler Hicks
@ 2022-06-14 13:55     ` Christian Schoenebeck
  2022-06-14 14:27       ` Dominique Martinet
  2022-06-15  3:16       ` [PATCH v3 " Dominique Martinet
  1 sibling, 2 replies; 28+ messages in thread
From: Christian Schoenebeck @ 2022-06-14 13:55 UTC (permalink / raw)
  To: Tyler Hicks, Eric Van Hensbergen, Latchesar Ionkov,
	Dominique Martinet, David S. Miller, Jakub Kicinski, Paolo Abeni,
	v9fs-developer
  Cc: linux-kernel, netdev

On Montag, 13. Juni 2022 01:45:54 CEST Dominique Martinet wrote:
> I was recently reminded that it is not clear that p9_client_clunk()
> was actually just decrementing refcount and clunking only when that
> reaches zero: make it clear through a set of helpers.
> 
> This will also allow instrumenting refcounting better for debugging
> next patch, which is the reason these are not defined as static inline:
> we won't be able to add trace events there...

Looks like you forgot to adjust the commit log sentence here, ...

> Signed-off-by: Dominique Martinet <asmadeus@codewreck.org>
> ---
> v1 -> v2: p9_fid_get/put are now static inline in .h

... as the two functions are in fact static inlined in this v2 now.

Some more below ...

>  fs/9p/fid.c             | 18 ++++++++--------
>  fs/9p/fid.h             |  2 +-
>  fs/9p/vfs_addr.c        |  4 ++--
>  fs/9p/vfs_dentry.c      |  4 ++--
>  fs/9p/vfs_dir.c         |  2 +-
>  fs/9p/vfs_file.c        |  4 ++--
>  fs/9p/vfs_inode.c       | 48 ++++++++++++++++++++---------------------
>  fs/9p/vfs_inode_dotl.c  | 42 ++++++++++++++++++------------------
>  fs/9p/vfs_super.c       |  6 +++---
>  fs/9p/xattr.c           |  8 +++----
>  include/net/9p/client.h | 18 ++++++++++++++++
>  net/9p/client.c         | 15 +++----------
>  12 files changed, 90 insertions(+), 81 deletions(-)
> 
> diff --git a/fs/9p/fid.c b/fs/9p/fid.c
> index e8fad28fc5bd..d792499349c4 100644
> --- a/fs/9p/fid.c
> +++ b/fs/9p/fid.c
> @@ -56,7 +56,7 @@ static struct p9_fid *v9fs_fid_find_inode(struct inode
> *inode, kuid_t uid) h = (struct hlist_head *)&inode->i_private;
>  	hlist_for_each_entry(fid, h, ilist) {
>  		if (uid_eq(fid->uid, uid)) {
> -			refcount_inc(&fid->count);
> +			p9_fid_get(fid);
>  			ret = fid;
>  			break;
>  		}
> @@ -104,7 +104,7 @@ static struct p9_fid *v9fs_fid_find(struct dentry
> *dentry, kuid_t uid, int any) hlist_for_each_entry(fid, h, dlist) {
>  			if (any || uid_eq(fid->uid, uid)) {
>  				ret = fid;
> -				refcount_inc(&ret->count);
> +				p9_fid_get(ret);
>  				break;
>  			}
>  		}
> @@ -172,7 +172,7 @@ static struct p9_fid *v9fs_fid_lookup_with_uid(struct
> dentry *dentry, old_fid = fid;
> 
>  		fid = p9_client_walk(old_fid, 1, &dentry->d_name.name, 1);
> -		p9_client_clunk(old_fid);
> +		p9_fid_put(old_fid);
>  		goto fid_out;
>  	}
>  	up_read(&v9ses->rename_sem);
> @@ -194,7 +194,7 @@ static struct p9_fid *v9fs_fid_lookup_with_uid(struct
> dentry *dentry, if (IS_ERR(root_fid))
>  			return root_fid;
> 
> -		refcount_inc(&root_fid->count);
> +		p9_fid_get(root_fid);
>  		v9fs_fid_add(dentry->d_sb->s_root, root_fid);
>  	}
>  	/* If we are root ourself just return that */
> @@ -225,7 +225,7 @@ static struct p9_fid *v9fs_fid_lookup_with_uid(struct
> dentry *dentry, old_fid == root_fid /* clone */);
>  		/* non-cloning walk will return the same fid */
>  		if (fid != old_fid) {
> -			p9_client_clunk(old_fid);
> +			p9_fid_put(old_fid);
>  			old_fid = fid;
>  		}
>  		if (IS_ERR(fid)) {
> @@ -240,11 +240,11 @@ static struct p9_fid *v9fs_fid_lookup_with_uid(struct
> dentry *dentry, spin_lock(&dentry->d_lock);
>  		if (d_unhashed(dentry)) {
>  			spin_unlock(&dentry->d_lock);
> -			p9_client_clunk(fid);
> +			p9_fid_put(fid);
>  			fid = ERR_PTR(-ENOENT);
>  		} else {
>  			__add_fid(dentry, fid);
> -			refcount_inc(&fid->count);
> +			p9_fid_get(fid);
>  			spin_unlock(&dentry->d_lock);
>  		}
>  	}
> @@ -301,7 +301,7 @@ struct p9_fid *v9fs_writeback_fid(struct dentry *dentry)
> fid = clone_fid(ofid);
>  	if (IS_ERR(fid))
>  		goto error_out;
> -	p9_client_clunk(ofid);
> +	p9_fid_put(ofid);
>  	/*
>  	 * writeback fid will only be used to write back the
>  	 * dirty pages. We always request for the open fid in read-write
> @@ -310,7 +310,7 @@ struct p9_fid *v9fs_writeback_fid(struct dentry *dentry)
> */
>  	err = p9_client_open(fid, O_RDWR);
>  	if (err < 0) {
> -		p9_client_clunk(fid);
> +		p9_fid_put(fid);
>  		fid = ERR_PTR(err);
>  		goto error_out;
>  	}
> diff --git a/fs/9p/fid.h b/fs/9p/fid.h
> index f7f33509e169..3168dfad510e 100644
> --- a/fs/9p/fid.h
> +++ b/fs/9p/fid.h
> @@ -29,7 +29,7 @@ static inline struct p9_fid *v9fs_fid_clone(struct dentry
> *dentry) return fid;
> 
>  	nfid = clone_fid(fid);
> -	p9_client_clunk(fid);
> +	p9_fid_put(fid);
>  	return nfid;
>  }
>  #endif
> diff --git a/fs/9p/vfs_addr.c b/fs/9p/vfs_addr.c
> index 8ce82ff1e40a..ed598160e0c6 100644
> --- a/fs/9p/vfs_addr.c
> +++ b/fs/9p/vfs_addr.c
> @@ -60,7 +60,7 @@ static int v9fs_init_request(struct netfs_io_request
> *rreq, struct file *file) {
>  	struct p9_fid *fid = file->private_data;
> 
> -	refcount_inc(&fid->count);
> +	p9_fid_get(fid);
>  	rreq->netfs_priv = fid;
>  	return 0;
>  }
> @@ -74,7 +74,7 @@ static void v9fs_req_cleanup(struct address_space
> *mapping, void *priv) {
>  	struct p9_fid *fid = priv;
> 
> -	p9_client_clunk(fid);
> +	p9_fid_put(fid);
>  }
> 
>  /**
> diff --git a/fs/9p/vfs_dentry.c b/fs/9p/vfs_dentry.c
> index 1c609e99d280..f89f01734587 100644
> --- a/fs/9p/vfs_dentry.c
> +++ b/fs/9p/vfs_dentry.c
> @@ -54,7 +54,7 @@ static void v9fs_dentry_release(struct dentry *dentry)
>  	p9_debug(P9_DEBUG_VFS, " dentry: %pd (%p)\n",
>  		 dentry, dentry);
>  	hlist_for_each_safe(p, n, (struct hlist_head *)&dentry->d_fsdata)
> -		p9_client_clunk(hlist_entry(p, struct p9_fid, dlist));
> +		p9_fid_put(hlist_entry(p, struct p9_fid, dlist));
>  	dentry->d_fsdata = NULL;
>  }
> 
> @@ -85,7 +85,7 @@ static int v9fs_lookup_revalidate(struct dentry *dentry,
> unsigned int flags) retval = v9fs_refresh_inode_dotl(fid, inode);
>  		else
>  			retval = v9fs_refresh_inode(fid, inode);
> -		p9_client_clunk(fid);
> +		p9_fid_put(fid);
> 
>  		if (retval == -ENOENT)
>  			return 0;
> diff --git a/fs/9p/vfs_dir.c b/fs/9p/vfs_dir.c
> index 958680f7f23e..000fbaae9b18 100644
> --- a/fs/9p/vfs_dir.c
> +++ b/fs/9p/vfs_dir.c
> @@ -218,7 +218,7 @@ int v9fs_dir_release(struct inode *inode, struct file
> *filp) spin_lock(&inode->i_lock);
>  		hlist_del(&fid->ilist);
>  		spin_unlock(&inode->i_lock);
> -		p9_client_clunk(fid);
> +		p9_fid_put(fid);
>  	}
> 
>  	if ((filp->f_mode & FMODE_WRITE)) {
> diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c
> index 2573c08f335c..8276f3af35d7 100644
> --- a/fs/9p/vfs_file.c
> +++ b/fs/9p/vfs_file.c
> @@ -63,7 +63,7 @@ int v9fs_file_open(struct inode *inode, struct file *file)
> 
>  		err = p9_client_open(fid, omode);
>  		if (err < 0) {
> -			p9_client_clunk(fid);
> +			p9_fid_put(fid);
>  			return err;
>  		}
>  		if ((file->f_flags & O_APPEND) &&
> @@ -98,7 +98,7 @@ int v9fs_file_open(struct inode *inode, struct file *file)
> v9fs_open_fid_add(inode, fid);
>  	return 0;
>  out_error:
> -	p9_client_clunk(file->private_data);
> +	p9_fid_put(file->private_data);
>  	file->private_data = NULL;
>  	return err;
>  }
> diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
> index 18c780ffd4b5..38186d1a1440 100644
> --- a/fs/9p/vfs_inode.c
> +++ b/fs/9p/vfs_inode.c
> @@ -399,7 +399,7 @@ void v9fs_evict_inode(struct inode *inode)
>  	fscache_relinquish_cookie(v9fs_inode_cookie(v9inode), false);
>  	/* clunk the fid stashed in writeback_fid */
>  	if (v9inode->writeback_fid) {
> -		p9_client_clunk(v9inode->writeback_fid);
> +		p9_fid_put(v9inode->writeback_fid);
>  		v9inode->writeback_fid = NULL;
>  	}
>  }
> @@ -568,7 +568,7 @@ static int v9fs_remove(struct inode *dir, struct dentry
> *dentry, int flags) if (v9fs_proto_dotl(v9ses))
>  		retval = p9_client_unlinkat(dfid, dentry->d_name.name,
>  					    v9fs_at_to_dotl_flags(flags));
> -	p9_client_clunk(dfid);
> +	p9_fid_put(dfid);
>  	if (retval == -EOPNOTSUPP) {
>  		/* Try the one based on path */
>  		v9fid = v9fs_fid_clone(dentry);
> @@ -632,14 +632,14 @@ v9fs_create(struct v9fs_session_info *v9ses, struct
> inode *dir, if (IS_ERR(ofid)) {
>  		err = PTR_ERR(ofid);
>  		p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err);
> -		p9_client_clunk(dfid);
> +		p9_fid_put(dfid);
>  		return ERR_PTR(err);
>  	}
> 
>  	err = p9_client_fcreate(ofid, name, perm, mode, extension);
>  	if (err < 0) {
>  		p9_debug(P9_DEBUG_VFS, "p9_client_fcreate failed %d\n", err);
> -		p9_client_clunk(dfid);
> +		p9_fid_put(dfid);
>  		goto error;
>  	}
> 
> @@ -651,7 +651,7 @@ v9fs_create(struct v9fs_session_info *v9ses, struct
> inode *dir, p9_debug(P9_DEBUG_VFS,
>  				   "p9_client_walk failed %d\n", err);
>  			fid = NULL;
> -			p9_client_clunk(dfid);
> +			p9_fid_put(dfid);
>  			goto error;
>  		}
>  		/*
> @@ -662,20 +662,20 @@ v9fs_create(struct v9fs_session_info *v9ses, struct
> inode *dir, err = PTR_ERR(inode);
>  			p9_debug(P9_DEBUG_VFS,
>  				   "inode creation failed %d\n", err);
> -			p9_client_clunk(dfid);
> +			p9_fid_put(dfid);
>  			goto error;
>  		}
>  		v9fs_fid_add(dentry, fid);
>  		d_instantiate(dentry, inode);
>  	}
> -	p9_client_clunk(dfid);
> +	p9_fid_put(dfid);
>  	return ofid;
>  error:
>  	if (ofid)
> -		p9_client_clunk(ofid);
> +		p9_fid_put(ofid);
> 
>  	if (fid)
> -		p9_client_clunk(fid);
> +		p9_fid_put(fid);
> 
>  	return ERR_PTR(err);
>  }
> @@ -707,7 +707,7 @@ v9fs_vfs_create(struct user_namespace *mnt_userns,
> struct inode *dir, return PTR_ERR(fid);
> 
>  	v9fs_invalidate_inode_attr(dir);
> -	p9_client_clunk(fid);
> +	p9_fid_put(fid);
> 
>  	return 0;
>  }
> @@ -743,7 +743,7 @@ static int v9fs_vfs_mkdir(struct user_namespace
> *mnt_userns, struct inode *dir, }
> 
>  	if (fid)
> -		p9_client_clunk(fid);
> +		p9_fid_put(fid);
> 
>  	return err;
>  }
> @@ -784,7 +784,7 @@ struct dentry *v9fs_vfs_lookup(struct inode *dir, struct
> dentry *dentry, */
>  	name = dentry->d_name.name;
>  	fid = p9_client_walk(dfid, 1, &name, 1);
> -	p9_client_clunk(dfid);
> +	p9_fid_put(dfid);
>  	if (fid == ERR_PTR(-ENOENT))
>  		inode = NULL;
>  	else if (IS_ERR(fid))
> @@ -807,7 +807,7 @@ struct dentry *v9fs_vfs_lookup(struct inode *dir, struct
> dentry *dentry, else if (!IS_ERR(res))
>  			v9fs_fid_add(res, fid);
>  		else
> -			p9_client_clunk(fid);
> +			p9_fid_put(fid);
>  	}
>  	return res;
>  }
> @@ -890,7 +890,7 @@ v9fs_vfs_atomic_open(struct inode *dir, struct dentry
> *dentry,
> 
>  error:
>  	if (fid)
> -		p9_client_clunk(fid);
> +		p9_fid_put(fid);
>  	goto out;
>  }
> 
> @@ -958,7 +958,7 @@ v9fs_vfs_rename(struct user_namespace *mnt_userns,
> struct inode *old_dir, dfid = v9fs_parent_fid(old_dentry);
>  	olddirfid = clone_fid(dfid);
>  	if (dfid && !IS_ERR(dfid))
> -		p9_client_clunk(dfid);
> +		p9_fid_put(dfid);
> 
>  	if (IS_ERR(olddirfid)) {
>  		retval = PTR_ERR(olddirfid);
> @@ -967,7 +967,7 @@ v9fs_vfs_rename(struct user_namespace *mnt_userns,
> struct inode *old_dir,
> 
>  	dfid = v9fs_parent_fid(new_dentry);
>  	newdirfid = clone_fid(dfid);
> -	p9_client_clunk(dfid);
> +	p9_fid_put(dfid);
> 
>  	if (IS_ERR(newdirfid)) {
>  		retval = PTR_ERR(newdirfid);
> @@ -1019,13 +1019,13 @@ v9fs_vfs_rename(struct user_namespace *mnt_userns,
> struct inode *old_dir, d_move(old_dentry, new_dentry);
>  	}
>  	up_write(&v9ses->rename_sem);
> -	p9_client_clunk(newdirfid);
> +	p9_fid_put(newdirfid);
> 
>  clunk_olddir:
> -	p9_client_clunk(olddirfid);
> +	p9_fid_put(olddirfid);
> 
>  done:
> -	p9_client_clunk(oldfid);
> +	p9_fid_put(oldfid);
>  	return retval;
>  }
> 
> @@ -1059,7 +1059,7 @@ v9fs_vfs_getattr(struct user_namespace *mnt_userns,
> const struct path *path, return PTR_ERR(fid);
> 
>  	st = p9_client_stat(fid);
> -	p9_client_clunk(fid);
> +	p9_fid_put(fid);
>  	if (IS_ERR(st))
>  		return PTR_ERR(st);
> 
> @@ -1135,7 +1135,7 @@ static int v9fs_vfs_setattr(struct user_namespace
> *mnt_userns, retval = p9_client_wstat(fid, &wstat);
> 
>  	if (use_dentry)
> -		p9_client_clunk(fid);
> +		p9_fid_put(fid);
> 
>  	if (retval < 0)
>  		return retval;
> @@ -1260,7 +1260,7 @@ static const char *v9fs_vfs_get_link(struct dentry
> *dentry, return ERR_CAST(fid);
> 
>  	st = p9_client_stat(fid);
> -	p9_client_clunk(fid);
> +	p9_fid_put(fid);
>  	if (IS_ERR(st))
>  		return ERR_CAST(st);
> 
> @@ -1307,7 +1307,7 @@ static int v9fs_vfs_mkspecial(struct inode *dir,
> struct dentry *dentry, return PTR_ERR(fid);
> 
>  	v9fs_invalidate_inode_attr(dir);
> -	p9_client_clunk(fid);
> +	p9_fid_put(fid);
>  	return 0;
>  }
> 
> @@ -1363,7 +1363,7 @@ v9fs_vfs_link(struct dentry *old_dentry, struct inode
> *dir, v9fs_refresh_inode(oldfid, d_inode(old_dentry));
>  		v9fs_invalidate_inode_attr(dir);
>  	}
> -	p9_client_clunk(oldfid);
> +	p9_fid_put(oldfid);
>  	return retval;
>  }
> 
> diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c
> index b6eb1160296c..09b124fe349c 100644
> --- a/fs/9p/vfs_inode_dotl.c
> +++ b/fs/9p/vfs_inode_dotl.c
> @@ -274,7 +274,7 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct
> dentry *dentry, if (IS_ERR(ofid)) {
>  		err = PTR_ERR(ofid);
>  		p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err);
> -		p9_client_clunk(dfid);
> +		p9_fid_put(dfid);
>  		goto out;
>  	}
> 
> @@ -286,7 +286,7 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct
> dentry *dentry, if (err) {
>  		p9_debug(P9_DEBUG_VFS, "Failed to get acl values in creat %d\n",
>  			 err);
> -		p9_client_clunk(dfid);
> +		p9_fid_put(dfid);
>  		goto error;
>  	}
>  	err = p9_client_create_dotl(ofid, name, v9fs_open_to_dotl_flags(flags),
> @@ -294,14 +294,14 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct
> dentry *dentry, if (err < 0) {
>  		p9_debug(P9_DEBUG_VFS, "p9_client_open_dotl failed in creat %d\n",
>  			 err);
> -		p9_client_clunk(dfid);
> +		p9_fid_put(dfid);
>  		goto error;
>  	}
>  	v9fs_invalidate_inode_attr(dir);
> 
>  	/* instantiate inode and assign the unopened fid to the dentry */
>  	fid = p9_client_walk(dfid, 1, &name, 1);
> -	p9_client_clunk(dfid);
> +	p9_fid_put(dfid);
>  	if (IS_ERR(fid)) {
>  		err = PTR_ERR(fid);
>  		p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err);
> @@ -358,10 +358,10 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct
> dentry *dentry,
> 
>  error:
>  	if (fid)
> -		p9_client_clunk(fid);
> +		p9_fid_put(fid);
>  err_clunk_old_fid:
>  	if (ofid)
> -		p9_client_clunk(ofid);
> +		p9_fid_put(ofid);
>  	goto out;
>  }
> 
> @@ -458,9 +458,9 @@ static int v9fs_vfs_mkdir_dotl(struct user_namespace
> *mnt_userns, v9fs_invalidate_inode_attr(dir);
>  error:
>  	if (fid)
> -		p9_client_clunk(fid);
> +		p9_fid_put(fid);
>  	v9fs_put_acl(dacl, pacl);
> -	p9_client_clunk(dfid);
> +	p9_fid_put(dfid);
>  	return err;
>  }
> 
> @@ -489,7 +489,7 @@ v9fs_vfs_getattr_dotl(struct user_namespace *mnt_userns,
> */
> 
>  	st = p9_client_getattr_dotl(fid, P9_STATS_ALL);
> -	p9_client_clunk(fid);
> +	p9_fid_put(fid);
>  	if (IS_ERR(st))
>  		return PTR_ERR(st);
> 
> @@ -603,7 +603,7 @@ int v9fs_vfs_setattr_dotl(struct user_namespace
> *mnt_userns, retval = p9_client_setattr(fid, &p9attr);
>  	if (retval < 0) {
>  		if (use_dentry)
> -			p9_client_clunk(fid);
> +			p9_fid_put(fid);
>  		return retval;
>  	}
> 
> @@ -619,12 +619,12 @@ int v9fs_vfs_setattr_dotl(struct user_namespace
> *mnt_userns, retval = v9fs_acl_chmod(inode, fid);
>  		if (retval < 0) {
>  			if (use_dentry)
> -				p9_client_clunk(fid);
> +				p9_fid_put(fid);
>  			return retval;
>  		}
>  	}
>  	if (use_dentry)
> -		p9_client_clunk(fid);
> +		p9_fid_put(fid);
> 
>  	return 0;
>  }
> @@ -771,9 +771,9 @@ v9fs_vfs_symlink_dotl(struct user_namespace *mnt_userns,
> struct inode *dir,
> 
>  error:
>  	if (fid)
> -		p9_client_clunk(fid);
> +		p9_fid_put(fid);
> 
> -	p9_client_clunk(dfid);
> +	p9_fid_put(dfid);
>  	return err;
>  }
> 
> @@ -803,14 +803,14 @@ v9fs_vfs_link_dotl(struct dentry *old_dentry, struct
> inode *dir,
> 
>  	oldfid = v9fs_fid_lookup(old_dentry);
>  	if (IS_ERR(oldfid)) {
> -		p9_client_clunk(dfid);
> +		p9_fid_put(dfid);
>  		return PTR_ERR(oldfid);
>  	}
> 
>  	err = p9_client_link(dfid, oldfid, dentry->d_name.name);
> 
> -	p9_client_clunk(dfid);
> -	p9_client_clunk(oldfid);
> +	p9_fid_put(dfid);
> +	p9_fid_put(oldfid);
>  	if (err < 0) {
>  		p9_debug(P9_DEBUG_VFS, "p9_client_link failed %d\n", err);
>  		return err;
> @@ -826,7 +826,7 @@ v9fs_vfs_link_dotl(struct dentry *old_dentry, struct
> inode *dir, return PTR_ERR(fid);
> 
>  		v9fs_refresh_inode_dotl(fid, d_inode(old_dentry));
> -		p9_client_clunk(fid);
> +		p9_fid_put(fid);
>  	}
>  	ihold(d_inode(old_dentry));
>  	d_instantiate(dentry, d_inode(old_dentry));
> @@ -924,9 +924,9 @@ v9fs_vfs_mknod_dotl(struct user_namespace *mnt_userns,
> struct inode *dir, }
>  error:
>  	if (fid)
> -		p9_client_clunk(fid);
> +		p9_fid_put(fid);
>  	v9fs_put_acl(dacl, pacl);
> -	p9_client_clunk(dfid);
> +	p9_fid_put(dfid);
> 
>  	return err;
>  }
> @@ -956,7 +956,7 @@ v9fs_vfs_get_link_dotl(struct dentry *dentry,
>  	if (IS_ERR(fid))
>  		return ERR_CAST(fid);
>  	retval = p9_client_readlink(fid, &target);
> -	p9_client_clunk(fid);
> +	p9_fid_put(fid);
>  	if (retval)
>  		return ERR_PTR(retval);
>  	set_delayed_call(done, kfree_link, target);
> diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c
> index 97e23b4e6982..bf350fad9500 100644
> --- a/fs/9p/vfs_super.c
> +++ b/fs/9p/vfs_super.c
> @@ -190,7 +190,7 @@ static struct dentry *v9fs_mount(struct file_system_type
> *fs_type, int flags, return dget(sb->s_root);
> 
>  clunk_fid:
> -	p9_client_clunk(fid);
> +	p9_fid_put(fid);
>  	v9fs_session_close(v9ses);
>  free_session:
>  	kfree(v9ses);
> @@ -203,7 +203,7 @@ static struct dentry *v9fs_mount(struct file_system_type
> *fs_type, int flags, * attached the fid to dentry so it won't get clunked
>  	 * automatically.
>  	 */
> -	p9_client_clunk(fid);
> +	p9_fid_put(fid);
>  	deactivate_locked_super(sb);
>  	return ERR_PTR(retval);
>  }
> @@ -270,7 +270,7 @@ static int v9fs_statfs(struct dentry *dentry, struct
> kstatfs *buf) }
>  	res = simple_statfs(dentry, buf);
>  done:
> -	p9_client_clunk(fid);
> +	p9_fid_put(fid);
>  	return res;
>  }
> 
> diff --git a/fs/9p/xattr.c b/fs/9p/xattr.c
> index a824441b95a2..1f9298a4bd42 100644
> --- a/fs/9p/xattr.c
> +++ b/fs/9p/xattr.c
> @@ -44,7 +44,7 @@ ssize_t v9fs_fid_xattr_get(struct p9_fid *fid, const char
> *name, if (err)
>  			retval = err;
>  	}
> -	p9_client_clunk(attr_fid);
> +	p9_fid_put(attr_fid);
>  	return retval;
>  }
> 
> @@ -71,7 +71,7 @@ ssize_t v9fs_xattr_get(struct dentry *dentry, const char
> *name, if (IS_ERR(fid))
>  		return PTR_ERR(fid);
>  	ret = v9fs_fid_xattr_get(fid, name, buffer, buffer_size);
> -	p9_client_clunk(fid);
> +	p9_fid_put(fid);
> 
>  	return ret;
>  }
> @@ -98,7 +98,7 @@ int v9fs_xattr_set(struct dentry *dentry, const char
> *name, if (IS_ERR(fid))
>  		return PTR_ERR(fid);
>  	ret = v9fs_fid_xattr_set(fid, name, value, value_len, flags);
> -	p9_client_clunk(fid);
> +	p9_fid_put(fid);
>  	return ret;
>  }
> 
> @@ -128,7 +128,7 @@ int v9fs_fid_xattr_set(struct p9_fid *fid, const char
> *name, retval);
>  	else
>  		p9_client_write(fid, 0, &from, &retval);
> -	err = p9_client_clunk(fid);
> +	err = p9_fid_put(fid);
>  	if (!retval && err)
>  		retval = err;
>  	return retval;
> diff --git a/include/net/9p/client.h b/include/net/9p/client.h
> index ec1d1706f43c..9fd38d674057 100644
> --- a/include/net/9p/client.h
> +++ b/include/net/9p/client.h
> @@ -237,6 +237,24 @@ static inline int p9_req_try_get(struct p9_req_t *r)
> 
>  int p9_req_put(struct p9_req_t *r);
> 
> +static inline struct p9_fid *p9_fid_get(struct p9_fid *fid)
> +{

Isn't this missing a check here?

    if (!fid)
        return NULL;

> +	refcount_inc(&fid->count);
> +
> +	return fid;
> +}
> +
> +static inline int p9_fid_put(struct p9_fid *fid)
> +{
> +	if (!fid || IS_ERR(fid))
> +		return 0;
> +
> +	if (!refcount_dec_and_test(&fid->count))
> +		return 0;
> +
> +	return p9_client_clunk(fid);
> +}
> +

I don't know the common symbol name patterns in the Linux kernel for acquiring
and releasing counted references are (if there is a common one at all), but I
think those two functions deserve a short API comment to make it clear they
belong together, i.e. that a p9_fid_get() call should be paired with
subsequent p9_fid_put(). It's maybe just nitpicking, as the code is quite
short and probably already speaks for itself.

On the long-term I could imagine using automated, destructor based
p9_fid_put() calls when leaving a block/function scope. That would simplify
code a load and avoid leaks in future.

>  void p9_client_cb(struct p9_client *c, struct p9_req_t *req, int status);
> 
>  int p9_parse_header(struct p9_fcall *pdu, int32_t *size, int8_t *type,
> diff --git a/net/9p/client.c b/net/9p/client.c
> index 8bba0d9cf975..f3eb280c7d9d 100644
> --- a/net/9p/client.c
> +++ b/net/9p/client.c
> @@ -1228,7 +1228,7 @@ struct p9_fid *p9_client_walk(struct p9_fid *oldfid,
> uint16_t nwname,
> 
>  clunk_fid:
>  	kfree(wqids);
> -	p9_client_clunk(fid);
> +	p9_fid_put(fid);
>  	fid = NULL;
> 
>  error:
> @@ -1459,15 +1459,6 @@ int p9_client_clunk(struct p9_fid *fid)
>  	struct p9_req_t *req;
>  	int retries = 0;
> 
> -	if (!fid || IS_ERR(fid)) {
> -		pr_warn("%s (%d): Trying to clunk with invalid fid\n",
> -			__func__, task_pid_nr(current));
> -		dump_stack();
> -		return 0;
> -	}
> -	if (!refcount_dec_and_test(&fid->count))
> -		return 0;
> -
>  again:
>  	p9_debug(P9_DEBUG_9P, ">>> TCLUNK fid %d (try %d)\n",
>  		 fid->fid, retries);
> @@ -1519,7 +1510,7 @@ int p9_client_remove(struct p9_fid *fid)
>  	p9_tag_remove(clnt, req);
>  error:
>  	if (err == -ERESTARTSYS)
> -		p9_client_clunk(fid);
> +		p9_fid_put(fid);
>  	else
>  		p9_fid_destroy(fid);
>  	return err;
> @@ -2042,7 +2033,7 @@ struct p9_fid *p9_client_xattrwalk(struct p9_fid
> *file_fid, attr_fid->fid, *attr_size);
>  	return attr_fid;
>  clunk_fid:
> -	p9_client_clunk(attr_fid);
> +	p9_fid_put(attr_fid);
>  	attr_fid = NULL;
>  error:
>  	if (attr_fid && attr_fid != file_fid)





^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH v2 04/06] 9p fid refcount: add p9_fid_get/put wrappers
  2022-06-14 13:55     ` Christian Schoenebeck
@ 2022-06-14 14:27       ` Dominique Martinet
  2022-06-15  3:16       ` [PATCH v3 " Dominique Martinet
  1 sibling, 0 replies; 28+ messages in thread
From: Dominique Martinet @ 2022-06-14 14:27 UTC (permalink / raw)
  To: Christian Schoenebeck
  Cc: Tyler Hicks, Eric Van Hensbergen, Latchesar Ionkov,
	David S. Miller, Jakub Kicinski, Paolo Abeni, v9fs-developer,
	linux-kernel, netdev


Thanks for the reviews :)

Christian Schoenebeck wrote on Tue, Jun 14, 2022 at 03:55:39PM +0200:
> On Montag, 13. Juni 2022 01:45:54 CEST Dominique Martinet wrote:
> > I was recently reminded that it is not clear that p9_client_clunk()
> > was actually just decrementing refcount and clunking only when that
> > reaches zero: make it clear through a set of helpers.
> > 
> > This will also allow instrumenting refcounting better for debugging
> > next patch, which is the reason these are not defined as static inline:
> > we won't be able to add trace events there...
> 
> Looks like you forgot to adjust the commit log sentence here, ...
> 
> > Signed-off-by: Dominique Martinet <asmadeus@codewreck.org>
> > ---
> > v1 -> v2: p9_fid_get/put are now static inline in .h
> 
> ... as the two functions are in fact static inlined in this v2 now.

Good point, will fix!


> > diff --git a/include/net/9p/client.h b/include/net/9p/client.h
> > index ec1d1706f43c..9fd38d674057 100644
> > --- a/include/net/9p/client.h
> > +++ b/include/net/9p/client.h
> > @@ -237,6 +237,24 @@ static inline int p9_req_try_get(struct p9_req_t *r)
> > 
> >  int p9_req_put(struct p9_req_t *r);
> > 
> > +static inline struct p9_fid *p9_fid_get(struct p9_fid *fid)
> > +{
> 
> Isn't this missing a check here?
> 
>     if (!fid)
>         return NULL;

It doesn't really make sense to get a null or error fid: whatever wants
to take a ref will error out first, so this didn't get a check unlike
put, which is nice to use without `if (fid && !IS_ERR(fid)) put(fid)`
all the time.


> 
> > +	refcount_inc(&fid->count);
> > +
> > +	return fid;
> > +}
> > +
> > +static inline int p9_fid_put(struct p9_fid *fid)
> > +{
> > +	if (!fid || IS_ERR(fid))
> > +		return 0;
> > +
> > +	if (!refcount_dec_and_test(&fid->count))
> > +		return 0;
> > +
> > +	return p9_client_clunk(fid);
> > +}
> > +
> 
> I don't know the common symbol name patterns in the Linux kernel for acquiring
> and releasing counted references are (if there is a common one at all), but I
> think those two functions deserve a short API comment to make it clear they
> belong together, i.e. that a p9_fid_get() call should be paired with
> subsequent p9_fid_put(). It's maybe just nitpicking, as the code is quite
> short and probably already speaks for itself.

I guess "but none of the other 50 functions do!" isn't a good reason not
to start, but it sure was enough to make me think it'd be silly to
document p9_fid_get/put right next to p9_req_get/put that don't have
their comment...
Better late than never though, I'll add something in v3.

As for common names you can see get/put in various places (kref_get/put,
of_node_get/put, pm_runime*_get/put) so I guess it's common enough.

> On the long-term I could imagine using automated, destructor based
> p9_fid_put() calls when leaving a block/function scope. That would simplify
> code a load and avoid leaks in future.

__attribute__(__cleanup__()) is nice but I've not seen any in linux
(looking again kcsan and locking selftests seem to be using it, I didn't
think it was allowed)...
Just making it clear goes a long way though, my last patch is a good
first step (inconditionally put'ing all fids at the end of functions and
NULLing fid pointers when stashing it in inode is pretty much what we'd
be doing if there were destructors), but I feel it's still not clear
which functions give a new ref or not cf. walk that can reuse the same
fid depending on its parameters.

I think making that clear would be a good next step for cleanup next
time there are problems and/or someone has time for it...
(But there are plenty of interesting things to check first, like the
performance regression with recent fscache perhaps...)

-- 
Dominique

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [PATCH v3 04/06] 9p fid refcount: add p9_fid_get/put wrappers
  2022-06-14 13:55     ` Christian Schoenebeck
  2022-06-14 14:27       ` Dominique Martinet
@ 2022-06-15  3:16       ` Dominique Martinet
  2022-06-15 13:00         ` Christian Schoenebeck
  1 sibling, 1 reply; 28+ messages in thread
From: Dominique Martinet @ 2022-06-15  3:16 UTC (permalink / raw)
  To: Eric Van Hensbergen, Latchesar Ionkov, Dominique Martinet,
	Christian Schoenebeck, David S. Miller, Jakub Kicinski,
	Paolo Abeni
  Cc: Tyler Hicks, v9fs-developer, linux-kernel, netdev

I was recently reminded that it is not clear that p9_client_clunk()
was actually just decrementing refcount and clunking only when that
reaches zero: make it clear through a set of helpers.

This will also allow instrumenting refcounting better for debugging
next patch

Link: https://lkml.kernel.org/r/20220612085330.1451496-5-asmadeus@codewreck.org
Reviewed-by: Tyler Hicks <tyhicks@linux.microsoft.com>
Signed-off-by: Dominique Martinet <asmadeus@codewreck.org>
---
v1 -> v2: p9_fid_get/put are now static inline in .h
v2 -> v3: fix commit message and add comment to helpers

 fs/9p/fid.c             | 18 ++++++++--------
 fs/9p/fid.h             |  2 +-
 fs/9p/vfs_addr.c        |  4 ++--
 fs/9p/vfs_dentry.c      |  4 ++--
 fs/9p/vfs_dir.c         |  2 +-
 fs/9p/vfs_file.c        |  4 ++--
 fs/9p/vfs_inode.c       | 48 ++++++++++++++++++++---------------------
 fs/9p/vfs_inode_dotl.c  | 42 ++++++++++++++++++------------------
 fs/9p/vfs_super.c       |  6 +++---
 fs/9p/xattr.c           |  8 +++----
 include/net/9p/client.h | 28 ++++++++++++++++++++++++
 net/9p/client.c         | 15 +++----------
 12 files changed, 100 insertions(+), 81 deletions(-)

diff --git a/fs/9p/fid.c b/fs/9p/fid.c
index e8fad28fc5bd..d792499349c4 100644
--- a/fs/9p/fid.c
+++ b/fs/9p/fid.c
@@ -56,7 +56,7 @@ static struct p9_fid *v9fs_fid_find_inode(struct inode *inode, kuid_t uid)
 	h = (struct hlist_head *)&inode->i_private;
 	hlist_for_each_entry(fid, h, ilist) {
 		if (uid_eq(fid->uid, uid)) {
-			refcount_inc(&fid->count);
+			p9_fid_get(fid);
 			ret = fid;
 			break;
 		}
@@ -104,7 +104,7 @@ static struct p9_fid *v9fs_fid_find(struct dentry *dentry, kuid_t uid, int any)
 		hlist_for_each_entry(fid, h, dlist) {
 			if (any || uid_eq(fid->uid, uid)) {
 				ret = fid;
-				refcount_inc(&ret->count);
+				p9_fid_get(ret);
 				break;
 			}
 		}
@@ -172,7 +172,7 @@ static struct p9_fid *v9fs_fid_lookup_with_uid(struct dentry *dentry,
 		old_fid = fid;
 
 		fid = p9_client_walk(old_fid, 1, &dentry->d_name.name, 1);
-		p9_client_clunk(old_fid);
+		p9_fid_put(old_fid);
 		goto fid_out;
 	}
 	up_read(&v9ses->rename_sem);
@@ -194,7 +194,7 @@ static struct p9_fid *v9fs_fid_lookup_with_uid(struct dentry *dentry,
 		if (IS_ERR(root_fid))
 			return root_fid;
 
-		refcount_inc(&root_fid->count);
+		p9_fid_get(root_fid);
 		v9fs_fid_add(dentry->d_sb->s_root, root_fid);
 	}
 	/* If we are root ourself just return that */
@@ -225,7 +225,7 @@ static struct p9_fid *v9fs_fid_lookup_with_uid(struct dentry *dentry,
 				     old_fid == root_fid /* clone */);
 		/* non-cloning walk will return the same fid */
 		if (fid != old_fid) {
-			p9_client_clunk(old_fid);
+			p9_fid_put(old_fid);
 			old_fid = fid;
 		}
 		if (IS_ERR(fid)) {
@@ -240,11 +240,11 @@ static struct p9_fid *v9fs_fid_lookup_with_uid(struct dentry *dentry,
 		spin_lock(&dentry->d_lock);
 		if (d_unhashed(dentry)) {
 			spin_unlock(&dentry->d_lock);
-			p9_client_clunk(fid);
+			p9_fid_put(fid);
 			fid = ERR_PTR(-ENOENT);
 		} else {
 			__add_fid(dentry, fid);
-			refcount_inc(&fid->count);
+			p9_fid_get(fid);
 			spin_unlock(&dentry->d_lock);
 		}
 	}
@@ -301,7 +301,7 @@ struct p9_fid *v9fs_writeback_fid(struct dentry *dentry)
 	fid = clone_fid(ofid);
 	if (IS_ERR(fid))
 		goto error_out;
-	p9_client_clunk(ofid);
+	p9_fid_put(ofid);
 	/*
 	 * writeback fid will only be used to write back the
 	 * dirty pages. We always request for the open fid in read-write
@@ -310,7 +310,7 @@ struct p9_fid *v9fs_writeback_fid(struct dentry *dentry)
 	 */
 	err = p9_client_open(fid, O_RDWR);
 	if (err < 0) {
-		p9_client_clunk(fid);
+		p9_fid_put(fid);
 		fid = ERR_PTR(err);
 		goto error_out;
 	}
diff --git a/fs/9p/fid.h b/fs/9p/fid.h
index f7f33509e169..3168dfad510e 100644
--- a/fs/9p/fid.h
+++ b/fs/9p/fid.h
@@ -29,7 +29,7 @@ static inline struct p9_fid *v9fs_fid_clone(struct dentry *dentry)
 		return fid;
 
 	nfid = clone_fid(fid);
-	p9_client_clunk(fid);
+	p9_fid_put(fid);
 	return nfid;
 }
 #endif
diff --git a/fs/9p/vfs_addr.c b/fs/9p/vfs_addr.c
index 7f924e671e3e..c5f71eeb28b6 100644
--- a/fs/9p/vfs_addr.c
+++ b/fs/9p/vfs_addr.c
@@ -70,7 +70,7 @@ static int v9fs_init_request(struct netfs_io_request *rreq, struct file *file)
 
 	BUG_ON(!fid);
 
-	refcount_inc(&fid->count);
+	p9_fid_get(fid);
 	rreq->netfs_priv = fid;
 	return 0;
 }
@@ -83,7 +83,7 @@ static void v9fs_free_request(struct netfs_io_request *rreq)
 {
 	struct p9_fid *fid = rreq->netfs_priv;
 
-	p9_client_clunk(fid);
+	p9_fid_put(fid);
 }
 
 /**
diff --git a/fs/9p/vfs_dentry.c b/fs/9p/vfs_dentry.c
index 1c609e99d280..f89f01734587 100644
--- a/fs/9p/vfs_dentry.c
+++ b/fs/9p/vfs_dentry.c
@@ -54,7 +54,7 @@ static void v9fs_dentry_release(struct dentry *dentry)
 	p9_debug(P9_DEBUG_VFS, " dentry: %pd (%p)\n",
 		 dentry, dentry);
 	hlist_for_each_safe(p, n, (struct hlist_head *)&dentry->d_fsdata)
-		p9_client_clunk(hlist_entry(p, struct p9_fid, dlist));
+		p9_fid_put(hlist_entry(p, struct p9_fid, dlist));
 	dentry->d_fsdata = NULL;
 }
 
@@ -85,7 +85,7 @@ static int v9fs_lookup_revalidate(struct dentry *dentry, unsigned int flags)
 			retval = v9fs_refresh_inode_dotl(fid, inode);
 		else
 			retval = v9fs_refresh_inode(fid, inode);
-		p9_client_clunk(fid);
+		p9_fid_put(fid);
 
 		if (retval == -ENOENT)
 			return 0;
diff --git a/fs/9p/vfs_dir.c b/fs/9p/vfs_dir.c
index 958680f7f23e..000fbaae9b18 100644
--- a/fs/9p/vfs_dir.c
+++ b/fs/9p/vfs_dir.c
@@ -218,7 +218,7 @@ int v9fs_dir_release(struct inode *inode, struct file *filp)
 		spin_lock(&inode->i_lock);
 		hlist_del(&fid->ilist);
 		spin_unlock(&inode->i_lock);
-		p9_client_clunk(fid);
+		p9_fid_put(fid);
 	}
 
 	if ((filp->f_mode & FMODE_WRITE)) {
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c
index 2573c08f335c..8276f3af35d7 100644
--- a/fs/9p/vfs_file.c
+++ b/fs/9p/vfs_file.c
@@ -63,7 +63,7 @@ int v9fs_file_open(struct inode *inode, struct file *file)
 
 		err = p9_client_open(fid, omode);
 		if (err < 0) {
-			p9_client_clunk(fid);
+			p9_fid_put(fid);
 			return err;
 		}
 		if ((file->f_flags & O_APPEND) &&
@@ -98,7 +98,7 @@ int v9fs_file_open(struct inode *inode, struct file *file)
 	v9fs_open_fid_add(inode, fid);
 	return 0;
 out_error:
-	p9_client_clunk(file->private_data);
+	p9_fid_put(file->private_data);
 	file->private_data = NULL;
 	return err;
 }
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index 3d8297714772..bde18776f0c7 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -400,7 +400,7 @@ void v9fs_evict_inode(struct inode *inode)
 	fscache_relinquish_cookie(v9fs_inode_cookie(v9inode), false);
 	/* clunk the fid stashed in writeback_fid */
 	if (v9inode->writeback_fid) {
-		p9_client_clunk(v9inode->writeback_fid);
+		p9_fid_put(v9inode->writeback_fid);
 		v9inode->writeback_fid = NULL;
 	}
 }
@@ -569,7 +569,7 @@ static int v9fs_remove(struct inode *dir, struct dentry *dentry, int flags)
 	if (v9fs_proto_dotl(v9ses))
 		retval = p9_client_unlinkat(dfid, dentry->d_name.name,
 					    v9fs_at_to_dotl_flags(flags));
-	p9_client_clunk(dfid);
+	p9_fid_put(dfid);
 	if (retval == -EOPNOTSUPP) {
 		/* Try the one based on path */
 		v9fid = v9fs_fid_clone(dentry);
@@ -633,14 +633,14 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,
 	if (IS_ERR(ofid)) {
 		err = PTR_ERR(ofid);
 		p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err);
-		p9_client_clunk(dfid);
+		p9_fid_put(dfid);
 		return ERR_PTR(err);
 	}
 
 	err = p9_client_fcreate(ofid, name, perm, mode, extension);
 	if (err < 0) {
 		p9_debug(P9_DEBUG_VFS, "p9_client_fcreate failed %d\n", err);
-		p9_client_clunk(dfid);
+		p9_fid_put(dfid);
 		goto error;
 	}
 
@@ -652,7 +652,7 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,
 			p9_debug(P9_DEBUG_VFS,
 				   "p9_client_walk failed %d\n", err);
 			fid = NULL;
-			p9_client_clunk(dfid);
+			p9_fid_put(dfid);
 			goto error;
 		}
 		/*
@@ -663,20 +663,20 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,
 			err = PTR_ERR(inode);
 			p9_debug(P9_DEBUG_VFS,
 				   "inode creation failed %d\n", err);
-			p9_client_clunk(dfid);
+			p9_fid_put(dfid);
 			goto error;
 		}
 		v9fs_fid_add(dentry, fid);
 		d_instantiate(dentry, inode);
 	}
-	p9_client_clunk(dfid);
+	p9_fid_put(dfid);
 	return ofid;
 error:
 	if (ofid)
-		p9_client_clunk(ofid);
+		p9_fid_put(ofid);
 
 	if (fid)
-		p9_client_clunk(fid);
+		p9_fid_put(fid);
 
 	return ERR_PTR(err);
 }
@@ -708,7 +708,7 @@ v9fs_vfs_create(struct user_namespace *mnt_userns, struct inode *dir,
 		return PTR_ERR(fid);
 
 	v9fs_invalidate_inode_attr(dir);
-	p9_client_clunk(fid);
+	p9_fid_put(fid);
 
 	return 0;
 }
@@ -744,7 +744,7 @@ static int v9fs_vfs_mkdir(struct user_namespace *mnt_userns, struct inode *dir,
 	}
 
 	if (fid)
-		p9_client_clunk(fid);
+		p9_fid_put(fid);
 
 	return err;
 }
@@ -785,7 +785,7 @@ struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
 	 */
 	name = dentry->d_name.name;
 	fid = p9_client_walk(dfid, 1, &name, 1);
-	p9_client_clunk(dfid);
+	p9_fid_put(dfid);
 	if (fid == ERR_PTR(-ENOENT))
 		inode = NULL;
 	else if (IS_ERR(fid))
@@ -808,7 +808,7 @@ struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
 		else if (!IS_ERR(res))
 			v9fs_fid_add(res, fid);
 		else
-			p9_client_clunk(fid);
+			p9_fid_put(fid);
 	}
 	return res;
 }
@@ -891,7 +891,7 @@ v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry,
 
 error:
 	if (fid)
-		p9_client_clunk(fid);
+		p9_fid_put(fid);
 	goto out;
 }
 
@@ -959,7 +959,7 @@ v9fs_vfs_rename(struct user_namespace *mnt_userns, struct inode *old_dir,
 	dfid = v9fs_parent_fid(old_dentry);
 	olddirfid = clone_fid(dfid);
 	if (dfid && !IS_ERR(dfid))
-		p9_client_clunk(dfid);
+		p9_fid_put(dfid);
 
 	if (IS_ERR(olddirfid)) {
 		retval = PTR_ERR(olddirfid);
@@ -968,7 +968,7 @@ v9fs_vfs_rename(struct user_namespace *mnt_userns, struct inode *old_dir,
 
 	dfid = v9fs_parent_fid(new_dentry);
 	newdirfid = clone_fid(dfid);
-	p9_client_clunk(dfid);
+	p9_fid_put(dfid);
 
 	if (IS_ERR(newdirfid)) {
 		retval = PTR_ERR(newdirfid);
@@ -1020,13 +1020,13 @@ v9fs_vfs_rename(struct user_namespace *mnt_userns, struct inode *old_dir,
 		d_move(old_dentry, new_dentry);
 	}
 	up_write(&v9ses->rename_sem);
-	p9_client_clunk(newdirfid);
+	p9_fid_put(newdirfid);
 
 clunk_olddir:
-	p9_client_clunk(olddirfid);
+	p9_fid_put(olddirfid);
 
 done:
-	p9_client_clunk(oldfid);
+	p9_fid_put(oldfid);
 	return retval;
 }
 
@@ -1060,7 +1060,7 @@ v9fs_vfs_getattr(struct user_namespace *mnt_userns, const struct path *path,
 		return PTR_ERR(fid);
 
 	st = p9_client_stat(fid);
-	p9_client_clunk(fid);
+	p9_fid_put(fid);
 	if (IS_ERR(st))
 		return PTR_ERR(st);
 
@@ -1136,7 +1136,7 @@ static int v9fs_vfs_setattr(struct user_namespace *mnt_userns,
 	retval = p9_client_wstat(fid, &wstat);
 
 	if (use_dentry)
-		p9_client_clunk(fid);
+		p9_fid_put(fid);
 
 	if (retval < 0)
 		return retval;
@@ -1261,7 +1261,7 @@ static const char *v9fs_vfs_get_link(struct dentry *dentry,
 		return ERR_CAST(fid);
 
 	st = p9_client_stat(fid);
-	p9_client_clunk(fid);
+	p9_fid_put(fid);
 	if (IS_ERR(st))
 		return ERR_CAST(st);
 
@@ -1308,7 +1308,7 @@ static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry,
 		return PTR_ERR(fid);
 
 	v9fs_invalidate_inode_attr(dir);
-	p9_client_clunk(fid);
+	p9_fid_put(fid);
 	return 0;
 }
 
@@ -1364,7 +1364,7 @@ v9fs_vfs_link(struct dentry *old_dentry, struct inode *dir,
 		v9fs_refresh_inode(oldfid, d_inode(old_dentry));
 		v9fs_invalidate_inode_attr(dir);
 	}
-	p9_client_clunk(oldfid);
+	p9_fid_put(oldfid);
 	return retval;
 }
 
diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c
index b6eb1160296c..09b124fe349c 100644
--- a/fs/9p/vfs_inode_dotl.c
+++ b/fs/9p/vfs_inode_dotl.c
@@ -274,7 +274,7 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
 	if (IS_ERR(ofid)) {
 		err = PTR_ERR(ofid);
 		p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err);
-		p9_client_clunk(dfid);
+		p9_fid_put(dfid);
 		goto out;
 	}
 
@@ -286,7 +286,7 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
 	if (err) {
 		p9_debug(P9_DEBUG_VFS, "Failed to get acl values in creat %d\n",
 			 err);
-		p9_client_clunk(dfid);
+		p9_fid_put(dfid);
 		goto error;
 	}
 	err = p9_client_create_dotl(ofid, name, v9fs_open_to_dotl_flags(flags),
@@ -294,14 +294,14 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
 	if (err < 0) {
 		p9_debug(P9_DEBUG_VFS, "p9_client_open_dotl failed in creat %d\n",
 			 err);
-		p9_client_clunk(dfid);
+		p9_fid_put(dfid);
 		goto error;
 	}
 	v9fs_invalidate_inode_attr(dir);
 
 	/* instantiate inode and assign the unopened fid to the dentry */
 	fid = p9_client_walk(dfid, 1, &name, 1);
-	p9_client_clunk(dfid);
+	p9_fid_put(dfid);
 	if (IS_ERR(fid)) {
 		err = PTR_ERR(fid);
 		p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err);
@@ -358,10 +358,10 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
 
 error:
 	if (fid)
-		p9_client_clunk(fid);
+		p9_fid_put(fid);
 err_clunk_old_fid:
 	if (ofid)
-		p9_client_clunk(ofid);
+		p9_fid_put(ofid);
 	goto out;
 }
 
@@ -458,9 +458,9 @@ static int v9fs_vfs_mkdir_dotl(struct user_namespace *mnt_userns,
 	v9fs_invalidate_inode_attr(dir);
 error:
 	if (fid)
-		p9_client_clunk(fid);
+		p9_fid_put(fid);
 	v9fs_put_acl(dacl, pacl);
-	p9_client_clunk(dfid);
+	p9_fid_put(dfid);
 	return err;
 }
 
@@ -489,7 +489,7 @@ v9fs_vfs_getattr_dotl(struct user_namespace *mnt_userns,
 	 */
 
 	st = p9_client_getattr_dotl(fid, P9_STATS_ALL);
-	p9_client_clunk(fid);
+	p9_fid_put(fid);
 	if (IS_ERR(st))
 		return PTR_ERR(st);
 
@@ -603,7 +603,7 @@ int v9fs_vfs_setattr_dotl(struct user_namespace *mnt_userns,
 	retval = p9_client_setattr(fid, &p9attr);
 	if (retval < 0) {
 		if (use_dentry)
-			p9_client_clunk(fid);
+			p9_fid_put(fid);
 		return retval;
 	}
 
@@ -619,12 +619,12 @@ int v9fs_vfs_setattr_dotl(struct user_namespace *mnt_userns,
 		retval = v9fs_acl_chmod(inode, fid);
 		if (retval < 0) {
 			if (use_dentry)
-				p9_client_clunk(fid);
+				p9_fid_put(fid);
 			return retval;
 		}
 	}
 	if (use_dentry)
-		p9_client_clunk(fid);
+		p9_fid_put(fid);
 
 	return 0;
 }
@@ -771,9 +771,9 @@ v9fs_vfs_symlink_dotl(struct user_namespace *mnt_userns, struct inode *dir,
 
 error:
 	if (fid)
-		p9_client_clunk(fid);
+		p9_fid_put(fid);
 
-	p9_client_clunk(dfid);
+	p9_fid_put(dfid);
 	return err;
 }
 
@@ -803,14 +803,14 @@ v9fs_vfs_link_dotl(struct dentry *old_dentry, struct inode *dir,
 
 	oldfid = v9fs_fid_lookup(old_dentry);
 	if (IS_ERR(oldfid)) {
-		p9_client_clunk(dfid);
+		p9_fid_put(dfid);
 		return PTR_ERR(oldfid);
 	}
 
 	err = p9_client_link(dfid, oldfid, dentry->d_name.name);
 
-	p9_client_clunk(dfid);
-	p9_client_clunk(oldfid);
+	p9_fid_put(dfid);
+	p9_fid_put(oldfid);
 	if (err < 0) {
 		p9_debug(P9_DEBUG_VFS, "p9_client_link failed %d\n", err);
 		return err;
@@ -826,7 +826,7 @@ v9fs_vfs_link_dotl(struct dentry *old_dentry, struct inode *dir,
 			return PTR_ERR(fid);
 
 		v9fs_refresh_inode_dotl(fid, d_inode(old_dentry));
-		p9_client_clunk(fid);
+		p9_fid_put(fid);
 	}
 	ihold(d_inode(old_dentry));
 	d_instantiate(dentry, d_inode(old_dentry));
@@ -924,9 +924,9 @@ v9fs_vfs_mknod_dotl(struct user_namespace *mnt_userns, struct inode *dir,
 	}
 error:
 	if (fid)
-		p9_client_clunk(fid);
+		p9_fid_put(fid);
 	v9fs_put_acl(dacl, pacl);
-	p9_client_clunk(dfid);
+	p9_fid_put(dfid);
 
 	return err;
 }
@@ -956,7 +956,7 @@ v9fs_vfs_get_link_dotl(struct dentry *dentry,
 	if (IS_ERR(fid))
 		return ERR_CAST(fid);
 	retval = p9_client_readlink(fid, &target);
-	p9_client_clunk(fid);
+	p9_fid_put(fid);
 	if (retval)
 		return ERR_PTR(retval);
 	set_delayed_call(done, kfree_link, target);
diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c
index 97e23b4e6982..bf350fad9500 100644
--- a/fs/9p/vfs_super.c
+++ b/fs/9p/vfs_super.c
@@ -190,7 +190,7 @@ static struct dentry *v9fs_mount(struct file_system_type *fs_type, int flags,
 	return dget(sb->s_root);
 
 clunk_fid:
-	p9_client_clunk(fid);
+	p9_fid_put(fid);
 	v9fs_session_close(v9ses);
 free_session:
 	kfree(v9ses);
@@ -203,7 +203,7 @@ static struct dentry *v9fs_mount(struct file_system_type *fs_type, int flags,
 	 * attached the fid to dentry so it won't get clunked
 	 * automatically.
 	 */
-	p9_client_clunk(fid);
+	p9_fid_put(fid);
 	deactivate_locked_super(sb);
 	return ERR_PTR(retval);
 }
@@ -270,7 +270,7 @@ static int v9fs_statfs(struct dentry *dentry, struct kstatfs *buf)
 	}
 	res = simple_statfs(dentry, buf);
 done:
-	p9_client_clunk(fid);
+	p9_fid_put(fid);
 	return res;
 }
 
diff --git a/fs/9p/xattr.c b/fs/9p/xattr.c
index a824441b95a2..1f9298a4bd42 100644
--- a/fs/9p/xattr.c
+++ b/fs/9p/xattr.c
@@ -44,7 +44,7 @@ ssize_t v9fs_fid_xattr_get(struct p9_fid *fid, const char *name,
 		if (err)
 			retval = err;
 	}
-	p9_client_clunk(attr_fid);
+	p9_fid_put(attr_fid);
 	return retval;
 }
 
@@ -71,7 +71,7 @@ ssize_t v9fs_xattr_get(struct dentry *dentry, const char *name,
 	if (IS_ERR(fid))
 		return PTR_ERR(fid);
 	ret = v9fs_fid_xattr_get(fid, name, buffer, buffer_size);
-	p9_client_clunk(fid);
+	p9_fid_put(fid);
 
 	return ret;
 }
@@ -98,7 +98,7 @@ int v9fs_xattr_set(struct dentry *dentry, const char *name,
 	if (IS_ERR(fid))
 		return PTR_ERR(fid);
 	ret = v9fs_fid_xattr_set(fid, name, value, value_len, flags);
-	p9_client_clunk(fid);
+	p9_fid_put(fid);
 	return ret;
 }
 
@@ -128,7 +128,7 @@ int v9fs_fid_xattr_set(struct p9_fid *fid, const char *name,
 			 retval);
 	else
 		p9_client_write(fid, 0, &from, &retval);
-	err = p9_client_clunk(fid);
+	err = p9_fid_put(fid);
 	if (!retval && err)
 		retval = err;
 	return retval;
diff --git a/include/net/9p/client.h b/include/net/9p/client.h
index ec1d1706f43c..eabb53992350 100644
--- a/include/net/9p/client.h
+++ b/include/net/9p/client.h
@@ -237,6 +237,34 @@ static inline int p9_req_try_get(struct p9_req_t *r)
 
 int p9_req_put(struct p9_req_t *r);
 
+/* fid reference counting helpers:
+ *  - fids used for any length of time should always be referenced through
+ *    p9_fid_get(), and released with p9_fid_put()
+ *  - v9fs_fid_lookup() or similar will automatically call get for you
+ *    and also require a put
+ *  - the *_fid_add() helpers will stash the fid in the inode,
+ *    at which point it is the responsibility of evict_inode()
+ *    to call the put
+ *  - the last put will automatically send a clunk to the server
+ */
+static inline struct p9_fid *p9_fid_get(struct p9_fid *fid)
+{
+	refcount_inc(&fid->count);
+
+	return fid;
+}
+
+static inline int p9_fid_put(struct p9_fid *fid)
+{
+	if (!fid || IS_ERR(fid))
+		return 0;
+
+	if (!refcount_dec_and_test(&fid->count))
+		return 0;
+
+	return p9_client_clunk(fid);
+}
+
 void p9_client_cb(struct p9_client *c, struct p9_req_t *req, int status);
 
 int p9_parse_header(struct p9_fcall *pdu, int32_t *size, int8_t *type,
diff --git a/net/9p/client.c b/net/9p/client.c
index 8bba0d9cf975..f3eb280c7d9d 100644
--- a/net/9p/client.c
+++ b/net/9p/client.c
@@ -1228,7 +1228,7 @@ struct p9_fid *p9_client_walk(struct p9_fid *oldfid, uint16_t nwname,
 
 clunk_fid:
 	kfree(wqids);
-	p9_client_clunk(fid);
+	p9_fid_put(fid);
 	fid = NULL;
 
 error:
@@ -1459,15 +1459,6 @@ int p9_client_clunk(struct p9_fid *fid)
 	struct p9_req_t *req;
 	int retries = 0;
 
-	if (!fid || IS_ERR(fid)) {
-		pr_warn("%s (%d): Trying to clunk with invalid fid\n",
-			__func__, task_pid_nr(current));
-		dump_stack();
-		return 0;
-	}
-	if (!refcount_dec_and_test(&fid->count))
-		return 0;
-
 again:
 	p9_debug(P9_DEBUG_9P, ">>> TCLUNK fid %d (try %d)\n",
 		 fid->fid, retries);
@@ -1519,7 +1510,7 @@ int p9_client_remove(struct p9_fid *fid)
 	p9_tag_remove(clnt, req);
 error:
 	if (err == -ERESTARTSYS)
-		p9_client_clunk(fid);
+		p9_fid_put(fid);
 	else
 		p9_fid_destroy(fid);
 	return err;
@@ -2042,7 +2033,7 @@ struct p9_fid *p9_client_xattrwalk(struct p9_fid *file_fid,
 		 attr_fid->fid, *attr_size);
 	return attr_fid;
 clunk_fid:
-	p9_client_clunk(attr_fid);
+	p9_fid_put(attr_fid);
 	attr_fid = NULL;
 error:
 	if (attr_fid && attr_fid != file_fid)
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* Re: [PATCH v3 04/06] 9p fid refcount: add p9_fid_get/put wrappers
  2022-06-15  3:16       ` [PATCH v3 " Dominique Martinet
@ 2022-06-15 13:00         ` Christian Schoenebeck
  2022-06-15 13:47           ` Dominique Martinet
  0 siblings, 1 reply; 28+ messages in thread
From: Christian Schoenebeck @ 2022-06-15 13:00 UTC (permalink / raw)
  To: Eric Van Hensbergen, Latchesar Ionkov, Dominique Martinet,
	David S. Miller, Jakub Kicinski, Paolo Abeni, Tyler Hicks
  Cc: v9fs-developer, linux-kernel, netdev

On Mittwoch, 15. Juni 2022 05:16:45 CEST Dominique Martinet wrote:
> I was recently reminded that it is not clear that p9_client_clunk()
> was actually just decrementing refcount and clunking only when that
> reaches zero: make it clear through a set of helpers.
> 
> This will also allow instrumenting refcounting better for debugging
> next patch
> 
> Link:
> https://lkml.kernel.org/r/20220612085330.1451496-5-asmadeus@codewreck.org
> Reviewed-by: Tyler Hicks <tyhicks@linux.microsoft.com>
> Signed-off-by: Dominique Martinet <asmadeus@codewreck.org>
> ---
> v1 -> v2: p9_fid_get/put are now static inline in .h
> v2 -> v3: fix commit message and add comment to helpers
> 
>  fs/9p/fid.c             | 18 ++++++++--------
>  fs/9p/fid.h             |  2 +-
>  fs/9p/vfs_addr.c        |  4 ++--
>  fs/9p/vfs_dentry.c      |  4 ++--
>  fs/9p/vfs_dir.c         |  2 +-
>  fs/9p/vfs_file.c        |  4 ++--
>  fs/9p/vfs_inode.c       | 48 ++++++++++++++++++++---------------------
>  fs/9p/vfs_inode_dotl.c  | 42 ++++++++++++++++++------------------
>  fs/9p/vfs_super.c       |  6 +++---
>  fs/9p/xattr.c           |  8 +++----
>  include/net/9p/client.h | 28 ++++++++++++++++++++++++
>  net/9p/client.c         | 15 +++----------
>  12 files changed, 100 insertions(+), 81 deletions(-)
> 
> diff --git a/fs/9p/fid.c b/fs/9p/fid.c
> index e8fad28fc5bd..d792499349c4 100644
> --- a/fs/9p/fid.c
> +++ b/fs/9p/fid.c
> @@ -56,7 +56,7 @@ static struct p9_fid *v9fs_fid_find_inode(struct inode
> *inode, kuid_t uid) h = (struct hlist_head *)&inode->i_private;
>  	hlist_for_each_entry(fid, h, ilist) {
>  		if (uid_eq(fid->uid, uid)) {
> -			refcount_inc(&fid->count);
> +			p9_fid_get(fid);
>  			ret = fid;
>  			break;
>  		}
> @@ -104,7 +104,7 @@ static struct p9_fid *v9fs_fid_find(struct dentry
> *dentry, kuid_t uid, int any) hlist_for_each_entry(fid, h, dlist) {
>  			if (any || uid_eq(fid->uid, uid)) {
>  				ret = fid;
> -				refcount_inc(&ret->count);
> +				p9_fid_get(ret);
>  				break;
>  			}
>  		}
> @@ -172,7 +172,7 @@ static struct p9_fid *v9fs_fid_lookup_with_uid(struct
> dentry *dentry, old_fid = fid;
> 
>  		fid = p9_client_walk(old_fid, 1, &dentry->d_name.name, 1);
> -		p9_client_clunk(old_fid);
> +		p9_fid_put(old_fid);
>  		goto fid_out;
>  	}
>  	up_read(&v9ses->rename_sem);
> @@ -194,7 +194,7 @@ static struct p9_fid *v9fs_fid_lookup_with_uid(struct
> dentry *dentry, if (IS_ERR(root_fid))
>  			return root_fid;
> 
> -		refcount_inc(&root_fid->count);
> +		p9_fid_get(root_fid);
>  		v9fs_fid_add(dentry->d_sb->s_root, root_fid);
>  	}
>  	/* If we are root ourself just return that */
> @@ -225,7 +225,7 @@ static struct p9_fid *v9fs_fid_lookup_with_uid(struct
> dentry *dentry, old_fid == root_fid /* clone */);
>  		/* non-cloning walk will return the same fid */
>  		if (fid != old_fid) {
> -			p9_client_clunk(old_fid);
> +			p9_fid_put(old_fid);
>  			old_fid = fid;
>  		}
>  		if (IS_ERR(fid)) {
> @@ -240,11 +240,11 @@ static struct p9_fid *v9fs_fid_lookup_with_uid(struct
> dentry *dentry, spin_lock(&dentry->d_lock);
>  		if (d_unhashed(dentry)) {
>  			spin_unlock(&dentry->d_lock);
> -			p9_client_clunk(fid);
> +			p9_fid_put(fid);
>  			fid = ERR_PTR(-ENOENT);
>  		} else {
>  			__add_fid(dentry, fid);
> -			refcount_inc(&fid->count);
> +			p9_fid_get(fid);
>  			spin_unlock(&dentry->d_lock);
>  		}
>  	}
> @@ -301,7 +301,7 @@ struct p9_fid *v9fs_writeback_fid(struct dentry *dentry)
> fid = clone_fid(ofid);
>  	if (IS_ERR(fid))
>  		goto error_out;
> -	p9_client_clunk(ofid);
> +	p9_fid_put(ofid);
>  	/*
>  	 * writeback fid will only be used to write back the
>  	 * dirty pages. We always request for the open fid in read-write
> @@ -310,7 +310,7 @@ struct p9_fid *v9fs_writeback_fid(struct dentry *dentry)
> */
>  	err = p9_client_open(fid, O_RDWR);
>  	if (err < 0) {
> -		p9_client_clunk(fid);
> +		p9_fid_put(fid);
>  		fid = ERR_PTR(err);
>  		goto error_out;
>  	}
> diff --git a/fs/9p/fid.h b/fs/9p/fid.h
> index f7f33509e169..3168dfad510e 100644
> --- a/fs/9p/fid.h
> +++ b/fs/9p/fid.h
> @@ -29,7 +29,7 @@ static inline struct p9_fid *v9fs_fid_clone(struct dentry
> *dentry) return fid;
> 
>  	nfid = clone_fid(fid);
> -	p9_client_clunk(fid);
> +	p9_fid_put(fid);
>  	return nfid;
>  }
>  #endif
> diff --git a/fs/9p/vfs_addr.c b/fs/9p/vfs_addr.c
> index 7f924e671e3e..c5f71eeb28b6 100644
> --- a/fs/9p/vfs_addr.c
> +++ b/fs/9p/vfs_addr.c
> @@ -70,7 +70,7 @@ static int v9fs_init_request(struct netfs_io_request
> *rreq, struct file *file)
> 
>  	BUG_ON(!fid);
> 
> -	refcount_inc(&fid->count);
> +	p9_fid_get(fid);
>  	rreq->netfs_priv = fid;
>  	return 0;
>  }
> @@ -83,7 +83,7 @@ static void v9fs_free_request(struct netfs_io_request
> *rreq) {
>  	struct p9_fid *fid = rreq->netfs_priv;
> 
> -	p9_client_clunk(fid);
> +	p9_fid_put(fid);
>  }
> 
>  /**
> diff --git a/fs/9p/vfs_dentry.c b/fs/9p/vfs_dentry.c
> index 1c609e99d280..f89f01734587 100644
> --- a/fs/9p/vfs_dentry.c
> +++ b/fs/9p/vfs_dentry.c
> @@ -54,7 +54,7 @@ static void v9fs_dentry_release(struct dentry *dentry)
>  	p9_debug(P9_DEBUG_VFS, " dentry: %pd (%p)\n",
>  		 dentry, dentry);
>  	hlist_for_each_safe(p, n, (struct hlist_head *)&dentry->d_fsdata)
> -		p9_client_clunk(hlist_entry(p, struct p9_fid, dlist));
> +		p9_fid_put(hlist_entry(p, struct p9_fid, dlist));
>  	dentry->d_fsdata = NULL;
>  }
> 
> @@ -85,7 +85,7 @@ static int v9fs_lookup_revalidate(struct dentry *dentry,
> unsigned int flags) retval = v9fs_refresh_inode_dotl(fid, inode);
>  		else
>  			retval = v9fs_refresh_inode(fid, inode);
> -		p9_client_clunk(fid);
> +		p9_fid_put(fid);
> 
>  		if (retval == -ENOENT)
>  			return 0;
> diff --git a/fs/9p/vfs_dir.c b/fs/9p/vfs_dir.c
> index 958680f7f23e..000fbaae9b18 100644
> --- a/fs/9p/vfs_dir.c
> +++ b/fs/9p/vfs_dir.c
> @@ -218,7 +218,7 @@ int v9fs_dir_release(struct inode *inode, struct file
> *filp) spin_lock(&inode->i_lock);
>  		hlist_del(&fid->ilist);
>  		spin_unlock(&inode->i_lock);
> -		p9_client_clunk(fid);
> +		p9_fid_put(fid);
>  	}
> 
>  	if ((filp->f_mode & FMODE_WRITE)) {
> diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c
> index 2573c08f335c..8276f3af35d7 100644
> --- a/fs/9p/vfs_file.c
> +++ b/fs/9p/vfs_file.c
> @@ -63,7 +63,7 @@ int v9fs_file_open(struct inode *inode, struct file *file)
> 
>  		err = p9_client_open(fid, omode);
>  		if (err < 0) {
> -			p9_client_clunk(fid);
> +			p9_fid_put(fid);
>  			return err;
>  		}
>  		if ((file->f_flags & O_APPEND) &&
> @@ -98,7 +98,7 @@ int v9fs_file_open(struct inode *inode, struct file *file)
> v9fs_open_fid_add(inode, fid);
>  	return 0;
>  out_error:
> -	p9_client_clunk(file->private_data);
> +	p9_fid_put(file->private_data);
>  	file->private_data = NULL;
>  	return err;
>  }
> diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
> index 3d8297714772..bde18776f0c7 100644
> --- a/fs/9p/vfs_inode.c
> +++ b/fs/9p/vfs_inode.c
> @@ -400,7 +400,7 @@ void v9fs_evict_inode(struct inode *inode)
>  	fscache_relinquish_cookie(v9fs_inode_cookie(v9inode), false);
>  	/* clunk the fid stashed in writeback_fid */
>  	if (v9inode->writeback_fid) {
> -		p9_client_clunk(v9inode->writeback_fid);
> +		p9_fid_put(v9inode->writeback_fid);
>  		v9inode->writeback_fid = NULL;
>  	}
>  }
> @@ -569,7 +569,7 @@ static int v9fs_remove(struct inode *dir, struct dentry
> *dentry, int flags) if (v9fs_proto_dotl(v9ses))
>  		retval = p9_client_unlinkat(dfid, dentry->d_name.name,
>  					    
v9fs_at_to_dotl_flags(flags));
> -	p9_client_clunk(dfid);
> +	p9_fid_put(dfid);
>  	if (retval == -EOPNOTSUPP) {
>  		/* Try the one based on path */
>  		v9fid = v9fs_fid_clone(dentry);
> @@ -633,14 +633,14 @@ v9fs_create(struct v9fs_session_info *v9ses, struct
> inode *dir, if (IS_ERR(ofid)) {
>  		err = PTR_ERR(ofid);
>  		p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err);
> -		p9_client_clunk(dfid);
> +		p9_fid_put(dfid);
>  		return ERR_PTR(err);
>  	}
> 
>  	err = p9_client_fcreate(ofid, name, perm, mode, extension);
>  	if (err < 0) {
>  		p9_debug(P9_DEBUG_VFS, "p9_client_fcreate failed %d\n", 
err);
> -		p9_client_clunk(dfid);
> +		p9_fid_put(dfid);
>  		goto error;
>  	}
> 
> @@ -652,7 +652,7 @@ v9fs_create(struct v9fs_session_info *v9ses, struct
> inode *dir, p9_debug(P9_DEBUG_VFS,
>  				   "p9_client_walk failed %d\n", err);
>  			fid = NULL;
> -			p9_client_clunk(dfid);
> +			p9_fid_put(dfid);
>  			goto error;
>  		}
>  		/*
> @@ -663,20 +663,20 @@ v9fs_create(struct v9fs_session_info *v9ses, struct
> inode *dir, err = PTR_ERR(inode);
>  			p9_debug(P9_DEBUG_VFS,
>  				   "inode creation failed %d\n", err);
> -			p9_client_clunk(dfid);
> +			p9_fid_put(dfid);
>  			goto error;
>  		}
>  		v9fs_fid_add(dentry, fid);
>  		d_instantiate(dentry, inode);
>  	}
> -	p9_client_clunk(dfid);
> +	p9_fid_put(dfid);
>  	return ofid;
>  error:
>  	if (ofid)
> -		p9_client_clunk(ofid);
> +		p9_fid_put(ofid);
> 
>  	if (fid)
> -		p9_client_clunk(fid);
> +		p9_fid_put(fid);
> 
>  	return ERR_PTR(err);
>  }
> @@ -708,7 +708,7 @@ v9fs_vfs_create(struct user_namespace *mnt_userns,
> struct inode *dir, return PTR_ERR(fid);
> 
>  	v9fs_invalidate_inode_attr(dir);
> -	p9_client_clunk(fid);
> +	p9_fid_put(fid);
> 
>  	return 0;
>  }
> @@ -744,7 +744,7 @@ static int v9fs_vfs_mkdir(struct user_namespace
> *mnt_userns, struct inode *dir, }
> 
>  	if (fid)
> -		p9_client_clunk(fid);
> +		p9_fid_put(fid);
> 
>  	return err;
>  }
> @@ -785,7 +785,7 @@ struct dentry *v9fs_vfs_lookup(struct inode *dir, struct
> dentry *dentry, */
>  	name = dentry->d_name.name;
>  	fid = p9_client_walk(dfid, 1, &name, 1);
> -	p9_client_clunk(dfid);
> +	p9_fid_put(dfid);
>  	if (fid == ERR_PTR(-ENOENT))
>  		inode = NULL;
>  	else if (IS_ERR(fid))
> @@ -808,7 +808,7 @@ struct dentry *v9fs_vfs_lookup(struct inode *dir, struct
> dentry *dentry, else if (!IS_ERR(res))
>  			v9fs_fid_add(res, fid);
>  		else
> -			p9_client_clunk(fid);
> +			p9_fid_put(fid);
>  	}
>  	return res;
>  }
> @@ -891,7 +891,7 @@ v9fs_vfs_atomic_open(struct inode *dir, struct dentry
> *dentry,
> 
>  error:
>  	if (fid)
> -		p9_client_clunk(fid);
> +		p9_fid_put(fid);
>  	goto out;
>  }
> 
> @@ -959,7 +959,7 @@ v9fs_vfs_rename(struct user_namespace *mnt_userns,
> struct inode *old_dir, dfid = v9fs_parent_fid(old_dentry);
>  	olddirfid = clone_fid(dfid);
>  	if (dfid && !IS_ERR(dfid))
> -		p9_client_clunk(dfid);
> +		p9_fid_put(dfid);
> 
>  	if (IS_ERR(olddirfid)) {
>  		retval = PTR_ERR(olddirfid);
> @@ -968,7 +968,7 @@ v9fs_vfs_rename(struct user_namespace *mnt_userns,
> struct inode *old_dir,
> 
>  	dfid = v9fs_parent_fid(new_dentry);
>  	newdirfid = clone_fid(dfid);
> -	p9_client_clunk(dfid);
> +	p9_fid_put(dfid);
> 
>  	if (IS_ERR(newdirfid)) {
>  		retval = PTR_ERR(newdirfid);
> @@ -1020,13 +1020,13 @@ v9fs_vfs_rename(struct user_namespace *mnt_userns,
> struct inode *old_dir, d_move(old_dentry, new_dentry);
>  	}
>  	up_write(&v9ses->rename_sem);
> -	p9_client_clunk(newdirfid);
> +	p9_fid_put(newdirfid);
> 
>  clunk_olddir:
> -	p9_client_clunk(olddirfid);
> +	p9_fid_put(olddirfid);
> 
>  done:
> -	p9_client_clunk(oldfid);
> +	p9_fid_put(oldfid);
>  	return retval;
>  }
> 
> @@ -1060,7 +1060,7 @@ v9fs_vfs_getattr(struct user_namespace *mnt_userns,
> const struct path *path, return PTR_ERR(fid);
> 
>  	st = p9_client_stat(fid);
> -	p9_client_clunk(fid);
> +	p9_fid_put(fid);
>  	if (IS_ERR(st))
>  		return PTR_ERR(st);
> 
> @@ -1136,7 +1136,7 @@ static int v9fs_vfs_setattr(struct user_namespace
> *mnt_userns, retval = p9_client_wstat(fid, &wstat);
> 
>  	if (use_dentry)
> -		p9_client_clunk(fid);
> +		p9_fid_put(fid);
> 
>  	if (retval < 0)
>  		return retval;
> @@ -1261,7 +1261,7 @@ static const char *v9fs_vfs_get_link(struct dentry
> *dentry, return ERR_CAST(fid);
> 
>  	st = p9_client_stat(fid);
> -	p9_client_clunk(fid);
> +	p9_fid_put(fid);
>  	if (IS_ERR(st))
>  		return ERR_CAST(st);
> 
> @@ -1308,7 +1308,7 @@ static int v9fs_vfs_mkspecial(struct inode *dir,
> struct dentry *dentry, return PTR_ERR(fid);
> 
>  	v9fs_invalidate_inode_attr(dir);
> -	p9_client_clunk(fid);
> +	p9_fid_put(fid);
>  	return 0;
>  }
> 
> @@ -1364,7 +1364,7 @@ v9fs_vfs_link(struct dentry *old_dentry, struct inode
> *dir, v9fs_refresh_inode(oldfid, d_inode(old_dentry));
>  		v9fs_invalidate_inode_attr(dir);
>  	}
> -	p9_client_clunk(oldfid);
> +	p9_fid_put(oldfid);
>  	return retval;
>  }
> 
> diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c
> index b6eb1160296c..09b124fe349c 100644
> --- a/fs/9p/vfs_inode_dotl.c
> +++ b/fs/9p/vfs_inode_dotl.c
> @@ -274,7 +274,7 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct
> dentry *dentry, if (IS_ERR(ofid)) {
>  		err = PTR_ERR(ofid);
>  		p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err);
> -		p9_client_clunk(dfid);
> +		p9_fid_put(dfid);
>  		goto out;
>  	}
> 
> @@ -286,7 +286,7 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct
> dentry *dentry, if (err) {
>  		p9_debug(P9_DEBUG_VFS, "Failed to get acl values in creat 
%d\n",
>  			 err);
> -		p9_client_clunk(dfid);
> +		p9_fid_put(dfid);
>  		goto error;
>  	}
>  	err = p9_client_create_dotl(ofid, name, 
v9fs_open_to_dotl_flags(flags),
> @@ -294,14 +294,14 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct
> dentry *dentry, if (err < 0) {
>  		p9_debug(P9_DEBUG_VFS, "p9_client_open_dotl failed in 
creat %d\n",
>  			 err);
> -		p9_client_clunk(dfid);
> +		p9_fid_put(dfid);
>  		goto error;
>  	}
>  	v9fs_invalidate_inode_attr(dir);
> 
>  	/* instantiate inode and assign the unopened fid to the dentry */
>  	fid = p9_client_walk(dfid, 1, &name, 1);
> -	p9_client_clunk(dfid);
> +	p9_fid_put(dfid);
>  	if (IS_ERR(fid)) {
>  		err = PTR_ERR(fid);
>  		p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err);
> @@ -358,10 +358,10 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct
> dentry *dentry,
> 
>  error:
>  	if (fid)
> -		p9_client_clunk(fid);
> +		p9_fid_put(fid);
>  err_clunk_old_fid:
>  	if (ofid)
> -		p9_client_clunk(ofid);
> +		p9_fid_put(ofid);
>  	goto out;
>  }
> 
> @@ -458,9 +458,9 @@ static int v9fs_vfs_mkdir_dotl(struct user_namespace
> *mnt_userns, v9fs_invalidate_inode_attr(dir);
>  error:
>  	if (fid)
> -		p9_client_clunk(fid);
> +		p9_fid_put(fid);
>  	v9fs_put_acl(dacl, pacl);
> -	p9_client_clunk(dfid);
> +	p9_fid_put(dfid);
>  	return err;
>  }
> 
> @@ -489,7 +489,7 @@ v9fs_vfs_getattr_dotl(struct user_namespace *mnt_userns,
> */
> 
>  	st = p9_client_getattr_dotl(fid, P9_STATS_ALL);
> -	p9_client_clunk(fid);
> +	p9_fid_put(fid);
>  	if (IS_ERR(st))
>  		return PTR_ERR(st);
> 
> @@ -603,7 +603,7 @@ int v9fs_vfs_setattr_dotl(struct user_namespace
> *mnt_userns, retval = p9_client_setattr(fid, &p9attr);
>  	if (retval < 0) {
>  		if (use_dentry)
> -			p9_client_clunk(fid);
> +			p9_fid_put(fid);
>  		return retval;
>  	}
> 
> @@ -619,12 +619,12 @@ int v9fs_vfs_setattr_dotl(struct user_namespace
> *mnt_userns, retval = v9fs_acl_chmod(inode, fid);
>  		if (retval < 0) {
>  			if (use_dentry)
> -				p9_client_clunk(fid);
> +				p9_fid_put(fid);
>  			return retval;
>  		}
>  	}
>  	if (use_dentry)
> -		p9_client_clunk(fid);
> +		p9_fid_put(fid);
> 
>  	return 0;
>  }
> @@ -771,9 +771,9 @@ v9fs_vfs_symlink_dotl(struct user_namespace *mnt_userns,
> struct inode *dir,
> 
>  error:
>  	if (fid)
> -		p9_client_clunk(fid);
> +		p9_fid_put(fid);
> 
> -	p9_client_clunk(dfid);
> +	p9_fid_put(dfid);
>  	return err;
>  }
> 
> @@ -803,14 +803,14 @@ v9fs_vfs_link_dotl(struct dentry *old_dentry, struct
> inode *dir,
> 
>  	oldfid = v9fs_fid_lookup(old_dentry);
>  	if (IS_ERR(oldfid)) {
> -		p9_client_clunk(dfid);
> +		p9_fid_put(dfid);
>  		return PTR_ERR(oldfid);
>  	}
> 
>  	err = p9_client_link(dfid, oldfid, dentry->d_name.name);
> 
> -	p9_client_clunk(dfid);
> -	p9_client_clunk(oldfid);
> +	p9_fid_put(dfid);
> +	p9_fid_put(oldfid);
>  	if (err < 0) {
>  		p9_debug(P9_DEBUG_VFS, "p9_client_link failed %d\n", err);
>  		return err;
> @@ -826,7 +826,7 @@ v9fs_vfs_link_dotl(struct dentry *old_dentry, struct
> inode *dir, return PTR_ERR(fid);
> 
>  		v9fs_refresh_inode_dotl(fid, d_inode(old_dentry));
> -		p9_client_clunk(fid);
> +		p9_fid_put(fid);
>  	}
>  	ihold(d_inode(old_dentry));
>  	d_instantiate(dentry, d_inode(old_dentry));
> @@ -924,9 +924,9 @@ v9fs_vfs_mknod_dotl(struct user_namespace *mnt_userns,
> struct inode *dir, }
>  error:
>  	if (fid)
> -		p9_client_clunk(fid);
> +		p9_fid_put(fid);
>  	v9fs_put_acl(dacl, pacl);
> -	p9_client_clunk(dfid);
> +	p9_fid_put(dfid);
> 
>  	return err;
>  }
> @@ -956,7 +956,7 @@ v9fs_vfs_get_link_dotl(struct dentry *dentry,
>  	if (IS_ERR(fid))
>  		return ERR_CAST(fid);
>  	retval = p9_client_readlink(fid, &target);
> -	p9_client_clunk(fid);
> +	p9_fid_put(fid);
>  	if (retval)
>  		return ERR_PTR(retval);
>  	set_delayed_call(done, kfree_link, target);
> diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c
> index 97e23b4e6982..bf350fad9500 100644
> --- a/fs/9p/vfs_super.c
> +++ b/fs/9p/vfs_super.c
> @@ -190,7 +190,7 @@ static struct dentry *v9fs_mount(struct file_system_type
> *fs_type, int flags, return dget(sb->s_root);
> 
>  clunk_fid:
> -	p9_client_clunk(fid);
> +	p9_fid_put(fid);
>  	v9fs_session_close(v9ses);
>  free_session:
>  	kfree(v9ses);
> @@ -203,7 +203,7 @@ static struct dentry *v9fs_mount(struct file_system_type
> *fs_type, int flags, * attached the fid to dentry so it won't get clunked
>  	 * automatically.
>  	 */
> -	p9_client_clunk(fid);
> +	p9_fid_put(fid);
>  	deactivate_locked_super(sb);
>  	return ERR_PTR(retval);
>  }
> @@ -270,7 +270,7 @@ static int v9fs_statfs(struct dentry *dentry, struct
> kstatfs *buf) }
>  	res = simple_statfs(dentry, buf);
>  done:
> -	p9_client_clunk(fid);
> +	p9_fid_put(fid);
>  	return res;
>  }
> 
> diff --git a/fs/9p/xattr.c b/fs/9p/xattr.c
> index a824441b95a2..1f9298a4bd42 100644
> --- a/fs/9p/xattr.c
> +++ b/fs/9p/xattr.c
> @@ -44,7 +44,7 @@ ssize_t v9fs_fid_xattr_get(struct p9_fid *fid, const char
> *name, if (err)
>  			retval = err;
>  	}
> -	p9_client_clunk(attr_fid);
> +	p9_fid_put(attr_fid);
>  	return retval;
>  }
> 
> @@ -71,7 +71,7 @@ ssize_t v9fs_xattr_get(struct dentry *dentry, const char
> *name, if (IS_ERR(fid))
>  		return PTR_ERR(fid);
>  	ret = v9fs_fid_xattr_get(fid, name, buffer, buffer_size);
> -	p9_client_clunk(fid);
> +	p9_fid_put(fid);
> 
>  	return ret;
>  }
> @@ -98,7 +98,7 @@ int v9fs_xattr_set(struct dentry *dentry, const char
> *name, if (IS_ERR(fid))
>  		return PTR_ERR(fid);
>  	ret = v9fs_fid_xattr_set(fid, name, value, value_len, flags);
> -	p9_client_clunk(fid);
> +	p9_fid_put(fid);
>  	return ret;
>  }
> 
> @@ -128,7 +128,7 @@ int v9fs_fid_xattr_set(struct p9_fid *fid, const char
> *name, retval);
>  	else
>  		p9_client_write(fid, 0, &from, &retval);
> -	err = p9_client_clunk(fid);
> +	err = p9_fid_put(fid);
>  	if (!retval && err)
>  		retval = err;
>  	return retval;
> diff --git a/include/net/9p/client.h b/include/net/9p/client.h
> index ec1d1706f43c..eabb53992350 100644
> --- a/include/net/9p/client.h
> +++ b/include/net/9p/client.h
> @@ -237,6 +237,34 @@ static inline int p9_req_try_get(struct p9_req_t *r)
> 
>  int p9_req_put(struct p9_req_t *r);
> 
> +/* fid reference counting helpers:
> + *  - fids used for any length of time should always be referenced through
> + *    p9_fid_get(), and released with p9_fid_put()
> + *  - v9fs_fid_lookup() or similar will automatically call get for you
> + *    and also require a put
> + *  - the *_fid_add() helpers will stash the fid in the inode,
> + *    at which point it is the responsibility of evict_inode()
> + *    to call the put
> + *  - the last put will automatically send a clunk to the server
> + */
> +static inline struct p9_fid *p9_fid_get(struct p9_fid *fid)
> +{
> +	refcount_inc(&fid->count);
> +
> +	return fid;
> +}
> +
> +static inline int p9_fid_put(struct p9_fid *fid)
> +{
> +	if (!fid || IS_ERR(fid))
> +		return 0;
> +
> +	if (!refcount_dec_and_test(&fid->count))
> +		return 0;
> +
> +	return p9_client_clunk(fid);
> +}
> +
>  void p9_client_cb(struct p9_client *c, struct p9_req_t *req, int status);
> 
>  int p9_parse_header(struct p9_fcall *pdu, int32_t *size, int8_t *type,
> diff --git a/net/9p/client.c b/net/9p/client.c
> index 8bba0d9cf975..f3eb280c7d9d 100644
> --- a/net/9p/client.c
> +++ b/net/9p/client.c
> @@ -1228,7 +1228,7 @@ struct p9_fid *p9_client_walk(struct p9_fid *oldfid,
> uint16_t nwname,
> 
>  clunk_fid:
>  	kfree(wqids);
> -	p9_client_clunk(fid);
> +	p9_fid_put(fid);
>  	fid = NULL;
> 
>  error:
> @@ -1459,15 +1459,6 @@ int p9_client_clunk(struct p9_fid *fid)
>  	struct p9_req_t *req;
>  	int retries = 0;
> 
> -	if (!fid || IS_ERR(fid)) {
> -		pr_warn("%s (%d): Trying to clunk with invalid fid\n",
> -			__func__, task_pid_nr(current));
> -		dump_stack();
> -		return 0;
> -	}
> -	if (!refcount_dec_and_test(&fid->count))
> -		return 0;
> -

I probably would have moved (and that way preserved) that sanity warning to 
p9_fid_put(), but anyway LGTM.

Reviewed-by: Christian Schoenebeck <linux_oss@crudebyte.com>

>  again:
>  	p9_debug(P9_DEBUG_9P, ">>> TCLUNK fid %d (try %d)\n",
>  		 fid->fid, retries);
> @@ -1519,7 +1510,7 @@ int p9_client_remove(struct p9_fid *fid)
>  	p9_tag_remove(clnt, req);
>  error:
>  	if (err == -ERESTARTSYS)
> -		p9_client_clunk(fid);
> +		p9_fid_put(fid);
>  	else
>  		p9_fid_destroy(fid);
>  	return err;
> @@ -2042,7 +2033,7 @@ struct p9_fid *p9_client_xattrwalk(struct p9_fid
> *file_fid, attr_fid->fid, *attr_size);
>  	return attr_fid;
>  clunk_fid:
> -	p9_client_clunk(attr_fid);
> +	p9_fid_put(attr_fid);
>  	attr_fid = NULL;
>  error:
>  	if (attr_fid && attr_fid != file_fid)





^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH v3 04/06] 9p fid refcount: add p9_fid_get/put wrappers
  2022-06-15 13:00         ` Christian Schoenebeck
@ 2022-06-15 13:47           ` Dominique Martinet
  0 siblings, 0 replies; 28+ messages in thread
From: Dominique Martinet @ 2022-06-15 13:47 UTC (permalink / raw)
  To: Christian Schoenebeck
  Cc: Eric Van Hensbergen, Latchesar Ionkov, David S. Miller,
	Jakub Kicinski, Paolo Abeni, Tyler Hicks, v9fs-developer,
	linux-kernel, netdev

Christian Schoenebeck wrote on Wed, Jun 15, 2022 at 03:00:19PM +0200:
> > -	if (!fid || IS_ERR(fid)) {
> > -		pr_warn("%s (%d): Trying to clunk with invalid fid\n",
> > -			__func__, task_pid_nr(current));
> > -		dump_stack();
> > -		return 0;
> > -	}
> > -	if (!refcount_dec_and_test(&fid->count))
> > -		return 0;
> > -
> 
> I probably would have moved (and that way preserved) that sanity warning to 
> p9_fid_put(), but anyway LGTM.

The existing code was careful not to call clunk on error, but I consider
put() calls to be kind of like free in that it's better to make these
easy to call: this allowed patch 6 reworked most fs/ functions getting a
ref to just initialize fids to NULL and inconditionally call
p9_fid_put() before return.

I guess it's just a matter of preference ultimately, but I think that'll
make it a bit easier to not leak fids. Time will tell if this works :)

> Reviewed-by: Christian Schoenebeck <linux_oss@crudebyte.com>

Thanks for this and other reviews!

--
Dominique

^ permalink raw reply	[flat|nested] 28+ messages in thread

end of thread, other threads:[~2022-06-15 13:47 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-06-12  8:53 [PATCH 00/06] fid refcounting improvements and fixes Dominique Martinet
2022-06-12  8:53 ` [PATCH 01/06] 9p: fix fid refcount leak in v9fs_vfs_atomic_open_dotl Dominique Martinet
2022-06-13 16:27   ` Tyler Hicks
2022-06-14 13:17   ` Christian Schoenebeck
2022-06-12  8:53 ` [PATCH 02/06] 9p: fix fid refcount leak in v9fs_vfs_get_link Dominique Martinet
2022-06-13 16:29   ` Tyler Hicks
2022-06-14 13:19   ` Christian Schoenebeck
2022-06-12  8:53 ` [PATCH 03/06] 9p: v9fs_fid_lookup_with_uid fix's fix suggestion Dominique Martinet
2022-06-13 20:08   ` Tyler Hicks
2022-06-12  8:53 ` [PATCH 04/06] 9p fid refcount: add p9_fid_get/put wrappers Dominique Martinet
2022-06-12 23:45   ` [PATCH v2 " Dominique Martinet
2022-06-13 17:31     ` Tyler Hicks
2022-06-14 13:55     ` Christian Schoenebeck
2022-06-14 14:27       ` Dominique Martinet
2022-06-15  3:16       ` [PATCH v3 " Dominique Martinet
2022-06-15 13:00         ` Christian Schoenebeck
2022-06-15 13:47           ` Dominique Martinet
2022-06-12  8:53 ` [PATCH 05/06] 9p fid refcount: add a 9p_fid_ref tracepoint Dominique Martinet
2022-06-12 22:46   ` Steven Rostedt
2022-06-12 23:46     ` [PATCH v2 " Dominique Martinet
2022-06-13  7:00       ` Dominique Martinet
2022-06-12  8:53 ` [PATCH 06/06] 9p fid refcount: cleanup p9_fid_put calls Dominique Martinet
2022-06-13 17:55   ` Tyler Hicks
2022-06-13 19:50     ` Dominique Martinet
2022-06-13 20:12       ` Tyler Hicks
2022-06-13 20:20 ` [PATCH 00/06] fid refcounting improvements and fixes Tyler Hicks
2022-06-13 21:00   ` Dominique Martinet
2022-06-14  1:14     ` Tyler Hicks

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.