Author: mjacob
Date: Wed Aug 11 17:25:14 2010
New Revision: 211183
URL: http://svn.freebsd.org/changeset/base/211183

Log:
  Consistently set us to be SPC3 for our inquiry data.
  
  For mptest, add delays to I/O that simulate real disks better. This
  also allows us to simulate what happens when a device goes away
  with active transactions. It's pretty spectacular.
  
  Sponsored by: Panasas
  MFC after:    1 month

Modified:
  head/tools/tools/vhba/mptest/vhba_mptest.c
  head/tools/tools/vhba/vhba.c

Modified: head/tools/tools/vhba/mptest/vhba_mptest.c
==============================================================================
--- head/tools/tools/vhba/mptest/vhba_mptest.c  Wed Aug 11 16:56:38 2010        
(r211182)
+++ head/tools/tools/vhba/mptest/vhba_mptest.c  Wed Aug 11 17:25:14 2010        
(r211183)
@@ -31,6 +31,17 @@
 #include "vhba.h"
 #include <sys/sysctl.h>
 
+static int vhba_stop_lun;
+static int vhba_start_lun = 0;
+static int vhba_notify_stop = 1;
+static int vhba_notify_start = 1;
+static int vhba_inject_hwerr = 0;
+SYSCTL_INT(_debug, OID_AUTO, vhba_stop_lun, CTLFLAG_RW, &vhba_stop_lun, 0, 
"stop lun bitmap");
+SYSCTL_INT(_debug, OID_AUTO, vhba_start_lun, CTLFLAG_RW, &vhba_start_lun, 0, 
"start lun bitmap");
+SYSCTL_INT(_debug, OID_AUTO, vhba_notify_stop, CTLFLAG_RW, &vhba_notify_stop, 
1, "notify when luns go away");
+SYSCTL_INT(_debug, OID_AUTO, vhba_notify_start, CTLFLAG_RW, 
&vhba_notify_start, 1, "notify when luns arrive");
+SYSCTL_INT(_debug, OID_AUTO, vhba_inject_hwerr, CTLFLAG_RW, 
&vhba_inject_hwerr, 0, "inject hardware error on lost luns");
+
 #define        MAX_TGT         1
 #define        MAX_LUN         2
 #define        VMP_TIME        hz
@@ -49,8 +60,11 @@ typedef struct {
        int             luns[2];
        struct callout  tick;
        struct task     qt;
+       TAILQ_HEAD(, ccb_hdr)   inproc;
+       int             nact, nact_high;
 } mptest_t;
 
+static timeout_t vhba_iodelay;
 static timeout_t vhba_timer;
 static void vhba_task(void *, int);
 static void mptest_act(mptest_t *, struct ccb_scsiio *);
@@ -59,13 +73,17 @@ void
 vhba_init(vhba_softc_t *vhba)
 {
        static mptest_t vhbastatic;
+
        vhbastatic.vhba = vhba;
        vhbastatic.disk_size = DISK_SIZE << 20;
        vhbastatic.disk = malloc(vhbastatic.disk_size, M_DEVBUF, 
M_WAITOK|M_ZERO);
        vhba->private = &vhbastatic;
        callout_init_mtx(&vhbastatic.tick, &vhba->lock, 0);
        callout_reset(&vhbastatic.tick, VMP_TIME, vhba_timer, vhba);
+       TAILQ_INIT(&vhbastatic.inproc);
        TASK_INIT(&vhbastatic.qt, 0, vhba_task, &vhbastatic);
+       vhbastatic.luns[0] = 1;
+       vhbastatic.luns[1] = 1;
 }
 
 void
