From: Maxim Date: Wed, 23 Jan 2019 23:12:36 +0000 (-0800) Subject: Adding a helper to format command to enable the user to specify desired block size... X-Git-Tag: v1.8~39^2 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=dcbfb6ecd058785fcaa2fd9be7df5f819655eb09;p=users%2Fsagi%2Fnvme-cli.git Adding a helper to format command to enable the user to specify desired block size and have nvme-cli determine the correct LBAF and add format helper to nvme-create-ns command --- diff --git a/Documentation/nvme-create-ns.txt b/Documentation/nvme-create-ns.txt index db583ead..dcf00a3f 100644 --- a/Documentation/nvme-create-ns.txt +++ b/Documentation/nvme-create-ns.txt @@ -13,6 +13,7 @@ SYNOPSIS [--flbas= | -f ] [--dps= | -d ] [--nmic= | -m ] + [--block-size= | -b ] DESCRIPTION ----------- @@ -36,6 +37,7 @@ OPTIONS -f:: --flbas:: The namespace formatted logical block size setting. + Conflicts with --block-size argument. -d:: --dps:: @@ -45,6 +47,12 @@ OPTIONS --nmic:: Namespace multipath and sharing capabilities. +-b:: +--block-size:: + Target block size the new namespace should be formatted as. Potential FLBAS + values will be values will be scanned and the lowest numbered will be + selected for the create-ns operation. Conflicts with --flbas argument. + EXAMPLES -------- diff --git a/Documentation/nvme-format.txt b/Documentation/nvme-format.txt index 85977417..ce95760c 100644 --- a/Documentation/nvme-format.txt +++ b/Documentation/nvme-format.txt @@ -10,6 +10,7 @@ SYNOPSIS [verse] 'nvme format' [--namespace-id= | -n ] [--lbaf= | -l ] + [--block-size=] [--ses= | -s ] [--pil= | -p ] [--pi= | -i ] @@ -48,7 +49,15 @@ OPTIONS --lbaf=:: LBA Format: This field specifies the LBA format to apply to the NVM media. This corresponds to the LBA formats indicated in the - Identify Namespace command. Defaults to 0. + Identify Namespace command. Conflicts with --block-size argument. + Defaults to 0. + +-b :: +--block-size=:: + Block Size: This field is used to specify the target block size to + format to. Potential lbaf values will be scanned and the lowest + numbered will be selected for the format operation. Conflicts with + --lbaf argument. -s :: --ses=:: diff --git a/nvme.c b/nvme.c index e0f3a88e..e6d0d9e5 100644 --- a/nvme.c +++ b/nvme.c @@ -1163,8 +1163,10 @@ static int create_ns(int argc, char **argv, struct command *cmd, struct plugin * const char *flbas = "FLBA size"; const char *dps = "data protection capabilities"; const char *nmic = "multipath and sharing capabilities"; + const char *bs = "target block size"; - int err = 0, fd; + int err = 0, fd, i; + struct nvme_id_ns ns; __u32 nsid; struct config { @@ -1173,17 +1175,21 @@ static int create_ns(int argc, char **argv, struct command *cmd, struct plugin * __u8 flbas; __u8 dps; __u8 nmic; + __u64 bs; }; struct config cfg = { + .flbas = 0xff, + .bs = 0x00, }; const struct argconfig_commandline_options command_line_options[] = { - {"nsze", 's', "NUM", CFG_LONG_SUFFIX, &cfg.nsze, required_argument, nsze}, - {"ncap", 'c', "NUM", CFG_LONG_SUFFIX, &cfg.ncap, required_argument, ncap}, - {"flbas", 'f', "NUM", CFG_BYTE, &cfg.flbas, required_argument, flbas}, - {"dps", 'd', "NUM", CFG_BYTE, &cfg.dps, required_argument, dps}, - {"nmic", 'm', "NUM", CFG_BYTE, &cfg.nmic, required_argument, nmic}, + {"nsze", 's', "NUM", CFG_LONG_SUFFIX, &cfg.nsze, required_argument, nsze}, + {"ncap", 'c', "NUM", CFG_LONG_SUFFIX, &cfg.ncap, required_argument, ncap}, + {"flbas", 'f', "NUM", CFG_BYTE, &cfg.flbas, required_argument, flbas}, + {"dps", 'd', "NUM", CFG_BYTE, &cfg.dps, required_argument, dps}, + {"nmic", 'm', "NUM", CFG_BYTE, &cfg.nmic, required_argument, nmic}, + {"block-size", 'b', "NUM", CFG_LONG_SUFFIX, &cfg.bs, required_argument, bs}, {NULL} }; @@ -1191,6 +1197,46 @@ static int create_ns(int argc, char **argv, struct command *cmd, struct plugin * if (fd < 0) return fd; + if (cfg.flbas != 0xFF && cfg.bs != 0x00) { + fprintf(stderr, + "Invalid specification fo both FLBAS and Block Size, please specify only one\n"); + return EINVAL; + } + + if (cfg.flbas == 0xFF) { + fprintf(stderr, + "FLBAS corresponding to block size %llu not found\n", cfg.bs); + fprintf(stderr, + "Please correct block size, or specify FLBAS directly\n"); + return EINVAL; + } + + if (cfg.bs) { + if ((cfg.bs & (~cfg.bs + 1)) != cfg.bs) { + fprintf(stderr, + "Invalid value for block size (%llu). Block size must be a power of two\n", cfg.bs); + return EINVAL; + } + err = nvme_identify_ns(fd, NVME_NSID_ALL, 0, &ns); + if (err) { + if (err < 0) + perror("identify-namespace"); + else + fprintf(stderr, + "NVME Admin command error:%s(%x)\n", + nvme_status_to_string(err), err); + return err; + } + for (i = 0; i < 16; ++i) { + if ((1 << ns.lbaf[i].ds) == cfg.bs && ns.lbaf[i].ms == 0) { + cfg.flbas = i; + break; + } + } + + } + + err = nvme_ns_create(fd, cfg.nsze, cfg.ncap, cfg.flbas, cfg.dps, cfg.nmic, &nsid); if (!err) printf("%s: Success, created nsid:%d\n", cmd->name, nsid); @@ -2993,9 +3039,11 @@ static int format(int argc, char **argv, struct command *cmd, struct plugin *plu const char *ms = "[0-1]: extended format off/on"; const char *reset = "Automatically reset the controller after successful format"; const char *timeout = "timeout value, in milliseconds"; + const char *bs = "target block size"; struct nvme_id_ns ns; - int err, fd; + int err, fd, i; __u8 prev_lbaf = 0; + __u8 lbads = 0; struct config { __u32 namespace_id; @@ -3005,6 +3053,7 @@ static int format(int argc, char **argv, struct command *cmd, struct plugin *plu __u8 pi; __u8 pil; __u8 ms; + __u64 bs; int reset; }; @@ -3015,6 +3064,7 @@ static int format(int argc, char **argv, struct command *cmd, struct plugin *plu .ses = 0, .pi = 0, .reset = 0, + .bs = 0, }; const struct argconfig_commandline_options command_line_options[] = { @@ -3026,13 +3076,26 @@ static int format(int argc, char **argv, struct command *cmd, struct plugin *plu {"pil", 'p', "NUM", CFG_BYTE, &cfg.pil, required_argument, pil}, {"ms", 'm', "NUM", CFG_BYTE, &cfg.ms, required_argument, ms}, {"reset", 'r', "", CFG_NONE, &cfg.reset, no_argument, reset}, + {"block-size", 'b', "NUM", CFG_LONG_SUFFIX, &cfg.bs, required_argument, bs}, {NULL} }; fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg)); if (fd < 0) return fd; - + + if (cfg.lbaf != 0xff && cfg.bs !=0) { + fprintf(stderr, + "Invalid specification of both LBAF and Block Size, please specify only one\n"); + return EINVAL; + } + if (cfg.bs) { + if ((cfg.bs & ( ~cfg.bs + 1)) != cfg.bs) { + fprintf(stderr, + "Invalid value for block size (%llu). Block size must be a power of two\n", cfg.bs); + return EINVAL; + } + } if (S_ISBLK(nvme_stat.st_mode)) { cfg.namespace_id = get_nsid(fd); if (cfg.namespace_id == 0) { @@ -3053,6 +3116,27 @@ static int format(int argc, char **argv, struct command *cmd, struct plugin *plu } prev_lbaf = ns.flbas & 0xf; } + if (cfg.bs) { + __u64 bs = cfg.bs; + bs = bs >> 1; + while (bs) { + ++lbads; + bs = bs >> 1; + } + for (i=0; i<16; ++i) { + if (ns.lbaf[i].ds == lbads && ns.lbaf[i].ms == 0) { + cfg.lbaf = i; + break; + } + } + if (cfg.lbaf == 0xff) { + fprintf(stderr, + "LBAF corresponding to block size %llu (LBAF %u) not found\n", cfg.bs, lbads); + fprintf(stderr, + "Please correct block size, or specify LBAF directly\n"); + return EINVAL; + } + } if (cfg.lbaf == 0xff) cfg.lbaf = prev_lbaf;