PERFORCE change 118008 for review

Scott Long scottl at FreeBSD.org
Fri Apr 13 15:55:48 UTC 2007


http://perforce.freebsd.org/chv.cgi?CH=118008

Change 118008 by scottl at scottl-y1 on 2007/04/13 15:54:55

	Untested but hopefully functional locking for the target driver.

Affected files ...

.. //depot/projects/scottl-camlock/src/sys/cam/scsi/scsi_target.c#10 edit

Differences ...

==== //depot/projects/scottl-camlock/src/sys/cam/scsi/scsi_target.c#10 (text+ko) ====

@@ -47,6 +47,7 @@
 #include <cam/cam_ccb.h>
 #include <cam/cam_periph.h>
 #include <cam/cam_xpt_periph.h>
+#include <cam/cam_sim.h>
 #include <cam/scsi/scsi_targetio.h>
 
 /* Transaction information attached to each CCB sent by the user */
@@ -160,7 +161,11 @@
 
 static MALLOC_DEFINE(M_TARG, "TARG", "TARG data");
 
-/* Create softc and initialize it. Only one proc can open each targ device. */
+/*
+ * Create softc and initialize it. Only one proc can open each targ device.
+ * There is no locking here because a periph doesn't get created until an
+ * ioctl is issued to do so, and that can't happen until this method returns.
+ */
 static int
 targopen(struct cdev *dev, int flags, int fmt, struct thread *td)
 {
@@ -199,9 +204,24 @@
 targclose(struct cdev *dev, int flag, int fmt, struct thread *td)
 {
 	struct targ_softc     *softc;
+	struct cam_periph     *periph;
 	int    error;
 
 	softc = (struct targ_softc *)dev->si_drv1;
+	if ((softc->periph == NULL) ||
+	    (softc->state & TARG_STATE_LUN_ENABLED) == 0) {
+		destroy_dev(dev);
+		FREE(softc, M_TARG);
+		return (0);
+	}
+
+	/*
+	 * Acquire a hold on the periph so that it doesn't go away before
+	 * we are ready at the end of the function.
+	 */
+	periph = softc->periph;
+	cam_periph_acquire(periph);
+	cam_periph_lock(periph);
 	error = targdisable(softc);
 	if (error == CAM_REQ_CMP) {
 		dev->si_drv1 = 0;
@@ -212,6 +232,9 @@
 		destroy_dev(dev);
 		FREE(softc, M_TARG);
 	}
+	cam_periph_unlock(periph);
+	cam_periph_release(periph);
+
 	return (error);
 }
 
@@ -229,44 +252,56 @@
 	{
 		struct ioc_enable_lun	*new_lun;
 		struct cam_path		*path;
+		struct cam_sim		*sim;
 
 		new_lun = (struct ioc_enable_lun *)addr;
-		status = xpt_create_path(&path, /*periph*/NULL,
-					 new_lun->path_id,
-					 new_lun->target_id,
-					 new_lun->lun_id);
+		status = xpt_create_path_unlocked(&path, /*periph*/NULL,
+						  new_lun->path_id,
+						  new_lun->target_id,
+						  new_lun->lun_id);
 		if (status != CAM_REQ_CMP) {
 			printf("Couldn't create path, status %#x\n", status);
 			break;
 		}
+		sim = xpt_path_sim(path);
+		mtx_lock(sim->mtx);
 		status = targenable(softc, path, new_lun->grp6_len,
 				    new_lun->grp7_len);
 		xpt_free_path(path);
+		mtx_unlock(sim->mtx);
 		break;
 	}
 	case TARGIOCDISABLE:
+		if (softc->periph == NULL) {
+			status = CAM_DEV_NOT_THERE;
+			break;
+		}
+		cam_periph_lock(softc->periph);
 		status = targdisable(softc);
+		cam_periph_unlock(softc->periph);
 		break;
 	case TARGIOCDEBUG:
 	{
 #ifdef	CAMDEBUG
 		struct ccb_debug cdbg;
 
+		/* If no periph available, disallow debugging changes */
+		if ((softc->state & TARG_STATE_LUN_ENABLED) == 0) {
+			status = CAM_DEV_NOT_THERE;
+			break;
+		}
 		bzero(&cdbg, sizeof cdbg);
 		if (*((int *)addr) != 0)
 			cdbg.flags = CAM_DEBUG_PERIPH;
 		else
 			cdbg.flags = CAM_DEBUG_NONE;
+		cam_periph_lock(softc->periph);
 		xpt_setup_ccb(&cdbg.ccb_h, softc->path, /*priority*/0);
 		cdbg.ccb_h.func_code = XPT_DEBUG;
 		cdbg.ccb_h.cbfcnp = targdone;
 
-		/* If no periph available, disallow debugging changes */
-		if ((softc->state & TARG_STATE_LUN_ENABLED) == 0) {
-			status = CAM_DEV_NOT_THERE;
-			break;
-		}
 		xpt_action((union ccb *)&cdbg);
+		cam_periph_unlock(softc->periph);
 		status = cdbg.ccb_h.status & CAM_STATUS_MASK;
 #else
 		status = CAM_FUNC_NOTAVAIL;
@@ -294,10 +329,12 @@
 	revents = poll_events & (POLLOUT | POLLWRNORM);
 	if ((poll_events & (POLLIN | POLLRDNORM)) != 0) {
 		/* Poll for read() depends on user and abort queues. */
+		cam_periph_lock(softc->periph);
 		if (!TAILQ_EMPTY(&softc->user_ccb_queue) ||
 		    !TAILQ_EMPTY(&softc->abort_queue)) {
 			revents |= poll_events & (POLLIN | POLLRDNORM);
 		}
+		cam_periph_unlock(softc->periph);
 		/* Only sleep if the user didn't poll for write. */
 		if (revents == 0)
 			selrecord(td, &softc->read_select);
@@ -335,8 +372,10 @@
 	int	retval;
 
 	softc = (struct targ_softc *)kn->kn_hook;
+	cam_periph_lock(softc->periph);
 	retval = !TAILQ_EMPTY(&softc->user_ccb_queue) ||
 		 !TAILQ_EMPTY(&softc->abort_queue);
+	cam_periph_unlock(softc->periph);
 	return (retval);
 }
 
@@ -532,6 +571,7 @@
 		switch (func_code) {
 		case XPT_ACCEPT_TARGET_IO:
 		case XPT_IMMED_NOTIFY:
+			cam_periph_lock(softc->periph);
 			ccb = targgetccb(softc, func_code, priority);
 			descr = (struct targ_cmd_descr *)ccb->ccb_h.targ_descr;
 			descr->user_ccb = user_ccb;
@@ -542,8 +582,10 @@
 			TAILQ_INSERT_TAIL(&softc->pending_ccb_queue,
 					  &ccb->ccb_h,
 					  periph_links.tqe);
+			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",
@@ -569,6 +611,7 @@
 					targsendccb(softc, ccb, descr);
 				targreturnccb(softc, ccb);
 			}
+			cam_periph_unlock(softc->periph);
 			break;
 		}
 		write_len += sizeof(user_ccb);
@@ -796,8 +839,6 @@
 	union  ccb	  *user_ccb;
 	int		   read_len, error;
 
-	mtx_lock(&Giant);
-
 	error = 0;
 	read_len = 0;
 	softc = (struct targ_softc *)dev->si_drv1;
@@ -806,11 +847,12 @@
 	CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH, ("targread\n"));
 
 	/* If no data is available, wait or return immediately */
