162
168
static const char * proc_allow_dio = "/proc/scsi/sg/allow_dio";
164
void sg_in_operation(Rq_coll * clp, Rq_elem * rep);
165
void sg_out_operation(Rq_coll * clp, Rq_elem * rep);
166
int normal_in_operation(Rq_coll * clp, Rq_elem * rep, int blocks);
167
void normal_out_operation(Rq_coll * clp, Rq_elem * rep, int blocks);
168
int sg_start_io(Rq_elem * rep);
169
int sg_finish_io(int wr, Rq_elem * rep, pthread_mutex_t * a_mutp);
170
static void sg_in_operation(Rq_coll * clp, Rq_elem * rep);
171
static void sg_out_operation(Rq_coll * clp, Rq_elem * rep);
172
static int normal_in_operation(Rq_coll * clp, Rq_elem * rep, int blocks);
173
static void normal_out_operation(Rq_coll * clp, Rq_elem * rep, int blocks);
174
static int sg_start_io(Rq_elem * rep);
175
static int sg_finish_io(int wr, Rq_elem * rep, pthread_mutex_t * a_mutp);
171
177
#define STRERR_BUFF_LEN 128
173
179
static pthread_mutex_t strerr_mut = PTHREAD_MUTEX_INITIALIZER;
181
static int do_time = 0;
182
static Rq_coll rcoll;
183
static struct timeval start_tm;
184
static long long dd_count = -1;
185
static int num_threads = DEF_NUM_THREADS;
186
static int do_sync = 0;
187
static int exit_status = 0;
190
static void calc_duration_throughput(int contin)
192
struct timeval end_tm, res_tm;
195
gettimeofday(&end_tm, NULL);
196
res_tm.tv_sec = end_tm.tv_sec - start_tm.tv_sec;
197
res_tm.tv_usec = end_tm.tv_usec - start_tm.tv_usec;
198
if (res_tm.tv_usec < 0) {
200
res_tm.tv_usec += 1000000;
203
a += (0.000001 * res_tm.tv_usec);
204
b = (double)rcoll.bs * (dd_count - rcoll.out_rem_count);
205
fprintf(stderr, "time to transfer data %s %d.%06d secs",
206
(contin ? "so far" : "was"), (int)res_tm.tv_sec,
207
(int)res_tm.tv_usec);
208
if ((a > 0.00001) && (b > 511))
209
fprintf(stderr, ", %.2f MB/sec\n", b / (a * 1000000.0));
211
fprintf(stderr, "\n");
214
static void print_stats(const char * str)
216
long long infull, outfull;
218
if (0 != rcoll.out_rem_count)
219
fprintf(stderr, " remaining block count=%lld\n",
220
rcoll.out_rem_count);
221
infull = dd_count - rcoll.in_rem_count;
222
fprintf(stderr, "%s%lld+%d records in\n", str, infull - rcoll.in_partial,
225
outfull = dd_count - rcoll.out_rem_count;
226
fprintf(stderr, "%s%lld+%d records out\n", str,
227
outfull - rcoll.out_partial, rcoll.out_partial);
230
static void interrupt_handler(int sig)
232
struct sigaction sigact;
234
sigact.sa_handler = SIG_DFL;
235
sigemptyset(&sigact.sa_mask);
237
sigaction(sig, &sigact, NULL);
238
fprintf(stderr, "Interrupted by signal,");
240
calc_duration_throughput(0);
242
kill(getpid (), sig);
245
static void siginfo_handler(int sig)
247
sig = sig; /* dummy to stop -W warning messages */
248
fprintf(stderr, "Progress report, continuing ...\n");
250
calc_duration_throughput(1);
254
static void install_handler(int sig_num, void (*sig_handler) (int sig))
256
struct sigaction sigact;
257
sigaction (sig_num, NULL, &sigact);
258
if (sigact.sa_handler != SIG_IGN)
260
sigact.sa_handler = sig_handler;
261
sigemptyset (&sigact.sa_mask);
263
sigaction (sig_num, &sigact, NULL);
175
267
/* Make safe_strerror() thread safe */
176
268
static char * tsafe_strerror(int code, char * ebp)
226
fprintf(stderr, "Usage: "
227
"sgp_dd [if=<infile>] [skip=<n>] [of=<ofile>] [seek=<n>]\n"
228
" [bs=<num>] [bpt=<num>] [count=<n>]\n"
229
" [dio=0|1>] [thr=<n>] [coe=0|1] [time=0|1]\n"
230
" [deb=<n>] [cdbsz=6|10|12|16] [--version]\n"
231
" 'bpt' is blocks_per_transfer (default is 128)\n"
232
" 'dio' is direct IO, 1->attempt, 0->indirect IO (def)\n"
233
" 'thr' is number of threads, must be > 0, default 4, max 16\n");
234
fprintf(stderr, " 'coe' continue on error, 0->exit (def), "
318
fprintf(stderr, "Usage: "
319
"sgp_dd [bs=<n>] [count=<n>] [ibs=<n>] [if=<ifile>]"
321
" [obs=<n>] [of=<ofile>] [oflag=<flags>] "
322
"[seek=<n>] [skip=<n>]\n"
323
" [--help] [--version]\n\n");
325
" [bpt=<num>] [cdbsz=6|10|12|16] [coe=0|1] "
326
"[deb=<n>] [dio=0|1]\n"
327
" [fua=0|1|2|3] [sync=0|1] [thr=<n>] "
329
" bpt is blocks_per_transfer (default is 128)\n"
330
" bs must be device block size (default 512)\n"
331
" cdbsz size of SCSI READ or WRITE command (default is 10)\n"
332
" coe continue on error, 0->exit (def), "
235
333
"1->zero + continue\n"
236
" 'time' 0->no timing(def), 1->time plus calculate throughput\n"
237
" 'fua' force unit access: 0->don't(def), 1->of, 2->if, 3->of+if\n"
238
" 'sync' 0->no sync(def), 1->SYNCHRONIZE CACHE on of after xfer\n"
239
" 'cdbsz' size of SCSI READ or WRITE command (default is 10)\n"
240
" 'deb' is debug, 0->none (def), > 0->varying degrees of debug\n");
334
" deb is debug, 0->none (def), > 0->varying degrees of "
337
" dio is direct IO, 1->attempt, 0->indirect IO (def)\n"
338
" fua force unit access: 0->don't(def), 1->of, 2->if, "
340
" iflag comma separated list from: [coe,direct,dpo,dsync,excl,"
342
" oflag comma separated list from: [append,coe,direct,dpo,"
345
" sync 0->no sync(def), 1->SYNCHRONIZE CACHE on of after xfer\n"
346
" thr is number of threads, must be > 0, default 4, max 16\n"
347
" time 0->no timing(def), 1->time plus calculate throughput\n");
243
350
static void guarded_stop_in(Rq_coll * clp)
260
367
guarded_stop_out(clp);
263
/* Return of 0 -> success, -1 -> failure, 2 -> try again */
264
int read_capacity(int sg_fd, long long * num_sect, int * sect_sz)
370
/* Return of 0 -> success, see sg_ll_read_capacity*() otherwise */
371
static int scsi_read_capacity(int sg_fd, long long * num_sect, int * sect_sz)
267
unsigned char rcCmdBlk[10] = {READ_CAPACITY, 0, 0, 0, 0, 0, 0, 0, 0, 0};
268
unsigned char rcBuff[READ_CAP_REPLY_LEN];
269
unsigned char sense_b[64];
270
struct sg_io_hdr io_hdr;
272
memset(&io_hdr, 0, sizeof(struct sg_io_hdr));
273
io_hdr.interface_id = 'S';
274
io_hdr.cmd_len = sizeof(rcCmdBlk);
275
io_hdr.mx_sb_len = sizeof(sense_b);
276
io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
277
io_hdr.dxfer_len = sizeof(rcBuff);
278
io_hdr.dxferp = rcBuff;
279
io_hdr.cmdp = rcCmdBlk;
280
io_hdr.sbp = sense_b;
281
io_hdr.timeout = DEF_TIMEOUT;
283
if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) {
284
perror("read_capacity (SG_IO) error");
287
res = sg_err_category3(&io_hdr);
288
if (SG_ERR_CAT_MEDIA_CHANGED == res)
289
return 2; /* probably have another go ... */
290
else if (SG_ERR_CAT_CLEAN != res) {
291
sg_chk_n_print3("read capacity", &io_hdr);
375
unsigned char rcBuff[RCAP16_REPLY_LEN];
377
res = sg_ll_readcap_10(sg_fd, 0, 0, rcBuff, READ_CAP_REPLY_LEN, 0, 0);
294
381
if ((0xff == rcBuff[0]) && (0xff == rcBuff[1]) && (0xff == rcBuff[2]) &&
295
382
(0xff == rcBuff[3])) {
296
unsigned char rcCmdBlk16[16] = {SERVICE_ACTION_IN,
297
SAI_READ_CAPACITY_16,
298
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
299
unsigned char rcBuff16[RCAP16_REPLY_LEN];
303
memset(&io_hdr, 0, sizeof(struct sg_io_hdr));
304
io_hdr.interface_id = 'S';
305
io_hdr.cmd_len = sizeof(rcCmdBlk16);
306
io_hdr.mx_sb_len = sizeof(sense_b);
307
io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
308
io_hdr.dxfer_len = sizeof(rcBuff16);
309
io_hdr.dxferp = rcBuff16;
310
io_hdr.cmdp = rcCmdBlk16;
311
io_hdr.sbp = sense_b;
312
io_hdr.timeout = DEF_TIMEOUT;
314
if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) {
315
perror("read_capacity_16 (SG_IO) error");
318
res = sg_err_category3(&io_hdr);
319
if (SG_ERR_CAT_CLEAN != res) {
320
sg_chk_n_print3("read capacity_16", &io_hdr);
385
res = sg_ll_readcap_16(sg_fd, 0, 0, rcBuff, RCAP16_REPLY_LEN, 0, 0);
323
388
for (k = 0, ls = 0; k < 8; ++k) {
327
392
*num_sect = ls + 1;
328
*sect_sz = (rcBuff16[8] << 24) | (rcBuff16[9] << 16) |
329
(rcBuff16[10] << 8) | rcBuff16[11];
393
*sect_sz = (rcBuff[8] << 24) | (rcBuff[9] << 16) |
394
(rcBuff[10] << 8) | rcBuff[11];
331
*num_sect = 1 + ((rcBuff[0] << 24) | (rcBuff[1] << 16) |
332
(rcBuff[2] << 8) | rcBuff[3]);
396
ui = ((rcBuff[0] << 24) | (rcBuff[1] << 16) | (rcBuff[2] << 8) |
398
/* take care not to sign extend values > 0x7fffffff */
399
*num_sect = (long long)ui + 1;
333
400
*sect_sz = (rcBuff[4] << 24) | (rcBuff[5] << 16) |
334
401
(rcBuff[6] << 8) | rcBuff[7];
337
fprintf(stderr, "number of sectors=%lld, sector size=%d\n",
338
*num_sect, *sect_sz);
343
/* Return of 0 -> success, -1 -> failure */
344
int read_blkdev_capacity(int sg_fd, long long * num_sect, int * sect_sz)
406
/* Return of 0 -> success, -1 -> failure. BLKGETSIZE64, BLKGETSIZE and */
407
/* BLKSSZGET macros problematic (from <linux/fs.h> or <sys/mount.h>). */
408
static int read_blkdev_capacity(int sg_fd, long long * num_sect, int * sect_sz)
347
unsigned long long ull;
349
if (ioctl(sg_fd, BLKGETSIZE64, &ull) < 0) {
351
perror("BLKGETSIZE64 ioctl error");
354
if (ioctl(sg_fd, BLKSSZGET, sect_sz) < 0) {
411
if ((ioctl(sg_fd, BLKSSZGET, sect_sz) < 0) && (*sect_sz > 0)) {
355
412
perror("BLKSSZGET ioctl error");
416
unsigned long long ull;
418
if (ioctl(sg_fd, BLKGETSIZE64, &ull) < 0) {
420
perror("BLKGETSIZE64 ioctl error");
423
*num_sect = ((long long)ull / (long long)*sect_sz);
427
if (ioctl(sg_fd, BLKGETSIZE, &ul) < 0) {
428
perror("BLKGETSIZE ioctl error");
431
*num_sect = (long long)ul;
358
*num_sect = ((long long)ull / (long long)*sect_sz);
362
if (ioctl(sg_fd, BLKGETSIZE, &ul) < 0) {
363
perror("BLKGETSIZE ioctl error");
366
*num_sect = (long long)ul;
367
if (ioctl(sg_fd, BLKSSZGET, sect_sz) < 0) {
368
perror("BLKSSZGET ioctl error");
375
/* Return of 0 -> success, -1 -> failure, 2 -> try again */
376
int sync_cache(int sg_fd)
379
unsigned char scCmdBlk [10] = {SYNCHRONIZE_CACHE, 0, 0, 0, 0, 0, 0,
381
unsigned char sense_b[64];
382
struct sg_io_hdr io_hdr;
384
memset(&io_hdr, 0, sizeof(struct sg_io_hdr));
385
io_hdr.interface_id = 'S';
386
io_hdr.cmd_len = sizeof(scCmdBlk);
387
io_hdr.mx_sb_len = sizeof(sense_b);
388
io_hdr.dxfer_direction = SG_DXFER_NONE;
389
io_hdr.dxfer_len = 0;
390
io_hdr.dxferp = NULL;
391
io_hdr.cmdp = scCmdBlk;
392
io_hdr.sbp = sense_b;
393
io_hdr.timeout = DEF_TIMEOUT;
395
if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) {
396
perror("synchronize_cache (SG_IO) error");
399
res = sg_err_category3(&io_hdr);
400
if (SG_ERR_CAT_MEDIA_CHANGED == res)
401
return 2; /* probably have another go ... */
402
else if (SG_ERR_CAT_CLEAN != res) {
403
sg_chk_n_print3("synchronize cache", &io_hdr);
409
void * sig_listen_thread(void * v_clp)
442
static void * sig_listen_thread(void * v_clp)
411
444
Rq_coll * clp = (Rq_coll *)v_clp;
762
794
if (0 != status) err_exit(status, "unlock in_mutex");
764
796
res = sg_finish_io(rep->wr, rep, &clp->aux_mutex);
798
case SG_LIB_CAT_UNIT_ATTENTION:
799
/* try again with same addr, count info */
800
/* now re-acquire in mutex for balance */
801
/* N.B. This re-read could now be out of read sequence */
802
status = pthread_mutex_lock(&clp->in_mutex);
803
if (0 != status) err_exit(status, "lock in_mutex");
805
case SG_LIB_CAT_MEDIUM_HARD:
806
if (0 == clp->in_flags.coe) {
807
fprintf(stderr, "error finishing sg in command (medium)\n");
808
if (exit_status <= 0)
810
guarded_stop_both(clp);
767
813
memset(rep->buffp, 0, rep->num_blks * rep->bs);
768
fprintf(stderr, ">> substituted zeros for in blk=%d for "
814
fprintf(stderr, ">> substituted zeros for in blk=%lld for "
769
815
"%d bytes\n", rep->blk, rep->num_blks * rep->bs);
772
fprintf(stderr, "error finishing sg in command\n");
773
guarded_stop_both(clp);
777
if (res <= 0) { /* looks good, going to return */
778
819
if (rep->dio_incomplete || rep->resid) {
779
820
status = pthread_mutex_lock(&clp->aux_mutex);
780
821
if (0 != status) err_exit(status, "lock aux_mutex");
821
863
if (0 != status) err_exit(status, "unlock out_mutex");
823
865
res = sg_finish_io(rep->wr, rep, &clp->aux_mutex);
826
fprintf(stderr, ">> ignored error for out blk=%d for "
827
"%d bytes\n", rep->blk, rep->num_blks * rep->bs);
829
fprintf(stderr, "error finishing sg out command\n");
867
case SG_LIB_CAT_UNIT_ATTENTION:
868
/* try again with same addr, count info */
869
/* now re-acquire out mutex for balance */
870
/* N.B. This re-write could now be out of write sequence */
871
status = pthread_mutex_lock(&clp->out_mutex);
872
if (0 != status) err_exit(status, "lock out_mutex");
874
case SG_LIB_CAT_MEDIUM_HARD:
875
if (0 == clp->out_flags.coe) {
876
fprintf(stderr, "error finishing sg out command (medium)\n");
877
if (exit_status <= 0)
830
879
guarded_stop_both(clp);
882
fprintf(stderr, ">> ignored error for out blk=%lld for "
883
"%d bytes\n", rep->blk, rep->num_blks * rep->bs);
835
886
if (rep->dio_incomplete || rep->resid) {
836
887
status = pthread_mutex_lock(&clp->aux_mutex);
837
888
if (0 != status) err_exit(status, "lock aux_mutex");
843
894
status = pthread_mutex_lock(&clp->out_mutex);
844
895
if (0 != status) err_exit(status, "lock out_mutex");
845
clp->out_done_count -= rep->num_blks;
896
clp->out_rem_count -= rep->num_blks;
846
897
status = pthread_mutex_unlock(&clp->out_mutex);
847
898
if (0 != status) err_exit(status, "unlock out_mutex");
901
fprintf(stderr, "error finishing sg out command (%d)\n", res);
902
if (exit_status <= 0)
904
guarded_stop_both(clp);
850
/* else assume 1 == res so try again with same addr, count info */
851
/* now re-acquire out mutex for balance */
852
/* N.B. This re-write could now be out of write sequence */
853
status = pthread_mutex_lock(&clp->out_mutex);
854
if (0 != status) err_exit(status, "lock out_mutex");
858
int sg_start_io(Rq_elem * rep)
910
static int sg_start_io(Rq_elem * rep)
860
912
struct sg_io_hdr * hp = &rep->io_hdr;
861
int fua = rep->wr ? (rep->fua_mode & 1) : (rep->fua_mode & 2);
913
int fua = rep->wr ? rep->out_flags.fua : rep->in_flags.fua;
914
int dpo = rep->wr ? rep->out_flags.dpo : rep->in_flags.dpo;
862
915
int cdbsz = rep->wr ? rep->cdbsz_out : rep->cdbsz_in;
865
918
if (sg_build_scsi_cdb(rep->cmd, cdbsz, rep->num_blks, rep->blk,
867
fprintf(stderr, ME "bad cdb build, start_blk=%d, blocks=%d\n",
919
rep->wr, fua, dpo)) {
920
fprintf(stderr, ME "bad cdb build, start_blk=%lld, blocks=%d\n",
868
921
rep->blk, rep->num_blks);
930
982
memcpy(&rep->io_hdr, &io_hdr, sizeof(struct sg_io_hdr));
931
983
hp = &rep->io_hdr;
933
switch (sg_err_category3(hp)) {
934
case SG_ERR_CAT_CLEAN:
936
case SG_ERR_CAT_RECOVERED:
937
fprintf(stderr, "Recovered error on block=%d, num=%d\n",
938
rep->blk, rep->num_blks);
940
case SG_ERR_CAT_MEDIA_CHANGED:
985
res = sg_err_category3(hp);
987
case SG_LIB_CAT_CLEAN:
989
case SG_LIB_CAT_RECOVERED:
990
sg_chk_n_print3((rep->wr ? "writing continuing":
991
"reading continuing"), hp, 0);
993
case SG_LIB_CAT_UNIT_ATTENTION:
995
case SG_LIB_CAT_NOT_READY:
944
998
char ebuff[EBUFF_SZ];
946
snprintf(ebuff, EBUFF_SZ,
947
"%s blk=%d", rep->wr ? "writing": "reading", rep->blk);
1000
snprintf(ebuff, EBUFF_SZ, "%s blk=%lld",
1001
rep->wr ? "writing": "reading", rep->blk);
948
1002
status = pthread_mutex_lock(a_mutp);
949
1003
if (0 != status) err_exit(status, "lock aux_mutex");
950
sg_chk_n_print3(ebuff, hp);
1004
sg_chk_n_print3(ebuff, hp, 0);
951
1005
status = pthread_mutex_unlock(a_mutp);
952
1006
if (0 != status) err_exit(status, "unlock aux_mutex");
985
1039
res = ioctl(fd, SG_SET_FORCE_PACK_ID, &t);
987
1041
perror(ME "SG_SET_FORCE_PACK_ID error");
989
struct sg_scsi_id info;
991
res = ioctl(fd, SG_GET_SCSI_ID, &info);
993
perror(ME "SG_SET_SCSI_ID error");
994
*scsi_typep = info.scsi_type;
999
int get_num(char * buf)
1007
if (('0' == buf[0]) && (('x' == buf[1]) || ('X' == buf[1]))) {
1008
res = sscanf(buf + 2, "%x", &unum);
1011
res = sscanf(buf, "%d%c", &num, &c);
1029
return num * 1024 * 1024;
1031
return num * 1000000;
1033
return num * 1024 * 1024 * 1024;
1035
return num * 1000000000;
1037
fprintf(stderr, "unrecognized multiplier\n");
1043
long long get_llnum(char * buf)
1047
unsigned long long unum;
1052
if (('0' == buf[0]) && (('x' == buf[1]) || ('X' == buf[1]))) {
1053
res = sscanf(buf + 2, "%llx", &unum);
1056
res = sscanf(buf, "%lld%c", &num, &c);
1074
return num * 1024 * 1024;
1076
return num * 1000000;
1078
return num * 1024 * 1024 * 1024;
1080
return num * 1000000000;
1082
return num * 1024LL * 1024LL * 1024LL * 1024LL;
1084
return num * 1000000000000LL;
1086
fprintf(stderr, "unrecognized multiplier\n");
1045
static int process_flags(const char * arg, struct flags_t * fp)
1051
strncpy(buff, arg, sizeof(buff));
1052
buff[sizeof(buff) - 1] = '\0';
1053
if ('\0' == buff[0]) {
1054
fprintf(stderr, "no flag found\n");
1059
np = strchr(cp, ',');
1062
if (0 == strcmp(cp, "append"))
1064
else if (0 == strcmp(cp, "coe"))
1066
else if (0 == strcmp(cp, "direct"))
1068
else if (0 == strcmp(cp, "dpo"))
1070
else if (0 == strcmp(cp, "dsync"))
1072
else if (0 == strcmp(cp, "excl"))
1074
else if (0 == strcmp(cp, "fua"))
1077
fprintf(stderr, "unrecognised flag: %s\n", cp);
1092
1086
#define STR_SZ 1024
1093
1087
#define INOUTF_SZ 512
1127
1116
rcoll.cdbsz_out = DEF_SCSI_CDBSZ;
1129
1118
outf[0] = '\0';
1135
for(k = 1; k < argc; k++) {
1120
for (k = 1; k < argc; k++) {
1137
1122
strncpy(str, argv[k], STR_SZ);
1138
1123
str[STR_SZ - 1] = '\0';
1142
for(key = str, buf = key; *buf && *buf != '=';)
1127
for (key = str, buf = key; *buf && *buf != '=';)
1146
if (strcmp(key,"if") == 0) {
1131
if (0 == strcmp(key,"bpt")) {
1132
rcoll.bpt = sg_get_num(buf);
1133
if (-1 == rcoll.bpt) {
1134
fprintf(stderr, ME "bad argument to 'bpt'\n");
1135
return SG_LIB_SYNTAX_ERROR;
1138
} else if (0 == strcmp(key,"bs")) {
1139
rcoll.bs = sg_get_num(buf);
1140
if (-1 == rcoll.bs) {
1141
fprintf(stderr, ME "bad argument to 'bs'\n");
1142
return SG_LIB_SYNTAX_ERROR;
1144
} else if (0 == strcmp(key,"cdbsz")) {
1145
rcoll.cdbsz_in = sg_get_num(buf);
1146
rcoll.cdbsz_out = rcoll.cdbsz_in;
1148
} else if (0 == strcmp(key,"coe")) {
1149
rcoll.in_flags.coe = sg_get_num(buf);
1150
rcoll.out_flags.coe = rcoll.in_flags.coe;
1151
} else if (0 == strcmp(key,"count")) {
1152
dd_count = sg_get_llnum(buf);
1153
if (-1LL == dd_count) {
1154
fprintf(stderr, ME "bad argument to 'count'\n");
1155
return SG_LIB_SYNTAX_ERROR;
1157
} else if (0 == strncmp(key,"deb", 3))
1158
rcoll.debug = sg_get_num(buf);
1159
else if (0 == strcmp(key,"dio"))
1160
rcoll.dio = sg_get_num(buf);
1161
else if (0 == strcmp(key,"fua")) {
1162
n = sg_get_num(buf);
1164
rcoll.out_flags.fua = 1;
1166
rcoll.in_flags.fua = 1;
1167
} else if (0 == strcmp(key,"ibs")) {
1168
ibs = sg_get_num(buf);
1170
fprintf(stderr, ME "bad argument to 'ibs'\n");
1171
return SG_LIB_SYNTAX_ERROR;
1173
} else if (strcmp(key,"if") == 0) {
1147
1174
if ('\0' != inf[0]) {
1148
1175
fprintf(stderr, "Second 'if=' argument??\n");
1176
return SG_LIB_SYNTAX_ERROR;
1151
1178
strncpy(inf, buf, INOUTF_SZ);
1179
} else if (0 == strcmp(key, "iflag")) {
1180
if (process_flags(buf, &rcoll.in_flags)) {
1181
fprintf(stderr, ME "bad argument to 'iflag'\n");
1182
return SG_LIB_SYNTAX_ERROR;
1184
} else if (0 == strcmp(key,"obs")) {
1185
obs = sg_get_num(buf);
1187
fprintf(stderr, ME "bad argument to 'obs'\n");
1188
return SG_LIB_SYNTAX_ERROR;
1152
1190
} else if (strcmp(key,"of") == 0) {
1153
1191
if ('\0' != outf[0]) {
1154
1192
fprintf(stderr, "Second 'of=' argument??\n");
1193
return SG_LIB_SYNTAX_ERROR;
1157
1195
strncpy(outf, buf, INOUTF_SZ);
1158
} else if (0 == strcmp(key,"ibs"))
1160
else if (0 == strcmp(key,"obs"))
1162
else if (0 == strcmp(key,"bs"))
1163
rcoll.bs = get_num(buf);
1164
else if (0 == strcmp(key,"bpt"))
1165
rcoll.bpt = get_num(buf);
1166
else if (0 == strcmp(key,"skip"))
1167
skip = get_llnum(buf);
1168
else if (0 == strcmp(key,"seek"))
1169
seek = get_llnum(buf);
1170
else if (0 == strcmp(key,"count"))
1171
count = get_llnum(buf);
1172
else if (0 == strcmp(key,"dio"))
1173
rcoll.dio = get_num(buf);
1196
} else if (0 == strcmp(key, "oflag")) {
1197
if (process_flags(buf, &rcoll.out_flags)) {
1198
fprintf(stderr, ME "bad argument to 'oflag'\n");
1199
return SG_LIB_SYNTAX_ERROR;
1201
} else if (0 == strcmp(key,"seek")) {
1202
seek = sg_get_llnum(buf);
1204
fprintf(stderr, ME "bad argument to 'seek'\n");
1205
return SG_LIB_SYNTAX_ERROR;
1207
} else if (0 == strcmp(key,"skip")) {
1208
skip = sg_get_llnum(buf);
1210
fprintf(stderr, ME "bad argument to 'skip'\n");
1211
return SG_LIB_SYNTAX_ERROR;
1213
} else if (0 == strcmp(key,"sync"))
1214
do_sync = sg_get_num(buf);
1174
1215
else if (0 == strcmp(key,"thr"))
1175
num_threads = get_num(buf);
1176
else if (0 == strcmp(key,"coe"))
1177
rcoll.coe = get_num(buf);
1216
num_threads = sg_get_num(buf);
1178
1217
else if (0 == strcmp(key,"time"))
1179
do_time = get_num(buf);
1180
else if (0 == strcmp(key,"cdbsz")) {
1181
rcoll.cdbsz_in = get_num(buf);
1182
rcoll.cdbsz_out = rcoll.cdbsz_in;
1183
} else if (0 == strcmp(key,"fua"))
1184
rcoll.fua_mode = get_num(buf);
1185
else if (0 == strcmp(key,"sync"))
1186
do_sync = get_num(buf);
1187
else if (0 == strncmp(key,"deb", 3))
1188
rcoll.debug = get_num(buf);
1189
else if (0 == strncmp(key, "--vers", 6)) {
1190
fprintf(stderr, ME "for sg version 3 driver: %s\n",
1218
do_time = sg_get_num(buf);
1219
else if ((0 == strncmp(key, "--help", 7)) ||
1220
(0 == strcmp(key, "-?"))) {
1223
} else if (0 == strncmp(key, "--vers", 6)) {
1224
fprintf(stderr, ME ": %s\n",
1195
fprintf(stderr, "Unrecognized argument '%s'\n", key);
1229
fprintf(stderr, "Unrecognized option '%s'\n", key);
1230
fprintf(stderr, "For more information use '--help'\n");
1231
return SG_LIB_SYNTAX_ERROR;
1200
1234
if (rcoll.bs <= 0) {
1205
1239
if ((ibs && (ibs != rcoll.bs)) || (obs && (obs != rcoll.bs))) {
1206
1240
fprintf(stderr, "If 'ibs' or 'obs' given must be same as 'bs'\n");
1242
return SG_LIB_SYNTAX_ERROR;
1210
1244
if ((skip < 0) || (seek < 0)) {
1211
1245
fprintf(stderr, "skip and seek cannot be negative\n");
1246
return SG_LIB_SYNTAX_ERROR;
1248
if ((rcoll.out_flags.append > 0) && (seek > 0)) {
1249
fprintf(stderr, "Can't use both append and seek switches\n");
1250
return SG_LIB_SYNTAX_ERROR;
1214
1252
if (rcoll.bpt < 1) {
1215
1253
fprintf(stderr, "bpt must be greater than 0\n");
1254
return SG_LIB_SYNTAX_ERROR;
1256
/* defaulting transfer size to 128*2048 for CD/DVDs is too large
1257
for the block layer in lk 2.6 and results in an EIO on the
1258
SG_IO ioctl. So reduce it in that case. */
1259
if ((rcoll.bs >= 2048) && (0 == bpt_given))
1260
rcoll.bpt = DEF_BLOCKS_PER_2048TRANSFER;
1218
1261
if ((num_threads < 1) || (num_threads > MAX_NUM_THREADS)) {
1219
1262
fprintf(stderr, "too few or too many threads requested\n");
1264
return SG_LIB_SYNTAX_ERROR;
1223
1266
if (rcoll.debug)
1224
1267
fprintf(stderr, ME "if=%s skip=%lld of=%s seek=%lld count=%lld\n",
1225
inf, skip, outf, seek, count);
1268
inf, skip, outf, seek, dd_count);
1270
install_handler(SIGINT, interrupt_handler);
1271
install_handler(SIGQUIT, interrupt_handler);
1272
install_handler(SIGPIPE, interrupt_handler);
1273
install_handler(SIGUSR1, siginfo_handler);
1226
1275
rcoll.infd = STDIN_FILENO;
1227
1276
rcoll.outfd = STDOUT_FILENO;
1228
1277
if (inf[0] && ('-' != inf[0])) {
1229
1278
rcoll.in_type = dd_filetype(inf);
1231
if (FT_ST == rcoll.in_type) {
1280
if (FT_ERROR == rcoll.in_type) {
1281
fprintf(stderr, ME "unable to access %s\n", inf);
1282
return SG_LIB_FILE_ERROR;
1283
} else if (FT_ST == rcoll.in_type) {
1232
1284
fprintf(stderr, ME "unable to use scsi tape device %s\n", inf);
1235
else if (FT_SG == rcoll.in_type) {
1236
if ((rcoll.infd = open(inf, O_RDWR)) < 0) {
1285
return SG_LIB_FILE_ERROR;
1286
} else if (FT_SG == rcoll.in_type) {
1288
if (rcoll.in_flags.direct)
1290
if (rcoll.in_flags.excl)
1292
if (rcoll.in_flags.dsync)
1295
if ((rcoll.infd = open(inf, flags)) < 0) {
1237
1296
snprintf(ebuff, EBUFF_SZ,
1238
1297
ME "could not open %s for sg reading", inf);
1299
return SG_LIB_FILE_ERROR;
1242
if (sg_prepare(rcoll.infd, rcoll.bs, rcoll.bpt,
1243
&rcoll.in_scsi_type))
1301
if (sg_prepare(rcoll.infd, rcoll.bs, rcoll.bpt))
1302
return SG_LIB_FILE_ERROR;
1247
if ((rcoll.infd = open(inf, O_RDONLY)) < 0) {
1306
if (rcoll.in_flags.direct)
1308
if (rcoll.in_flags.excl)
1310
if (rcoll.in_flags.dsync)
1313
if ((rcoll.infd = open(inf, flags)) < 0) {
1248
1314
snprintf(ebuff, EBUFF_SZ,
1249
1315
ME "could not open %s for reading", inf);
1317
return SG_LIB_FILE_ERROR;
1253
1319
else if (skip > 0) {
1254
1320
llse_loff_t offset = skip;
1269
1335
if (FT_ST == rcoll.out_type) {
1270
1336
fprintf(stderr, ME "unable to use scsi tape device %s\n", outf);
1337
return SG_LIB_FILE_ERROR;
1273
1339
else if (FT_SG == rcoll.out_type) {
1274
if ((rcoll.outfd = open(outf, O_RDWR)) < 0) {
1341
if (rcoll.out_flags.direct)
1343
if (rcoll.out_flags.excl)
1345
if (rcoll.out_flags.dsync)
1348
if ((rcoll.outfd = open(outf, flags)) < 0) {
1275
1349
snprintf(ebuff, EBUFF_SZ,
1276
1350
ME "could not open %s for sg writing", outf);
1352
return SG_LIB_FILE_ERROR;
1281
if (sg_prepare(rcoll.outfd, rcoll.bs, rcoll.bpt,
1282
&rcoll.out_scsi_type))
1355
if (sg_prepare(rcoll.outfd, rcoll.bs, rcoll.bpt))
1356
return SG_LIB_FILE_ERROR;
1285
1358
else if (FT_DEV_NULL == rcoll.out_type)
1286
1359
rcoll.outfd = -1; /* don't bother opening */
1288
1361
if (FT_RAW != rcoll.out_type) {
1289
if ((rcoll.outfd = open(outf, O_WRONLY | O_CREAT, 0666)) < 0) {
1362
flags = O_WRONLY | O_CREAT;
1363
if (rcoll.out_flags.direct)
1365
if (rcoll.out_flags.excl)
1367
if (rcoll.out_flags.dsync)
1369
if (rcoll.out_flags.append)
1372
if ((rcoll.outfd = open(outf, flags, 0666)) < 0) {
1290
1373
snprintf(ebuff, EBUFF_SZ,
1291
1374
ME "could not open %s for writing", outf);
1376
return SG_LIB_FILE_ERROR;
1379
else { /* raw output file */
1297
1380
if ((rcoll.outfd = open(outf, O_WRONLY)) < 0) {
1298
1381
snprintf(ebuff, EBUFF_SZ,
1299
1382
ME "could not open %s for raw writing", outf);
1384
return SG_LIB_FILE_ERROR;
1304
1387
if (seek > 0) {
1309
1392
snprintf(ebuff, EBUFF_SZ,
1310
1393
ME "couldn't seek to required position on %s", outf);
1395
return SG_LIB_FILE_ERROR;
1317
1400
if ((STDIN_FILENO == rcoll.infd) && (STDOUT_FILENO == rcoll.outfd)) {
1318
fprintf(stderr, "Disallow both if and of to be stdin and stdout");
1401
fprintf(stderr, "Can't have both 'if' as stdin _and_ 'of' as "
1403
fprintf(stderr, "For more information use '--help'\n");
1404
return SG_LIB_SYNTAX_ERROR;
1322
1407
in_num_sect = -1;
1323
1408
if (FT_SG == rcoll.in_type) {
1324
res = read_capacity(rcoll.infd, &in_num_sect, &in_sect_sz);
1409
res = scsi_read_capacity(rcoll.infd, &in_num_sect, &in_sect_sz);
1325
1410
if (2 == res) {
1326
1411
fprintf(stderr,
1327
1412
"Unit attention, media changed(in), continuing\n");
1328
res = read_capacity(rcoll.infd, &in_num_sect, &in_sect_sz);
1413
res = scsi_read_capacity(rcoll.infd, &in_num_sect,
1330
1416
if (0 != res) {
1331
fprintf(stderr, "Unable to read capacity on %s\n", inf);
1417
if (res == SG_LIB_CAT_INVALID_OP)
1418
fprintf(stderr, "read capacity not supported on %s\n",
1420
else if (res == SG_LIB_CAT_NOT_READY)
1421
fprintf(stderr, "read capacity failed, %s not ready\n",
1424
fprintf(stderr, "Unable to read capacity on %s\n", inf);
1332
1425
in_num_sect = -1;
1334
1427
} else if (FT_BLOCK == rcoll.in_type) {
1377
1478
if (in_num_sect > 0) {
1378
1479
if (out_num_sect > 0)
1379
count = (in_num_sect > out_num_sect) ? out_num_sect :
1480
dd_count = (in_num_sect > out_num_sect) ? out_num_sect :
1382
count = in_num_sect;
1483
dd_count = in_num_sect;
1385
count = out_num_sect;
1486
dd_count = out_num_sect;
1387
1488
if (rcoll.debug > 1)
1388
1489
fprintf(stderr, "Start of loop, count=%lld, in_num_sect=%lld, "
1389
"out_num_sect=%lld\n", count, in_num_sect, out_num_sect);
1490
"out_num_sect=%lld\n", dd_count, in_num_sect, out_num_sect);
1391
1492
fprintf(stderr, "Couldn't calculate count, please give one\n");
1394
if ((FT_SG == rcoll.in_type) && ((count + skip) > UINT_MAX) &&
1395
(MAX_SCSI_CDBSZ != rcoll.cdbsz_in)) {
1396
fprintf(stderr, "Note: SCSI command size increased to 16 bytes "
1398
rcoll.cdbsz_in = MAX_SCSI_CDBSZ;
1400
if ((FT_SG == rcoll.out_type) && ((count + seek) > UINT_MAX) &&
1401
(MAX_SCSI_CDBSZ != rcoll.cdbsz_out)) {
1402
fprintf(stderr, "Note: SCSI command size increased to 16 bytes "
1404
rcoll.cdbsz_out = MAX_SCSI_CDBSZ;
1493
return SG_LIB_CAT_OTHER;
1495
if (! cdbsz_given) {
1496
if ((FT_SG == rcoll.in_type) && (MAX_SCSI_CDBSZ != rcoll.cdbsz_in) &&
1497
(((dd_count + skip) > UINT_MAX) || (rcoll.bpt > USHRT_MAX))) {
1498
fprintf(stderr, "Note: SCSI command size increased to 16 bytes "
1500
rcoll.cdbsz_in = MAX_SCSI_CDBSZ;
1502
if ((FT_SG == rcoll.out_type) && (MAX_SCSI_CDBSZ != rcoll.cdbsz_out) &&
1503
(((dd_count + seek) > UINT_MAX) || (rcoll.bpt > USHRT_MAX))) {
1504
fprintf(stderr, "Note: SCSI command size increased to 16 bytes "
1506
rcoll.cdbsz_out = MAX_SCSI_CDBSZ;
1407
rcoll.in_count = count;
1408
rcoll.in_done_count = count;
1510
rcoll.in_count = dd_count;
1511
rcoll.in_rem_count = dd_count;
1409
1512
rcoll.skip = skip;
1410
1513
rcoll.in_blk = skip;
1411
rcoll.out_count = count;
1412
rcoll.out_done_count = count;
1514
rcoll.out_count = dd_count;
1515
rcoll.out_rem_count = dd_count;
1413
1516
rcoll.seek = seek;
1414
1517
rcoll.out_blk = seek;
1415
1518
status = pthread_mutex_init(&rcoll.in_mutex, NULL);
1475
if ((do_time) && (start_tm.tv_sec || start_tm.tv_usec)) {
1476
struct timeval res_tm;
1578
if ((do_time) && (start_tm.tv_sec || start_tm.tv_usec))
1579
calc_duration_throughput(0);
1479
gettimeofday(&end_tm, NULL);
1480
res_tm.tv_sec = end_tm.tv_sec - start_tm.tv_sec;
1481
res_tm.tv_usec = end_tm.tv_usec - start_tm.tv_usec;
1482
if (res_tm.tv_usec < 0) {
1484
res_tm.tv_usec += 1000000;
1487
a += (0.000001 * res_tm.tv_usec);
1488
b = (double)rcoll.bs * (count - rcoll.out_done_count);
1489
fprintf(stderr, "time to transfer data was %d.%06d secs",
1490
(int)res_tm.tv_sec, (int)res_tm.tv_usec);
1491
if ((a > 0.00001) && (b > 511))
1492
fprintf(stderr, ", %.2f MB/sec\n", b / (a * 1000000.0));
1494
fprintf(stderr, "\n");
1497
1582
if (FT_SG == rcoll.out_type) {
1498
1583
fprintf(stderr, ">> Synchronizing cache on %s\n", outf);
1499
res = sync_cache(rcoll.outfd);
1584
res = sg_ll_sync_cache_10(rcoll.outfd, 0, 0, 0, 0, 0, 0, 0);
1585
if (SG_LIB_CAT_UNIT_ATTENTION == res) {
1501
1586
fprintf(stderr,
1502
"Unit attention, media changed(in), continuing\n");
1503
res = sync_cache(rcoll.outfd);
1587
"Unit attention(out), continuing\n");
1588
res = sg_ll_sync_cache_10(rcoll.outfd, 0, 0, 0, 0, 0, 0, 0);
1506
1591
fprintf(stderr, "Unable to synchronize cache\n");