aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDouglas Gilbert <dgilbert@interlog.com>2019-01-31 14:29:54 +0000
committerDouglas Gilbert <dgilbert@interlog.com>2019-01-31 14:29:54 +0000
commit04adb7f5027fb9f8b4368e4eaa561e14591bb1a7 (patch)
tree7f3af533e28c692c020eabd152b49762f340f106 /lib
parenta918d1a30569c4d3f09cc87836ff19215db6d8b7 (diff)
downloadsg3_utils-04adb7f5027fb9f8b4368e4eaa561e14591bb1a7.tar.gz
linux: add nanosecond durations when SG3_UTILS_LINUX_NANO environment variable given
git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@809 6180dd3e-e324-4e3e-922d-17de1ae2f315
Diffstat (limited to 'lib')
-rw-r--r--lib/sg_cmds_basic.c24
-rw-r--r--lib/sg_lib.c2
-rw-r--r--lib/sg_pt_common.c2
-rw-r--r--lib/sg_pt_freebsd.c8
-rw-r--r--lib/sg_pt_linux.c110
-rw-r--r--lib/sg_pt_osf1.c8
-rw-r--r--lib/sg_pt_solaris.c8
-rw-r--r--lib/sg_pt_win32.c8
8 files changed, 143 insertions, 27 deletions
diff --git a/lib/sg_cmds_basic.c b/lib/sg_cmds_basic.c
index 3e26af24..927c92a5 100644
--- a/lib/sg_cmds_basic.c
+++ b/lib/sg_cmds_basic.c
@@ -23,6 +23,8 @@
#include <errno.h>
#include <string.h>
#include <unistd.h>
+#define __STDC_FORMAT_MACROS 1
+#include <inttypes.h>
#ifdef HAVE_CONFIG_H
#include "config.h"
@@ -40,7 +42,7 @@
#endif
-static const char * const version_str = "1.91 20190113";
+static const char * const version_str = "1.93 20190128";
#define SENSE_BUFF_LEN 64 /* Arbitrary, could be larger */
@@ -190,7 +192,7 @@ sg_cmds_process_resp(struct sg_pt_base * ptvp, const char * leadin,
int pt_res, bool noisy, int verbose, int * o_sense_cat)
{
bool transport_sense;
- int cat, duration, slen, resp_code, sstat, req_din_x, req_dout_x;
+ int cat, slen, resp_code, sstat, req_din_x, req_dout_x;
int act_din_x, act_dout_x;
const uint8_t * sbp;
char b[1024];
@@ -223,8 +225,18 @@ sg_cmds_process_resp(struct sg_pt_base * ptvp, const char * leadin,
pr2ws("%s: %s timeout\n", leadin, pass_through_s);
return -1;
}
- if ((verbose > 2) && ((duration = get_scsi_pt_duration_ms(ptvp)) >= 0))
- pr2ws(" duration=%d ms\n", duration);
+ if (verbose > 2) {
+ uint64_t duration = get_pt_duration_ns(ptvp);
+
+ if (duration > 0)
+ pr2ws(" duration=%" PRIu64 " ns\n", duration);
+ else {
+ int d = get_scsi_pt_duration_ms(ptvp);
+
+ if (d != -1)
+ pr2ws(" duration=%u ms\n", (uint32_t)d);
+ }
+ }
get_pt_req_lengths(ptvp, &req_din_x, &req_dout_x);
get_pt_actual_lengths(ptvp, &act_din_x, &act_dout_x);
slen = get_scsi_pt_sense_len(ptvp);
@@ -503,7 +515,7 @@ sg_simple_inquiry(int sg_fd, struct sg_simple_inquiry_resp * inq_data,
inq_data->peripheral_qualifier = 0x3;
inq_data->peripheral_type = 0x1f;
}
- inq_resp = sg_memalign(SAFE_STD_INQ_RESP_LEN, 0, &free_irp, verbose > 4);
+ inq_resp = sg_memalign(SAFE_STD_INQ_RESP_LEN, 0, &free_irp, false);
if (NULL == inq_resp) {
pr2ws("%s: out of memory\n", __func__);
return sg_convert_errno(ENOMEM);
@@ -545,7 +557,7 @@ sg_simple_inquiry_pt(struct sg_pt_base * ptvp,
inq_data->peripheral_qualifier = 0x3;
inq_data->peripheral_type = 0x1f;
}
- inq_resp = sg_memalign(SAFE_STD_INQ_RESP_LEN, 0, &free_irp, verbose > 4);
+ inq_resp = sg_memalign(SAFE_STD_INQ_RESP_LEN, 0, &free_irp, false);
if (NULL == inq_resp) {
pr2ws("%s: out of memory\n", __func__);
return sg_convert_errno(ENOMEM);
diff --git a/lib/sg_lib.c b/lib/sg_lib.c
index 3e40c111..79783974 100644
--- a/lib/sg_lib.c
+++ b/lib/sg_lib.c
@@ -1914,7 +1914,7 @@ sg_print_sense(const char * leadin, const uint8_t * sbp, int sb_len,
char *cp;
uint8_t *free_cp;
- cp = (char *)sg_memalign(pg_sz, pg_sz, &free_cp, 0);
+ cp = (char *)sg_memalign(pg_sz, pg_sz, &free_cp, false);
if (NULL == cp)
return;
sg_get_sense_str(leadin, sbp, sb_len, raw_sinfo, pg_sz, cp);
diff --git a/lib/sg_pt_common.c b/lib/sg_pt_common.c
index ffd76c1d..48bf4b2e 100644
--- a/lib/sg_pt_common.c
+++ b/lib/sg_pt_common.c
@@ -31,7 +31,7 @@
#include "sg_pt_nvme.h"
#endif
-static const char * scsi_pt_version_str = "3.10 20190113";
+static const char * scsi_pt_version_str = "3.11 20190128";
const char *
diff --git a/lib/sg_pt_freebsd.c b/lib/sg_pt_freebsd.c
index 3c38dbe6..596c77aa 100644
--- a/lib/sg_pt_freebsd.c
+++ b/lib/sg_pt_freebsd.c
@@ -890,6 +890,14 @@ get_scsi_pt_duration_ms(const struct sg_pt_base * vp __attribute__ ((unused)))
return -1;
}
+/* If not available return 0 otherwise return number of nanoseconds that the
+ * lower layers (and hardware) took to execute the command just completed. */
+uint64_t
+get_pt_duration_ns(const struct sg_pt_base * vp __attribute__ ((unused)))
+{
+ return 0;
+}
+
int
get_scsi_pt_transport_err(const struct sg_pt_base * vp)
{
diff --git a/lib/sg_pt_linux.c b/lib/sg_pt_linux.c
index 0b50e439..4a570f8e 100644
--- a/lib/sg_pt_linux.c
+++ b/lib/sg_pt_linux.c
@@ -109,6 +109,10 @@ bool sg_bsg_nvme_char_major_checked = false;
int sg_bsg_major = 0;
volatile int sg_nvme_char_major = 0;
+bool sg_checked_version_num = false;
+int sg_driver_version_num = 0;
+bool sg_duration_set_nano = false;
+
long sg_lin_page_size = 4096; /* default, overridden with correct value */
@@ -470,6 +474,36 @@ clear_scsi_pt_obj(struct sg_pt_base * vp)
}
}
+#ifndef SG_SET_GET_EXTENDED
+
+/* If both sei_wr_mask and sei_rd_mask are 0, this ioctl does nothing */
+struct sg_extended_info {
+ uint32_t sei_wr_mask; /* OR-ed SG_SEIM_* user->driver values */
+ uint32_t sei_rd_mask; /* OR-ed SG_SEIM_* driver->user values */
+ uint32_t ctl_flags_wr_mask; /* OR-ed SG_CTL_FLAGM_* values */
+ uint32_t ctl_flags_rd_mask; /* OR-ed SG_CTL_FLAGM_* values */
+ uint32_t ctl_flags; /* bit values OR-ed, see SG_CTL_FLAGM_* */
+ uint32_t read_value; /* write SG_SEIRV_*, read back related */
+
+ uint32_t reserved_sz; /* data/sgl size of pre-allocated request */
+ uint32_t tot_fd_thresh; /* total data/sgat for this fd, 0: no limit */
+ uint32_t minor_index; /* rd: kernel's sg device minor number */
+ uint32_t share_fd; /* SHARE_FD and CHG_SHARE_FD use this */
+ uint32_t sgat_elem_sz; /* sgat element size (must be power of 2) */
+ uint8_t pad_to_96[52]; /* pad so struct is 96 bytes long */
+};
+
+#define SG_IOCTL_MAGIC_NUM 0x22
+
+#define SG_SET_GET_EXTENDED _IOWR(SG_IOCTL_MAGIC_NUM, 0x51, \
+ struct sg_extended_info)
+
+#define SG_SEIM_CTL_FLAGS 0x1
+
+#define SG_CTL_FLAGM_TIME_IN_NS 0x1
+
+#endif
+
/* Forget any previous dev_fd and install the one given. May attempt to
* find file type (e.g. if pass-though) from OS so there could be an error.
* Returns 0 for success or the same value as get_scsi_pt_os_err()
@@ -489,12 +523,15 @@ set_pt_file_handle(struct sg_pt_base * vp, int dev_fd, int verbose)
ptp->is_sg = check_file_type(dev_fd, &a_stat, &ptp->is_bsg,
&ptp->is_nvme, &ptp->nvme_nsid,
&ptp->os_err, verbose);
- if (ptp->is_sg) {
+ if (ptp->is_sg && (! sg_checked_version_num)) {
if (ioctl(dev_fd, SG_GET_VERSION_NUM, &ptp->sg_version) < 0) {
ptp->sg_version = 0;
if (verbose > 3)
pr2ws("%s: ioctl(SG_GET_VERSION_NUM) failed: errno: %d "
"[%s]\n", __func__, errno, safe_strerror(errno));
+ } else { /* got version number */
+ sg_driver_version_num = ptp->sg_version;
+ sg_checked_version_num = true;
}
if (verbose > 4) {
int ver = ptp->sg_version;
@@ -514,6 +551,30 @@ set_pt_file_handle(struct sg_pt_base * vp, int dev_fd, int verbose)
__func__, ver / 10000, (ver / 100) % 100,
ver % 100);
}
+ } else if (ptp->is_sg)
+ ptp->sg_version = sg_driver_version_num;
+
+ if (ptp->is_sg && (ptp->sg_version >= SG_LINUX_SG_VER_V4) &&
+ getenv("SG3_UTILS_LINUX_NANO")) {
+ struct sg_extended_info sei;
+ struct sg_extended_info * seip = &sei;
+
+ memset(seip, 0, sizeof(*seip));
+ /* try to override default of milliseconds */
+ seip->sei_wr_mask |= SG_SEIM_CTL_FLAGS;
+ seip->ctl_flags_wr_mask |= SG_CTL_FLAGM_TIME_IN_NS;
+ seip->ctl_flags |= SG_CTL_FLAGM_TIME_IN_NS;
+ if (ioctl(dev_fd, SG_SET_GET_EXTENDED, seip) < 0) {
+ if (verbose > 2)
+ pr2ws("%s: unable to override milli --> nanoseconds: "
+ "%s\n", __func__, safe_strerror(errno));
+ } else {
+ if (! sg_duration_set_nano)
+ sg_duration_set_nano = true;
+ if (verbose > 5)
+ pr2ws("%s: dev_fd=%d, succeeding in setting durations "
+ "to nanoseconds\n", __func__, dev_fd);
+ }
}
} else {
ptp->is_sg = false;
@@ -708,16 +769,16 @@ get_pt_req_lengths(const struct sg_pt_base * vp, int * req_dinp,
const struct sg_pt_linux_scsi * ptp = &vp->impl;
if (req_dinp) {
- if (ptp->io_hdr.din_xfer_len > 0)
- *req_dinp = ptp->io_hdr.din_xfer_len;
- else
- *req_dinp = 0;
+ if (ptp->io_hdr.din_xfer_len > 0)
+ *req_dinp = ptp->io_hdr.din_xfer_len;
+ else
+ *req_dinp = 0;
}
if (req_doutp) {
- if (ptp->io_hdr.dout_xfer_len > 0)
- *req_doutp = ptp->io_hdr.dout_xfer_len;
- else
- *req_doutp = 0;
+ if (ptp->io_hdr.dout_xfer_len > 0)
+ *req_doutp = ptp->io_hdr.dout_xfer_len;
+ else
+ *req_doutp = 0;
}
}
@@ -728,18 +789,18 @@ get_pt_actual_lengths(const struct sg_pt_base * vp, int * act_dinp,
const struct sg_pt_linux_scsi * ptp = &vp->impl;
if (act_dinp) {
- if (ptp->io_hdr.din_xfer_len > 0) {
- int res = ptp->io_hdr.din_xfer_len - ptp->io_hdr.din_resid;
+ if (ptp->io_hdr.din_xfer_len > 0) {
+ int res = ptp->io_hdr.din_xfer_len - ptp->io_hdr.din_resid;
- *act_dinp = (res > 0) ? res : 0;
- } else
- *act_dinp = 0;
+ *act_dinp = (res > 0) ? res : 0;
+ } else
+ *act_dinp = 0;
}
if (act_doutp) {
- if (ptp->io_hdr.dout_xfer_len > 0)
- *act_doutp = ptp->io_hdr.dout_xfer_len - ptp->io_hdr.dout_resid;
- else
- *act_doutp = 0;
+ if (ptp->io_hdr.dout_xfer_len > 0)
+ *act_doutp = ptp->io_hdr.dout_xfer_len - ptp->io_hdr.dout_resid;
+ else
+ *act_doutp = 0;
}
}
@@ -786,7 +847,18 @@ get_scsi_pt_duration_ms(const struct sg_pt_base * vp)
{
const struct sg_pt_linux_scsi * ptp = &vp->impl;
- return ptp->io_hdr.duration;
+ return sg_duration_set_nano ? (ptp->io_hdr.duration / 1000) :
+ ptp->io_hdr.duration;
+}
+
+/* If not available return 0 otherwise return number of nanoseconds that the
+ * lower layers (and hardware) took to execute the command just completed. */
+uint64_t
+get_pt_duration_ns(const struct sg_pt_base * vp)
+{
+ const struct sg_pt_linux_scsi * ptp = &vp->impl;
+
+ return sg_duration_set_nano ? (uint32_t)ptp->io_hdr.duration : 0;
}
int
diff --git a/lib/sg_pt_osf1.c b/lib/sg_pt_osf1.c
index 3114a8b1..18ba5287 100644
--- a/lib/sg_pt_osf1.c
+++ b/lib/sg_pt_osf1.c
@@ -539,6 +539,14 @@ get_scsi_pt_duration_ms(const struct sg_pt_base * vp)
return -1;
}
+/* If not available return 0 otherwise return number of nanoseconds that the
+ * lower layers (and hardware) took to execute the command just completed. */
+uint64_t
+get_pt_duration_ns(const struct sg_pt_base * vp __attribute__ ((unused)))
+{
+ return 0;
+}
+
int
get_scsi_pt_transport_err(const struct sg_pt_base * vp)
{
diff --git a/lib/sg_pt_solaris.c b/lib/sg_pt_solaris.c
index e8d71dc6..3d0cb228 100644
--- a/lib/sg_pt_solaris.c
+++ b/lib/sg_pt_solaris.c
@@ -413,6 +413,14 @@ get_scsi_pt_duration_ms(const struct sg_pt_base * vp)
return -1; /* not available */
}
+/* If not available return 0 otherwise return number of nanoseconds that the
+ * lower layers (and hardware) took to execute the command just completed. */
+uint64_t
+get_pt_duration_ns(const struct sg_pt_base * vp __attribute__ ((unused)))
+{
+ return 0;
+}
+
int
get_scsi_pt_transport_err(const struct sg_pt_base * vp)
{
diff --git a/lib/sg_pt_win32.c b/lib/sg_pt_win32.c
index e357ff22..65e3f2b9 100644
--- a/lib/sg_pt_win32.c
+++ b/lib/sg_pt_win32.c
@@ -1360,6 +1360,14 @@ get_scsi_pt_duration_ms(const struct sg_pt_base * vp __attribute__ ((unused)))
return -1;
}
+/* If not available return 0 otherwise return number of nanoseconds that the
+ * lower layers (and hardware) took to execute the command just completed. */
+uint64_t
+get_pt_duration_ns(const struct sg_pt_base * vp __attribute__ ((unused)))
+{
+ return 0;
+}
+
int
get_scsi_pt_transport_err(const struct sg_pt_base * vp)
{