* [PATCH 1/2] erofs-utils: mount: add support for netlink disconnection
@ 2025-12-22 7:46 Gao Xiang
2025-12-22 7:46 ` [PATCH 2/2] erofs-utils: mount: add `--disconnect` command Gao Xiang
0 siblings, 1 reply; 4+ messages in thread
From: Gao Xiang @ 2025-12-22 7:46 UTC (permalink / raw)
To: linux-erofs; +Cc: Gao Xiang
One significant benefit of using the netlink interface is that it
avoids opening NBD device files since openers can hang in the kernel
in some cases (it's hard to resolve with traditional ioctl interfaces,
but I don't want to explain more kernel internals here.)
In fact, using the NBD netlink interface is now always recommended.
Signed-off-by: Gao Xiang <hsiangkao@linux.alibaba.com>
---
lib/backends/nbd.c | 37 +++++++++++++++++++++++++++++++++++++
lib/liberofs_nbd.h | 1 +
mount/main.c | 18 +++++++++++++++---
3 files changed, 53 insertions(+), 3 deletions(-)
diff --git a/lib/backends/nbd.c b/lib/backends/nbd.c
index 2e54814af6ca..77c4f609d5de 100644
--- a/lib/backends/nbd.c
+++ b/lib/backends/nbd.c
@@ -515,6 +515,39 @@ err_nls_free:
nl_socket_free(socket);
return err;
}
+
+int erofs_nbd_nl_disconnect(int index)
+{
+ struct nl_sock *socket;
+ struct nl_msg *msg;
+ int driver_id, err;
+
+ 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_DISCONNECT, 0);
+ NLA_PUT_U32(msg, NBD_ATTR_INDEX, index);
+ err = nl_send_sync(socket, msg);
+ if (err < 0)
+ erofs_err("Failed to disconnect device %d, check dmesg", err);
+ nl_socket_free(socket);
+ return err;
+nla_put_failure:
+ erofs_err("Failed to create netlink message");
+ 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)
@@ -532,6 +565,10 @@ int erofs_nbd_nl_reconfigure(int index, const char *identifier,
{
return -EOPNOTSUPP;
}
+int erofs_nbd_nl_disconnect(int index)
+{
+ return -EOPNOTSUPP;
+}
#endif
int erofs_nbd_do_it(int nbdfd)
diff --git a/lib/liberofs_nbd.h b/lib/liberofs_nbd.h
index 260605ae201a..78c8af511bec 100644
--- a/lib/liberofs_nbd.h
+++ b/lib/liberofs_nbd.h
@@ -49,4 +49,5 @@ int erofs_nbd_nl_connect(int *index, int blkbits, u64 blocks,
int erofs_nbd_nl_reconnect(int index, const char *identifier);
int erofs_nbd_nl_reconfigure(int index, const char *identifier,
bool autoclear);
+int erofs_nbd_nl_disconnect(int index);
#endif
diff --git a/mount/main.c b/mount/main.c
index ed6bcdcfe26d..b3b2e0fc33e0 100644
--- a/mount/main.c
+++ b/mount/main.c
@@ -1306,9 +1306,9 @@ out_err:
int erofsmount_umount(char *target)
{
char *device = NULL, *mountpoint = NULL;
+ int err, fd, nbdnum;
struct stat st;
FILE *mounts;
- int err, fd;
size_t n;
char *s;
bool isblk;
@@ -1376,6 +1376,14 @@ int erofsmount_umount(char *target)
goto err_out;
}
+ if (isblk && !mountpoint &&
+ S_ISBLK(st.st_mode) && major(st.st_rdev) == EROFS_NBD_MAJOR) {
+ nbdnum = erofs_nbd_get_index_from_minor(minor(st.st_rdev));
+ err = erofs_nbd_nl_disconnect(nbdnum);
+ if (err != -EOPNOTSUPP)
+ return err;
+ }
+
/* Avoid TOCTOU issue with NBD_CFLAG_DISCONNECT_ON_CLOSE */
fd = open(isblk ? target : device, O_RDWR);
if (fd < 0) {
@@ -1393,8 +1401,12 @@ int erofsmount_umount(char *target)
err = fstat(fd, &st);
if (err < 0)
err = -errno;
- else if (S_ISBLK(st.st_mode) && major(st.st_rdev) == EROFS_NBD_MAJOR)
- err = erofs_nbd_disconnect(fd);
+ else if (S_ISBLK(st.st_mode) && major(st.st_rdev) == EROFS_NBD_MAJOR) {
+ nbdnum = erofs_nbd_get_index_from_minor(minor(st.st_rdev));
+ err = erofs_nbd_nl_disconnect(nbdnum);
+ if (err == -EOPNOTSUPP)
+ err = erofs_nbd_disconnect(fd);
+ }
close(fd);
err_out:
free(device);
--
2.43.5
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 2/2] erofs-utils: mount: add `--disconnect` command
2025-12-22 7:46 [PATCH 1/2] erofs-utils: mount: add support for netlink disconnection Gao Xiang
@ 2025-12-22 7:46 ` Gao Xiang
2025-12-23 1:33 ` zhaoyifan (H)
0 siblings, 1 reply; 4+ messages in thread
From: Gao Xiang @ 2025-12-22 7:46 UTC (permalink / raw)
To: linux-erofs; +Cc: Gao Xiang
Users can use the new `--disconnect` option to forcibly disconnect or
abort NBD block devices.
Signed-off-by: Gao Xiang <hsiangkao@linux.alibaba.com>
---
mount/main.c | 55 +++++++++++++++++++++++++++++++++++++++++++++-------
1 file changed, 48 insertions(+), 7 deletions(-)
diff --git a/mount/main.c b/mount/main.c
index b3b2e0fc33e0..693dba2dc78d 100644
--- a/mount/main.c
+++ b/mount/main.c
@@ -51,6 +51,7 @@ enum erofs_backend_drv {
enum erofsmount_mode {
EROFSMOUNT_MODE_MOUNT,
EROFSMOUNT_MODE_UMOUNT,
+ EROFSMOUNT_MODE_DISCONNECT,
EROFSMOUNT_MODE_REATTACH,
};
@@ -88,13 +89,14 @@ static void usage(int argc, char **argv)
"Manage EROFS filesystem.\n"
"\n"
"General options:\n"
- " -V, --version print the version number of mount.erofs and exit\n"
- " -h, --help display this help and exit\n"
- " -o options comma-separated list of mount options\n"
- " -t type[.subtype] filesystem type (and optional subtype)\n"
- " subtypes: fuse, local, nbd\n"
- " -u unmount the filesystem\n"
- " --reattach reattach to an existing NBD device\n"
+ " -V, --version print the version number of mount.erofs and exit\n"
+ " -h, --help display this help and exit\n"
+ " -o options comma-separated list of mount options\n"
+ " -t type[.subtype] filesystem type (and optional subtype)\n"
+ " subtypes: fuse, local, nbd\n"
+ " -u unmount the filesystem\n"
+ " --disconnect abort an existing NBD device forcibly\n"
+ " --reattach reattach to an existing NBD device\n"
#ifdef OCIEROFS_ENABLED
"\n"
"OCI-specific options (with -o):\n"
@@ -271,6 +273,7 @@ static int erofsmount_parse_options(int argc, char **argv)
{"help", no_argument, 0, 'h'},
{"version", no_argument, 0, 'V'},
{"reattach", no_argument, 0, 512},
+ {"disconnect", no_argument, 0, 513},
{0, 0, 0, 0},
};
char *dot;
@@ -316,6 +319,9 @@ static int erofsmount_parse_options(int argc, char **argv)
case 512:
mountcfg.mountmode = EROFSMOUNT_MODE_REATTACH;
break;
+ case 513:
+ mountcfg.mountmode = EROFSMOUNT_MODE_DISCONNECT;
+ break;
default:
return -EINVAL;
}
@@ -1415,6 +1421,33 @@ err_out:
return err < 0 ? err : 0;
}
+static int erofsmount_disconnect(const char *target)
+{
+ int nbdnum, err, fd;
+ struct stat st;
+
+ err = lstat(target, &st);
+ if (err < 0)
+ return -errno;
+
+ if (!S_ISBLK(st.st_mode) || major(st.st_rdev) != EROFS_NBD_MAJOR)
+ return -ENOTBLK;
+
+ nbdnum = erofs_nbd_get_index_from_minor(minor(st.st_rdev));
+ err = erofs_nbd_nl_disconnect(nbdnum);
+ if (err == -EOPNOTSUPP) {
+ fd = open(target, O_RDWR);
+ if (fd < 0) {
+ err = -errno;
+ goto err_out;
+ }
+ err = erofs_nbd_disconnect(fd);
+ close(fd);
+ }
+err_out:
+ return err < 0 ? err : 0;
+}
+
int main(int argc, char *argv[])
{
int err;
@@ -1443,6 +1476,14 @@ int main(int argc, char *argv[])
return err ? EXIT_FAILURE : EXIT_SUCCESS;
}
+ if (mountcfg.mountmode == EROFSMOUNT_MODE_DISCONNECT) {
+ err = erofsmount_disconnect(mountcfg.target);
+ if (err < 0)
+ fprintf(stderr, "Failed to disconnect %s: %s\n",
+ mountcfg.target, erofs_strerror(err));
+ return err ? EXIT_FAILURE : EXIT_SUCCESS;
+ }
+
if (mountcfg.backend == EROFSFUSE) {
err = erofsmount_fuse(mountcfg.device, mountcfg.target,
mountcfg.fstype, mountcfg.full_options);
--
2.43.5
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH 2/2] erofs-utils: mount: add `--disconnect` command
2025-12-22 7:46 ` [PATCH 2/2] erofs-utils: mount: add `--disconnect` command Gao Xiang
@ 2025-12-23 1:33 ` zhaoyifan (H)
2025-12-23 2:09 ` Gao Xiang
0 siblings, 1 reply; 4+ messages in thread
From: zhaoyifan (H) @ 2025-12-23 1:33 UTC (permalink / raw)
To: Gao Xiang, linux-erofs
On 2025/12/22 15:46, Gao Xiang wrote:
> Users can use the new `--disconnect` option to forcibly disconnect or
> abort NBD block devices.
>
> Signed-off-by: Gao Xiang <hsiangkao@linux.alibaba.com>
Hi Xiang,
It seems
mount.erofs -u /dev/nbdX
serving the same purpose of --disconnect? Why do we need a separate
--disconnect subcommand?
Thanks,
Yifan
> ---
> mount/main.c | 55 +++++++++++++++++++++++++++++++++++++++++++++-------
> 1 file changed, 48 insertions(+), 7 deletions(-)
>
> diff --git a/mount/main.c b/mount/main.c
> index b3b2e0fc33e0..693dba2dc78d 100644
> --- a/mount/main.c
> +++ b/mount/main.c
> @@ -51,6 +51,7 @@ enum erofs_backend_drv {
> enum erofsmount_mode {
> EROFSMOUNT_MODE_MOUNT,
> EROFSMOUNT_MODE_UMOUNT,
> + EROFSMOUNT_MODE_DISCONNECT,
> EROFSMOUNT_MODE_REATTACH,
> };
>
> @@ -88,13 +89,14 @@ static void usage(int argc, char **argv)
> "Manage EROFS filesystem.\n"
> "\n"
> "General options:\n"
> - " -V, --version print the version number of mount.erofs and exit\n"
> - " -h, --help display this help and exit\n"
> - " -o options comma-separated list of mount options\n"
> - " -t type[.subtype] filesystem type (and optional subtype)\n"
> - " subtypes: fuse, local, nbd\n"
> - " -u unmount the filesystem\n"
> - " --reattach reattach to an existing NBD device\n"
> + " -V, --version print the version number of mount.erofs and exit\n"
> + " -h, --help display this help and exit\n"
> + " -o options comma-separated list of mount options\n"
> + " -t type[.subtype] filesystem type (and optional subtype)\n"
> + " subtypes: fuse, local, nbd\n"
> + " -u unmount the filesystem\n"
> + " --disconnect abort an existing NBD device forcibly\n"
> + " --reattach reattach to an existing NBD device\n"
> #ifdef OCIEROFS_ENABLED
> "\n"
> "OCI-specific options (with -o):\n"
> @@ -271,6 +273,7 @@ static int erofsmount_parse_options(int argc, char **argv)
> {"help", no_argument, 0, 'h'},
> {"version", no_argument, 0, 'V'},
> {"reattach", no_argument, 0, 512},
> + {"disconnect", no_argument, 0, 513},
> {0, 0, 0, 0},
> };
> char *dot;
> @@ -316,6 +319,9 @@ static int erofsmount_parse_options(int argc, char **argv)
> case 512:
> mountcfg.mountmode = EROFSMOUNT_MODE_REATTACH;
> break;
> + case 513:
> + mountcfg.mountmode = EROFSMOUNT_MODE_DISCONNECT;
> + break;
> default:
> return -EINVAL;
> }
> @@ -1415,6 +1421,33 @@ err_out:
> return err < 0 ? err : 0;
> }
>
> +static int erofsmount_disconnect(const char *target)
> +{
> + int nbdnum, err, fd;
> + struct stat st;
> +
> + err = lstat(target, &st);
> + if (err < 0)
> + return -errno;
> +
> + if (!S_ISBLK(st.st_mode) || major(st.st_rdev) != EROFS_NBD_MAJOR)
> + return -ENOTBLK;
> +
> + nbdnum = erofs_nbd_get_index_from_minor(minor(st.st_rdev));
> + err = erofs_nbd_nl_disconnect(nbdnum);
> + if (err == -EOPNOTSUPP) {
> + fd = open(target, O_RDWR);
> + if (fd < 0) {
> + err = -errno;
> + goto err_out;
> + }
> + err = erofs_nbd_disconnect(fd);
> + close(fd);
> + }
> +err_out:
> + return err < 0 ? err : 0;
> +}
> +
> int main(int argc, char *argv[])
> {
> int err;
> @@ -1443,6 +1476,14 @@ int main(int argc, char *argv[])
> return err ? EXIT_FAILURE : EXIT_SUCCESS;
> }
>
> + if (mountcfg.mountmode == EROFSMOUNT_MODE_DISCONNECT) {
> + err = erofsmount_disconnect(mountcfg.target);
> + if (err < 0)
> + fprintf(stderr, "Failed to disconnect %s: %s\n",
> + mountcfg.target, erofs_strerror(err));
> + return err ? EXIT_FAILURE : EXIT_SUCCESS;
> + }
> +
> if (mountcfg.backend == EROFSFUSE) {
> err = erofsmount_fuse(mountcfg.device, mountcfg.target,
> mountcfg.fstype, mountcfg.full_options);
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH 2/2] erofs-utils: mount: add `--disconnect` command
2025-12-23 1:33 ` zhaoyifan (H)
@ 2025-12-23 2:09 ` Gao Xiang
0 siblings, 0 replies; 4+ messages in thread
From: Gao Xiang @ 2025-12-23 2:09 UTC (permalink / raw)
To: zhaoyifan (H), linux-erofs
On 2025/12/23 09:33, zhaoyifan (H) wrote:
>
> On 2025/12/22 15:46, Gao Xiang wrote:
>> Users can use the new `--disconnect` option to forcibly disconnect or
>> abort NBD block devices.
>>
>> Signed-off-by: Gao Xiang <hsiangkao@linux.alibaba.com>
>
> Hi Xiang,
>
> It seems
>
> mount.erofs -u /dev/nbdX
>
> serving the same purpose of --disconnect? Why do we need a separate --disconnect subcommand?
It won't handle unmount, just forcibly send
the disconnect command. It's up to users
to run umount instead.
Thanks,
Gao Xiang
>
>
> Thanks,
>
> Yifan
>
>> ---
>> mount/main.c | 55 +++++++++++++++++++++++++++++++++++++++++++++-------
>> 1 file changed, 48 insertions(+), 7 deletions(-)
>>
>> diff --git a/mount/main.c b/mount/main.c
>> index b3b2e0fc33e0..693dba2dc78d 100644
>> --- a/mount/main.c
>> +++ b/mount/main.c
>> @@ -51,6 +51,7 @@ enum erofs_backend_drv {
>> enum erofsmount_mode {
>> EROFSMOUNT_MODE_MOUNT,
>> EROFSMOUNT_MODE_UMOUNT,
>> + EROFSMOUNT_MODE_DISCONNECT,
>> EROFSMOUNT_MODE_REATTACH,
>> };
>> @@ -88,13 +89,14 @@ static void usage(int argc, char **argv)
>> "Manage EROFS filesystem.\n"
>> "\n"
>> "General options:\n"
>> - " -V, --version print the version number of mount.erofs and exit\n"
>> - " -h, --help display this help and exit\n"
>> - " -o options comma-separated list of mount options\n"
>> - " -t type[.subtype] filesystem type (and optional subtype)\n"
>> - " subtypes: fuse, local, nbd\n"
>> - " -u unmount the filesystem\n"
>> - " --reattach reattach to an existing NBD device\n"
>> + " -V, --version print the version number of mount.erofs and exit\n"
>> + " -h, --help display this help and exit\n"
>> + " -o options comma-separated list of mount options\n"
>> + " -t type[.subtype] filesystem type (and optional subtype)\n"
>> + " subtypes: fuse, local, nbd\n"
>> + " -u unmount the filesystem\n"
>> + " --disconnect abort an existing NBD device forcibly\n"
>> + " --reattach reattach to an existing NBD device\n"
>> #ifdef OCIEROFS_ENABLED
>> "\n"
>> "OCI-specific options (with -o):\n"
>> @@ -271,6 +273,7 @@ static int erofsmount_parse_options(int argc, char **argv)
>> {"help", no_argument, 0, 'h'},
>> {"version", no_argument, 0, 'V'},
>> {"reattach", no_argument, 0, 512},
>> + {"disconnect", no_argument, 0, 513},
>> {0, 0, 0, 0},
>> };
>> char *dot;
>> @@ -316,6 +319,9 @@ static int erofsmount_parse_options(int argc, char **argv)
>> case 512:
>> mountcfg.mountmode = EROFSMOUNT_MODE_REATTACH;
>> break;
>> + case 513:
>> + mountcfg.mountmode = EROFSMOUNT_MODE_DISCONNECT;
>> + break;
>> default:
>> return -EINVAL;
>> }
>> @@ -1415,6 +1421,33 @@ err_out:
>> return err < 0 ? err : 0;
>> }
>> +static int erofsmount_disconnect(const char *target)
>> +{
>> + int nbdnum, err, fd;
>> + struct stat st;
>> +
>> + err = lstat(target, &st);
>> + if (err < 0)
>> + return -errno;
>> +
>> + if (!S_ISBLK(st.st_mode) || major(st.st_rdev) != EROFS_NBD_MAJOR)
>> + return -ENOTBLK;
>> +
>> + nbdnum = erofs_nbd_get_index_from_minor(minor(st.st_rdev));
>> + err = erofs_nbd_nl_disconnect(nbdnum);
>> + if (err == -EOPNOTSUPP) {
>> + fd = open(target, O_RDWR);
>> + if (fd < 0) {
>> + err = -errno;
>> + goto err_out;
>> + }
>> + err = erofs_nbd_disconnect(fd);
>> + close(fd);
>> + }
>> +err_out:
>> + return err < 0 ? err : 0;
>> +}
>> +
>> int main(int argc, char *argv[])
>> {
>> int err;
>> @@ -1443,6 +1476,14 @@ int main(int argc, char *argv[])
>> return err ? EXIT_FAILURE : EXIT_SUCCESS;
>> }
>> + if (mountcfg.mountmode == EROFSMOUNT_MODE_DISCONNECT) {
>> + err = erofsmount_disconnect(mountcfg.target);
>> + if (err < 0)
>> + fprintf(stderr, "Failed to disconnect %s: %s\n",
>> + mountcfg.target, erofs_strerror(err));
>> + return err ? EXIT_FAILURE : EXIT_SUCCESS;
>> + }
>> +
>> if (mountcfg.backend == EROFSFUSE) {
>> err = erofsmount_fuse(mountcfg.device, mountcfg.target,
>> mountcfg.fstype, mountcfg.full_options);
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2025-12-23 2:10 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-12-22 7:46 [PATCH 1/2] erofs-utils: mount: add support for netlink disconnection Gao Xiang
2025-12-22 7:46 ` [PATCH 2/2] erofs-utils: mount: add `--disconnect` command Gao Xiang
2025-12-23 1:33 ` zhaoyifan (H)
2025-12-23 2:09 ` Gao Xiang
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.