aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gilbert <dgilbert@interlog.com>2019-04-14 23:06:18 +0000
committerDouglas Gilbert <dgilbert@interlog.com>2019-04-14 23:06:18 +0000
commitf55a523cb14c613b30b6d63fe78c892e8a414e3a (patch)
treed5a6a5f344ec7872137356aac114d2279185218b
parentcc730c8de77b8f35d924cb4a01437f7166d85e12 (diff)
downloadsg3_utils-f55a523cb14c613b30b6d63fe78c892e8a414e3a.tar.gz
testing folder utilities for sg v4 driver
git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@818 6180dd3e-e324-4e3e-922d-17de1ae2f315
-rw-r--r--ChangeLog2
-rw-r--r--testing/sg_tst_async.cpp15
-rw-r--r--testing/sgh_dd.cpp98
-rw-r--r--testing/sgs_dd.c24
4 files changed, 85 insertions, 54 deletions
diff --git a/ChangeLog b/ChangeLog
index 4350f984..6d0d0d3a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,7 +2,7 @@ Each utility has its own version number, date of last change and
some description at the top of its ".c" file. All utilities in the main
directory have their own "man" pages. There is also a sg3_utils man page.
-Changelog for sg3_utils-1.45 [20190410] [svn: r817]
+Changelog for sg3_utils-1.45 [20190414] [svn: r818]
- sg_ses: bug: --page= being overridden when --control
and --data= also given; fix
- sg_opcodes: expand MLU (spc5r20)
diff --git a/testing/sg_tst_async.cpp b/testing/sg_tst_async.cpp
index bdd024fb..e33d8ec0 100644
--- a/testing/sg_tst_async.cpp
+++ b/testing/sg_tst_async.cpp
@@ -89,7 +89,7 @@
#include "sg_pt.h"
#include "sg_cmds.h"
-static const char * version_str = "1.26 20190409";
+static const char * version_str = "1.28 20190414";
static const char * util_name = "sg_tst_async";
/* This is a test program for checking the async usage of the Linux sg
@@ -372,7 +372,8 @@ usage(void)
"Each thread queues up to NT commands.\nOne block is transferred "
"by each READ and WRITE; zeros are written. If a\nlogical block "
"range is given, a uniform distribution generates a pseudo\n"
- "random sequence of LBAs.\n");
+ "random sequence of LBAs. Set environment variable\n"
+ "SG3_UTILS_LINUX_NANO to get command timings in nanoseconds\n");
}
#ifdef __GNUC__
@@ -1001,7 +1002,9 @@ work_thread(int id, struct opts_t * op)
memset(seip, 0, sizeof(*seip));
seip->sei_wr_mask |= SG_SEIM_CTL_FLAGS;
seip->sei_rd_mask |= SG_SEIM_CTL_FLAGS;
+ seip->ctl_flags_wr_mask |= SG_CTL_FLAGM_TIME_IN_NS;
seip->ctl_flags_rd_mask |= SG_CTL_FLAGM_TIME_IN_NS;
+ seip->ctl_flags |= SG_CTL_FLAGM_TIME_IN_NS;
if (ioctl(sg_fd, SG_SET_GET_EXTENDED, seip) < 0) {
pr2serr_lk("ioctl(EXTENDED(TIME_IN_NS)) failed, errno=%d %s\n",
errno, strerror(errno));
@@ -1916,10 +1919,10 @@ main(int argc, char * argv[])
op->maxq_per_thread = 1;
}
if (! op->cmd_time && getenv("SG3_UTILS_LINUX_NANO")) {
- op->cmd_time = true;
- if (op->verbose)
- fprintf(stderr, "setting nanosecond timing due to environment "
- "variable: SG3_UTILS_LINUX_NANO\n");
+ op->cmd_time = true;
+ if (op->verbose)
+ fprintf(stderr, "setting nanosecond timing due to environment "
+ "variable: SG3_UTILS_LINUX_NANO\n");
}
if (0 == op->dev_names.size()) {
fprintf(stderr, "No sg_disk_device-s given\n\n");
diff --git a/testing/sgh_dd.cpp b/testing/sgh_dd.cpp
index b7608cfb..c982c868 100644
--- a/testing/sgh_dd.cpp
+++ b/testing/sgh_dd.cpp
@@ -103,7 +103,7 @@
using namespace std;
-static const char * version_str = "1.22 20190331";
+static const char * version_str = "1.25 20190413";
#ifdef __GNUC__
#ifndef __clang__
@@ -213,6 +213,7 @@ typedef struct global_collection
int dry_run;
bool ofile_given;
bool ofile2_given;
+ bool unit_nanosec; /* default duration unit is millisecond */
const char * infp;
const char * outfp;
const char * out2fp;
@@ -278,8 +279,9 @@ static void sg_out_wr_cmd(Gbl_coll * clp, Rq_elem * rep, mrq_arr_t & def_arr,
bool is_wr2);
static bool normal_in_rd(Gbl_coll * clp, Rq_elem * rep, int blocks);
static void normal_out_wr(Gbl_coll * clp, Rq_elem * rep, int blocks);
-static int sg_start_io(Rq_elem * rep, mrq_arr_t & def_arr, bool is_wr2);
-static int sg_finish_io(bool wr, Rq_elem * rep, bool is_wr2);
+static int sg_start_io(Rq_elem * rep, mrq_arr_t & def_arr, int & pack_id,
+ bool is_wr2);
+static int sg_finish_io(bool wr, Rq_elem * rep, int pack_id, bool is_wr2);
static int sg_in_open(Gbl_coll *clp, const char *inf, uint8_t **mmpp,
int *mmap_len);
static int sg_out_open(Gbl_coll *clp, const char *outf, uint8_t **mmpp,
@@ -669,7 +671,7 @@ page2:
" sync 0->no sync(def), 1->SYNCHRONIZE CACHE on OFILE "
"after copy\n"
" thr is number of threads, must be > 0, default 4, "
- "max 16\n"
+ "max 1024\n"
" time 0->no timing, 1->time plus calculate "
"throughput (def)\n"
" verbose same as 'deb=VERB': increase verbosity\n"
@@ -899,7 +901,7 @@ read_write_thread(void * v_tip)
memset(rep, 0, sizeof(Rq_elem));
/* Following clp members are constant during lifetime of thread */
rep->id = tip->id;
- if (vb > 0)
+ if (vb > 2)
pr2serr_lk("%d <-- Starting worker thread\n", rep->id);
if (! clp->in_flags.mmap) {
rep->buffp = sg_memalign(sz, 0 /* page align */, &rep->alloc_bp,
@@ -990,7 +992,7 @@ read_write_thread(void * v_tip)
rep->out2fd);
}
if (rep->in_flags.noshare || rep->out_flags.noshare) {
- if (vb)
+ if (vb > 4)
pr2serr_lk("thread=%d: Skipping share on both IFILE and OFILE\n",
rep->id);
} else if ((FT_SG == clp->in_type) && (FT_SG == clp->out_type))
@@ -1345,11 +1347,10 @@ sg_build_scsi_cdb(uint8_t * cdbp, int cdb_sz, unsigned int blocks,
static void
sg_in_rd_cmd(Gbl_coll * clp, Rq_elem * rep, mrq_arr_t & def_arr)
{
- int res;
- int status;
+ int res, status, pack_id;
while (1) {
- res = sg_start_io(rep, def_arr, false);
+ res = sg_start_io(rep, def_arr, pack_id, false);
if (1 == res)
err_exit(ENOMEM, "sg starting in command");
else if (res < 0) {
@@ -1364,7 +1365,7 @@ sg_in_rd_cmd(Gbl_coll * clp, Rq_elem * rep, mrq_arr_t & def_arr)
status = pthread_mutex_unlock(&clp->in_mutex);
if (0 != status) err_exit(status, "unlock in_mutex");
- res = sg_finish_io(rep->wr, rep, false);
+ res = sg_finish_io(rep->wr, rep, pack_id, false);
switch (res) {
case SG_LIB_CAT_ABORTED_COMMAND:
case SG_LIB_CAT_UNIT_ATTENTION:
@@ -1465,15 +1466,14 @@ sg_wr_swap_share(Rq_elem * rep, int to_fd, bool before)
static void
sg_out_wr_cmd(Gbl_coll * clp, Rq_elem * rep, mrq_arr_t & def_arr, bool is_wr2)
{
- int res;
- int status;
+ int res, status, pack_id;
pthread_mutex_t * mutexp = is_wr2 ? &clp->out2_mutex : &clp->out_mutex;
if (rep->has_share && is_wr2)
sg_wr_swap_share(rep, rep->out2fd, true);
while (1) {
- res = sg_start_io(rep, def_arr, is_wr2);
+ res = sg_start_io(rep, def_arr, pack_id, is_wr2);
if (1 == res)
err_exit(ENOMEM, "sg starting out command");
else if (res < 0) {
@@ -1488,7 +1488,7 @@ sg_out_wr_cmd(Gbl_coll * clp, Rq_elem * rep, mrq_arr_t & def_arr, bool is_wr2)
status = pthread_mutex_unlock(mutexp);
if (0 != status) err_exit(status, "unlock out_mutex");
- res = sg_finish_io(rep->wr, rep, is_wr2);
+ res = sg_finish_io(rep->wr, rep, pack_id, is_wr2);
switch (res) {
case SG_LIB_CAT_ABORTED_COMMAND:
case SG_LIB_CAT_UNIT_ATTENTION:
@@ -1611,7 +1611,8 @@ sgh_do_def(Rq_elem * rep, mrq_arr_t & def_arr)
/* Returns 0 on success, 1 if ENOMEM error else -1 for other errors. */
static int
-sg_start_io(Rq_elem * rep, mrq_arr_t & def_arr, bool is_wr2)
+sg_start_io(Rq_elem * rep, mrq_arr_t & def_arr, int & pack_id,
+ bool is_wr2)
{
bool wr = rep->wr;
bool fua = wr ? rep->out_flags.fua : rep->in_flags.fua;
@@ -1664,10 +1665,11 @@ sg_start_io(Rq_elem * rep, mrq_arr_t & def_arr, bool is_wr2)
cp = (wr ? " slave active" : " master active");
} else
cp = (wr ? " slave not sharing" : " master not sharing");
- rep->rq_id = atomic_fetch_add(&mono_pack_id, 1); /* fetch before */
+ pack_id = atomic_fetch_add(&mono_pack_id, 1); /* fetch before */
+ rep->rq_id = pack_id;
if (rep->debug > 3) {
pr2serr_lk("%s tid,rq_id=%d,%d: SCSI %s%s%s%s, blk=%" PRId64
- " num_blks=%d\n", __func__, rep->id, rep->rq_id, crwp, cp,
+ " num_blks=%d\n", __func__, rep->id, pack_id, crwp, cp,
c2p, c3p, blk, rep->num_blks);
lk_print_command(rep->cmd);
}
@@ -1685,7 +1687,7 @@ sg_start_io(Rq_elem * rep, mrq_arr_t & def_arr, bool is_wr2)
hp->sbp = rep->sb;
hp->timeout = DEF_TIMEOUT;
hp->usr_ptr = rep;
- hp->pack_id = rep->rq_id;
+ hp->pack_id = pack_id;
hp->flags = flags;
while (((res = write(fd, hp, sizeof(struct sg_io_hdr))) < 0) &&
@@ -1716,8 +1718,8 @@ do_v4:
h4p->response = (uint64_t)rep->sb;
h4p->timeout = DEF_TIMEOUT;
h4p->usr_ptr = (uint64_t)rep;
- h4p->request_extra = rep->rq_id; /* this is the pack_id */
- h4p->flags = flags;
+ h4p->request_extra = pack_id; /* this is the pack_id */
+ h4p->flags = flags | SGV4_FLAG_IMMED;
if (rep->nmrqs > 0) {
if (rep->both_sg && (rep->outfd == fd))
h4p->flags |= SGV4_FLAG_DO_ON_OTHER;
@@ -1760,7 +1762,7 @@ do_v4:
__func__, safe_strerror(errno), errno);
else if (rep->debug > 1)
pr2serr_lk("%s: sending ioctl(SG_IOABORT) on rq_id=%d\n",
- __func__, rep->rq_id);
+ __func__, pack_id);
} /* else got response, too late for timeout, so skip */
}
}
@@ -1771,7 +1773,7 @@ do_v4:
-> try again, SG_LIB_CAT_NOT_READY, SG_LIB_CAT_MEDIUM_HARD,
-1 other errors */
static int
-sg_finish_io(bool wr, Rq_elem * rep, bool is_wr2)
+sg_finish_io(bool wr, Rq_elem * rep, int pack_id, bool is_wr2)
{
bool v4 = wr ? rep->out_flags.v4 : rep->in_flags.v4;
int res, fd;
@@ -1797,7 +1799,7 @@ sg_finish_io(bool wr, Rq_elem * rep, bool is_wr2)
/* FORCE_PACK_ID active set only read packet with matching pack_id */
io_hdr.interface_id = 'S';
io_hdr.dxfer_direction = wr ? SG_DXFER_TO_DEV : SG_DXFER_FROM_DEV;
- io_hdr.pack_id = rep->rq_id;
+ io_hdr.pack_id = pack_id;
while (((res = read(fd, &io_hdr, sizeof(struct sg_io_hdr))) < 0) &&
((EINTR == errno) || (EAGAIN == errno)))
@@ -1852,6 +1854,7 @@ do_v4:
return 0;
}
h4p = &rep->io_hdr4;
+ h4p->request_extra = pack_id;
while (((res = ioctl(fd, SG_IORECEIVE, h4p)) < 0) &&
((EINTR == errno) || (EAGAIN == errno)))
sched_yield(); /* another thread may be able to progress */
@@ -1882,7 +1885,7 @@ do_v4:
char ebuff[EBUFF_SZ];
snprintf(ebuff, EBUFF_SZ, "%s rq_id=%d, blk=%" PRId64, cp,
- rep->rq_id, blk);
+ pack_id, blk);
lk_chk_n_print4(ebuff, h4p, false);
if ((rep->debug > 4) && h4p->info)
pr2serr_lk(" info=0x%x sg_info_check=%d direct=%d "
@@ -1905,7 +1908,7 @@ do_v4:
rep->resid = h4p->din_resid;
if (rep->debug > 3) {
pr2serr_lk("%s: tid,rq_id=%d,%d: completed %s\n", __func__, rep->id,
- rep->rq_id, cp);
+ pack_id, cp);
if ((rep->debug > 4) && h4p->info)
pr2serr_lk(" info=0x%x sg_info_check=%d direct=%d "
"detaching=%d aborted=%d\n", h4p->info,
@@ -1926,8 +1929,7 @@ sg_in_out_interleave(Gbl_coll *clp, Rq_elem * rep, mrq_arr_t & def_arr)
while (1) {
/* start READ */
- res = sg_start_io(rep, def_arr, false);
- pid_read = rep->rq_id;
+ res = sg_start_io(rep, def_arr, pid_read, false);
if (1 == res)
err_exit(ENOMEM, "sg interleave starting in command");
else if (res < 0) {
@@ -1941,8 +1943,7 @@ sg_in_out_interleave(Gbl_coll *clp, Rq_elem * rep, mrq_arr_t & def_arr)
/* start WRITE */
rep->wr = true;
- res = sg_start_io(rep, def_arr, false);
- pid_write = rep->rq_id;
+ res = sg_start_io(rep, def_arr, pid_write, false);
if (1 == res)
err_exit(ENOMEM, "sg interleave starting out command");
else if (res < 0) {
@@ -1964,9 +1965,8 @@ read_complet:
#endif
/* finish READ */
- rep->rq_id = pid_read;
rep->wr = false;
- res = sg_finish_io(rep->wr, rep, false);
+ res = sg_finish_io(rep->wr, rep, pid_read, false);
switch (res) {
case SG_LIB_CAT_ABORTED_COMMAND:
case SG_LIB_CAT_UNIT_ATTENTION:
@@ -2025,9 +2025,8 @@ read_complet:
write_complet:
#endif
/* finish WRITE, no lock held */
- rep->rq_id = pid_write;
rep->wr = true;
- res = sg_finish_io(rep->wr, rep, false);
+ res = sg_finish_io(rep->wr, rep, pid_write, false);
switch (res) {
case SG_LIB_CAT_ABORTED_COMMAND:
case SG_LIB_CAT_UNIT_ATTENTION:
@@ -2081,21 +2080,20 @@ write_complet:
/* Returns reserved_buffer_size/mmap_size if success, else 0 for failure */
static int
sg_prepare_resbuf(int fd, int bs, int bpt, bool def_res, int elem_sz,
- uint8_t **mmpp)
+ bool unit_nano, uint8_t **mmpp)
{
int res, t, num;
uint8_t *mmp;
+ struct sg_extended_info sei;
+ struct sg_extended_info * seip;
+ seip = &sei;
res = ioctl(fd, SG_GET_VERSION_NUM, &t);
if ((res < 0) || (t < 40000)) {
pr2serr_lk("%ssg driver prior to 4.0.00\n", my_name);
return 0;
}
if (elem_sz >= 4096) {
- struct sg_extended_info sei;
- struct sg_extended_info * seip;
-
- seip = &sei;
memset(seip, 0, sizeof(*seip));
seip->sei_rd_mask |= SG_SEIM_SGAT_ELEM_SZ;
res = ioctl(fd, SG_SET_GET_EXTENDED, seip);
@@ -2131,6 +2129,17 @@ sg_prepare_resbuf(int fd, int bs, int bpt, bool def_res, int elem_sz,
res = ioctl(fd, SG_SET_FORCE_PACK_ID, &t);
if (res < 0)
perror("sgh_dd: SG_SET_FORCE_PACK_ID error");
+ if (unit_nano) {
+ memset(seip, 0, sizeof(*seip));
+ 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(fd, SG_SET_GET_EXTENDED, seip) < 0) {
+ res = -1;
+ pr2serr_lk("ioctl(EXTENDED(TIME_IN_NS)) failed, errno=%d %s\n",
+ errno, strerror(errno));
+ }
+ }
return (res < 0) ? 0 : num;
}
@@ -2232,7 +2241,7 @@ sg_in_open(Gbl_coll *clp, const char *inf, uint8_t **mmpp, int * mmap_lenp)
return -sg_convert_errno(err);
}
n = sg_prepare_resbuf(fd, clp->bs, clp->bpt, clp->in_flags.defres,
- clp->elem_sz, mmpp);
+ clp->elem_sz, clp->unit_nanosec, mmpp);
if (n <= 0)
return -SG_LIB_FILE_ERROR;
if (mmap_lenp)
@@ -2262,7 +2271,7 @@ sg_out_open(Gbl_coll *clp, const char *outf, uint8_t **mmpp, int * mmap_lenp)
return -sg_convert_errno(err);
}
n = sg_prepare_resbuf(fd, clp->bs, clp->bpt, clp->out_flags.defres,
- clp->elem_sz, mmpp);
+ clp->elem_sz, clp->unit_nanosec, mmpp);
if (n <= 0)
return -SG_LIB_FILE_ERROR;
if (mmap_lenp)
@@ -2582,8 +2591,11 @@ main(int argc, char * argv[])
usage(1);
return SG_LIB_SYNTAX_ERROR;
}
- if (clp->in_flags.swait && (! clp->out_flags.swait))
- pr2serr("iflag=swait is ignored, it should be oflag=swait\n");
+ if (clp->in_flags.swait && (! clp->out_flags.swait)) {
+ pr2serr("iflag=swait is treated as oflag=swait\n");
+ clp->out_flags.swait = true;
+ }
+ clp->unit_nanosec = !!getenv("SG3_UTILS_LINUX_NANO");
if (clp->debug)
pr2serr("%sif=%s skip=%" PRId64 " of=%s seek=%" PRId64 " count=%"
PRId64 "\n", my_name, inf, skip, outf, seek, dd_count);
@@ -2995,7 +3007,7 @@ main(int argc, char * argv[])
tip = thread_arr + k;
status = pthread_join(tip->a_pthr, &vp);
if (0 != status) err_exit(status, "pthread_join");
- if (clp->debug > 0)
+ if (clp->debug > 2)
pr2serr_lk("%d <-- Worker thread terminated, vp=%s\n", k,
((vp == clp) ? "clp" : "NULL (or !clp)"));
}
diff --git a/testing/sgs_dd.c b/testing/sgs_dd.c
index 624c41b3..d4dabcab 100644
--- a/testing/sgs_dd.c
+++ b/testing/sgs_dd.c
@@ -78,7 +78,7 @@
#include "sg_unaligned.h"
-static const char * version_str = "4.04 20190324";
+static const char * version_str = "4.05 20190412";
static const char * my_name = "sgs_dd";
#define DEF_BLOCK_SIZE 512
@@ -170,7 +170,8 @@ typedef struct request_collection
Rq_elem elem[SGQ_NUM_ELEMS];
} Rq_coll;
-static bool sgs_old_sg_driver = false;
+static bool sgs_old_sg_driver = false; /* true if VERSION_NUM < 4.00.00 */
+static bool sgs_nanosec_unit = false;
static void
@@ -472,7 +473,10 @@ static int
sz_reserve(int fd, int bs, int bpt, bool rt_sig)
{
int res, t, flags;
+ struct sg_extended_info sei;
+ struct sg_extended_info * seip;
+ seip = &sei;
res = ioctl(fd, SG_GET_VERSION_NUM, &t);
if ((res < 0) || (t < 30000)) {
fprintf(stderr, "sgs_dd: sg driver prior to 3.0.00\n");
@@ -487,6 +491,18 @@ sz_reserve(int fd, int bs, int bpt, bool rt_sig)
res = ioctl(fd, SG_SET_RESERVED_SIZE, &t);
if (res < 0)
perror("sgs_dd: SG_SET_RESERVED_SIZE error");
+
+ if (sgs_nanosec_unit) {
+ memset(seip, 0, sizeof(*seip));
+ 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(fd, SG_SET_GET_EXTENDED, seip) < 0) {
+ pr2serr("ioctl(EXTENDED(TIME_IN_NS)) failed, errno=%d %s\n",
+ errno, strerror(errno));
+ return 1;
+ }
+ }
if (-1 == fcntl(fd, F_SETOWN, getpid())) {
perror("fcntl(F_SETOWN)");
return 1;
@@ -933,6 +949,7 @@ main(int argc, char * argv[])
usage();
return 1;
}
+ sgs_nanosec_unit = !!getenv("SG3_UTILS_LINUX_NANO");
for(k = 1; k < argc; k++) {
if (argv[k]) {
@@ -1045,8 +1062,7 @@ main(int argc, char * argv[])
return 1;
}
}
- }
- else { /* looks like sg device so close then re-open it RW */
+ } else { /* looks like sg device so close then re-open it RW */
close(clp->infd);
open_fl = clp->iflag.excl ? O_EXCL : 0;
open_fl |= (O_RDWR | O_NONBLOCK);