nbd: fix zero cmd timeout handling v2
This fixes a regression added in 4.9 with commit:
commit 0eadf37afc
Author: Josef Bacik <jbacik@fb.com>
Date: Thu Sep 8 12:33:40 2016 -0700
nbd: allow block mq to deal with timeouts
where before the patch userspace would set the timeout to 0 to disable
it. With the above patch, a zero timeout tells the block layer to use
the default value of 30 seconds. For setups where commands can take a
long time or experience transient issues like network disruptions this
then results in IO errors being sent to the application.
To fix this, the patch still uses the common block layer timeout
framework, but if zero is set, nbd just logs a message and then resets
the timer when it expires.
Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Mike Christie <mchristi@redhat.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
parent
887e975c41
commit
2da22da573
|
@ -121,6 +121,7 @@ struct nbd_cmd {
|
||||||
struct mutex lock;
|
struct mutex lock;
|
||||||
int index;
|
int index;
|
||||||
int cookie;
|
int cookie;
|
||||||
|
int retries;
|
||||||
blk_status_t status;
|
blk_status_t status;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
u32 cmd_cookie;
|
u32 cmd_cookie;
|
||||||
|
@ -407,10 +408,25 @@ static enum blk_eh_timer_return nbd_xmit_timeout(struct request *req,
|
||||||
nbd_config_put(nbd);
|
nbd_config_put(nbd);
|
||||||
return BLK_EH_DONE;
|
return BLK_EH_DONE;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
dev_err_ratelimited(nbd_to_dev(nbd),
|
|
||||||
"Connection timed out\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!nbd->tag_set.timeout) {
|
||||||
|
/*
|
||||||
|
* Userspace sets timeout=0 to disable socket disconnection,
|
||||||
|
* so just warn and reset the timer.
|
||||||
|
*/
|
||||||
|
cmd->retries++;
|
||||||
|
dev_info(nbd_to_dev(nbd), "Possible stuck request %p: control (%s@%llu,%uB). Runtime %u seconds\n",
|
||||||
|
req, nbdcmd_to_ascii(req_to_nbd_cmd_type(req)),
|
||||||
|
(unsigned long long)blk_rq_pos(req) << 9,
|
||||||
|
blk_rq_bytes(req), (req->timeout / HZ) * cmd->retries);
|
||||||
|
|
||||||
|
mutex_unlock(&cmd->lock);
|
||||||
|
nbd_config_put(nbd);
|
||||||
|
return BLK_EH_RESET_TIMER;
|
||||||
|
}
|
||||||
|
|
||||||
|
dev_err_ratelimited(nbd_to_dev(nbd), "Connection timed out\n");
|
||||||
set_bit(NBD_TIMEDOUT, &config->runtime_flags);
|
set_bit(NBD_TIMEDOUT, &config->runtime_flags);
|
||||||
cmd->status = BLK_STS_IOERR;
|
cmd->status = BLK_STS_IOERR;
|
||||||
mutex_unlock(&cmd->lock);
|
mutex_unlock(&cmd->lock);
|
||||||
|
@ -531,6 +547,7 @@ static int nbd_send_cmd(struct nbd_device *nbd, struct nbd_cmd *cmd, int index)
|
||||||
}
|
}
|
||||||
cmd->index = index;
|
cmd->index = index;
|
||||||
cmd->cookie = nsock->cookie;
|
cmd->cookie = nsock->cookie;
|
||||||
|
cmd->retries = 0;
|
||||||
request.type = htonl(type | nbd_cmd_flags);
|
request.type = htonl(type | nbd_cmd_flags);
|
||||||
if (type != NBD_CMD_FLUSH) {
|
if (type != NBD_CMD_FLUSH) {
|
||||||
request.from = cpu_to_be64((u64)blk_rq_pos(req) << 9);
|
request.from = cpu_to_be64((u64)blk_rq_pos(req) << 9);
|
||||||
|
@ -1254,7 +1271,8 @@ static bool nbd_is_valid_blksize(unsigned long blksize)
|
||||||
static void nbd_set_cmd_timeout(struct nbd_device *nbd, u64 timeout)
|
static void nbd_set_cmd_timeout(struct nbd_device *nbd, u64 timeout)
|
||||||
{
|
{
|
||||||
nbd->tag_set.timeout = timeout * HZ;
|
nbd->tag_set.timeout = timeout * HZ;
|
||||||
blk_queue_rq_timeout(nbd->disk->queue, timeout * HZ);
|
if (timeout)
|
||||||
|
blk_queue_rq_timeout(nbd->disk->queue, timeout * HZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Must be called with config_lock held */
|
/* Must be called with config_lock held */
|
||||||
|
@ -1287,8 +1305,7 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
|
||||||
nbd_size_set(nbd, config->blksize, arg);
|
nbd_size_set(nbd, config->blksize, arg);
|
||||||
return 0;
|
return 0;
|
||||||
case NBD_SET_TIMEOUT:
|
case NBD_SET_TIMEOUT:
|
||||||
if (arg)
|
nbd_set_cmd_timeout(nbd, arg);
|
||||||
nbd_set_cmd_timeout(nbd, arg);
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case NBD_SET_FLAGS:
|
case NBD_SET_FLAGS:
|
||||||
|
|
Loading…
Reference in New Issue