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 <hsiang...@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


Reply via email to