~ubuntu-branches/ubuntu/intrepid/sg3-utils/intrepid

« back to all changes in this revision

Viewing changes to sgp_dd.c

  • Committer: Bazaar Package Importer
  • Author(s): Luk Claes
  • Date: 2006-11-05 17:23:29 UTC
  • mfrom: (1.1.4 upstream) (3.1.2 edgy)
  • Revision ID: james.westby@ubuntu.com-20061105172329-l4loha00sk36qz6k
* Non-maintainer upload.
* Fix FTBFS due to old syscall usage (Closes: #395512).

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
#include <sys/sysmacros.h>
18
18
#include <sys/time.h>
19
19
#include <linux/major.h>
20
 
#include <linux/fs.h>
21
 
#include "sg_include.h"
22
 
#include "sg_err.h"
 
20
#include <linux/fs.h>   /* <sys/mount.h> */
 
21
#include "sg_lib.h"
 
22
#include "sg_cmds.h"
 
23
#include "sg_io_linux.h"
23
24
#include "llseek.h"
24
25
 
25
26
/* A utility program for copying files. Specialised for "files" that
26
27
*  represent devices that understand the SCSI command set.
27
28
*
28
 
*  Copyright (C) 1999 - 2004 D. Gilbert and P. Allworth
 
29
*  Copyright (C) 1999 - 2006 D. Gilbert and P. Allworth
29
30
*  This program is free software; you can redistribute it and/or modify
30
31
*  it under the terms of the GNU General Public License as published by
31
32
*  the Free Software Foundation; either version 2, or (at your option)
36
37
   device. A block size ('bs') is assumed to be 512 if not given. This
37
38
   program complains if 'ibs' or 'obs' are given with some other value
38
39
   than 'bs'. If 'if' is not given or 'if=-' then stdin is assumed. If
39
 
   'of' is not given or 'of=-' then stdout assumed.  Multipliers:
40
 
      'c','C'  *1       'b','B' *512      'k' *1024      'K' *1000
41
 
      'm' *(1024^2)     'M' *(1000^2)     'g' *(1024^3)  'G' *(1000^3)
42
 
      't' *(1024^4)     'T' *(1000^4)
 
40
   'of' is not given or 'of=-' then stdout assumed.
43
41
   
44
42
   A non-standard argument "bpt" (blocks per transfer) is added to control
45
43
   the maximum number of blocks in each transfer. The default value is 128.
46
 
   For example if "bs=512" and "bpt=32" then a maximum of 32 blocks (16KB
 
44
   For example if "bs=512" and "bpt=32" then a maximum of 32 blocks (16 KiB
47
45
   in this case) are transferred to or from the sg device in a single SCSI
48
46
   command.
49
47
 
51
49
 
52
50
*/
53
51
 
54
 
static char * version_str = "5.18 20040810";
 
52
static char * version_str = "5.31 20060704";
55
53
 
56
54
#define DEF_BLOCK_SIZE 512
57
55
#define DEF_BLOCKS_PER_TRANSFER 128
 
56
#define DEF_BLOCKS_PER_2048TRANSFER 32
58
57
#define DEF_SCSI_CDBSZ 10
59
58
#define MAX_SCSI_CDBSZ 16
60
59
 
64
63
 
65
64
#define SENSE_BUFF_LEN 32       /* Arbitrary, could be larger */
66
65
#define READ_CAP_REPLY_LEN 8
67
 
#define RCAP16_REPLY_LEN 12
 
66
#define RCAP16_REPLY_LEN 32
68
67
 
69
68
#ifndef SERVICE_ACTION_IN
70
69
#define SERVICE_ACTION_IN     0x9e
90
89
#define FT_DEV_NULL 8           /* either "/dev/null" or "." as filename */
91
90
#define FT_ST 16                /* filetype is st char device (tape) */
92
91
#define FT_BLOCK 32             /* filetype is a block device */
 
92
#define FT_ERROR 64             /* couldn't "stat" file */
93
93
 
94
94
#define DEV_NULL_MINOR_NUM 3
95
95
 
96
96
#define EBUFF_SZ 512
97
97
 
 
98
struct flags_t {
 
99
    int append;
 
100
    int coe;
 
101
    int direct;
 
102
    int dpo;
 
103
    int dsync;
 
104
    int excl;
 
105
    int fua;
 
106
};
98
107
 
99
108
typedef struct request_collection
100
109
{       /* one instance visible to all threads */
101
110
    int infd;
102
111
    long long skip;
103
112
    int in_type;
104
 
    int in_scsi_type;
105
113
    int cdbsz_in;
 
114
    struct flags_t in_flags;
106
115
    long long in_blk;                 /* -\ next block address to read */
107
116
    long long in_count;               /*  | blocks remaining for next read */
108
 
    long long in_done_count;          /*  | count of completed in blocks */
 
117
    long long in_rem_count;           /*  | count of remaining in blocks */
109
118
    int in_partial;                   /*  | */
110
119
    int in_stop;                      /*  | */
111
120
    pthread_mutex_t in_mutex;         /* -/ */
112
121
    int outfd;
113
122
    long long seek;
114
123
    int out_type;
115
 
    int out_scsi_type;
116
124
    int cdbsz_out;
 
125
    struct flags_t out_flags;
117
126
    long long out_blk;                /* -\ next block address to write */
118
127
    long long out_count;              /*  | blocks remaining for next write */
119
 
    long long out_done_count;         /*  | count of completed out blocks */
 
128
    long long out_rem_count;          /*  | count of remaining out blocks */
120
129
    int out_partial;                  /*  | */
121
130
    int out_stop;                     /*  | */
122
131
    pthread_mutex_t out_mutex;        /*  | */
123
132
    pthread_cond_t out_sync_cv;       /* -/ hold writes until "in order" */
124
133
    int bs;
125
134
    int bpt;
126
 
    int fua_mode;
127
135
    int dio;
128
136
    int dio_incomplete;         /* -\ */
129
137
    int sum_of_resids;          /*  | */
130
138
    pthread_mutex_t aux_mutex;  /* -/ (also serializes some printf()s */
131
 
    int coe;
132
139
    int debug;
133
140
} Rq_coll;
134
141
 
137
144
    int infd;
138
145
    int outfd;
139
146
    int wr;
140
 
    int blk;
 
147
    long long blk;
141
148
    int num_blks;
142
149
    unsigned char * buffp;
143
150
    unsigned char * alloc_bp;
145
152
    unsigned char cmd[MAX_SCSI_CDBSZ];
146
153
    unsigned char sb[SENSE_BUFF_LEN];
147
154
    int bs;
148
 
    int fua_mode;
149
155
    int dio;
150
156
    int dio_incomplete;
151
157
    int resid;
152
 
    int in_scsi_type;
153
 
    int out_scsi_type;
154
158
    int cdbsz_in;
155
159
    int cdbsz_out;
 
160
    struct flags_t in_flags;
 
161
    struct flags_t out_flags;
156
162
    int debug;
157
163
} Rq_elem;
158
164
 
161
167
 
