summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authormjacob <mjacob@FreeBSD.org>2010-08-11 17:25:14 +0000
committermjacob <mjacob@FreeBSD.org>2010-08-11 17:25:14 +0000
commit5688dd21e911eab4ec09be1089f77d8d58fff05c (patch)
treea9f21e6358ecd066e5121f8b511cb3cba153d318 /tools
parent6ee4bb3af6053dd233954048abe04480b15442c1 (diff)
downloadFreeBSD-src-5688dd21e911eab4ec09be1089f77d8d58fff05c.zip
FreeBSD-src-5688dd21e911eab4ec09be1089f77d8d58fff05c.tar.gz
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
Diffstat (limited to 'tools')
-rw-r--r--tools/tools/vhba/mptest/vhba_mptest.c83
-rw-r--r--tools/tools/vhba/vhba.c8
2 files changed, 73 insertions, 18 deletions
diff --git a/tools/tools/vhba/mptest/vhba_mptest.c b/tools/tools/vhba/mptest/vhba_mptest.c
index 865d80b..9a2ec85 100644
--- a/tools/tools/vhba/mptest/vhba_mptest.c
+++ b/tools/tools/vhba/mptest/vhba_mptest.c
@@ -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_scsiio *csio)
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_scsiio *csio)
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_scsiio *csio)
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_scsiio *csio)
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)
diff --git a/tools/tools/vhba/vhba.c b/tools/tools/vhba/vhba.c
index fd0dce6..3fdfe35 100644
--- a/tools/tools/vhba/vhba.c
+++ b/tools/tools/vhba/vhba.c
@@ -106,7 +106,7 @@ vhba_action(struct cam_sim *sim, union ccb *ccb)
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 ccb *ccb)
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, lun_id_t max_lun, uint8_t *sparse_lun_
{
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',
OpenPOWER on IntegriCloud