diff options
author | Douglas Gilbert <dgilbert@interlog.com> | 2015-02-07 20:28:00 +0000 |
---|---|---|
committer | Douglas Gilbert <dgilbert@interlog.com> | 2015-02-07 20:28:00 +0000 |
commit | cc44a8ffd8b6c05d6dcb96accf3e3ebcc16a9cf4 (patch) | |
tree | 43dfce42172b40bbfd62ae5c474819853dafd89e /examples | |
parent | 8eb6e683154b2538f67bc379824c1c64dc7e10cb (diff) | |
download | sg3_utils-cc44a8ffd8b6c05d6dcb96accf3e3ebcc16a9cf4.tar.gz |
sg_simple_aio.c: remove; sg_iovec_tst.c: improve
git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@633 6180dd3e-e324-4e3e-922d-17de1ae2f315
Diffstat (limited to 'examples')
-rw-r--r-- | examples/Makefile | 8 | ||||
-rw-r--r-- | examples/sg_iovec_tst.c | 130 | ||||
-rw-r--r-- | examples/sg_simple_aio.c | 239 |
3 files changed, 103 insertions, 274 deletions
diff --git a/examples/Makefile b/examples/Makefile index 7fb43404..2f02328f 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -12,7 +12,7 @@ EXECS = sg_simple1 sg_simple2 sg_simple3 sg_simple4 sg_simple16 \ sg__sat_identify sg__sat_phy_event sg__sat_set_features \ sg_sat_chk_power sg_sat_smart_rd_data -EXTRAS = sg_simple_aio sg_queue_tst sgq_dd +EXTRAS = sg_queue_tst sgq_dd BSG_EXTRAS = bsg_queue_tst @@ -60,12 +60,6 @@ sg_simple4: sg_simple4.o $(LIBFILESOLD) sg_simple16: sg_simple16.o $(LIBFILESOLD) $(LD) -o $@ $(LDFLAGS) $^ -# sg_simple_aio: sg_simple_aio.o $(LIBFILESOLD) -# $(LD) -o $@ $(LDFLAGS) $^ -l aio - -sg_simple_aio: sg_simple_aio.o $(LIBFILESOLD) - $(LD) -o $@ $(LDFLAGS) $^ - sg_iovec_tst: sg_iovec_tst.o $(LIBFILESOLD) $(LD) -o $@ $(LDFLAGS) $^ diff --git a/examples/sg_iovec_tst.c b/examples/sg_iovec_tst.c index 9f8bbe3c..2a924261 100644 --- a/examples/sg_iovec_tst.c +++ b/examples/sg_iovec_tst.c @@ -5,6 +5,7 @@ #include <stdlib.h> #include <string.h> #include <errno.h> +#include <poll.h> #include <sys/ioctl.h> #include <sys/types.h> #include <sys/stat.h> @@ -13,7 +14,7 @@ /* Test code for D. Gilbert's extensions to the Linux OS SCSI generic ("sg") device driver. -* Copyright (C) 2003-2007 D. Gilbert +* Copyright (C) 2003-2015 D. Gilbert * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) @@ -24,7 +25,7 @@ normal file. The purpose is to test the sg_iovec mechanism within the sg_io_hdr structure. - Version 0.12 (20070121) + Version 0.13 (20150204) */ @@ -38,15 +39,32 @@ struct sg_iovec iovec[IOVEC_ELEMS]; + +static void +usage(void) +{ + printf("Usage: sg_iovec_tst [-a] [-b=bs] -c=num [-e=es] [-h]\n" + " <generic_device> <output_filename>\n"); + printf(" where: -a async sg use (def: use ioctl(SGIO) )\n"); + printf(" -b=bs block size (default 512 Bytes)\n"); + printf(" -c=num count of blocks to transfer\n"); + printf(" -e=es iovec element size (def: 509)\n"); + printf(" -h this usage message\n"); + printf(" reads from <generic_device> and sends to " + "<output_filename>\nUses iovec (a scatter list) in linear " + "mode\n"); +} + /* Returns 0 if everything ok */ -int sg_read(int sg_fd, unsigned char * buff, int num_blocks, int from_block, - int bs) +static int sg_read(int sg_fd, unsigned char * buff, int num_blocks, + int from_block, int bs, int elem_size, int async) { unsigned char rdCmd[10] = {READ_10, 0, 0, 0, 0, 0, 0, 0, 0, 0}; unsigned char senseBuff[SENSE_BUFF_LEN]; struct sg_io_hdr io_hdr; + struct pollfd a_poll; int dxfer_len = bs * num_blocks; - int k, pos, rem; + int k, pos, rem, res; rdCmd[2] = (unsigned char)((from_block >> 24) & 0xff); rdCmd[3] = (unsigned char)((from_block >> 16) & 0xff); @@ -57,11 +75,11 @@ int sg_read(int sg_fd, unsigned char * buff, int num_blocks, int from_block, for (k = 0, pos = 0, rem = dxfer_len; k < IOVEC_ELEMS; ++k) { iovec[k].iov_base = buff + pos; - iovec[k].iov_len = (rem > A_PRIME) ? A_PRIME : rem; - if (rem <= A_PRIME) + iovec[k].iov_len = (rem > elem_size) ? elem_size : rem; + if (rem <= elem_size) break; - pos += A_PRIME; - rem -= A_PRIME; + pos += elem_size; + rem -= elem_size; } if (k >= IOVEC_ELEMS) { fprintf(stderr, "Can't fit dxfer_len=%d bytes in iovec\n", dxfer_len); @@ -80,7 +98,39 @@ int sg_read(int sg_fd, unsigned char * buff, int num_blocks, int from_block, io_hdr.timeout = DEF_TIMEOUT; io_hdr.pack_id = from_block; - if (ioctl(sg_fd, SG_IO, &io_hdr)) { + if (async) { + res = write(sg_fd, &io_hdr, sizeof(io_hdr)); + if (res < 0) { + perror("write(<sg_device>), error"); + return -1; + } else if (res < (int)sizeof(io_hdr)) { + fprintf(stderr, "write(<sg_device>) returned %d, expected %d\n", + res, (int)sizeof(io_hdr)); + return -1; + } + a_poll.fd = sg_fd; + a_poll.events = POLLIN; + a_poll.revents = 0; + res = poll(&a_poll, 1, 2000 /* millisecs */ ); + if (res < 0) { + perror("poll error on <sg_device>"); + return -1; + } + if (0 == (POLLIN & a_poll.revents)) { + fprintf(stderr, "strange, poll() completed without data to " + "read\n"); + return -1; + } + res = read(sg_fd, &io_hdr, sizeof(io_hdr)); + if (res < 0) { + perror("read(<sg_device>), error"); + return -1; + } else if (res < (int)sizeof(io_hdr)) { + fprintf(stderr, "read(<sg_device>) returned %d, expected %d\n", + res, (int)sizeof(io_hdr)); + return -1; + } + } else if (ioctl(sg_fd, SG_IO, &io_hdr)) { perror("reading (SG_IO) on sg device, error"); return -1; } @@ -106,15 +156,19 @@ int main(int argc, char * argv[]) { int sg_fd, fd, res, j, m, dxfer_len; unsigned int k, num; + int do_async = 0; int do_help = 0; int blk_size = 512; + int elem_size = A_PRIME; int count = 0; char * sg_file_name = 0; char * out_file_name = 0; unsigned char * buffp; for (j = 1; j < argc; ++j) { - if (0 == strncmp("-b=", argv[j], 3)) { + if (0 == strcmp("-a", argv[j])) + do_async = 1; + else if (0 == strncmp("-b=", argv[j], 3)) { m = 3; num = sscanf(argv[j] + m, "%d", &blk_size); if ((1 != num) || (blk_size <= 0)) { @@ -122,8 +176,7 @@ int main(int argc, char * argv[]) sg_file_name = 0; break; } - } - else if (0 == strncmp("-c=", argv[j], 3)) { + } else if (0 == strncmp("-c=", argv[j], 3)) { m = 3; num = sscanf(argv[j] + m, "%d", &count); if (1 != num) { @@ -131,31 +184,49 @@ int main(int argc, char * argv[]) sg_file_name = 0; break; } - } - else if (0 == strcmp("-h", argv[j])) + } else if (0 == strncmp("-e=", argv[j], 3)) { + m = 3; + num = sscanf(argv[j] + m, "%d", &elem_size); + if (1 != num) { + printf("Couldn't decode number after '-e' switch\n"); + sg_file_name = 0; + break; + } + } else if (0 == strcmp("-h", argv[j])) do_help = 1; else if (*argv[j] == '-') { printf("Unrecognized switch: %s\n", argv[j]); sg_file_name = 0; break; - } - else if (NULL == sg_file_name) + } else if (NULL == sg_file_name) sg_file_name = argv[j]; else out_file_name = argv[j]; } - if ((NULL == sg_file_name) || (NULL == out_file_name) || (0 == count)) { - printf("Usage: sg_iovec_tst [-h] [-b=num] -c=num <generic_device> " - "<output_filename>\n"); - printf(" where: -h this usage message\n"); - printf(" -b=num block size (default 512 Bytes)\n"); - printf(" -c=num count of blocks to transfer\n"); - printf(" reads from <generic_device> and sends to " - "<output_filename>\n"); + if (do_help) { + usage(); + return 0; + } + if (NULL == sg_file_name) { + printf(">>> need sg node name (e.g. /dev/sg3)\n\n"); + usage(); + return 1; + } + if (NULL == out_file_name) { + printf(">>> need out filename (to place what is fetched by READ\n\n"); + usage(); + return 1; + } + if (0 == count) { + printf(">>> need count of blocks to READ\n\n"); + usage(); return 1; } - sg_fd = open(sg_file_name, O_RDONLY); + if (do_async) + sg_fd = open(sg_file_name, O_RDWR); + else + sg_fd = open(sg_file_name, O_RDONLY); if (sg_fd < 0) { perror(ME "sg device node open error"); return 1; @@ -174,12 +245,15 @@ int main(int argc, char * argv[]) dxfer_len = count * blk_size; buffp = (unsigned char *)malloc(dxfer_len); if (buffp) { - if (0 == sg_read(sg_fd, buffp, count, 0, blk_size)) { + if (0 == sg_read(sg_fd, buffp, count, 0, blk_size, elem_size, + do_async)) { if (write(fd, buffp, dxfer_len) < 0) perror(ME "output write failed"); } free(buffp); - } + } else + fprintf(stderr, "user space malloc for %d bytes failed\n", + dxfer_len); res = close(fd); if (res < 0) { perror(ME "output file close error"); diff --git a/examples/sg_simple_aio.c b/examples/sg_simple_aio.c deleted file mode 100644 index 95dfcfa2..00000000 --- a/examples/sg_simple_aio.c +++ /dev/null @@ -1,239 +0,0 @@ -#include <unistd.h> -#include <fcntl.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include <sys/ioctl.h> -#include <sys/types.h> -#include <sys/stat.h> - -/* - * To use "aio" then uncomment the 'WANT_AIO' define. - * Depending on the distribution libaio and libaio-dev packages - * may need to be loaded. - * If WANT_AIO is defined then a '-laio' term will most likely - * be required in the Makefile. - */ -/* #define WANT_AIO 1 */ - -#ifdef WANT_AIO -#include <libaio.h> -#endif - -#include "sg_lib.h" -#include "sg_io_linux.h" -#include "sg_linux_inc.h" - -/* This is a simple program executing a SCSI INQUIRY command and a - TEST UNIT READY command using the SCSI generic (sg) driver - This variant to test async I/O. - -* Copyright (C) 2003-2010 D. Gilbert -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2, or (at your option) -* any later version. - - Invocation: sg_simple_aio [-x] <sg_device> - - Version 0.92 (20100320) - -6 byte INQUIRY command: -[0x12][ |lu][pg cde][res ][al len][cntrl ] - -6 byte TEST UNIT READY command: -[0x00][ |lu][res ][res ][res ][res ] - -*/ - -#define INQ_REPLY_LEN 96 -#define INQ_CMD_LEN 6 -#define TUR_CMD_LEN 6 - -#define EBUFF_SZ 256 - - - -#ifdef WANT_AIO -void my_io_callback(io_context_t ctx, struct iocb *iocb, long res, long res2) -{ - printf("my_io_callback: res=%ld, res2=%ld\n", res, res2); -} -#endif - - -int main(int argc, char * argv[]) -{ - int sg_fd, k, ok; - unsigned char inqCmdBlk [INQ_CMD_LEN] = - {0x12, 0, 0, 0, INQ_REPLY_LEN, 0}; - unsigned char turCmdBlk [TUR_CMD_LEN] = - {0x00, 0, 0, 0, 0, 0}; - unsigned char inqBuff[INQ_REPLY_LEN]; - sg_io_hdr_t io_hdr; - char * file_name = 0; - char ebuff[EBUFF_SZ]; - unsigned char sense_buffer[32]; - int do_extra = 0; - - for (k = 1; k < argc; ++k) { - if (0 == memcmp("-x", argv[k], 2)) - do_extra = 1; - else if (*argv[k] == '-') { - printf("Unrecognized switch: %s\n", argv[k]); - file_name = 0; - break; - } - else if (0 == file_name) - file_name = argv[k]; - else { - printf("too many arguments\n"); - file_name = 0; - break; - } - } - if (0 == file_name) { - printf("Usage: 'sg_simple_aio [-x] <sg_device>'\n"); - return 1; - } - - /* An access mode of O_RDWR is required for write()/read() interface */ - if ((sg_fd = open(file_name, O_RDWR)) < 0) { - snprintf(ebuff, EBUFF_SZ, - "sg_simple_aio: error opening file: %s", file_name); - perror(ebuff); - return 1; - } - /* Just to be safe, check we have a new sg device by trying an ioctl */ - if ((ioctl(sg_fd, SG_GET_VERSION_NUM, &k) < 0) || (k < 30000)) { - printf("sg_simple_aio: %s doesn't seem to be an new sg device\n", - file_name); - close(sg_fd); - return 1; - } - - /* Prepare INQUIRY command */ - memset(&io_hdr, 0, sizeof(sg_io_hdr_t)); - io_hdr.interface_id = 'S'; - io_hdr.cmd_len = sizeof(inqCmdBlk); - /* io_hdr.iovec_count = 0; */ /* memset takes care of this */ - io_hdr.mx_sb_len = sizeof(sense_buffer); - io_hdr.dxfer_direction = SG_DXFER_FROM_DEV; - io_hdr.dxfer_len = INQ_REPLY_LEN; - io_hdr.dxferp = inqBuff; - io_hdr.cmdp = inqCmdBlk; - io_hdr.sbp = sense_buffer; - io_hdr.timeout = 20000; /* 20000 millisecs == 20 seconds */ - /* io_hdr.flags = 0; */ /* take defaults: indirect IO, etc */ - /* io_hdr.pack_id = 0; */ - /* io_hdr.usr_ptr = NULL; */ - -#if WANT_AIO - { - struct iocb a_iocb; - struct iocb * iocb_arr[1]; - io_context_t io_ctx; - int res; - - if (0 != (res = io_queue_init(1, &io_ctx))) { - printf("io_queue_init: failed %s\n", strerror(-res)); - close(sg_fd); - return 1; - } - iocb_arr[0] = &a_iocb; - io_prep_pwrite(iocb_arr[0], sg_fd, &io_hdr, sizeof(io_hdr), 0); - io_set_callback(iocb_arr[0], my_io_callback); - res = io_submit(io_ctx, 1, iocb_arr); - if (1 != res) { - printf("io_submit: returned %d\n", res); - close(sg_fd); - return 1; - } - } -#else - if (write(sg_fd, &io_hdr, sizeof(io_hdr)) < 0) { - perror("sg_simple_aio: Inquiry write error"); - close(sg_fd); - return 1; - } -#endif - /* sleep(3); */ - if (read(sg_fd, &io_hdr, sizeof(io_hdr)) < 0) { - perror("sg_simple_aio: Inquiry read error"); - close(sg_fd); - return 1; - } - - /* now for the error processing */ - ok = 0; - switch (sg_err_category3(&io_hdr)) { - case SG_LIB_CAT_CLEAN: - ok = 1; - break; - case SG_LIB_CAT_RECOVERED: - printf("Recovered error on INQUIRY, continuing\n"); - ok = 1; - break; - default: /* won't bother decoding other categories */ - sg_chk_n_print3("INQUIRY command error", &io_hdr, 1); - break; - } - - if (ok) { /* output result if it is available */ - char * p = (char *)inqBuff; - int f = (int)*(p + 7); - printf("Some of the INQUIRY command's results:\n"); - printf(" %.8s %.16s %.4s ", p + 8, p + 16, p + 32); - printf("[wide=%d sync=%d cmdque=%d sftre=%d]\n", - !!(f & 0x20), !!(f & 0x10), !!(f & 2), !!(f & 1)); - /* Extra info, not necessary to look at */ - if (do_extra) - printf("INQUIRY duration=%u millisecs, resid=%d, msg_status=%d\n", - io_hdr.duration, io_hdr.resid, (int)io_hdr.msg_status); - } - - /* Prepare TEST UNIT READY command */ - memset(&io_hdr, 0, sizeof(sg_io_hdr_t)); - io_hdr.interface_id = 'S'; - io_hdr.cmd_len = sizeof(turCmdBlk); - io_hdr.mx_sb_len = sizeof(sense_buffer); - io_hdr.dxfer_direction = SG_DXFER_NONE; - io_hdr.cmdp = turCmdBlk; - io_hdr.sbp = sense_buffer; - io_hdr.timeout = 20000; /* 20000 millisecs == 20 seconds */ - - if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) { - perror("sg_simple_aio: Test Unit Ready SG_IO ioctl error"); - close(sg_fd); - return 1; - } - - /* now for the error processing */ - ok = 0; - switch (sg_err_category3(&io_hdr)) { - case SG_LIB_CAT_CLEAN: - ok = 1; - break; - case SG_LIB_CAT_RECOVERED: - printf("Recovered error on Test Unit Ready, continuing\n"); - ok = 1; - break; - default: /* won't bother decoding other categories */ - sg_chk_n_print3("Test Unit Ready command error", &io_hdr, 1); - break; - } - - if (ok) - printf("Test Unit Ready successful so unit is ready!\n"); - else - printf("Test Unit Ready failed so unit may _not_ be ready!\n"); - - if (do_extra) - printf("TEST UNIT READY duration=%u millisecs, resid=%d, " - "msg_status=%d\n", io_hdr.duration, io_hdr.resid, - (int)io_hdr.msg_status); - - close(sg_fd); - return 0; -} |