From cd5c5d7bc4020d4b22ba973da9bce4ee69a30de7 Mon Sep 17 00:00:00 2001 From: Nate Thornton Date: Fri, 26 Sep 2025 07:54:11 -0700 Subject: [PATCH 1/3] nvme: add --block-size option to io commands to bypass identify commands. When specified, the --block-size is used as the logical block size in bytes, and the --metadata-size is used as the metadata size in bytes. Signed-off-by: Nate Thornton --- nvme.c | 74 +++++++++++++++++++++++++++++++++------------------------- 1 file changed, 42 insertions(+), 32 deletions(-) diff --git a/nvme.c b/nvme.c index 3f1e286b51..051e239a5d 100644 --- a/nvme.c +++ b/nvme.c @@ -8188,6 +8188,8 @@ static int submit_io(int opcode, char *command, const char *desc, int argc, char __u16 ms; const char *start_block_addr = "64-bit addr of first block to access"; + const char *block_size = "if specified, logical block size in bytes;\n" + "discovered by identify namespace otherwise"; const char *data_size = "size of data in bytes"; const char *metadata_size = "size of metadata in bytes"; const char *data = "data file"; @@ -8205,6 +8207,7 @@ static int submit_io(int opcode, char *command, const char *desc, int argc, char __u32 namespace_id; __u64 start_block; __u16 block_count; + __u16 block_size; __u64 data_size; __u64 metadata_size; __u64 ref_tag; @@ -8229,6 +8232,7 @@ static int submit_io(int opcode, char *command, const char *desc, int argc, char .namespace_id = 0, .start_block = 0, .block_count = 0, + .block_size = 0, .data_size = 0, .metadata_size = 0, .ref_tag = 0, @@ -8253,6 +8257,7 @@ static int submit_io(int opcode, char *command, const char *desc, int argc, char OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id_desired), OPT_SUFFIX("start-block", 's', &cfg.start_block, start_block_addr), OPT_SHRT("block-count", 'c', &cfg.block_count, block_count), + OPT_SHRT("block-size", 'b', &cfg.block_size, block_size), OPT_SUFFIX("data-size", 'z', &cfg.data_size, data_size), OPT_SUFFIX("metadata-size", 'y', &cfg.metadata_size, metadata_size), OPT_SUFFIX("ref-tag", 'r', &cfg.ref_tag, ref_tag), @@ -8353,40 +8358,48 @@ static int submit_io(int opcode, char *command, const char *desc, int argc, char return -EINVAL; } - ns = nvme_alloc(sizeof(*ns)); - if (!ns) - return -ENOMEM; + if (cfg.block_size) { + logical_block_size = cfg.block_size; + ms = cfg.metadata_size; + } else { + ns = nvme_alloc(sizeof(*ns)); + if (!ns) + return -ENOMEM; - err = nvme_cli_identify_ns(dev, cfg.namespace_id, ns); - if (err > 0) { - nvme_show_status(err); - return err; - } else if (err < 0) { - nvme_show_error("identify namespace: %s", nvme_strerror(errno)); - return err; - } + err = nvme_cli_identify_ns(dev, cfg.namespace_id, ns); + if (err > 0) { + nvme_show_status(err); + return err; + } else if (err < 0) { + nvme_show_error("identify namespace: %s", nvme_strerror(errno)); + return err; + } - nvme_id_ns_flbas_to_lbaf_inuse(ns->flbas, &lba_index); - logical_block_size = 1 << ns->lbaf[lba_index].ds; - ms = le16_to_cpu(ns->lbaf[lba_index].ms); + nvme_id_ns_flbas_to_lbaf_inuse(ns->flbas, &lba_index); + logical_block_size = 1 << ns->lbaf[lba_index].ds; + ms = le16_to_cpu(ns->lbaf[lba_index].ms); - nvm_ns = nvme_alloc(sizeof(*nvm_ns)); - if (!nvm_ns) - return -ENOMEM; + nvm_ns = nvme_alloc(sizeof(*nvm_ns)); + if (!nvm_ns) + return -ENOMEM; - err = nvme_identify_ns_csi(dev_fd(dev), cfg.namespace_id, 0, NVME_CSI_NVM, nvm_ns); - if (!err) - get_pif_sts(ns, nvm_ns, &pif, &sts); + err = nvme_identify_ns_csi(dev_fd(dev), cfg.namespace_id, 0, NVME_CSI_NVM, nvm_ns); + if (!err) + get_pif_sts(ns, nvm_ns, &pif, &sts); + + pi_size = (pif == NVME_NVM_PIF_16B_GUARD) ? 8 : 16; + if (NVME_FLBAS_META_EXT(ns->flbas)) { + /* + * No meta data is transferred for PRACT=1 and MD=PI size: + * 5.2.2.1 Protection Information and Write Commands + * 5.2.2.2 Protection Information and Read Commands + */ + if (!((cfg.prinfo & 0x8) != 0 && ms == pi_size)) + logical_block_size += ms; + } - pi_size = (pif == NVME_NVM_PIF_16B_GUARD) ? 8 : 16; - if (NVME_FLBAS_META_EXT(ns->flbas)) { - /* - * No meta data is transferred for PRACT=1 and MD=PI size: - * 5.2.2.1 Protection Information and Write Commands - * 5.2.2.2 Protection Information and Read Commands - */ - if (!((cfg.prinfo & 0x8) != 0 && ms == pi_size)) - logical_block_size += ms; + if (invalid_tags(cfg.storage_tag, cfg.ref_tag, sts, pif)) + return -EINVAL; } buffer_size = ((long long)cfg.block_count + 1) * logical_block_size; @@ -8426,9 +8439,6 @@ static int submit_io(int opcode, char *command, const char *desc, int argc, char memset(mbuffer, 0, mbuffer_size); } - if (invalid_tags(cfg.storage_tag, cfg.ref_tag, sts, pif)) - return -EINVAL; - if (opcode & 1) { err = read(dfd, (void *)buffer, cfg.data_size); if (err < 0) { From 8f043c56712e04942917cac5a35f83334de90608 Mon Sep 17 00:00:00 2001 From: Nate Thornton Date: Fri, 26 Sep 2025 08:07:24 -0700 Subject: [PATCH 2/3] completions: add --block-size option to io commands to bypass identify commands. Adds `--block-size=` and `-b` to various completions Signed-off-by: Nate Thornton --- completions/_nvme | 6 ++++++ completions/bash-nvme-completion.sh | 6 +++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/completions/_nvme b/completions/_nvme index 88617a622d..a0ddbfc71b 100644 --- a/completions/_nvme +++ b/completions/_nvme @@ -2039,6 +2039,8 @@ _nvme () { -s':alias of --start-block' --block-count=':number of logical blocks on device to compare to local data' -c':alias of --block-count' + --block-size=':if specified, logical block size in bytes (if not included, the logical block size is found through identify namespace)' + -b':alias of --block-size' --metadata-size=':number of bytes of metadata to compare' -y':alias of --metadata-size' --data-size=':size of local data buffer in bytes' @@ -2074,6 +2076,8 @@ _nvme () { -s':alias of --start-block' --block-count=':number of logical blocks on device to read' -c':alias of --block-count' + --block-size=':if specified, logical block size in bytes (if not included, the logical block size is found through identify namespace)' + -b':alias of --block-size' --data-size=':size of data to be read' -z':alias of --data-size' --metadata-size=':size of metadata to be read' @@ -2111,6 +2115,8 @@ _nvme () { -s':alias of --start-block' --block-count=':number of logical blocks on device to write' -c':alias of --block-count' + --block-size=':if specified, logical block size in bytes (if not included, the logical block size is found through identify namespace)' + -b':alias of --block-size' --data-size=':size of data to be written' -z':alias of --data-size' --metadata-size=':size of metadata to be written' diff --git a/completions/bash-nvme-completion.sh b/completions/bash-nvme-completion.sh index e15617e3ad..043fe47df4 100644 --- a/completions/bash-nvme-completion.sh +++ b/completions/bash-nvme-completion.sh @@ -308,7 +308,7 @@ nvme_list_opts () { opts+=" --namespace-id= -n" ;; "compare") - opts+=" --start-block= -s --block-count= -c --data-size= -z \ + opts+=" --start-block= -s --block-count= -c --block-size= -b --data-size= -z \ --metadata-size= -y --ref-tag= -r --data= -d \ --metadata= -M --prinfo= -p --app-tag-mask= -m \ --app-tag= -a --limited-retry -l \ @@ -317,7 +317,7 @@ nvme_list_opts () { --dry-run -w --latency -t --timeout=" ;; "read") - opts+=" --start-block= -s --block-count= -c --data-size= -z \ + opts+=" --start-block= -s --block-count= -c --block-size= -b --data-size= -z \ --metadata-size= -y --ref-tag= -r --data= -d \ --metadata= -M --prinfo= -p --app-tag-mask= -m \ --app-tag= -a --limited-retry -l \ @@ -326,7 +326,7 @@ nvme_list_opts () { --dry-run -w --latency -t --timeout=" ;; "write") - opts+=" --start-block= -s --block-count= -c --data-size= -z \ + opts+=" --start-block= -s --block-count= -c --block-size= -b --data-size= -z \ --metadata-size= -y --ref-tag= -r --data= -d \ --metadata= -M --prinfo= -p --app-tag-mask= -m \ --app-tag= -a --limited-retry -l \ From b4fb8fc18f664bb1ab6f9d8bfd3d373d22fb9950 Mon Sep 17 00:00:00 2001 From: Nate Thornton Date: Fri, 26 Sep 2025 09:26:04 -0700 Subject: [PATCH 3/3] docs: update with new --block-size= argument for compare/read/write Include new `--block-size=` in compare/read/write documentation Signed-off-by: Nate Thornton --- Documentation/nvme-compare.txt | 7 +++++++ Documentation/nvme-read.txt | 7 +++++++ Documentation/nvme-write.txt | 7 +++++++ 3 files changed, 21 insertions(+) diff --git a/Documentation/nvme-compare.txt b/Documentation/nvme-compare.txt index 0f28e58fc3..5b2f005daf 100644 --- a/Documentation/nvme-compare.txt +++ b/Documentation/nvme-compare.txt @@ -10,6 +10,7 @@ SYNOPSIS [verse] 'nvme-compare' [--start-block= | -s ] [--block-count= | -c ] + [--block-size= | -b ] [--data-size= | -z ] [--metadata-size= | -y ] [--ref-tag= | -r ] @@ -52,6 +53,12 @@ OPTIONS --block-count=:: Number of blocks to be accessed (zero-based). +-b :: +--block-size=:: + If specified, the logical block size in bytes, with metasize + also describing the metadata size for an individual block. + Discovered by identify namespace otherwise. + -z :: --data-size=:: Size of data to be compared in bytes. diff --git a/Documentation/nvme-read.txt b/Documentation/nvme-read.txt index 4054113af6..f8f59ae12d 100644 --- a/Documentation/nvme-read.txt +++ b/Documentation/nvme-read.txt @@ -10,6 +10,7 @@ SYNOPSIS [verse] 'nvme-read' [--start-block= | -s ] [--block-count= | -c ] + [--block-size= | -b ] [--data-size= | -z ] [--metadata-size= | -y ] [--ref-tag= | -r ] @@ -45,6 +46,12 @@ OPTIONS align with the kernel's use of this field. (ie. 0 means transfer 1 block). +-b :: +--block-size=:: + If specified, the logical block size in bytes, with metasize + also describing the metadata size for an individual block. + Discovered by identify namespace otherwise. + -z :: --data-size=:: Size of data, in bytes. diff --git a/Documentation/nvme-write.txt b/Documentation/nvme-write.txt index 8dbad98c3b..e2084f63ae 100644 --- a/Documentation/nvme-write.txt +++ b/Documentation/nvme-write.txt @@ -10,6 +10,7 @@ SYNOPSIS [verse] 'nvme-write' [--start-block= | -s ] [--block-count= | -c ] + [--block-size= | -c ] [--data-size= | -z ] [--metadata-size= | -y ] [--ref-tag= | -r ] @@ -45,6 +46,12 @@ OPTIONS align with the kernel's use of this field. (ie. 0 means transfer 1 block). +-b :: +--block-size=:: + If specified, the logical block size in bytes, with metasize + also describing the metadata size for an individual block. + Discovered by identify namespace otherwise. + -z :: --data-size=:: Size of data, in bytes.