]> www.infradead.org Git - users/hch/nvme-cli.git/commitdiff
Implement disconnect command
authorMing Lin <ming.l@ssi.samsung.com>
Tue, 7 Jun 2016 15:19:26 +0000 (17:19 +0200)
committerKeith Busch <keith.busch@intel.com>
Tue, 7 Jun 2016 19:08:04 +0000 (13:08 -0600)
Example usage:

Disconnect by NQN,
nvme disconnect -n nqn.testiqn

or by device name,
nvme disconnect -d nvme0

Signed-off-by: Ming Lin <ming.l@ssi.samsung.com>
Tested-by: Armen Baloyan <armenx.baloyan@intel.com>
Tested-by: Sagi Grimberg <sagi@grimberg.me>
Reviewed-by: Jay Freyensee <james.p.freyensee@intel.com>
fabrics.c
fabrics.h
nvme.c

index 84dde2b2f793f56d8446c3838b87add301826dcb..0a60258ea0457293818dfaad40660107aa6a5bec 100644 (file)
--- a/fabrics.c
+++ b/fabrics.c
@@ -46,6 +46,7 @@ struct config {
        char *traddr;
        char *trsvcid;
        char *raw;
+       char *device;
 } cfg = { 0 };
 
 #define BUF_SIZE               4096
@@ -452,3 +453,116 @@ int connect(const char *desc, int argc, char **argv)
                return instance;
        return 0;
 }
+
+static int disconnect_subsys(struct udev_enumerate *enumerate, char *nqn)
+{
+       struct udev_list_entry *list_entry;
+       const char *subsysnqn;
+       char *sysfs_path;
+       int ret = 1;
+
+       udev_list_entry_foreach(list_entry, udev_enumerate_get_list_entry(enumerate)) {
+               struct udev_device *device;
+
+               device = udev_device_new_from_syspath(udev_enumerate_get_udev(enumerate),
+                                               udev_list_entry_get_name(list_entry));
+               if (device != NULL) {
+                       subsysnqn = udev_device_get_sysattr_value(device, "subsysnqn");
+                       if (subsysnqn && !strcmp(subsysnqn, nqn)) {
+                               if (asprintf(&sysfs_path, "%s/delete_controller",
+                                               udev_device_get_syspath(device)) < 0) {
+                                       ret = errno;
+                                       udev_device_unref(device);
+                                       break;
+                               }
+                               udev_device_unref(device);
+                               ret = remove_ctrl_by_path(sysfs_path);
+                               free(sysfs_path);
+                               break;
+                       }
+                       udev_device_unref(device);
+               }
+       }
+
+       return ret;
+}
+
+static int disconnect_by_nqn(char *nqn)
+{
+       struct udev *udev;
+       struct udev_enumerate *udev_enumerate;
+       int ret;
+
+       if (strlen(nqn) > NVMF_NQN_SIZE) {
+               ret = -EINVAL;
+               goto exit;
+       }
+
+       udev = udev_new();
+       if (!udev) {
+               fprintf(stderr, "failed to create udev\n");
+               ret = -ENOMEM;
+               goto exit;
+       }
+
+       udev_enumerate = udev_enumerate_new(udev);
+       if (udev_enumerate == NULL) {
+               ret = -ENOMEM;
+               goto free_udev;
+       }
+
+       udev_enumerate_add_match_subsystem(udev_enumerate, "nvme");
+       udev_enumerate_scan_devices(udev_enumerate);
+       ret = disconnect_subsys(udev_enumerate, nqn);
+       udev_enumerate_unref(udev_enumerate);
+
+free_udev:
+       udev_unref(udev);
+exit:
+       return ret;
+}
+
+static int disconnect_by_device(char *device)
+{
+       int instance;
+       int ret;
+
+       ret = sscanf(device, "nvme%d", &instance);
+       if (ret < 0)
+               return ret;
+
+       return remove_ctrl(instance);
+}
+
+int disconnect(const char *desc, int argc, char **argv)
+{
+       const char *nqn = "nqn name";
+       const char *device = "nvme device";
+       int ret = 0;
+
+       const struct argconfig_commandline_options command_line_options[] = {
+               {"nqn", 'n', "LIST", CFG_STRING, &cfg.nqn, required_argument, nqn},
+               {"device", 'd', "LIST", CFG_STRING, &cfg.device, required_argument, device},
+               {0},
+       };
+
+       argconfig_parse(argc, argv, desc, command_line_options, &cfg, sizeof(cfg));
+       if (!cfg.nqn && !cfg.device) {
+               fprintf(stderr, "need a -n or -d argument\n");
+               return -EINVAL;
+       }
+
+       if (cfg.nqn) {
+               ret = disconnect_by_nqn(cfg.nqn);
+               if (ret)
+                       fprintf(stderr, "Failed to disconnect by NQN: %s\n", cfg.nqn);
+       }
+
+       if (cfg.device) {
+               ret = disconnect_by_device(cfg.device);
+               if (ret)
+                       fprintf(stderr, "Failed to disconnect by device name: %s\n", cfg.device);
+       }
+
+       return ret;
+}
index 43072a1566493fd7adb9249212300513eb914de4..7e3eb1939d68ecee01f16289e0d1efae4913d851 100644 (file)
--- a/fabrics.h
+++ b/fabrics.h
@@ -3,5 +3,6 @@
 
 extern int discover(const char *desc, int argc, char **argv);
 extern int connect(const char *desc, int argc, char **argv);
+extern int disconnect(const char *desc, int argc, char **argv);
 
 #endif
diff --git a/nvme.c b/nvme.c
index 902d84b06bf2ad600f1fc60d7a38a283b1ead64c..e4030226fdca115c30466d66c88af0176df7ec38 100644 (file)
--- a/nvme.c
+++ b/nvme.c
@@ -116,6 +116,7 @@ static const char nvme_version_string[] = NVME_VERSION;
        ENTRY(LNVM_BBTBL_SET, "lnvm-diag-set-bbtbl", "Update bad block table", lnvm_set_bbtbl) \
        ENTRY(DISCOVER, "discover", "Discover NVMeoF subsystems", discover_cmd) \
        ENTRY(CONNECT, "connect", "Connect to NVMeoF subsystem", connect_cmd) \
+       ENTRY(DISCONNECT, "disconnect", "Disconnect from NVMeoF subsystem", disconnect_cmd) \
        ENTRY(VERSION, "version", "Shows the program version", version) \
        ENTRY(HELP, "help", "Display this help", help)
 
@@ -2853,6 +2854,12 @@ static int connect_cmd(int argc, char **argv)
        return connect(desc, argc, argv);
 }
 
+static int disconnect_cmd(int argc, char **argv)
+{
+       const char *desc = "Disconnect from NVMeoF subsystem";
+       return disconnect(desc, argc, argv);
+}
+
 static void usage()
 {
        printf("usage: nvme <command> [<device>] [<args>]\n");