From: Benjamin Coddington <ben.coddington@hammerspace.com>
To: Trond Myklebust <trondmy@kernel.org>,
Anna Schumaker <anna@kernel.org>,
Mike Snitzer <snitzer@kernel.org>
Cc: linux-nfs@vger.kernel.org
Subject: [PATCH v2 3/6] pNFS: don't leak layout segments when prepare_layoutcommit fails
Date: Fri, 30 Oct 2026 11:30:19 -0400 [thread overview]
Message-ID: <352ff35c2e51bf8fb025ebd88bbec3c4cb7152ea.1793373378.git.bcodding@hammerspace.com> (raw)
In-Reply-To: <cover.1793373378.git.bcodding@hammerspace.com>
From: Benjamin Coddington <bcodding@hammerspace.com>
pnfs_list_write_lseg() clears NFS_LSEG_LAYOUTCOMMIT on each segment that
needs a LAYOUTCOMMIT and moves the reference that flag held onto
data->lseg_list, to be put when the LAYOUTCOMMIT completes. If
->prepare_layoutcommit() fails with anything but -ENOSPC, no LAYOUTCOMMIT
is sent and data is freed with the segments still on that list, so their
references are never put. The segments and their layout header are then
never freed.
Before freeing data, give each segment's reference back to
NFS_LSEG_LAYOUTCOMMIT if the layout stateid is still valid and the flag
hasn't been set again, so that the next LAYOUTCOMMIT, which the error path
has already rescheduled, takes it. That keeps a segment invalidated
meanwhile pinned until its LAYOUTCOMMIT is sent, as it would have been.
Otherwise put the reference with pnfs_list_write_lseg_done(): if the
layout stateid was invalidated, every other LAYOUTCOMMIT reference has
already been dropped, and if the flag was set again, it holds a reference
of its own.
Once the segments can be freed, the layout header can be too, so only
reschedule the LAYOUTCOMMIT if the layout stateid is still valid.
pnfs_mark_layout_stateid_invalid() clears NFS_INO_LAYOUTCOMMIT, and
setting it again would leave the next pnfs_layoutcommit_inode() to
dereference a NULL nfsi->layout.
Fixes: 5f919c9f10c1 ("pnfs: allow splicing pre-encoded pages into the layoutcommit args")
Signed-off-by: Benjamin Coddington <bcodding@hammerspace.com>
---
fs/nfs/pnfs.c | 28 +++++++++++++++++++++++-----
1 file changed, 23 insertions(+), 5 deletions(-)
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index 6d391985fb21..393de479da3b 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -3634,6 +3634,17 @@ static void pnfs_list_write_lseg(struct inode *inode, struct list_head *listp)
}
}
+static void pnfs_list_write_lseg_undo(struct list_head *listp)
+{
+ struct pnfs_layout_segment *lseg, *tmp;
+
+ list_for_each_entry_safe(lseg, tmp, listp, pls_lc_list) {
+ if (pnfs_layout_is_valid(lseg->pls_layout) &&
+ !test_and_set_bit(NFS_LSEG_LAYOUTCOMMIT, &lseg->pls_flags))
+ list_del_init(&lseg->pls_lc_list);
+ }
+}
+
static void pnfs_list_write_lseg_done(struct inode *inode, struct list_head *listp)
{
struct pnfs_layout_segment *lseg, *tmp;
@@ -3763,11 +3774,18 @@ pnfs_layoutcommit_inode(struct inode *inode, bool sync)
if (status != -ENOSPC)
put_cred(data->cred);
spin_lock(&inode->i_lock);
- set_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags);
- if (end_pos > nfsi->layout->plh_lwb)
- nfsi->layout->plh_lwb = end_pos;
- if (status != -ENOSPC)
- goto out_unlock;
+ if (pnfs_layout_is_valid(nfsi->layout)) {
+ set_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags);
+ if (end_pos > nfsi->layout->plh_lwb)
+ nfsi->layout->plh_lwb = end_pos;
+ }
+ if (status != -ENOSPC) {
+ pnfs_list_write_lseg_undo(&data->lseg_list);
+ spin_unlock(&inode->i_lock);
+ pnfs_list_write_lseg_done(inode, &data->lseg_list);
+ kfree(data);
+ goto out;
+ }
spin_unlock(&inode->i_lock);
mark_as_dirty = true;
}
--
2.53.0
next prev parent reply other threads:[~2026-10-30 15:30 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-30 15:30 [PATCH v2 0/6] pNFS: don't reply NOMATCHING to a layout recall with I/O in flight Benjamin Coddington
2026-10-30 15:30 ` [PATCH v2 1/6] NFSv4: add a tracepoint for bulk CB_LAYOUTRECALL replies Benjamin Coddington
2026-10-30 15:30 ` [PATCH v2 2/6] pNFS: clear NFS_LAYOUT_BULK_RECALL when an invalid layout's last segment is freed Benjamin Coddington
2026-10-30 15:30 ` Benjamin Coddington [this message]
2026-10-30 15:30 ` [PATCH v2 4/6] pNFS: don't send _NOMATCHING_LAYOUT if still doing IO on a layout Benjamin Coddington
2026-10-30 15:30 ` [PATCH v2 5/6] pNFS: answer a file recall with NFS4ERR_DELAY while I/O drains Benjamin Coddington
2026-10-30 15:30 ` [PATCH v2 6/6] pNFS/flexfiles: write through the MDS while a recalled layout drains Benjamin Coddington
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=352ff35c2e51bf8fb025ebd88bbec3c4cb7152ea.1793373378.git.bcodding@hammerspace.com \
--to=ben.coddington@hammerspace.com \
--cc=anna@kernel.org \
--cc=linux-nfs@vger.kernel.org \
--cc=snitzer@kernel.org \
--cc=trondmy@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox