All of lore.kernel.org
 help / color / mirror / Atom feed
* [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.