Page MenuHomeFreeBSD

D59535.id187925.diff
No OneTemporary

D59535.id187925.diff

diff --git a/sbin/camcontrol/Makefile b/sbin/camcontrol/Makefile
--- a/sbin/camcontrol/Makefile
+++ b/sbin/camcontrol/Makefile
@@ -18,7 +18,7 @@
SRCS+= identify_ext.c
SRCS+= nc_util.c
.PATH: ${SRCTOP}/sys/dev/nvme
-SRCS+= nvme_util.c nvres.c
+SRCS+= nvme_util.c nvres.c nvformat.c
# This is verboten
.if ${MACHINE_CPUARCH} == "arm"
WARNS?= 3
diff --git a/sbin/camcontrol/camcontrol.h b/sbin/camcontrol/camcontrol.h
--- a/sbin/camcontrol/camcontrol.h
+++ b/sbin/camcontrol/camcontrol.h
@@ -80,6 +80,9 @@
int nvmepersist(struct cam_device *device, int argc, char **argv,
char *combinedopt, int retry_count, int timeout,
int verbosemode, int err_recover);
+int nvmeformat(struct cam_device *device, int argc, char **argv,
+ char *combinedopt, int retry_count, int timeout,
+ int verbosemode, int err_recover);
int camxferrate(struct cam_device *device);
int fwdownload(struct cam_device *device, int argc, char **argv,
char *combinedopt, int printerrors, int task_attr,
diff --git a/sbin/camcontrol/camcontrol.8 b/sbin/camcontrol/camcontrol.8
--- a/sbin/camcontrol/camcontrol.8
+++ b/sbin/camcontrol/camcontrol.8
@@ -369,6 +369,16 @@
.Op generic args
.Ao Fl r Oo Ns Fl f Ar format | Fl m | Fl U Oc | Fl s Ao Fl f Ar format Fl T Ar time | Fl U Ac Ac
.Nm
+.Ic nvformat
+.Op device id
+.Op generic args
+.Op Fl e Ar ses
+.Op Fl G
+.Op Fl f Ar lbaf
+.Op Fl l Ar pil
+.Op Fl m Ar mset
+.Op Fl p Ar pi
+.Nm
.Ic devtype
.Op device id
.Nm
@@ -1230,6 +1240,12 @@
Issue the
.Tn SCSI
FORMAT UNIT command to the named device.
+This only works on
+.Tn SCSI
+devices.
+See the nvformat subcommand to format
+.Tn NVMe
+devices.
.Pp
.Em WARNING! WARNING! WARNING!
.Pp
@@ -2696,6 +2712,65 @@
Set the timestamp to the host system's time in UTC.
.El
.El
+.It Ic nvformat
+Format an NVMe device.
+Most devices format very quickly, but for drives that take longer, you can
+see format progress in the NVMe namespace identify if the drive supports
+it.
+.Bl -tag -width 8n
+.It Fl e Ar ses
+Specify the NVMe Secure Erase Setting.
+.Bl -tag -width 8n
+.It none
+This is the default.
+It indicates that no specific erase option is requested.
+.It user
+This requests that all user data be erased.
+The controller can use any method to erase the user data.
+.It crypto
+This requests that the controller erase the data cryptographically by
+deleting the encryption key.
+.It num
+Specify a numeric (decimal or hexadecimal) value
+.El
+.It Fl G
+Some NVMe controllers only allow formatting all namespaces attached to the
+controller.
+By default,
+.Nm
+will format the NVMe namespace addressed by the command.
+If you get an error message saying that the controller doesn't support
+per-NS format, you can try this option.
+.It Fl f Ar lbaf
+Use the specified LBA format number.
+You can use this option to change the sector size of the drive.
+To see a list of allowed LBA formats (combination of sector size and
+metadata size), and the current LBA format, look at
+the NVMe Namespace Identify data.
+You can see it with:
+.Pp
+.Dl camcontrol identify ndaX -N
+.It Fl l Ar pil
+Specify the protection information location.
+If set to 1, and protection information is enabled (see the
+.Fl p
+option), protection information is transferred as the first 8 bytes of
+metadata.
+If set to 0 (the default) and protection information is enabled, protection
+information is transferred as the last 8 bytes of metadata.
+.It Fl m Ar mset
+If set to 1, metadata is transferred as part of an extended LBA.
+If set to 0 (the default), metadata is transferred as part of a separate
+buffer.
+.It Fl p Ar pi
+This specifies whether protection information is enabled, and if so, the
+type of protection information.
+The default is 0, no protection information enabled.
+You may specify Type 1, 2 or 3 protection with a numeric argument of 1, 2
+or 3 respectively.
+Other types are allowed up to 7, but the only values currently defined in
+the NVMe 1.4 specification are 0-3.
+.El
.It Ic devtype
Print out the device type for specified device.
.Bl -tag -width 10n
diff --git a/sbin/camcontrol/camcontrol.c b/sbin/camcontrol/camcontrol.c
--- a/sbin/camcontrol/camcontrol.c
+++ b/sbin/camcontrol/camcontrol.c
@@ -112,7 +112,8 @@
CAM_CMD_DEVTYPE,
CAM_CMD_AMA,
CAM_CMD_DEPOP,
- CAM_CMD_REQSENSE
+ CAM_CMD_REQSENSE,
+ CAM_CMD_NVFORMAT
} cam_cmd;
typedef enum {
@@ -234,6 +235,7 @@
{"zone", CAM_CMD_ZONE, CAM_ARG_NONE, "ac:l:No:P:"},
{"epc", CAM_CMD_EPC, CAM_ARG_NONE, "c:dDeHp:Pr:sS:T:"},
{"timestamp", CAM_CMD_TIMESTAMP, CAM_ARG_NONE, "f:mrsUT:"},
+ {"nvformat", CAM_CMD_NVFORMAT, CAM_ARG_NONE, "e:Gf:l:m:p:"},
{"depop", CAM_CMD_DEPOP, CAM_ARG_NONE, "ac:de:ls"},
{"sense", CAM_CMD_REQSENSE, CAM_ARG_NONE, "Dx"},
{"help", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
@@ -10158,6 +10160,8 @@
" [-S power_src] [-T timer]\n"
" camcontrol timestamp [dev_id][generic_args] <-r [-f format|-m|-U]>|\n"
" <-s <-f format -T time | -U >>\n"
+" camcontrol nvformat [dev_id][generic args][-e <user|crypto|num>]\n"
+" [-G][-f format][-l pil][-m mset][-p pi]\n"
" camcontrol devtype [dev_id]\n"
" camcontrol depop [dev_id] [-d | -l | -r] [-e element] [-c capacity]\n"
" camcontrol mmcsdcmd [dev_id] [[-c mmc_opcode] [-a mmc_arg]\n"
@@ -10213,6 +10217,7 @@
"zone manage Zoned Block (Shingled) devices\n"
"epc send ATA Extended Power Conditions commands\n"
"timestamp report or set the device's timestamp\n"
+"nvformat send NVMe format command\n"
"devtype report the type of device\n"
"depop manage drive storage elements\n"
"mmcsdcmd send the given MMC command, needs -c and -a as well\n"
@@ -10429,6 +10434,13 @@
"-f format the format of the time string passed into strptime(3)\n"
"-T time the time value passed into strptime(3)\n"
"-U set the timestamp of the device to UTC time\n"
+"nvformat arguments:\n"
+"-e ses secure erase setting: user, crypto\n"
+"-G global format, formats all Namespaces\n"
+"-f num specify format number, see Namespace Identify\n"
+"-l pil Protection Information Location, 1 = start, 0 = end\n"
+"-m mset metadata setting, 0 = separate buffer, 1 ext. LBA\n"
+"-p pi Protection Information type\n"
"depop arguments:\n"
"-d remove an element from service\n"
"-l list status of all elements of drive\n"
@@ -10877,6 +10889,12 @@
task_attr, retry_count, timeout,
arglist & CAM_ARG_VERBOSE);
break;
+ case CAM_CMD_NVFORMAT:
+ error = nvmeformat(cam_dev, argc, argv, combinedopt,
+ retry_count, timeout,
+ arglist & CAM_ARG_VERBOSE,
+ arglist & CAM_ARG_ERR_RECOVER);
+ break;
case CAM_CMD_DEPOP:
error = depop(cam_dev, argc, argv, combinedopt,
task_attr, retry_count, timeout,
diff --git a/sbin/camcontrol/nvformat.c b/sbin/camcontrol/nvformat.c
new file mode 100644
--- /dev/null
+++ b/sbin/camcontrol/nvformat.c
@@ -0,0 +1,278 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (C) 2018-2019 Alexander Motin <mav@FreeBSD.org>
+ * Copyright (C) 2021 Spectra Logic Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/*
+ * NVMe format support for camcontrol(8).
+ */
+
+#include <sys/ioctl.h>
+#include <sys/stdint.h>
+#include <sys/types.h>
+#include <sys/endian.h>
+#include <sys/sbuf.h>
+#include <sys/queue.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include <unistd.h>
+#include <string.h>
+#include <strings.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <limits.h>
+#include <err.h>
+
+#include <cam/cam.h>
+#include <cam/cam_debug.h>
+#include <cam/cam_ccb.h>
+#include <cam/scsi/scsi_all.h>
+#include <cam/scsi/scsi_pass.h>
+#include <dev/nvme/nvme.h>
+#include <camlib.h>
+#include "camcontrol.h"
+
+static struct scsi_nv nvme_ses_settings[] = {
+ { "none", NVME_FORMAT_SES_NONE },
+ { "user", NVME_FORMAT_SES_USER },
+ { "crypto", NVME_FORMAT_SES_CRYPTO },
+};
+
+int
+nvmeformat(struct cam_device *device, int argc, char **argv, char *combinedopt,
+ int retry_count, int timeout, int verbosemode, int err_recover)
+{
+ union ccb *ccb = NULL;
+ struct nvme_controller_data cdata;
+ struct nvme_namespace_data nsdata;
+ char *end;
+ int global_op = 0;
+ int lbaf = -1, mset = -1, pi = -1, pil = -1, ses = -1;
+ int error = 0;
+ int c;
+
+ ccb = cam_getccb(device);
+ if (ccb == NULL) {
+ warnx("%s: error allocating CCB", __func__);
+ error = 1;
+ goto bailout;
+ }
+
+ CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->nvmeio);
+
+ while ((c = getopt(argc, argv, combinedopt)) != -1) {
+ switch (c) {
+ case 'e': {
+ scsi_nv_status status;
+ int table_entry = 0;
+
+ status = scsi_get_nv(nvme_ses_settings,
+ sizeof(nvme_ses_settings) /
+ sizeof(nvme_ses_settings[0]), optarg,
+ &table_entry, SCSI_NV_FLAG_IG_CASE);
+ if (status == SCSI_NV_FOUND)
+ ses = nvme_ses_settings[table_entry].value;
+ else if (status == SCSI_NV_AMBIGUOUS) {
+ warnx("%s: ambiguous Secure Erase Setting %s",
+ __func__, optarg);
+ error = 1;
+ goto bailout;
+ } else {
+ ses = strtol(optarg, &end, 0);
+ if ((*end != '\0')
+ || ((ses < 0) || (ses > 0x7))) {
+ warnx("%s: invalid Secure Erase "
+ "setting %s", __func__, optarg);
+ error = 1;
+ goto bailout;
+ }
+ }
+ break;
+ }
+ case 'G':
+ global_op = 1;
+ break;
+ case 'f':
+ lbaf = strtol(optarg, &end, 0);
+ if (*end != '\0') {
+ warnx("%s: invalid format argument %s",
+ __func__, optarg);
+ error = 1;
+ goto bailout;
+ }
+ break;
+ case 'l':
+ pil = strtol(optarg, &end, 0);
+ if ((*end != '\0') || ((pil < 0) || (pil > 1))) {
+ warnx("%s: invalid location argument %s",
+ __func__, optarg);
+ error = 1;
+ goto bailout;
+ }
+ break;
+ case 'm':
+ mset = strtol(optarg, &end, 0);
+ if ((*end != '\0') || ((mset < 0) || (mset > 1))) {
+ warnx("%s: invalid metadata setting %s",
+ __func__, optarg);
+ error = 1;
+ goto bailout;
+ }
+ break;
+ case 'p':
+ pi = strtol(optarg, &end, 0);
+ if ((*end != '\0') || ((pi < 0) || (pi > 0x7))) {
+ warnx("%s: invalid Protection Information "
+ "type %s", __func__, optarg);
+ error = 1;
+ goto bailout;
+ }
+ break;
+ }
+ }
+
+ bzero(&cdata, sizeof(cdata));
+ error = nvme_get_data(device, CDAI_TYPE_NVME_CNTRL, &cdata,
+ sizeof(cdata));
+ if (error != 0)
+ goto bailout;
+
+ if (((cdata.oacs >> NVME_CTRLR_DATA_OACS_FORMAT_SHIFT) &
+ NVME_CTRLR_DATA_OACS_FORMAT_MASK) == 0) {
+ warnx("%s: controller doesn't support format", __func__);
+ error = 1;
+ goto bailout;
+ }
+
+ if ((((cdata.fna >> NVME_CTRLR_DATA_FNA_CRYPTO_ERASE_SHIFT) &
+ NVME_CTRLR_DATA_FNA_CRYPTO_ERASE_MASK) == 0) && (ses == 2)){
+ warnx("%s: controller doesn't support crypto erase", __func__);
+ error = 1;
+ goto bailout;
+ }
+
+ if (global_op == 0) {
+
+ if ((cdata.fna >> NVME_CTRLR_DATA_FNA_FORMAT_ALL_SHIFT) &
+ NVME_CTRLR_DATA_FNA_FORMAT_ALL_MASK) {
+ warnx("%s: controller does not support per-NS format, "
+ "use -G", __func__);
+ error = 1;
+ goto bailout;
+ }
+ if ((cdata.fna >> NVME_CTRLR_DATA_FNA_ERASE_ALL_SHIFT) &
+ NVME_CTRLR_DATA_FNA_ERASE_ALL_MASK) {
+ warnx("%s: controller does not support per-NS erase, "
+ "use -G", __func__);
+ error = 1;
+ goto bailout;
+ }
+
+ bzero(&nsdata, sizeof(nsdata));
+ error = nvme_get_data(device, CDAI_TYPE_NVME_NS, &nsdata,
+ sizeof(nsdata));
+ if (error != 0)
+ goto bailout;
+
+ if (lbaf < 0)
+ lbaf = (nsdata.flbas >> NVME_NS_DATA_FLBAS_FORMAT_SHIFT)
+ & NVME_NS_DATA_FLBAS_FORMAT_MASK;
+
+ if (lbaf > nsdata.nlbaf) {
+ warnx("%s: LBA format %d is out of range", __func__,
+ lbaf);
+ error = 1;
+ goto bailout;
+ }
+ if (mset < 0) {
+ mset = (nsdata.flbas >>
+ NVME_NS_DATA_FLBAS_EXTENDED_SHIFT)
+ & NVME_NS_DATA_FLBAS_EXTENDED_MASK;
+ }
+ if (pi < 0) {
+ pi = (nsdata.dps >> NVME_NS_DATA_DPS_MD_START_SHIFT)
+ & NVME_NS_DATA_DPS_MD_START_MASK;
+ }
+ if (pil < 0) {
+ pil = (nsdata.dps >> NVME_NS_DATA_DPS_PIT_SHIFT) &
+ NVME_NS_DATA_DPS_PIT_MASK;
+ }
+ if (ses < 0)
+ ses = 0;
+ } else {
+ if (ses < 0)
+ ses = 0;
+ if (lbaf < 0)
+ lbaf = 0;
+ if (mset < 0)
+ mset = 0;
+ if (pi < 0)
+ pi = 0;
+ if (pil < 0)
+ pil = 0;
+ }
+
+ nvme_format(/*nvmeio*/ &ccb->nvmeio,
+ /*retries*/ retry_count,
+ /*cbfcnp*/ NULL,
+ /*nsid*/ global_op ? NVME_GLOBAL_NAMESPACE_TAG :
+ device->target_lun,
+ /*ses*/ ses,
+ /*pil*/ pil,
+ /*pi*/ pi,
+ /*mset*/ mset,
+ /*lbaf*/ lbaf,
+ /*
+ * A cryptographic erase just changes the media
+ * encryption key, so it should be quick. A user data
+ * erase or a plain format can take a long time.
+ */
+ /*timeout*/ timeout ? timeout :
+ (ses == NVME_FORMAT_SES_CRYPTO ?
+ (30 * 1000) : (30 * 60 * 1000)));
+
+ if (err_recover != 0)
+ ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
+
+ if (cam_send_ccb(device, ccb) < 0) {
+ warn("error sending NVMe Format command");
+ error = 1;
+ goto bailout;
+ }
+
+ if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
+ if (verbosemode != 0) {
+ cam_error_print(device, ccb, CAM_ESF_ALL,
+ CAM_EPF_ALL, stderr);
+ }
+ error = 1;
+ goto bailout;
+ }
+
+bailout:
+ return (error);
+}

File Metadata

Mime Type
text/plain
Expires
Sat, Oct 3, 9:09 PM (21 h, 55 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
40153548
Default Alt Text
D59535.id187925.diff (14 KB)

Event Timeline