aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gilbert <dgilbert@interlog.com>2018-12-21 19:33:41 +0000
committerDouglas Gilbert <dgilbert@interlog.com>2018-12-21 19:33:41 +0000
commitf32c01a8a383e9d15f20a6784749aab0ed248ad8 (patch)
tree6c8d68ea311299ec70cb4034b8573af048809fdd
parent18c9852db91032afe4bedd85857d558402b360e2 (diff)
downloadsg3_utils-f32c01a8a383e9d15f20a6784749aab0ed248ad8.tar.gz
sg_raw: fix --send bug when using stdin; work on sgs_dd
git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@800 6180dd3e-e324-4e3e-922d-17de1ae2f315
-rw-r--r--ChangeLog3
-rw-r--r--doc/sg_raw.82
-rw-r--r--src/sg_raw.c37
-rw-r--r--testing/sgs_dd.c88
4 files changed, 92 insertions, 38 deletions
diff --git a/ChangeLog b/ChangeLog
index 61559027..49ca7341 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,13 +2,14 @@ Each utility has its own version number, date of last change and
some description at the top of its ".c" file. All utilities in the main
directory have their own "man" pages. There is also a sg3_utils man page.
-Changelog for sg3_utils-1.45 [20181217] [svn: r798]
+Changelog for sg3_utils-1.45 [20181220] [svn: r800]
- sg_ses: bug: --page= being overridden when --control
and --data= also given; fix
- sg_opcodes: expand MLU (18-102r0)
- sg_write_buffer: allow comma and period separated
lists when input from stdin
- sg_format: add --dcrt used twice (FOV=1 DCRT=0)
+ - sg_raw: fix --send bug when using stdin
- sg_scan (win32): expand limits for big arrays
- rescan-scsi-bus: widen LUN 0 only scanning
- testing/sg_tst_async: fix free_list issue
diff --git a/doc/sg_raw.8 b/doc/sg_raw.8
index b6bdbccd..62fa3cc2 100644
--- a/doc/sg_raw.8
+++ b/doc/sg_raw.8
@@ -1,4 +1,4 @@
-.TH SG_RAW "8" "May 2018" "sg3_utils\-1.43" SG3_UTILS
+.TH SG_RAW "8" "December 2018" "sg3_utils\-1.45" SG3_UTILS
.SH NAME
sg_raw \- send arbitrary SCSI command to a device
.SH SYNOPSIS
diff --git a/src/sg_raw.c b/src/sg_raw.c
index 9cc0ab2b..33a85f7c 100644
--- a/src/sg_raw.c
+++ b/src/sg_raw.c
@@ -39,7 +39,7 @@
#include "sg_pr2serr.h"
#include "sg_unaligned.h"
-#define SG_RAW_VERSION "0.4.27 (2018-06-27)"
+#define SG_RAW_VERSION "0.4.28 (2018-12-20)"
#define DEFAULT_TIMEOUT 20
#define MIN_SCSI_CDBSZ 6
@@ -540,7 +540,7 @@ static uint8_t *
fetch_dataout(struct opts_t * op, uint8_t ** free_buf, int * errp)
{
bool ok = false;
- int fd, len, err;
+ int fd, len, tot_len, boff, err;
uint8_t *buf = NULL;
*free_buf = NULL;
@@ -574,28 +574,29 @@ fetch_dataout(struct opts_t * op, uint8_t ** free_buf, int * errp)
}
}
- buf = sg_memalign(op->dataout_len, 0 /* page_size */, free_buf,
- op->verbose > 3);
+ tot_len = op->dataout_len;
+ buf = sg_memalign(tot_len, 0 /* page_size */, free_buf, op->verbose > 3);
if (buf == NULL) {
- pr2serr("sg_memalign: failed to get %d bytes of memory\n",
- op->dataout_len);
+ pr2serr("sg_memalign: failed to get %d bytes of memory\n", tot_len);
if (errp)
*errp = sg_convert_errno(ENOMEM);
goto bail;
}
- len = read(fd, buf, op->dataout_len);
- if (len < 0) {
- err = errno;
- if (errp)
- *errp = sg_convert_errno(err);
- perror("Failed to read input data");
- goto bail;
- } else if (len < op->dataout_len) {
- if (errp)
- *errp = SG_LIB_FILE_ERROR;
- pr2serr("EOF on input file/stream\n");
- goto bail;
+ for (boff = 0; boff < tot_len; boff += len) {
+ len = read(fd, buf + boff , tot_len - boff);
+ if (len < 0) {
+ err = errno;
+ if (errp)
+ *errp = sg_convert_errno(err);
+ perror("Failed to read input data");
+ goto bail;
+ } else if (0 == len) {
+ if (errp)
+ *errp = SG_LIB_FILE_ERROR;
+ pr2serr("EOF on input file/stream at buffer offset %d\n", boff);
+ goto bail;
+ }
}
ok = true;
diff --git a/testing/sgs_dd.c b/testing/sgs_dd.c
index 3d1a1076..15c4a4b0 100644
--- a/testing/sgs_dd.c
+++ b/testing/sgs_dd.c
@@ -88,7 +88,7 @@
#include "sg_pr2serr.h"
-static const char * version_str = "1.06 20181215";
+static const char * version_str = "1.08 20181220";
#ifdef __GNUC__
#pragma GCC diagnostic ignored "-Wclobbered"
@@ -141,6 +141,7 @@ struct flags_t {
bool fua;
bool mmap;
bool noshare;
+ bool noxfer;
bool v3;
bool v4;
};
@@ -152,6 +153,7 @@ typedef struct global_collection
int in_type;
int cdbsz_in;
int help;
+ int elem_sz;
struct flags_t in_flags;
int64_t in_blk; /* -\ next block address to read */
int64_t in_count; /* | blocks remaining for next read */
@@ -180,6 +182,7 @@ typedef struct global_collection
int sum_of_resids; /* -/ */
int debug; /* both -v and deb=VERB bump this field */
int dry_run;
+ bool ofile_given;
const char * infp;
const char * outfp;
} Gbl_coll;
@@ -240,7 +243,7 @@ static pthread_mutex_t strerr_mut = PTHREAD_MUTEX_INITIALIZER;
static bool shutting_down = false;
static bool do_sync = false;
-static bool do_time = false;
+static bool do_time = true;
static Gbl_coll gcoll;
static struct timeval start_tm;
static int64_t dd_count = -1;
@@ -479,9 +482,10 @@ usage(int pg_num)
" [--help] [--version]\n\n");
pr2serr(" [bpt=BPT] [cdbsz=6|10|12|16] [coe=0|1] "
"[deb=VERB] [dio=0|1]\n"
- " [fua=0|1|2|3] [of2=OFILE2] [sync=0|1] [thr=THR] "
- "[time=0|1]\n"
- " [verbose=VERB] [--dry-run] [--verbose]\n\n"
+ " [elemsz_kb=ESK] [fua=0|1|2|3] [of2=OFILE2] "
+ "[sync=0|1]\n"
+ " [thr=THR] [time=0|1] [verbose=VERB] [--dry-run] "
+ "[--verbose]\n\n"
" where the main options (shown in first group above) are:\n"
" bs must be device logical block size (default "
"512)\n"
@@ -489,13 +493,14 @@ usage(int pg_num)
" if file or device to read from (def: stdin)\n"
" iflag comma separated list from: [2fds,coe,defres,dio,"
"direct,dpo,\n"
- " dsync,excl,fua,mmap,noshare,null,v3,v4]\n"
- " of file or device to write to (def: stdout), "
- "OFILE of '.'\n"
- " treated as /dev/null\n"
+ " dsync,excl,fua,mmap,noshare,noxfer,null,v3,v4]\n"
+ " of file or device to write to (def: /dev/null which "
+ "is different\n"
+ " from dd that defaults to stdout). If 'of=.' "
+ "assumes /dev/null\n"
" oflag comma separated list from: [2fds,append,coe,dio,"
"direct,dpo,\n"
- " dsync,excl,fua,mmap,noshare,null,v3,v4]\n"
+ " dsync,excl,fua,mmap,noshare,noxfer,null,v3,v4]\n"
" 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"
@@ -503,7 +508,9 @@ usage(int pg_num)
"Copy from IFILE to OFILE, similar to dd command. This utility "
"is specialized\nfor SCSI devices and uses multiple POSIX "
"threads. It expects one or both\nIFILE and OFILE to be sg "
- "devices. Use '-hh' or '-hhh' for more information.\n"
+ "devices. It is Linux specific and uses the v4\nsg driver "
+ "'share' capbility if available (hence the 'sgs' part of its "
+ "name).\nUse '-hh' or '-hhh' for more information.\n"
);
return;
page2:
@@ -520,6 +527,8 @@ page2:
" deb for debug, 0->none (def), > 0->varying degrees "
"of debug\n"
" dio is direct IO, 1->attempt, 0->indirect IO (def)\n"
+ " elemsz_kb scatter gather list element size in kilobytes "
+ "(def: 32 [KB])\n"
" fua force unit access: 0->don't(def), 1->OFILE, "
"2->IFILE,\n"
" 3->OFILE+IFILE\n"
@@ -530,8 +539,8 @@ page2:
"after copy\n"
" thr is number of threads, must be > 0, default 4, "
"max 16\n"
- " time 0->no timing(def), 1->time plus calculate "
- "throughput\n"
+ " time 0->no timing, 1->time plus calculate "
+ "throughput (def)\n"
" verbose same as 'deb=VERB': increase verbosity\n"
" --dry-run|-d prepare but bypass copy/read\n"
" --verbose|-v increase verbosity of utility\n\n"
@@ -770,7 +779,7 @@ read_write_thread(void * v_tip)
rep->in_flags = clp->in_flags;
rep->out_flags = clp->out_flags;
if (rep->in_flags.fds2 || rep->out_flags.fds2)
- ;
+ ; /* we are sharing a single pair of fd_s across all threads */
else {
int fd;
@@ -1255,6 +1264,7 @@ sg_start_io(Rq_elem * rep)
bool dpo = wr ? rep->out_flags.dpo : rep->in_flags.dpo;
bool dio = wr ? rep->out_flags.dio : rep->in_flags.dio;
bool mmap = wr ? rep->out_flags.mmap : rep->in_flags.mmap;
+ bool noxfer = wr ? rep->out_flags.noxfer : rep->in_flags.noxfer;
bool v4 = wr ? rep->out_flags.v4 : rep->in_flags.v4;
int cdbsz = wr ? rep->cdbsz_out : rep->cdbsz_in;
int flags = 0;
@@ -1275,6 +1285,8 @@ sg_start_io(Rq_elem * rep)
flags |= SG_FLAG_MMAP_IO;
c3p = " mmap";
}
+ if (noxfer)
+ flags |= SG_FLAG_NO_DXFER;
if (dio)
flags |= SG_FLAG_DIRECT_IO;
if (rep->has_share) {
@@ -1496,7 +1508,8 @@ do_v4:
/* Returns reserved_buffer_size/mmap_size if success, else 0 for failure */
static int
-sg_prepare(int fd, int bs, int bpt, bool def_res, uint8_t **mmpp)
+sg_prepare_resbuf(int fd, int bs, int bpt, bool def_res, int elem_sz,
+ uint8_t **mmpp)
{
int res, t, num;
uint8_t *mmp;
@@ -1506,6 +1519,27 @@ sg_prepare(int fd, int bs, int bpt, bool def_res, uint8_t **mmpp)
pr2serr_lk("%ssg driver prior to 3.9.02\n", my_name);
return 0;
}
+ if (elem_sz >= 4096) {
+ struct sg_extended_info sei;
+ struct sg_extended_info * seip;
+
+ seip = &sei;
+ memset(seip, 0, sizeof(*seip));
+ seip->valid_rd_mask |= SG_SEIM_SGAT_ELEM_SZ;
+ res = ioctl(fd, SG_SET_GET_EXTENDED, seip);
+ if (res < 0)
+ pr2serr_lk("sgs_dd: %s: SG_SET_GET_EXTENDED(SGAT_ELEM_SZ) rd "
+ "error: %s\n", __func__, strerror(errno));
+ if (elem_sz != (int)seip->sgat_elem_sz) {
+ memset(seip, 0, sizeof(*seip));
+ seip->valid_wr_mask |= SG_SEIM_SGAT_ELEM_SZ;
+ seip->sgat_elem_sz = elem_sz;
+ res = ioctl(fd, SG_SET_GET_EXTENDED, seip);
+ if (res < 0)
+ pr2serr_lk("sgs_dd: %s: SG_SET_GET_EXTENDED(SGAT_ELEM_SZ) "
+ "wr error: %s\n", __func__, strerror(errno));
+ }
+ }
if (! def_res) {
num = bs * bpt;
res = ioctl(fd, SG_SET_RESERVED_SIZE, &num);
@@ -1570,6 +1604,8 @@ process_flags(const char * arg, struct flags_t * fp)
fp->mmap = true;
else if (0 == strcmp(cp, "noshare"))
fp->noshare = true;
+ else if (0 == strcmp(cp, "noxfer"))
+ fp->noxfer = true;
else if (0 == strcmp(cp, "null"))
;
else if (0 == strcmp(cp, "v3"))
@@ -1620,7 +1656,8 @@ sg_in_open(Gbl_coll *clp, const char *inf, uint8_t **mmpp, int * mmap_lenp)
perror(ebuff);
return -sg_convert_errno(err);;
}
- n = sg_prepare(fd, clp->bs, clp->bpt, clp->in_flags.defres, mmpp);
+ n = sg_prepare_resbuf(fd, clp->bs, clp->bpt, clp->in_flags.defres,
+ clp->elem_sz, mmpp);
if (n <= 0)
return -SG_LIB_FILE_ERROR;
if (mmap_lenp)
@@ -1649,7 +1686,8 @@ sg_out_open(Gbl_coll *clp, const char *outf, uint8_t **mmpp, int * mmap_lenp)
perror(ebuff);
return -sg_convert_errno(err);
}
- n = sg_prepare(fd, clp->bs, clp->bpt, clp->out_flags.defres, mmpp);
+ n = sg_prepare_resbuf(fd, clp->bs, clp->bpt, clp->out_flags.defres,
+ clp->elem_sz, mmpp);
if (n <= 0)
return -SG_LIB_FILE_ERROR;
if (mmap_lenp)
@@ -1698,7 +1736,8 @@ main(int argc, char * argv[])
memset(thread_arr, 0, sizeof(thread_arr));
clp->bpt = DEF_BLOCKS_PER_TRANSFER;
clp->in_type = FT_OTHER;
- clp->out_type = FT_OTHER;
+ /* change dd's default: if of=OFILE not given, assume /dev/null */
+ clp->out_type = FT_DEV_NULL;
clp->cdbsz_in = DEF_SCSI_CDBSZ;
clp->cdbsz_out = DEF_SCSI_CDBSZ;
inf[0] = '\0';
@@ -1751,6 +1790,13 @@ main(int argc, char * argv[])
else if (0 == strcmp(key,"dio")) {
clp->in_flags.dio = !! sg_get_num(buf);
clp->out_flags.dio = clp->in_flags.dio;
+ } else if (0 == strcmp(key,"elemsz_kb")) {
+ clp->elem_sz = sg_get_num(buf) * 1024;
+ if ((clp->elem_sz > 0) && (clp->elem_sz < 4096)) {
+ pr2serr("elemsz_kb cannot be less than 4 (4 KB = 4096 "
+ "bytes)\n");
+ return SG_LIB_SYNTAX_ERROR;
+ }
} else if (0 == strcmp(key,"fua")) {
n = sg_get_num(buf);
if (n & 1)
@@ -1987,6 +2033,8 @@ main(int argc, char * argv[])
"device\n", my_name);
}
}
+ if (outf[0])
+ clp->ofile_given = true;
if (outf[0] && ('-' != outf[0])) {
clp->out_type = dd_filetype(outf);
@@ -2203,6 +2251,10 @@ main(int argc, char * argv[])
pr2serr("Due to --dry-run option, bypass copy/read\n");
goto fini;
}
+ if (! clp->ofile_given)
+ pr2serr("of=OFILE not given so only read from IFILE, to output to "
+ "stdout use 'of=-'\n");
+
sigemptyset(&signal_set);
sigaddset(&signal_set, SIGINT);
status = pthread_sigmask(SIG_BLOCK, &signal_set, NULL);