Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 15 Jul 2011 21:30:51 +0000 (UTC)
From:      Matt Jacob <mjacob@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org
Subject:   svn commit: r224070 - stable/8/sys/cam/scsi
Message-ID:  <201107152130.p6FLUpqd096669@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mjacob
Date: Fri Jul 15 21:30:50 2011
New Revision: 224070
URL: http://svn.freebsd.org/changeset/base/224070

Log:
  MFC of 197332:
  
  Remember to unlock the peripheral prior to notifying the user. Make some
  allocations M_NOWAIT so that we don't try and sleep with a nested non-sleepable
  lock.
  
  This makes the userland scsi_target begin to function again.

Modified:
  stable/8/sys/cam/scsi/scsi_target.c
Directory Properties:
  stable/8/sys/   (props changed)
  stable/8/sys/amd64/include/xen/   (props changed)
  stable/8/sys/cddl/contrib/opensolaris/   (props changed)
  stable/8/sys/contrib/dev/acpica/   (props changed)
  stable/8/sys/contrib/pf/   (props changed)

Modified: stable/8/sys/cam/scsi/scsi_target.c
==============================================================================
--- stable/8/sys/cam/scsi/scsi_target.c	Fri Jul 15 21:08:58 2011	(r224069)
+++ stable/8/sys/cam/scsi/scsi_target.c	Fri Jul 15 21:30:50 2011	(r224070)
@@ -42,6 +42,9 @@ __FBSDID("$FreeBSD$");
 #include <sys/mutex.h>
 #include <sys/devicestat.h>
 #include <sys/proc.h>
+/* Includes to support callout */
+#include <sys/types.h>
+#include <sys/systm.h>
 
 #include <cam/cam.h>
 #include <cam/cam_ccb.h>
@@ -50,6 +53,7 @@ __FBSDID("$FreeBSD$");
 #include <cam/cam_sim.h>
 #include <cam/scsi/scsi_targetio.h>
 
