|
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 |
|