From f0195003bb0c66ba55084b2f7e0fe982f08c5675 Mon Sep 17 00:00:00 2001 From: Douglas Gilbert Date: Thu, 28 Oct 2021 23:35:11 +0000 Subject: 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 --- testing/sg_mrq_dd.cpp | 164 +++++++++++++++++++++++++++++-------------------- testing/sgh_dd.cpp | 167 +++++++++++++++++++++++++++++++++++--------------- testing/sgs_dd.c | 16 ++++- 3 files changed, 228 insertions(+), 119 deletions(-) (limited to 'testing') 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 #include #include +#include /* for nanosleep() */ #include #include // #include @@ -69,7 +70,8 @@ static const char * version_str = "1.36 20210906"; #include #include // needed for std::this_thread::yield() #include -#include +#include // for infant_cv: copy/verify first segment + // single threaded #include #ifdef HAVE_CONFIG_H @@ -286,8 +288,8 @@ struct global_collection /* one instance visible to all threads */ atomic 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(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(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(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(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 work_thr; - vector listen_thr; + vector work_thr_v; + vector 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 = ""; + 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 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 = ""; + 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; -- cgit v1.2.3