+
 /* Transaction information attached to each CCB sent by the user */
 struct targ_cmd_descr {
 	struct cam_periph_map_info  mapinfo;
@@ -92,6 +96,8 @@ struct targ_softc {
 	targ_state		 state;
 	struct selinfo		 read_select;
 	struct devstat		 device_stats;
+	struct callout		destroy_dev_callout;
+	struct mtx		destroy_mtx;
 };
 
 static d_open_t		targopen;
@@ -151,6 +157,7 @@ static void		abort_all_pending(struct ta
 static void		notify_user(struct targ_softc *softc);
 static int		targcamstatus(cam_status status);
 static size_t		targccblen(xpt_opcode func_code);
+static void		targdestroy(void *);
 
 static struct periph_driver targdriver =
 {
@@ -208,10 +215,18 @@ targclose(struct cdev *dev, int flag, in
 	int    error;
 
 	softc = (struct targ_softc *)dev->si_drv1;
-	if ((softc->periph == NULL) ||
-	    (softc->state & TARG_STATE_LUN_ENABLED) == 0) {
+	mtx_init(&softc->destroy_mtx, "targ_destroy", "SCSI Target dev destroy", MTX_DEF);
+ 	callout_init_mtx(&softc->destroy_dev_callout, &softc->destroy_mtx, CALLOUT_RETURNUNLOCKED);
+	if (softc->periph == NULL) {
+#if 0
 		destroy_dev(dev);
 		free(softc, M_TARG);
+#endif
+		printf("%s: destroying non-enabled target\n", __func__);
+		mtx_lock(&softc->destroy_mtx);
+       		callout_reset(&softc->destroy_dev_callout, hz / 2,
+                        (void *)targdestroy, (void *)dev);
+		mtx_unlock(&softc->destroy_mtx);
 		return (0);
 	}
 
@@ -223,18 +238,23 @@ targclose(struct cdev *dev, int flag, in
 	cam_periph_acquire(periph);
 	cam_periph_lock(periph);
 	error = targdisable(softc);
-	if (error == CAM_REQ_CMP) {
-		dev->si_drv1 = 0;
-		if (softc->periph != NULL) {
-			cam_periph_invalidate(softc->periph);
-			softc->periph = NULL;
-		}
-		destroy_dev(dev);
-		free(softc, M_TARG);
+	if (softc->periph != NULL) {
+		cam_periph_invalidate(softc->periph);
+		softc->periph = NULL;
 	}
 	cam_periph_unlock(periph);
 	cam_periph_release(periph);
 
+#if 0
+	destroy_dev(dev);
+	free(softc, M_TARG);
+#endif
+
+	printf("%s: close finished error(%d)\n", __func__, error);
+	mtx_lock(&softc->destroy_mtx);
+      	callout_reset(&softc->destroy_dev_callout, hz / 2,
+		(void *)targdestroy, (void *)dev);
+	mtx_unlock(&softc->destroy_mtx);
 	return (error);
 }
 
@@ -818,7 +838,9 @@ targdone(struct cam_periph *periph, unio
 	case XPT_CONT_TARGET_IO:
 		TAILQ_INSERT_TAIL(&softc->user_ccb_queue, &done_ccb->ccb_h,
 				  periph_links.tqe);
+ 		cam_periph_unlock(softc->periph);
 		notify_user(softc);
+ 		cam_periph_lock(softc->periph);
 		break;
 	default:
 		panic("targdone: impossible xpt opcode %#x",
@@ -966,13 +988,19 @@ targgetccb(struct targ_softc *softc, xpt
 	int ccb_len;
 
 	ccb_len = targccblen(type);
-	ccb = malloc(ccb_len, M_TARG, M_WAITOK);
+	ccb = malloc(ccb_len, M_TARG, M_NOWAIT);
 	CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH, ("getccb %p\n", ccb));
-
+	if (ccb == NULL) {
+		return (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);
+	if (ccb->ccb_h.targ_descr == NULL) {
+		free (ccb, M_TARG);
+		ccb = NULL;
+	}
 	return (ccb);
 }
 
@@ -1010,8 +1038,10 @@ targgetdescr(struct targ_softc *softc)
 	struct targ_cmd_descr *descr;
 
 	descr = malloc(sizeof(*descr), M_TARG,
-	       M_WAITOK);
-	descr->mapinfo.num_bufs_used = 0;
+	       M_NOWAIT);
+	if (descr) {
+		descr->mapinfo.num_bufs_used = 0;
+	}
 	return (descr);
 }
 
@@ -1091,8 +1121,11 @@ abort_all_pending(struct targ_softc *sof
 
 	/* If we aborted anything from the work queue, wakeup user. */
 	if (!TAILQ_EMPTY(&softc->user_ccb_queue)
-	 || !TAILQ_EMPTY(&softc->abort_queue))
+	 || !TAILQ_EMPTY(&softc->abort_queue)) {
+		cam_periph_unlock(softc->periph);
 		notify_user(softc);
+		cam_periph_lock(softc->periph);
+	}
 }
 
 /* Notify the user that data is ready */
@@ -1185,3 +1218,25 @@ targccblen(xpt_opcode func_code)
 
 	return (len);
 }
+
+/*
+ * work around to destroy targ device
+ * outside of targclose
+ */
+static void
+targdestroy(void *dev)
+{
+	struct cdev *device = (struct cdev *)dev;
+	struct targ_softc *softc = (struct targ_softc *)device->si_drv1;
+
+#if 0
+	callout_stop(&softc->destroy_dev_callout);
+#endif
+
+	mtx_unlock(&softc->destroy_mtx);
+	mtx_destroy(&softc->destroy_mtx);
+	free(softc, M_TARG);
+	device->si_drv1 = 0;
+	destroy_dev(device);
+	printf("%s: destroyed dev\n", __func__);
+}



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201107152130.p6FLUpqd096669>