[PATCH] nfs/localio: fix nfsd_file ref leak on nfs_local_doio() init failure

Jeff Layton <[email protected]>
Newsgroups gmane.linux.nfs,gmane.linux.kernel
Message-ID <[email protected]>
Two early return paths in nfs_local_doio() fail to release the localio
(nfsd_file) reference passed in by the caller:

- When hdr->args.count is zero, the function returns 0 without calling
  nfs_local_file_put().

- When nfs_local_iocb_init() fails (e.g. -ENOMEM from allocation or
  -EOPNOTSUPP if the file lacks read_iter/write_iter), the function
  returns the error without releasing localio or completing the hdr
  lifecycle.

A leaked nfsd_file pins the associated net namespace reference,
blocking network namespace teardown, and holds a reference on the
exported filesystem, preventing unmount.

Fix the zero-count path by adding the missing nfs_local_file_put()
call. Fix the iocb init failure path by jumping to a new cleanup label
that releases localio, sets hdr->task.tk_status, and calls
nfs_local_hdr_release() -- matching the existing error handling pattern
for the post-iocb error path.

Fixes: e77c464c31b3 ("nfs/nfsd: add "local io" support")
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Jeff Layton <[email protected]>
---
I had originally sent this as part of a pile of nfsd patches, but Chuck
pointed out that this was client side.
---
 fs/nfs/localio.c | 16 +++++++++++++---
 1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/fs/nfs/localio.c b/fs/nfs/localio.c
index e55c5977fcc3..63cf6e2cc745 100644
--- a/fs/nfs/localio.c
+++ b/fs/nfs/localio.c
@@ -970,12 +970,16 @@ int nfs_local_doio(struct nfs_client *clp, struct nfsd_file *localio,
 	struct nfs_local_kiocb *iocb;
 	int status = 0;
 
-	if (!hdr->args.count)
+	if (!hdr->args.count) {
+		nfs_local_file_put(localio);
 		return 0;
+	}
 
 	iocb = nfs_local_iocb_init(hdr, localio);
-	if (IS_ERR(iocb))
-		return PTR_ERR(iocb);
+	if (IS_ERR(iocb)) {
+		status = PTR_ERR(iocb);
+		goto out_put_localio;
+	}
 
 	switch (hdr->rw_mode) {
 	case FMODE_READ:
@@ -996,6 +1000,12 @@ int nfs_local_doio(struct nfs_client *clp, struct nfsd_file *localio,
 		nfs_local_hdr_release(hdr, call_ops);
 	}
 	return status;
+
+out_put_localio:
+	nfs_local_file_put(localio);
+	hdr->task.tk_status = status;
+	nfs_local_hdr_release(hdr, call_ops);
+	return status;
 }
 
 static void

---
base-commit: ec039126b7fac4e3af35ebccaa7c6f9b6875ba81
change-id: 20260611-nfs-localio-1edd961f0b6e

Best regards,
-- 
Jeff Layton <[email protected]>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.