Skip to content

Commit 8618289

Browse files
trondmyamschuma-ntap
authored andcommitted
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: 045d2a6 ("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>
1 parent d0fbb1d commit 8618289

File tree

1 file changed

+10
-4
lines changed

1 file changed

+10
-4
lines changed

fs/nfs/callback_proc.c

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -442,11 +442,14 @@ validate_seqid(const struct nfs4_slot_table *tbl, const struct nfs4_slot *slot,
442442
* a match. If the slot is in use and the sequence numbers match, the
443443
* client is still waiting for a response to the original request.
444444
*/
445-
static bool referring_call_exists(struct nfs_client *clp,
445+
static int referring_call_exists(struct nfs_client *clp,
446446
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)
448451
{
449-
bool status = false;
452+
int status = 0;
450453
int i, j;
451454
struct nfs4_session *session;
452455
struct nfs4_slot_table *tbl;
@@ -469,8 +472,10 @@ static bool referring_call_exists(struct nfs_client *clp,
469472

470473
for (j = 0; j < rclist->rcl_nrefcalls; j++) {
471474
ref = &rclist->rcl_refcalls[j];
475+
spin_unlock(lock);
472476
status = nfs4_slot_wait_on_seqid(tbl, ref->rc_slotid,
473477
ref->rc_sequenceid, HZ >> 1) < 0;
478+
spin_lock(lock);
474479
if (status)
475480
goto out;
476481
}
@@ -547,7 +552,8 @@ __be32 nfs4_callback_sequence(void *argp, void *resp,
547552
* related callback was received before the response to the original
548553
* call.
549554
*/
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) {
551557
status = htonl(NFS4ERR_DELAY);
552558
goto out_unlock;
553559
}

0 commit comments

Comments
 (0)