diff options
author | Douglas Gilbert <dgilbert@interlog.com> | 2019-01-31 14:29:54 +0000 |
---|---|---|
committer | Douglas Gilbert <dgilbert@interlog.com> | 2019-01-31 14:29:54 +0000 |
commit | 04adb7f5027fb9f8b4368e4eaa561e14591bb1a7 (patch) | |
tree | 7f3af533e28c692c020eabd152b49762f340f106 /lib | |
parent | a918d1a30569c4d3f09cc87836ff19215db6d8b7 (diff) | |
download | sg3_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.c | 24 | ||||
-rw-r--r-- | lib/sg_lib.c | 2 | ||||
-rw-r--r-- | lib/sg_pt_common.c | 2 | ||||
-rw-r--r-- | lib/sg_pt_freebsd.c | 8 | ||||
-rw-r--r-- | lib/sg_pt_linux.c | 110 | ||||
-rw-r--r-- | lib/sg_pt_osf1.c | 8 | ||||
-rw-r--r-- | lib/sg_pt_solaris.c | 8 | ||||
-rw-r--r-- | lib/sg_pt_win32.c | 8 |
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) { |