[PATCH] erofs-utils: mount: enable autoclear for NBD devices

Gao Xiang hsiangkao at linux.alibaba.com
Wed Sep 3 18:23:41 AEST 2025


Enable NBD_CFLAG_DISCONNECT_ON_CLOSE to allow `umount(2)` to unmount
the filesystem and disconnect NBD devices in a single operation.

Signed-off-by: Gao Xiang <hsiangkao at linux.alibaba.com>
---
 lib/backends/nbd.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
 lib/liberofs_nbd.h |  2 ++
 mount/main.c       | 16 +++++++++++++++-
 3 files changed, 63 insertions(+), 1 deletion(-)

diff --git a/lib/backends/nbd.c b/lib/backends/nbd.c
index 682fc7b..b9535dc 100644
--- a/lib/backends/nbd.c
+++ b/lib/backends/nbd.c
@@ -466,6 +466,46 @@ err_out:
 	close(sv[1]);
 	return err;
 }
+
+int erofs_nbd_nl_reconfigure(int index, const char *identifier,
+			     bool autoclear)
+{
+	struct nl_sock *socket;
+	struct nl_msg *msg;
+	int err, driver_id;
+	unsigned int cflags;
+
+	socket = erofs_nbd_get_nl_sock(&driver_id);
+	if (IS_ERR(socket))
+		return PTR_ERR(socket);
+
+	msg = nlmsg_alloc();
+	if (!msg) {
+		erofs_err("Couldn't allocate netlink message");
+		err = -ENOMEM;
+		goto err_nls_free;
+	}
+
+	err = -EINVAL;
+	genlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, driver_id, 0, 0,
+		    NBD_CMD_RECONFIGURE, 0);
+	NLA_PUT_U32(msg, NBD_ATTR_INDEX, index);
+	if (identifier)
+		NLA_PUT_STRING(msg, NBD_ATTR_BACKEND_IDENTIFIER, identifier);
+
+	cflags = (autoclear ? NBD_CFLAG_DISCONNECT_ON_CLOSE : 0);
+	NLA_PUT_U64(msg, NBD_ATTR_CLIENT_FLAGS, cflags);
+
+	err = nl_send_sync(socket, msg);
+	nl_socket_free(socket);
+	return err;
+
+nla_put_failure:
+	nlmsg_free(msg);
+err_nls_free:
+	nl_socket_free(socket);
+	return err;
+}
 #else
 int erofs_nbd_nl_connect(int *index, int blkbits, u64 blocks,
 			 const char *identifier)
@@ -477,6 +517,12 @@ int erofs_nbd_nl_reconnect(int index, const char *identifier)
 {
 	return -EOPNOTSUPP;
 }
+
+int erofs_nbd_nl_reconfigure(int index, const char *identifier,
+			     bool autoclear)
+{
+	return -EOPNOTSUPP;
+}
 #endif
 
 int erofs_nbd_do_it(int nbdfd)
diff --git a/lib/liberofs_nbd.h b/lib/liberofs_nbd.h
index 049c318..260605a 100644
--- a/lib/liberofs_nbd.h
+++ b/lib/liberofs_nbd.h
@@ -47,4 +47,6 @@ int erofs_nbd_disconnect(int nbdfd);
 int erofs_nbd_nl_connect(int *index, int blkbits, u64 blocks,
 			 const char *identifier);
 int erofs_nbd_nl_reconnect(int index, const char *identifier);
+int erofs_nbd_nl_reconfigure(int index, const char *identifier,
+			     bool autoclear);
 #endif
diff --git a/mount/main.c b/mount/main.c
index 139b532..a270f0a 100644
--- a/mount/main.c
+++ b/mount/main.c
@@ -544,7 +544,8 @@ static int erofsmount_nbd(const char *source, const char *mountpoint,
 			  const char *fstype, int flags,
 			  const char *options)
 {
-	char nbdpath[32];
+	bool is_netlink = false;
+	char nbdpath[32], *id;
 	int num, nbdfd;
 	pid_t pid = 0;
 	long err;
@@ -575,6 +576,7 @@ static int erofsmount_nbd(const char *source, const char *mountpoint,
 	} else {
 		num = err;
 		(void)snprintf(nbdpath, sizeof(nbdpath), "/dev/nbd%d", num);
+		is_netlink = true;
 	}
 
 	while (1) {
@@ -591,6 +593,18 @@ static int erofsmount_nbd(const char *source, const char *mountpoint,
 		err = mount(nbdpath, mountpoint, fstype, flags, options);
 		if (err < 0)
 			err = -errno;
+
+		if (!err && is_netlink) {
+			id = erofs_nbd_get_identifier(num);
+			if (id == ERR_PTR(-ENOENT))
+				id = NULL;
+
+			err = IS_ERR(id) ? PTR_ERR(id) :
+				erofs_nbd_nl_reconfigure(num, id, true);
+			if (err)
+				erofs_warn("failed to turn on autoclear for nbd%d: %s",
+					   num, erofs_strerror(err));
+		}
 	}
 	return err;
 }
-- 
2.43.5



More information about the Linux-erofs mailing list