Page MenuHomeFreeBSD

D11433.1784760805.diff
No OneTemporary

Size
7 KB
Referenced Files
None
Subscribers
None

D11433.1784760805.diff

Index: sbin/nvmecontrol/Makefile
===================================================================
--- sbin/nvmecontrol/Makefile
+++ sbin/nvmecontrol/Makefile
@@ -3,7 +3,7 @@
PACKAGE=runtime
PROG= nvmecontrol
SRCS= nvmecontrol.c devlist.c firmware.c identify.c logpage.c \
- perftest.c reset.c nvme_util.c power.c util.c wdc.c
+ perftest.c reset.c nvme_util.c power.c util.c wdc.c format.c
MAN= nvmecontrol.8
.PATH: ${SRCTOP}/sys/dev/nvme
Index: sbin/nvmecontrol/format.c
===================================================================
--- /dev/null
+++ sbin/nvmecontrol/format.c
@@ -0,0 +1,185 @@
+
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/ioccom.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "nvmecontrol.h"
+
+/* The LBAF field is 4 bits */
+#define MAX_LBAF 15
+/* The PI field is 3 bits */
+#define MAX_PI 7
+/* The SES field is 3 bits */
+#define MAX_SES 7
+
+static void
+format_usage(void)
+{
+ fprintf(stderr, "usage:\n");
+ fprintf(stderr, FORMAT_USAGE);
+ exit(1);
+}
+
+static int
+format_nvm(int fd, uint32_t nsid, uint8_t lbaf, uint8_t mset, uint8_t pi,
+ uint8_t pil, uint8_t ses)
+{
+ struct nvme_pt_command pt;
+
+ lbaf &= 0xf;
+ mset &= 0x1;
+ pi &= 0x7;
+ pil &= 0x1;
+ ses &= 0x7;
+
+ memset(&pt, 0, sizeof(pt));
+ pt.cmd.opc = NVME_OPC_FORMAT_NVM;
+ pt.cmd.nsid = nsid;
+ pt.cmd.cdw10 = lbaf | (mset << 4) | (pi << 5) | (pil << 8) | (ses << 9);
+ pt.is_read = 0;
+
+ if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0)
+ err(1, "format request failed");
+
+ if (nvme_completion_is_error(&pt.cpl))
+ errx(1, "format request returned error");
+
+ return 0;
+}
+
+void
+format(int argc, char *argv[])
+{
+ int fd = -1;
+ char ch, *p;
+ uint8_t lbaf = 0, mset = 1,
+ pi = 0, pil = 0,
+ ses = 0;
+ uint32_t nsid = 0;
+ char path[64];
+ struct nvme_controller_data cdata;
+ struct nvme_namespace_data nsdata;
+
+ while ((ch = getopt(argc, argv, "f:m:p:l:s:")) != -1) {
+ switch (ch) {
+ case 'f':
+ lbaf = strtol(optarg, &p, 0);
+ if (p != NULL && *p != '\0') {
+ fprintf(stderr,
+ "\"%s\" not valid LBAF.\n",
+ optarg);
+ format_usage();
+ } else if (lbaf > MAX_LBAF) {
+ fprintf(stderr,
+ "LBAF %u out of range (max=%u).\n",
+ lbaf, MAX_LBAF);
+ format_usage();
+ }
+ break;
+ case 'm':
+ mset = strtol(optarg, &p, 0);
+ if (p != NULL && *p != '\0') {
+ fprintf(stderr,
+ "\"%s\" not valid MSET.\n",
+ optarg);
+ format_usage();
+ } else if (mset > 1) {
+ fprintf(stderr,
+ "MSET %u out of range (max=1).\n",
+ mset);
+ format_usage();
+ }
+ break;
+ case 'p':
+ pi = strtol(optarg, &p, 0);
+ if (p != NULL && *p != '\0') {
+ fprintf(stderr,
+ "\"%s\" not valid PI.\n",
+ optarg);
+ format_usage();
+ } else if (pi > MAX_PI) {
+ fprintf(stderr,
+ "PI %u out of range (max=%u).\n",
+ pi, MAX_PI);
+ format_usage();
+ }
+ break;
+ case 'l':
+ pil = strtol(optarg, &p, 0);
+ if (p != NULL && *p != '\0') {
+ fprintf(stderr,
+ "\"%s\" not valid PIL.\n",
+ optarg);
+ format_usage();
+ } else if (pil > 1) {
+ fprintf(stderr,
+ "PIL %u out of range (max=1).\n",
+ pil);
+ format_usage();
+ }
+ break;
+ case 's':
+ ses = strtol(optarg, &p, 0);
+ if (p != NULL && *p != '\0') {
+ fprintf(stderr,
+ "\"%s\" not valid SES.\n",
+ optarg);
+ format_usage();
+ } else if (ses > MAX_SES) {
+ fprintf(stderr,
+ "SES %u out of range (max=%u).\n",
+ ses, MAX_SES);
+ }
+ break;
+ }
+ }
+
+ /* Check that a namespace (and not a controller) was specified. */
+ if (optind >= argc || strstr(argv[optind], NVME_NS_PREFIX) == NULL) {
+ printf("expecting NS optind=%d argc=%d %s\n", optind, argc, argv[optind]);
+ format_usage();
+ }
+
+ parse_ns_str(argv[optind], path, &nsid);
+ open_dev(path, &fd, 1, 1);
+ read_controller_data(fd, &cdata);
+ read_namespace_data(fd, nsid, &nsdata);
+
+ if (cdata.oacs.format == 0) {
+ errx(1, "controller does not support format");
+ }
+
+#define FNA_SUPPORTS_CRYPTO_ERASE(fna) (((fna) & 0x4) == 0x4)
+#define SES_CRYPTO_ERASE 0x2
+
+ if ((ses == SES_CRYPTO_ERASE) &&
+ !FNA_SUPPORTS_CRYPTO_ERASE(cdata.fna)) {
+ errx(1, "controller does not support cryptographic erase");
+ }
+
+ if (lbaf > nsdata.nlbaf) {
+ errx(1, "LBAF %u out of controller range (max=%u).", lbaf, nsdata.nlbaf);
+ }
+
+ format_nvm(fd, nsid, lbaf, mset, pi, pil, ses);
+
+ close(fd);
+
+ exit(0);
+}
Index: sbin/nvmecontrol/nvmecontrol.h
===================================================================
--- sbin/nvmecontrol/nvmecontrol.h
+++ sbin/nvmecontrol/nvmecontrol.h
@@ -69,6 +69,9 @@
#define WDC_USAGE \
" nvmecontrol wdc (cap-diag|drive-log|get-crash-dump|purge|purge-montior)\n"
+#define FORMAT_USAGE \
+" nvmecontrol format [-f LBAF] [-m MSET] [-p PI] [-l PIL] [-s SES] <namespace id>\n"
+
void devlist(int argc, char *argv[]);
void identify(int argc, char *argv[]);
void perftest(int argc, char *argv[]);
@@ -77,6 +80,7 @@
void firmware(int argc, char *argv[]);
void power(int argc, char *argv[]);
void wdc(int argc, char *argv[]);
+void format(int argc, char *argv[]);
int open_dev(const char *str, int *fd, int show_error, int exit_on_error);
void parse_ns_str(const char *ns_str, char *ctrlr_str, int *nsid);
Index: sbin/nvmecontrol/nvmecontrol.8
===================================================================
--- sbin/nvmecontrol/nvmecontrol.8
+++ sbin/nvmecontrol/nvmecontrol.8
@@ -95,6 +95,13 @@
.\" .Nm
.\" .Ic wdc purge-monitor
.\" .Aq device id
+.Nm
+.Ic format
+.Op Fl f Ar LBAF
+.Op Fl m Ar MSET
+.Op Fl p Ar PI
+.Op Fl s Ar SES
+.Aq namespace id
.Sh DESCRIPTION
NVM Express (NVMe) is a storage protocol standard, for SSDs and other
high-speed storage devices over PCI Express.
@@ -127,6 +134,22 @@
by .bin.
These logs must be sent to the vendor for analysis.
This tool only provides a way to extract them.
+.Ss format
+The format command allows a low level format of the NVM media. Each of the
+options mirror the field names defined in the NVM Express specification.
+.Fl f
+chooses the LBA Format. Valid values are 0-15.
+.Fl m
+chooses whether metadata is appended to the block (extended LBA) or sent
+in a separate buffer.
+.Fl p
+selects the end-to-end protection information (Type 0 - 3).
+.Fl l
+selects whether the protection information is first (1) or last (0) in the
+metadata.
+.Fl s
+selects the type of low level format (none = 0, user erase = 1, cryptographic
+erase = 2).
.Sh EXAMPLES
.Dl nvmecontrol devlist
.Pp
Index: sbin/nvmecontrol/nvmecontrol.c
===================================================================
--- sbin/nvmecontrol/nvmecontrol.c
+++ sbin/nvmecontrol/nvmecontrol.c
@@ -55,6 +55,7 @@
{"firmware", firmware, FIRMWARE_USAGE},
{"power", power, POWER_USAGE},
{"wdc", wdc, WDC_USAGE},
+ {"format", format, FORMAT_USAGE},
{NULL, NULL, NULL},
};

File Metadata

Mime Type
text/plain
Expires
Wed, Jul 22, 10:53 PM (16 h, 26 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
29232235
Default Alt Text
D11433.1784760805.diff (7 KB)

Event Timeline