acrn-kernel/fs/nfsd
NeilBrown 51a8f31b93 nfsd: don't take fi_lock in nfsd_break_deleg_cb()
[ Upstream commit 5ea9a7c5fe4149f165f0e3b624fe08df02b6c301 ]

A recent change to check_for_locks() changed it to take ->flc_lock while
holding ->fi_lock.  This creates a lock inversion (reported by lockdep)
because there is a case where ->fi_lock is taken while holding
->flc_lock.

->flc_lock is held across ->fl_lmops callbacks, and
nfsd_break_deleg_cb() is one of those and does take ->fi_lock.  However
it doesn't need to.

Prior to v4.17-rc1~110^2~22 ("nfsd: create a separate lease for each
delegation") nfsd_break_deleg_cb() would walk the ->fi_delegations list
and so needed the lock.  Since then it doesn't walk the list and doesn't
need the lock.

Two actions are performed under the lock.  One is to call
nfsd_break_one_deleg which calls nfsd4_run_cb().  These doesn't act on
the nfs4_file at all, so don't need the lock.

The other is to set ->fi_had_conflict which is in the nfs4_file.
This field is only ever set here (except when initialised to false)
so there is no possible problem will multiple threads racing when
setting it.

The field is tested twice in nfs4_set_delegation().  The first test does
not hold a lock and is documented as an opportunistic optimisation, so
it doesn't impose any need to hold ->fi_lock while setting
->fi_had_conflict.

The second test in nfs4_set_delegation() *is* make under ->fi_lock, so
removing the locking when ->fi_had_conflict is set could make a change.
The change could only be interesting if ->fi_had_conflict tested as
false even though nfsd_break_one_deleg() ran before ->fi_lock was
unlocked.  i.e. while hash_delegation_locked() was running.
As hash_delegation_lock() doesn't interact in any way with nfs4_run_cb()
there can be no importance to this interaction.

So this patch removes the locking from nfsd_break_one_deleg() and moves
the final test on ->fi_had_conflict out of the locked region to make it
clear that locking isn't important to the test.  It is still tested
*after* vfs_setlease() has succeeded.  This might be significant and as
vfs_setlease() takes ->flc_lock, and nfsd_break_one_deleg() is called
under ->flc_lock this "after" is a true ordering provided by a spinlock.

Fixes: edcf9725150e ("nfsd: fix RELEASE_LOCKOWNER")
Signed-off-by: NeilBrown <neilb@suse.de>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2024-02-23 09:12:50 +01:00
..
Kconfig
Makefile
acl.h
auth.c
auth.h
blocklayout.c nfsd: call op_release, even when op_func returns an error 2023-04-13 16:55:21 +02:00
blocklayoutxdr.c NFSD: da_addr_body field missing in some GETDEVICEINFO replies 2023-09-13 09:42:49 +02:00
blocklayoutxdr.h
cache.h NFSD: Fix checksum mismatches in the duplicate reply cache 2023-12-03 07:32:10 +01:00
current_stateid.h
export.c
export.h
fault_inject.c
filecache.c nfsd: don't fsync nfsd_files on last close 2023-03-10 09:33:25 +01:00
filecache.h nfsd: fix handling of cached open files in nfsd4_open codepath 2023-01-18 11:58:26 +01:00
flexfilelayout.c
flexfilelayoutxdr.c NFSD: da_addr_body field missing in some GETDEVICEINFO replies 2023-09-13 09:42:49 +02:00
flexfilelayoutxdr.h
idmap.h
lockd.c
netns.h NFSD: add shrinker to reap courtesy clients on low memory condition 2022-09-26 14:02:41 -04:00
nfs2acl.c NFSD: Finish converting the NFSv2 GETACL result encoder 2022-12-31 13:31:58 +01:00
nfs3acl.c NFSD: Finish converting the NFSv3 GETACL result encoder 2022-12-31 13:31:58 +01:00
nfs3proc.c NFSD: Add an NFSD_FILE_GC flag to enable nfsd_file garbage collection 2023-01-18 11:58:25 +01:00
nfs3xdr.c NFSD: Clean up WRITE arg decoders 2022-09-26 14:02:47 -04:00
nfs4acl.c
nfs4callback.c NFSD: callback request does not use correct credential for AUTH_SYS 2023-04-13 16:55:23 +02:00
nfs4idmap.c
nfs4layouts.c nfsd: fix race to check ls_layouts 2023-03-10 09:33:24 +01:00
nfs4proc.c nfsd: fix change_info in NFSv4 RENAME replies 2023-09-23 11:11:11 +02:00
nfs4recover.c struct file-related stuff 2022-10-06 17:13:18 -07:00
nfs4state.c nfsd: don't take fi_lock in nfsd_break_deleg_cb() 2024-02-23 09:12:50 +01:00
nfs4xdr.c NFSD: da_addr_body field missing in some GETDEVICEINFO replies 2023-09-13 09:42:49 +02:00
nfscache.c NFSD: Fix checksum mismatches in the duplicate reply cache 2023-12-03 07:32:10 +01:00
nfsctl.c Revert "nfsd: call nfsd_last_thread() before final nfsd_put()" 2024-01-15 18:54:50 +01:00
nfsd.h Revert "nfsd: separate nfsd_last_thread() from nfsd_put()" 2024-01-15 18:54:50 +01:00
nfsfh.c nfsd: ensure we always call fh_verify_error tracepoint 2022-10-13 12:12:37 -04:00
nfsfh.h
nfsproc.c NFSD: Refactor common code out of dirlist helpers 2022-09-26 14:02:47 -04:00
nfssvc.c Revert "nfsd: separate nfsd_last_thread() from nfsd_put()" 2024-01-15 18:54:50 +01:00
nfsxdr.c NFSD: Clean up WRITE arg decoders 2022-09-26 14:02:47 -04:00
pnfs.h
state.h nfsd: make nfsd4_run_cb a bool return function 2022-09-26 14:50:57 -04:00
stats.c nfsd: use DEFINE_PROC_SHOW_ATTRIBUTE to define nfsd_proc_ops 2022-09-26 14:02:49 -04:00
stats.h
trace.c
trace.h nfsd: don't fsync nfsd_files on last close 2023-03-10 09:33:25 +01:00
vfs.c nfsd: lock_rename() needs both directories to live on the same fs 2023-11-02 09:35:25 +01:00
vfs.h NFSD: Pass the target nfsd_file to nfsd_commit() 2023-01-18 11:58:25 +01:00
xdr.h
xdr3.h
xdr4.h NFSD: enhance inter-server copy cleanup 2023-03-10 09:33:24 +01:00
xdr4cb.h