From: Benreese0 <5884008+benreese0@users.noreply.github.com> Date: Tue, 8 Jan 2019 22:59:19 +0000 (-0800) Subject: nvme: Adding a block size selector to format X-Git-Tag: v1.7~4^2~1 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=8e8aad36d1bd81f7dceb0f94330739a3cf3f8112;p=users%2Fsagi%2Fnvme-cli.git nvme: Adding a block size selector to format Provide format option to allow the user to specify desired block size and have nvme-cli determine the correct LBAF. Signed-off-by: Benjamin Reese [changelog, minor formatting, shift lbaf instead of bs, reference id_ns only if we read it] Signed-off-by: Keith Busch --- diff --git a/Documentation/nvme-format.txt b/Documentation/nvme-format.txt index 85977417..93ee813d 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..86d8e839 100644 --- a/nvme.c +++ b/nvme.c @@ -2993,9 +2993,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 +3007,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 +3018,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,6 +3030,7 @@ 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} }; @@ -3033,6 +3038,19 @@ static int format(int argc, char **argv, struct command *cmd, struct plugin *plu 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), 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) { @@ -3052,6 +3070,24 @@ static int format(int argc, char **argv, struct command *cmd, struct plugin *plu return err; } prev_lbaf = ns.flbas & 0xf; + + if (cfg.bs) { + for (i = 0; i < 16; ++i) { + if ((1ULL << ns.lbaf[i].ds) == cfg.bs && + 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;