* [PATCH v4 0/7] nbd: eliminate queue freeze/unfreeze overhead in connection setup
@ 2026-07-27 7:47 Yang Erkun
2026-07-27 7:47 ` [PATCH v4 1/7] nbd: simplify find_fallback() by removing redundant logic Yang Erkun
` (6 more replies)
0 siblings, 7 replies; 8+ messages in thread
From: Yang Erkun @ 2026-07-27 7:47 UTC (permalink / raw)
To: josef, axboe, hch, yukuai
Cc: yi.zhang, chengzhihao1, echo.chenlin, leo.lilong, wangkefeng.wang,
huawei.libin, leijitang, linux-block, nbd
This series eliminates the blk_mq_freeze_queue()/unfreeze_queue()
overhead that currently occurs during nbd connection setup(nbd provide
ondemand and was using in AI sandbox e2b[1] to mount and attach rootfs).
Each freeze cycle will introduce a RCU grace which was significant
with multi-core system.
time nbd-client --name myexport --connections 96 127.0.0.1 1234
After this patchset:
real 0m0.090s
user 0m0.004s
sys 0m0.018s
Without this patchset:
real 0m2.195s
user 0m0.005s
sys 0m0.022s
v3->v4:
1. factor out nbd_genl_foreach_sock to cleanup duplicated code
2. rewrite some commit message to make what's going more clearly
v2->v3:
1. Stop using xarray, and protect it by rejecting late NBD_SET_SOCKS
2. Eliminate freeze in nbd_set_size when device setup
3. Add module parameter to eliminate freeze for pre-created device
v1->v2:
1. Rewrite cover letter
2. Eliminate freeze call from blk_mq_update_nr_hw_queues in
nbd_start_device for netlink path
Long Li (1):
nbd: simplify find_fallback() by removing redundant logic
Yang Erkun (6):
nbd: disallow NBD_SET_SOCK on an active device
nbd: remove queue freeze in nbd_add_socket
nbd: skip queue freeze when setting size at device startup
nbd: factor out a nbd_genl_foreach_sock
nbd: remove queue freeze for newly created nbd from netlink path
nbd: add nr_hw_queues module parameter for pre-created devices
drivers/block/nbd.c | 228 +++++++++++++++++++++++---------------------
1 file changed, 121 insertions(+), 107 deletions(-)
--
2.52.0
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v4 1/7] nbd: simplify find_fallback() by removing redundant logic
2026-07-27 7:47 [PATCH v4 0/7] nbd: eliminate queue freeze/unfreeze overhead in connection setup Yang Erkun
@ 2026-07-27 7:47 ` Yang Erkun
2026-07-27 7:47 ` [PATCH v4 2/7] nbd: disallow NBD_SET_SOCK on an active device Yang Erkun
` (5 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Yang Erkun @ 2026-07-27 7:47 UTC (permalink / raw)
To: josef, axboe, hch, yukuai
Cc: yi.zhang, chengzhihao1, echo.chenlin, leo.lilong, wangkefeng.wang,
huawei.libin, leijitang, linux-block, nbd
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>
Reviewed-by: Yu Kuai <yukuai@fygo.io>
---
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 8f10762e90ef..b1a5acd57426 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.52.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v4 2/7] nbd: disallow NBD_SET_SOCK on an active device
2026-07-27 7:47 [PATCH v4 0/7] nbd: eliminate queue freeze/unfreeze overhead in connection setup Yang Erkun
2026-07-27 7:47 ` [PATCH v4 1/7] nbd: simplify find_fallback() by removing redundant logic Yang Erkun
@ 2026-07-27 7:47 ` Yang Erkun
2026-07-27 7:47 ` [PATCH v4 3/7] nbd: remove queue freeze in nbd_add_socket Yang Erkun
` (4 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Yang Erkun @ 2026-07-27 7:47 UTC (permalink / raw)
To: josef, axboe, hch, yukuai
Cc: yi.zhang, chengzhihao1, echo.chenlin, leo.lilong, wangkefeng.wang,
huawei.libin, leijitang, linux-block, nbd
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").
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 b1a5acd57426..7ec85f94f742 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -1278,6 +1278,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
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v4 3/7] nbd: remove queue freeze in nbd_add_socket
2026-07-27 7:47 [PATCH v4 0/7] nbd: eliminate queue freeze/unfreeze overhead in connection setup Yang Erkun
2026-07-27 7:47 ` [PATCH v4 1/7] nbd: simplify find_fallback() by removing redundant logic Yang Erkun
2026-07-27 7:47 ` [PATCH v4 2/7] nbd: disallow NBD_SET_SOCK on an active device Yang Erkun
@ 2026-07-27 7:47 ` Yang Erkun
2026-07-27 7:47 ` [PATCH v4 4/7] nbd: skip queue freeze when setting size at device startup Yang Erkun
` (3 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Yang Erkun @ 2026-07-27 7:47 UTC (permalink / raw)
To: josef, axboe, hch, yukuai
Cc: yi.zhang, chengzhihao1, echo.chenlin, leo.lilong, wangkefeng.wang,
huawei.libin, leijitang, linux-block, nbd
The function nbd_add_socket use krealloc to expand the config->socks
array when adding new sockets. If I/O operations concurrently, this can
lead to UAF when accessing config->socks. Commit b98e762e3d71 ("nbd:
freeze the queue while we're adding connections") addressed this by
freezing the request_queue during the addtion. However, freezing and
unfreezing for multiprocess environments introduces noticeable latency,
espically there can be multi call for nbd_add_socket when one nbd setup.
Actually, after previous commit, nbd_add_socket cannot be called
after nbd_start_device, causing the device's capabilities to remain 0
and write cache disabled. This will make sure no I/O can happened
simultaneously(nbd accept I/O from bio):
- read/write bios with sectors are rejected by bio_check_eod in
submit_bio_noacct
- flush-only bio for write cache disabled device will directly return 0
in submit_bio_noacct (ps: we cannot enable write_cache for nbd device
since without BLK_FEAT_WRITE_CACHE)
Removing the freeze in nbd_add_socket to speed up nbd device startup.
Signed-off-by: Yang Erkun <yangerkun@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 7ec85f94f742..1a31e621b6f7 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -1272,7 +1272,6 @@ static int nbd_add_socket(struct nbd_device *nbd, unsigned long arg,
struct socket *sock;
struct nbd_sock **socks;
struct nbd_sock *nsock;
- unsigned int memflags;
int err;
/* Arg will be cast to int, check it to avoid overflow */
@@ -1290,12 +1289,6 @@ static int nbd_add_socket(struct nbd_device *nbd, unsigned long arg,
return err;
nbd_reclassify_socket(sock);
- /*
- * 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;
@@ -1335,12 +1328,10 @@ static int nbd_add_socket(struct nbd_device *nbd, unsigned long arg,
INIT_WORK(&nsock->work, nbd_pending_cmd_work);
socks[config->num_connections++] = nsock;
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.52.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v4 4/7] nbd: skip queue freeze when setting size at device startup
2026-07-27 7:47 [PATCH v4 0/7] nbd: eliminate queue freeze/unfreeze overhead in connection setup Yang Erkun
` (2 preceding siblings ...)
2026-07-27 7:47 ` [PATCH v4 3/7] nbd: remove queue freeze in nbd_add_socket Yang Erkun
@ 2026-07-27 7:47 ` Yang Erkun
2026-07-27 7:47 ` [PATCH v4 5/7] nbd: factor out a nbd_genl_foreach_sock Yang Erkun
` (2 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Yang Erkun @ 2026-07-27 7:47 UTC (permalink / raw)
To: josef, axboe, hch, yukuai
Cc: yi.zhang, chengzhihao1, echo.chenlin, leo.lilong, wangkefeng.wang,
huawei.libin, leijitang, linux-block, nbd
The commit 242a49e5c878 ("nbd: freeze the queue for queue limits
updates") introduced freezing and unfreezing of the queue in
nbd_set_size to prevent inflight commands from seeing inconsistent
limits. However, this protection appears unnecessary during the nbd
startup process because no I/O can occur before nbd_set_size is
called (with zero capability and write cache disabled).
To address this, nbd_set_size is split with a boolean parameter
'freeze': the startup path nbd_start_device passes false, while
runtime resize or reconfigure paths (such as ioctls and
nbd_genl_size_set) pass true. Although nbd_genl_connect calls
nbd_genl_size_set before nbd_start_device, nbd->pid is zero at that
point, so nbd_set_size returns early before applying the limits
commit. The 'true' parameter covers the nbd_genl_reconnect path,
which operates on a live device where concurrent I/O may occur.
Signed-off-by: Yang Erkun <yangerkun@huawei.com>
---
drivers/block/nbd.c | 21 ++++++++++++++-------
1 file changed, 14 insertions(+), 7 deletions(-)
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index 1a31e621b6f7..e2fb787248c8 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -331,7 +331,8 @@ static void nbd_mark_nsock_dead(struct nbd_device *nbd, struct nbd_sock *nsock,
nsock->sent = 0;
}
-static int nbd_set_size(struct nbd_device *nbd, loff_t bytesize, loff_t blksize)
+static int nbd_set_size(struct nbd_device *nbd, loff_t bytesize, loff_t blksize,
+ bool freeze)
{
struct queue_limits lim;
int error;
@@ -371,7 +372,13 @@ static int nbd_set_size(struct nbd_device *nbd, loff_t bytesize, loff_t blksize)
lim.logical_block_size = blksize;
lim.physical_block_size = blksize;
- error = queue_limits_commit_update_frozen(nbd->disk->queue, &lim);
+
+ if (freeze)
+ error = queue_limits_commit_update_frozen(nbd->disk->queue,
+ &lim);
+ else
+ error = queue_limits_commit_update(nbd->disk->queue, &lim);
+
if (error)
return error;
@@ -1563,7 +1570,7 @@ static int nbd_start_device(struct nbd_device *nbd)
args->index = i;
queue_work(nbd->recv_workq, &args->work);
}
- return nbd_set_size(nbd, config->bytesize, nbd_blksize(config));
+ return nbd_set_size(nbd, config->bytesize, nbd_blksize(config), false);
}
static int nbd_start_device_ioctl(struct nbd_device *nbd)
@@ -1631,13 +1638,13 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
case NBD_SET_SOCK:
return nbd_add_socket(nbd, arg, false);
case NBD_SET_BLKSIZE:
- return nbd_set_size(nbd, config->bytesize, arg);
+ return nbd_set_size(nbd, config->bytesize, arg, true);
case NBD_SET_SIZE:
- return nbd_set_size(nbd, arg, nbd_blksize(config));
+ return nbd_set_size(nbd, arg, nbd_blksize(config), true);
case NBD_SET_SIZE_BLOCKS:
if (check_shl_overflow(arg, config->blksize_bits, &bytesize))
return -EINVAL;
- return nbd_set_size(nbd, bytesize, nbd_blksize(config));
+ return nbd_set_size(nbd, bytesize, nbd_blksize(config), true);
case NBD_SET_TIMEOUT:
nbd_set_cmd_timeout(nbd, arg);
return 0;
@@ -2092,7 +2099,7 @@ static int nbd_genl_size_set(struct genl_info *info, struct nbd_device *nbd)
bsize = nla_get_u64(info->attrs[NBD_ATTR_BLOCK_SIZE_BYTES]);
if (bytes != config->bytesize || bsize != nbd_blksize(config))
- return nbd_set_size(nbd, bytes, bsize);
+ return nbd_set_size(nbd, bytes, bsize, true);
return 0;
}
--
2.52.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v4 5/7] nbd: factor out a nbd_genl_foreach_sock
2026-07-27 7:47 [PATCH v4 0/7] nbd: eliminate queue freeze/unfreeze overhead in connection setup Yang Erkun
` (3 preceding siblings ...)
2026-07-27 7:47 ` [PATCH v4 4/7] nbd: skip queue freeze when setting size at device startup Yang Erkun
@ 2026-07-27 7:47 ` Yang Erkun
2026-07-27 7:47 ` [PATCH v4 6/7] nbd: remove queue freeze for newly created nbd from netlink path Yang Erkun
2026-07-27 7:47 ` [PATCH v4 7/7] nbd: add nr_hw_queues module parameter for pre-created devices Yang Erkun
6 siblings, 0 replies; 8+ messages in thread
From: Yang Erkun @ 2026-07-27 7:47 UTC (permalink / raw)
To: josef, axboe, hch, yukuai
Cc: yi.zhang, chengzhihao1, echo.chenlin, leo.lilong, wangkefeng.wang,
huawei.libin, leijitang, linux-block, nbd
The walk for NBD_ATTR_SOCKETS in nbd_genl_connect and
nbd_genl_disconnect seems duplicated, factor out nbd_genl_foreach_sock,
and this will be use in latter patch.
Signed-off-by: Yang Erkun <yangerkun@huawei.com>
---
drivers/block/nbd.c | 135 +++++++++++++++++++++++---------------------
1 file changed, 71 insertions(+), 64 deletions(-)
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index e2fb787248c8..4b9f0349877e 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -2103,6 +2103,59 @@ 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, int 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, int 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;
@@ -2222,36 +2275,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],
@@ -2340,6 +2366,20 @@ static int nbd_genl_disconnect(struct sk_buff *skb, struct genl_info *info)
return 0;
}
+static int nbd_genl_reconnect_sock_cb(struct nbd_device *nbd, int fd)
+{
+ int ret = nbd_reconnect_socket(nbd, fd);
+
+ if (!ret) {
+ dev_info(nbd_to_dev(nbd), "reconnected socket\n");
+ return 0;
+ }
+
+ if (ret == -ENOSPC)
+ return 1;
+ return ret;
+}
+
static int nbd_genl_reconfigure(struct sk_buff *skb, struct genl_info *info)
{
struct nbd_device *nbd = NULL;
@@ -2436,40 +2476,7 @@ 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);
out:
mutex_unlock(&nbd->config_lock);
nbd_config_put(nbd);
--
2.52.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v4 6/7] nbd: remove queue freeze for newly created nbd from netlink path
2026-07-27 7:47 [PATCH v4 0/7] nbd: eliminate queue freeze/unfreeze overhead in connection setup Yang Erkun
` (4 preceding siblings ...)
2026-07-27 7:47 ` [PATCH v4 5/7] nbd: factor out a nbd_genl_foreach_sock Yang Erkun
@ 2026-07-27 7:47 ` Yang Erkun
2026-07-27 7:47 ` [PATCH v4 7/7] nbd: add nr_hw_queues module parameter for pre-created devices Yang Erkun
6 siblings, 0 replies; 8+ messages in thread
From: Yang Erkun @ 2026-07-27 7:47 UTC (permalink / raw)
To: josef, axboe, hch, yukuai
Cc: yi.zhang, chengzhihao1, echo.chenlin, leo.lilong, wangkefeng.wang,
huawei.libin, leijitang, linux-block, nbd
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.
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 4b9f0349877e..2bb98e41b99b 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -1937,7 +1937,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 queue_limits lim = {
.max_hw_sectors = 65536,
@@ -1954,7 +1955,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);
@@ -2208,7 +2209,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);
@@ -2729,7 +2734,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
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v4 7/7] nbd: add nr_hw_queues module parameter for pre-created devices
2026-07-27 7:47 [PATCH v4 0/7] nbd: eliminate queue freeze/unfreeze overhead in connection setup Yang Erkun
` (5 preceding siblings ...)
2026-07-27 7:47 ` [PATCH v4 6/7] nbd: remove queue freeze for newly created nbd from netlink path Yang Erkun
@ 2026-07-27 7:47 ` Yang Erkun
6 siblings, 0 replies; 8+ messages in thread
From: Yang Erkun @ 2026-07-27 7:47 UTC (permalink / raw)
To: josef, axboe, hch, yukuai
Cc: yi.zhang, chengzhihao1, echo.chenlin, leo.lilong, wangkefeng.wang,
huawei.libin, leijitang, linux-block, nbd
The function blk_mq_update_nr_hw_queues in nbd_start_device may causes a
queue freeze. The previous commit addressed this issue for newly created
nbd device via setting the expected nr_hw_queues in nbd_dev_add.
However, when reusing an old inactive nbd device, the queue freeze can
still occur when old nbd->tag_set->nr_hw_queues 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, we can add a
module parameter to allow changing the default nr_hw_queues. This way,
users who know their expected number of connections can 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
Signed-off-by: Yang Erkun <yangerkun@huawei.com>
---
drivers/block/nbd.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index 2bb98e41b99b..1d8cdc5713eb 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -166,6 +166,7 @@ static struct dentry *nbd_dbg_dir;
static unsigned int nbds_max = 16;
static int max_part = 16;
+static int nr_hw_queues = 1;
static int part_shift;
static int nbd_dev_dbg_init(struct nbd_device *nbd);
@@ -2733,8 +2734,10 @@ static int __init nbd_init(void)
}
nbd_dbg_init();
+ if (nr_hw_queues < 1)
+ nr_hw_queues = 1;
for (i = 0; i < nbds_max; i++)
- nbd_dev_add(i, 1, 1);
+ nbd_dev_add(i, 1, nr_hw_queues);
return 0;
}
@@ -2795,3 +2798,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(nr_hw_queues, int, 0444);
+MODULE_PARM_DESC(nr_hw_queues,
+"number of hardware queues for devices pre-created at module load (default: 1). ");
--
2.52.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
end of thread, other threads:[~2026-07-27 7:56 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-27 7:47 [PATCH v4 0/7] nbd: eliminate queue freeze/unfreeze overhead in connection setup Yang Erkun
2026-07-27 7:47 ` [PATCH v4 1/7] nbd: simplify find_fallback() by removing redundant logic Yang Erkun
2026-07-27 7:47 ` [PATCH v4 2/7] nbd: disallow NBD_SET_SOCK on an active device Yang Erkun
2026-07-27 7:47 ` [PATCH v4 3/7] nbd: remove queue freeze in nbd_add_socket Yang Erkun
2026-07-27 7:47 ` [PATCH v4 4/7] nbd: skip queue freeze when setting size at device startup Yang Erkun
2026-07-27 7:47 ` [PATCH v4 5/7] nbd: factor out a nbd_genl_foreach_sock Yang Erkun
2026-07-27 7:47 ` [PATCH v4 6/7] nbd: remove queue freeze for newly created nbd from netlink path Yang Erkun
2026-07-27 7:47 ` [PATCH v4 7/7] nbd: add nr_hw_queues module parameter for pre-created devices Yang Erkun
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox