* [PATCH 0/4] nbd: replace socks pointer array with xarray to eliminate queue freeze
@ 2026-03-27 9:12 leo.lilong
2026-03-27 9:12 ` [PATCH 1/4] nbd: simplify find_fallback() by removing redundant logic leo.lilong
` (4 more replies)
0 siblings, 5 replies; 6+ messages in thread
From: leo.lilong @ 2026-03-27 9:12 UTC (permalink / raw)
To: josef, axboe
Cc: leo.lilong, linux-block, linux-kernel, yi.zhang, yangerkun,
lonuxli.64
From: Long Li <leo.lilong@huawei.com>
Hi,
Commit b98e762e3d ("nbd: freeze the queue while we're adding
connections") introduced blk_mq_freeze_queue() in the add-socket path
to prevent use-after-free when krealloc() relocates the config->socks
array while I/O is in flight. However, freezing the queue on every
connection setup introduces significant latency when establishing a
large number of connections.
This series eliminates the queue freeze by replacing the
krealloc-based struct nbd_sock **socks array with a struct xarray.
The xarray provides RCU-safe pointer publishing: each nbd_sock is
fully initialized before being stored via xa_store(), and concurrent
readers access individual entries through xa_load() without ever
holding a reference to the array itself. This removes the possibility
of UAF on array reallocation, making the queue freeze unnecessary.
The following test was performed with 256 connections on a local
nbd-server:
nbd-server -M 256 -C /etc/nbd-server/config
time nbd-client 127.0.0.1 10809 /dev/nbd0 -N myexport -C 256
Before: real 4.510s user 0.004s sys 0.038s
After: real 0.263s user 0.009s sys 0.032s
Connection setup time is reduced by ~94%.
Long Li (4):
nbd: simplify find_fallback() by removing redundant logic
nbd: replace socks pointer array with xarray
nbd: remove redundant num_connections boundary checks
nbd: remove queue freeze in nbd_add_socket
drivers/block/nbd.c | 201 +++++++++++++++++++++++---------------------
1 file changed, 106 insertions(+), 95 deletions(-)
--
2.39.2
^ permalink raw reply [flat|nested] 6+ messages in thread* [PATCH 1/4] nbd: simplify find_fallback() by removing redundant logic 2026-03-27 9:12 [PATCH 0/4] nbd: replace socks pointer array with xarray to eliminate queue freeze leo.lilong @ 2026-03-27 9:12 ` leo.lilong 2026-03-27 9:12 ` [PATCH 2/4] nbd: replace socks pointer array with xarray leo.lilong ` (3 subsequent siblings) 4 siblings, 0 replies; 6+ messages in thread From: leo.lilong @ 2026-03-27 9:12 UTC (permalink / raw) To: josef, axboe Cc: leo.lilong, linux-block, linux-kernel, yi.zhang, yangerkun, lonuxli.64 From: Long Li <leo.lilong@huawei.com> Remove the intermediate new_index variable and return -1 directly. The second conditional checking nsock->fallback_index validity is the logical inverse of the first, so drop it and let execution fall through naturally. Consolidate the two identical dev_err_ratelimited() + return paths into a single no_fallback label to reduce duplication. Signed-off-by: Long Li <leo.lilong@huawei.com> --- drivers/block/nbd.c | 37 ++++++++++++++----------------------- 1 file changed, 14 insertions(+), 23 deletions(-) diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index fe63f3c55d0d..f26ad2f1f3ff 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -1061,40 +1061,31 @@ 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) { - dev_err_ratelimited(disk_to_dev(nbd->disk), - "Dead connection, failed to find a fallback\n"); - return new_index; - } + if (config->num_connections <= 1) + goto no_fallback; if (fallback >= 0 && fallback < config->num_connections && !config->socks[fallback]->dead) return fallback; - 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; + for (i = 0; i < config->num_connections; i++) { + if (i != index && !config->socks[i]->dead) { + new_index = i; + break; } } - new_index = nsock->fallback_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"); return new_index; } -- 2.39.2 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 2/4] nbd: replace socks pointer array with xarray 2026-03-27 9:12 [PATCH 0/4] nbd: replace socks pointer array with xarray to eliminate queue freeze leo.lilong 2026-03-27 9:12 ` [PATCH 1/4] nbd: simplify find_fallback() by removing redundant logic leo.lilong @ 2026-03-27 9:12 ` leo.lilong 2026-03-27 9:12 ` [PATCH 3/4] nbd: remove redundant num_connections boundary checks leo.lilong ` (2 subsequent siblings) 4 siblings, 0 replies; 6+ messages in thread From: leo.lilong @ 2026-03-27 9:12 UTC (permalink / raw) To: josef, axboe Cc: leo.lilong, linux-block, linux-kernel, yi.zhang, yangerkun, lonuxli.64 From: Long Li <leo.lilong@huawei.com> Replace the krealloc-based struct nbd_sock **socks array with struct xarray socks. Each nbd sock is fully initialized before being stored into the xarray via xa_store(), ensuring concurrent readers calling xa_load() never observe a partially initialized socket. Convert all array index accesses to xa_load() and open-coded for-loops to xa_for_each(). Signed-off-by: Long Li <leo.lilong@huawei.com> --- drivers/block/nbd.c | 155 +++++++++++++++++++++++++++----------------- 1 file changed, 96 insertions(+), 59 deletions(-) diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index f26ad2f1f3ff..728db2e832f8 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -38,6 +38,7 @@ #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 +95,7 @@ struct nbd_config { unsigned long runtime_flags; u64 dead_conn_timeout; - struct nbd_sock **socks; + struct xarray socks; int num_connections; atomic_t live_connections; wait_queue_head_t conn_wait; @@ -398,15 +399,15 @@ static void nbd_complete_rq(struct request *req) static void sock_shutdown(struct nbd_device *nbd) { struct nbd_config *config = nbd->config; - int i; + struct nbd_sock *nsock; + unsigned long i; if (config->num_connections == 0) return; if (test_and_set_bit(NBD_RT_DISCONNECTED, &config->runtime_flags)) return; - for (i = 0; i < config->num_connections; i++) { - struct nbd_sock *nsock = config->socks[i]; + xa_for_each(&config->socks, i, nsock) { mutex_lock(&nsock->tx_lock); nbd_mark_nsock_dead(nbd, nsock, 0); mutex_unlock(&nsock->tx_lock); @@ -453,6 +454,7 @@ 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; @@ -488,10 +490,9 @@ 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 (config->socks) { - if (cmd->index < config->num_connections) { - struct nbd_sock *nsock = - config->socks[cmd->index]; + if (!xa_empty(&config->socks)) { + nsock = xa_load(&config->socks, cmd->index); + if (nsock) { mutex_lock(&nsock->tx_lock); /* We can have multiple outstanding requests, so * we don't want to mark the nsock dead if we've @@ -515,22 +516,24 @@ 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); - mutex_lock(&nsock->tx_lock); - if (cmd->cookie != nsock->cookie) { - nbd_requeue_cmd(cmd); + 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_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; @@ -600,8 +603,16 @@ 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 socket *sock = config->socks[index]->sock; + struct nbd_sock *nsock; + struct socket *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); } @@ -647,7 +658,7 @@ static blk_status_t nbd_send_cmd(struct nbd_device *nbd, struct nbd_cmd *cmd, { struct request *req = blk_mq_rq_from_pdu(cmd); struct nbd_config *config = nbd->config; - struct nbd_sock *nsock = config->socks[index]; + struct nbd_sock *nsock; int result; struct nbd_request request = {.magic = htonl(NBD_REQUEST_MAGIC)}; struct kvec iov = {.iov_base = &request, .iov_len = sizeof(request)}; @@ -656,7 +667,14 @@ static blk_status_t nbd_send_cmd(struct nbd_device *nbd, struct nbd_cmd *cmd, u64 handle; u32 type; u32 nbd_cmd_flags = 0; - int sent = nsock->sent, skip = 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; + } lockdep_assert_held(&cmd->lock); lockdep_assert_held(&nsock->tx_lock); @@ -683,6 +701,7 @@ static blk_status_t nbd_send_cmd(struct nbd_device *nbd, struct nbd_cmd *cmd, * 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); @@ -1059,9 +1078,10 @@ static int find_fallback(struct nbd_device *nbd, int index) { struct nbd_config *config = nbd->config; int new_index = -1; - struct nbd_sock *nsock = config->socks[index]; - int fallback = nsock->fallback_index; - int i; + struct nbd_sock *nsock; + struct nbd_sock *fallback_nsock; + unsigned long i; + int fallback; if (test_bit(NBD_RT_DISCONNECTED, &config->runtime_flags)) return new_index; @@ -1069,12 +1089,19 @@ static int find_fallback(struct nbd_device *nbd, int index) if (config->num_connections <= 1) goto no_fallback; - if (fallback >= 0 && fallback < config->num_connections && - !config->socks[fallback]->dead) - return fallback; + nsock = xa_load(&config->socks, index); + if (unlikely(!nsock)) + goto no_fallback; - for (i = 0; i < config->num_connections; i++) { - if (i != index && !config->socks[i]->dead) { + 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; + } + + xa_for_each(&config->socks, i, fallback_nsock) { + if (i != index && !fallback_nsock->dead) { new_index = i; break; } @@ -1130,7 +1157,14 @@ static blk_status_t nbd_handle_cmd(struct nbd_cmd *cmd, int index) } cmd->status = BLK_STS_OK; again: - nsock = config->socks[index]; + 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; + } + mutex_lock(&nsock->tx_lock); if (nsock->dead) { int old_index = index; @@ -1234,9 +1268,9 @@ 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 memflags; + unsigned int index; int err; /* Arg will be cast to int, check it to avoid overflow */ @@ -1271,16 +1305,6 @@ 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); @@ -1289,7 +1313,14 @@ static int nbd_add_socket(struct nbd_device *nbd, unsigned long arg, nsock->sent = 0; nsock->cookie = 0; INIT_WORK(&nsock->work, nbd_pending_cmd_work); - socks[config->num_connections++] = nsock; + + err = xa_alloc(&config->socks, &index, nsock, xa_limit_32b, GFP_KERNEL); + if (err < 0) { + kfree(nsock); + goto put_socket; + } + + config->num_connections++; atomic_inc(&config->live_connections); blk_mq_unfreeze_queue(nbd->disk->queue, memflags); @@ -1306,7 +1337,8 @@ 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; - int i; + struct nbd_sock *nsock; + unsigned long i; int err; sock = nbd_get_socket(nbd, arg, &err); @@ -1319,9 +1351,7 @@ static int nbd_reconnect_socket(struct nbd_device *nbd, unsigned long arg) return -ENOMEM; } - for (i = 0; i < config->num_connections; i++) { - struct nbd_sock *nsock = config->socks[i]; - + xa_for_each(&config->socks, i, nsock) { if (!nsock->dead) continue; @@ -1387,10 +1417,11 @@ static void send_disconnects(struct nbd_device *nbd) }; struct kvec iov = {.iov_base = &request, .iov_len = sizeof(request)}; struct iov_iter from; - int i, ret; + struct nbd_sock *nsock; + unsigned long i; + int ret; - for (i = 0; i < config->num_connections; i++) { - struct nbd_sock *nsock = config->socks[i]; + xa_for_each(&config->socks, i, nsock) { iov_iter_kvec(&from, ITER_SOURCE, &iov, 1, sizeof(request)); mutex_lock(&nsock->tx_lock); @@ -1425,6 +1456,9 @@ 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) @@ -1440,14 +1474,15 @@ static void nbd_config_put(struct nbd_device *nbd) nbd->backend = NULL; } nbd_clear_sock(nbd); + if (config->num_connections) { - int i; - for (i = 0; i < config->num_connections; i++) { - sockfd_put(config->socks[i]->sock); - kfree(config->socks[i]); + xa_for_each(&config->socks, i, nsock) { + sockfd_put(nsock->sock); + kfree(nsock); } - kfree(config->socks); } + xa_destroy(&config->socks); + kfree(nbd->config); nbd->config = NULL; @@ -1463,11 +1498,13 @@ static int nbd_start_device(struct nbd_device *nbd) { struct nbd_config *config = nbd->config; int num_connections = config->num_connections; - int error = 0, i; + int error = 0; + unsigned long i; + struct nbd_sock *nsock; if (nbd->pid) return -EBUSY; - if (!config->socks) + if (xa_empty(&config->socks)) return -EINVAL; if (num_connections > 1 && !(config->flags & NBD_FLAG_CAN_MULTI_CONN)) { @@ -1498,7 +1535,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); - for (i = 0; i < num_connections; i++) { + xa_for_each(&config->socks, i, nsock) { struct recv_thread_args *args; args = kzalloc_obj(*args); @@ -1516,15 +1553,14 @@ static int nbd_start_device(struct nbd_device *nbd) flush_workqueue(nbd->recv_workq); return -ENOMEM; } - sk_set_memalloc(config->socks[i]->sock->sk); + sk_set_memalloc(nsock->sock->sk); if (nbd->tag_set.timeout) - config->socks[i]->sock->sk->sk_sndtimeo = - nbd->tag_set.timeout; + nsock->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 = config->socks[i]; + args->nsock = nsock; args->index = i; queue_work(nbd->recv_workq, &args->work); } @@ -1674,6 +1710,7 @@ 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.39.2 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 3/4] nbd: remove redundant num_connections boundary checks 2026-03-27 9:12 [PATCH 0/4] nbd: replace socks pointer array with xarray to eliminate queue freeze leo.lilong 2026-03-27 9:12 ` [PATCH 1/4] nbd: simplify find_fallback() by removing redundant logic leo.lilong 2026-03-27 9:12 ` [PATCH 2/4] nbd: replace socks pointer array with xarray leo.lilong @ 2026-03-27 9:12 ` leo.lilong 2026-03-27 9:12 ` [PATCH 4/4] nbd: remove queue freeze in nbd_add_socket leo.lilong 2026-04-20 2:46 ` [PATCH 0/4] nbd: replace socks pointer array with xarray to eliminate queue freeze Long Li 4 siblings, 0 replies; 6+ messages in thread From: leo.lilong @ 2026-03-27 9:12 UTC (permalink / raw) To: josef, axboe Cc: leo.lilong, linux-block, linux-kernel, yi.zhang, yangerkun, lonuxli.64 From: Long Li <leo.lilong@huawei.com> Now that config->socks uses xarray instead of a plain array, explicit bounds checking against num_connections is no longer necessary. xa_load() returns NULL for any out-of-range or missing index, and xa_for_each() is a no-op on an empty xarray, making these guards redundant. Signed-off-by: Long Li <leo.lilong@huawei.com> --- drivers/block/nbd.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 728db2e832f8..1606cdaa868d 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -1094,7 +1094,7 @@ static int find_fallback(struct nbd_device *nbd, int index) goto no_fallback; fallback = nsock->fallback_index; - if (fallback >= 0 && fallback < config->num_connections) { + if (fallback >= 0) { fallback_nsock = xa_load(&config->socks, fallback); if (fallback_nsock && !fallback_nsock->dead) return fallback; @@ -1149,12 +1149,6 @@ 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); @@ -1475,11 +1469,9 @@ static void nbd_config_put(struct nbd_device *nbd) } nbd_clear_sock(nbd); - if (config->num_connections) { - xa_for_each(&config->socks, i, nsock) { - sockfd_put(nsock->sock); - kfree(nsock); - } + xa_for_each(&config->socks, i, nsock) { + sockfd_put(nsock->sock); + kfree(nsock); } xa_destroy(&config->socks); -- 2.39.2 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 4/4] nbd: remove queue freeze in nbd_add_socket 2026-03-27 9:12 [PATCH 0/4] nbd: replace socks pointer array with xarray to eliminate queue freeze leo.lilong ` (2 preceding siblings ...) 2026-03-27 9:12 ` [PATCH 3/4] nbd: remove redundant num_connections boundary checks leo.lilong @ 2026-03-27 9:12 ` leo.lilong 2026-04-20 2:46 ` [PATCH 0/4] nbd: replace socks pointer array with xarray to eliminate queue freeze Long Li 4 siblings, 0 replies; 6+ messages in thread From: leo.lilong @ 2026-03-27 9:12 UTC (permalink / raw) To: josef, axboe Cc: leo.lilong, linux-block, linux-kernel, yi.zhang, yangerkun, lonuxli.64 From: Long Li <leo.lilong@huawei.com> The queue freeze was originally needed to prevent concurrent requests from accessing config->socks while the backing array was being reallocated. Since config->socks is now an xarray, insertions are safe under RCU without freezing the queue. This significantly reduces connection setup time when using a large number of connections (-C 256): before: real 4.510s after: real 0.263s Signed-off-by: Long Li <leo.lilong@huawei.com> --- drivers/block/nbd.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 1606cdaa868d..24aa65c723af 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -1263,7 +1263,6 @@ static int nbd_add_socket(struct nbd_device *nbd, unsigned long arg, struct nbd_config *config = nbd->config; struct socket *sock; struct nbd_sock *nsock; - unsigned int memflags; unsigned int index; int err; @@ -1274,12 +1273,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. - */ - memflags = blk_mq_freeze_queue(nbd->disk->queue); - if (!netlink && !nbd->task_setup && !test_bit(NBD_RT_BOUND, &config->runtime_flags)) nbd->task_setup = current; @@ -1316,12 +1309,10 @@ 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, memflags); return 0; put_socket: - blk_mq_unfreeze_queue(nbd->disk->queue, memflags); sockfd_put(sock); return err; } -- 2.39.2 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH 0/4] nbd: replace socks pointer array with xarray to eliminate queue freeze 2026-03-27 9:12 [PATCH 0/4] nbd: replace socks pointer array with xarray to eliminate queue freeze leo.lilong ` (3 preceding siblings ...) 2026-03-27 9:12 ` [PATCH 4/4] nbd: remove queue freeze in nbd_add_socket leo.lilong @ 2026-04-20 2:46 ` Long Li 4 siblings, 0 replies; 6+ messages in thread From: Long Li @ 2026-04-20 2:46 UTC (permalink / raw) To: leo.lilong, josef, axboe Cc: linux-block, linux-kernel, yi.zhang, yangerkun, lonuxli.64 On Fri, Mar 27, 2026 at 05:12:19PM +0800, leo.lilong@huaweicloud.com wrote: > From: Long Li <leo.lilong@huawei.com> > > Hi, > > Commit b98e762e3d ("nbd: freeze the queue while we're adding > connections") introduced blk_mq_freeze_queue() in the add-socket path > to prevent use-after-free when krealloc() relocates the config->socks > array while I/O is in flight. However, freezing the queue on every > connection setup introduces significant latency when establishing a > large number of connections. > > This series eliminates the queue freeze by replacing the > krealloc-based struct nbd_sock **socks array with a struct xarray. > The xarray provides RCU-safe pointer publishing: each nbd_sock is > fully initialized before being stored via xa_store(), and concurrent > readers access individual entries through xa_load() without ever > holding a reference to the array itself. This removes the possibility > of UAF on array reallocation, making the queue freeze unnecessary. > > The following test was performed with 256 connections on a local > nbd-server: > > nbd-server -M 256 -C /etc/nbd-server/config > time nbd-client 127.0.0.1 10809 /dev/nbd0 -N myexport -C 256 > > Before: real 4.510s user 0.004s sys 0.038s > After: real 0.263s user 0.009s sys 0.032s > > Connection setup time is reduced by ~94%. > > Long Li (4): > nbd: simplify find_fallback() by removing redundant logic > nbd: replace socks pointer array with xarray > nbd: remove redundant num_connections boundary checks > nbd: remove queue freeze in nbd_add_socket > > drivers/block/nbd.c | 201 +++++++++++++++++++++++--------------------- > 1 file changed, 106 insertions(+), 95 deletions(-) > > -- > 2.39.2 > Friendly ping ... ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-04-20 2:52 UTC | newest] Thread overview: 6+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-03-27 9:12 [PATCH 0/4] nbd: replace socks pointer array with xarray to eliminate queue freeze leo.lilong 2026-03-27 9:12 ` [PATCH 1/4] nbd: simplify find_fallback() by removing redundant logic leo.lilong 2026-03-27 9:12 ` [PATCH 2/4] nbd: replace socks pointer array with xarray leo.lilong 2026-03-27 9:12 ` [PATCH 3/4] nbd: remove redundant num_connections boundary checks leo.lilong 2026-03-27 9:12 ` [PATCH 4/4] nbd: remove queue freeze in nbd_add_socket leo.lilong 2026-04-20 2:46 ` [PATCH 0/4] nbd: replace socks pointer array with xarray to eliminate queue freeze Long Li
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox