sg_inq: update version descriptors to spc5r21; scripts/scsi-sg3_id: update rules; testing folder work
git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@814 6180dd3e-e324-4e3e-922d-17de1ae2f315
diff --git a/testing/sg_tst_ioctl.c b/testing/sg_tst_ioctl.c
index ea3dde9..5e6b0ef 100644
--- a/testing/sg_tst_ioctl.c
+++ b/testing/sg_tst_ioctl.c
@@ -15,6 +15,9 @@
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <ctype.h>
#include <string.h>
#include <errno.h>
#include <sys/ioctl.h>
@@ -53,9 +56,9 @@
* later of the Linux sg driver. */
-static const char * version_str = "Version: 1.04 20190201";
+static const char * version_str = "Version: 1.06 20190323";
-#define INQ_REPLY_LEN 96
+#define INQ_REPLY_LEN 128
#define INQ_CMD_LEN 6
#define SDIAG_CMD_LEN 6
#define SENSE_BUFFER_LEN 96
@@ -80,11 +83,14 @@
static bool ioctl_only = false;
static bool q_at_tail = false;
static bool write_only = false;
+static bool mrq_immed = false; /* if set, also sets mrq_iosubmit */
+static bool mrq_iosubmit = false;
static int childs_pid = 0;
static int q_len = DEF_Q_LEN;
static int sleep_secs = 0;
static int reserve_buff_sz = DEF_RESERVE_BUFF_SZ;
+static int num_mrqs = 0;
static int verbose = 0;
static const char * relative_cp = NULL;
@@ -93,13 +99,20 @@
static void
usage(void)
{
- printf("Usage: sg_tst_ioctl [-f] [-h] [-l=Q_LEN] [-o] [-r=SZ] [-s=SEC] "
- "[-t]\n"
- " [-v] [-V] [-w] <sg_device> [<sg_device2>]\n"
+ printf("Usage: sg_tst_ioctl [-f] [-h] [-l=Q_LEN] [-m=MRQS[,I|S]] [-r=SZ] "
+ "[-s=SEC]\n"
+ " [-t] [-v] [-V] [-w] <sg_device> "
+ "[<sg_device2>]\n"
" where:\n"
" -f fork and test share between processes\n"
" -h help: print usage message then exit\n"
" -l=Q_LEN queue length, between 1 and 511 (def: 16)\n"
+ " -m=MRQS[,I|S] test multi-req, MRQS number to do; if "
+ "the letter\n"
+ " 'I' is appended after a comma, then do "
+ "IMMED mrq;\n"
+ " 'S' is appended, then use "
+ "ioctl(SG_IOSUBMIT)\n"
" -o ioctls only, then exit\n"
" -r=SZ reserve buffer size in KB (def: 256 --> 256 "
"KB)\n"
@@ -240,7 +253,6 @@
seip->ctl_flags_rd_mask |= SG_CTL_FLAGM_UNSHARE;
seip->ctl_flags_rd_mask |= SG_CTL_FLAGM_MASTER_FINI;
seip->ctl_flags_rd_mask |= SG_CTL_FLAGM_MASTER_ERR;
- seip->ctl_flags_rd_mask |= SG_CTL_FLAGM_CHECK_FOR_MORE;
seip->ctl_flags |= SG_CTL_FLAGM_TIME_IN_NS;
if (ioctl(sg_fd, SG_SET_GET_EXTENDED, seip) < 0) {
@@ -286,9 +298,6 @@
if (SG_CTL_FLAGM_MASTER_ERR & seip->ctl_flags_rd_mask)
printf(" %sMASTER_ERR: %s\n", cp,
(SG_CTL_FLAGM_MASTER_ERR & cflags) ? "true" : "false");
- if (SG_CTL_FLAGM_CHECK_FOR_MORE & seip->ctl_flags_rd_mask)
- printf(" %sCHECK_FOR_MORE: %s\n", cp,
- (SG_CTL_FLAGM_CHECK_FOR_MORE & cflags) ? "true" : "false");
}
if (SG_SEIM_MINOR_INDEX & seip->sei_rd_mask)
printf(" %sminor_index: %u\n", cp, seip->minor_index);
@@ -437,14 +446,134 @@
return 0;
}
-#include <linux/fs.h>
-#include <linux/blktrace_api.h>
+static int
+do_mrqs(int sg_fd, int sg_fd2, int mrqs)
+{
+ bool both = (sg_fd2 >= 0);
+ int k, arr_v4_sz, good;
+ int res = 0;
+ struct sg_io_v4 * arr_v4;
+ struct sg_io_v4 * h4p;
+ struct sg_io_v4 * mrq_h4p;
+ struct sg_io_v4 mrq_h4;
+ uint8_t sense_buffer[SENSE_BUFFER_LEN];
+ uint8_t inq_cdb[INQ_CMD_LEN] = /* Device Id VPD page */
+ {0x12, 0x1, 0x83, 0, INQ_REPLY_LEN, 0};
+ uint8_t sdiag_cdb[SDIAG_CMD_LEN] =
+ {0x1d, 0x10 /* PF */, 0, 0, 0, 0};
+ uint8_t inqBuff[INQ_REPLY_LEN];
+
+ if (both) {
+ struct sg_extended_info sei;
+ struct sg_extended_info * seip;
+
+ seip = &sei;
+ memset(seip, 0, sizeof(*seip));
+ seip->sei_wr_mask |= SG_SEIM_SHARE_FD;
+ seip->sei_rd_mask |= SG_SEIM_SHARE_FD;
+ seip->share_fd = sg_fd; /* master */
+ if (ioctl(sg_fd2, SG_SET_GET_EXTENDED, seip) < 0) {
+ res = errno;
+ pr2serr("ioctl(sg_fd2, SG_SET_GET_EXTENDED) shared_fd, "
+ "failed errno=%d %s\n", res, strerror(res));
+ return res;
+ }
+ }
+ memset(inqBuff, 0, sizeof(inqBuff));
+ mrq_h4p = &mrq_h4;
+ memset(mrq_h4p, 0, sizeof(*mrq_h4p));
+ mrq_h4p->guard = 'Q';
+ mrq_h4p->flags = SGV4_FLAG_MULTIPLE_REQS;
+ if (mrq_immed)
+ mrq_h4p->flags |= SGV4_FLAG_IMMED;
+ arr_v4 = calloc(mrqs, sizeof(struct sg_io_v4));
+ if (NULL == arr_v4) {
+ res = ENOMEM;
+ goto fini;
+ }
+ arr_v4_sz = mrqs * sizeof(struct sg_io_v4);
+
+ for (k = 0; k < mrqs; ++k) {
+ h4p = arr_v4 + k;
+
+ h4p->guard = 'Q';
+ /* ->protocol and ->subprotocol are already zero */
+ /* io_hdr[k].iovec_count = 0; */ /* memset takes care of this */
+ if (0 == (k % 2)) {
+ h4p->request_len = sizeof(sdiag_cdb);
+ h4p->request = (uint64_t)sdiag_cdb;
+ /* all din and dout fields are zero */
+ } else {
+ h4p->request_len = sizeof(inq_cdb);
+ h4p->request = (uint64_t)inq_cdb;
+ h4p->din_xfer_len = INQ_REPLY_LEN;
+ h4p->din_xferp = (uint64_t)inqBuff;
+ if (both)
+ h4p->flags |= SGV4_FLAG_DO_ON_OTHER;
+ }
+ h4p->response = (uint64_t)sense_buffer;
+ h4p->max_response_len = sizeof(sense_buffer);
+ h4p->timeout = 20000; /* 20000 millisecs == 20 seconds */
+ h4p->request_extra = k + 3; /* so pack_id doesn't start at 0 */
+ /* default is to queue at head (in SCSI mid level) */
+ if (q_at_tail)
+ h4p->flags |= SG_FLAG_Q_AT_TAIL;
+ else
+ h4p->flags |= SG_FLAG_Q_AT_HEAD;
+ }
+ mrq_h4p->din_xferp = (uint64_t)arr_v4;
+ mrq_h4p->din_xfer_len = arr_v4_sz;
+ mrq_h4p->dout_xferp = mrq_h4p->din_xferp;
+ mrq_h4p->dout_xfer_len = mrq_h4p->din_xfer_len;
+ if (ioctl(sg_fd, (mrq_iosubmit ? SG_IOSUBMIT : SG_IO), mrq_h4p) < 0) {
+ res = errno;
+ pr2serr("ioctl(SG_IO%s, mrq) failed, errno=%d %s\n",
+ (mrq_iosubmit ? "SUBMIT" : ""), res, strerror(res));
+ goto fini;
+ }
+ if (mrq_immed) {
+mrq_h4p->flags = SGV4_FLAG_MULTIPLE_REQS; // zap SGV4_FLAG_IMMED
+ if (ioctl(sg_fd, SG_IORECEIVE, mrq_h4p) < 0) {
+ res = errno;
+ pr2serr("ioctl(SG_IORECEIVE, mrq) failed, errno=%d %s\n",
+ res, strerror(res));
+ goto fini;
+ }
+ }
+
+ for (k = 0, good = 0; k < mrqs; ++k) {
+ h4p = arr_v4 + k;
+ if (! (h4p->driver_status || h4p->transport_status ||
+ h4p->device_status)) {
+ if (h4p->info & SG_INFO_MRQ_FINI)
+ ++good;
+ }
+ }
+ if (good > 0) {
+ printf("Final INQUIRY response:\n");
+ hex2stdout(inqBuff, INQ_REPLY_LEN, 0);
+ }
+ printf("Good responses: %d, bad responses: %d\n", good, mrqs - good);
+ if (mrq_h4p->driver_status != 0)
+ printf("Master mrq object: driver_status=%d\n",
+ mrq_h4p->driver_status);
+ h4p = arr_v4 + mrqs - 1;
+ if (h4p->driver_status != 0)
+ printf("Last mrq object: driver_status=%d\n", h4p->driver_status);
+
+fini:
+ if (arr_v4)
+ free(arr_v4);
+ return res;
+}
+
int
main(int argc, char * argv[])
{
bool done;
int sg_fd, k, ok, ver_num, pack_id, num_waiting;
+ int res = 0;
int sg_fd2 = -1;
int sock = -1;
uint8_t inq_cdb[INQ_CMD_LEN] =
@@ -479,6 +608,26 @@
file_name = 0;
break;
}
+ } else if (0 == memcmp("-m=", argv[k], 3)) {
+ num_mrqs = sg_get_num(argv[k] + 3);
+ if (num_mrqs < 1) {
+ printf("Expect -m= to take a number greater than 0\n");
+ file_name = 0;
+ break;
+ }
+ if ((cp = strchr(argv[k] + 3, ','))) {
+ mrq_iosubmit = true;
+ if (toupper(cp[1]) == 'I')
+ mrq_immed = true;
+ else if (toupper(cp[1]) == 'S')
+ ;
+ else {
+ printf("-m= option expects 'A' or 'a' as a suffix, "
+ "after comma\n");
+ file_name = 0;
+ break;
+ }
+ }
} else if (0 == memcmp("-o", argv[k], 2))
ioctl_only = true;
else if (0 == memcmp("-r=", argv[k], 3)) {
@@ -562,6 +711,11 @@
second_fname, sg_fd2);
}
+ if (num_mrqs > 0) {
+ res = do_mrqs(sg_fd, sg_fd2, num_mrqs);
+ goto out;
+ }
+
if (do_fork) {
int pid;
int sv[2];
@@ -731,5 +885,5 @@
close(sg_fd);
if (sg_fd2 >= 0)
close(sg_fd2);
- return 0;
+ return res;
}