From 6052a3d400c0fadd3ac1ae423f555e13a87f7338 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 29 Jan 2024 07:15:39 -0800 Subject: [PATCH] drop nfsd patch --- queue-5.10/nfsd-fix-release_lockowner.patch | 149 -------------------- queue-5.10/series | 1 - queue-5.15/nfsd-fix-release_lockowner.patch | 149 -------------------- queue-5.15/series | 1 - queue-5.4/nfsd-fix-release_lockowner.patch | 149 -------------------- queue-5.4/series | 1 - queue-6.1/nfsd-fix-release_lockowner.patch | 149 -------------------- queue-6.1/series | 1 - 8 files changed, 600 deletions(-) delete mode 100644 queue-5.10/nfsd-fix-release_lockowner.patch delete mode 100644 queue-5.15/nfsd-fix-release_lockowner.patch delete mode 100644 queue-5.4/nfsd-fix-release_lockowner.patch delete mode 100644 queue-6.1/nfsd-fix-release_lockowner.patch diff --git a/queue-5.10/nfsd-fix-release_lockowner.patch b/queue-5.10/nfsd-fix-release_lockowner.patch deleted file mode 100644 index 093879ef2d3..00000000000 --- a/queue-5.10/nfsd-fix-release_lockowner.patch +++ /dev/null @@ -1,149 +0,0 @@ -From cb99b2854e2c04fd668e5ea9fec4625f970bc3c5 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Mon, 22 Jan 2024 14:58:16 +1100 -Subject: nfsd: fix RELEASE_LOCKOWNER - -From: NeilBrown - -[ Upstream commit edcf9725150e42beeca42d085149f4c88fa97afd ] - -The test on so_count in nfsd4_release_lockowner() is nonsense and -harmful. Revert to using check_for_locks(), changing that to not sleep. - -First: harmful. -As is documented in the kdoc comment for nfsd4_release_lockowner(), the -test on so_count can transiently return a false positive resulting in a -return of NFS4ERR_LOCKS_HELD when in fact no locks are held. This is -clearly a protocol violation and with the Linux NFS client it can cause -incorrect behaviour. - -If RELEASE_LOCKOWNER is sent while some other thread is still -processing a LOCK request which failed because, at the time that request -was received, the given owner held a conflicting lock, then the nfsd -thread processing that LOCK request can hold a reference (conflock) to -the lock owner that causes nfsd4_release_lockowner() to return an -incorrect error. - -The Linux NFS client ignores that NFS4ERR_LOCKS_HELD error because it -never sends NFS4_RELEASE_LOCKOWNER without first releasing any locks, so -it knows that the error is impossible. It assumes the lock owner was in -fact released so it feels free to use the same lock owner identifier in -some later locking request. - -When it does reuse a lock owner identifier for which a previous RELEASE -failed, it will naturally use a lock_seqid of zero. However the server, -which didn't release the lock owner, will expect a larger lock_seqid and -so will respond with NFS4ERR_BAD_SEQID. - -So clearly it is harmful to allow a false positive, which testing -so_count allows. - -The test is nonsense because ... well... it doesn't mean anything. - -so_count is the sum of three different counts. -1/ the set of states listed on so_stateids -2/ the set of active vfs locks owned by any of those states -3/ various transient counts such as for conflicting locks. - -When it is tested against '2' it is clear that one of these is the -transient reference obtained by find_lockowner_str_locked(). It is not -clear what the other one is expected to be. - -In practice, the count is often 2 because there is precisely one state -on so_stateids. If there were more, this would fail. - -In my testing I see two circumstances when RELEASE_LOCKOWNER is called. -In one case, CLOSE is called before RELEASE_LOCKOWNER. That results in -all the lock states being removed, and so the lockowner being discarded -(it is removed when there are no more references which usually happens -when the lock state is discarded). When nfsd4_release_lockowner() finds -that the lock owner doesn't exist, it returns success. - -The other case shows an so_count of '2' and precisely one state listed -in so_stateid. It appears that the Linux client uses a separate lock -owner for each file resulting in one lock state per lock owner, so this -test on '2' is safe. For another client it might not be safe. - -So this patch changes check_for_locks() to use the (newish) -find_any_file_locked() so that it doesn't take a reference on the -nfs4_file and so never calls nfsd_file_put(), and so never sleeps. With -this check is it safe to restore the use of check_for_locks() rather -than testing so_count against the mysterious '2'. - -Fixes: ce3c4ad7f4ce ("NFSD: Fix possible sleep during nfsd4_release_lockowner()") -Signed-off-by: NeilBrown -Reviewed-by: Jeff Layton -Cc: stable@vger.kernel.org # v6.2+ -Signed-off-by: Chuck Lever -Signed-off-by: Sasha Levin ---- - fs/nfsd/nfs4state.c | 26 +++++++++++++++----------- - 1 file changed, 15 insertions(+), 11 deletions(-) - -diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c -index b6480be7b5e6..16b073c63798 100644 ---- a/fs/nfsd/nfs4state.c -+++ b/fs/nfsd/nfs4state.c -@@ -7080,14 +7080,16 @@ check_for_locks(struct nfs4_file *fp, struct nfs4_lockowner *lowner) - { - struct file_lock *fl; - int status = false; -- struct nfsd_file *nf = find_any_file(fp); -+ struct nfsd_file *nf; - struct inode *inode; - struct file_lock_context *flctx; - -+ spin_lock(&fp->fi_lock); -+ nf = find_any_file_locked(fp); - if (!nf) { - /* Any valid lock stateid should have some sort of access */ - WARN_ON_ONCE(1); -- return status; -+ goto out; - } - - inode = locks_inode(nf->nf_file); -@@ -7103,7 +7105,8 @@ check_for_locks(struct nfs4_file *fp, struct nfs4_lockowner *lowner) - } - spin_unlock(&flctx->flc_lock); - } -- nfsd_file_put(nf); -+out: -+ spin_unlock(&fp->fi_lock); - return status; - } - -@@ -7113,10 +7116,8 @@ check_for_locks(struct nfs4_file *fp, struct nfs4_lockowner *lowner) - * @cstate: NFSv4 COMPOUND state - * @u: RELEASE_LOCKOWNER arguments - * -- * The lockowner's so_count is bumped when a lock record is added -- * or when copying a conflicting lock. The latter case is brief, -- * but can lead to fleeting false positives when looking for -- * locks-in-use. -+ * Check if theree are any locks still held and if not - free the lockowner -+ * and any lock state that is owned. - * - * Return values: - * %nfs_ok: lockowner released or not found -@@ -7152,10 +7153,13 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp, - spin_unlock(&clp->cl_lock); - return nfs_ok; - } -- if (atomic_read(&lo->lo_owner.so_count) != 2) { -- spin_unlock(&clp->cl_lock); -- nfs4_put_stateowner(&lo->lo_owner); -- return nfserr_locks_held; -+ -+ list_for_each_entry(stp, &lo->lo_owner.so_stateids, st_perstateowner) { -+ if (check_for_locks(stp->st_stid.sc_file, lo)) { -+ spin_unlock(&clp->cl_lock); -+ nfs4_put_stateowner(&lo->lo_owner); -+ return nfserr_locks_held; -+ } - } - unhash_lockowner_locked(lo); - while (!list_empty(&lo->lo_owner.so_stateids)) { --- -2.43.0 - diff --git a/queue-5.10/series b/queue-5.10/series index 07a9af9404d..b489a24df08 100644 --- a/queue-5.10/series +++ b/queue-5.10/series @@ -90,7 +90,6 @@ btrfs-remove-err-variable-from-btrfs_delete_subvolum.patch btrfs-avoid-copying-btrfs_root_subvol_dead-flag-to-s.patch nfsd-modernize-nfsd4_release_lockowner.patch nfsd-add-documenting-comment-for-nfsd4_release_locko.patch -nfsd-fix-release_lockowner.patch drm-panel-simple-add-missing-bus-flags-for-tianma-tm.patch drm-exynos-fix-accidental-on-stack-copy-of-exynos_dr.patch drm-exynos-gsc-minor-fix-for-loop-iteration-in-gsc_r.patch diff --git a/queue-5.15/nfsd-fix-release_lockowner.patch b/queue-5.15/nfsd-fix-release_lockowner.patch deleted file mode 100644 index 6938f300626..00000000000 --- a/queue-5.15/nfsd-fix-release_lockowner.patch +++ /dev/null @@ -1,149 +0,0 @@ -From b99447c0e88afdb26e8907c0904190f6064f4f1b Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Mon, 22 Jan 2024 14:58:16 +1100 -Subject: nfsd: fix RELEASE_LOCKOWNER - -From: NeilBrown - -[ Upstream commit edcf9725150e42beeca42d085149f4c88fa97afd ] - -The test on so_count in nfsd4_release_lockowner() is nonsense and -harmful. Revert to using check_for_locks(), changing that to not sleep. - -First: harmful. -As is documented in the kdoc comment for nfsd4_release_lockowner(), the -test on so_count can transiently return a false positive resulting in a -return of NFS4ERR_LOCKS_HELD when in fact no locks are held. This is -clearly a protocol violation and with the Linux NFS client it can cause -incorrect behaviour. - -If RELEASE_LOCKOWNER is sent while some other thread is still -processing a LOCK request which failed because, at the time that request -was received, the given owner held a conflicting lock, then the nfsd -thread processing that LOCK request can hold a reference (conflock) to -the lock owner that causes nfsd4_release_lockowner() to return an -incorrect error. - -The Linux NFS client ignores that NFS4ERR_LOCKS_HELD error because it -never sends NFS4_RELEASE_LOCKOWNER without first releasing any locks, so -it knows that the error is impossible. It assumes the lock owner was in -fact released so it feels free to use the same lock owner identifier in -some later locking request. - -When it does reuse a lock owner identifier for which a previous RELEASE -failed, it will naturally use a lock_seqid of zero. However the server, -which didn't release the lock owner, will expect a larger lock_seqid and -so will respond with NFS4ERR_BAD_SEQID. - -So clearly it is harmful to allow a false positive, which testing -so_count allows. - -The test is nonsense because ... well... it doesn't mean anything. - -so_count is the sum of three different counts. -1/ the set of states listed on so_stateids -2/ the set of active vfs locks owned by any of those states -3/ various transient counts such as for conflicting locks. - -When it is tested against '2' it is clear that one of these is the -transient reference obtained by find_lockowner_str_locked(). It is not -clear what the other one is expected to be. - -In practice, the count is often 2 because there is precisely one state -on so_stateids. If there were more, this would fail. - -In my testing I see two circumstances when RELEASE_LOCKOWNER is called. -In one case, CLOSE is called before RELEASE_LOCKOWNER. That results in -all the lock states being removed, and so the lockowner being discarded -(it is removed when there are no more references which usually happens -when the lock state is discarded). When nfsd4_release_lockowner() finds -that the lock owner doesn't exist, it returns success. - -The other case shows an so_count of '2' and precisely one state listed -in so_stateid. It appears that the Linux client uses a separate lock -owner for each file resulting in one lock state per lock owner, so this -test on '2' is safe. For another client it might not be safe. - -So this patch changes check_for_locks() to use the (newish) -find_any_file_locked() so that it doesn't take a reference on the -nfs4_file and so never calls nfsd_file_put(), and so never sleeps. With -this check is it safe to restore the use of check_for_locks() rather -than testing so_count against the mysterious '2'. - -Fixes: ce3c4ad7f4ce ("NFSD: Fix possible sleep during nfsd4_release_lockowner()") -Signed-off-by: NeilBrown -Reviewed-by: Jeff Layton -Cc: stable@vger.kernel.org # v6.2+ -Signed-off-by: Chuck Lever -Signed-off-by: Sasha Levin ---- - fs/nfsd/nfs4state.c | 26 +++++++++++++++----------- - 1 file changed, 15 insertions(+), 11 deletions(-) - -diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c -index f8533299db1c..07ea35803629 100644 ---- a/fs/nfsd/nfs4state.c -+++ b/fs/nfsd/nfs4state.c -@@ -7257,14 +7257,16 @@ check_for_locks(struct nfs4_file *fp, struct nfs4_lockowner *lowner) - { - struct file_lock *fl; - int status = false; -- struct nfsd_file *nf = find_any_file(fp); -+ struct nfsd_file *nf; - struct inode *inode; - struct file_lock_context *flctx; - -+ spin_lock(&fp->fi_lock); -+ nf = find_any_file_locked(fp); - if (!nf) { - /* Any valid lock stateid should have some sort of access */ - WARN_ON_ONCE(1); -- return status; -+ goto out; - } - - inode = locks_inode(nf->nf_file); -@@ -7280,7 +7282,8 @@ check_for_locks(struct nfs4_file *fp, struct nfs4_lockowner *lowner) - } - spin_unlock(&flctx->flc_lock); - } -- nfsd_file_put(nf); -+out: -+ spin_unlock(&fp->fi_lock); - return status; - } - -@@ -7290,10 +7293,8 @@ check_for_locks(struct nfs4_file *fp, struct nfs4_lockowner *lowner) - * @cstate: NFSv4 COMPOUND state - * @u: RELEASE_LOCKOWNER arguments - * -- * The lockowner's so_count is bumped when a lock record is added -- * or when copying a conflicting lock. The latter case is brief, -- * but can lead to fleeting false positives when looking for -- * locks-in-use. -+ * Check if theree are any locks still held and if not - free the lockowner -+ * and any lock state that is owned. - * - * Return values: - * %nfs_ok: lockowner released or not found -@@ -7329,10 +7330,13 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp, - spin_unlock(&clp->cl_lock); - return nfs_ok; - } -- if (atomic_read(&lo->lo_owner.so_count) != 2) { -- spin_unlock(&clp->cl_lock); -- nfs4_put_stateowner(&lo->lo_owner); -- return nfserr_locks_held; -+ -+ list_for_each_entry(stp, &lo->lo_owner.so_stateids, st_perstateowner) { -+ if (check_for_locks(stp->st_stid.sc_file, lo)) { -+ spin_unlock(&clp->cl_lock); -+ nfs4_put_stateowner(&lo->lo_owner); -+ return nfserr_locks_held; -+ } - } - unhash_lockowner_locked(lo); - while (!list_empty(&lo->lo_owner.so_stateids)) { --- -2.43.0 - diff --git a/queue-5.15/series b/queue-5.15/series index 829e7fd43e2..6a68a5ab307 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -116,7 +116,6 @@ btrfs-add-definition-for-extent_tree_v2.patch btrfs-don-t-abort-filesystem-when-attempting-to-snap.patch nfsd-modernize-nfsd4_release_lockowner.patch nfsd-add-documenting-comment-for-nfsd4_release_locko.patch -nfsd-fix-release_lockowner.patch ksmbd-fix-global-oob-in-ksmbd_nl_policy.patch cpufreq-intel_pstate-drop-redundant-intel_pstate_get.patch cpufreq-intel_pstate-refine-computation-of-p-state-f.patch diff --git a/queue-5.4/nfsd-fix-release_lockowner.patch b/queue-5.4/nfsd-fix-release_lockowner.patch deleted file mode 100644 index 6ef9a949475..00000000000 --- a/queue-5.4/nfsd-fix-release_lockowner.patch +++ /dev/null @@ -1,149 +0,0 @@ -From 9dc318f8e50bb1c547f2b480a1162c645eb7e9bc Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Mon, 22 Jan 2024 14:58:16 +1100 -Subject: nfsd: fix RELEASE_LOCKOWNER - -From: NeilBrown - -[ Upstream commit edcf9725150e42beeca42d085149f4c88fa97afd ] - -The test on so_count in nfsd4_release_lockowner() is nonsense and -harmful. Revert to using check_for_locks(), changing that to not sleep. - -First: harmful. -As is documented in the kdoc comment for nfsd4_release_lockowner(), the -test on so_count can transiently return a false positive resulting in a -return of NFS4ERR_LOCKS_HELD when in fact no locks are held. This is -clearly a protocol violation and with the Linux NFS client it can cause -incorrect behaviour. - -If RELEASE_LOCKOWNER is sent while some other thread is still -processing a LOCK request which failed because, at the time that request -was received, the given owner held a conflicting lock, then the nfsd -thread processing that LOCK request can hold a reference (conflock) to -the lock owner that causes nfsd4_release_lockowner() to return an -incorrect error. - -The Linux NFS client ignores that NFS4ERR_LOCKS_HELD error because it -never sends NFS4_RELEASE_LOCKOWNER without first releasing any locks, so -it knows that the error is impossible. It assumes the lock owner was in -fact released so it feels free to use the same lock owner identifier in -some later locking request. - -When it does reuse a lock owner identifier for which a previous RELEASE -failed, it will naturally use a lock_seqid of zero. However the server, -which didn't release the lock owner, will expect a larger lock_seqid and -so will respond with NFS4ERR_BAD_SEQID. - -So clearly it is harmful to allow a false positive, which testing -so_count allows. - -The test is nonsense because ... well... it doesn't mean anything. - -so_count is the sum of three different counts. -1/ the set of states listed on so_stateids -2/ the set of active vfs locks owned by any of those states -3/ various transient counts such as for conflicting locks. - -When it is tested against '2' it is clear that one of these is the -transient reference obtained by find_lockowner_str_locked(). It is not -clear what the other one is expected to be. - -In practice, the count is often 2 because there is precisely one state -on so_stateids. If there were more, this would fail. - -In my testing I see two circumstances when RELEASE_LOCKOWNER is called. -In one case, CLOSE is called before RELEASE_LOCKOWNER. That results in -all the lock states being removed, and so the lockowner being discarded -(it is removed when there are no more references which usually happens -when the lock state is discarded). When nfsd4_release_lockowner() finds -that the lock owner doesn't exist, it returns success. - -The other case shows an so_count of '2' and precisely one state listed -in so_stateid. It appears that the Linux client uses a separate lock -owner for each file resulting in one lock state per lock owner, so this -test on '2' is safe. For another client it might not be safe. - -So this patch changes check_for_locks() to use the (newish) -find_any_file_locked() so that it doesn't take a reference on the -nfs4_file and so never calls nfsd_file_put(), and so never sleeps. With -this check is it safe to restore the use of check_for_locks() rather -than testing so_count against the mysterious '2'. - -Fixes: ce3c4ad7f4ce ("NFSD: Fix possible sleep during nfsd4_release_lockowner()") -Signed-off-by: NeilBrown -Reviewed-by: Jeff Layton -Cc: stable@vger.kernel.org # v6.2+ -Signed-off-by: Chuck Lever -Signed-off-by: Sasha Levin ---- - fs/nfsd/nfs4state.c | 26 +++++++++++++++----------- - 1 file changed, 15 insertions(+), 11 deletions(-) - -diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c -index 0dfc45d37658..bca22325083c 100644 ---- a/fs/nfsd/nfs4state.c -+++ b/fs/nfsd/nfs4state.c -@@ -6840,14 +6840,16 @@ check_for_locks(struct nfs4_file *fp, struct nfs4_lockowner *lowner) - { - struct file_lock *fl; - int status = false; -- struct nfsd_file *nf = find_any_file(fp); -+ struct nfsd_file *nf; - struct inode *inode; - struct file_lock_context *flctx; - -+ spin_lock(&fp->fi_lock); -+ nf = find_any_file_locked(fp); - if (!nf) { - /* Any valid lock stateid should have some sort of access */ - WARN_ON_ONCE(1); -- return status; -+ goto out; - } - - inode = locks_inode(nf->nf_file); -@@ -6863,7 +6865,8 @@ check_for_locks(struct nfs4_file *fp, struct nfs4_lockowner *lowner) - } - spin_unlock(&flctx->flc_lock); - } -- nfsd_file_put(nf); -+out: -+ spin_unlock(&fp->fi_lock); - return status; - } - -@@ -6873,10 +6876,8 @@ check_for_locks(struct nfs4_file *fp, struct nfs4_lockowner *lowner) - * @cstate: NFSv4 COMPOUND state - * @u: RELEASE_LOCKOWNER arguments - * -- * The lockowner's so_count is bumped when a lock record is added -- * or when copying a conflicting lock. The latter case is brief, -- * but can lead to fleeting false positives when looking for -- * locks-in-use. -+ * Check if theree are any locks still held and if not - free the lockowner -+ * and any lock state that is owned. - * - * Return values: - * %nfs_ok: lockowner released or not found -@@ -6912,10 +6913,13 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp, - spin_unlock(&clp->cl_lock); - return nfs_ok; - } -- if (atomic_read(&lo->lo_owner.so_count) != 2) { -- spin_unlock(&clp->cl_lock); -- nfs4_put_stateowner(&lo->lo_owner); -- return nfserr_locks_held; -+ -+ list_for_each_entry(stp, &lo->lo_owner.so_stateids, st_perstateowner) { -+ if (check_for_locks(stp->st_stid.sc_file, lo)) { -+ spin_unlock(&clp->cl_lock); -+ nfs4_put_stateowner(&lo->lo_owner); -+ return nfserr_locks_held; -+ } - } - unhash_lockowner_locked(lo); - while (!list_empty(&lo->lo_owner.so_stateids)) { --- -2.43.0 - diff --git a/queue-5.4/series b/queue-5.4/series index c6ea6093acc..04b4e15ebd9 100644 --- a/queue-5.4/series +++ b/queue-5.4/series @@ -51,7 +51,6 @@ drm-bridge-nxp-ptn3460-fix-i2c_master_send-error-checking.patch drm-bridge-nxp-ptn3460-simplify-some-error-checking.patch nfsd-modernize-nfsd4_release_lockowner.patch nfsd-add-documenting-comment-for-nfsd4_release_locko.patch -nfsd-fix-release_lockowner.patch drm-exynos-fix-accidental-on-stack-copy-of-exynos_dr.patch drm-exynos-gsc-minor-fix-for-loop-iteration-in-gsc_r.patch gpio-eic-sprd-clear-interrupt-after-set-the-interrup.patch diff --git a/queue-6.1/nfsd-fix-release_lockowner.patch b/queue-6.1/nfsd-fix-release_lockowner.patch deleted file mode 100644 index 92ab4646455..00000000000 --- a/queue-6.1/nfsd-fix-release_lockowner.patch +++ /dev/null @@ -1,149 +0,0 @@ -From 2073110fe8693c6bc6a3cfc5f198fe444b5c2397 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Mon, 22 Jan 2024 14:58:16 +1100 -Subject: nfsd: fix RELEASE_LOCKOWNER - -From: NeilBrown - -[ Upstream commit edcf9725150e42beeca42d085149f4c88fa97afd ] - -The test on so_count in nfsd4_release_lockowner() is nonsense and -harmful. Revert to using check_for_locks(), changing that to not sleep. - -First: harmful. -As is documented in the kdoc comment for nfsd4_release_lockowner(), the -test on so_count can transiently return a false positive resulting in a -return of NFS4ERR_LOCKS_HELD when in fact no locks are held. This is -clearly a protocol violation and with the Linux NFS client it can cause -incorrect behaviour. - -If RELEASE_LOCKOWNER is sent while some other thread is still -processing a LOCK request which failed because, at the time that request -was received, the given owner held a conflicting lock, then the nfsd -thread processing that LOCK request can hold a reference (conflock) to -the lock owner that causes nfsd4_release_lockowner() to return an -incorrect error. - -The Linux NFS client ignores that NFS4ERR_LOCKS_HELD error because it -never sends NFS4_RELEASE_LOCKOWNER without first releasing any locks, so -it knows that the error is impossible. It assumes the lock owner was in -fact released so it feels free to use the same lock owner identifier in -some later locking request. - -When it does reuse a lock owner identifier for which a previous RELEASE -failed, it will naturally use a lock_seqid of zero. However the server, -which didn't release the lock owner, will expect a larger lock_seqid and -so will respond with NFS4ERR_BAD_SEQID. - -So clearly it is harmful to allow a false positive, which testing -so_count allows. - -The test is nonsense because ... well... it doesn't mean anything. - -so_count is the sum of three different counts. -1/ the set of states listed on so_stateids -2/ the set of active vfs locks owned by any of those states -3/ various transient counts such as for conflicting locks. - -When it is tested against '2' it is clear that one of these is the -transient reference obtained by find_lockowner_str_locked(). It is not -clear what the other one is expected to be. - -In practice, the count is often 2 because there is precisely one state -on so_stateids. If there were more, this would fail. - -In my testing I see two circumstances when RELEASE_LOCKOWNER is called. -In one case, CLOSE is called before RELEASE_LOCKOWNER. That results in -all the lock states being removed, and so the lockowner being discarded -(it is removed when there are no more references which usually happens -when the lock state is discarded). When nfsd4_release_lockowner() finds -that the lock owner doesn't exist, it returns success. - -The other case shows an so_count of '2' and precisely one state listed -in so_stateid. It appears that the Linux client uses a separate lock -owner for each file resulting in one lock state per lock owner, so this -test on '2' is safe. For another client it might not be safe. - -So this patch changes check_for_locks() to use the (newish) -find_any_file_locked() so that it doesn't take a reference on the -nfs4_file and so never calls nfsd_file_put(), and so never sleeps. With -this check is it safe to restore the use of check_for_locks() rather -than testing so_count against the mysterious '2'. - -Fixes: ce3c4ad7f4ce ("NFSD: Fix possible sleep during nfsd4_release_lockowner()") -Signed-off-by: NeilBrown -Reviewed-by: Jeff Layton -Cc: stable@vger.kernel.org # v6.2+ -Signed-off-by: Chuck Lever -Signed-off-by: Sasha Levin ---- - fs/nfsd/nfs4state.c | 26 +++++++++++++++----------- - 1 file changed, 15 insertions(+), 11 deletions(-) - -diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c -index faecdbfa01a2..0443fe4e29e1 100644 ---- a/fs/nfsd/nfs4state.c -+++ b/fs/nfsd/nfs4state.c -@@ -7736,14 +7736,16 @@ check_for_locks(struct nfs4_file *fp, struct nfs4_lockowner *lowner) - { - struct file_lock *fl; - int status = false; -- struct nfsd_file *nf = find_any_file(fp); -+ struct nfsd_file *nf; - struct inode *inode; - struct file_lock_context *flctx; - -+ spin_lock(&fp->fi_lock); -+ nf = find_any_file_locked(fp); - if (!nf) { - /* Any valid lock stateid should have some sort of access */ - WARN_ON_ONCE(1); -- return status; -+ goto out; - } - - inode = locks_inode(nf->nf_file); -@@ -7759,7 +7761,8 @@ check_for_locks(struct nfs4_file *fp, struct nfs4_lockowner *lowner) - } - spin_unlock(&flctx->flc_lock); - } -- nfsd_file_put(nf); -+out: -+ spin_unlock(&fp->fi_lock); - return status; - } - -@@ -7769,10 +7772,8 @@ check_for_locks(struct nfs4_file *fp, struct nfs4_lockowner *lowner) - * @cstate: NFSv4 COMPOUND state - * @u: RELEASE_LOCKOWNER arguments - * -- * The lockowner's so_count is bumped when a lock record is added -- * or when copying a conflicting lock. The latter case is brief, -- * but can lead to fleeting false positives when looking for -- * locks-in-use. -+ * Check if theree are any locks still held and if not - free the lockowner -+ * and any lock state that is owned. - * - * Return values: - * %nfs_ok: lockowner released or not found -@@ -7808,10 +7809,13 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp, - spin_unlock(&clp->cl_lock); - return nfs_ok; - } -- if (atomic_read(&lo->lo_owner.so_count) != 2) { -- spin_unlock(&clp->cl_lock); -- nfs4_put_stateowner(&lo->lo_owner); -- return nfserr_locks_held; -+ -+ list_for_each_entry(stp, &lo->lo_owner.so_stateids, st_perstateowner) { -+ if (check_for_locks(stp->st_stid.sc_file, lo)) { -+ spin_unlock(&clp->cl_lock); -+ nfs4_put_stateowner(&lo->lo_owner); -+ return nfserr_locks_held; -+ } - } - unhash_lockowner_locked(lo); - while (!list_empty(&lo->lo_owner.so_stateids)) { --- -2.43.0 - diff --git a/queue-6.1/series b/queue-6.1/series index 245975e973b..fd33014ddc8 100644 --- a/queue-6.1/series +++ b/queue-6.1/series @@ -161,7 +161,6 @@ serial-sc16is7xx-use-port-lock-wrappers.patch serial-sc16is7xx-fix-unconditional-activation-of-thr.patch btrfs-zoned-factor-out-prepare_allocation_zoned.patch btrfs-zoned-optimize-hint-byte-for-zoned-allocator.patch -nfsd-fix-release_lockowner.patch drm-panel-edp-drm-panel-edp-fix-auo-b116xak01-name-a.patch revert-powerpc-64s-increase-default-stack-size-to-32.patch drm-bridge-parade-ps8640-wait-for-hpd-when-doing-an-.patch -- 2.47.3