diff options
author | Douglas Gilbert <dgilbert@interlog.com> | 2021-05-02 01:09:24 +0000 |
---|---|---|
committer | Douglas Gilbert <dgilbert@interlog.com> | 2021-05-02 01:09:24 +0000 |
commit | 0791cf6b3cd25a054d12c42425cbb8ffee7e598a (patch) | |
tree | e50a551f783363a35d07893dd9db836d60080e0b /testing | |
parent | 28400776770cf5453f196690fcd24e353c5826e0 (diff) | |
download | sg3_utils-0791cf6b3cd25a054d12c42425cbb8ffee7e598a.tar.gz |
major rework of lib/sg_pt_freebsd.c; sg_raw: fix prints of NVMe NVM command names
git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@896 6180dd3e-e324-4e3e-922d-17de1ae2f315
Diffstat (limited to 'testing')
-rw-r--r-- | testing/sg_mrq_dd.cpp | 103 | ||||
-rw-r--r-- | testing/sgh_dd.cpp | 138 |
2 files changed, 190 insertions, 51 deletions
diff --git a/testing/sg_mrq_dd.cpp b/testing/sg_mrq_dd.cpp index 49f027ae..4a486d8b 100644 --- a/testing/sg_mrq_dd.cpp +++ b/testing/sg_mrq_dd.cpp @@ -30,7 +30,7 @@ * */ -static const char * version_str = "1.26 20210402"; +static const char * version_str = "1.27 20210424"; #define _XOPEN_SOURCE 600 #ifndef _GNU_SOURCE @@ -133,6 +133,8 @@ using namespace std; #define DEF_BLOCK_SIZE 512 #define DEF_BLOCKS_PER_TRANSFER 128 #define DEF_BLOCKS_PER_2048TRANSFER 32 +#define DEF_SDT_ICT_MS 300 +#define DEF_SDT_CRT_SEC 3 #define DEF_SCSI_CDB_SZ 10 #define MAX_SCSI_CDB_SZ 16 /* could be 32 */ #define PACK_ID_TID_MULTIPLIER (0x1000000) /* 16,777,216 */ @@ -151,7 +153,6 @@ using namespace std; #define DEF_NUM_THREADS 4 #define MAX_NUM_THREADS 1024 /* was SG_MAX_QUEUE with v3 driver */ #define DEF_MRQ_NUM 16 -#define DEF_STALL_THRESH 4 #ifndef RAW_MAJOR #define RAW_MAJOR 255 /*unlikely value */ @@ -191,7 +192,7 @@ struct flags_t { bool no_dur; bool nocreat; bool no_waitq; /* dummy, no longer supported, just warn */ - bool order; + bool order_wr; bool qhead; bool qtail; bool random; @@ -255,6 +256,8 @@ struct global_collection /* one instance visible to all threads */ atomic<int> sum_of_resids; atomic<int> reason_res; 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; bool mrq_eq_0; /* true when user gives mrq=0 */ @@ -861,11 +864,11 @@ usage(int pg_num) "[dio=0|1]\n" " [elemsz_kb=EKB] [ese=0|1] [fua=0|1|2|3] " "[hipri=NRQS]\n" - " [mrq=NRQS] [ofreg=OFREG] [sync=0|1] " - "[thr=THR]\n" - " [time=0|1|2[,TO]] [verbose=VERB] [--dry-run] " - "[--pre-fetch]\n" - " [--verbose] [--version]\n\n" + " [mrq=NRQS] [ofreg=OFREG] [sdt=SDT] " + "[sync=0|1]\n" + " [thr=THR] [time=0|1|2[,TO]] [verbose=VERB] " + "[--dry-run]\n" + " [--pre-fetch] [--verbose] [--version]\n\n" " where: operands have the form name=value and are pecular to " "'dd'\n" " style commands, and options start with one or " @@ -937,6 +940,12 @@ page2: " ofreg OFREG is regular file or pipe to send what is " "read from\n" " IFILE in the first half of each shared element\n" + " sdt stall detection times: CRT[,ICT]. CRT: check " + "repetition\n" + " time (after first) in seconds; ICT: initial " + "check time\n" + " in milliseconds. Default: 3,300 . Use CRT=0 " + "to disable\n" " sync 0->no sync(def), 1->SYNCHRONIZE CACHE on OFILE " "after copy\n" " thr is number of threads, must be > 0, default 4, " @@ -1141,40 +1150,38 @@ static void sig_listen_thread(struct global_collection * clp) { bool stall_reported = false; - int stall_count = 0; int prev_pack_id = 0; int sig_number, pack_id; + uint32_t ict_ms = (clp->sdt_ict ? clp->sdt_ict : DEF_SDT_ICT_MS); struct timespec ts; struct timespec * tsp = &ts; - tsp->tv_sec = 0; - tsp->tv_nsec = 300 * 1000 * 1000; /* 300 ms */ + tsp->tv_sec = ict_ms / 1000; + tsp->tv_nsec = (ict_ms % 1000) * 1000 * 1000; /* DEF_SDT_ICT_MS */ while (1) { sig_number = sigtimedwait(&signal_set, NULL, tsp); if (shutting_down) break; if (sig_number < 0) { - int err = errno; - - if (EAGAIN == err) { /* timeout */ - pack_id = clp->most_recent_pack_id.load(); - if (pack_id == prev_pack_id) { - ++stall_count; - if (0 == (stall_count % DEF_STALL_THRESH)) { - if (! stall_reported) { - stall_reported = true; - pr2serr_lk("%s: stall at pack_id=%d " - "detected\n", __func__, pack_id); - } - pr2serr_lk("%s: stall at pack_id=%d, dump sg/debug\n", + int err = errno; + + /* EAGAIN implies a timeout */ + if ((EAGAIN == err) && (clp->sdt_crt > 0)) { + pack_id = clp->most_recent_pack_id.load(); + if ((pack_id > 0) && (pack_id == prev_pack_id)) { + if (! stall_reported) { + stall_reported = true; + tsp->tv_sec = clp->sdt_crt; + tsp->tv_nsec = 0; + pr2serr_lk("%s: first stall at pack_id=%d detected\n", __func__, pack_id); - system_wrapper("/usr/bin/cat /proc/scsi/sg/debug\n"); - } - } else { - stall_count = 0; + } else + pr2serr_lk("%s: subsequent stall at pack_id=%d\n", + __func__, pack_id); + system_wrapper("/usr/bin/cat /proc/scsi/sg/debug\n"); + } else prev_pack_id = pack_id; - } - } else + } else if (EAGAIN != err) pr2serr_lk("%s: sigtimedwait() errno=%d\n", __func__, err); } if (SIGINT == sig_number) { @@ -1182,7 +1189,7 @@ sig_listen_thread(struct global_collection * clp) clp->next_count_pos.store(-1); shutting_down.store(true); } - } + } /* end of while loop */ if (clp->verbose > 1) pr2serr_lk("%s: exiting\n", __func__); } @@ -1809,7 +1816,7 @@ process_mrq_response(Rq_elem * rep, const struct sg_io_v4 * ctl_v4p, sg_info_str(a_v4p->info, sizeof(b), b)); } sstatus = a_v4p->device_status; - if ((sstatus && (SAM_STAT_CONDITION_MET != sstatus)) || + if ((! sg_scsi_status_is_good(sstatus)) || a_v4p->transport_status || a_v4p->driver_status) { ok = false; last_err_on_in = ! (a_v4p->flags & SGV4_FLAG_DO_ON_OTHER); @@ -2729,7 +2736,7 @@ do_both_sg_segment(Rq_elem * rep, scat_gath_iter & i_sg_it, ctl_v4.flags = SGV4_FLAG_MULTIPLE_REQS | SGV4_FLAG_SHARE; if (! (iflagsp->coe || oflagsp->coe)) ctl_v4.flags |= SGV4_FLAG_STOP_IF; - if ((! clp->verify) && clp->out_flags.order) + if ((! clp->verify) && clp->out_flags.order_wr) ctl_v4.flags |= SGV4_FLAG_ORDERED_WR; if (clp->mrq_hipri) ctl_v4.flags |= SGV4_FLAG_HIPRI; @@ -3117,9 +3124,9 @@ process_flags(const char * arg, struct flags_t * fp) else if (0 == strcmp(cp, "null")) ; else if (0 == strcmp(cp, "ordered")) - fp->order = true; + fp->order_wr = true; else if (0 == strcmp(cp, "order")) - fp->order = true; + fp->order_wr = true; else if (0 == strcmp(cp, "qhead")) fp->qhead = true; else if (0 == strcmp(cp, "qtail")) @@ -3462,6 +3469,23 @@ parse_cmdline_sanity(int argc, char * argv[], struct global_collection * clp, pr2serr("%sbad argument to 'oflag='\n", my_name); goto syn_err; } + } else if (0 == strcmp(key, "sdt")) { + ccp = strchr(buf, ','); + n = sg_get_num(buf); + if (n < 0) { + pr2serr("%sbad argument to 'sdt=CRT[,ICT]'\n", my_name); + goto syn_err; + } + clp->sdt_crt = n; + if (ccp) { + n = sg_get_num(ccp + 1); + if (n < 0) { + pr2serr("%sbad 2nd argument to 'sdt=CRT,ICT'\n", + my_name); + goto syn_err; + } + clp->sdt_ict = n; + } } else if (0 == strcmp(key, "seek")) { n = strlen(buf); if (n < 1) { @@ -3635,7 +3659,7 @@ parse_cmdline_sanity(int argc, char * argv[], struct global_collection * clp, * SG_IO ioctl. So reduce it in that case. */ if ((clp->bs >= 2048) && (! bpt_given)) clp->bpt = DEF_BLOCKS_PER_2048TRANSFER; - if (clp->in_flags.order && (! clp->out_flags.order)) + if (clp->in_flags.order_wr && (! clp->out_flags.order_wr)) pr2serr("Warning iflag=order is ignored, use with oflag=\n"); if ((num_threads < 1) || (num_threads > MAX_NUM_THREADS)) { pr2serr("too few or too many threads requested\n"); @@ -3906,6 +3930,8 @@ main(int argc, char * argv[]) clp->dd_count = SG_COUNT_INDEFINITE; clp->bpt = DEF_BLOCKS_PER_TRANSFER; clp->cmd_timeout = DEF_TIMEOUT; + clp->sdt_ict = DEF_SDT_ICT_MS; + clp->sdt_crt = DEF_SDT_CRT_SEC; clp->in_type = FT_FIFO; /* change dd's default: if of=OFILE not given, assume /dev/null */ clp->out_type = FT_DEV_NULL; @@ -4076,7 +4102,10 @@ main(int argc, char * argv[]) if (clp->in_flags.serial || clp->out_flags.serial) pr2serr("serial flag ignored when both IFILE and OFILE are sg " "devices\n"); - } else if (clp->in_flags.order) + if (clp->in_flags.order_wr && (num_threads > 1)) + pr2serr("Warning: write ordering only guaranteed for single " + "thread\n"); + } else if (clp->in_flags.order_wr) pr2serr("Warning: oflag=order only active on sg->sg copies\n"); if (outregf[0]) { diff --git a/testing/sgh_dd.cpp b/testing/sgh_dd.cpp index 7fb4ae06..af226958 100644 --- a/testing/sgh_dd.cpp +++ b/testing/sgh_dd.cpp @@ -36,7 +36,7 @@ * renamed [20181221] */ -static const char * version_str = "2.04 20210402"; +static const char * version_str = "2.06 20210427"; #define _XOPEN_SOURCE 600 #ifndef _GNU_SOURCE @@ -130,6 +130,8 @@ using namespace std; #define DEF_BLOCK_SIZE 512 #define DEF_BLOCKS_PER_TRANSFER 128 #define DEF_BLOCKS_PER_2048TRANSFER 32 +#define DEF_SDT_ICT_MS 300 +#define DEF_SDT_CRT_SEC 3 #define DEF_SCSI_CDBSZ 10 #define MAX_SCSI_CDBSZ 16 @@ -244,7 +246,8 @@ struct global_collection int ofsplit; atomic<int> dio_incomplete_count; atomic<int> sum_of_resids; - int vebose; + uint32_t sdt_ict; /* stall detection; initial check time (milliseconds) */ + uint32_t sdt_crt; /* check repetition time (seconds), after first stall */ int fail_mask; int verbose; int dry_run; @@ -914,12 +917,13 @@ usage(int pg_num) "[fua=0|1|2|3]\n" " [mrq=[I|O,]NRQS[,C]] [noshare=0|1] " "[of2=OFILE2]\n" - " [ofreg=OFREG] [ofsplit=OSP] [sync=0|1] " - "[thr=THR]\n" - " [time=0|1|2[,TO]] [unshare=1|0] [verbose=VERB] " - "[--dry-run]\n" - " [--prefetch] [-v|-vv|-vvv] [--verbose] [--verify] " - "[--version]\n\n" + " [ofreg=OFREG] [ofsplit=OSP] [sdt=SDT] " + "[sync=0|1]\n" + " [thr=THR] [time=0|1|2[,TO]] [unshare=1|0] " + "[verbose=VERB]\n" + " [--dry-run] [--prefetch] [-v|-vv|-vvv] " + "[--verbose]\n" + " [--verify] [--version]\n\n" " where the main options (shown in first group above) are:\n" " bs must be device logical block size (default " "512)\n" @@ -995,6 +999,12 @@ page2: " IFILE in the first half of each shared element\n" " ofsplit split ofile write in two at block OSP (def: 0 " "(no split))\n" + " sdt stall detection times: CRT[,ICT]. CRT: check " + "repetition\n" + " time (after first) in seconds; ICT: initial " + "check time\n" + " in milliseconds. Default: 3,300 . Use CRT=0 " + "to disable\n" " sync 0->no sync(def), 1->SYNCHRONIZE CACHE on OFILE " "after copy\n" " thr is number of threads, must be > 0, default 4, " @@ -1188,22 +1198,103 @@ read_blkdev_capacity(int sg_fd, int64_t * num_sect, int * sect_sz) #endif } +static int +system_wrapper(const char * cmd) +{ + int res; + + res = system(cmd); + if (WIFSIGNALED(res) && + (WTERMSIG(res) == SIGINT || WTERMSIG(res) == SIGQUIT)) + raise(WTERMSIG(res)); + return WEXITSTATUS(res); +} + +/* Has an infinite loop doing a timed wait for any signals in sig_set. After + * each timeout (300 ms) checks if the most_recent_pack_id atomic integer + * has changed. If not after another two timeouts announces a stall has + * been detected. If shutting down atomic is true breaks out of loop and + * shuts down this thread. Other than that, this thread is normally cancelled + * by the main thread, after other threads have exited. */ static void * sig_listen_thread(void * v_clp) { + bool stall_reported = false; + int prev_pack_id = 0; + int sig_number, pack_id; + struct timespec ts; + struct timespec * tsp = &ts; struct global_collection * clp = (struct global_collection *)v_clp; - int sig_number; + uint32_t ict_ms = (clp->sdt_ict ? clp->sdt_ict : DEF_SDT_ICT_MS); + tsp->tv_sec = ict_ms / 1000; + tsp->tv_nsec = (ict_ms % 1000) * 1000 * 1000; /* DEF_SDT_ICT_MS */ while (1) { - sigwait(&signal_set, &sig_number); + sig_number = sigtimedwait(&signal_set, NULL, tsp); if (shutting_down) break; + if (sig_number < 0) { + int err = errno; + + /* EAGAIN implies a timeout */ + if ((EAGAIN == err) && (clp->sdt_crt > 0)) { + pack_id = mono_pack_id.load(); + if ((pack_id > 0) && (pack_id == prev_pack_id)) { + if (! stall_reported) { + stall_reported = true; + tsp->tv_sec = clp->sdt_crt; + tsp->tv_nsec = 0; + pr2serr_lk("%s: first stall at pack_id=%d detected\n", + __func__, pack_id); + } else + pr2serr_lk("%s: subsequent stall at pack_id=%d\n", + __func__, pack_id); + system_wrapper("/usr/bin/cat /proc/scsi/sg/debug\n"); + } else + prev_pack_id = pack_id; + } else if (EAGAIN != err) + pr2serr_lk("%s: sigtimedwait() errno=%d\n", __func__, err); + } + if (SIGINT == sig_number) { + pr2serr_lk("%sinterrupted by SIGINT\n", my_name); + stop_both(clp); + pthread_cond_broadcast(&clp->out_sync_cv); + } + } /* end of while loop */ + if (clp->verbose > 1) + pr2serr_lk("%s: exiting\n", __func__); + + +#if 0 + + + if (EAGAIN == err) { /* timeout */ + pack_id = mono_pack_id.load(); + if (pack_id == prev_pack_id) { + if (! stall_reported) { + stall_reported = true; + tsp->tv_sec = 2; + tsp->tv_nsec = 0; + pr2serr_lk("%s: first stall at pack_id=%d " + "detected\n", __func__, pack_id); + } else + pr2serr_lk("%s: subsequent stall at pack_id=%d\n", + __func__, pack_id); + system_wrapper("/usr/bin/cat /proc/scsi/sg/debug\n"); + } else + prev_pack_id = pack_id; + } else + pr2serr_lk("%s: sigtimedwait() errno=%d\n", __func__, err); + } if (SIGINT == sig_number) { pr2serr_lk("%sinterrupted by SIGINT\n", my_name); stop_both(clp); pthread_cond_broadcast(&clp->out_sync_cv); } } + if (clp->verbose > 1) + pr2serr_lk("%s: exiting\n", __func__); +#endif return NULL; } @@ -2321,7 +2412,7 @@ process_mrq_response(Rq_elem * rep, const struct sg_io_v4 * ctl_v4p, sg_info_str(a_v4p->info, sizeof(b), b)); } sstatus = a_v4p->device_status; - if ((sstatus && (SAM_STAT_CONDITION_MET != sstatus)) || + if ((! sg_scsi_status_is_good(sstatus)) || a_v4p->transport_status || a_v4p->driver_status) { ok = false; if (SAM_STAT_CHECK_CONDITION != a_v4p->device_status) { @@ -2441,7 +2532,7 @@ chk_mrq_response(Rq_elem * rep, const struct sg_io_v4 * ctl_v4p, sg_info_str(a_np->info, sizeof(b), b)); } sstatus = a_np->device_status; - if ((sstatus && (SAM_STAT_CONDITION_MET != sstatus)) || + if ((! sg_scsi_status_is_good(sstatus)) || a_np->transport_status || a_np->driver_status) { ok = false; if (SAM_STAT_CHECK_CONDITION != a_np->device_status) { @@ -4045,6 +4136,23 @@ parse_cmdline_sanity(int argc, char * argv[], struct global_collection * clp, pr2serr("%sbad argument to 'oflag='\n", my_name); return SG_LIB_SYNTAX_ERROR; } + } else if (0 == strcmp(key, "sdt")) { + cp = strchr(buf, ','); + n = sg_get_num(buf); + if (n < 0) { + pr2serr("%sbad argument to 'sdt=CRT[,ICT]'\n", my_name); + return SG_LIB_SYNTAX_ERROR; + } + clp->sdt_crt = n; + if (cp) { + n = sg_get_num(cp + 1); + if (n < 0) { + pr2serr("%sbad 2nd argument to 'sdt=CRT,ICT'\n", + my_name); + return SG_LIB_SYNTAX_ERROR; + } + clp->sdt_ict = n; + } } else if (0 == strcmp(key, "seek")) { clp->seek = sg_get_llnum(buf); if (-1LL == clp->seek) { @@ -4129,7 +4237,7 @@ parse_cmdline_sanity(int argc, char * argv[], struct global_collection * clp, version_given = true; else { pr2serr("Unrecognized option '%s'\n", key); - pr2serr("For more information use '--help'\n"); + pr2serr("For more information use '--help' or '-h'\n"); return SG_LIB_SYNTAX_ERROR; } } @@ -4292,6 +4400,8 @@ main(int argc, char * argv[]) clp->out2_type = FT_DEV_NULL; clp->cdbsz_in = DEF_SCSI_CDBSZ; clp->cdbsz_out = DEF_SCSI_CDBSZ; + clp->sdt_ict = DEF_SDT_ICT_MS; + clp->sdt_crt = DEF_SDT_CRT_SEC; clp->nmrqs = DEF_NUM_MRQS; clp->unshare = true; inf[0] = '\0'; @@ -4599,7 +4709,7 @@ main(int argc, char * argv[]) if ((STDIN_FILENO == clp->infd) && (STDOUT_FILENO == clp->outfd)) { pr2serr("Won't default both IFILE to stdin _and_ OFILE to " "/dev/null\n"); - pr2serr("For more information use '--help'\n"); + pr2serr("For more information use '--help' or '-h'\n"); return SG_LIB_SYNTAX_ERROR; } if (dd_count < 0) { |