@@ -89,15 +107,23 @@ vhba_task(void *arg, int pending)
 {
        mptest_t *vhbas = arg;
        struct ccb_hdr *ccbh;
+       int nadded = 0;
 
        mtx_lock(&vhbas->vhba->lock);
        while ((ccbh = TAILQ_FIRST(&vhbas->vhba->actv)) != NULL) {
                TAILQ_REMOVE(&vhbas->vhba->actv, ccbh, sim_links.tqe);
                 mptest_act(vhbas, (struct ccb_scsiio *)ccbh);
+               nadded++;
+               ccbh->sim_priv.entries[0].ptr = vhbas;
+               callout_handle_init(&ccbh->timeout_ch);
        }
-       while ((ccbh = TAILQ_FIRST(&vhbas->vhba->done)) != NULL) {
-               TAILQ_REMOVE(&vhbas->vhba->done, ccbh, sim_links.tqe);
-               xpt_done((union ccb *)ccbh);
+       if (nadded) {
+               vhba_kick(vhbas->vhba);
+       } else {
+               while ((ccbh = TAILQ_FIRST(&vhbas->vhba->done)) != NULL) {
+                       TAILQ_REMOVE(&vhbas->vhba->done, ccbh, sim_links.tqe);
+                       xpt_done((union ccb *)ccbh);
+               }
        }
        mtx_unlock(&vhbas->vhba->lock);
 }
@@ -108,10 +134,10 @@ mptest_act(mptest_t *vhbas, struct ccb_s
        char junk[128];
        cam_status camstatus;
        uint8_t *cdb, *ptr, status;
-       uint32_t data_len;
+       uint32_t data_len, blkcmd;
        uint64_t off;
            
-       data_len = 0;
+       blkcmd = data_len = 0;
        status = SCSI_STATUS_OK;
 
        memset(&csio->sense_data, 0, sizeof (csio->sense_data));
@@ -122,6 +148,11 @@ mptest_act(mptest_t *vhbas, struct ccb_s
                TAILQ_INSERT_TAIL(&vhbas->vhba->done, &csio->ccb_h, 
sim_links.tqe);
                return;
        }
+       if (vhba_inject_hwerr && csio->ccb_h.target_lun < MAX_LUN && 
vhbas->luns[csio->ccb_h.target_lun] == 0) {
+               vhba_fill_sense(csio, SSD_KEY_HARDWARE_ERROR, 0x44, 0x0);
+               TAILQ_INSERT_TAIL(&vhbas->vhba->done, &csio->ccb_h, 
sim_links.tqe);
+               return;
+       }
        if ((csio->ccb_h.target_lun >= MAX_LUN || 
vhbas->luns[csio->ccb_h.target_lun] == 0) && cdb[0] != INQUIRY && cdb[0] != 
REPORT_LUNS && cdb[0] != REQUEST_SENSE) {
                vhba_fill_sense(csio, SSD_KEY_ILLEGAL_REQUEST, 0x25, 0x0);
                TAILQ_INSERT_TAIL(&vhbas->vhba->done, &csio->ccb_h, 
sim_links.tqe);
@@ -284,6 +315,11 @@ mptest_act(mptest_t *vhbas, struct ccb_s
                        vhba_fill_sense(csio, SSD_KEY_ILLEGAL_REQUEST, 0x24, 
0x0);
                        break;
                }
+               blkcmd++;
+               if (++vhbas->nact > vhbas->nact_high) {
+                       vhbas->nact_high = vhbas->nact;
+                       printf("%s: high block count now %d\n", __func__, 
vhbas->nact);
+               }
                if (data_len) {
                        if ((cdb[0] & 0xf) == 8) {
                                memcpy(csio->data_ptr, &vhbas->disk[off], 
data_len);
@@ -339,17 +375,36 @@ mptest_act(mptest_t *vhbas, struct ccb_s
                camstatus = CAM_REQ_CMP;
        }
        vhba_set_status(&csio->ccb_h, camstatus);
-       TAILQ_INSERT_TAIL(&vhbas->vhba->done, &csio->ccb_h, sim_links.tqe);
+       if (blkcmd) {
+               int ticks;
+               struct timeval t;
+
+               TAILQ_INSERT_TAIL(&vhbas->inproc, &csio->ccb_h, sim_links.tqe);
+               t.tv_sec = 0;
+               t.tv_usec = (500 + arc4random());
+               if (t.tv_usec > 10000) {
+                       t.tv_usec = 10000;
+               }
+               ticks = tvtohz(&t);
+               csio->ccb_h.timeout_ch = timeout(vhba_iodelay, &csio->ccb_h, 
ticks);
+       } else {
+               TAILQ_INSERT_TAIL(&vhbas->vhba->done, &csio->ccb_h, 
sim_links.tqe);
+       }
 }
 
-static int vhba_stop_lun;
-SYSCTL_INT(_debug, OID_AUTO, vhba_stop_lun, CTLFLAG_RW, &vhba_stop_lun, 0, 
"stop this lun");
-static int vhba_start_lun = 3;
-SYSCTL_INT(_debug, OID_AUTO, vhba_start_lun, CTLFLAG_RW, &vhba_start_lun, 3, 
"start this lun");
-static int vhba_notify_stop = 1;
-SYSCTL_INT(_debug, OID_AUTO, vhba_notify_stop, CTLFLAG_RW, &vhba_notify_stop, 
1, "notify when luns go away");
-static int vhba_notify_start = 1;
-SYSCTL_INT(_debug, OID_AUTO, vhba_notify_start, CTLFLAG_RW, 
&vhba_notify_start, 1, "notify when luns arrive");
+static void
+vhba_iodelay(void *arg)
+{
+       struct ccb_hdr *ccbh = arg;
+       mptest_t *vhbas = ccbh->sim_priv.entries[0].ptr;
+
+       mtx_lock(&vhbas->vhba->lock);
+       TAILQ_REMOVE(&vhbas->inproc, ccbh, sim_links.tqe);
+       TAILQ_INSERT_TAIL(&vhbas->vhba->done, ccbh, sim_links.tqe);
+       vhbas->nact -= 1;
+       vhba_kick(vhbas->vhba);
+       mtx_unlock(&vhbas->vhba->lock);
+}
 
 static void
 vhba_timer(void *arg)

Modified: head/tools/tools/vhba/vhba.c
==============================================================================
--- head/tools/tools/vhba/vhba.c        Wed Aug 11 16:56:38 2010        
(r211182)
+++ head/tools/tools/vhba/vhba.c        Wed Aug 11 17:25:14 2010        
(r211183)
@@ -106,7 +106,7 @@ vhba_action(struct cam_sim *sim, union c
 
        case XPT_GET_TRAN_SETTINGS:
                cts = &ccb->cts;
-               cts->protocol_version = SCSI_REV_SPC2;
+               cts->protocol_version = SCSI_REV_SPC3;
                cts->protocol = PROTO_SCSI;
                cts->transport_version = 0;
                cts->transport = XPORT_PPB;
@@ -133,7 +133,7 @@ vhba_action(struct cam_sim *sim, union c
                cpi->transport = XPORT_PPB;
                cpi->base_transfer_speed = 1000000;
                cpi->protocol = PROTO_SCSI;
-               cpi->protocol_version = SCSI_REV_SPC2;
+               cpi->protocol_version = SCSI_REV_SPC3;
                strlcpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
                strlcpy(cpi->hba_vid, "FakeHBA", HBA_IDLEN);
                strlcpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
@@ -235,14 +235,14 @@ vhba_default_cmd(struct ccb_scsiio *csio
 {
        char junk[128];
        const uint8_t niliqd[SHORT_INQUIRY_LENGTH] = {
-               0x7f, 0x0, 0x5, 0x2, 32, 0, 0, 0x32,
+               0x7f, 0x0, SCSI_REV_SPC3, 0x2, 32, 0, 0, 0x32,
                'P', 'A', 'N', 'A', 'S', 'A', 'S', ' ',
                'N', 'U', 'L', 'L', ' ', 'D', 'E', 'V',
                'I', 'C', 'E', ' ', ' ', ' ', ' ', ' ',
                '0', '0', '0', '1'
        };
        const uint8_t iqd[SHORT_INQUIRY_LENGTH] = {
-               0, 0x0, 0x5, 0x2, 32, 0, 0, 0x32,
+               0, 0x0, SCSI_REV_SPC3, 0x2, 32, 0, 0, 0x32,
                'P', 'A', 'N', 'A', 'S', 'A', 'S', ' ',
                'V', 'I', 'R', 'T', ' ', 'M', 'E', 'M',
                'O', 'R', 'Y', ' ', 'D', 'I', 'S', 'K',
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to