[PATCH OLK-6.6 0/9] nbd: boost nbd setup
Drop local patchset, using mainline pathset to do the same thing. Yang Erkun (9): Revert "nbd: remove queue freeze in nbd_add_socket" Revert "nbd: remove redundant num_connections boundary checks" Revert "nbd: replace socks pointer array with xarray" Revert "nbd: simplify find_fallback() by removing redundant logic" nbd: disallow NBD_SET_SOCK on an active device nbd: remove queue freeze in nbd_add_socket nbd: factor out a nbd_genl_foreach_sock nbd: remove queue freeze for newly created nbd from netlink path nbd: add pre_defined_connections module parameter for pre-created devices drivers/block/nbd.c | 350 ++++++++++++++++++++++---------------------- 1 file changed, 176 insertions(+), 174 deletions(-) -- 2.52.0
hulk inclusion category: feature bugzilla: https://atomgit.com/openeuler/kernel/issues/9153 ---------------------------------------- This reverts commit d5ceebf6b957ff30c0fcafe97b2b2a334c944e0c. Revert self-developed patchset, using mainline patchset. Signed-off-by: Yang Erkun <yangerkun@huawei.com> --- drivers/block/nbd.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index be2191f7c4c1..621f42fb87cb 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -1185,6 +1185,12 @@ static int nbd_add_socket(struct nbd_device *nbd, unsigned long arg, if (!sock) return err; + /* + * We need to make sure we don't get any errant requests while we're + * reallocating the ->socks array. + */ + blk_mq_freeze_queue(nbd->disk->queue); + if (!netlink && !nbd->task_setup && !test_bit(NBD_RT_BOUND, &config->runtime_flags)) nbd->task_setup = current; @@ -1220,10 +1226,12 @@ static int nbd_add_socket(struct nbd_device *nbd, unsigned long arg, config->num_connections++; atomic_inc(&config->live_connections); + blk_mq_unfreeze_queue(nbd->disk->queue); return 0; put_socket: + blk_mq_unfreeze_queue(nbd->disk->queue); sockfd_put(sock); return err; } -- 2.52.0
hulk inclusion category: feature bugzilla: https://atomgit.com/openeuler/kernel/issues/9153 ---------------------------------------- This reverts commit daf28c1b005f61ff365062ee901d591b45346c1a. Revert self-developed patchset, using mainline patchset. Signed-off-by: Yang Erkun <yangerkun@huawei.com> --- drivers/block/nbd.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 621f42fb87cb..25885a2c7e70 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -989,7 +989,7 @@ static int find_fallback(struct nbd_device *nbd, int index) goto no_fallback; fallback = nsock->fallback_index; - if (fallback >= 0) { + if (fallback >= 0 && fallback < config->num_connections) { fallback_nsock = xa_load(&config->socks, fallback); if (fallback_nsock && !fallback_nsock->dead) return fallback; @@ -1044,6 +1044,12 @@ static blk_status_t nbd_handle_cmd(struct nbd_cmd *cmd, int index) return BLK_STS_IOERR; } + if (index >= config->num_connections) { + dev_err_ratelimited(disk_to_dev(nbd->disk), + "Attempted send on invalid socket\n"); + nbd_config_put(nbd); + return BLK_STS_IOERR; + } cmd->status = BLK_STS_OK; again: nsock = xa_load(&config->socks, index); @@ -1388,9 +1394,11 @@ static void nbd_config_put(struct nbd_device *nbd) } nbd_clear_sock(nbd); - xa_for_each(&config->socks, i, nsock) { - sockfd_put(nsock->sock); - kfree(nsock); + if (config->num_connections) { + xa_for_each(&config->socks, i, nsock) { + sockfd_put(nsock->sock); + kfree(nsock); + } } xa_destroy(&config->socks); -- 2.52.0
hulk inclusion category: feature bugzilla: https://atomgit.com/openeuler/kernel/issues/9153 ---------------------------------------- This reverts commit 05db143d68ef17d206b5d925256bbac834016e0b. Revert self-developed patchset, using mainline patchset. Signed-off-by: Yang Erkun <yangerkun@huawei.com> --- drivers/block/nbd.c | 155 +++++++++++++++++--------------------------- 1 file changed, 59 insertions(+), 96 deletions(-) diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 25885a2c7e70..2cc7abcf8bc7 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -38,7 +38,6 @@ #include <linux/types.h> #include <linux/debugfs.h> #include <linux/blk-mq.h> -#include <linux/xarray.h> #include <linux/uaccess.h> #include <asm/types.h> @@ -94,7 +93,7 @@ struct nbd_config { unsigned long runtime_flags; u64 dead_conn_timeout; - struct xarray socks; + struct nbd_sock **socks; int num_connections; atomic_t live_connections; wait_queue_head_t conn_wait; @@ -380,15 +379,15 @@ static void nbd_complete_rq(struct request *req) static void sock_shutdown(struct nbd_device *nbd) { struct nbd_config *config = nbd->config; - struct nbd_sock *nsock; - unsigned long i; + int i; if (config->num_connections == 0) return; if (test_and_set_bit(NBD_RT_DISCONNECTED, &config->runtime_flags)) return; - xa_for_each(&config->socks, i, nsock) { + for (i = 0; i < config->num_connections; i++) { + struct nbd_sock *nsock = config->socks[i]; mutex_lock(&nsock->tx_lock); nbd_mark_nsock_dead(nbd, nsock, 0); mutex_unlock(&nsock->tx_lock); @@ -433,7 +432,6 @@ static enum blk_eh_timer_return nbd_xmit_timeout(struct request *req) struct nbd_cmd *cmd = blk_mq_rq_to_pdu(req); struct nbd_device *nbd = cmd->nbd; struct nbd_config *config; - struct nbd_sock *nsock; if (!mutex_trylock(&cmd->lock)) return BLK_EH_RESET_TIMER; @@ -463,9 +461,10 @@ static enum blk_eh_timer_return nbd_xmit_timeout(struct request *req) * connection is configured, the submit path will wait util * a new connection is reconfigured or util dead timeout. */ - if (!xa_empty(&config->socks)) { - nsock = xa_load(&config->socks, cmd->index); - if (nsock) { + if (config->socks) { + if (cmd->index < config->num_connections) { + struct nbd_sock *nsock = + config->socks[cmd->index]; mutex_lock(&nsock->tx_lock); /* We can have multiple outstanding requests, so * we don't want to mark the nsock dead if we've @@ -489,24 +488,22 @@ static enum blk_eh_timer_return nbd_xmit_timeout(struct request *req) * Userspace sets timeout=0 to disable socket disconnection, * so just warn and reset the timer. */ + struct nbd_sock *nsock = config->socks[cmd->index]; 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); - nsock = xa_load(&config->socks, cmd->index); - if (nsock) { - mutex_lock(&nsock->tx_lock); - if (cmd->cookie != nsock->cookie) { - nbd_requeue_cmd(cmd); - mutex_unlock(&nsock->tx_lock); - mutex_unlock(&cmd->lock); - nbd_config_put(nbd); - return BLK_EH_DONE; - } + mutex_lock(&nsock->tx_lock); + if (cmd->cookie != nsock->cookie) { + nbd_requeue_cmd(cmd); mutex_unlock(&nsock->tx_lock); + mutex_unlock(&cmd->lock); + nbd_config_put(nbd); + return BLK_EH_DONE; } + mutex_unlock(&nsock->tx_lock); mutex_unlock(&cmd->lock); nbd_config_put(nbd); return BLK_EH_RESET_TIMER; @@ -573,16 +570,8 @@ static int sock_xmit(struct nbd_device *nbd, int index, int send, struct iov_iter *iter, int msg_flags, int *sent) { struct nbd_config *config = nbd->config; - struct nbd_sock *nsock; - struct socket *sock; + struct socket *sock = config->socks[index]->sock; - nsock = xa_load(&config->socks, index); - if (unlikely(!nsock)) { - dev_err_ratelimited(disk_to_dev(nbd->disk), - "Attempted xmit on invalid socket\n"); - return -EINVAL; - } - sock = nsock->sock; return __sock_xmit(nbd, sock, send, iter, msg_flags, sent); } @@ -603,7 +592,7 @@ static int nbd_send_cmd(struct nbd_device *nbd, struct nbd_cmd *cmd, int index) { struct request *req = blk_mq_rq_from_pdu(cmd); struct nbd_config *config = nbd->config; - struct nbd_sock *nsock; + struct nbd_sock *nsock = config->socks[index]; int result; struct nbd_request request = {.magic = htonl(NBD_REQUEST_MAGIC)}; struct kvec iov = {.iov_base = &request, .iov_len = sizeof(request)}; @@ -613,14 +602,7 @@ static int nbd_send_cmd(struct nbd_device *nbd, struct nbd_cmd *cmd, int index) u64 handle; u32 type; u32 nbd_cmd_flags = 0; - int sent, skip = 0; - - nsock = xa_load(&config->socks, index); - if (unlikely(!nsock)) { - dev_err_ratelimited(disk_to_dev(nbd->disk), - "Attempted send on invalid socket\n"); - return BLK_STS_IOERR; - } + int sent = nsock->sent, skip = 0; lockdep_assert_held(&cmd->lock); lockdep_assert_held(&nsock->tx_lock); @@ -645,7 +627,6 @@ static int nbd_send_cmd(struct nbd_device *nbd, struct nbd_cmd *cmd, int index) * request struct, so just go and send the rest of the pages in the * request. */ - sent = nsock->sent; if (sent) { if (sent >= sizeof(request)) { skip = sent - sizeof(request); @@ -973,10 +954,9 @@ static int find_fallback(struct nbd_device *nbd, int index) { struct nbd_config *config = nbd->config; int new_index = -1; - struct nbd_sock *nsock; - struct nbd_sock *fallback_nsock; - unsigned long i; - int fallback; + struct nbd_sock *nsock = config->socks[index]; + int fallback = nsock->fallback_index; + int i; if (test_bit(NBD_RT_DISCONNECTED, &config->runtime_flags)) return new_index; @@ -984,19 +964,12 @@ static int find_fallback(struct nbd_device *nbd, int index) if (config->num_connections <= 1) goto no_fallback; - nsock = xa_load(&config->socks, index); - if (unlikely(!nsock)) - goto no_fallback; - - fallback = nsock->fallback_index; - if (fallback >= 0 && fallback < config->num_connections) { - fallback_nsock = xa_load(&config->socks, fallback); - if (fallback_nsock && !fallback_nsock->dead) - return fallback; - } + if (fallback >= 0 && fallback < config->num_connections && + !config->socks[fallback]->dead) + return fallback; - xa_for_each(&config->socks, i, fallback_nsock) { - if (i != index && !fallback_nsock->dead) { + for (i = 0; i < config->num_connections; i++) { + if (i != index && !config->socks[i]->dead) { new_index = i; break; } @@ -1052,14 +1025,7 @@ static blk_status_t nbd_handle_cmd(struct nbd_cmd *cmd, int index) } cmd->status = BLK_STS_OK; again: - nsock = xa_load(&config->socks, index); - if (unlikely(!nsock)) { - dev_err_ratelimited(disk_to_dev(nbd->disk), - "Attempted send on invalid socket\n"); - nbd_config_put(nbd); - return BLK_STS_IOERR; - } - + nsock = config->socks[index]; mutex_lock(&nsock->tx_lock); if (nsock->dead) { int old_index = index; @@ -1180,8 +1146,8 @@ static int nbd_add_socket(struct nbd_device *nbd, unsigned long arg, { struct nbd_config *config = nbd->config; struct socket *sock; + struct nbd_sock **socks; struct nbd_sock *nsock; - unsigned int index; int err; /* Arg will be cast to int, check it to avoid overflow */ @@ -1216,6 +1182,16 @@ static int nbd_add_socket(struct nbd_device *nbd, unsigned long arg, goto put_socket; } + socks = krealloc(config->socks, (config->num_connections + 1) * + sizeof(struct nbd_sock *), GFP_KERNEL); + if (!socks) { + kfree(nsock); + err = -ENOMEM; + goto put_socket; + } + + config->socks = socks; + nsock->fallback_index = -1; nsock->dead = false; mutex_init(&nsock->tx_lock); @@ -1223,14 +1199,7 @@ static int nbd_add_socket(struct nbd_device *nbd, unsigned long arg, nsock->pending = NULL; nsock->sent = 0; nsock->cookie = 0; - - err = xa_alloc(&config->socks, &index, nsock, xa_limit_32b, GFP_KERNEL); - if (err < 0) { - kfree(nsock); - goto put_socket; - } - - config->num_connections++; + socks[config->num_connections++] = nsock; atomic_inc(&config->live_connections); blk_mq_unfreeze_queue(nbd->disk->queue); @@ -1247,8 +1216,7 @@ static int nbd_reconnect_socket(struct nbd_device *nbd, unsigned long arg) struct nbd_config *config = nbd->config; struct socket *sock, *old; struct recv_thread_args *args; - struct nbd_sock *nsock; - unsigned long i; + int i; int err; sock = nbd_get_socket(nbd, arg, &err); @@ -1261,7 +1229,9 @@ static int nbd_reconnect_socket(struct nbd_device *nbd, unsigned long arg) return -ENOMEM; } - xa_for_each(&config->socks, i, nsock) { + for (i = 0; i < config->num_connections; i++) { + struct nbd_sock *nsock = config->socks[i]; + if (!nsock->dead) continue; @@ -1336,11 +1306,10 @@ static void send_disconnects(struct nbd_device *nbd) }; struct kvec iov = {.iov_base = &request, .iov_len = sizeof(request)}; struct iov_iter from; - struct nbd_sock *nsock; - unsigned long i; - int ret; + int i, ret; - xa_for_each(&config->socks, i, nsock) { + for (i = 0; i < config->num_connections; i++) { + struct nbd_sock *nsock = config->socks[i]; iov_iter_kvec(&from, ITER_SOURCE, &iov, 1, sizeof(request)); mutex_lock(&nsock->tx_lock); @@ -1375,9 +1344,6 @@ static void nbd_config_put(struct nbd_device *nbd) if (refcount_dec_and_mutex_lock(&nbd->config_refs, &nbd->config_lock)) { struct nbd_config *config = nbd->config; - struct nbd_sock *nsock; - unsigned long i; - nbd_dev_dbg_close(nbd); invalidate_disk(nbd->disk); if (nbd->config->bytesize) @@ -1393,15 +1359,14 @@ static void nbd_config_put(struct nbd_device *nbd) nbd->backend = NULL; } nbd_clear_sock(nbd); - if (config->num_connections) { - xa_for_each(&config->socks, i, nsock) { - sockfd_put(nsock->sock); - kfree(nsock); + int i; + for (i = 0; i < config->num_connections; i++) { + sockfd_put(config->socks[i]->sock); + kfree(config->socks[i]); } + kfree(config->socks); } - xa_destroy(&config->socks); - kfree(nbd->config); nbd->config = NULL; @@ -1419,13 +1384,11 @@ static int nbd_start_device(struct nbd_device *nbd) { struct nbd_config *config = nbd->config; int num_connections = config->num_connections; - int error = 0; - unsigned long i; - struct nbd_sock *nsock; + int error = 0, i; if (nbd->pid) return -EBUSY; - if (xa_empty(&config->socks)) + if (!config->socks) return -EINVAL; if (num_connections > 1 && !(config->flags & NBD_FLAG_CAN_MULTI_CONN)) { @@ -1446,7 +1409,7 @@ static int nbd_start_device(struct nbd_device *nbd) set_bit(NBD_RT_HAS_PID_FILE, &config->runtime_flags); nbd_dev_dbg_init(nbd); - xa_for_each(&config->socks, i, nsock) { + for (i = 0; i < num_connections; i++) { struct recv_thread_args *args; args = kzalloc(sizeof(*args), GFP_KERNEL); @@ -1464,14 +1427,15 @@ static int nbd_start_device(struct nbd_device *nbd) flush_workqueue(nbd->recv_workq); return -ENOMEM; } - sk_set_memalloc(nsock->sock->sk); + sk_set_memalloc(config->socks[i]->sock->sk); if (nbd->tag_set.timeout) - nsock->sock->sk->sk_sndtimeo = nbd->tag_set.timeout; + config->socks[i]->sock->sk->sk_sndtimeo = + nbd->tag_set.timeout; atomic_inc(&config->recv_threads); refcount_inc(&nbd->config_refs); INIT_WORK(&args->work, recv_work); args->nbd = nbd; - args->nsock = nsock; + args->nsock = config->socks[i]; args->index = i; queue_work(nbd->recv_workq, &args->work); } @@ -1626,7 +1590,6 @@ static int nbd_alloc_and_init_config(struct nbd_device *nbd) return -ENOMEM; } - xa_init_flags(&config->socks, XA_FLAGS_ALLOC); atomic_set(&config->recv_threads, 0); init_waitqueue_head(&config->recv_wq); init_waitqueue_head(&config->conn_wait); -- 2.52.0
hulk inclusion category: feature bugzilla: https://atomgit.com/openeuler/kernel/issues/9153 ---------------------------------------- This reverts commit a798223fb5d3c56bcd0faae02cab0a23eea35e7d. Revert self-developed patchset, using mainline patchset. Signed-off-by: Yang Erkun <yangerkun@huawei.com> --- drivers/block/nbd.c | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 2cc7abcf8bc7..abf8e34516e0 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -956,31 +956,40 @@ static int find_fallback(struct nbd_device *nbd, int index) int new_index = -1; struct nbd_sock *nsock = config->socks[index]; int fallback = nsock->fallback_index; - int i; if (test_bit(NBD_RT_DISCONNECTED, &config->runtime_flags)) return new_index; - if (config->num_connections <= 1) - goto no_fallback; + if (config->num_connections <= 1) { + dev_err_ratelimited(disk_to_dev(nbd->disk), + "Dead connection, failed to find a fallback\n"); + return new_index; + } if (fallback >= 0 && fallback < config->num_connections && !config->socks[fallback]->dead) return fallback; - for (i = 0; i < config->num_connections; i++) { - if (i != index && !config->socks[i]->dead) { - new_index = i; - break; + if (nsock->fallback_index < 0 || + nsock->fallback_index >= config->num_connections || + config->socks[nsock->fallback_index]->dead) { + int i; + for (i = 0; i < config->num_connections; i++) { + if (i == index) + continue; + if (!config->socks[i]->dead) { + new_index = i; + break; + } + } + nsock->fallback_index = new_index; + if (new_index < 0) { + dev_err_ratelimited(disk_to_dev(nbd->disk), + "Dead connection, failed to find a fallback\n"); + return new_index; } } - nsock->fallback_index = new_index; - if (new_index >= 0) - return new_index; - -no_fallback: - dev_err_ratelimited(disk_to_dev(nbd->disk), - "Dead connection, failed to find a fallback\n"); + new_index = nsock->fallback_index; return new_index; } -- 2.52.0
mainline inclusion from mainline-v7.3-rc1 commit 04d8fb23e520419a283dd53c1d9cdfb7c5b1705e category: feature bugzilla: https://atomgit.com/openeuler/kernel/issues/9153 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i... -------------------------------- We cannot add a socket to an already running nbd device, the reconfigure for netlink can only active an inactive socket. But for ioctl path, we can call NBD_SET_SOCK after NBD_DO_IT, reject this using nbd->pid which has been setted when NBD_DO_IT. Besides, it is the root cause for commit b98e762e3d71 ("nbd: freeze the queue while we're adding connections"). Reviewed-by: Yu Kuai <yukuai@fygo.io> Signed-off-by: Yang Erkun <yangerkun@huawei.com> Link: https://patch.msgid.link/20260805122930.57647-3-yangerkun@huawei.com Signed-off-by: Jens Axboe <axboe@kernel.dk> Signed-off-by: Yang Erkun <yangerkun@huawei.com> --- drivers/block/nbd.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index abf8e34516e0..d045ec6ed661 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -1162,6 +1162,13 @@ static int nbd_add_socket(struct nbd_device *nbd, unsigned long arg, /* Arg will be cast to int, check it to avoid overflow */ if (arg > INT_MAX) return -EINVAL; + + if (nbd->pid) { + dev_err(disk_to_dev(nbd->disk), + "Cannot add socket to a running device\n"); + return -EBUSY; + } + sock = nbd_get_socket(nbd, arg, &err); if (!sock) return err; -- 2.52.0
mainline inclusion from mainline-v7.3-rc1 commit 285908f554fe32d9ca7cb7c3a03a05144faeb461 category: feature bugzilla: https://atomgit.com/openeuler/kernel/issues/9153 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i... -------------------------------- nbd_add_socket() kreallocs config->socks, which a concurrent reader in nbd_handle_cmd() could UAF; commit b98e762e3d71 ("nbd: freeze the queue while we're adding connections")froze the queue to block that. But the freeze costs an RCU grace period on every socket added, and setup adds them one by one. After the previous patch, nbd_add_socket() is rejected once nbd->pid is set, so it only runs during setup. There the capacity is 0 and the write cache is off (cleared on disconnect by the preceding patch, and re-enabled only later in nbd_set_size), so submit_bio_noacct() rejects every bio before it reaches the driver -- non-zero-sector ones via bio_check_eod(), and flush-only ones via the !bdev_write_cache() branch. No I/O is in flight, so the freeze is unnecessary. Reviewed-by: Yu Kuai <yukuai@fygo.io> Signed-off-by: Yang Erkun <yangerkun@huawei.com> Link: https://patch.msgid.link/20260805122930.57647-5-yangerkun@huawei.com Signed-off-by: Jens Axboe <axboe@kernel.dk> Conflicts: drivers/block/nbd.c [6.6 still uses the one-argument blk_mq_freeze_queue()/ blk_mq_unfreeze_queue() without the memflags return value, so drop the memflags declaration and the two unfreeze calls accordingly.] Signed-off-by: Yang Erkun <yangerkun@huawei.com> --- drivers/block/nbd.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index d045ec6ed661..8f2032e533de 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -1173,12 +1173,6 @@ static int nbd_add_socket(struct nbd_device *nbd, unsigned long arg, if (!sock) return err; - /* - * We need to make sure we don't get any errant requests while we're - * reallocating the ->socks array. - */ - blk_mq_freeze_queue(nbd->disk->queue); - if (!netlink && !nbd->task_setup && !test_bit(NBD_RT_BOUND, &config->runtime_flags)) nbd->task_setup = current; @@ -1217,12 +1211,10 @@ static int nbd_add_socket(struct nbd_device *nbd, unsigned long arg, nsock->cookie = 0; socks[config->num_connections++] = nsock; atomic_inc(&config->live_connections); - blk_mq_unfreeze_queue(nbd->disk->queue); return 0; put_socket: - blk_mq_unfreeze_queue(nbd->disk->queue); sockfd_put(sock); return err; } -- 2.52.0
mainline inclusion from mainline-v7.3-rc1 commit f8d21c590e55d629abed675554b186291ac08915 category: feature bugzilla: https://atomgit.com/openeuler/kernel/issues/9153 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i... -------------------------------- The NBD_ATTR_SOCKETS walk is duplicated in nbd_genl_connect (add sockets) and nbd_genl_reconfigure (reconnect). Factor out a single helper that walks the list and calls a callback per fd; with a NULL callback it is a pure counter, used by a later patch to learn nr_hw_queues before the device exists. Returns the number of fds walked (>= 0) or a negative errno; a callback >0 will stops early. Reviewed-by: Yu Kuai <yukuai@fygo.io> Signed-off-by: Yang Erkun <yangerkun@huawei.com> Link: https://patch.msgid.link/20260805122930.57647-7-yangerkun@huawei.com Signed-off-by: Jens Axboe <axboe@kernel.dk> Signed-off-by: Yang Erkun <yangerkun@huawei.com> --- drivers/block/nbd.c | 128 +++++++++++++++++++++----------------------- 1 file changed, 62 insertions(+), 66 deletions(-) diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 8f2032e533de..73dfa216de1f 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -1219,7 +1219,7 @@ static int nbd_add_socket(struct nbd_device *nbd, unsigned long arg, return err; } -static int nbd_reconnect_socket(struct nbd_device *nbd, unsigned long arg) +static int nbd_genl_reconnect_sock_cb(struct nbd_device *nbd, unsigned long arg) { struct nbd_config *config = nbd->config; struct socket *sock, *old; @@ -1274,11 +1274,12 @@ static int nbd_reconnect_socket(struct nbd_device *nbd, unsigned long arg) atomic_inc(&config->live_connections); wake_up(&config->conn_wait); + dev_info(nbd_to_dev(nbd), "reconnected socket\n"); return 0; } sockfd_put(sock); kfree(args); - return -ENOSPC; + return 1; } static void nbd_bdev_reset(struct nbd_device *nbd) @@ -1987,6 +1988,58 @@ static int nbd_genl_size_set(struct genl_info *info, struct nbd_device *nbd) return 0; } +/* + * Walk the NBD_ATTR_SOCKETS nested list can call @cb for each socket fd. + * + * Return the number of fds walked, or a negative errno. + */ +static int nbd_genl_foreach_sock(struct genl_info *info, + int (*cb)(struct nbd_device *nbd, unsigned long fd), + struct nbd_device *nbd) +{ + struct nlattr *attr; + int rem, count = 0; + + if (!info->attrs[NBD_ATTR_SOCKETS]) + return 0; + + nla_for_each_nested(attr, info->attrs[NBD_ATTR_SOCKETS], rem) { + struct nlattr *socks[NBD_SOCK_MAX + 1]; + int ret; + + if (nla_type(attr) != NBD_SOCK_ITEM) { + pr_err("socks must be embedded in a SOCK_ITEM attr\n"); + return -EINVAL; + } + + if (nla_parse_nested_deprecated(socks, NBD_SOCK_MAX, + attr, + nbd_sock_policy, + info->extack)) { + pr_err("error processing sock list\n"); + return -EINVAL; + } + + if (!socks[NBD_SOCK_FD]) + continue; + + count++; + if (cb) { + ret = cb(nbd, (int)nla_get_u32(socks[NBD_SOCK_FD])); + if (ret > 0) + return count; + if (ret < 0) + return ret; + } + } + return count; +} + +static int nbd_genl_connect_sock_cb(struct nbd_device *nbd, unsigned long fd) +{ + return nbd_add_socket(nbd, fd, true); +} + static int nbd_genl_connect(struct sk_buff *skb, struct genl_info *info) { struct nbd_device *nbd; @@ -2106,36 +2159,9 @@ static int nbd_genl_connect(struct sk_buff *skb, struct genl_info *info) } } - if (info->attrs[NBD_ATTR_SOCKETS]) { - struct nlattr *attr; - int rem, fd; - - nla_for_each_nested(attr, info->attrs[NBD_ATTR_SOCKETS], - rem) { - struct nlattr *socks[NBD_SOCK_MAX+1]; - - if (nla_type(attr) != NBD_SOCK_ITEM) { - pr_err("socks must be embedded in a SOCK_ITEM attr\n"); - ret = -EINVAL; - goto out; - } - ret = nla_parse_nested_deprecated(socks, NBD_SOCK_MAX, - attr, - nbd_sock_policy, - info->extack); - if (ret != 0) { - pr_err("error processing sock list\n"); - ret = -EINVAL; - goto out; - } - if (!socks[NBD_SOCK_FD]) - continue; - fd = (int)nla_get_u32(socks[NBD_SOCK_FD]); - ret = nbd_add_socket(nbd, fd, true); - if (ret) - goto out; - } - } + ret = nbd_genl_foreach_sock(info, nbd_genl_connect_sock_cb, nbd); + if (ret < 0) + goto out; if (info->attrs[NBD_ATTR_BACKEND_IDENTIFIER]) { nbd->backend = nla_strdup(info->attrs[NBD_ATTR_BACKEND_IDENTIFIER], @@ -2320,40 +2346,10 @@ static int nbd_genl_reconfigure(struct sk_buff *skb, struct genl_info *info) } } - if (info->attrs[NBD_ATTR_SOCKETS]) { - struct nlattr *attr; - int rem, fd; - - nla_for_each_nested(attr, info->attrs[NBD_ATTR_SOCKETS], - rem) { - struct nlattr *socks[NBD_SOCK_MAX+1]; - - if (nla_type(attr) != NBD_SOCK_ITEM) { - pr_err("socks must be embedded in a SOCK_ITEM attr\n"); - ret = -EINVAL; - goto out; - } - ret = nla_parse_nested_deprecated(socks, NBD_SOCK_MAX, - attr, - nbd_sock_policy, - info->extack); - if (ret != 0) { - pr_err("error processing sock list\n"); - ret = -EINVAL; - goto out; - } - if (!socks[NBD_SOCK_FD]) - continue; - fd = (int)nla_get_u32(socks[NBD_SOCK_FD]); - ret = nbd_reconnect_socket(nbd, fd); - if (ret) { - if (ret == -ENOSPC) - ret = 0; - goto out; - } - dev_info(nbd_to_dev(nbd), "reconnected socket\n"); - } - } + ret = nbd_genl_foreach_sock(info, nbd_genl_reconnect_sock_cb, nbd); + /* foreach_sock returns a positive count on success; doit must return 0 */ + if (ret >= 0) + ret = 0; out: mutex_unlock(&nbd->config_lock); nbd_config_put(nbd); -- 2.52.0
mainline inclusion from mainline-v7.3-rc1 commit a9d414b4a15c69b5389da3ec08f23e9f2926c52a category: feature bugzilla: https://atomgit.com/openeuler/kernel/issues/9153 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i... -------------------------------- Previous commits has removed the queue freeze in nbd_add_socket and nbd_set_size during nbd device setup. However, a queue freeze can still occur when nbd_start_device calls blk_mq_update_nr_hw_queues if the socket connection count does not match nbd->tag_set->nr_hw_queues. The nbd_start_device function can be invoked through either the ioctl or netlink paths. The ioctl path only allows reusing an existing inactivate nbd device, there is nothing more we can do to prevent the queue freeze since the old nbd->tag_set->nr_hw_queues may not match the new socket connection count. Similarly, the netlink path can reuse a preferred inactivate nbd device, and again, we cannot do more in this scenario. However, the netlink path can also add a new nbd device using nbd_dev_add. In this case, we can obtain the new number of socket connections, and by adding a new argument representing the expected nr_hw_queues in nbd_dev_add, we can ensure the queue freeze is avoided for this situation. Reviewed-by: Yu Kuai <yukuai@fygo.io> Signed-off-by: Yang Erkun <yangerkun@huawei.com> Link: https://patch.msgid.link/20260805122930.57647-8-yangerkun@huawei.com Signed-off-by: Jens Axboe <axboe@kernel.dk> Conflicts: drivers/block/nbd.c [Context conflicts only: 6.6 nbd_dev_add() configures the queue with the individual blk_queue_* helpers instead of the queue_limits argument, and still sets BLK_MQ_F_SHOULD_MERGE.] Signed-off-by: Yang Erkun <yangerkun@huawei.com> --- drivers/block/nbd.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 73dfa216de1f..2084a0227f00 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -1816,7 +1816,8 @@ static const struct blk_mq_ops nbd_mq_ops = { .timeout = nbd_xmit_timeout, }; -static struct nbd_device *nbd_dev_add(int index, unsigned int refs) +static struct nbd_device *nbd_dev_add(int index, unsigned int refs, + int nr_hw_queues) { struct nbd_device *nbd; struct gendisk *disk; @@ -1827,7 +1828,7 @@ static struct nbd_device *nbd_dev_add(int index, unsigned int refs) goto out; nbd->tag_set.ops = &nbd_mq_ops; - nbd->tag_set.nr_hw_queues = 1; + nbd->tag_set.nr_hw_queues = nr_hw_queues; nbd->tag_set.queue_depth = 128; nbd->tag_set.numa_node = NUMA_NO_NODE; nbd->tag_set.cmd_size = sizeof(struct nbd_cmd); @@ -2092,7 +2093,11 @@ static int nbd_genl_connect(struct sk_buff *skb, struct genl_info *info) mutex_unlock(&nbd_index_mutex); if (!nbd) { - nbd = nbd_dev_add(index, 2); + ret = nbd_genl_foreach_sock(info, NULL, NULL); + if (ret < 0) + return ret; + + nbd = nbd_dev_add(index, 2, ret > 0 ? ret : 1); if (IS_ERR(nbd)) { pr_err("failed to add new device\n"); return PTR_ERR(nbd); @@ -2602,7 +2607,7 @@ static int __init nbd_init(void) nbd_dbg_init(); for (i = 0; i < nbds_max; i++) - nbd_dev_add(i, 1); + nbd_dev_add(i, 1, 1); return 0; } -- 2.52.0
mainline inclusion from mainline-v7.3-rc1 commit 326d49039c10b65522ac7277b19b9b5c42ed1aeb category: feature bugzilla: https://atomgit.com/openeuler/kernel/issues/9153 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i... -------------------------------- blk_mq_update_nr_hw_queues() in nbd_start_device() may cause a queue freeze. The previous commit addressed this for newly created nbd devices by setting the expected nr_hw_queues in nbd_dev_add(). However, when reusing an old inactive nbd device, the queue freeze can still occur if the old nbd->tag_set->nr_hw_queues does not match the new socket connection count. Inactive nbd devices can originate from two sources: loading the nbd module with nbds_max, which sets the default nr_hw_queues to 1, and the netlink method, which sets nr_hw_queues according to the expected number of socket connections. For the first case, add a module parameter so the default nr_hw_queues can be changed. Users who know their expected number of connections can then prevent queue freezes on pre-created devices via nbds_max. Before this patchset: real 0m2.195s user 0m0.005s sys 0m0.022s After this patchset: real 0m0.090s user 0m0.004s sys 0m0.018s Reviewed-by: Yu Kuai <yukuai@fygo.io> Signed-off-by: Yang Erkun <yangerkun@huawei.com> Link: https://patch.msgid.link/20260805122930.57647-9-yangerkun@huawei.com Signed-off-by: Jens Axboe <axboe@kernel.dk> Signed-off-by: Yang Erkun <yangerkun@huawei.com> --- drivers/block/nbd.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 2084a0227f00..2f256f94a895 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -162,6 +162,7 @@ static struct dentry *nbd_dbg_dir; static unsigned int nbds_max = 16; static int max_part = 16; +static int pre_defined_connections = 1; static int part_shift; static int nbd_dev_dbg_init(struct nbd_device *nbd); @@ -2590,6 +2591,12 @@ static int __init nbd_init(void) if (nbds_max > 1UL << (MINORBITS - part_shift)) return -EINVAL; + /* An excessively large value will be adjusted in blk_mq_alloc_tag_set */ + if (pre_defined_connections < 1) { + pr_err("pre_defined_connections must be >= 1\n"); + return -EINVAL; + } + if (register_blkdev(NBD_MAJOR, "nbd")) return -EIO; @@ -2606,8 +2613,12 @@ static int __init nbd_init(void) } nbd_dbg_init(); + /* + * Set to the intended connection count so nbd_start_device() can skip + * the queue-freezing blk_mq_update_nr_hw_queues() call. + */ for (i = 0; i < nbds_max; i++) - nbd_dev_add(i, 1, 1); + nbd_dev_add(i, 1, pre_defined_connections); return 0; } @@ -2668,3 +2679,6 @@ module_param(nbds_max, int, 0444); MODULE_PARM_DESC(nbds_max, "number of network block devices to initialize (default: 16)"); module_param(max_part, int, 0444); MODULE_PARM_DESC(max_part, "number of partitions per device (default: 16)"); +module_param(pre_defined_connections, int, 0444); +MODULE_PARM_DESC(pre_defined_connections, +"number of connections for devices pre-created at module load (default: 1)"); -- 2.52.0
反馈: 您发送到kernel@openeuler.org的补丁/补丁集,已成功转换为PR! PR链接地址: https://atomgit.com/openeuler/kernel/merge_requests/27261 邮件列表地址:https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/WJY... FeedBack: The patch(es) which you have sent to kernel@openeuler.org mailing list has been converted to a pull request successfully! Pull request link: https://atomgit.com/openeuler/kernel/merge_requests/27261 Mailing list address: https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/WJY...
participants (2)
-
patchwork bot -
Yang Erkun