svn commit: r250331 - projects/camlock/sys/cam
Alexander Motin
mav at FreeBSD.org
Tue May 7 13:33:47 UTC 2013
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
More information about the svn-src-projects
mailing list