int connect(const char *desc, int argc, char **argv) { char argstr[BUF_SIZE]; int instance, ret; const struct argconfig_commandline_options command_line_options[] = { {"transport", 't', "LIST", CFG_STRING, &cfg.transport, required_argument, "transport type" }, {"nqn", 'n', "LIST", CFG_STRING, &cfg.nqn, required_argument, "nqn name" }, {"traddr", 'a', "LIST", CFG_STRING, &cfg.traddr, required_argument, "transport address" }, {"trsvcid", 's', "LIST", CFG_STRING, &cfg.trsvcid, required_argument, "transport service id (e.g. IP port)" }, {"host-traddr", 'w', "LIST", CFG_STRING, &cfg.host_traddr, required_argument, "host traddr (e.g. FC WWN's)" }, {"hostnqn", 'q', "LIST", CFG_STRING, &cfg.hostnqn, required_argument, "user-defined hostnqn" }, {"nr-io-queues", 'i', "LIST", CFG_STRING, &cfg.nr_io_queues, required_argument, "number of io queues to use (default is core count)" }, {"keep-alive-tmo", 'k', "LIST", CFG_STRING, &cfg.keep_alive_tmo, required_argument, "keep alive timeout period in seconds" }, {"reconnect-delay", 'c', "LIST", CFG_STRING, &cfg.reconnect_delay, required_argument, "reconnect timeout period in seconds" }, {NULL}, }; argconfig_parse(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); ret = build_options(argstr, BUF_SIZE); if (ret) return ret; if (!cfg.nqn) { fprintf(stderr, "need a -n argument\n"); return -EINVAL; } instance = add_ctrl(argstr); if (instance < 0) return instance; return 0; }
static int discover_from_conf_file(const char *desc, char *argstr, const struct argconfig_commandline_options *opts, bool connect) { FILE *f; char line[256], *ptr, *args, **argv; int argc, err, ret = 0; f = fopen(PATH_NVMF_DISC, "r"); if (f == NULL) { fprintf(stderr, "No discover params given and no %s conf\n", PATH_NVMF_DISC); return -EINVAL; } while (fgets(line, sizeof(line), f) != NULL) { if (line[0] == '#' || line[0] == '\n') continue; args = strdup(line); if (!args) { fprintf(stderr, "failed to strdup args\n"); ret = -ENOMEM; goto out; } argv = calloc(MAX_DISC_ARGS, BUF_SIZE); if (!argv) { fprintf(stderr, "failed to allocate argv vector\n"); free(args); ret = -ENOMEM; goto out; } argc = 0; argv[argc++] = "discover"; while ((ptr = strsep(&args, " =\n")) != NULL) argv[argc++] = ptr; argconfig_parse(argc, argv, desc, opts, &cfg, sizeof(cfg)); err = build_options(argstr, BUF_SIZE); if (err) { ret = err; continue; } err = do_discover(argstr, connect); if (err) { ret = err; continue; } free(args); free(argv); } out: fclose(f); return ret; }
int discover(const char *desc, int argc, char **argv, bool connect) { char argstr[BUF_SIZE]; int ret; const struct argconfig_commandline_options command_line_options[] = { {"transport", 't', "LIST", CFG_STRING, &cfg.transport, required_argument, "transport type" }, {"traddr", 'a', "LIST", CFG_STRING, &cfg.traddr, required_argument, "transport address" }, {"trsvcid", 's', "LIST", CFG_STRING, &cfg.trsvcid, required_argument, "transport service id (e.g. IP port)" }, {"host-traddr", 'w', "LIST", CFG_STRING, &cfg.host_traddr, required_argument, "host traddr (e.g. FC WWN's)" }, {"hostnqn", 'q', "LIST", CFG_STRING, &cfg.hostnqn, required_argument, "user-defined hostnqn (if default not used)" }, {"raw", 'r', "LIST", CFG_STRING, &cfg.raw, required_argument, "raw output file" }, {NULL}, }; argconfig_parse(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); cfg.nqn = NVME_DISC_SUBSYS_NAME; if (!cfg.transport && !cfg.traddr) { return discover_from_conf_file(desc, argstr, command_line_options, connect); } else { ret = build_options(argstr, BUF_SIZE); if (ret) return ret; return do_discover(argstr, connect); } }
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}, {NULL}, }; 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 < 0) fprintf(stderr, "Failed to disconnect by NQN: %s\n", cfg.nqn); else printf("NQN:%s disconnected %d controller(s)\n", cfg.nqn, ret); } 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; }
static int lnvm_init(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "Initialize LightNVM device. A LightNVM/Open-Channel SSD"\ " must have a media manager associated before it can "\ " be exposed to the user. The default is to initialize" " the general media manager on top of the device.\n\n" "Example:" " lnvm-init -d nvme0n1"; const char *devname = "identifier of desired device. e.g. nvme0n1."; const char *mmtype = "media manager to initialize on top of device. Default: gennvm."; int ret; struct config { char *devname; char *mmtype; }; struct config cfg = { .devname = "", .mmtype = "gennvm", }; const struct argconfig_commandline_options command_line_options[] = { {"device-name", 'd', "DEVICE", CFG_STRING, &cfg.devname, required_argument, devname}, {"mediamgr-name", 'm', "MM", CFG_STRING, &cfg.mmtype, required_argument, mmtype}, {NULL} }; ret = argconfig_parse(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); if (ret < 0) return ret; if (!strlen(cfg.devname)) { fprintf(stderr, "device name missing %d\n", (int)strlen(cfg.devname)); return -EINVAL; } return lnvm_do_init(cfg.devname, cfg.mmtype); } static int lnvm_list(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "List all devices registered with LightNVM."; int ret; const struct argconfig_commandline_options command_line_options[] = { {NULL} }; ret = argconfig_parse(argc, argv, desc, command_line_options, NULL, 0); if (ret < 0) return ret; return lnvm_do_list_devices(); } static int lnvm_info(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "Show general information and registered target types with LightNVM"; int ret; const struct argconfig_commandline_options command_line_options[] = { {NULL} }; ret = argconfig_parse(argc, argv, desc, command_line_options, NULL, 0); if (ret < 0) return ret; return lnvm_do_info(); } static int lnvm_id_ns(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "Send an Identify Geometry command to the "\ "given LightNVM device, returns properties of the specified "\ "namespace in either human-readable or binary format."; const char *raw_binary = "show infos in binary format"; const char *human_readable = "show infos in readable format"; const char *namespace_id = "identifier of desired namespace. default: 1"; unsigned int fd, flags = 0; struct config { __u32 namespace_id; int raw_binary; int human_readable; }; struct config cfg = { .namespace_id = 1, }; const struct argconfig_commandline_options command_line_options[] = { {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id, required_argument, namespace_id}, {"raw-binary", 'b', "FLAG", CFG_NONE, &cfg.raw_binary, no_argument, raw_binary}, {"human-readable", 'H', "FLAG", CFG_NONE, &cfg.human_readable, no_argument, human_readable}, {NULL} }; fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); if (fd < 0) return fd; if (cfg.human_readable) flags |= HUMAN; else if (cfg.raw_binary) flags |= RAW; return lnvm_do_id_ns(fd, cfg.namespace_id, flags); } static int lnvm_create_tgt(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "Instantiate a target on top of a LightNVM enabled device."; const char *devname = "identifier of desired device. e.g. nvme0n1."; const char *tgtname = "target name of the device to initialize. e.g. target0."; const char *tgttype = "identifier of target type. e.g. pblk."; const char *lun_begin = "Define begin of luns to use for target."; const char *lun_end = "Define set of luns to use for target."; const char *over_prov = "Define over-provision percentage for target."; const char *flag_factory = "Create target in factory mode"; int flags; int ret; struct config { char *devname; char *tgtname; char *tgttype; __u32 lun_begin; __u32 lun_end; __u32 over_prov; /* flags */ __u32 factory; }; struct config cfg = { .devname = "", .tgtname = "", .tgttype = "", .lun_begin = -1, .lun_end = -1, .over_prov = -1, .factory = 0, }; const struct argconfig_commandline_options command_line_options[] = { {"device-name", 'd', "DEVICE", CFG_STRING, &cfg.devname, required_argument, devname}, {"target-name", 'n', "TARGET", CFG_STRING, &cfg.tgtname, required_argument, tgtname}, {"target-type", 't', "TARGETTYPE", CFG_STRING, &cfg.tgttype, required_argument, tgttype}, {"lun-begin", 'b', "NUM", CFG_POSITIVE, &cfg.lun_begin, required_argument, lun_begin}, {"lun-end", 'e', "NUM", CFG_POSITIVE, &cfg.lun_end, required_argument, lun_end}, {"over-prov", 'o', "NUM", CFG_POSITIVE, &cfg.over_prov, required_argument, over_prov}, {"factory", 'f', "FLAG", CFG_NONE, &cfg.factory, no_argument, flag_factory}, {NULL} }; ret = argconfig_parse(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); if (ret < 0) return ret; if (!strlen(cfg.devname)) { fprintf(stderr, "device name missing %d\n", (int)strlen(cfg.devname)); return -EINVAL; } if (!strlen(cfg.tgtname)) { fprintf(stderr, "target name missing\n"); return -EINVAL; } if (!strlen(cfg.tgttype)) { fprintf(stderr, "target type missing\n"); return -EINVAL; } flags = 0; if (cfg.factory) flags |= NVM_TARGET_FACTORY; return lnvm_do_create_tgt(cfg.devname, cfg.tgtname, cfg.tgttype, cfg.lun_begin, cfg.lun_end, cfg.over_prov, flags); } static int lnvm_remove_tgt(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "Remove an initialized LightNVM target."; const char *tgtname = "target name of the device to initialize. e.g. target0."; int ret; struct config { char *tgtname; }; struct config cfg = { .tgtname = "", }; const struct argconfig_commandline_options command_line_options[] = { {"target-name", 'n', "TARGET", CFG_STRING, &cfg.tgtname, required_argument, tgtname}, {NULL} }; ret = argconfig_parse(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); if (ret < 0) return ret; if (!strlen(cfg.tgtname)) { fprintf(stderr, "target name missing\n"); return -EINVAL; } return lnvm_do_remove_tgt(cfg.tgtname); } static int lnvm_factory_init(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "Factory initialize a LightNVM enabled device."; const char *devname = "identifier of desired device. e.g. nvme0n1."; const char *erase_only_marked = "only erase marked blocks. default: all blocks."; const char *host_marks = "remove host side blocks list. default: keep."; const char *bb_marks = "remove grown bad blocks list. default: keep"; int ret; struct config { char *devname; int erase_only_marked; int clear_host_marks; int clear_bb_marks; }; struct config cfg = { .devname = "", }; const struct argconfig_commandline_options command_line_options[] = { {"device-name", 'd', "DEVICE", CFG_STRING, &cfg.devname, required_argument, devname}, {"erase-only-marked", 'e', "", CFG_NONE, &cfg.erase_only_marked, no_argument, erase_only_marked}, {"clear-host-side-blks", 's', "", CFG_NONE, &cfg.clear_host_marks, no_argument, host_marks}, {"clear-bb-blks", 'b', "", CFG_NONE, &cfg.clear_bb_marks, no_argument, bb_marks}, {NULL} }; ret = argconfig_parse(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); if (ret < 0) return ret; if (!strlen(cfg.devname)) { fprintf(stderr, "device name missing %d\n", (int)strlen(cfg.devname)); return -EINVAL; } return lnvm_do_factory_init(cfg.devname, cfg.erase_only_marked, cfg.clear_host_marks, cfg.clear_bb_marks); } static int lnvm_get_bbtbl(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "Receive bad block table from a LightNVM compatible"\ " device."; const char *namespace = "(optional) desired namespace"; const char *ch = "channel identifier"; const char *lun = "lun identifier (within a channel)"; const char *raw_binary = "show infos in binary format"; unsigned int fd, flags = 0; struct config { __u32 namespace_id; __u16 lunid; __u16 chid; int raw_binary; }; struct config cfg = { .namespace_id = 1, .lunid = 0, .chid = 0, }; const struct argconfig_commandline_options command_line_options[] = { {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id, required_argument, namespace}, {"channel-id", 'c', "", CFG_SHORT, &cfg.chid, required_argument, ch}, {"lun-id", 'l', "", CFG_SHORT, &cfg.lunid, required_argument, lun}, {"raw-binary", 'b', "FLAG", CFG_NONE, &cfg.raw_binary, no_argument, raw_binary}, {NULL} }; fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); if (cfg.raw_binary) flags |= RAW; return lnvm_do_get_bbtbl(fd, cfg.namespace_id, cfg.lunid, cfg.chid, flags); } static int lnvm_set_bbtbl(int argc, char **argv, struct command *cmd, struct plugin *plugin) { const char *desc = "Update bad block table on a LightNVM compatible"\ " device."; const char *namespace = "(optional) desired namespace"; const char *ch = "channel identifier"; const char *lun = "lun identifier (within a channel)"; const char *pln = "plane identifier (within a lun)"; const char *blk = "block identifier (within a plane)"; const char *value = "value to update the specific block to."; int fd; struct config { __u32 namespace_id; __u16 lunid; __u16 chid; __u16 plnid; __u16 blkid; __u16 value; }; struct config cfg = { .namespace_id = 1, .lunid = 0, .chid = 0, .plnid = 0, .blkid = 0, .value = 0, }; const struct argconfig_commandline_options command_line_options[] = { {"namespace-id", 'n', "NUM", CFG_POSITIVE, &cfg.namespace_id, required_argument, namespace}, {"channel-id", 'c', "NUM", CFG_SHORT, &cfg.chid, required_argument, ch}, {"lun-id", 'l', "NUM", CFG_SHORT, &cfg.lunid, required_argument, lun}, {"plane-id", 'p', "NUM", CFG_SHORT, &cfg.plnid, required_argument, pln}, {"block-id", 'b', "NUM", CFG_SHORT, &cfg.blkid, required_argument, blk}, {"value", 'v', "NUM", CFG_SHORT, &cfg.value, required_argument, value}, {NULL} }; fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); printf("Updating: Ch.: %u LUN: %u Plane: %u Block: %u -> %u\n", cfg.chid, cfg.lunid, cfg.plnid, cfg.blkid, cfg.value); return lnvm_do_set_bbtbl(fd, cfg.namespace_id, cfg.chid, cfg.lunid, cfg.plnid, cfg.blkid, cfg.value); }