git: 3b66efc6e9b8 - main - nvmecontrol: add format dry-run support
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 19 Oct 2026 06:24:42 UTC
The branch main has been updated by imp:
URL: https://cgit.FreeBSD.org/src/commit/?id=3b66efc6e9b8999053f11a449056fad5ebc1c1ac
commit 3b66efc6e9b8999053f11a449056fad5ebc1c1ac
Author: Warner Losh <imp@FreeBSD.org>
AuthorDate: 2026-10-19 04:43:00 +0000
Commit: Warner Losh <imp@FreeBSD.org>
CommitDate: 2026-10-19 06:22:51 +0000
nvmecontrol: add format dry-run support
Add -n/--dry-run to resolve and print the Format NVM command without
submitting it. This lets users verify namespace selection and format
parameters before making destructive media changes.
Reviewed by: seuros, chuck
Differential Revision: https://reviews.freebsd.org/D59835
---
sbin/nvmecontrol/format.c | 22 +++++++++++++++++-----
sbin/nvmecontrol/nvmecontrol.8 | 5 +++++
2 files changed, 22 insertions(+), 5 deletions(-)
diff --git a/sbin/nvmecontrol/format.c b/sbin/nvmecontrol/format.c
index ee0ecc34aeaa..ccf0981103c0 100644
--- a/sbin/nvmecontrol/format.c
+++ b/sbin/nvmecontrol/format.c
@@ -59,6 +59,7 @@ static struct options {
uint32_t ses;
bool Eflag;
bool Cflag;
+ bool dry_run;
const char *dev;
} opt = {
.lbaf = NONE,
@@ -69,6 +70,7 @@ static struct options {
.ses = SES_NONE,
.Eflag = false,
.Cflag = false,
+ .dry_run = false,
.dev = NULL,
};
@@ -78,6 +80,8 @@ static const struct opts format_opts[] = {
"Cryptographic erase"),
OPT("erase", 'E', arg_none, opt, Eflag,
"User data erase"),
+ OPT("dry-run", 'n', arg_none, opt, dry_run,
+ "Print the Format NVM command without submitting it"),
OPT("lbaf", 'f', arg_uint32, opt, lbaf,
"LBA Format to apply to the media"),
OPT("ms", 'm', arg_uint32, opt, ms,
@@ -186,7 +190,7 @@ format(const struct cmd *f, int argc, char *argv[])
struct nvme_pt_command pt;
char *path;
const char *target;
- uint32_t nsid, scan_nsid;
+ uint32_t cdw10, nsid, scan_nsid;
int lbaf, ms, pi, pil, ses, fd;
u_int i;
uint32_t sector_size;
@@ -220,7 +224,7 @@ format(const struct cmd *f, int argc, char *argv[])
else
ses = opt.ses;
- open_dev(target, &fd, 1, 1);
+ open_dev(target, &fd, !opt.dry_run, 1);
get_nsid(fd, &path, &nsid);
if (nsid == 0) {
nsid = NVME_GLOBAL_NAMESPACE_TAG;
@@ -232,7 +236,7 @@ format(const struct cmd *f, int argc, char *argv[])
* string to get the controller substring and namespace ID.
*/
close(fd);
- open_dev(path, &fd, 1, 1);
+ open_dev(path, &fd, !opt.dry_run, 1);
}
free(path);
@@ -316,11 +320,19 @@ format(const struct cmd *f, int argc, char *argv[])
pil = 0;
}
+ cdw10 = (ses << 9) + (pil << 8) + (pi << 5) + (ms << 4) + lbaf;
+ if (opt.dry_run) {
+ printf("Format NVM: opc=%#x nsid=%#010x cdw10=%#010x "
+ "(lbaf=%d mset=%d pi=%d pil=%d ses=%d)\n",
+ NVME_OPC_FORMAT_NVM, nsid, cdw10, lbaf, ms, pi, pil, ses);
+ close(fd);
+ exit(0);
+ }
+
memset(&pt, 0, sizeof(pt));
pt.cmd.opc = NVME_OPC_FORMAT_NVM;
pt.cmd.nsid = htole32(nsid);
- pt.cmd.cdw10 = htole32((ses << 9) + (pil << 8) + (pi << 5) +
- (ms << 4) + lbaf);
+ pt.cmd.cdw10 = htole32(cdw10);
if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0)
err(EX_IOERR, "format request failed");
diff --git a/sbin/nvmecontrol/nvmecontrol.8 b/sbin/nvmecontrol/nvmecontrol.8
index 793016652e73..19015a8c90df 100644
--- a/sbin/nvmecontrol/nvmecontrol.8
+++ b/sbin/nvmecontrol/nvmecontrol.8
@@ -153,6 +153,7 @@
.Aq Ar device-id
.Nm
.Ic format
+.Op Fl n
.Op Fl f Ar fmt
.Op Fl s Ar sector-size
.Op Fl m Ar mset
@@ -505,6 +506,10 @@ Use Extended Data Structure.
Format either specified namespace, or all namespaces of specified controller,
using specified parameters:
.Bl -tag -width 8n
+.It Fl n , Fl Fl dry-run
+Print the resolved Format NVM command without submitting it to the controller.
+Identify commands needed to resolve and validate the format parameters are
+still performed.
.It Fl f Ar fmt
The index
.Ar fmt