From: Yun Zhou <yun.zhou@windriver.com>
To: <josef@toxicpanda.com>, <axboe@kernel.dk>
Cc: <linux-block@vger.kernel.org>, <nbd@other.debian.org>,
<linux-kernel@vger.kernel.org>, <yun.zhou@windriver.com>
Subject: [PATCH 2/2] nbd: detect management process exit via netlink notifier
Date: Tue, 7 Jul 2026 18:27:24 +0800 [thread overview]
Message-ID: <20260707102724.3838638-2-yun.zhou@windriver.com> (raw)
In-Reply-To: <20260707102724.3838638-1-yun.zhou@windriver.com>
Register a netlink notifier to detect when the NBD management process
closes its netlink socket (on exit or crash).
Without this, in-flight I/O waits for socket timeout while udevd holds
disk->open_mutex for partition scanning, blocking poweroff's
sync_bdevs() and causing a hung task during shutdown.
Fix this by tracking the management process's netlink portid and, on
NETLINK_URELEASE, calling sock_shutdown() on all devices it owns.
This fails in-flight I/O immediately so shutdown can proceed.
Signed-off-by: Yun Zhou <yun.zhou@windriver.com>
---
drivers/block/nbd.c | 59 +++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 59 insertions(+)
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index 43aa4121f0c5..3bf88f7b3535 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -45,6 +45,7 @@
#include <linux/nbd.h>
#include <linux/nbd-netlink.h>
#include <net/genetlink.h>
+#include <linux/netlink.h>
#define CREATE_TRACE_POINTS
#include <trace/events/nbd.h>
@@ -131,6 +132,7 @@ struct nbd_device {
unsigned long flags;
pid_t pid; /* pid of nbd-client, if attached */
+ u32 owner_portid; /* netlink portid of management process */
char *backend;
};
@@ -2331,12 +2333,19 @@ static int nbd_genl_connect(struct sk_buff *skb, struct genl_info *info)
}
set_bit(NBD_RT_HAS_BACKEND_FILE, &config->runtime_flags);
+ /*
+ * Set owner before starting device so that the netlink notifier
+ * can clean up if the management process exits during setup.
+ */
+ nbd->owner_portid = info->snd_portid;
ret = nbd_start_device(nbd);
out:
if (!ret) {
set_bit(NBD_RT_HAS_CONFIG_REF, &config->runtime_flags);
refcount_inc(&nbd->config_refs);
nbd_connect_reply(info, nbd->index);
+ } else {
+ nbd->owner_portid = 0;
}
mutex_unlock(&nbd->config_lock);
@@ -2541,6 +2550,12 @@ static int nbd_genl_reconfigure(struct sk_buff *skb, struct genl_info *info)
}
}
out:
+ /*
+ * Update owner to the reconfiguring process so the notifier
+ * tracks the correct management process.
+ */
+ if (!ret)
+ nbd->owner_portid = info->snd_portid;
mutex_unlock(&nbd->config_lock);
nbd_config_put(nbd);
nbd_put(nbd);
@@ -2743,6 +2758,48 @@ static void nbd_dead_link_work(struct work_struct *work)
kfree(args);
}
+/*
+ * Detect when the management process (the one that issued NBD_CMD_CONNECT)
+ * closes its netlink socket (e.g., exit or crash). When this happens,
+ * no one can reconnect, so mark all its devices as disconnected to stop
+ * waiting for reconnect and fail pending I/O promptly.
+ */
+static int nbd_netlink_event(struct notifier_block *this,
+ unsigned long event, void *ptr)
+{
+ struct netlink_notify *n = ptr;
+ struct nbd_device *nbd;
+ int id;
+
+ if (event != NETLINK_URELEASE || n->protocol != NETLINK_GENERIC)
+ return NOTIFY_DONE;
+
+ mutex_lock(&nbd_index_mutex);
+ idr_for_each_entry(&nbd_index_idr, nbd, id) {
+ if (nbd->owner_portid != n->portid)
+ continue;
+
+ nbd->owner_portid = 0;
+ if (refcount_inc_not_zero(&nbd->config_refs)) {
+ /*
+ * Shut down all sockets. sock_shutdown() holds
+ * tx_lock for each socket, preventing races with
+ * reconnect, and sets NBD_RT_DISCONNECTED so that
+ * nbd_reconnect_possible() fails immediately.
+ */
+ sock_shutdown(nbd);
+ nbd_config_put(nbd);
+ }
+ }
+ mutex_unlock(&nbd_index_mutex);
+
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block nbd_netlink_notifier = {
+ .notifier_call = nbd_netlink_event,
+};
+
static int __init nbd_init(void)
{
int i;
@@ -2789,6 +2846,7 @@ static int __init nbd_init(void)
unregister_blkdev(NBD_MAJOR, "nbd");
return -EINVAL;
}
+ netlink_register_notifier(&nbd_netlink_notifier);
nbd_dbg_init();
for (i = 0; i < nbds_max; i++)
@@ -2818,6 +2876,7 @@ static void __exit nbd_cleanup(void)
* for the completion of netlink commands.
*/
genl_unregister_family(&nbd_genl_family);
+ netlink_unregister_notifier(&nbd_netlink_notifier);
nbd_dbg_close();
--
2.43.0
prev parent reply other threads:[~2026-07-07 10:28 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-07 10:27 [PATCH 1/2] nbd: replace wait_for_reconnect with non-blocking retry Yun Zhou
2026-07-07 10:27 ` Yun Zhou [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260707102724.3838638-2-yun.zhou@windriver.com \
--to=yun.zhou@windriver.com \
--cc=axboe@kernel.dk \
--cc=josef@toxicpanda.com \
--cc=linux-block@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=nbd@other.debian.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox