svn commit: r211183 - in head/tools/tools/vhba: . mptest

Matt Jacob mjacob at FreeBSD.org
Wed Aug 11 17:25:14 UTC 2010


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',


More information about the svn-src-all mailing list