162
168
static const char * proc_allow_dio = "/proc/scsi/sg/allow_dio";
163
169
 
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);
170
176
 
171
177
#define STRERR_BUFF_LEN 128
172
178
 
173
179
static pthread_mutex_t strerr_mut = PTHREAD_MUTEX_INITIALIZER;
174
180
 
 
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;
 
188
 
 
189
 
 
190
static void calc_duration_throughput(int contin)
 
191
{
 
192
    struct timeval end_tm, res_tm;
 
193
    double a, b;
 
194
 
 
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) {
 
199
        --res_tm.tv_sec;
 
200
        res_tm.tv_usec += 1000000;
 
201
    }
 
202
    a = res_tm.tv_sec;
 
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));
 
210
    else
 
211
        fprintf(stderr, "\n");
 
212
}
 
213
 
 
214
static void print_stats(const char * str)
 
215
{
 
216
    long long infull, outfull;
 
217
 
 
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,
 
223
            rcoll.in_partial);
 
224
 
 
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);
 
228
}
 
229
 
 
230
static void interrupt_handler(int sig)
 
231
{
 
232
    struct sigaction sigact;
 
233
 
 
234
    sigact.sa_handler = SIG_DFL;
 
235
    sigemptyset(&sigact.sa_mask);
 
236
    sigact.sa_flags = 0;
 
237
    sigaction(sig, &sigact, NULL);
 
238
    fprintf(stderr, "Interrupted by signal,");
 
239
    if (do_time)
 
240
        calc_duration_throughput(0);
 
241
    print_stats("");
 
242
    kill(getpid (), sig);
 
243
}
 
244
 
 
245
static void siginfo_handler(int sig)
 
246
{
 
247
    sig = sig;  /* dummy to stop -W warning messages */
 
248
    fprintf(stderr, "Progress report, continuing ...\n");
 
249
    if (do_time)
 
250
        calc_duration_throughput(1);
 
251
    print_stats("  ");
 
252
}
 
253
 
 
254
static void install_handler(int sig_num, void (*sig_handler) (int sig))
 
255
{
 
256
    struct sigaction sigact;
 
257
    sigaction (sig_num, NULL, &sigact);
 
258
    if (sigact.sa_handler != SIG_IGN)
 
259
    {
 
260
        sigact.sa_handler = sig_handler;
 
261
        sigemptyset (&sigact.sa_mask);
 
262
        sigact.sa_flags = 0;
 
263
        sigaction (sig_num, &sigact, NULL);
 
264
    }
 
265
}
 
266
 
175
267
/* Make safe_strerror() thread safe */
176
268
static char * tsafe_strerror(int code, char * ebp)
177
269
{
197
289
    } while (0)
198
290
 
199
291
 
200
 
int dd_filetype(const char * filename)
 
292
static int dd_filetype(const char * filename)
201
293
{
202
294
    struct stat st;
203
295
    size_t len = strlen(filename);
205
297
    if ((1 == len) && ('.' == filename[0]))
206
298
        return FT_DEV_NULL;
207
299
    if (stat(filename, &st) < 0)
208
 
        return FT_OTHER;
 
300
        return FT_ERROR;
209
301
    if (S_ISCHR(st.st_mode)) {
210
302
        if ((MEM_MAJOR == major(st.st_rdev)) &&
211
303
            (DEV_NULL_MINOR_NUM == minor(st.st_rdev)))
221
313
    return FT_OTHER;
222
314
}
223
315
 
224
 
void usage()
 
316
static void usage()
225
317
{
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>]"
 
320
           " [iflag=<flags>]\n"
 
321
           "               [obs=<n>] [of=<ofile>] [oflag=<flags>] "
 
322
           "[seek=<n>] [skip=<n>]\n"
 
323
           "               [--help] [--version]\n\n");
 
324
    fprintf(stderr,
 
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>] "
 
328
           "[time=0|1]\n\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 "
 
335
           "debug\n");
 
336
    fprintf(stderr,
 
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, "
 
339
           "3->of+if\n"
 
340
           "  iflag  comma separated list from: [coe,direct,dpo,dsync,excl,"
 
341
           "fua]\n"
 
342
           "  oflag  comma separated list from: [append,coe,direct,dpo,"
 
343
           "dsync,excl,\n"
 
344
           "          fua]\n"
 
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");
241
348
}
242
349
 
243
350
static void guarded_stop_in(Rq_coll * clp)
260
367
    guarded_stop_out(clp);
261
368
}
262
369
 
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)
265
372
{
266
 
    int res;
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;
271
 
 
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;
282
 
 
283
 
    if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) {
284
 
        perror("read_capacity (SG_IO) error");
285
 
        return -1;
286
 
    }
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);
292
 
        return -1;
293
 
    }
 
373
    int k, res;
 
374
    unsigned int ui;
 
375
    unsigned char rcBuff[RCAP16_REPLY_LEN];
 
376
 
 
377
    res = sg_ll_readcap_10(sg_fd, 0, 0, rcBuff, READ_CAP_REPLY_LEN, 0, 0);
 
378
    if (0 != res)
 
379
        return res;
 
380
 
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];
300
 
        int k;
301
383
        long long ls;
302
384
 
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;
313
 
 
314
 
        if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) {
315
 
            perror("read_capacity_16 (SG_IO) error");
316
 
            return -1;
317
 
        }
318
 
        res = sg_err_category3(&io_hdr);
319
 
        if (SG_ERR_CAT_CLEAN != res) {
320
 
            sg_chk_n_print3("read capacity_16", &io_hdr);
321
 
            return -1;
322
 
        }
 
385
        res = sg_ll_readcap_16(sg_fd, 0, 0, rcBuff, RCAP16_REPLY_LEN, 0, 0);
 
386
        if (0 != res)
 
387
            return res;
323
388
        for (k = 0, ls = 0; k < 8; ++k) {
324
389
            ls <<= 8;
325
 
            ls |= rcBuff16[k];
 
390
            ls |= rcBuff[k];
326
391
        }
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];
330
395
    } else {
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) |
 
397
              rcBuff[3]);
 
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];
335
402
    }
336
 
#ifdef SG_DEBUG
337
 
    fprintf(stderr, "number of sectors=%lld, sector size=%d\n",
338
 
            *num_sect, *sect_sz);
339
 
#endif
340
403
    return 0;
