Introduce a dedicated client flag NBD_RT_WAIT_ON_TIMEOUT to reset timer in nbd_xmit_timer instead of depending on tag_set.timeout == 0. So that the timeout value could be configured by the user to whatever they like instead of the default 30s. A smaller timeout value allow us to detect if a new socket is reconfigured in a shorter time. Thus the io could be requeued more quickly. In multiple sockets configuration, the user could also disable dropping the socket in timeout by setting this flag. The tag_set.timeout == 0 setting still works like before. Reviewed-by: Josef Bacik <josef@xxxxxxxxxxxxxx> Signed-off-by: Hou Pu <houpu@xxxxxxxxxxxxx> --- drivers/block/nbd.c | 27 ++++++++++++++++++++++----- include/uapi/linux/nbd.h | 4 ++++ 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 538e9dcf5bf2..2d32e31b7b96 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -80,6 +80,7 @@ struct link_dead_args { #define NBD_RT_BOUND 5 #define NBD_RT_DESTROY_ON_DISCONNECT 6 #define NBD_RT_DISCONNECT_ON_CLOSE 7 +#define NBD_RT_WAIT_ON_TIMEOUT 8 #define NBD_DESTROY_ON_DISCONNECT 0 #define NBD_DISCONNECT_REQUESTED 1 @@ -378,6 +379,16 @@ static u32 req_to_nbd_cmd_type(struct request *req) } } +static inline bool wait_on_timeout(struct nbd_device *nbd, + struct nbd_config *config) +{ + if (test_bit(NBD_RT_WAIT_ON_TIMEOUT, &config->runtime_flags) || + (config->num_connections == 1 && nbd->tag_set.timeout == 0)) + return true; + else + return false; +} + static enum blk_eh_timer_return nbd_xmit_timeout(struct request *req, bool reserved) { @@ -400,8 +411,7 @@ static enum blk_eh_timer_return nbd_xmit_timeout(struct request *req, nbd->tag_set.timeout) goto error_out; - if (config->num_connections > 1 || - (config->num_connections == 1 && nbd->tag_set.timeout)) { + if (!wait_on_timeout(nbd, config)) { dev_err_ratelimited(nbd_to_dev(nbd), "Connection timed out, retrying (%d/%d alive)\n", atomic_read(&config->live_connections), @@ -432,9 +442,7 @@ static enum blk_eh_timer_return nbd_xmit_timeout(struct request *req, nbd_config_put(nbd); return BLK_EH_DONE; } - } - - if (!nbd->tag_set.timeout) { + } else { /* * Userspace sets timeout=0 to disable socket disconnection, * so just warn and reset the timer. @@ -1956,6 +1964,9 @@ static int nbd_genl_connect(struct sk_buff *skb, struct genl_info *info) set_bit(NBD_RT_DISCONNECT_ON_CLOSE, &config->runtime_flags); } + if (flags & NBD_CFLAG_WAIT_ON_TIMEOUT) + set_bit(NBD_RT_WAIT_ON_TIMEOUT, + &config->runtime_flags); } if (info->attrs[NBD_ATTR_SOCKETS]) { @@ -2139,6 +2150,12 @@ static int nbd_genl_reconfigure(struct sk_buff *skb, struct genl_info *info) clear_bit(NBD_RT_DISCONNECT_ON_CLOSE, &config->runtime_flags); } + if (flags & NBD_CFLAG_WAIT_ON_TIMEOUT) + set_bit(NBD_RT_WAIT_ON_TIMEOUT, + &config->runtime_flags); + else + clear_bit(NBD_RT_WAIT_ON_TIMEOUT, + &config->runtime_flags); } if (info->attrs[NBD_ATTR_SOCKETS]) { diff --git a/include/uapi/linux/nbd.h b/include/uapi/linux/nbd.h index 20d6cc91435d..cc3abfb92de5 100644 --- a/include/uapi/linux/nbd.h +++ b/include/uapi/linux/nbd.h @@ -56,6 +56,10 @@ enum { #define NBD_CFLAG_DISCONNECT_ON_CLOSE (1 << 1) /* disconnect the nbd device on * close by last opener. */ +#define NBD_CFLAG_WAIT_ON_TIMEOUT (1 << 2) /* do not fallback to other sockets + * in io timeout, instead just reset + * timer and wait. + */ /* userspace doesn't need the nbd_device structure */ -- 2.11.0