Page MenuHomeFreeBSD

D59533.diff
No OneTemporary

D59533.diff

diff --git a/sbin/camcontrol/camcontrol.h b/sbin/camcontrol/camcontrol.h
--- a/sbin/camcontrol/camcontrol.h
+++ b/sbin/camcontrol/camcontrol.h
@@ -75,6 +75,8 @@
int get_ata_status(struct cam_device *dev, union ccb *ccb, uint8_t *error,
uint16_t *count, uint64_t *lba, uint8_t *device,
uint8_t *status);
+int nvme_get_data(struct cam_device *dev, int nvme_data_type, void *data,
+ size_t data_len);
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
@@ -25,7 +25,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd December 28, 2023
+.Dd August 21, 2026
.Dt CAMCONTROL 8
.Os
.Sh NAME
@@ -67,6 +67,7 @@
.Ic identify
.Op device id
.Op generic args
+.Op Fl N
.Op Fl v
.Nm
.Ic reportluns
@@ -524,7 +525,15 @@
Print out transfer rate information.
.El
.It Ic identify
-Send an ATA identify command (0xec) to a device.
+Send a ATA identify command (0xec) or NVMe identify command to a device.
+For NVMe devices, this displays Identify data cached in the kernel, and
+does not send commands to the drive.
+.Bl -tag -width 8n
+.It Fl N
+Display NVMe Identify Namespace data.
+This shows the capacity of the namespace (CAM peripheral drivers are attached
+to a NVMe namespace) as opposed to the entire drive.
+.El
.It Ic reportluns
Send the SCSI REPORT LUNS (0xA0) command to the given device.
By default,
@@ -2935,6 +2944,7 @@
.Xr pass 4 ,
.Xr xpt 4 ,
.Xr diskinfo 8 ,
+.Xr nvmecontrol 8 ,
.Xr trim 8 ,
.Xr zonectl 8
.Sh HISTORY
diff --git a/sbin/camcontrol/camcontrol.c b/sbin/camcontrol/camcontrol.c
--- a/sbin/camcontrol/camcontrol.c
+++ b/sbin/camcontrol/camcontrol.c
@@ -185,7 +185,7 @@
static struct camcontrol_opts option_table[] = {
{"tur", CAM_CMD_TUR, CAM_ARG_NONE, NULL},
{"inquiry", CAM_CMD_INQUIRY, CAM_ARG_NONE, "DSR"},
- {"identify", CAM_CMD_IDENTIFY, CAM_ARG_NONE, NULL},
+ {"identify", CAM_CMD_IDENTIFY, CAM_ARG_NONE, "N"},
{"start", CAM_CMD_STARTSTOP, CAM_ARG_START_UNIT, NULL},
{"stop", CAM_CMD_STARTSTOP, CAM_ARG_NONE, NULL},
{"load", CAM_CMD_STARTSTOP, CAM_ARG_START_UNIT | CAM_ARG_EJECT, NULL},
@@ -779,12 +779,35 @@
return (0);
}
-static int
-nvme_get_cdata(struct cam_device *dev, struct nvme_controller_data *cdata)
+int
+nvme_get_data(struct cam_device *dev, int nvme_data_type, void *data,
+ size_t data_len)
{
union ccb *ccb;
+ struct nvme_controller_data *cdata;
+ struct nvme_namespace_data *nsdata;
struct ccb_dev_advinfo *advi;
+ switch (nvme_data_type) {
+ case CDAI_TYPE_NVME_CNTRL:
+ if (data_len != sizeof(*cdata)) {
+ warnx("%s: supplied data length %zu != controller data "
+ "length %zu", __func__, data_len, sizeof(*nsdata));
+ goto bailout_error;
+ }
+ break;
+ case CDAI_TYPE_NVME_NS:
+ if (data_len != sizeof(*nsdata)) {
+ warnx("%s: supplied data length %zu != namespace data "
+ "length %zu", __func__, data_len, sizeof(*nsdata));
+ goto bailout_error;
+ }
+ break;
+ default:
+ warnx("Unknown NVMe data type %d", nvme_data_type);
+ goto bailout_error;
+ }
+
ccb = cam_getccb(dev);
if (ccb == NULL) {
warnx("couldn't allocate CCB");
@@ -792,28 +815,31 @@
return (1);
}
+ CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->cdai);
advi = &ccb->cdai;
advi->ccb_h.flags = CAM_DIR_IN;
advi->ccb_h.func_code = XPT_DEV_ADVINFO;
advi->flags = CDAI_FLAG_NONE;
- advi->buftype = CDAI_TYPE_NVME_CNTRL;
- advi->bufsiz = sizeof(struct nvme_controller_data);
- advi->buf = (uint8_t *)cdata;
+ advi->buftype = nvme_data_type;
+ advi->bufsiz = data_len;
+ advi->buf = data;
if (cam_send_ccb(dev, ccb) < 0) {
- warn("error sending XPT_DEV_ADVINFO CCB");
+ warn("%s: error sending XPT_DEV_ADVINFO CCB", __func__);
cam_freeccb(ccb);
- cam_close_device(dev);
- return(1);
+ goto bailout_error;
}
- if (advi->ccb_h.status != CAM_REQ_CMP) {
- warnx("got CAM error %#x", advi->ccb_h.status);
+ if ((advi->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
+ cam_error_print(dev, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
cam_freeccb(ccb);
- cam_close_device(dev);
- return(1);
+ goto bailout_error;
}
cam_freeccb(ccb);
return 0;
+
+bailout_error:
+ cam_close_device(dev);
+ return (1);
}
static int
@@ -830,7 +856,7 @@
return (1);
}
- if (nvme_get_cdata(dev, &cdata))
+ if (nvme_get_data(dev, CDAI_TYPE_NVME_CNTRL, &cdata, sizeof(cdata)))
return (1);
cam_strvis(vendor, cdata.mn, sizeof(cdata.mn), sizeof(vendor));
@@ -2470,7 +2496,8 @@
static int
-ataidentify(struct cam_device *device, int retry_count, int timeout)
+ataidentify(struct cam_device *device, int argc __unused, char **argv __unused,
+ char *combinedopt __unused, int retry_count, int timeout)
{
union ccb *ccb;
struct ata_params *ident_buf;
@@ -2515,19 +2542,47 @@
}
static int
-nvmeidentify(struct cam_device *device, int retry_count __unused, int timeout __unused)
+nvmeidentify(struct cam_device *device, int argc, char **argv,
+ char *combinedopt, int retry_count __unused, int timeout __unused)
{
- struct nvme_controller_data cdata;
+ int ns_identify = 0;
+ int c;
- if (nvme_get_cdata(device, &cdata))
- return (1);
- nvme_print_controller(&cdata);
+
+ while ((c = getopt(argc, argv, combinedopt)) != -1) {
+ switch (c) {
+ case 'N':
+ ns_identify = 1;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (ns_identify == 0) {
+ struct nvme_controller_data cdata;
+
+ if (nvme_get_data(device, CDAI_TYPE_NVME_CNTRL, &cdata,
+ sizeof(cdata)))
+ return (1);
+
+ nvme_print_controller(&cdata);
+ } else {
+ struct nvme_namespace_data ns_data;
+
+ if (nvme_get_data(device, CDAI_TYPE_NVME_NS, &ns_data,
+ sizeof(ns_data)))
+ return (1);
+
+ nvme_print_namespace(&ns_data);
+ }
return (0);
}
static int
-identify(struct cam_device *device, int retry_count, int timeout)
+identify(struct cam_device *device, int argc, char **argv, char *combinedopt,
+ int retry_count, int timeout)
{
struct ccb_pathinq cpi;
@@ -2537,9 +2592,12 @@
}
if (cpi.protocol == PROTO_NVME) {
- return (nvmeidentify(device, retry_count, timeout));
+ return (nvmeidentify(device, argc, argv, combinedopt,
+ retry_count, timeout));
+ } else {
+ return (ataidentify(device, argc, argv, combinedopt,
+ retry_count, timeout));
}
- return (ataidentify(device, retry_count, timeout));
}
@@ -10030,7 +10088,7 @@
" camcontrol tur [dev_id][generic args]\n"
" camcontrol sense [dev_id][generic args][-D][-x]\n"
" camcontrol inquiry [dev_id][generic args] [-D] [-S] [-R]\n"
-" camcontrol identify [dev_id][generic args] [-v]\n"
+" camcontrol identify [dev_id][generic args] [-N] [-v]\n"
" camcontrol reportluns [dev_id][generic args] [-c] [-l] [-r report]\n"
" camcontrol readcap [dev_id][generic args] [-b] [-h] [-H] [-N]\n"
" [-q] [-s] [-l]\n"
@@ -10120,7 +10178,7 @@
"sense send a request sense command to the named device\n"
"tur send a test unit ready to the named device\n"
"inquiry send a SCSI inquiry command to the named device\n"
-"identify send a ATA identify command to the named device\n"
+"identify send a ATA or NVMe identify command to the named device\n"
"reportluns send a SCSI report luns command to the device\n"
"readcap send a SCSI read capacity command to the device\n"
"start send a Start Unit command to the device\n"
@@ -10189,6 +10247,8 @@
"-D get the standard inquiry data\n"
"-S get the serial number\n"
"-R get the transfer rate, etc.\n"
+"identify arguments:\n"
+"-N send identify to the NVMe namespace\n"
"reportluns arguments:\n"
"-c only report a count of available LUNs\n"
"-l only print out luns, and not a count\n"
@@ -10668,7 +10728,8 @@
task_attr, retry_count, timeout);
break;
case CAM_CMD_IDENTIFY:
- error = identify(cam_dev, retry_count, timeout);
+ error = identify(cam_dev, argc, argv, combinedopt, retry_count,
+ timeout);
break;
case CAM_CMD_STARTSTOP:
error = scsistart(cam_dev, arglist & CAM_ARG_START_UNIT,

File Metadata

Mime Type
text/plain
Expires
Fri, Oct 2, 4:27 AM (7 h, 14 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
40054445
Default Alt Text
D59533.diff (8 KB)

Event Timeline