341
404
}
342
405
 
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)
345
409
{
346
 
#ifdef BLKGETSIZE64
347
 
    unsigned long long ull;
348
 
 
349
 
    if (ioctl(sg_fd, BLKGETSIZE64, &ull) < 0) {
350
 
 
351
 
        perror("BLKGETSIZE64 ioctl error");
352
 
        return -1;
353
 
    }
354
 
    if (ioctl(sg_fd, BLKSSZGET, sect_sz) < 0) {
 
410
#ifdef BLKSSZGET
 
411
    if ((ioctl(sg_fd, BLKSSZGET, sect_sz) < 0) && (*sect_sz > 0)) {
355
412
        perror("BLKSSZGET ioctl error");
356
413
        return -1;
 
414
    } else {
 
415
 #ifdef BLKGETSIZE64
 
416
        unsigned long long ull;
 
417
 
 
418
        if (ioctl(sg_fd, BLKGETSIZE64, &ull) < 0) {
 
419
 
 
420
            perror("BLKGETSIZE64 ioctl error");
 
421
            return -1;
 
422
        }
 
423
        *num_sect = ((long long)ull / (long long)*sect_sz);
 
424
 #else
 
425
        unsigned long ul;
 
426
 
 
427
        if (ioctl(sg_fd, BLKGETSIZE, &ul) < 0) {
 
428
            perror("BLKGETSIZE ioctl error");
 
429
            return -1;
 
430
        }
 
431
        *num_sect = (long long)ul;
 
432
 #endif
357
433
    }
358
 
    *num_sect = ((long long)ull / (long long)*sect_sz);
 
434
    return 0;
359
435
#else
360
 
    unsigned long ul;
361
 
 
362
 
    if (ioctl(sg_fd, BLKGETSIZE, &ul) < 0) {
363
 
        perror("BLKGETSIZE ioctl error");
364
 
        return -1;
365
 
    }
366
 
    *num_sect = (long long)ul;
367
 
    if (ioctl(sg_fd, BLKSSZGET, sect_sz) < 0) {
368
 
        perror("BLKSSZGET ioctl error");
369
 
        return -1;
370
 
    }
 
436
    *num_sect = 0;
 
437
    *sect_sz = 0;
 
438
    return -1;
371
439
#endif
372
 
    return 0;
373
 
}
374
 
 
375
 
/* Return of 0 -> success, -1 -> failure, 2 -> try again */
376
 
int sync_cache(int sg_fd)
377
 
{
378
 
    int res;
379
 
    unsigned char scCmdBlk [10] = {SYNCHRONIZE_CACHE, 0, 0, 0, 0, 0, 0, 
380
 
                                   0, 0, 0};
381
 
    unsigned char sense_b[64];
382
 
    struct sg_io_hdr io_hdr;
383
 
 
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;
394
 
 
395
 
    if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) {
396
 
        perror("synchronize_cache (SG_IO) error");
397
 
        return -1;
398
 
    }
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);
404
 
        return -1;
405
 
    }
406
 
    return 0;
407
 
}
408
 
 
409
 
void * sig_listen_thread(void * v_clp)
 
440
}
 
441
 
 
442
static void * sig_listen_thread(void * v_clp)
410
443
{
411
444
    Rq_coll * clp = (Rq_coll *)v_clp;
412
445
    int sig_number;
422
455
    return NULL;
423
456
}
424
457
 
425
 
void cleanup_in(void * v_clp)
 
458
static void cleanup_in(void * v_clp)
426
459
{
427
460
    Rq_coll * clp = (Rq_coll *)v_clp;
428
461
 
433
466
    pthread_cond_broadcast(&clp->out_sync_cv);
434
467
}
435
468
 
436
 
void cleanup_out(void * v_clp)
 
469
static void cleanup_out(void * v_clp)
437
470
{
438
471
    Rq_coll * clp = (Rq_coll *)v_clp;
439
472
 
444
477
    pthread_cond_broadcast(&clp->out_sync_cv);
445
478
}
446
479
 
447
 
void * read_write_thread(void * v_clp)
 
480
static void * read_write_thread(void * v_clp)
448
481
{
449
482
    Rq_coll * clp = (Rq_coll *)v_clp;
450
483
    Rq_elem rel;
452
485
    size_t psz = 0;
453
486
    int sz = clp->bpt * clp->bs;
454
487
    int stop_after_write = 0;
455
 
    int seek_skip =  clp->seek - clp->skip;
 
488
    long long seek_skip =  clp->seek - clp->skip;
456
489
    int blocks, status;
457
490
 
458
491
    memset(rep, 0, sizeof(Rq_elem));
463
496
                                   (~(psz - 1)));
464
497
    /* Follow clp members are constant during lifetime of thread */
465
498
    rep->bs = clp->bs;
466
 
    rep->fua_mode = clp->fua_mode;
467
499
    rep->dio = clp->dio;
468
500
    rep->infd = clp->infd;
469
501
    rep->outfd = clp->outfd;
470
502
    rep->debug = clp->debug;
471
 
    rep->in_scsi_type = clp->in_scsi_type;
472
 
    rep->out_scsi_type = clp->out_scsi_type;
473
503
    rep->cdbsz_in = clp->cdbsz_in;
474
504
    rep->cdbsz_out = clp->cdbsz_out;
 
505
    rep->in_flags = clp->in_flags;
 
506
    rep->out_flags = clp->out_flags;
475
507
 
476
508
    while(1) {
477
509
        status = pthread_mutex_lock(&clp->in_mutex);
539
571
            sg_out_operation(clp, rep); /* releases out_mutex mid operation */
540
572
        else if (FT_DEV_NULL == clp->out_type) {
541
573
            /* skip actual write operation */
542
 
            clp->out_done_count -= blocks;
 
574
            clp->out_rem_count -= blocks;
543
575
            status = pthread_mutex_unlock(&clp->out_mutex);
544
576
            if (0 != status) err_exit(status, "unlock out_mutex");
545
577
        }
565
597
    return stop_after_write ? NULL : v_clp;
566
598
}
567
599
 
568
 
int normal_in_operation(Rq_coll * clp, Rq_elem * rep, int blocks)
 
600
static int normal_in_operation(Rq_coll * clp, Rq_elem * rep, int blocks)
569
601
{
570
602
    int res;
571
603
    int stop_after_write = 0;
576
608
                        blocks * clp->bs)) < 0) && (EINTR == errno))
577
609
        ;
578
610
    if (res < 0) {
579
 
        if (clp->coe) {
 
611
        if (clp->in_flags.coe) {
580
612
            memset(rep->buffp, 0, rep->num_blks * rep->bs);
581
 
            fprintf(stderr, ">> substituted zeros for in blk=%d for "
 
613
            fprintf(stderr, ">> substituted zeros for in blk=%lld for "
582
614
                    "%d bytes, %s\n", rep->blk, 
583
615
                    rep->num_blks * rep->bs, 
584
616
                    tsafe_strerror(errno, strerr_buff));
607
639
        clp->in_blk += blocks;
608
640
        clp->in_count -= blocks;
609
641
    }
610
 
    clp->in_done_count -= blocks;
 
642
    clp->in_rem_count -= blocks;
611
643
    return stop_after_write;
612
644
}
613
645
 
614
 
void normal_out_operation(Rq_coll * clp, Rq_elem * rep, int blocks)
 
646
static void normal_out_operation(Rq_coll * clp, Rq_elem * rep, int blocks)
615
647
{
616
648
    int res;
617
649
    char strerr_buff[STRERR_BUFF_LEN];
621
653
                 rep->num_blks * clp->bs)) < 0) && (EINTR == errno))
622
654
        ;
623
655
    if (res < 0) {
624
 
        if (clp->coe) {
625
 
            fprintf(stderr, ">> ignored error for out blk=%d for "
 
656
        if (clp->out_flags.coe) {
 
657
            fprintf(stderr, ">> ignored error for out blk=%lld for "
626
658
                    "%d bytes, %s\n", rep->blk, 
627
659
                    rep->num_blks * rep->bs,
628
660
                    tsafe_strerror(errno, strerr_buff));
644
676
        }
645
677
        rep->num_blks = blocks;
646
678
    }
647
 
    clp->out_done_count -= blocks;
 
679
    clp->out_rem_count -= blocks;
648
680
}
649
681
 
650
 
int sg_build_scsi_cdb(unsigned char * cdbp, int cdb_sz, unsigned int blocks,
651
 
                      long long start_block, int write_true, int fua,
652
 
                      int dpo)
 
682
static int sg_build_scsi_cdb(unsigned char * cdbp, int cdb_sz,
 
683
                             unsigned int blocks, long long start_block,
 
684
                             int write_true, int fua, int dpo)
653
685
{
654
686
    int rd_opcode[] = {0x8, 0x28, 0xa8, 0x88};
655
687
    int wr_opcode[] = {0xa, 0x2a, 0xaa, 0x8a};
733
765
        break;
734
766
    default:
735
767
        fprintf(stderr, ME "expected cdb size of 6, 10, 12, or 16 but got"
736
 
                        "=%d\n", cdb_sz);
 
768
                        " %d\n", cdb_sz);
737
769
        return 1;
738
770
    }
739
771
    return 0;
740
772
}
741
773
 
742
 
void sg_in_operation(Rq_coll * clp, Rq_elem * rep)
 
774
static void sg_in_operation(Rq_coll * clp, Rq_elem * rep)
743
775
{
744
776
    int res;
745
777
    int status;
750
782
        if (1 == res)
751
783
            err_exit(ENOMEM, "sg starting in command");
752
784
        else if (res < 0) {
753
 
            fprintf(stderr, ME "inputting to sg failed, blk=%d\n",
 
785
            fprintf(stderr, ME "inputting to sg failed, blk=%lld\n",
754
786
                    rep->blk);
755
787
            status = pthread_mutex_unlock(&clp->in_mutex);
756
788
            if (0 != status) err_exit(status, "unlock in_mutex");
762
794
        if (0 != status) err_exit(status, "unlock in_mutex");
763
795
 
764
796
        res = sg_finish_io(rep->wr, rep, &clp->aux_mutex);
765
 
        if (res < 0) {
766
 
            if (clp->coe) {
 
797
        switch (res) {
 
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");
 
804
            break;
 
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)
 
809
                    exit_status = res;
 
810
                guarded_stop_both(clp);
 
811
                return;
 
812
            } else {
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);
770
816
            }
771
 
            else {
772
 
                fprintf(stderr, "error finishing sg in command\n");
773
 
                guarded_stop_both(clp);
774
 
                return;
775
 
            }
776
 
        }
777
 
        if (res <= 0) { /* looks good, going to return */
 
817
            /* fall through */
 
818
        case 0:
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");
785
826
            }
786
827
            status = pthread_mutex_lock(&clp->in_mutex);
787
828
            if (0 != status) err_exit(status, "lock in_mutex");
788
 
            clp->in_done_count -= rep->num_blks;
 
829
            clp->in_rem_count -= rep->num_blks;
789
830
            status = pthread_mutex_unlock(&clp->in_mutex);
790
831
            if (0 != status) err_exit(status, "unlock in_mutex");
791
832
            return;
 
833
        default:
 
834
            fprintf(stderr, "error finishing sg in command (%d)\n", res);
 
835
            if (exit_status <= 0)
 
836
                exit_status = res;
 
837
            guarded_stop_both(clp);
 
838
            return;
792
839
        }
793
 
        /* else assume 1 == res so try again with same addr, count info */
794
 
        /* now re-acquire read mutex for balance */
795
 
        /* N.B. This re-read could now be out of read sequence */
796
 
        status = pthread_mutex_lock(&clp->in_mutex);
797
 
        if (0 != status) err_exit(status, "lock in_mutex");
798
840
    }
799
841
}
800
842
 
801
 
void sg_out_operation(Rq_coll * clp, Rq_elem * rep)
 
843
static void sg_out_operation(Rq_coll * clp, Rq_elem * rep)
802
844
{
803
845
    int res;
804
846
    int status;
809
851
        if (1 == res)
810
852
            err_exit(ENOMEM, "sg starting out command");
811
853
        else if (res < 0) {
812
 
            fprintf(stderr, ME "outputting from sg failed, blk=%d\n",
 
854
            fprintf(stderr, ME "outputting from sg failed, blk=%lld\n",
813
855
                    rep->blk);
814
856
            status = pthread_mutex_unlock(&clp->out_mutex);
815
857
            if (0 != status) err_exit(status, "unlock out_mutex");
821
863
        if (0 != status) err_exit(status, "unlock out_mutex");
822
864
 
823
865
        res = sg_finish_io(rep->wr, rep, &clp->aux_mutex);
824
 
        if (res < 0) {
825
 
            if (clp->coe)
826
 
                fprintf(stderr, ">> ignored error for out blk=%d for "
827
 
                        "%d bytes\n", rep->blk, rep->num_blks * rep->bs);
828
 
            else {
829
 
                fprintf(stderr, "error finishing sg out command\n");
 
866
        switch (res) {
 
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");
 
873
            break;
 
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)
 
878
                    exit_status = res;
830
879
                guarded_stop_both(clp);
831
880
                return;
832
 
            }
833
 
        }
834
 
        if (res <= 0) {
 
881
            } else
 
882
                fprintf(stderr, ">> ignored error for out blk=%lld for "
 
883
                        "%d bytes\n", rep->blk, rep->num_blks * rep->bs);
 
884
            /* fall through */
 
885
        case 0:
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");
842
893
            }
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");
848
899
            return;
 
900
        default:
 
901
            fprintf(stderr, "error finishing sg out command (%d)\n", res);
 
902
            if (exit_status <= 0)
 
903
                exit_status = res;
 
904
            guarded_stop_both(clp);
 
905
            return;
849
906
        }
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");
855
907
    }
856
908
}
857
909
 
858
 
int sg_start_io(Rq_elem * rep)
 
910
static int sg_start_io(Rq_elem * rep)
859
911
{
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;
863
916
    int res;
864
917
 
865
918
    if (sg_build_scsi_cdb(rep->cmd, cdbsz, rep->num_blks, rep->blk, 
866
 
                          rep->wr, fua, 0)) {
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);
869
922
        return -1;
870
923
    }
883
936
    if (rep->dio)
884
937
        hp->flags |= SG_FLAG_DIRECT_IO;
