Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 7 May 2013 13:33:45 +0000 (UTC)
From:      Alexander Motin <mav@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r250331 - projects/camlock/sys/cam
Message-ID:  <201305071333.r47DXjCe015697@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mav
Date: Tue May  7 13:33:45 2013
New Revision: 250331
URL: http://svnweb.freebsd.org/changeset/base/250331

Log:
  Another round of CCB allocation changes:
   - Make allocation periph-centric by removing device level allocation queue.
  Aside from code simplification that makes CCB allocation almost indifferent
  to periph locking, allowing different periphs to use different locks.
   - Restore cam_periph_getccb() to respect number of allocation openings
  (now they are per-periph) to avoid unlimited kernel resources usage.

Modified:
  projects/camlock/sys/cam/cam_periph.c
  projects/camlock/sys/cam/cam_periph.h
  projects/camlock/sys/cam/cam_queue.c
  projects/camlock/sys/cam/cam_queue.h
  projects/camlock/sys/cam/cam_xpt.c

Modified: projects/camlock/sys/cam/cam_periph.c
==============================================================================
--- projects/camlock/sys/cam/cam_periph.c	Tue May  7 12:39:14 2013	(r250330)
+++ projects/camlock/sys/cam/cam_periph.c	Tue May  7 13:33:45 2013	(r250331)
@@ -196,14 +196,16 @@ cam_periph_alloc(periph_ctor_t *periph_c
 	path_id = xpt_path_path_id(path);
 	target_id = xpt_path_target_id(path);
 	lun_id = xpt_path_lun_id(path);
-	cam_init_pinfo(&periph->pinfo);
 	periph->periph_start = periph_start;
 	periph->periph_dtor = periph_dtor;
 	periph->periph_oninval = periph_oninvalidate;
 	periph->type = type;
 	periph->periph_name = name;
+	periph->scheduled_priority = CAM_PRIORITY_NONE;
+	periph->immediate_priority = CAM_PRIORITY_NONE;
 	periph->refcount = 1;		/* Dropped by invalidation. */
 	periph->sim = sim;
+	SLIST_INIT(&periph->ccb_list);
 	mtx_init(&periph->periph_mtx, "CAM periph lock", NULL, MTX_DEF);
 	status = xpt_create_path(&path, periph, path_id, target_id, lun_id);
 	if (status != CAM_REQ_CMP)

Modified: projects/camlock/sys/cam/cam_periph.h
==============================================================================
--- projects/camlock/sys/cam/cam_periph.h	Tue May  7 12:39:14 2013	(r250330)
+++ projects/camlock/sys/cam/cam_periph.h	Tue May  7 13:33:45 2013	(r250331)
@@ -103,7 +103,6 @@ typedef cam_status	periph_ctor_t (struct
 typedef void		periph_oninv_t (struct cam_periph *periph);
 typedef void		periph_dtor_t (struct cam_periph *periph);
 struct cam_periph {
-	cam_pinfo		 pinfo;
 	periph_start_t		*periph_start;
 	periph_oninv_t		*periph_oninval;
 	periph_dtor_t		*periph_dtor;
@@ -121,7 +120,12 @@ struct cam_periph {
 #define CAM_PERIPH_NEW_DEV_FOUND	0x10
 #define CAM_PERIPH_RECOVERY_INPROG	0x20
 #define CAM_PERIPH_FREE			0x80
+	uint32_t		 scheduled_priority;
+	uint32_t		 immediate_priority;
+	int			 periph_allocating;
+	int			 periph_allocated;
 	u_int32_t		 refcount;
+	SLIST_HEAD(, ccb_hdr)	 ccb_list;	/* For "immediate" requests */
 	SLIST_ENTRY(cam_periph)  periph_links;
 	TAILQ_ENTRY(cam_periph)  unit_links;
 	ac_callback_t		*deferred_callback; 

Modified: projects/camlock/sys/cam/cam_queue.c
==============================================================================
--- projects/camlock/sys/cam/cam_queue.c	Tue May  7 12:39:14 2013	(r250330)
+++ projects/camlock/sys/cam/cam_queue.c	Tue May  7 13:33:45 2013	(r250331)
@@ -289,6 +289,7 @@ cam_ccbq_resize(struct cam_ccbq *ccbq, i
 	int delta;
 
 	delta = new_size - (ccbq->dev_active + ccbq->dev_openings);
+	ccbq->total_openings += delta;
 	ccbq->devq_openings += delta;
 	ccbq->dev_openings += delta;
 
@@ -306,6 +307,7 @@ cam_ccbq_init(struct cam_ccbq *ccbq, int
 	if (camq_init(&ccbq->queue,
 	    imax(64, 1 << fls(openings + openings / 2))) != 0)
 		return (1);
+	ccbq->total_openings = openings;
 	ccbq->devq_openings = openings;
 	ccbq->dev_openings = openings;
 	return (0);

Modified: projects/camlock/sys/cam/cam_queue.h
==============================================================================
--- projects/camlock/sys/cam/cam_queue.h	Tue May  7 12:39:14 2013	(r250330)
+++ projects/camlock/sys/cam/cam_queue.h	Tue May  7 13:33:45 2013	(r250331)
@@ -61,8 +61,8 @@ struct cam_ccbq {
 	struct	camq queue;
 	struct ccb_hdr_tailq	queue_extra_head;
 	int	queue_extra_entries;
+	int	total_openings;
 	int	devq_openings;
-	int	devq_allocating;
 	int	dev_openings;
 	int	dev_active;
 	int	held;

Modified: projects/camlock/sys/cam/cam_xpt.c
==============================================================================
--- projects/camlock/sys/cam/cam_xpt.c	Tue May  7 12:39:14 2013	(r250330)
+++ projects/camlock/sys/cam/cam_xpt.c	Tue May  7 13:33:45 2013	(r250331)
@@ -222,8 +222,8 @@ static void		xpt_async_bcast(struct asyn
 					void *async_arg);
 static path_id_t xptnextfreepathid(void);
 static path_id_t xptpathid(const char *sim_name, int sim_unit, int sim_bus);
-static union ccb *xpt_get_ccb(struct cam_ed *device);
-static void	 xpt_run_dev_allocq(struct cam_ed *device);
+static union ccb *xpt_get_ccb(struct cam_periph *periph);
+static void	 xpt_run_allocq(struct cam_periph *periph);
 static void	 xpt_run_devq(struct cam_devq *devq);
 static timeout_t xpt_release_devq_timeout;
 static void	 xpt_release_simq_timeout(void *arg) __unused;
@@ -297,7 +297,6 @@ static xpt_devicefunc_t	xptsetasyncfunc;
 static xpt_busfunc_t	xptsetasyncbusfunc;
 static cam_status	xptregister(struct cam_periph *periph,
 				    void *arg);
-static __inline int periph_is_queued(struct cam_periph *periph);
 static __inline int device_is_queued(struct cam_ed *device);
 
 static __inline int
@@ -325,12 +324,6 @@ xpt_schedule_devq(struct cam_devq *devq,
 }
 
 static __inline int
-periph_is_queued(struct cam_periph *periph)
-{
-	return (periph->pinfo.index != CAM_UNQUEUED_INDEX);
-}
-
-static __inline int
 device_is_queued(struct cam_ed *device)
 {
 	return (device->devq_entry.pinfo.index != CAM_UNQUEUED_INDEX);
@@ -3034,39 +3027,16 @@ xpt_polled_action(union ccb *start_ccb)
  * target device has space for more transactions.
  */
 void
-xpt_schedule(struct cam_periph *perph, u_int32_t new_priority)
+xpt_schedule(struct cam_periph *periph, u_int32_t new_priority)
 {
-	struct cam_ed *device;
 	struct cam_devq *devq;
-	int runq = 0;
 
-	CAM_DEBUG(perph->path, CAM_DEBUG_TRACE, ("xpt_schedule\n"));
-	device = perph->path->device;
-	devq = device->sim->devq;
+	CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("xpt_schedule\n"));
+	devq = periph->sim->devq;
 	mtx_lock(&devq->send_mtx);
-	if (periph_is_queued(perph)) {
-		/* Simply reorder based on new priority */
-		CAM_DEBUG(perph->path, CAM_DEBUG_SUBTRACE,
-			  ("   change priority to %d\n", new_priority));
-		if (new_priority < perph->pinfo.priority) {
-			camq_change_priority(&device->drvq,
-					     perph->pinfo.index,
-					     new_priority);
-			runq = 1;
-		}
-	} else {
-		/* New entry on the queue */
-		CAM_DEBUG(perph->path, CAM_DEBUG_SUBTRACE,
-			  ("   added periph to queue\n"));
-		perph->pinfo.priority = new_priority;
-		perph->pinfo.generation = ++device->drvq.generation;
-		camq_insert(&device->drvq, &perph->pinfo);
-		runq = 1;
-	}
-	if (runq != 0) {
-		CAM_DEBUG(perph->path, CAM_DEBUG_SUBTRACE,
-			  ("   calling xpt_run_dev_allocq\n"));
-		xpt_run_dev_allocq(device);
+	if (new_priority < periph->scheduled_priority) {
+		periph->scheduled_priority = new_priority;
+		xpt_run_allocq(periph);
 	}
 	mtx_unlock(&devq->send_mtx);
 }
@@ -3120,36 +3090,26 @@ xpt_schedule_dev(struct camq *queue, cam
 }
 
 static void
-xpt_run_dev_allocq(struct cam_ed *device)
+xpt_run_allocq(struct cam_periph *periph)
 {
+	struct cam_ed	*device;
 	struct cam_devq	*devq;
-	struct camq	*drvq;
+	uint32_t	 prio;
 
-	devq = device->sim->devq;
+	devq = periph->sim->devq;
 	mtx_assert(&devq->send_mtx, MA_OWNED);
-	if (device->ccbq.devq_allocating)
+	if (periph->periph_allocating)
 		return;
-	device->ccbq.devq_allocating = 1;
-	CAM_DEBUG_PRINT(CAM_DEBUG_XPT, ("xpt_run_dev_allocq(%p)\n", device));
-	drvq = &device->drvq;
-	while ((drvq->entries > 0) &&
-	    (device->ccbq.devq_openings > 0 ||
-	     CAMQ_GET_PRIO(drvq) <= CAM_PRIORITY_OOB)) {
-		union	ccb *work_ccb;
-		struct	cam_periph *drv;
-
-		KASSERT(drvq->entries > 0, ("xpt_run_dev_allocq: "
-		    "Device on queue without any work to do"));
-		if ((work_ccb = xpt_get_ccb(device)) != NULL) {
-			drv = (struct cam_periph*)camq_remove(drvq, CAMQ_HEAD);
-			xpt_setup_ccb(&work_ccb->ccb_h, drv->path,
-				      drv->pinfo.priority);
-			CAM_DEBUG_PRINT(CAM_DEBUG_XPT,
-					("calling periph start\n"));
-			mtx_unlock(&devq->send_mtx);
-			drv->periph_start(drv, work_ccb);
-			mtx_lock(&devq->send_mtx);
-		} else {
+	periph->periph_allocating = 1;
+	CAM_DEBUG_PRINT(CAM_DEBUG_XPT, ("xpt_run_allocq(%p)\n", periph));
+	device = periph->path->device;
+	while ((prio = min(periph->scheduled_priority,
+	    periph->immediate_priority)) != CAM_PRIORITY_NONE &&
+	    (periph->periph_allocated < device->ccbq.total_openings ||
+	     prio <= CAM_PRIORITY_OOB)) {
+		union	ccb *ccb;
+
+		if ((ccb = xpt_get_ccb(periph)) == NULL) {
 			/*
 			 * Malloc failure in alloc_ccb
 			 */
@@ -3161,8 +3121,24 @@ xpt_run_dev_allocq(struct cam_ed *device
 			 */
 			break;
 		}
+		xpt_setup_ccb(&ccb->ccb_h, periph->path, prio);
+		if (prio == periph->immediate_priority) {
+			periph->immediate_priority = CAM_PRIORITY_NONE;
+			CAM_DEBUG_PRINT(CAM_DEBUG_XPT,
+					("waking cam_periph_getccb()\n"));
+			SLIST_INSERT_HEAD(&periph->ccb_list, &ccb->ccb_h,
+					  periph_links.sle);
+			wakeup(&periph->ccb_list);
+		} else {
+			periph->scheduled_priority = CAM_PRIORITY_NONE;
+			CAM_DEBUG_PRINT(CAM_DEBUG_XPT,
+					("calling periph_start()\n"));
+			mtx_unlock(&devq->send_mtx);
+			periph->periph_start(periph, ccb);
+			mtx_lock(&devq->send_mtx);
+		}
 	}
-	device->ccbq.devq_allocating = 0;
+	periph->periph_allocating = 0;
 }
 
 static void
@@ -3721,17 +3697,20 @@ void
 xpt_release_ccb(union ccb *free_ccb)
 {
 	struct	 cam_ed *device;
-	struct cam_devq *devq;
+	struct	 cam_devq *devq;
+	struct	 cam_periph *periph;
 
 	CAM_DEBUG_PRINT(CAM_DEBUG_XPT, ("xpt_release_ccb\n"));
 	device = free_ccb->ccb_h.path->device;
 	devq = device->sim->devq;
+	periph = free_ccb->ccb_h.path->periph;
 
+	xpt_free_ccb(free_ccb);
 	mtx_lock(&devq->send_mtx);
+	periph->periph_allocated--;
 	cam_ccbq_release_opening(&device->ccbq);
-	xpt_run_dev_allocq(device);
+	xpt_run_allocq(periph);
 	mtx_unlock(&devq->send_mtx);
-	xpt_free_ccb(free_ccb);
 }
 
 /* Functions accessed by SIM drivers */
@@ -4319,32 +4298,41 @@ xpt_free_ccb(union ccb *free_ccb)
  * ccbs, we also return NULL.
  */
 static union ccb *
-xpt_get_ccb(struct cam_ed *device)
+xpt_get_ccb(struct cam_periph *periph)
 {
 	union ccb *new_ccb;
 
 	new_ccb = malloc(sizeof(*new_ccb), M_CAMCCB, M_NOWAIT);
 	if (new_ccb == NULL)
 		return (NULL);
-	cam_ccbq_take_opening(&device->ccbq);
+	periph->periph_allocated++;
+	cam_ccbq_take_opening(&periph->path->device->ccbq);
 	return (new_ccb);
 }
 
 union ccb *
 cam_periph_getccb(struct cam_periph *periph, u_int32_t priority)
 {
-	union ccb	*ccb;
-	struct cam_devq	*devq;
+	struct cam_devq *devq;
+	struct ccb_hdr *ccb_h;
 
-	cam_periph_unlock(periph);
-	ccb = malloc(sizeof(*ccb), M_CAMCCB, M_WAITOK);
-	cam_periph_lock(periph);
+	CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("cam_periph_getccb\n"));
 	devq = periph->sim->devq;
+	cam_periph_unlock(periph);
 	mtx_lock(&devq->send_mtx);
-	cam_ccbq_take_opening(&periph->path->device->ccbq);
-	xpt_setup_ccb(&ccb->ccb_h, periph->path, priority);
+	while ((ccb_h = SLIST_FIRST(&periph->ccb_list)) == NULL ||
+	    ccb_h->pinfo.priority != priority) {
+		if (priority < periph->immediate_priority) {
+			periph->immediate_priority = priority;
+			xpt_run_allocq(periph);
+		} else
+			mtx_sleep(&periph->ccb_list, &devq->send_mtx, PRIBIO,
+			    "cgticb", 0);
+	}
+	SLIST_REMOVE_HEAD(&periph->ccb_list, periph_links.sle);
 	mtx_unlock(&devq->send_mtx);
-	return (ccb);
+	cam_periph_lock(periph);
+	return ((union ccb *)ccb_h);
 }
 
 static void



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