summaryrefslogtreecommitdiffstats
path: root/sys/cam/scsi/scsi_ch.c
diff options
context:
space:
mode:
authorscottl <scottl@FreeBSD.org>2014-01-07 01:51:48 +0000
committerscottl <scottl@FreeBSD.org>2014-01-07 01:51:48 +0000
commitcd4455d63815797dee4bd5d2fbe903ace2888a8f (patch)
treee4a932aed55b2e611c4a7cbe18560be7eb0cd1f1 /sys/cam/scsi/scsi_ch.c
parent0a34594b9cd7c8b87f719ed058da6be2b756a8e5 (diff)
downloadFreeBSD-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.c49
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);
/*
OpenPOWER on IntegriCloud