885
938
    if (rep->debug > 8) {
886
 
        fprintf(stderr, "sg_start_io: SCSI %s, blk=%d num_blks=%d\n",
 
939
        fprintf(stderr, "sg_start_io: SCSI %s, blk=%lld num_blks=%d\n",
887
940
               rep->wr ? "WRITE" : "READ", rep->blk, rep->num_blks);
888
941
        sg_print_command(hp->cmdp);
889
 
        fprintf(stderr, "dir=%d, len=%d, dxfrp=%p, cmd_len=%d\n",
890
 
                hp->dxfer_direction, hp->dxfer_len, hp->dxferp, hp->cmd_len);
891
942
    }
892
943
 
893
944
    while (((res = write(rep->wr ? rep->outfd : rep->infd, hp,
902
953
    return 0;
903
954
}
904
955
 
905
 
/* -1 -> unrecoverable error, 0 -> successful, 1 -> try again */
906
 
int sg_finish_io(int wr, Rq_elem * rep, pthread_mutex_t * a_mutp)
 
956
/* 0 -> successful, SG_LIB_CAT_UNIT_ATTENTION -> try again,
 
957
   SG_LIB_CAT_NOT_READY, SG_LIB_CAT_MEDIUM_HARD, -1 other errors */
 
958
static int sg_finish_io(int wr, Rq_elem * rep, pthread_mutex_t * a_mutp)
907
959
{
908
960
    int res, status;
909
961
    struct sg_io_hdr io_hdr;
930
982
    memcpy(&rep->io_hdr, &io_hdr, sizeof(struct sg_io_hdr));
931
983
    hp = &rep->io_hdr;
932
984
 
933
 
    switch (sg_err_category3(hp)) {
934
 
        case SG_ERR_CAT_CLEAN:
935
 
            break;
936
 
        case SG_ERR_CAT_RECOVERED:
937
 
            fprintf(stderr, "Recovered error on block=%d, num=%d\n",
938
 
                    rep->blk, rep->num_blks);
939
 
            break;
940
 
        case SG_ERR_CAT_MEDIA_CHANGED:
941
 
            return 1;
 
985
    res = sg_err_category3(hp);
 
986
    switch (res) {
 
987
        case SG_LIB_CAT_CLEAN:
 
988
            break;
 
989
        case SG_LIB_CAT_RECOVERED:
 
990
            sg_chk_n_print3((rep->wr ? "writing continuing":
 
991
                                       "reading continuing"), hp, 0);
 
992
            break;
 
993
        case SG_LIB_CAT_UNIT_ATTENTION:
 
994
            return res;
 
995
        case SG_LIB_CAT_NOT_READY:
942
996
        default:
943
997
            {
944
998
                char ebuff[EBUFF_SZ];
945
999
 
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");
953
 
                return -1;
 
1007
                return res;
954
1008
            }
955
1009
    }
956
1010
#if 0
967
1021
    return 0;
968
1022
}
969
1023
 
970
 
int sg_prepare(int fd, int bs, int bpt, int * scsi_typep)
 
1024
static int sg_prepare(int fd, int bs, int bpt)
971
1025
{
972
1026
    int res, t;
973
1027
 
985
1039
    res = ioctl(fd, SG_SET_FORCE_PACK_ID, &t);
986
1040
    if (res < 0)
987
1041
        perror(ME "SG_SET_FORCE_PACK_ID error");
988
 
    if (scsi_typep) {
989
 
        struct sg_scsi_id info;
990
 
 
991
 
        res = ioctl(fd, SG_GET_SCSI_ID, &info);
992
 
        if (res < 0)
993
 
            perror(ME "SG_SET_SCSI_ID error");
994
 
        *scsi_typep = info.scsi_type;
995
 
    }
996
 
    return 0;
997
 
}
998
 
 
999
 
int get_num(char * buf)
1000
 
{
1001
 
    int res, num;
1002
 
    unsigned int unum;
1003
 
    char c = 'c';
1004
 
 
1005
 
    if ('\0' == buf[0])
1006
 
        return -1;
1007
 
    if (('0' == buf[0]) && (('x' == buf[1]) || ('X' == buf[1]))) {
1008
 
        res = sscanf(buf + 2, "%x", &unum);
1009
 
        num = unum;
1010
 
    } else
1011
 
        res = sscanf(buf, "%d%c", &num, &c);
1012
 
    if (1 == res)
1013
 
        return num;
1014
 
    else if (2 != res)
1015
 
        return -1;
1016
 
    else {
1017
 
        switch (c) {
1018
 
        case 'c':
1019
 
        case 'C':
1020
 
            return num;
1021
 
        case 'b':
1022
 
        case 'B':
1023
 
            return num * 512;
1024
 
        case 'k':
1025
 
            return num * 1024;
1026
 
        case 'K':
1027
 
            return num * 1000;
1028
 
        case 'm':
1029
 
            return num * 1024 * 1024;
1030
 
        case 'M':
1031
 
            return num * 1000000;
1032
 
        case 'g':
1033
 
            return num * 1024 * 1024 * 1024;
1034
 
        case 'G':
1035
 
            return num * 1000000000;
1036
 
        default:
1037
 
            fprintf(stderr, "unrecognized multiplier\n");
1038
 
            return -1;
1039
 
        }
1040
 
    }
1041
 
}
1042
 
 
1043
 
long long get_llnum(char * buf)
1044
 
{
1045
 
    int res;
1046
 
    long long num;
1047
 
    unsigned long long unum;
1048
 
    char c = 'c';
1049
 
 
1050
 
    if ('\0' == buf[0])
1051
 
        return -1;
1052
 
    if (('0' == buf[0]) && (('x' == buf[1]) || ('X' == buf[1]))) {
1053
 
        res = sscanf(buf + 2, "%llx", &unum);
1054
 
        num = unum;
1055
 
    } else
1056
 
        res = sscanf(buf, "%lld%c", &num, &c);
1057
 
    if (1 == res)
1058
 
        return num;
1059
 
    else if (2 != res)
1060
 
        return -1LL;
1061
 
    else {
1062
 
        switch (c) {
1063
 
        case 'c':
1064
 
        case 'C':
1065
 
            return num;
1066
 
        case 'b':
1067
 
        case 'B':
1068
 
            return num * 512;
1069
 
        case 'k':
1070
 
            return num * 1024;
1071
 
        case 'K':
1072
 
            return num * 1000;
1073
 
        case 'm':
1074
 
            return num * 1024 * 1024;
1075
 
        case 'M':
1076
 
            return num * 1000000;
1077
 
        case 'g':
1078
 
            return num * 1024 * 1024 * 1024;
1079
 
        case 'G':
1080
 
            return num * 1000000000;
1081
 
        case 't':
1082
 
            return num * 1024LL * 1024LL * 1024LL * 1024LL;
1083
 
        case 'T':
1084
 
            return num * 1000000000000LL;
1085
 
        default:
1086
 
            fprintf(stderr, "unrecognized multiplier\n");
1087
 
            return -1LL;
1088
 
        }
1089
 
    }
1090
 
}
 
1042
    return 0;
 
1043
}
 
1044
 
 
1045
static int process_flags(const char * arg, struct flags_t * fp)
 
1046
{
 
1047
    char buff[256];
 
1048
    char * cp;
 
1049
    char * np;
 
1050
 
 
1051
    strncpy(buff, arg, sizeof(buff));
 
1052
    buff[sizeof(buff) - 1] = '\0';
 
1053
    if ('\0' == buff[0]) {
 
1054
        fprintf(stderr, "no flag found\n");
 
1055
        return 1;
 
1056
    }
 
1057
    cp = buff;
 
1058
    do {
 
1059
        np = strchr(cp, ',');
 
1060
        if (np)
 
1061
            *np++ = '\0';
 
1062
        if (0 == strcmp(cp, "append"))
 
1063
            fp->append = 1;
 
1064
        else if (0 == strcmp(cp, "coe"))
 
1065
            fp->coe = 1;
 
1066
        else if (0 == strcmp(cp, "direct"))
 
1067
            fp->direct = 1;
 
1068
        else if (0 == strcmp(cp, "dpo"))
 
1069
            fp->dpo = 1;
 
1070
        else if (0 == strcmp(cp, "dsync"))
 
1071
            fp->dsync = 1;
 
1072
        else if (0 == strcmp(cp, "excl"))
 
1073
            fp->excl = 1;
 
1074
        else if (0 == strcmp(cp, "fua"))
 
1075
            fp->fua = 1;
 
1076
        else {
 
1077
            fprintf(stderr, "unrecognised flag: %s\n", cp);
 
1078
            return 1;
 
1079
        }
 
1080
        cp = np;
 
1081
    } while (cp);
 
1082
    return 0;
 
1083
}
 
1084
 
1091
1085
 
1092
1086
#define STR_SZ 1024
1093
1087
#define INOUTF_SZ 512
1099
1093
    long long seek = 0;
1100
1094
    int ibs = 0;
1101
1095
    int obs = 0;
1102
 
    long long count = -1;
 
1096
    int bpt_given = 0;
 
1097
    int cdbsz_given = 0;
1103
1098
    char str[STR_SZ];
1104
1099
    char * key;
1105
1100
    char * buf;
1108
1103
    int res, k;
1109
1104
    long long in_num_sect = 0;
1110
1105
    long long out_num_sect = 0;
1111
 
    int num_threads = DEF_NUM_THREADS;
1112
1106
    pthread_t threads[MAX_NUM_THREADS];
1113
 
    int do_time = 0;
1114
 
    int do_sync = 0;
1115
 
    int in_sect_sz, out_sect_sz, status;
1116
 
    long long infull, outfull;
 
1107
    int in_sect_sz, out_sect_sz, status, n, flags;
1117
1108
    void * vp;
1118
1109
    char ebuff[EBUFF_SZ];
1119
 
    struct timeval start_tm, end_tm;
1120
 
    Rq_coll rcoll;
1121
1110
 
1122
1111
    memset(&rcoll, 0, sizeof(Rq_coll));
1123
1112
    rcoll.bpt = DEF_BLOCKS_PER_TRANSFER;
1127
1116
    rcoll.cdbsz_out = DEF_SCSI_CDBSZ;
1128
1117
    inf[0] = '\0';
1129
1118
    outf[0] = '\0';
1130
 
    if (argc < 2) {
1131
 
        usage();
1132
 
        return 1;
1133
 
    }
1134
1119
 
1135
 
    for(k = 1; k < argc; k++) {
 
1120
    for (k = 1; k < argc; k++) {
1136
1121
        if (argv[k]) {
1137
1122
            strncpy(str, argv[k], STR_SZ);
1138
1123
            str[STR_SZ - 1] = '\0';
1139
1124
        }
1140
1125
        else
1141
1126
            continue;
1142
 
        for(key = str, buf = key; *buf && *buf != '=';)
 
1127
        for (key = str, buf = key; *buf && *buf != '=';)
1143
1128
            buf++;
1144
1129
        if (*buf)
1145
1130
            *buf++ = '\0';
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;
 
1136
            }
 
1137
            bpt_given = 1;
 
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;
 
1143
            }
 
1144
        } else if (0 == strcmp(key,"cdbsz")) {
 
1145
            rcoll.cdbsz_in = sg_get_num(buf);
 
1146
            rcoll.cdbsz_out = rcoll.cdbsz_in;
 
1147
            cdbsz_given = 1;
 
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;
 
1156
            }
 
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);
 
1163
            if (n & 1)
 
1164
                rcoll.out_flags.fua = 1;
 
1165
            if (n & 2)
 
1166
                rcoll.in_flags.fua = 1;
 
1167
        } else if (0 == strcmp(key,"ibs")) {
 
1168
            ibs = sg_get_num(buf);
 
1169
            if (-1 == ibs) {
 
1170
                fprintf(stderr, ME "bad argument to 'ibs'\n");
 
1171
                return SG_LIB_SYNTAX_ERROR;
 
1172
            }
 
1173
        } else if (strcmp(key,"if") == 0) {
1147
1174
            if ('\0' != inf[0]) {
1148
1175
                fprintf(stderr, "Second 'if=' argument??\n");
1149
 
                return 1;
 
1176
                return SG_LIB_SYNTAX_ERROR;
1150
1177
            } else
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;
 
1183
            }
 
1184
        } else if (0 == strcmp(key,"obs")) {
 
1185
            obs = sg_get_num(buf);
 
1186
            if (-1 == obs) {
 
1187
                fprintf(stderr, ME "bad argument to 'obs'\n");
 
1188
                return SG_LIB_SYNTAX_ERROR;
 
1189
            }
1152
1190
        } else if (strcmp(key,"of") == 0) {
1153
1191
            if ('\0' != outf[0]) {
1154
1192
                fprintf(stderr, "Second 'of=' argument??\n");
1155
 
                return 1;
 
1193
                return SG_LIB_SYNTAX_ERROR;
1156
1194
            } else
1157
1195
                strncpy(outf, buf, INOUTF_SZ);
1158
 
        } else if (0 == strcmp(key,"ibs"))
