Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d453f04e authored by Trond Myklebust's avatar Trond Myklebust Committed by Greg Kroah-Hartman
Browse files

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: default avatarJia-Ju Bai <baijiaju1990@gmail.com>
Fixes: 045d2a6d ("NFSv4.1: Delay callback processing...")
Cc: stable@vger.kernel.org # v4.9+
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@hammerspace.com>
Signed-off-by: default avatarAnna Schumaker <Anna.Schumaker@Netapp.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent c5759d5a
Loading
Loading
Loading
Loading
+10 −4
Original line number Diff line number Diff line
@@ -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;
	}