+	cam_periph_lock(softc->periph);
 	ccb_h = TAILQ_FIRST(user_queue);
 	user_descr = TAILQ_FIRST(abort_queue);
 	while (ccb_h == NULL && user_descr == NULL) {
 		if ((ioflag & IO_NDELAY) == 0) {
-			error = tsleep(user_queue,
+			error = msleep(user_queue, softc->periph->sim->mtx,
 			    PRIBIO | PCATCH, "targrd", 0);
 			ccb_h = TAILQ_FIRST(user_queue);
 			user_descr = TAILQ_FIRST(abort_queue);
@@ -822,7 +864,7 @@
 				}
 			}
 		} else {
-			mtx_unlock(&Giant);
+			cam_periph_unlock(softc->periph);
 			return (EAGAIN);
 		}
 	}
@@ -841,7 +883,9 @@
 		error = targreturnccb(softc, (union ccb *)ccb_h);
 		if (error != 0)
 			goto read_fail;
+		cam_periph_unlock(softc->periph);
 		error = uiomove((caddr_t)&user_ccb, sizeof(user_ccb), uio);
+		cam_periph_lock(softc->periph);
 		if (error != 0)
 			goto read_fail;
 		read_len += sizeof(user_ccb);
@@ -859,7 +903,9 @@
 			  ("targread aborted descr %p (%p)\n",
 			  user_descr, user_ccb));
 		suword(&user_ccb->ccb_h.status, CAM_REQ_ABORTED);
+		cam_periph_unlock(softc->periph);
 		error = uiomove((caddr_t)&user_ccb, sizeof(user_ccb), uio);
+		cam_periph_lock(softc->periph);
 		if (error != 0)
 			goto read_fail;
 		read_len += sizeof(user_ccb);
@@ -876,7 +922,7 @@
 		error = ENOSPC;
 
 read_fail:
-	mtx_unlock(&Giant);
+	cam_periph_unlock(softc->periph);
 	return (error);
 }
 


More information about the p4-projects mailing list