1159
 
            ibs = get_num(buf);
1160
 
        else if (0 == strcmp(key,"obs"))
1161
 
            obs = get_num(buf);
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;
 
1200
            }
 
1201
        } else if (0 == strcmp(key,"seek")) {
 
1202
            seek = sg_get_llnum(buf);
 
1203
            if (-1LL == seek) {
 
1204
                fprintf(stderr, ME "bad argument to 'seek'\n");
 
1205
                return SG_LIB_SYNTAX_ERROR;
 
1206
            }
 
1207
        } else if (0 == strcmp(key,"skip")) {
 
1208
            skip = sg_get_llnum(buf);
 
1209
            if (-1LL == skip) {
 
1210
                fprintf(stderr, ME "bad argument to 'skip'\n");
 
1211
                return SG_LIB_SYNTAX_ERROR;
 
1212
            }
 
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, "-?"))) {
 
1221
            usage();
 
1222
            return 0;
 
1223
        } else if (0 == strncmp(key, "--vers", 6)) {
 
1224
            fprintf(stderr, ME ": %s\n", 
1191
1225
                    version_str);
1192
1226
            return 0;
1193
1227
        }
1194
1228
        else {
1195
 
            fprintf(stderr, "Unrecognized argument '%s'\n", key);
1196
 
            usage();
1197
 
            return 1;
 
1229
            fprintf(stderr, "Unrecognized option '%s'\n", key);
 
1230
            fprintf(stderr, "For more information use '--help'\n");
 
1231
            return SG_LIB_SYNTAX_ERROR;
1198
1232
        }
