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>