Coly Li ee3da1
From 6a468d5990ecd1c2d07dd85f8633bbdd0ba61c40 Mon Sep 17 00:00:00 2001
Coly Li ee3da1
From: Josef Bacik <jbacik@fb.com>
Coly Li ee3da1
Date: Mon, 6 Nov 2017 16:11:58 -0500
Coly Li ee3da1
Subject: [PATCH] nbd: don't start req until after the dead connection logic
Coly Li ee3da1
Git-commit: 6a468d5990ecd1c2d07dd85f8633bbdd0ba61c40
Coly Li ee3da1
Patch-mainline: v4.15-rc1
Coly Li ee3da1
References: bsc#1099918
Coly Li ee3da1
Coly Li ee3da1
We can end up sleeping for a while waiting for the dead timeout, which
Coly Li ee3da1
means we could get the per request timer to fire.  We did handle this
Coly Li ee3da1
case, but if the dead timeout happened right after we submitted we'd
Coly Li ee3da1
either tear down the connection or possibly requeue as we're handling an
Coly Li ee3da1
error and race with the endio which can lead to panics and other
Coly Li ee3da1
hilarity.
Coly Li ee3da1
Coly Li ee3da1
Fixes: 560bc4b39952 ("nbd: handle dead connections")
Coly Li ee3da1
Cc: stable@vger.kernel.org
Coly Li ee3da1
Signed-off-by: Josef Bacik <jbacik@fb.com>
Coly Li ee3da1
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Coly Li ee3da1
Signed-off-by: Coly Li <colyli@suse.de>
Coly Li ee3da1
Coly Li ee3da1
---
Coly Li ee3da1
 drivers/block/nbd.c | 20 +++++++-------------
Coly Li ee3da1
 1 file changed, 7 insertions(+), 13 deletions(-)
Coly Li ee3da1
Coly Li ee3da1
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
Coly Li ee3da1
index b94a735bfe3c..95cab69d9c8b 100644
Coly Li ee3da1
--- a/drivers/block/nbd.c
Coly Li ee3da1
+++ b/drivers/block/nbd.c
Coly Li ee3da1
@@ -289,15 +289,6 @@ static enum blk_eh_timer_return nbd_xmit_timeout(struct request *req,
Coly Li ee3da1
 		cmd->status = BLK_STS_TIMEOUT;
Coly Li ee3da1
 		return BLK_EH_HANDLED;
Coly Li ee3da1
 	}
Coly Li ee3da1
-
Coly Li ee3da1
-	/* If we are waiting on our dead timer then we could get timeout
Coly Li ee3da1
-	 * callbacks for our request.  For this we just want to reset the timer
Coly Li ee3da1
-	 * and let the queue side take care of everything.
Coly Li ee3da1
-	 */
Coly Li ee3da1
-	if (!completion_done(&cmd->send_complete)) {
Coly Li ee3da1
-		nbd_config_put(nbd);
Coly Li ee3da1
-		return BLK_EH_RESET_TIMER;
Coly Li ee3da1
-	}
Coly Li ee3da1
 	config = nbd->config;
Coly Li ee3da1
 
Coly Li ee3da1
 	if (config->num_connections > 1) {
Coly Li ee3da1
@@ -732,6 +723,7 @@ static int nbd_handle_cmd(struct nbd_cmd *cmd, int index)
Coly Li ee3da1
 	if (!refcount_inc_not_zero(&nbd->config_refs)) {
Coly Li ee3da1
 		dev_err_ratelimited(disk_to_dev(nbd->disk),
Coly Li ee3da1
 				    "Socks array is empty\n");
Coly Li ee3da1
+		blk_mq_start_request(req);
Coly Li ee3da1
 		return -EINVAL;
Coly Li ee3da1
 	}
Coly Li ee3da1
 	config = nbd->config;
Coly Li ee3da1
@@ -740,6 +732,7 @@ static int nbd_handle_cmd(struct nbd_cmd *cmd, int index)
Coly Li ee3da1
 		dev_err_ratelimited(disk_to_dev(nbd->disk),
Coly Li ee3da1
 				    "Attempted send on invalid socket\n");
Coly Li ee3da1
 		nbd_config_put(nbd);
Coly Li ee3da1
+		blk_mq_start_request(req);
Coly Li ee3da1
 		return -EINVAL;
Coly Li ee3da1
 	}
Coly Li ee3da1
 	cmd->status = BLK_STS_OK;
Coly Li ee3da1
@@ -763,6 +756,7 @@ static int nbd_handle_cmd(struct nbd_cmd *cmd, int index)
Coly Li ee3da1
 			 */
Coly Li ee3da1
 			sock_shutdown(nbd);
Coly Li ee3da1
 			nbd_config_put(nbd);
Coly Li ee3da1
+			blk_mq_start_request(req);
Coly Li ee3da1
 			return -EIO;
Coly Li ee3da1
 		}
Coly Li ee3da1
 		goto again;
Coly Li ee3da1
@@ -773,6 +767,7 @@ static int nbd_handle_cmd(struct nbd_cmd *cmd, int index)
Coly Li ee3da1
 	 * here so that it gets put _after_ the request that is already on the
Coly Li ee3da1
 	 * dispatch list.
Coly Li ee3da1
 	 */
Coly Li ee3da1
+	blk_mq_start_request(req);
Coly Li ee3da1
 	if (unlikely(nsock->pending && nsock->pending != req)) {
Coly Li ee3da1
 		blk_mq_requeue_request(req, true);
Coly Li ee3da1
 		ret = 0;
Coly Li ee3da1
@@ -785,10 +780,10 @@ static int nbd_handle_cmd(struct nbd_cmd *cmd, int index)
Coly Li ee3da1
 	ret = nbd_send_cmd(nbd, cmd, index);
Coly Li ee3da1
 	if (ret == -EAGAIN) {
Coly Li ee3da1
 		dev_err_ratelimited(disk_to_dev(nbd->disk),
Coly Li ee3da1
-				    "Request send failed trying another connection\n");
Coly Li ee3da1
+				    "Request send failed, requeueing\n");
Coly Li ee3da1
 		nbd_mark_nsock_dead(nbd, nsock, 1);
Coly Li ee3da1
-		mutex_unlock(&nsock->tx_lock);
Coly Li ee3da1
-		goto again;
Coly Li ee3da1
+		blk_mq_requeue_request(req, true);
Coly Li ee3da1
+		ret = 0;
Coly Li ee3da1
 	}
Coly Li ee3da1
 out:
Coly Li ee3da1
 	mutex_unlock(&nsock->tx_lock);
Coly Li ee3da1
@@ -812,7 +807,6 @@ static blk_status_t nbd_queue_rq(struct blk_mq_hw_ctx *hctx,
Coly Li ee3da1
 	 * done sending everything over the wire.
Coly Li ee3da1
 	 */
Coly Li ee3da1
 	init_completion(&cmd->send_complete);
Coly Li ee3da1
-	blk_mq_start_request(bd->rq);
Coly Li ee3da1
 
Coly Li ee3da1
 	/* We can be called directly from the user space process, which means we
Coly Li ee3da1
 	 * could possibly have signals pending so our sendmsg will fail.  In
Coly Li ee3da1
-- 
Coly Li ee3da1
2.17.1
Coly Li ee3da1