aboutsummaryrefslogtreecommitdiff
path: root/testing
diff options
context:
space:
mode:
authorDouglas Gilbert <dgilbert@interlog.com>2021-10-28 23:35:11 +0000
committerDouglas Gilbert <dgilbert@interlog.com>2021-10-28 23:35:11 +0000
commitf0195003bb0c66ba55084b2f7e0fe982f08c5675 (patch)
treeac27a2f679ce91e865fa0a578c9cfa2d97110b07 /testing
parentc1ce6d6c5f3f64038e17dfd65380aa728c5d994d (diff)
downloadsg3_utils-f0195003bb0c66ba55084b2f7e0fe982f08c5675.tar.gz
sg_dd: 'iflag=00,ff' places the 32 bit block address (big endian) into each block; sgp_dd: major rework, new: --chkaddr which checks for block address in each block
git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@916 6180dd3e-e324-4e3e-922d-17de1ae2f315
Diffstat (limited to 'testing')
-rw-r--r--testing/sg_mrq_dd.cpp164
-rw-r--r--testing/sgh_dd.cpp167
-rw-r--r--testing/sgs_dd.c16
3 files changed, 228 insertions, 119 deletions
diff --git a/testing/sg_mrq_dd.cpp b/testing/sg_mrq_dd.cpp
index b554614a..bb6b3a03 100644
--- a/testing/sg_mrq_dd.cpp
+++ b/testing/sg_mrq_dd.cpp
@@ -30,7 +30,7 @@
*
*/
-static const char * version_str = "1.36 20210906";
+static const char * version_str = "1.38 20211028";
#define _XOPEN_SOURCE 600
#ifndef _GNU_SOURCE
@@ -46,6 +46,7 @@ static const char * version_str = "1.36 20210906";
#include <string.h>
#include <ctype.h>
#include <errno.h>
+#include <time.h> /* for nanosleep() */
#include <poll.h>
#include <limits.h>
// #include <pthread.h>
@@ -69,7 +70,8 @@ static const char * version_str = "1.36 20210906";
#include <random>
#include <thread> // needed for std::this_thread::yield()
#include <mutex>
-#include <condition_variable>
+#include <condition_variable> // for infant_cv: copy/verify first segment
+ // single threaded
#include <chrono>
#ifdef HAVE_CONFIG_H
@@ -286,8 +288,8 @@ struct global_collection /* one instance visible to all threads */
atomic<int> most_recent_pack_id;
uint32_t sdt_ict; /* stall detection; initial check time (milliseconds) */
uint32_t sdt_crt; /* check repetition time (seconds), after first stall */
- int verbose;
int dry_run;
+ int verbose;
bool mrq_eq_0; /* true when user gives mrq=0 */
bool processed;
bool cdbsz_given;
@@ -319,6 +321,7 @@ typedef struct request_element
bool stop_after_write;
bool stop_now;
int id;
+ int bs;
int infd;
int outfd;
int outregfd;
@@ -419,6 +422,7 @@ static struct global_collection gcoll;
static struct timeval start_tm;
static int num_threads = DEF_NUM_THREADS;
static bool after1 = false;
+static int listen_t_tid;
static const char * my_name = "sg_mrq_dd: ";
@@ -576,6 +580,8 @@ page3:
"below:\n\n"
" 00 use all zeros instead of if=IFILE (only in "
"iflag)\n"
+ " 00,ff generates blocks that contain own (32 bit be) "
+ "blk addr\n"
" append append output to OFILE (assumes OFILE is "
"regular file)\n"
" coe continue of error (reading, fills with zeros)\n"
@@ -1051,7 +1057,7 @@ interrupt_handler(int sig)
if (do_time > 0)
calc_duration_throughput(0);
print_stats("");
- kill(getpid (), sig);
+ kill(getpid(), sig);
}
static void
@@ -1388,11 +1394,11 @@ static int
scsi_read_capacity(int sg_fd, int64_t * num_sect, int * sect_sz)
{
int res;
- uint8_t rcBuff[RCAP16_REPLY_LEN];
+ uint8_t rcBuff[RCAP16_REPLY_LEN] = {};
res = sg_ll_readcap_10(sg_fd, 0, 0, rcBuff, READ_CAP_REPLY_LEN, false, 0);
if (0 != res)
- return res;
+ goto bad;
if ((0xff == rcBuff[0]) && (0xff == rcBuff[1]) && (0xff == rcBuff[2]) &&
(0xff == rcBuff[3])) {
@@ -1400,7 +1406,7 @@ scsi_read_capacity(int sg_fd, int64_t * num_sect, int * sect_sz)
res = sg_ll_readcap_16(sg_fd, 0, 0, rcBuff, RCAP16_REPLY_LEN, false,
0);
if (0 != res)
- return res;
+ goto bad;
*num_sect = sg_get_unaligned_be64(rcBuff + 0) + 1;
*sect_sz = sg_get_unaligned_be32(rcBuff + 8);
} else {
@@ -1409,6 +1415,10 @@ scsi_read_capacity(int sg_fd, int64_t * num_sect, int * sect_sz)
*sect_sz = sg_get_unaligned_be32(rcBuff + 4);
}
return 0;
+bad:
+ *num_sect = 0;
+ *sect_sz = 0;
+ return res;
}
/* Return of 0 -> success, -1 -> failure. BLKGETSIZE64, BLKGETSIZE and */
@@ -1476,6 +1486,7 @@ sig_listen_thread(struct global_collection * clp)
tsp->tv_sec = ict_ms / 1000;
tsp->tv_nsec = (ict_ms % 1000) * 1000 * 1000; /* DEF_SDT_ICT_MS */
+ listen_t_tid = gettid(); // to facilitate sending SIGUSR2 to exit
while (1) {
sig_number = sigtimedwait(&signal_set, NULL, tsp);
if (sig_number < 0) {
@@ -1508,9 +1519,11 @@ sig_listen_thread(struct global_collection * clp)
raise(SIGINT);
break;
}
- if (SIGUSR2 == sig_number)
+ if (SIGUSR2 == sig_number) {
+ if (clp->verbose > 2)
+ pr2serr_lk("%s: SIGUSR2 received\n", __func__);
break;
- if (shutting_down)
+ } if (shutting_down)
break;
} /* end of while loop */
if (clp->verbose > 3)
@@ -1589,6 +1602,7 @@ read_write_thread(struct global_collection * clp, int thr_idx, int slice_idx,
out_mmap = (out_is_sg && (clp->out_flags.mmap > 0));
rep->clp = clp;
rep->id = thr_idx;
+ rep->bs = clp->bs;
if (in_is_sg && out_is_sg)
rep->both_sg = true;
@@ -1894,14 +1908,22 @@ normal_in_rd(Rq_elem * rep, int64_t lba, int blocks, int d_boff)
long rn;
uint8_t * bp;
- if (clp->in_flags.zero)
- memset(rep->buffp + d_boff, 0, blocks * clp->bs);
+ if (clp->in_flags.zero && clp->in_flags.ff && (rep->bs >= 4)) {
+ uint32_t pos = (uint32_t)lba;
+ uint off;
+
+ for (k = 0, off = 0; k < blocks; ++k, off += rep->bs, ++pos) {
+ for (j = 0; j < (rep->bs - 3); j += 4)
+ sg_put_unaligned_be32(pos, rep->buffp + off + j);
+ }
+ } else if (clp->in_flags.zero)
+ memset(rep->buffp + d_boff, 0, blocks * rep->bs);
else if (clp->in_flags.ff)
- memset(rep->buffp + d_boff, 0xff, blocks * clp->bs);
+ memset(rep->buffp + d_boff, 0xff, blocks * rep->bs);
else {
bp = rep->buffp + d_boff;
- for (k = 0; k < blocks; ++k, bp += clp->bs) {
- for (j = 0; j < clp->bs; j += jbump) {
+ for (k = 0; k < blocks; ++k, bp += rep->bs) {
+ for (j = 0; j < rep->bs; j += jbump) {
/* mrand48 takes uniformly from [-2^31, 2^31) */
#ifdef HAVE_SRAND48_R
mrand48_r(&rep->drand, &rn);
@@ -1916,7 +1938,7 @@ normal_in_rd(Rq_elem * rep, int64_t lba, int blocks, int d_boff)
}
if (clp->in_type != FT_FIFO) {
- int64_t pos = lba * clp->bs;
+ int64_t pos = lba * rep->bs;
if (rep->in_follow_on != pos) {
if (lseek64(rep->infd, pos, SEEK_SET) < 0) {
@@ -1929,18 +1951,18 @@ normal_in_rd(Rq_elem * rep, int64_t lba, int blocks, int d_boff)
}
}
bp = rep->buffp + d_boff;
- while (((res = read(rep->infd, bp, blocks * clp->bs)) < 0) &&
+ while (((res = read(rep->infd, bp, blocks * rep->bs)) < 0) &&
((EINTR == errno) || (EAGAIN == errno)))
std::this_thread::yield();/* another thread may be able to progress */
if (res < 0) {
err = errno;
if (clp->in_flags.coe) {
- memset(bp, 0, blocks * clp->bs);
+ memset(bp, 0, blocks * rep->bs);
pr2serr_lk("[%d] %s : >> substituted zeros for in blk=%" PRId64
" for %d bytes, %s\n", id, __func__, lba,
- blocks * clp->bs,
+ blocks * rep->bs,
tsafe_strerror(err, strerr_buff));
- res = blocks * clp->bs;
+ res = blocks * rep->bs;
} else {
pr2serr_lk("[%d] %s: error in normal read, %s\n", id, __func__,
tsafe_strerror(err, strerr_buff));
@@ -1948,11 +1970,11 @@ normal_in_rd(Rq_elem * rep, int64_t lba, int blocks, int d_boff)
}
}
rep->in_follow_on += res;
- if (res < blocks * clp->bs) {
- blocks = res / clp->bs;
- if ((res % clp->bs) > 0) {
+ if (res < blocks * rep->bs) {
+ blocks = res / rep->bs;
+ if ((res % rep->bs) > 0) {
rep->in_local_partial++;
- rep->in_resid_bytes = res % clp->bs;
+ rep->in_resid_bytes = res % rep->bs;
}
}
return blocks;
@@ -1974,7 +1996,7 @@ normal_out_wr(Rq_elem * rep, int64_t lba, int blocks, int d_boff)
__func__, lba, blocks, d_boff);
if (clp->in_type != FT_FIFO) {
- int64_t pos = lba * clp->bs;
+ int64_t pos = lba * rep->bs;
if (rep->out_follow_on != pos) {
if (lseek64(rep->outfd, pos, SEEK_SET) < 0) {
@@ -1986,7 +2008,7 @@ normal_out_wr(Rq_elem * rep, int64_t lba, int blocks, int d_boff)
rep->out_follow_on = pos;
}
}
- while (((res = write(rep->outfd, bp, blocks * clp->bs))
+ while (((res = write(rep->outfd, bp, blocks * rep->bs))
< 0) && ((EINTR == errno) || (EAGAIN == errno)))
std::this_thread::yield();/* another thread may be able to progress */
if (res < 0) {
@@ -1994,8 +2016,8 @@ normal_out_wr(Rq_elem * rep, int64_t lba, int blocks, int d_boff)
if (clp->out_flags.coe) {
pr2serr_lk("[%d] %s: >> ignored error for out lba=%" PRId64
" for %d bytes, %s\n", id, __func__, lba,
- blocks * clp->bs, tsafe_strerror(err, strerr_buff));
- res = blocks * clp->bs;
+ blocks * rep->bs, tsafe_strerror(err, strerr_buff));
+ res = blocks * rep->bs;
}
else {
pr2serr_lk("[%d] %s: error normal write, %s\n", id, __func__,
@@ -2004,9 +2026,9 @@ normal_out_wr(Rq_elem * rep, int64_t lba, int blocks, int d_boff)
}
}
rep->out_follow_on += res;
- if (res < blocks * clp->bs) {
- blocks = res / clp->bs;
- if ((res % clp->bs) > 0) {
+ if (res < blocks * rep->bs) {
+ blocks = res / rep->bs;
+ if ((res % rep->bs) > 0) {
blocks++;
rep->out_local_partial++;
}
@@ -2236,12 +2258,12 @@ process_mrq_response(Rq_elem * rep, const struct sg_io_v4 * ctl_v4p,
cat = SG_LIB_CAT_OTHER;
if (ok && f1) {
++n_good;
- if (a_v4p->dout_xfer_len >= (uint32_t)clp->bs)
+ if (a_v4p->dout_xfer_len >= (uint32_t)rep->bs)
good_outblks += (a_v4p->dout_xfer_len - a_v4p->dout_resid) /
- clp->bs;
- if (a_v4p->din_xfer_len >= (uint32_t)clp->bs)
+ rep->bs;
+ if (a_v4p->din_xfer_len >= (uint32_t)rep->bs)
good_inblks += (a_v4p->din_xfer_len - a_v4p->din_resid) /
- clp->bs;
+ rep->bs;
}
if (! ok) {
if ((a_v4p->dout_xfer_len > 0) || (! clp->in_flags.coe))
@@ -2333,12 +2355,12 @@ sg_half_segment_mrq0(Rq_elem * rep, scat_gath_iter & sg_it, bool is_wr,
t_v4p->flags = rflags;
t_v4p->request_len = cdbsz;
if (is_wr) {
- t_v4p->dout_xfer_len = num * clp->bs;
- t_v4p->dout_xferp = (uint64_t)(dp + (q_blks * clp->bs));
+ t_v4p->dout_xfer_len = num * rep->bs;
+ t_v4p->dout_xferp = (uint64_t)(dp + (q_blks * rep->bs));
t_v4p->din_xfer_len = 0;
} else {
- t_v4p->din_xfer_len = num * clp->bs;
- t_v4p->din_xferp = (uint64_t)(dp + (q_blks * clp->bs));
+ t_v4p->din_xfer_len = num * rep->bs;
+ t_v4p->din_xferp = (uint64_t)(dp + (q_blks * rep->bs));
t_v4p->dout_xfer_len = 0;
}
t_v4p->timeout = clp->cmd_timeout;
@@ -2457,13 +2479,13 @@ sg_half_segment(Rq_elem * rep, scat_gath_iter & sg_it, bool is_wr,
t_v4p->usr_ptr = (uint64_t)&a_cdb[a_cdb.size() - 1];
if (is_wr) {
rep->a_mrq_dout_blks += num;
- t_v4p->dout_xfer_len = num * clp->bs;
- t_v4p->dout_xferp = (uint64_t)(dp + (mrq_q_blks * clp->bs));
+ t_v4p->dout_xfer_len = num * rep->bs;
+ t_v4p->dout_xferp = (uint64_t)(dp + (mrq_q_blks * rep->bs));
t_v4p->din_xfer_len = 0;
} else {
rep->a_mrq_din_blks += num;
- t_v4p->din_xfer_len = num * clp->bs;
- t_v4p->din_xferp = (uint64_t)(dp + (mrq_q_blks * clp->bs));
+ t_v4p->din_xfer_len = num * rep->bs;
+ t_v4p->din_xferp = (uint64_t)(dp + (mrq_q_blks * rep->bs));
t_v4p->dout_xfer_len = 0;
}
t_v4p->timeout = clp->cmd_timeout;
@@ -2621,7 +2643,7 @@ do_normal_normal_segment(Rq_elem * rep, scat_gath_iter & i_sg_it,
kk = min<int>(seg_blks, clp->bpt);
num = i_sg_it.linear_for_n_blks(kk);
res = normal_in_rd(rep, i_sg_it.current_lba(), num,
- d_off * clp->bs);
+ d_off * rep->bs);
if (res < 0) {
pr2serr_lk("[%d] %s: normal in failed d_off=%d, err=%d\n",
id, __func__, d_off, -res);
@@ -2644,7 +2666,7 @@ do_normal_normal_segment(Rq_elem * rep, scat_gath_iter & i_sg_it,
kk = min<int>(seg_blks, clp->bpt);
num = o_sg_it.linear_for_n_blks(kk);
res = normal_out_wr(rep, o_sg_it.current_lba(), num,
- d_off * clp->bs);
+ d_off * rep->bs);
if (res < num) {
if (res < 0) {
pr2serr_lk("[%d] %s: normal out failed d_off=%d, err=%d\n",
@@ -2660,7 +2682,7 @@ do_normal_normal_segment(Rq_elem * rep, scat_gath_iter & i_sg_it,
}
}
if (rep->in_resid_bytes > 0) {
- res = extra_out_wr(rep, rep->in_resid_bytes, d_off * clp->bs);
+ res = extra_out_wr(rep, rep->in_resid_bytes, d_off * rep->bs);
if (res < 0)
pr2serr_lk("[%d] %s: extr out failed d_off=%d, err=%d\n", id,
__func__, d_off, -res);
@@ -2710,7 +2732,7 @@ do_normal_sg_segment(Rq_elem * rep, scat_gath_iter & i_sg_it,
kk = min<int>(seg_blks, clp->bpt);
num = i_sg_it.linear_for_n_blks(kk);
res = normal_in_rd(rep, i_sg_it.current_lba(), num,
- d_off * clp->bs);
+ d_off * rep->bs);
if (res < 0) {
pr2serr_lk("[%d] %s: normal in failed d_off=%d, err=%d\n",
id, __func__, d_off, -res);
@@ -2774,7 +2796,7 @@ do_normal_sg_segment(Rq_elem * rep, scat_gath_iter & i_sg_it,
kk = min<int>(seg_blks, clp->bpt);
num = o_sg_it.linear_for_n_blks(kk);
res = normal_out_wr(rep, o_sg_it.current_lba(), num,
- d_off * clp->bs);
+ d_off * rep->bs);
if (res < num) {
if (res < 0) {
pr2serr_lk("[%d] %s: normal out failed d_off=%d, err=%d\n",
@@ -2888,7 +2910,7 @@ do_both_sg_segment_mrq0(Rq_elem * rep, scat_gath_iter & i_sg_it,
t_v4p->max_response_len = sizeof(rep->sb);
t_v4p->flags = iflags;
t_v4p->request_len = cdbsz;
- t_v4p->din_xfer_len = num * clp->bs;
+ t_v4p->din_xfer_len = num * rep->bs;
t_v4p->dout_xfer_len = 0;
t_v4p->timeout = clp->cmd_timeout;
t_v4p->request_extra = pack_id_base + ++rep->mrq_pack_id_off;
@@ -2940,7 +2962,7 @@ mrq0_again:
t_v4p->flags = oflags;
t_v4p->request_len = cdbsz;
t_v4p->din_xfer_len = 0;
- t_v4p->dout_xfer_len = num * clp->bs;
+ t_v4p->dout_xfer_len = num * rep->bs;
t_v4p->timeout = clp->cmd_timeout;
t_v4p->request_extra = pack_id_base + ++rep->mrq_pack_id_off;
clp->most_recent_pack_id.store(t_v4p->request_extra);
@@ -3072,7 +3094,7 @@ do_both_sg_segment(Rq_elem * rep, scat_gath_iter & i_sg_it,
t_v4p->response = (uint64_t)rep->sb;
t_v4p->max_response_len = sizeof(rep->sb);
t_v4p->usr_ptr = (uint64_t)&a_cdb[a_cdb.size() - 1];
- t_v4p->din_xfer_len = num * clp->bs;
+ t_v4p->din_xfer_len = num * rep->bs;
rep->a_mrq_din_blks += num;
t_v4p->dout_xfer_len = 0;
t_v4p->timeout = clp->cmd_timeout;
@@ -3100,7 +3122,7 @@ do_both_sg_segment(Rq_elem * rep, scat_gath_iter & i_sg_it,
t_v4p->max_response_len = sizeof(rep->sb);
t_v4p->usr_ptr = (uint64_t)&a_cdb[a_cdb.size() - 1];
t_v4p->din_xfer_len = 0;
- t_v4p->dout_xfer_len = num * clp->bs;
+ t_v4p->dout_xfer_len = num * rep->bs;
rep->a_mrq_dout_blks += num;
t_v4p->timeout = clp->cmd_timeout;
out_mrq_q_blks += num;
@@ -4100,6 +4122,9 @@ do_count_work(struct global_collection * clp, const char * inf,
return SG_LIB_CAT_OTHER;
}
} else if (clp->dd_count != 0) { /* and both input and output are soft */
+ int64_t iposs = INT64_MAX;
+ int64_t oposs = INT64_MAX;
+
if (clp->dd_count > 0) {
if (isglp->sum > clp->dd_count) {
pr2serr("%sskip sgl sum [%" PRId64 "] exceeds COUNT\n",
@@ -4115,9 +4140,6 @@ do_count_work(struct global_collection * clp, const char * inf,
}
/* clp->dd_count == SG_COUNT_INDEFINITE */
- int64_t iposs = INT64_MAX;
- int64_t oposs = INT64_MAX;
-
if (in_num_sect > 0)
iposs = in_num_sect + isglp->sum - isglp->high_lba_p1;
if (out_num_sect > 0)
@@ -4166,8 +4188,8 @@ main(int argc, char * argv[])
const char * cc2p;
struct global_collection * clp = &gcoll;
thread sig_listen_thr;
- vector<thread> work_thr;
- vector<thread> listen_thr;
+ vector<thread> work_thr_v;
+ vector<thread> listen_thr_v;
char ebuff[EBUFF_SZ];
#if 0 /* SG_LIB_ANDROID */
struct sigaction actions;
@@ -4277,7 +4299,10 @@ main(int argc, char * argv[])
}
clp->in0fd = STDIN_FILENO;
clp->out0fd = STDOUT_FILENO;
- if (clp->in_flags.ff) {
+ if (clp->in_flags.ff && clp->in_flags.zero) {
+ ccp = "<addr_as_data>";
+ cc2p = "addr_as_data";
+ } else if (clp->in_flags.ff) {
ccp = "<0xff bytes>";
cc2p = "ff";
} else if (clp->in_flags.random) {
@@ -4488,7 +4513,7 @@ main(int argc, char * argv[])
goto fini;
}
- listen_thr.emplace_back(sig_listen_thread, clp);
+ listen_thr_v.emplace_back(sig_listen_thread, clp);
if (do_time) {
start_tm.tv_sec = 0;
@@ -4504,14 +4529,14 @@ main(int argc, char * argv[])
cvp.out_fd = clp->out0fd;
/* launch "infant" thread to catch early mortality, if any */
- work_thr.emplace_back(read_write_thread, clp, 0, 0, true);
+ work_thr_v.emplace_back(read_write_thread, clp, 0, 0, true);
{
unique_lock<mutex> lk(clp->infant_mut);
clp->infant_cv.wait(lk, []{ return gcoll.processed; });
}
if (clp->cp_ver_arr[0].next_count_pos.load() < 0) {
/* infant thread error-ed out, join with it */
- for (auto & t : work_thr) {
+ for (auto & t : work_thr_v) {
if (t.joinable())
t.join();
}
@@ -4520,15 +4545,15 @@ main(int argc, char * argv[])
/* now start the rest of the threads */
for (k = 1; k < num_threads; ++k)
- work_thr.emplace_back(read_write_thread, clp, k,
+ work_thr_v.emplace_back(read_write_thread, clp, k,
k % (int)num_slices, false);
/* now wait for worker threads to finish */
- for (auto & t : work_thr) {
+ for (auto & t : work_thr_v) {
if (t.joinable())
t.join();
}
- } /* started worker threads and hereafter they have all exited */
+ } /* worker threads hereafter have all exited */
jump:
if (do_time && (start_tm.tv_sec || start_tm.tv_usec))
calc_duration_throughput(0);
@@ -4549,15 +4574,22 @@ jump:
}
shutting_down = true;
- for (auto & t : listen_thr) {
+ for (auto & t : listen_thr_v) {
if (t.joinable()) {
t.detach();
- t.~thread(); /* kill listening thread */
+ if (listen_t_tid > 0)
+ kill(listen_t_tid, SIGUSR2);
+ // t.~thread(); /* kill listening thread; doesn't work */
+ }
+ std::this_thread::yield(); // not enough it seems
+ { /* allow time for SIGUSR2 signal to get through */
+ struct timespec tspec = {0, 400000}; /* 400 usecs */
+
+ nanosleep(&tspec, NULL);
}
}
fini:
-
if ((STDIN_FILENO != clp->in0fd) && (clp->in0fd >= 0))
close(clp->in0fd);
if ((STDOUT_FILENO != clp->out0fd) && (FT_DEV_NULL != clp->out_type) &&
diff --git a/testing/sgh_dd.cpp b/testing/sgh_dd.cpp
index bc98de43..38ee1d55 100644
--- a/testing/sgh_dd.cpp
+++ b/testing/sgh_dd.cpp
@@ -36,7 +36,7 @@
* renamed [20181221]
*/
-static const char * version_str = "2.16 20210906";
+static const char * version_str = "2.18 20211027";
#define _XOPEN_SOURCE 600
#ifndef _GNU_SOURCE
@@ -253,6 +253,7 @@ struct global_collection
int fail_mask;
int verbose;
int dry_run;
+ int chkaddr;
bool aen_given;
bool cdbsz_given;
bool is_mrq_i;
@@ -292,6 +293,7 @@ typedef struct request_element
bool only_out_sg;
// bool mrq_abort_thread_active;
int id;
+ int bs;
int infd;
int outfd;
int out2fd;
@@ -509,7 +511,6 @@ usage(int pg_num)
" seek block position to start writing to OFILE\n"
" skip block position to start reading from IFILE\n"
" --help|-h output this usage message then exit\n"
- " --prefetch|-p with verify: do pre-fetch first\n"
" --verify|-x do a verify (compare) operation [def: do a "
"copy]\n"
" --version|-V output version string then exit\n\n"
@@ -576,7 +577,12 @@ page2:
"close do\n"
" file unshare (default)\n"
" verbose increase verbosity\n"
+ " --chkaddr|-c exits if read block does not contain "
+ "32 bit block\n"
+ " address, used once only checks first "
+ "address in block\n"
" --dry-run|-d prepare but bypass copy/read\n"
+ " --prefetch|-p with verify: do pre-fetch first\n"
" --verbose|-v increase verbosity of utility\n\n"
"Use '-hhh' or '-hhhh' for more information about flags.\n"
);
@@ -587,6 +593,8 @@ page3:
"below:\n\n"
" 00 use all zeros instead of if=IFILE (only in "
"iflags)\n"
+ " 00,ff generates blocks that contain own (32 bit be) "
+ "blk address\n"
" append append output to OFILE (assumes OFILE is "
"regular file)\n"
" coe continue of error (reading, fills with zeros)\n"
@@ -1138,7 +1146,7 @@ static int
scsi_read_capacity(int sg_fd, int64_t * num_sect, int * sect_sz)
{
int res;
- uint8_t rcBuff[RCAP16_REPLY_LEN];
+ uint8_t rcBuff[RCAP16_REPLY_LEN] = {};
res = sg_ll_readcap_10(sg_fd, 0, 0, rcBuff, READ_CAP_REPLY_LEN, false, 0);
if (0 != res)
@@ -1262,8 +1270,11 @@ sig_listen_thread(void * v_clp)
raise(SIGINT);
break;
}
- if (SIGUSR2 == sig_number)
+ if (SIGUSR2 == sig_number) {
+ if (clp->verbose > 2)
+ pr2serr_lk("%s: interrupted by SIGUSR2\n", __func__);
break;
+ }
if (shutting_down)
break;
} /* end of while loop */
@@ -1474,7 +1485,7 @@ read_write_thread(void * v_tip)
struct global_collection * clp;
Rq_elem rel {};
Rq_elem * rep = &rel;
- int n, sz, blocks, status, vb, err, res, wr_blks;
+ int n, sz, blocks, status, vb, err, res, wr_blks, c_addr;
int num_sg = 0;
int64_t my_index;
volatile bool stop_after_write = false;
@@ -1488,7 +1499,9 @@ read_write_thread(void * v_tip)
tip = (Thread_info *)v_tip;
clp = tip->gcp;
vb = clp->verbose;
- sz = clp->bpt * clp->bs;
+ rep->bs = clp->bs;
+ sz = clp->bpt * rep->bs;
+ c_addr = clp->chkaddr;
in_is_sg = (FT_SG == clp->in_type);
in_mmap = (in_is_sg && (clp->in_flags.mmap > 0));
out_is_sg = (FT_SG == clp->out_type);
@@ -1664,6 +1677,26 @@ read_write_thread(void * v_tip)
status = pthread_mutex_unlock(&clp->in_mutex);
if (0 != status) err_exit(status, "unlock in_mutex");
}
+ if (c_addr && (rep->bs > 3)) {
+ int k, j, off, num;
+ uint32_t addr = (uint32_t)rep->iblk;
+
+ num = (1 == c_addr) ? 4 : (rep->bs - 3);
+ for (k = 0, off = 0; k < blocks; ++k, ++addr, off += rep->bs) {
+ for (j = 0; j < num; j += 4) {
+ if (addr != sg_get_unaligned_be32(rep->buffp + off + j))
+ break;
+ }
+ if (j < num)
+ break;
+ }
+ if (k < blocks) {
+ pr2serr("%s: chkaddr failure at addr=0x%x\n", __func__, addr);
+ exit_status = SG_LIB_CAT_MISCOMPARE;
+ ++num_miscompare;
+ stop_both(clp);
+ }
+ }
pthread_cleanup_pop(0);
++rep->rep_count;
@@ -1705,7 +1738,7 @@ skip_force_out_sequence:
pthread_cleanup_push(cleanup_out, (void *)clp);
if (rep->outregfd >= 0) {
res = write(rep->outregfd, get_buffp(rep),
- rep->clp->bs * rep->num_blks);
+ rep->bs * rep->num_blks);
err = errno;
if (res < 0)
pr2serr_lk("%s: tid=%d: write(outregfd) failed: %s\n",
@@ -1856,13 +1889,21 @@ normal_in_rd(Rq_elem * rep, int blocks)
long rn;
uint8_t * bp;
- if (clp->in_flags.zero)
- memset(rep->buffp, 0, blocks * clp->bs);
+ if (clp->in_flags.zero && clp->in_flags.ff && (rep->bs >= 4)) {
+ uint32_t pos = (uint32_t)rep->iblk;
+ uint off;
+
+ for (k = 0, off = 0; k < blocks; ++k, off += rep->bs, ++pos) {
+ for (j = 0; j < (rep->bs - 3); j += 4)
+ sg_put_unaligned_be32(pos, rep->buffp + off + j);
+ }
+ } else if (clp->in_flags.zero)
+ memset(rep->buffp, 0, blocks * rep->bs);
else if (clp->in_flags.ff)
- memset(rep->buffp, 0xff, blocks * clp->bs);
+ memset(rep->buffp, 0xff, blocks * rep->bs);
else {
- for (k = 0, bp = rep->buffp; k < blocks; ++k, bp += clp->bs) {
- for (j = 0; j < clp->bs; j += jbump) {
+ for (k = 0, bp = rep->buffp; k < blocks; ++k, bp += rep->bs) {
+ for (j = 0; j < rep->bs; j += jbump) {
/* mrand48 takes uniformly from [-2^31, 2^31) */
#ifdef HAVE_SRAND48_R
mrand48_r(&rep->drand, &rn);
@@ -1877,7 +1918,7 @@ normal_in_rd(Rq_elem * rep, int blocks)
return stop_after_write;
}
if (! same_fds) { /* each has own file pointer, so we need to move it */
- int64_t pos = rep->iblk * clp->bs;
+ int64_t pos = rep->iblk * rep->bs;
if (lseek64(rep->infd, pos, SEEK_SET) < 0) { /* problem if pipe! */
pr2serr_lk("%s: tid=%d: >> lseek64(%" PRId64 "): %s\n", __func__,
@@ -1887,19 +1928,19 @@ normal_in_rd(Rq_elem * rep, int blocks)
}
}
/* enters holding in_mutex */
- while (((res = read(clp->infd, rep->buffp, blocks * clp->bs)) < 0) &&
+ while (((res = read(clp->infd, rep->buffp, blocks * rep->bs)) < 0) &&
((EINTR == errno) || (EAGAIN == errno)))
std::this_thread::yield();/* another thread may be able to progress */
if (res < 0) {
char strerr_buff[STRERR_BUFF_LEN + 1];
if (clp->in_flags.coe) {
- memset(rep->buffp, 0, rep->num_blks * clp->bs);
+ memset(rep->buffp, 0, rep->num_blks * rep->bs);
pr2serr_lk("tid=%d: >> substituted zeros for in blk=%" PRId64
" for %d bytes, %s\n", rep->id, rep->iblk,
- rep->num_blks * clp->bs,
+ rep->num_blks * rep->bs,
tsafe_strerror(errno, strerr_buff));
- res = rep->num_blks * clp->bs;
+ res = rep->num_blks * rep->bs;
}
else {
pr2serr_lk("tid=%d: error in normal read, %s\n", rep->id,
@@ -1908,12 +1949,12 @@ normal_in_rd(Rq_elem * rep, int blocks)
return true;
}
}
- if (res < blocks * clp->bs) {
+ if (res < blocks * rep->bs) {
// int o_blocks = blocks;
stop_after_write = true;
- blocks = res / clp->bs;
- if ((res % clp->bs) > 0) {
+ blocks = res / rep->bs;
+ if ((res % rep->bs) > 0) {
blocks++;
clp->in_partial++;
}
@@ -1938,7 +1979,7 @@ normal_out_wr(Rq_elem * rep, int blocks)
if (clp->verbose > 4)
pr2serr_lk("%s: tid=%d: oblk=%" PRIu64 ", blocks=%d\n", __func__,
rep->id, rep->oblk, blocks);
- while (((res = write(clp->outfd, rep->buffp, blocks * clp->bs))
+ while (((res = write(clp->outfd, rep->buffp, blocks * rep->bs))
< 0) && ((EINTR == errno) || (EAGAIN == errno)))
std::this_thread::yield();/* another thread may be able to progress */
if (res < 0) {
@@ -1947,9 +1988,9 @@ normal_out_wr(Rq_elem * rep, int blocks)
if (clp->out_flags.coe) {
pr2serr_lk("tid=%d: >> ignored error for out blk=%" PRId64
" for %d bytes, %s\n", rep->id, rep->oblk,
- rep->num_blks * clp->bs,
+ rep->num_blks * rep->bs,
tsafe_strerror(errno, strerr_buff));
- res = rep->num_blks * clp->bs;
+ res = rep->num_blks * rep->bs;
}
else {
pr2serr_lk("tid=%d: error normal write, %s\n", rep->id,
@@ -1958,9 +1999,9 @@ normal_out_wr(Rq_elem * rep, int blocks)
return;
}
}
- if (res < blocks * clp->bs) {
- blocks = res / clp->bs;
- if ((res % clp->bs) > 0) {
+ if (res < blocks * rep->bs) {
+ blocks = res / rep->bs;
+ if ((res % rep->bs) > 0) {
blocks++;
clp->out_partial++;
}
@@ -2095,10 +2136,10 @@ sg_in_rd_cmd(struct global_collection * clp, Rq_elem * rep,
stop_both(clp);
return;
} else {
- memset(get_buffp(rep), 0, rep->num_blks * clp->bs);
+ memset(get_buffp(rep), 0, rep->num_blks * rep->bs);
pr2serr_lk("tid=%d: >> substituted zeros for in blk=%" PRId64
" for %d bytes\n", rep->id, rep->iblk,
- rep->num_blks * clp->bs);
+ rep->num_blks * rep->bs);
}
#if defined(__GNUC__)
#if (__GNUC__ >= 7)
@@ -2284,7 +2325,7 @@ split_upper:
goto fini;
} else
pr2serr_lk(">> ignored error for %s blk=%" PRId64 " for %d "
- "bytes\n", wr_or_ver, rep->oblk, nblks * clp->bs);
+ "bytes\n", wr_or_ver, rep->oblk, nblks * rep->bs);
#if defined(__GNUC__)
#if (__GNUC__ >= 7)
__attribute__((fallthrough));
@@ -2420,12 +2461,12 @@ process_mrq_response(Rq_elem * rep, const struct sg_io_v4 * ctl_v4p,
}
if (ok && f1) {
++n_good;
- if (a_v4p->dout_xfer_len >= (uint32_t)clp->bs)
+ if (a_v4p->dout_xfer_len >= (uint32_t)rep->bs)
good_outblks += (a_v4p->dout_xfer_len - a_v4p->dout_resid) /
- clp->bs;
- if (a_v4p->din_xfer_len >= (uint32_t)clp->bs)
+ rep->bs;
+ if (a_v4p->din_xfer_len >= (uint32_t)rep->bs)
good_inblks += (a_v4p->din_xfer_len - a_v4p->din_resid) /
- clp->bs;
+ rep->bs;
}
} /* end of request array scan loop */
if ((n_subm == num_mrq) || (vb < 3))
@@ -2536,12 +2577,12 @@ chk_mrq_response(Rq_elem * rep, const struct sg_io_v4 * ctl_v4p,
}
if (ok) {
++n_good;
- if (a_np->dout_xfer_len >= (uint32_t)clp->bs)
+ if (a_np->dout_xfer_len >= (uint32_t)rep->bs)
good_outblks += (a_np->dout_xfer_len - a_np->dout_resid) /
- clp->bs;
- if (a_np->din_xfer_len >= (uint32_t)clp->bs)
+ rep->bs;
+ if (a_np->din_xfer_len >= (uint32_t)rep->bs)
good_inblks += (a_np->din_xfer_len - a_np->din_resid) /
- clp->bs;
+ rep->bs;
}
}
if ((n_subm == nrq) || (vb < 3))
@@ -3478,7 +3519,7 @@ sg_finish_io(bool wr, Rq_elem * rep, int pack_id, struct sg_io_extra *xtrp)
char ebuff[EBUFF_SZ];
snprintf(ebuff, EBUFF_SZ, "%s blk=%" PRId64, cp, blk);
- lk_chk_n_print3(ebuff, hp, false);
+ lk_chk_n_print3(ebuff, hp, clp->verbose > 1);
return res;
}
}
@@ -3554,7 +3595,7 @@ do_v4:
snprintf(ebuff, EBUFF_SZ, "%s rq_id=%d, blk=%" PRId64, cp,
pack_id, blk);
- lk_chk_n_print4(ebuff, h4p, false);
+ lk_chk_n_print4(ebuff, h4p, clp->verbose > 1);
if ((clp->verbose > 4) && h4p->info)
pr2serr_lk(" info=0x%x sg_info_check=%d direct=%d "
"detaching=%d aborted=%d\n", h4p->info,
@@ -4200,6 +4241,9 @@ parse_cmdline_sanity(int argc, char * argv[], struct global_collection * clp,
clp->verbose = sg_get_num(buf);
else if ((keylen > 1) && ('-' == key[0]) && ('-' != key[1])) {
res = 0;
+ n = num_chs_in_str(key + 1, keylen - 1, 'c');
+ clp->chkaddr += n;
+ res += n;
n = num_chs_in_str(key + 1, keylen - 1, 'd');
clp->dry_run += n;
res += n;
@@ -4229,8 +4273,10 @@ parse_cmdline_sanity(int argc, char * argv[], struct global_collection * clp,
key);
return SG_LIB_SYNTAX_ERROR;
}
- } else if ((0 == strncmp(key, "--dry-run", 9)) ||
- (0 == strncmp(key, "--dry_run", 9)))
+ } else if (0 == strncmp(key, "--chkaddr", 9))
+ ++clp->chkaddr;
+ else if ((0 == strncmp(key, "--dry-run", 9)) ||
+ (0 == strncmp(key, "--dry_run", 9)))
++clp->dry_run;
else if ((0 == strncmp(key, "--help", 6)) ||
(0 == strcmp(key, "-?")))
@@ -4418,18 +4464,20 @@ main(int argc, char * argv[])
out2f[0] = '\0';
outregf[0] = '\0';
fetch_sg_version();
- if (sg_version > 40000) {
- clp->in_flags.v4 = true;
- clp->out_flags.v4 = true;
- if (sg_version >= 40045)
- sg_version_ge_40045 = true;
- }
+ if (sg_version >= 40045)
+ sg_version_ge_40045 = true;
res = parse_cmdline_sanity(argc, argv, clp, inf, outf, out2f, outregf);
if (SG_LIB_OK_FALSE == res)
return 0;
if (res)
return res;
+ if (sg_version > 40000) {
+ if (! clp->in_flags.v3)
+ clp->in_flags.v4 = true;
+ if (! clp->out_flags.v3)
+ clp->out_flags.v4 = true;
+ }
install_handler(SIGINT, interrupt_handler);
install_handler(SIGQUIT, interrupt_handler);
@@ -4439,7 +4487,10 @@ main(int argc, char * argv[])
clp->infd = STDIN_FILENO;
clp->outfd = STDOUT_FILENO;
- if (clp->in_flags.ff) {
+ if (clp->in_flags.ff && clp->in_flags.zero) {
+ ccp = "<addr_as_data>";
+ cc2p = "addr_as_data";
+ } else if (clp->in_flags.ff) {
ccp = "<0xff bytes>";
cc2p = "ff";
} else if (clp->in_flags.random) {
@@ -4471,6 +4522,9 @@ main(int argc, char * argv[])
return SG_LIB_FILE_ERROR;
} else if (FT_SG == clp->in_type) {
clp->infd = sg_in_open(clp, inf, NULL, NULL);
+ if (clp->verbose > 2)
+ pr2serr("using sg v%c interface on %s\n",
+ (clp->in_flags.v4 ? '4' : '3'), inf);
if (clp->infd < 0)
return -clp->infd;
} else {
@@ -4528,6 +4582,9 @@ main(int argc, char * argv[])
return SG_LIB_FILE_ERROR;
} else if (FT_SG == clp->out_type) {
clp->outfd = sg_out_open(clp, outf, NULL, NULL);
+ if (clp->verbose > 2)
+ pr2serr("using sg v%c interface on %s\n",
+ (clp->out_flags.v4 ? '4' : '3'), outf);
if (clp->outfd < 0)
return -clp->outfd;
} else if (FT_DEV_NULL == clp->out_type)
@@ -4908,13 +4965,23 @@ main(int argc, char * argv[])
}
} /* started worker threads and here after they have all exited */
+ if (do_time && (start_tm.tv_sec || start_tm.tv_usec))
+ calc_duration_throughput(0);
+
shutting_down = true;
+ status = pthread_join(sig_listen_thread_id, &vp);
+ if (0 != status) err_exit(status, "pthread_join");
+#if 0
/* pthread_cancel() has issues and is not supported in Android */
status = pthread_kill(sig_listen_thread_id, SIGUSR2);
if (0 != status) err_exit(status, "pthread_kill");
+ std::this_thread::yield(); // not enough it seems
+ { /* allow time for SIGUSR2 signal to get through */
+ struct timespec tspec = {0, 400000}; /* 400 usecs */
- if (do_time && (start_tm.tv_sec || start_tm.tv_usec))
- calc_duration_throughput(0);
+ nanosleep(&tspec, NULL);
+ }
+#endif
if (do_sync) {
if (FT_SG == clp->out_type) {
diff --git a/testing/sgs_dd.c b/testing/sgs_dd.c
index 8af8612b..65b2c061 100644
--- a/testing/sgs_dd.c
+++ b/testing/sgs_dd.c
@@ -84,7 +84,7 @@
#include "sg_unaligned.h"
-static const char * version_str = "4.20 20210727";
+static const char * version_str = "4.21 20211006";
static const char * my_name = "sgs_dd";
#ifndef SGV4_FLAG_HIPRI
@@ -1201,8 +1201,10 @@ process_flags(const char * arg, struct flags_t * fp)
fp->tag = true;
else if (0 == strcmp(cp, "v3")) {
fp->v3 = true;
+ fp->v4 = false;
fp->given_v3v4 = true;
} else if (0 == strcmp(cp, "v4")) {
+ fp->v3 = false;
fp->v4 = true;
fp->given_v3v4 = true;
} else {
@@ -1251,6 +1253,8 @@ main(int argc, char * argv[])
clp->bpt = 0;
clp->in_evfd = -1;
clp->out_evfd = -1;
+ clp->iflag.v3 = true;
+ clp->oflag.v3 = true;
inf[0] = '\0';
outf[0] = '\0';
if (argc < 2) {
@@ -1288,7 +1292,9 @@ main(int argc, char * argv[])
pr2serr("%s: bad argument to 'iflag='\n", my_name);
return SG_LIB_SYNTAX_ERROR;
}
- } else if (0 == strcmp(key,"no_sig")) { /* default changes */
+ } else if (strcmp(key,"mrq") == 0)
+ ; /* do nothing */
+ else if (0 == strcmp(key,"no_sig")) { /* default changes */
clp->no_sig = !!sg_get_num(buf);
no_sig_given = true;
} else if (0 == strcmp(key,"obs"))
@@ -1309,6 +1315,8 @@ main(int argc, char * argv[])
seek = sg_get_num(buf);
else if (0 == strcmp(key,"skip"))
skip = sg_get_num(buf);
+ else if (0 == strcmp(key,"time"))
+ ; /* do nothing */
else if ((0 == strcmp(key,"-V")) || (0 == strcmp(key,"--version"))) {
pr2serr("%s: version: %s\n", my_name, version_str);
return 0;
@@ -1499,9 +1507,11 @@ main(int argc, char * argv[])
}
}
if ((clp->in_is_sg || clp->out_is_sg) && !clp->iflag.given_v3v4 &&
- !clp->oflag.given_v3v4 && (clp->debug > 0))
+ !clp->oflag.given_v3v4 && (clp->debug > 0)) {
+ clp->iflag.v3 = true;
pr2serr("using sg driver version 3 interface on %s\n",
clp->in_is_sg ? inf : outf);
+ }
if (0 == count)
return 0;