aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/callback_proc.c
diff options
context:
space:
mode:
authorTrond Myklebust <trondmy@gmail.com>2018-08-14 17:55:56 -0400
committerAnna Schumaker <Anna.Schumaker@Netapp.com>2018-08-15 12:05:15 -0400
commit8618289c46556fd4dd259a1af02ccc448032f48d (patch)
treedae02612130410f169459c9a56e81dcbab2e7f6b /fs/nfs/callback_proc.c
parentd0fbb1d8a194c0ec0180c1d073ad709e45503a43 (diff)
NFSv4: Fix a sleep in atomic context in nfs4_callback_sequence()
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>
Diffstat (limited to 'fs/nfs/callback_proc.c')
-rw-r--r--fs/nfs/callback_proc.c14
1 files changed, 10 insertions, 4 deletions
diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c
index cd733649646b..fa515d5ea5ba 100644
--- a/fs/nfs/callback_proc.c
+++ b/fs/nfs/callback_proc.c
@@ -442,11 +442,14 @@ validate_seqid(const struct nfs4_slot_table *tbl, const struct nfs4_slot *slot,
442 * a match. If the slot is in use and the sequence numbers match, the 442 * a match. If the slot is in use and the sequence numbers match, the
443 * client is still waiting for a response to the original request. 443 * client is still waiting for a response to the original request.
444 */ 444 */
445static bool referring_call_exists(struct nfs_client *clp, 445static int referring_call_exists(struct nfs_client *clp,
446 uint32_t nrclists, 446 uint32_t nrclists,
447 struct referring_call_list *rclists) 447 struct referring_call_list *rclists,
448 spinlock_t *lock)
449 __releases(lock)
450 __acquires(lock)
448{ 451{
449 bool status = false; 452 int status = 0;
450 int i, j; 453 int i, j;
451 struct nfs4_session *session; 454 struct nfs4_session *session;
452 struct nfs4_slot_table *tbl; 455 struct nfs4_slot_table *tbl;
@@ -469,8 +472,10 @@ static bool referring_call_exists(struct nfs_client *clp,
469 472
470 for (j = 0; j < rclist->rcl_nrefcalls; j++) { 473 for (j = 0; j < rclist->rcl_nrefcalls; j++) {
471 ref = &rclist->rcl_refcalls[j]; 474 ref = &rclist->rcl_refcalls[j];
475 spin_unlock(lock);
472 status = nfs4_slot_wait_on_seqid(tbl, ref->rc_slotid, 476 status = nfs4_slot_wait_on_seqid(tbl, ref->rc_slotid,
473 ref->rc_sequenceid, HZ >> 1) < 0; 477 ref->rc_sequenceid, HZ >> 1) < 0;
478 spin_lock(lock);
474 if (status) 479 if (status)
475 goto out; 480 goto out;
476 } 481 }
@@ -547,7 +552,8 @@ __be32 nfs4_callback_sequence(void *argp, void *resp,
547 * related callback was received before the response to the original 552 * related callback was received before the response to the original
548 * call. 553 * call.
549 */ 554 */
550 if (referring_call_exists(clp, args->csa_nrclists, args->csa_rclists)) { 555 if (referring_call_exists(clp, args->csa_nrclists, args->csa_rclists,
556 &tbl->slot_tbl_lock) < 0) {
551 status = htonl(NFS4ERR_DELAY); 557 status = htonl(NFS4ERR_DELAY);
552 goto out_unlock; 558 goto out_unlock;
553 } 559 }