aboutsummaryrefslogtreecommitdiff
path: root/testing
diff options
context:
space:
mode:
authorDouglas Gilbert <dgilbert@interlog.com>2019-04-04 02:59:52 +0000
committerDouglas Gilbert <dgilbert@interlog.com>2019-04-04 02:59:52 +0000
commit3905f5ce447048fdc0fe1f9573cab87df97972bb (patch)
tree590175ec612ca729fbdc112c8b8b6a82d25ff74b /testing
parent8c86fe26b4e371af1fd007d076025a5d5e442f42 (diff)
downloadsg3_utils-3905f5ce447048fdc0fe1f9573cab87df97972bb.tar.gz
sgv4 support updates in testing
git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@816 6180dd3e-e324-4e3e-922d-17de1ae2f315
Diffstat (limited to 'testing')
-rw-r--r--testing/Makefile.cplus8
-rw-r--r--testing/sg_tst_async.cpp216
-rw-r--r--testing/sg_tst_ioctl.c21
-rw-r--r--testing/sgh_dd.cpp55
4 files changed, 227 insertions, 73 deletions
diff --git a/testing/Makefile.cplus b/testing/Makefile.cplus
index 34c94831..51a5bad7 100644
--- a/testing/Makefile.cplus
+++ b/testing/Makefile.cplus
@@ -4,10 +4,10 @@ PREFIX=/usr/local
INSTDIR=$(DESTDIR)/$(PREFIX)/bin
MANDIR=$(DESTDIR)/$(PREFIX)/man
-CC = g++
-LD = g++
-## CC = clang++
-## LD = clang++
+## CC = g++
+## LD = g++
+CXX = clang++-7
+LD = clang++-7
EXECS = sg_tst_excl sg_tst_excl2 sg_tst_excl3 sg_tst_context sg_tst_async \
sgh_dd
diff --git a/testing/sg_tst_async.cpp b/testing/sg_tst_async.cpp
index ab133348..cc4e9bba 100644
--- a/testing/sg_tst_async.cpp
+++ b/testing/sg_tst_async.cpp
@@ -55,6 +55,7 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
+#include <sys/resource.h> /* getrusage */
#ifdef HAVE_CONFIG_H
@@ -88,13 +89,13 @@
#include "sg_pt.h"
#include "sg_cmds.h"
-static const char * version_str = "1.25 20190128";
+static const char * version_str = "1.26 20190403";
static const char * util_name = "sg_tst_async";
/* This is a test program for checking the async usage of the Linux sg
* driver. Each thread opens 1 file descriptor to the next sg device (1
- * or more can be given on the command line) and then starts up to 16
- * commands or more while checking with the poll command (or
+ * or more can be given on the command line) and then starts up to
+ * num_per_thread commands or more while checking with the poll command (or
* ioctl(SG_GET_NUM_WAITING) ) for the completion of those commands. Each
* command has a unique "pack_id" which is a sequence starting at 1.
* Either TEST UNIT UNIT, READ(16) or WRITE(16) commands are issued.
@@ -142,7 +143,7 @@ using namespace std::chrono;
#define DEF_LBA 1000
#define MAX_Q_PER_FD 16383 /* sg driver per file descriptor limit */
-#define MAX_CONSEC_NOMEMS 16
+#define MAX_CONSEC_NOMEMS 4 /* was 16 */
#define URANDOM_DEV "/dev/urandom"
#ifndef SG_FLAG_Q_AT_TAIL
@@ -168,7 +169,7 @@ static atomic<int> start_eagain_count(0);
static atomic<int> fin_eagain_count(0);
static atomic<int> start_edom_count(0);
static atomic<int> uniq_pack_id(1);
-static atomic<int> generic_errs(0);
+// static atomic<int> generic_errs(0);
static int page_size = 4096; /* rough guess, will ask sysconf() */
@@ -486,7 +487,7 @@ start_sg3_cmd(int sg_fd, command2execute cmd2exe, int pack_id, uint64_t lba,
for (int k = 0;
(submit ? ioctl(sg_fd, SG_IOSUBMIT, ptp) :
- write(sg_fd, ptp, sizeof(*ptp)) < 0);
+ write(sg_fd, ptp, sizeof(*ptp)) < 0);
++k) {
if ((ENOMEM == errno) && (k < MAX_CONSEC_NOMEMS)) {
this_thread::yield();
@@ -771,6 +772,44 @@ finish_sg4_cmd(int sg_fd, command2execute cmd2exe, bool pack_id_force,
return ok ? 0 : -1;
}
+static int
+num_submitted(int sg_fd)
+{
+ uint32_t num_subm_wait = 0;
+ struct sg_extended_info sei;
+ struct sg_extended_info *seip = &sei;
+ const char * err = NULL;
+
+ memset(seip, 0, sizeof(*seip));
+ seip->sei_wr_mask |= SG_SEIM_READ_VAL;
+ seip->sei_rd_mask |= SG_SEIM_READ_VAL;
+ seip->read_value = SG_SEIRV_SUBMITTED;
+ if (ioctl(sg_fd, SG_SET_GET_EXTENDED, seip) < 0)
+ err = "ioctl(SG_SET_GET_EXTENDED) failed\n";
+ else
+ num_subm_wait = seip->read_value;
+ if (err)
+ pr2serr_lk("%s: %s, errno=%d\n", __func__, err, errno);
+ return err ? -1 : (int)num_subm_wait;
+}
+
+static int
+pr_rusage(int id)
+{
+ int res;
+ struct rusage ru;
+
+ res = getrusage(RUSAGE_SELF /* RUSAGE_THREAD */, &ru);
+ if (res < 0) {
+ pr2serr_lk("%d->id: %s: getrusage() failed, errno=%d\n", id,
+ __func__, errno);
+ return res;
+ }
+ pr2serr_lk("%d->id: maxrss=%ldKB nvcsw=%ld nivcsw=%ld majflt=%ld\n", id,
+ ru.ru_maxrss, ru.ru_nvcsw, ru.ru_nivcsw, ru.ru_majflt);
+ return 0;
+}
+
static void
work_sync_thread(int id, const char * dev_name, unsigned int /* hi_lba */,
struct opts_t * op)
@@ -858,12 +897,21 @@ work_thread(int id, struct opts_t * op)
{
bool is_rw = (SCSI_TUR != op->c2e);
bool need_finish, repeat;
+ bool once = false;
+ bool once1000 = false;
+ bool once_2000 = false;
+ bool once_4000 = false;
+ bool once5000 = false;
+ bool once_6000 = false;
+ bool once_7000 = false;
+ bool once10_000 = false;
+ bool once20_000 = false;
int open_flags = O_RDWR;
int thr_async_starts = 0;
int thr_async_finishes = 0;
int vb = op->verbose;
int k, n, res, sg_fd, num_outstanding, do_inc, npt, pack_id, sg_flags;
- int num_waiting_read, num_to_read, sz, ern, encore_pack_id, ask, j;
+ int num_waiting_read, num_to_read, sz, ern, encore_pack_id, ask, j, m, o;
int prev_pack_id;
unsigned int thr_start_eagain_count = 0;
unsigned int thr_start_ebusy_count = 0;
@@ -1020,10 +1068,86 @@ work_thread(int id, struct opts_t * op)
pack_id = 0;
prev_pack_id = 0;
encore_pack_id = 0;
+ do_inc = 0;
/* main loop, continues until num_per_thread exhausted and there are
* no more outstanding responses */
- for (k = 0, num_outstanding = 0; (k < npt) || num_outstanding;
- k = do_inc ? k + 1 : k) {
+ for (k = 0, m = 0, o=0, num_outstanding = 0; (k < npt) || num_outstanding;
+ k = do_inc ? k + 1 : k, ++o) {
+ if (do_inc)
+ m = 0;
+ else {
+ ++m;
+ if (m > 100) {
+ pr2serr_lk("%d->id: m=%d\n", id, m);
+ m = 0;
+ }
+ }
+ if (vb && ! once1000 && num_outstanding >= 1000) {
+ int num_waiting;
+ int num_subm = (op->sg_vn_ge_30901) ? num_submitted(sg_fd) : -1;
+
+ once1000 = true;
+ if (ioctl(sg_fd, SG_GET_NUM_WAITING, &num_waiting) < 0) {
+ err = "ioctl(SG_GET_NUM_WAITING) failed";
+ break;
+ }
+ pr2serr_lk("%d->id: once 1000: k=%d, submitted=%d waiting=%d; "
+ "pi2buff.sz=%u\n", id, k, num_subm, num_waiting,
+ (uint32_t)pi2buff.size());
+ pr_rusage(id);
+ }
+ if (vb && ! once5000 && num_outstanding >= 5000) {
+ int num_waiting;
+ int num_subm = (op->sg_vn_ge_30901) ? num_submitted(sg_fd) : -1;
+
+ once5000 = true;
+ if (ioctl(sg_fd, SG_GET_NUM_WAITING, &num_waiting) < 0) {
+ err = "ioctl(SG_GET_NUM_WAITING) failed";
+ break;
+ }
+ pr2serr_lk("%d->id: once 5000: k=%d, submitted=%d waiting=%d\n",
+ id, k, num_subm, num_waiting);
+ pr_rusage(id);
+ }
+ if (vb && ! once_7000 && num_outstanding >= 7000) {
+ int num_waiting;
+ int num_subm = (op->sg_vn_ge_30901) ? num_submitted(sg_fd) : -1;
+
+ once_7000 = true;
+ if (ioctl(sg_fd, SG_GET_NUM_WAITING, &num_waiting) < 0) {
+ err = "ioctl(SG_GET_NUM_WAITING) failed";
+ break;
+ }
+ pr2serr_lk("%d->id: once 7000: k=%d, submitted=%d waiting=%d\n",
+ id, k, num_subm, num_waiting);
+ pr_rusage(id);
+ }
+ if (vb && ! once10_000 && num_outstanding >= 10000) {
+ int num_waiting;
+ int num_subm = (op->sg_vn_ge_30901) ? num_submitted(sg_fd) : -1;
+
+ once10_000 = true;
+ if (ioctl(sg_fd, SG_GET_NUM_WAITING, &num_waiting) < 0) {
+ err = "ioctl(SG_GET_NUM_WAITING) failed";
+ break;
+ }
+ pr2serr_lk("%d->id: once 10^4: k=%d, submitted=%d waiting=%d\n",
+ id, k, num_subm, num_waiting);
+ pr_rusage(id);
+ }
+ if (vb && ! once20_000 && num_outstanding >= 20000) {
+ int num_waiting;
+ int num_subm = (op->sg_vn_ge_30901) ? num_submitted(sg_fd) : -1;
+
+ once20_000 = true;
+ if (ioctl(sg_fd, SG_GET_NUM_WAITING, &num_waiting) < 0) {
+ err = "ioctl(SG_GET_NUM_WAITING) failed";
+ break;
+ }
+ pr2serr_lk("%d->id: once 20000: k=%d, submitted=%d waiting=%d\n",
+ id, k, num_subm, num_waiting);
+ pr_rusage(id);
+ }
do_inc = 0;
if ((num_outstanding < op->maxq_per_thread) && (k < npt)) {
do_inc = 1;
@@ -1051,14 +1175,17 @@ work_thread(int id, struct opts_t * op)
} else {
lbp = encore_lbps.first;
free_lbp = encore_lbps.second;
- if (free_lst.size() > 1000) {
- static bool once = false;
-
- if (! once) {
- once = true;
- pr2serr_lk("id=%d: free_lst.size() over 1000\n",
- id);
- }
+ if (vb && !once && free_lst.size() > 1000) {
+ once = true;
+ pr2serr_lk("%d->id: free_lst.size() over 1000\n", id);
+ }
+ if (vb && !once_2000 && free_lst.size() > 2000) {
+ once_2000 = true;
+ pr2serr_lk("%d->id: free_lst.size() over 2000\n", id);
+ }
+ if (vb && !once_6000 && free_lst.size() > 6000) {
+ once_2000 = true;
+ pr2serr_lk("%d->id: free_lst.size() over 6000\n", id);
}
}
} else
@@ -1093,7 +1220,7 @@ work_thread(int id, struct opts_t * op)
encore_pack_id = pack_id;
pack_id = prev_pack_id;
encore_lbps = make_pair(lbp, free_lbp);
- if (vb > 3)
+ if (vb > 2)
pr2serr_lk("t_id=%d: E2BIG hit, prev_pack_id=%d, "
"encore_pack_id=%d\n", id, prev_pack_id,
encore_pack_id);
@@ -1108,13 +1235,17 @@ work_thread(int id, struct opts_t * op)
if (ruip)
pi_2_lba[pack_id] = lba;
}
- if (pi2buff.size() > 1000) {
- static bool once = false;
-
- if (! once) {
- once = true;
- pr2serr_lk("id=%d: pi2buff.size() over 1000\n", id);
- }
+ if (vb && !once && (pi2buff.size() > 1000)) {
+ once = true;
+ pr2serr_lk("%d->id: pi2buff.size() over 1000 (b)\n", id);
+ }
+ if (vb && !once_2000 && free_lst.size() > 2000) {
+ once_2000 = true;
+ pr2serr_lk("%d->id: free_lst.size() over 2000 (b)\n", id);
+ }
+ if (vb && !once_6000 && free_lst.size() > 6000) {
+ once_2000 = true;
+ pr2serr_lk("%d->id: free_lst.size() over 6000 (b)\n", id);
}
}
num_to_read = 0;
@@ -1164,15 +1295,30 @@ work_thread(int id, struct opts_t * op)
}
}
} else { /* nothing waiting to be read */
- n = (op->wait_ms > 0) ? op->wait_ms : 0;
- while (0 == (res = poll(pfd, 1, n))) {
- if (res < 0) {
- err = "poll(wait_ms) failed";
+ if (op->sg_vn_ge_30901) {
+ int val = num_submitted(sg_fd);
+
+ if (0 == val) {
+ err = "nothing submitted now ??";
+ break;
+ } else if (val < 0) {
+ err = "num_submitted failed";
break;
}
}
- if (err)
+ n = (op->wait_ms > 0) ? op->wait_ms : 0;
+ for (j = 0; (j < 1000000) && (0 == (res = poll(pfd, 1, n)));
+ ++j)
+ ;
+
+ if (j >= 1000000) {
+ err = "poll() looped 1 million times";
break;
+ }
+ if (res < 0) {
+ err = "poll(wait_ms) failed";
+ break;
+ }
}
} else { /* not full, not finished injecting */
if (MYQD_HIGH == op->myqd)
@@ -1191,7 +1337,12 @@ work_thread(int id, struct opts_t * op)
}
}
- while (num_to_read-- > 0) {
+ if (vb && !once_4000 && (num_to_read > 4000)) {
+ once_4000 = true;
+ pr2serr_lk("%d->id: num_to_read=%d\n", id, num_to_read);
+ }
+ while (num_to_read > 0) {
+ --num_to_read;
if (op->pack_id_force) {
j = pi2buff.size();
if (j > 0)
@@ -1258,6 +1409,9 @@ work_thread(int id, struct opts_t * op)
if (err)
break;
} /* end of for loop over npt (number per thread) */
+ if (vb)
+ pr2serr_lk("%d->id: leaving main thread loop; k=%d, o=%d\n", id, k,
+ o);
close(sg_fd); // sg driver will handle any commands "in flight"
if (ruip)
delete ruip;
diff --git a/testing/sg_tst_ioctl.c b/testing/sg_tst_ioctl.c
index 5e6b0eff..08c8bab1 100644
--- a/testing/sg_tst_ioctl.c
+++ b/testing/sg_tst_ioctl.c
@@ -56,7 +56,7 @@
* later of the Linux sg driver. */
-static const char * version_str = "Version: 1.06 20190323";
+static const char * version_str = "Version: 1.07 20190402";
#define INQ_REPLY_LEN 128
#define INQ_CMD_LEN 6
@@ -382,6 +382,17 @@ tst_ioctl(const char * fnp, int sg_fd, const char * fn2p, int sg_fd2,
printf(" %sread_value[SG_SEIRV_TRC_MAX_SZ]= %u\n", cp, seip->read_value);
memset(seip, 0, sizeof(*seip));
+ seip->sei_wr_mask |= SG_SEIM_READ_VAL;
+ seip->sei_rd_mask |= SG_SEIM_READ_VAL;
+ seip->read_value = SG_SEIRV_SUBMITTED;
+ if (ioctl(sg_fd, SG_SET_GET_EXTENDED, seip) < 0) {
+ pr2serr("ioctl(SG_SET_GET_EXTENDED) failed, errno=%d %s\n", errno,
+ strerror(errno));
+ return 1;
+ }
+ printf(" %sread_value[SG_SEIRV_SUBMITTED]= %u\n", cp, seip->read_value);
+
+ memset(seip, 0, sizeof(*seip));
seip->sei_wr_mask |= SG_SEIM_SHARE_FD;
seip->sei_rd_mask |= SG_SEIM_SHARE_FD;
#if 1
@@ -521,10 +532,10 @@ do_mrqs(int sg_fd, int sg_fd2, int mrqs)
else
h4p->flags |= SG_FLAG_Q_AT_HEAD;
}
- mrq_h4p->din_xferp = (uint64_t)arr_v4;
- mrq_h4p->din_xfer_len = arr_v4_sz;
- mrq_h4p->dout_xferp = mrq_h4p->din_xferp;
- mrq_h4p->dout_xfer_len = mrq_h4p->din_xfer_len;
+ mrq_h4p->dout_xferp = (uint64_t)arr_v4;
+ mrq_h4p->dout_xfer_len = arr_v4_sz;
+ mrq_h4p->din_xferp = mrq_h4p->dout_xferp;
+ mrq_h4p->din_xfer_len = mrq_h4p->dout_xfer_len;
if (ioctl(sg_fd, (mrq_iosubmit ? SG_IOSUBMIT : SG_IO), mrq_h4p) < 0) {
res = errno;
pr2serr("ioctl(SG_IO%s, mrq) failed, errno=%d %s\n",
diff --git a/testing/sgh_dd.cpp b/testing/sgh_dd.cpp
index 0fdfb366..b7608cfb 100644
--- a/testing/sgh_dd.cpp
+++ b/testing/sgh_dd.cpp
@@ -103,7 +103,7 @@
using namespace std;
-static const char * version_str = "1.21 20190324";
+static const char * version_str = "1.22 20190331";
#ifdef __GNUC__
#ifndef __clang__
@@ -1008,11 +1008,13 @@ read_write_thread(void * v_tip)
/* Start of READ half of a segment */
status = pthread_mutex_lock(&clp->in_mutex);
if (0 != status) err_exit(status, "lock in_mutex");
+
#if 0
if (clp->in_stop || (clp->in_count <= 0)) {
/* no more to do, exit loop then thread */
status = pthread_mutex_unlock(&clp->in_mutex);
if (0 != status) err_exit(status, "unlock in_mutex");
+pr2serr_lk("tid=%d: clp->in_stop\n", rep->id);
break;
}
#endif
@@ -1070,35 +1072,20 @@ read_write_thread(void * v_tip)
}
skip_force_out_sequence:
-#if 0
if (clp->out_stop || (clp->out_count <= 0)) {
if (! clp->out_stop)
clp->out_stop = true;
status = pthread_mutex_unlock(&clp->out_mutex);
if (0 != status) err_exit(status, "unlock out_mutex");
+pr2serr_lk("tid=%d: clp->out_stop\n", rep->id);
break;
}
-#endif
if (stop_after_write)
clp->out_stop = true;
clp->out_blk += blocks;
clp->out_count -= blocks;
- if (0 == rep->num_blks) {
- if ((rep->nmrqs > 0) && (def_arr.first.size() > 0)) {
- if (rep->debug)
- pr2serr_lk("thread=%d: tail-end, to_do=%u\n", rep->id,
- (uint32_t)def_arr.first.size());
- sgh_do_def(rep, def_arr);
- }
- clp->out_stop = true;
- stop_after_write = true;
- status = pthread_mutex_unlock(&clp->out_mutex);
- if (0 != status) err_exit(status, "unlock out_mutex");
- break; /* read nothing so leave loop */
- }
-
pthread_cleanup_push(cleanup_out, (void *)clp);
if (rep->outregfd >= 0) {
res = write(rep->outregfd, rep->buffp, rep->bs * rep->num_blks);
@@ -1142,19 +1129,22 @@ skip_force_out_sequence:
pthread_cleanup_pop(0);
}
+ if (0 == rep->num_blks) {
+ if ((rep->nmrqs > 0) && (def_arr.first.size() > 0)) {
+ if (rep->debug)
+ pr2serr_lk("thread=%d: tail-end, to_do=%u\n", rep->id,
+ (uint32_t)def_arr.first.size());
+ sgh_do_def(rep, def_arr);
+ }
+ clp->out_stop = true;
+ stop_after_write = true;
+ break; /* read nothing so leave loop */
+ }
// if ((! rep->has_share) && (FT_DEV_NULL != clp->out_type))
pthread_cond_broadcast(&clp->out_sync_cv);
if (stop_after_write)
break;
- } /* ^^^^^^^^^^ end of main while loop which copies segments ^^^^^^ */
-#if 0
- if ((rep->nmrqs > 0) && (def_arr.first.size() > 0)) {
- if (rep->debug)
- pr2serr_lk("thread=%d: tail-end, to_do=%u\n", rep->id,
- (uint32_t)def_arr.first.size());
- sgh_do_def(rep, def_arr);
- }
-#endif
+ } /* ^^^^^^^^^^ end of main while loop which copies segments ^^^^^^ */
status = pthread_mutex_lock(&clp->in_mutex);
if (0 != status) err_exit(status, "lock in_mutex");
@@ -1182,9 +1172,6 @@ fini:
if (own_out2fd && (rep->out2fd >= 0))
close(rep->out2fd);
pthread_cond_broadcast(&clp->out_sync_cv);
- if (rep->num_blks > 0)
- pr2serr("%d <-- thread exiting with rep->num_blks=%d\n", rep->id,
- rep->num_blks);
return stop_after_write ? NULL : clp;
}
@@ -1583,10 +1570,10 @@ sgh_do_def(Rq_elem * rep, mrq_arr_t & def_arr)
fd = rep->outfd;
res = 0;
ctl_v4.flags = SGV4_FLAG_MULTIPLE_REQS | SGV4_FLAG_STOP_IF;
- ctl_v4.din_xferp = (uint64_t)a_v4p;
- ctl_v4.din_xfer_len = n * sizeof(*a_v4p);
- ctl_v4.dout_xferp = (uint64_t)a_v4p;
+ ctl_v4.dout_xferp = (uint64_t)a_v4p; /* request array */
ctl_v4.dout_xfer_len = n * sizeof(*a_v4p);
+ ctl_v4.din_xferp = (uint64_t)a_v4p; /* response array */
+ ctl_v4.din_xfer_len = n * sizeof(*a_v4p);
if (rep->debug > 2) {
pr2serr_lk("%s: Controlling object _before_ ioctl(SG_IO):\n",
__func__);
@@ -1860,8 +1847,10 @@ sg_finish_io(bool wr, Rq_elem * rep, bool is_wr2)
return 0;
do_v4:
- if (rep->nmrqs > 0)
+ if (rep->nmrqs > 0) {
+ rep->resid = 0;
return 0;
+ }
h4p = &rep->io_hdr4;
while (((res = ioctl(fd, SG_IORECEIVE, h4p)) < 0) &&
((EINTR == errno) || (EAGAIN == errno)))