diff options
author | scottl <scottl@FreeBSD.org> | 2014-01-07 01:51:48 +0000 |
---|---|---|
committer | scottl <scottl@FreeBSD.org> | 2014-01-07 01:51:48 +0000 |
commit | cd4455d63815797dee4bd5d2fbe903ace2888a8f (patch) | |
tree | e4a932aed55b2e611c4a7cbe18560be7eb0cd1f1 /sys/cam/scsi/scsi_ch.c | |
parent | 0a34594b9cd7c8b87f719ed058da6be2b756a8e5 (diff) | |
download | FreeBSD-src-cd4455d63815797dee4bd5d2fbe903ace2888a8f.zip FreeBSD-src-cd4455d63815797dee4bd5d2fbe903ace2888a8f.tar.gz |
MFC Alexander Motin's direct dispatch, multi-queue, and finer-grained
locking support for CAM
r256826:
Fix several target mode SIMs to not blindly clear ccb_h.flags field of
ATIO CCBs. Not all CCB flags there belong to them.
r256836:
Remove hard limit on number of BIOs handled with one ATA TRIM request.
r256843:
Merge CAM locking changes from the projects/camlock branch to radically
reduce lock congestion and improve SMP scalability of the SCSI/ATA stack,
preparing the ground for the coming next GEOM direct dispatch support.
r256888:
Unconditionally acquire periph reference on CCB allocation failure.
r256895:
Fix memory and references leak due to unfreed path.
r256960:
Move CAM_UNQUEUED_INDEX setting to the last moment and under the periph lock.
This fixes race condition with cam_periph_ccbwait(), causing use-after-free.
r256975:
Minor (mostly cosmetical) addition to r256960.
r257054:
Some microoptimizations for da and ada drivers:
- Replace ordered_tag_count counter with single flag;
- From da remove outstanding_cmds counter, duplicating pending_ccbs list;
- From da_softc remove unused links field.
r257482:
Fix lock recursion, triggered by `smartctl -a /dev/adaX`.
r257501:
Make getenv_*() functions and respectively TUNABLE_*_FETCH() macros not
allocate memory and so not require sleepable environment. getenv() has
already used on-stack temporary storage, so just use it more rationally.
getenv_string() receives buffer as argument, so don't need another one.
r257914:
Some CAM locks polishing:
- Fix LOR and possible lock recursion when handling high-power commands.
Introduce new lock to protect left power quota and list of frozen devices.
- Correct locking around xpt periph creation.
- Remove seems never used XPT_FLAG_OPEN xpt periph flag.
Again, Netflix assisted with testing the merge, but all of the credit goes
to Alexander and iX Systems.
Submitted by: mav
Sponsored by: iX Systems
Diffstat (limited to 'sys/cam/scsi/scsi_ch.c')
-rw-r--r-- | sys/cam/scsi/scsi_ch.c | 49 |
1 files changed, 15 insertions, 34 deletions
diff --git a/sys/cam/scsi/scsi_ch.c b/sys/cam/scsi/scsi_ch.c index fb208ed..b83bc53 100644 --- a/sys/cam/scsi/scsi_ch.c +++ b/sys/cam/scsi/scsi_ch.c @@ -116,8 +116,7 @@ typedef enum { } ch_state; typedef enum { - CH_CCB_PROBE, - CH_CCB_WAITING + CH_CCB_PROBE } ch_ccb_types; typedef enum { @@ -248,20 +247,19 @@ chinit(void) static void chdevgonecb(void *arg) { - struct cam_sim *sim; struct ch_softc *softc; struct cam_periph *periph; + struct mtx *mtx; int i; periph = (struct cam_periph *)arg; - sim = periph->sim; - softc = (struct ch_softc *)periph->softc; + mtx = cam_periph_mtx(periph); + mtx_lock(mtx); + softc = (struct ch_softc *)periph->softc; KASSERT(softc->open_count >= 0, ("Negative open count %d", softc->open_count)); - mtx_lock(sim->mtx); - /* * When we get this callback, we will get no more close calls from * devfs. So if we have any dangling opens, we need to release the @@ -278,13 +276,13 @@ chdevgonecb(void *arg) cam_periph_release_locked(periph); /* - * We reference the SIM lock directly here, instead of using + * We reference the lock directly here, instead of using * cam_periph_unlock(). The reason is that the final call to * cam_periph_release_locked() above could result in the periph * getting freed. If that is the case, dereferencing the periph * with a cam_periph_unlock() call would cause a page fault. */ - mtx_unlock(sim->mtx); + mtx_unlock(mtx); } static void @@ -350,7 +348,7 @@ chasync(void *callback_arg, u_int32_t code, struct cam_path *path, void *arg) */ status = cam_periph_alloc(chregister, choninvalidate, chcleanup, chstart, "ch", - CAM_PERIPH_BIO, cgd->ccb_h.path, + CAM_PERIPH_BIO, path, chasync, AC_FOUND_DEVICE, cgd); if (status != CAM_REQ_CMP @@ -503,25 +501,23 @@ chopen(struct cdev *dev, int flags, int fmt, struct thread *td) static int chclose(struct cdev *dev, int flag, int fmt, struct thread *td) { - struct cam_sim *sim; struct cam_periph *periph; struct ch_softc *softc; + struct mtx *mtx; periph = (struct cam_periph *)dev->si_drv1; if (periph == NULL) return(ENXIO); + mtx = cam_periph_mtx(periph); + mtx_lock(mtx); - sim = periph->sim; softc = (struct ch_softc *)periph->softc; - - mtx_lock(sim->mtx); - softc->open_count--; cam_periph_release_locked(periph); /* - * We reference the SIM lock directly here, instead of using + * We reference the lock directly here, instead of using * cam_periph_unlock(). The reason is that the call to * cam_periph_release_locked() above could result in the periph * getting freed. If that is the case, dereferencing the periph @@ -532,7 +528,7 @@ chclose(struct cdev *dev, int flag, int fmt, struct thread *td) * protect the open count and avoid another lock acquisition and * release. */ - mtx_unlock(sim->mtx); + mtx_unlock(mtx); return(0); } @@ -547,14 +543,7 @@ chstart(struct cam_periph *periph, union ccb *start_ccb) switch (softc->state) { case CH_STATE_NORMAL: { - if (periph->immediate_priority <= periph->pinfo.priority){ - start_ccb->ccb_h.ccb_state = CH_CCB_WAITING; - - SLIST_INSERT_HEAD(&periph->ccb_list, &start_ccb->ccb_h, - periph_links.sle); - periph->immediate_priority = CAM_PRIORITY_NONE; - wakeup(&periph->ccb_list); - } + xpt_release_ccb(start_ccb); break; } case CH_STATE_PROBE: @@ -734,12 +723,6 @@ chdone(struct cam_periph *periph, union ccb *done_ccb) cam_periph_unhold(periph); return; } - case CH_CCB_WAITING: - { - /* Caller will release the CCB */ - wakeup(&done_ccb->ccb_h.cbfcnp); - return; - } default: break; } @@ -1724,10 +1707,8 @@ chscsiversion(struct cam_periph *periph) struct scsi_inquiry_data *inq_data; struct ccb_getdev *cgd; int dev_scsi_version; - struct cam_sim *sim; - sim = xpt_path_sim(periph->path); - mtx_assert(sim->mtx, MA_OWNED); + cam_periph_assert(periph, MA_OWNED); if ((cgd = (struct ccb_getdev *)xpt_alloc_ccb_nowait()) == NULL) return (-1); /* |