FAILED: patch "[PATCH] pNFS: Fix a hang in nfs4_evict_inode()" failed to apply to 5.4-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 5.4-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-5.4.y
git checkout FETCH_HEAD
git cherry-pick -x f63955721a8020e979b99cc417dcb6da3106aa24
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2023102135-blurt-entree-54ec@gregkh' --subject-prefix 'PATCH 5.4.y' HEAD^..
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From f63955721a8020e979b99cc417dcb6da3106aa24 Mon Sep 17 00:00:00 2001
From: Trond Myklebust <[email protected]>
Date: Sun, 8 Oct 2023 14:20:19 -0400
Subject: [PATCH] pNFS: Fix a hang in nfs4_evict_inode()
We are not allowed to call pnfs_mark_matching_lsegs_return() without also holding a reference to the layout header, since doing so could lead to the reference count going to zero when we call pnfs_layout_remove_lseg(). This again can lead to a hang when we get to nfs4_evict_inode() and are unable to clear the layout pointer.
pnfs_layout_return_unused_byserver() is guilty of this behaviour, and has been seen to trigger the refcount warning prior to a hang.
fs/nfs/pnfs.c +23 -10
@@ -2634,31 +2634,44 @@ pnfs_should_return_unused_layout(struct pnfs_layout_hdr *lo,return mode ==0 ; } -static int -pnfs_layout_return_unused_byserver (struct nfs_server *server,void *data) +static int pnfs_layout_return_unused_byserver (struct nfs_server *server, +void *data) {const struct pnfs_layout_range *range = data; +const struct cred *cred;struct pnfs_layout_hdr *lo;struct inode *inode; +nfs4_stateid stateid; +enum pnfs_iomode iomode; + restart:rcu_read_lock ();list_for_each_entry_rcu (lo, &server->layouts, plh_layouts) { -if (!pnfs_layout_can_be_returned (lo) || + inode = lo->plh_inode; +if (!inode || !pnfs_layout_can_be_returned (lo) ||test_bit (NFS_LAYOUT_RETURN_REQUESTED , &lo->plh_flags))continue ; - inode = lo->plh_inode;spin_lock (&inode->i_lock); -if (!pnfs_should_return_unused_layout (lo, range)) { +if (!lo->plh_inode || + !pnfs_should_return_unused_layout (lo, range)) {spin_unlock (&inode->i_lock);continue ; } +pnfs_get_layout_hdr (lo); +pnfs_set_plh_return_info (lo, range->iomode,0 ); +if (pnfs_mark_matching_lsegs_return (lo, &lo->plh_return_segs, + range,0 ) !=0 || + !pnfs_prepare_layoutreturn (lo, &stateid, &cred, &iomode)) { +spin_unlock (&inode->i_lock); +rcu_read_unlock (); +pnfs_put_layout_hdr (lo); +cond_resched (); + goto restart; + }spin_unlock (&inode->i_lock); - inode =pnfs_grab_inode_layout_hdr (lo); -if (!inode) -continue ;rcu_read_unlock (); -pnfs_mark_layout_for_return (inode, range); -iput (inode); +pnfs_send_layoutreturn (lo, &stateid, &cred, iomode, false); +pnfs_put_layout_hdr (lo);cond_resched (); goto restart; }