diff options
author | Douglas Gilbert <dgilbert@interlog.com> | 2021-10-28 23:35:11 +0000 |
---|---|---|
committer | Douglas Gilbert <dgilbert@interlog.com> | 2021-10-28 23:35:11 +0000 |
commit | f0195003bb0c66ba55084b2f7e0fe982f08c5675 (patch) | |
tree | ac27a2f679ce91e865fa0a578c9cfa2d97110b07 /testing/sg_mrq_dd.cpp | |
parent | c1ce6d6c5f3f64038e17dfd65380aa728c5d994d (diff) | |
download | sg3_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/sg_mrq_dd.cpp')
-rw-r--r-- | testing/sg_mrq_dd.cpp | 164 |
1 files changed, 98 insertions, 66 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) && |