scsi_target witness lock error

Hidetoshi Shimokawa simokawa at FreeBSD.ORG
Tue Dec 11 18:17:29 PST 2007


Hi Sean,

At Tue, 11 Dec 2007 16:53:15 -0800,
Sean Bruno wrote:
> 
> While I was debugging some random stuff with the firewire target, I
> noted the following witness lock:
> 
> http://www.consultcsg.com/scsitarget_witness.txt
> 
> It looks like there is some kind of conflict between the locks in
> sys/cam/scsi/scsi_target.c and the kern environment locks?  I'm fairly
> certain that this is an easy fix, but I just don't see how to work
> around it.
> 
> Sean

This a patch I sent Scott several months ago.
It may help you. (this is for -current at that time)

/\ Hidetoshi Shimokawa
\/  simokawa at FreeBSD.ORG

Subject: scsi_target and WITNESS
From: Hidetoshi Shimokawa <simokawa at FreeBSD.ORG>
Date: Fri, 01 Jun 2007 11:57:50 +0900
Message-ID: <86vee8pej5.wl%simokawa at FreeBSD.ORG>

Hi Scott,

scsi_target seems to have several problems with WITNESS and MPSAFE sim.

I applied the following patch to workaround recurse/sleep/pagefault
problems. I think you should have a better fix.

=============================================
(cd /usr/src && patch -p6) < diff_to_current
=============================================
--- //depot/vendor/freebsd/src/sys/cam/scsi/scsi_target.c	2007/04/15 08:53:22
+++ //depot/user/simokawa/firewire_lock/sys/cam/scsi/scsi_target.c	2007/05/21 14:31:55
@@ -372,10 +372,14 @@
 	int	retval;
 
 	softc = (struct targ_softc *)kn->kn_hook;
+#if 0
 	cam_periph_lock(softc->periph);
+#endif
 	retval = !TAILQ_EMPTY(&softc->user_ccb_queue) ||
 		 !TAILQ_EMPTY(&softc->abort_queue);
+#if 0
 	cam_periph_unlock(softc->periph);
+#endif
 	return (retval);
 }
 
@@ -585,12 +589,12 @@
 			cam_periph_unlock(softc->periph);
 			break;
 		default:
-			cam_periph_lock(softc->periph);
 			if ((func_code & XPT_FC_QUEUED) != 0) {
 				CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH,
 					  ("Sending queued ccb %#x (%p)\n",
 					  func_code, user_ccb));
 				descr = targgetdescr(softc);
+				cam_periph_lock(softc->periph);
 				descr->user_ccb = user_ccb;
 				descr->priority = priority;
 				descr->func_code = func_code;
@@ -601,6 +605,7 @@
 				CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH,
 					  ("Sending inline ccb %#x (%p)\n",
 					  func_code, user_ccb));
+				cam_periph_lock(softc->periph);
 				ccb = targgetccb(softc, func_code, priority);
 				descr = (struct targ_cmd_descr *)
 					 ccb->ccb_h.targ_descr;
@@ -762,7 +767,9 @@
 	    && ((ccb_h->flags & CAM_DIR_MASK) != CAM_DIR_NONE))
 	  || (ccb_h->func_code == XPT_DEV_MATCH))) {
 
+		cam_periph_unlock(softc->periph);
 		error = cam_periph_mapmem(ccb, mapinfo);
+		cam_periph_lock(softc->periph);
 
 		/*
 		 * cam_periph_mapmem returned an error, we can't continue.
@@ -966,13 +973,16 @@
 	int ccb_len;
 
 	ccb_len = targccblen(type);
+	/* XXX */
+	cam_periph_unlock(softc->periph);
 	MALLOC(ccb, union ccb *, ccb_len, M_TARG, M_WAITOK);
+	ccb->ccb_h.targ_descr = targgetdescr(softc);
+	cam_periph_lock(softc->periph);
 	CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH, ("getccb %p\n", ccb));
 
 	xpt_setup_ccb(&ccb->ccb_h, softc->path, priority);
 	ccb->ccb_h.func_code = type;
 	ccb->ccb_h.cbfcnp = targdone;
-	ccb->ccb_h.targ_descr = targgetdescr(softc);
 	return (ccb);
 }
 
@@ -1099,6 +1109,7 @@
 static void
 notify_user(struct targ_softc *softc)
 {
+        mtx_assert(softc->periph->sim->mtx, MA_OWNED);
 	/*
 	 * Notify users sleeping via poll(), kqueue(), and
 	 * blocking read().




More information about the freebsd-firewire mailing list