2021-01-25 02:25:05

by Trond Myklebust

[permalink] [raw]
Subject: [PATCH 1/4] pNFS/NFSv4: Fix a layout segment leak in pnfs_layout_process()

From: Trond Myklebust <[email protected]>

If the server returns a new stateid that does not match the one in our
cache, then pnfs_layout_process() will leak the layout segments returned
by pnfs_mark_layout_stateid_invalid().

Fixes: 9888d837f3cf ("pNFS: Force a retry of LAYOUTGET if the stateid doesn't match our cache")
Signed-off-by: Trond Myklebust <[email protected]>
---
fs/nfs/pnfs.c | 1 +
1 file changed, 1 insertion(+)

diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index 4f274f21c4ab..e68e6f8cb407 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -2417,6 +2417,7 @@ pnfs_layout_process(struct nfs4_layoutget *lgp)
spin_unlock(&ino->i_lock);
lseg->pls_layout = lo;
NFS_SERVER(ino)->pnfs_curr_ld->free_lseg(lseg);
+ pnfs_free_lseg_list(&free_me);
return ERR_PTR(-EAGAIN);
}

--
2.29.2


2021-01-25 02:26:32

by Trond Myklebust

[permalink] [raw]
Subject: [PATCH 2/4] pNFS/NFSv4: Try to return invalid layout in pnfs_layout_process()

From: Trond Myklebust <[email protected]>

If the server returns a new stateid that does not match the one in our
cache, then try to return the one we hold instead of just invalidating
it on the client side. This ensures that both client and server will
agree that the stateid is invalid.

Signed-off-by: Trond Myklebust <[email protected]>
---
fs/nfs/pnfs.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index e68e6f8cb407..d6262289cf4a 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -2398,7 +2398,13 @@ pnfs_layout_process(struct nfs4_layoutget *lgp)
* We got an entirely new state ID. Mark all segments for the
* inode invalid, and retry the layoutget
*/
- pnfs_mark_layout_stateid_invalid(lo, &free_me);
+ struct pnfs_layout_range range = {
+ .iomode = IOMODE_ANY,
+ .length = NFS4_MAX_UINT64,
+ };
+ pnfs_set_plh_return_info(lo, IOMODE_ANY, 0);
+ pnfs_mark_matching_lsegs_return(lo, &lo->plh_return_segs,
+ &range, 0);
goto out_forget;
}

@@ -2417,7 +2423,6 @@ pnfs_layout_process(struct nfs4_layoutget *lgp)
spin_unlock(&ino->i_lock);
lseg->pls_layout = lo;
NFS_SERVER(ino)->pnfs_curr_ld->free_lseg(lseg);
- pnfs_free_lseg_list(&free_me);
return ERR_PTR(-EAGAIN);
}

--
2.29.2