Users can use the new `--disconnect` option to forcibly disconnect or abort NBD block devices.
Signed-off-by: Gao Xiang <[email protected]> --- 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
