]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
drop nfsd patch
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 29 Jan 2024 15:15:39 +0000 (07:15 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 29 Jan 2024 15:15:39 +0000 (07:15 -0800)
queue-5.10/nfsd-fix-release_lockowner.patch [deleted file]
queue-5.10/series
queue-5.15/nfsd-fix-release_lockowner.patch [deleted file]
queue-5.15/series
queue-5.4/nfsd-fix-release_lockowner.patch [deleted file]
queue-5.4/series
queue-6.1/nfsd-fix-release_lockowner.patch [deleted file]
queue-6.1/series

diff --git a/queue-5.10/nfsd-fix-release_lockowner.patch b/queue-5.10/nfsd-fix-release_lockowner.patch
deleted file mode 100644 (file)
index 093879e..0000000
+++ /dev/null
@@ -1,149 +0,0 @@
-From cb99b2854e2c04fd668e5ea9fec4625f970bc3c5 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Mon, 22 Jan 2024 14:58:16 +1100
-Subject: nfsd: fix RELEASE_LOCKOWNER
-
-From: NeilBrown <neilb@suse.de>
-
-[ 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 <neilb@suse.de>
-Reviewed-by: Jeff Layton <jlayton@kernel.org>
-Cc: stable@vger.kernel.org # v6.2+
-Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- 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
-
index 07a9af9404db70461dc2504066633035fcdde872..b489a24df08fddb6757770633239ec65c00216b2 100644 (file)
@@ -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 (file)
index 6938f30..0000000
+++ /dev/null
@@ -1,149 +0,0 @@
-From b99447c0e88afdb26e8907c0904190f6064f4f1b Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Mon, 22 Jan 2024 14:58:16 +1100
-Subject: nfsd: fix RELEASE_LOCKOWNER
-
-From: NeilBrown <neilb@suse.de>
-
-[ 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 <neilb@suse.de>
-Reviewed-by: Jeff Layton <jlayton@kernel.org>
-Cc: stable@vger.kernel.org # v6.2+
-Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- 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
-
index 829e7fd43e2d3a77673665dcc712abcbb99ef5a6..6a68a5ab3072ccbb3eaad01b8721f04da1953645 100644 (file)
@@ -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 (file)
index 6ef9a94..0000000
+++ /dev/null
@@ -1,149 +0,0 @@
-From 9dc318f8e50bb1c547f2b480a1162c645eb7e9bc Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Mon, 22 Jan 2024 14:58:16 +1100
-Subject: nfsd: fix RELEASE_LOCKOWNER
-
-From: NeilBrown <neilb@suse.de>
-
-[ 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 <neilb@suse.de>
-Reviewed-by: Jeff Layton <jlayton@kernel.org>
-Cc: stable@vger.kernel.org # v6.2+
-Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- 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
-
index c6ea6093acc4026c21e730ab38eee1641c939bc2..04b4e15ebd9a169294054a299fdd279d89585bab 100644 (file)
@@ -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 (file)
index 92ab464..0000000
+++ /dev/null
@@ -1,149 +0,0 @@
-From 2073110fe8693c6bc6a3cfc5f198fe444b5c2397 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Mon, 22 Jan 2024 14:58:16 +1100
-Subject: nfsd: fix RELEASE_LOCKOWNER
-
-From: NeilBrown <neilb@suse.de>
-
-[ 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 <neilb@suse.de>
-Reviewed-by: Jeff Layton <jlayton@kernel.org>
-Cc: stable@vger.kernel.org # v6.2+
-Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- 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
-
index 245975e973bf9dc61dd2e67a8364ec399aadea84..fd33014ddc890dc918ce0345961db0e95480c353 100644 (file)
@@ -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