1199
1233
    }
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");
1207
1241
        usage();
1208
 
        return 1;
 
1242
        return SG_LIB_SYNTAX_ERROR;
1209
1243
    }
1210
1244
    if ((skip < 0) || (seek < 0)) {
1211
1245
        fprintf(stderr, "skip and seek cannot be negative\n");
1212
 
        return 1;
 
1246
        return SG_LIB_SYNTAX_ERROR;
 
1247
    }
 
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;
1213
1251
    }
1214
1252
    if (rcoll.bpt < 1) {
1215
1253
        fprintf(stderr, "bpt must be greater than 0\n");
1216
 
        return 1;
 
1254
        return SG_LIB_SYNTAX_ERROR;
1217
1255
    }
 
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");
1220
1263
        usage();
1221
 
        return 1;
 
1264
        return SG_LIB_SYNTAX_ERROR;
1222
1265
    }
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);
 
1269
 
 
1270
    install_handler(SIGINT, interrupt_handler);
 
1271
    install_handler(SIGQUIT, interrupt_handler);
 
1272
    install_handler(SIGPIPE, interrupt_handler);
 
1273
    install_handler(SIGUSR1, siginfo_handler);
 
1274
 
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);
1230
1279
 
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);
1233
 
            return 1;
1234
 
        }
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) {
 
1287
            flags = O_RDWR;
 
1288
            if (rcoll.in_flags.direct)
 
1289
                flags |= O_DIRECT;
 
1290
            if (rcoll.in_flags.excl)
 
1291
                flags |= O_EXCL;
 
1292
            if (rcoll.in_flags.dsync)
 
1293
                flags |= O_SYNC;
 
1294
 
 
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);
1239
1298
                perror(ebuff);
1240
 
                return 1;
 
1299
                return SG_LIB_FILE_ERROR;
1241
1300
            }
1242
 
            if (sg_prepare(rcoll.infd, rcoll.bs, rcoll.bpt,
1243
 
                           &rcoll.in_scsi_type))
1244
 
                return 1;
 
1301
            if (sg_prepare(rcoll.infd, rcoll.bs, rcoll.bpt))
 
1302
                return SG_LIB_FILE_ERROR;
1245
1303
        }
1246
1304
        else {
1247
 
            if ((rcoll.infd = open(inf, O_RDONLY)) < 0) {
 
1305
            flags = O_RDONLY;
 
1306
            if (rcoll.in_flags.direct)
 
1307
                flags |= O_DIRECT;
 
1308
            if (rcoll.in_flags.excl)
 
1309
                flags |= O_EXCL;
 
1310
            if (rcoll.in_flags.dsync)
 
1311
                flags |= O_SYNC;
 
1312
 
 
1313
            if ((rcoll.infd = open(inf, flags)) < 0) {
1248
1314
                snprintf(ebuff, EBUFF_SZ,
1249
1315
                         ME "could not open %s for reading", inf);
1250
1316
                perror(ebuff);
1251
 
                return 1;
 
1317
                return SG_LIB_FILE_ERROR;
1252
1318
            }
1253
1319
            else if (skip > 0) {
1254
1320
                llse_loff_t offset = skip;
1258
1324
                    snprintf(ebuff, EBUFF_SZ,
1259
1325
                        ME "couldn't skip to required position on %s", inf);
1260
1326
                    perror(ebuff);
1261
 
                    return 1;
 
1327
                    return SG_LIB_FILE_ERROR;
1262
1328
                }
1263
1329
            }
1264
1330
        }
1268
1334
 
1269
1335
        if (FT_ST == rcoll.out_type) {
1270
1336
            fprintf(stderr, ME "unable to use scsi tape device %s\n", outf);
1271
 
            return 1;
 
1337
            return SG_LIB_FILE_ERROR;
1272
1338
        }
1273
1339
        else if (FT_SG == rcoll.out_type) {
1274
 
            if ((rcoll.outfd = open(outf, O_RDWR)) < 0) {
 
1340
            flags = O_RDWR;
 
1341
            if (rcoll.out_flags.direct)
 
1342
                flags |= O_DIRECT;
 
1343
            if (rcoll.out_flags.excl)
 
1344
                flags |= O_EXCL;
 
1345
            if (rcoll.out_flags.dsync)
 
1346
                flags |= O_SYNC;
 
1347
 
 
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);
1277
1351
                perror(ebuff);
1278
 
                return 1;
 
1352
                return SG_LIB_FILE_ERROR;
1279
1353
            }
1280
1354
 
1281
 
            if (sg_prepare(rcoll.outfd, rcoll.bs, rcoll.bpt,
1282
 
                           &rcoll.out_scsi_type))
1283
 
                return 1;
 
1355
            if (sg_prepare(rcoll.outfd, rcoll.bs, rcoll.bpt))
 
1356
                return SG_LIB_FILE_ERROR;
1284
1357
        }
1285
1358
        else if (FT_DEV_NULL == rcoll.out_type)
1286
1359
            rcoll.outfd = -1; /* don't bother opening */
1287
1360
        else {
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)
 
1364
                    flags |= O_DIRECT;
 
1365
                if (rcoll.out_flags.excl)
 
1366
                    flags |= O_EXCL;
 
1367
                if (rcoll.out_flags.dsync)
 
1368
                    flags |= O_SYNC;
 
1369
                if (rcoll.out_flags.append)
 
1370
                    flags |= O_APPEND;
 
1371
 
 
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);
1292
1375
                    perror(ebuff);
1293
 
                    return 1;
 
1376
                    return SG_LIB_FILE_ERROR;
1294
1377
                }
1295
1378
            }
1296
 
            else {
 
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);
1300
1383
                    perror(ebuff);
1301
 
                    return 1;
 
1384
                    return SG_LIB_FILE_ERROR;
1302
1385
                }
1303
1386
            }
1304
1387
            if (seek > 0) {
1309
1392
                    snprintf(ebuff, EBUFF_SZ,
1310
1393
                        ME "couldn't seek to required position on %s", outf);
1311
1394
                    perror(ebuff);
1312
 
                    return 1;
 
1395
                    return SG_LIB_FILE_ERROR;
1313
1396
                }
1314
1397
            }
1315
1398
        }
1316
1399
    }
1317
1400
    if ((STDIN_FILENO == rcoll.infd) && (STDOUT_FILENO == rcoll.outfd)) {
1318
 
        fprintf(stderr, "Disallow both if and of to be stdin and stdout");
1319
 
        return 1;
 
1401
        fprintf(stderr, "Can't have both 'if' as stdin _and_ 'of' as "
 
1402
                "stdout\n");
 
1403
        fprintf(stderr, "For more information use '--help'\n");
 
1404
        return SG_LIB_SYNTAX_ERROR;
1320
1405
    }
