aboutsummaryrefslogtreecommitdiff
path: root/sgm_dd.c
diff options
context:
space:
mode:
Diffstat (limited to 'sgm_dd.c')
-rw-r--r--sgm_dd.c75
1 files changed, 53 insertions, 22 deletions
diff --git a/sgm_dd.c b/sgm_dd.c
index d2c3bbd0..870924b6 100644
--- a/sgm_dd.c
+++ b/sgm_dd.c
@@ -55,7 +55,7 @@
This version is designed for the linux kernel 2.4 and 2.6 series.
*/
-static char * version_str = "1.31 20070123";
+static char * version_str = "1.32 20070318 shared_mmap";
#define DEF_BLOCK_SIZE 512
#define DEF_BLOCKS_PER_TRANSFER 128
@@ -82,6 +82,13 @@ static char * version_str = "1.31 20070123";
#define SAI_READ_CAPACITY_16 0x10
#endif
+#ifndef SG_FLAG_SHARED_MMAP_IO
+#define SG_FLAG_SHARED_MMAP_IO 8
+#endif
+#ifndef SG_INFO_SHARED_MMAP_IO
+#define SG_INFO_SHARED_MMAP_IO 8
+#endif
+
#define DEF_TIMEOUT 60000 /* 60,000 millisecs == 60 seconds */
#ifndef RAW_MAJOR
@@ -115,15 +122,20 @@ static int start_tm_valid = 0;
static struct timeval start_tm;
static int blk_sz = 0;
+static int shared_mm_req = 0;
+static int shared_mm_done = 0;
+
static const char * proc_allow_dio = "/proc/scsi/sg/allow_dio";
struct flags_t {
int append;
+ int dio;
int direct;
int dpo;
int dsync;
int excl;
int fua;
+ int smmap;
};
@@ -273,8 +285,9 @@ void usage()
" of file or device to write to (def: stdout), "
"OFILE of '.'\n"
" treated as /dev/null\n"
- " oflag comma separated list from: [append,direct,dpo,"
- "dsync,excl,fua]\n"
+ " oflag comma separated list from: [append,dio,direct,"
+ "dpo,dsync,\n"
+ " excl,fua,smmap]\n"
" seek block position to start writing to OFILE\n"
" skip block position to start reading from IFILE\n"
" sync 0->no sync(def), 1->SYNCHRONIZE CACHE on OFILE "
@@ -286,7 +299,7 @@ void usage()
" --help print usage message then exit\n"
" --version print version information then exit\n\n"
"Copy from IFILE to OFILE, similar to dd command\n"
- "specialized for SCSI devices for which mmap-ed IO attemped\n");
+ "specialized for SCSI devices for which mmap-ed IO attempted\n");
}
/* Return of 0 -> success, see sg_ll_read_capacity*() otherwise */
@@ -563,7 +576,8 @@ int sg_read(int sg_fd, unsigned char * buff, int blocks, long long from_block,
* SG_LIB_CAT_ABORTED_COMMAND, -2 -> recoverable (ENOMEM),
* -1 -> unrecoverable error */
int sg_write(int sg_fd, unsigned char * buff, int blocks, long long to_block,
- int bs, int cdbsz, int fua, int dpo, int do_mmap, int * diop)
+ int bs, int cdbsz, int fua, int dpo, int do_mmap,
+ int mmap_shareable, int * diop)
{
unsigned char wrCmd[MAX_SCSI_CDBSZ];
unsigned char senseBuff[SENSE_BUFF_LEN];
@@ -582,15 +596,18 @@ int sg_write(int sg_fd, unsigned char * buff, int blocks, long long to_block,
io_hdr.cmdp = wrCmd;
io_hdr.dxfer_direction = SG_DXFER_TO_DEV;
io_hdr.dxfer_len = bs * blocks;
- if (! do_mmap)
+ if (mmap_shareable || (! do_mmap))
io_hdr.dxferp = buff;
io_hdr.mx_sb_len = SENSE_BUFF_LEN;
io_hdr.sbp = senseBuff;
io_hdr.timeout = DEF_TIMEOUT;
io_hdr.pack_id = (int)to_block;
- if (do_mmap)
+ if (mmap_shareable) {
+ io_hdr.flags |= SG_FLAG_SHARED_MMAP_IO;
+ ++shared_mm_req;
+ } else if (do_mmap)
io_hdr.flags |= SG_FLAG_MMAP_IO;
- if (diop && *diop)
+ else if (diop && *diop)
io_hdr.flags |= SG_FLAG_DIRECT_IO;
if (verbose > 2) {
fprintf(stderr, " write cdb: ");
@@ -644,6 +661,8 @@ int sg_write(int sg_fd, unsigned char * buff, int blocks, long long to_block,
sg_chk_n_print3("writing", &io_hdr, verbose > 1);
return res;
}
+ if ((mmap_shareable) && (SG_INFO_SHARED_MMAP_IO & io_hdr.info))
+ ++shared_mm_done;
if (diop && *diop &&
((io_hdr.info & SG_INFO_DIRECT_IO_MASK) != SG_INFO_DIRECT_IO))
*diop = 0; /* flag that dio not done (completely) */
@@ -669,6 +688,8 @@ static int process_flags(const char * arg, struct flags_t * fp)
*np++ = '\0';
if (0 == strcmp(cp, "append"))
fp->append = 1;
+ else if (0 == strcmp(cp, "dio"))
+ fp->dio = 1;
else if (0 == strcmp(cp, "direct"))
fp->direct = 1;
else if (0 == strcmp(cp, "dpo"))
@@ -679,6 +700,8 @@ static int process_flags(const char * arg, struct flags_t * fp)
fp->excl = 1;
else if (0 == strcmp(cp, "fua"))
fp->fua = 1;
+ else if (0 == strcmp(cp, "smmap"))
+ fp->smmap = 1;
else {
fprintf(stderr, "unrecognised flag: %s\n", cp);
return 1;
@@ -723,7 +746,6 @@ int main(int argc, char * argv[])
int cdbsz_given = 0;
int do_coe = 0; /* dummy, just accept + ignore */
int do_sync = 0;
- int do_dio = 0;
int num_dio_not_done = 0;
int in_sect_sz, out_sect_sz;
int n, flags;
@@ -732,6 +754,7 @@ int main(int argc, char * argv[])
size_t psz = getpagesize();
struct flags_t in_flags;
struct flags_t out_flags;
+ int mmap_shareable = 0;
int ret = 0;
inf[0] = '\0';
@@ -774,7 +797,7 @@ int main(int argc, char * argv[])
return SG_LIB_SYNTAX_ERROR;
}
} else if (0 == strcmp(key,"dio"))
- do_dio = sg_get_num(buf);
+ out_flags.dio = sg_get_num(buf);
else if (0 == strcmp(key,"fua")) {
n = sg_get_num(buf);
if (n & 1)
@@ -939,6 +962,7 @@ int main(int argc, char * argv[])
perror(ebuff);
return SG_LIB_FILE_ERROR;
}
+ mmap_shareable = 1;
}
else {
flags = O_RDONLY;
@@ -1183,12 +1207,12 @@ int main(int argc, char * argv[])
}
}
- if (do_dio && (FT_SG != in_type)) {
- do_dio = 0;
+ if (out_flags.dio && (FT_SG != in_type)) {
+ out_flags.dio = 0;
fprintf(stderr, ">>> dio only performed on 'of' side when 'if' is"
" an sg device\n");
}
- if (do_dio) {
+ if (out_flags.dio) {
int fd;
char c;
@@ -1202,9 +1226,11 @@ int main(int argc, char * argv[])
}
}
- if (wrkMmap)
+ if (wrkMmap) {
wrkPos = wrkMmap;
- else {
+ if (! (mmap_shareable && out_flags.smmap && (FT_SG == out_type)))
+ mmap_shareable = 0;
+ } else {
if ((FT_RAW == in_type) || (FT_RAW == out_type)) {
wrkBuff = (unsigned char *)malloc(blk_sz * bpt + psz);
if (0 == wrkBuff) {
@@ -1237,8 +1263,8 @@ int main(int argc, char * argv[])
}
req_count = dd_count;
- if (verbose && (dd_count > 0) && (0 == do_dio) &&
- (FT_SG == in_type) && (FT_SG == out_type))
+ if (verbose && (dd_count > 0) && (0 == out_flags.dio) &&
+ (FT_SG == in_type) && (FT_SG == out_type) && (! mmap_shareable))
fprintf(stderr, "Since both 'if' and 'of' are sg devices, only do "
"mmap-ed transfers on 'if'\n");
@@ -1290,18 +1316,19 @@ int main(int argc, char * argv[])
if (FT_SG == out_type) {
int do_mmap = (FT_SG == in_type) ? 0 : 1;
- int dio_res = do_dio;
+ int dio_res = out_flags.dio;
ret = sg_write(outfd, wrkPos, blocks, seek, blk_sz, scsi_cdbsz_out,
- out_flags.fua, out_flags.dpo, do_mmap, &dio_res);
+ out_flags.fua, out_flags.dpo, do_mmap,
+ mmap_shareable, &dio_res);
if ((SG_LIB_CAT_UNIT_ATTENTION == ret) ||
(SG_LIB_CAT_ABORTED_COMMAND == ret)) {
fprintf(stderr, "Unit attention or aborted command, "
"continuing (w)\n");
- dio_res = do_dio;
+ dio_res = out_flags.dio;
ret = sg_write(outfd, wrkPos, blocks, seek, blk_sz,
scsi_cdbsz_out, out_flags.fua, out_flags.dpo,
- do_mmap, &dio_res);
+ do_mmap, mmap_shareable, &dio_res);
}
if (0 != ret) {
fprintf(stderr, "sg_write failed, seek=%lld\n", seek);
@@ -1309,7 +1336,7 @@ int main(int argc, char * argv[])
}
else {
out_full += blocks;
- if (do_dio && (0 == dio_res))
+ if (out_flags.dio && (0 == dio_res))
num_dio_not_done++;
}
}
@@ -1376,5 +1403,9 @@ int main(int argc, char * argv[])
if (num_dio_not_done)
fprintf(stderr, ">> dio requested but _not_ done %d times\n",
num_dio_not_done);
+ if ((verbose > 0) && out_flags.smmap && (shared_mm_req > 0)) {
+ fprintf(stderr, ">> shared_mm_req=%d, shared_mm_done=%d\n",
+ shared_mm_req, shared_mm_done);
+ }
return (ret >= 0) ? ret : SG_LIB_CAT_OTHER;
}