diff options
author | Trond Myklebust <trondmy@gmail.com> | 2018-08-15 00:55:56 +0300 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2018-09-09 20:55:59 +0300 |
commit | d453f04e813a9ded568b0bbb918909698c8bfed0 (patch) | |
tree | da7f8cc2f2a9c284d0feba4561871cf17f1141c9 /fs | |
parent | c5759d5a7e6a00ffd8a342cde8f33340891bd095 (diff) | |
download | linux-d453f04e813a9ded568b0bbb918909698c8bfed0.tar.xz |
NFSv4: Fix a sleep in atomic context in nfs4_callback_sequence()
commit 8618289c46556fd4dd259a1af02ccc448032f48d upstream.
We must drop the lock before we can sleep in referring_call_exists().
Reported-by: Jia-Ju Bai <baijiaju1990@gmail.com>
Fixes: 045d2a6d076a ("NFSv4.1: Delay callback processing...")
Cc: stable@vger.kernel.org # v4.9+
Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/nfs/callback_proc.c | 14 |
1 files changed, 10 insertions, 4 deletions
diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c index 516b2248cafe..2c3f398995f6 100644 --- a/fs/nfs/callback_proc.c +++ b/fs/nfs/callback_proc.c @@ -433,11 +433,14 @@ validate_seqid(const struct nfs4_slot_table *tbl, const struct nfs4_slot *slot, * a match. If the slot is in use and the sequence numbers match, the * client is still waiting for a response to the original request. */ -static bool referring_call_exists(struct nfs_client *clp, +static int referring_call_exists(struct nfs_client *clp, uint32_t nrclists, - struct referring_call_list *rclists) + struct referring_call_list *rclists, + spinlock_t *lock) + __releases(lock) + __acquires(lock) { - bool status = 0; + int status = 0; int i, j; struct nfs4_session *session; struct nfs4_slot_table *tbl; @@ -460,8 +463,10 @@ static bool referring_call_exists(struct nfs_client *clp, for (j = 0; j < rclist->rcl_nrefcalls; j++) { ref = &rclist->rcl_refcalls[j]; + spin_unlock(lock); status = nfs4_slot_wait_on_seqid(tbl, ref->rc_slotid, ref->rc_sequenceid, HZ >> 1) < 0; + spin_lock(lock); if (status) goto out; } @@ -538,7 +543,8 @@ __be32 nfs4_callback_sequence(void *argp, void *resp, * related callback was received before the response to the original * call. */ - if (referring_call_exists(clp, args->csa_nrclists, args->csa_rclists)) { + if (referring_call_exists(clp, args->csa_nrclists, args->csa_rclists, + &tbl->slot_tbl_lock) < 0) { status = htonl(NFS4ERR_DELAY); goto out_unlock; } |