1321
 
    if (count < 0) {
 
1406
    if (dd_count < 0) {
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,
 
1414
                                         &in_sect_sz);
1329
1415
            }
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",
 
1419
                            inf);
 
1420
                else if (res == SG_LIB_CAT_NOT_READY)
 
1421
                    fprintf(stderr, "read capacity failed, %s not ready\n",
 
1422
                            inf);
 
1423
                else
 
1424
                    fprintf(stderr, "Unable to read capacity on %s\n", inf);
1332
1425
                in_num_sect = -1;
1333
1426
            }
1334
1427
        } else if (FT_BLOCK == rcoll.in_type) {
1348
1441
 
1349
1442
        out_num_sect = -1;
1350
1443
        if (FT_SG == rcoll.out_type) {
1351
 
            res = read_capacity(rcoll.outfd, &out_num_sect, &out_sect_sz);
 
1444
            res = scsi_read_capacity(rcoll.outfd, &out_num_sect, &out_sect_sz);
1352
1445
            if (2 == res) {
1353
1446
                fprintf(stderr,         
1354
1447
                        "Unit attention, media changed(out), continuing\n");
1355
 
                res = read_capacity(rcoll.outfd, &out_num_sect, &out_sect_sz);
 
1448
                res = scsi_read_capacity(rcoll.outfd, &out_num_sect,
 
1449
                                         &out_sect_sz);
1356
1450
            }
1357
1451
            if (0 != res) {
1358
 
                fprintf(stderr, "Unable to read capacity on %s\n", outf);
 
1452
                if (res == SG_LIB_CAT_INVALID_OP)
 
1453
                    fprintf(stderr, "read capacity not supported on %s\n",
 
1454
                            outf);
 
1455
                else if (res == SG_LIB_CAT_NOT_READY)
 
1456
                    fprintf(stderr, "read capacity failed, %s not ready\n",
 
1457
                            outf);
 
1458
                else
 
1459
                    fprintf(stderr, "Unable to read capacity on %s\n", outf);
1359
1460
                out_num_sect = -1;
1360
1461
            }
1361
1462
        } else if (FT_BLOCK == rcoll.out_type) {
1376
1477
 
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 :
1380
 
                                                       in_num_sect;
 
1480
                dd_count = (in_num_sect > out_num_sect) ? out_num_sect :
 
1481
                                                          in_num_sect;
1381
1482
            else
1382
 
                count = in_num_sect;
 
1483
                dd_count = in_num_sect;
1383
1484
        }
1384
1485
        else
1385
 
            count = out_num_sect;
 
1486
            dd_count = out_num_sect;
1386
1487
    }
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);
1390
 
    if (count < 0) {
 
1490
                "out_num_sect=%lld\n", dd_count, in_num_sect, out_num_sect);
 
1491
    if (dd_count < 0) {
1391
1492
        fprintf(stderr, "Couldn't calculate count, please give one\n");
1392
 
        return 1;
1393
 
    }
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 "
1397
 
                "(for 'if')\n");
1398
 
        rcoll.cdbsz_in = MAX_SCSI_CDBSZ;
1399
 
    }
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 "
1403
 
                "(for 'of')\n");
1404
 
        rcoll.cdbsz_out = MAX_SCSI_CDBSZ;
 
1493
        return SG_LIB_CAT_OTHER;
 
1494
    }
 
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 "
 
1499
                    "(for 'if')\n");
 
1500
            rcoll.cdbsz_in = MAX_SCSI_CDBSZ;
 
1501
        }
 
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 "
 
1505
                    "(for 'of')\n");
 
1506
            rcoll.cdbsz_out = MAX_SCSI_CDBSZ;
 
1507
        }
1405
1508
    }
1406
1509
 
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);
1436
1539
    }
1437
1540
 
1438
1541
/* vvvvvvvvvvv  Start worker threads  vvvvvvvvvvvvvvvvvvvvvvvv */
1439
 
    if ((rcoll.out_done_count > 0) && (num_threads > 0)) {
 
1542
    if ((rcoll.out_rem_count > 0) && (num_threads > 0)) {
1440
1543
        /* Run 1 work thread to shake down infant retryable stuff */
1441
1544
        status = pthread_mutex_lock(&rcoll.out_mutex);
1442
1545
        if (0 != status) err_exit(status, "lock out_mutex");
1472
1575
        }
1473
1576
    }
1474
1577
 
1475
 
    if ((do_time) && (start_tm.tv_sec || start_tm.tv_usec)) {
1476
 
        struct timeval res_tm;
1477
 
        double a, b;
 
1578
    if ((do_time) && (start_tm.tv_sec || start_tm.tv_usec))
 
1579
        calc_duration_throughput(0);
1478
1580
 
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) {
1483
 
            --res_tm.tv_sec;
1484
 
            res_tm.tv_usec += 1000000;
1485
 
        }
1486
 
        a = res_tm.tv_sec;
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));
1493
 
        else
1494
 
            fprintf(stderr, "\n");
1495
 
    }
1496
1581
    if (do_sync) {
1497
1582
        if (FT_SG == rcoll.out_type) {
1498
1583
            fprintf(stderr, ">> Synchronizing cache on %s\n", outf);
1499
 
            res = sync_cache(rcoll.outfd);
1500
 
            if (2 == res) {
 
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);
1504
1589
            }
1505
1590
            if (0 != res)
1506
1591
                fprintf(stderr, "Unable to synchronize cache\n");
1513
1598
        close(rcoll.infd);
1514
1599
    if ((STDOUT_FILENO != rcoll.outfd) && (FT_DEV_NULL != rcoll.out_type))
1515
1600
        close(rcoll.outfd);
1516
 
    res = 0;
 
1601
    res = exit_status;
1517
1602
    if (0 != rcoll.out_count) {
1518
1603
        fprintf(stderr, ">>>> Some error occurred, remaining blocks=%lld\n",
1519
1604
               rcoll.out_count);
1520
 
        res = 2;
 
1605
        if (0 == res)
 
1606
            res = SG_LIB_CAT_OTHER;
1521
1607
    }
1522
 
    infull = count - rcoll.in_done_count -  rcoll.in_partial;
1523
 
    fprintf(stderr, "%lld+%d records in\n", infull, rcoll.in_partial);
1524
 
    outfull = count - rcoll.out_done_count - rcoll.out_partial;
1525
 
    fprintf(stderr, "%lld+%d records out\n", outfull, rcoll.out_partial);
 
1608
    print_stats("");
1526
1609
    if (rcoll.dio_incomplete) {
1527
1610
        int fd;
1528
1611
        char c;
1541
1624
    if (rcoll.sum_of_resids)
1542
1625
        fprintf(stderr, ">> Non-zero sum of residual counts=%d\n",
1543
1626
               rcoll.sum_of_resids);
1544
 
    return res;
 
1627
    return (res >= 0) ? res : SG_LIB_CAT_OTHER;
1545
1628
}