summaryrefslogtreecommitdiffstats
path: root/sys/dev/ata/atapi-cam.c
diff options
context:
space:
mode:
authorscottl <scottl@FreeBSD.org>2005-04-05 15:08:19 +0000
committerscottl <scottl@FreeBSD.org>2005-04-05 15:08:19 +0000
commit224fe6574bafae89368c757d51a02d00eb09b45c (patch)
tree11dc6375bd88f17742d86e143b17484e896e8667 /sys/dev/ata/atapi-cam.c
parent6435ce940d56f3abecd7ff6812b8dce00e260ee7 (diff)
downloadFreeBSD-src-224fe6574bafae89368c757d51a02d00eb09b45c.zip
FreeBSD-src-224fe6574bafae89368c757d51a02d00eb09b45c.tar.gz
Fix a use-after-free problem in atapi_cb(). Add some necessary synchronization
to the XPT_PATH_INQ op. Don't leak locks on failure in XPT_SCSIIO. Correctly fix the CAMDEBUG message.
Diffstat (limited to 'sys/dev/ata/atapi-cam.c')
-rw-r--r--sys/dev/ata/atapi-cam.c17
1 files changed, 13 insertions, 4 deletions
diff --git a/sys/dev/ata/atapi-cam.c b/sys/dev/ata/atapi-cam.c
index 6c3189f..4c5eaa7 100644
--- a/sys/dev/ata/atapi-cam.c
+++ b/sys/dev/ata/atapi-cam.c
@@ -340,9 +340,11 @@ atapi_action(struct cam_sim *sim, union ccb *ccb)
cpi->base_transfer_speed = 3300;
if (softc->ata_ch && tid != CAM_TARGET_WILDCARD) {
+ mtx_lock(&softc->state_lock);
if (softc->atadev[tid] == NULL) {
ccb->ccb_h.status = CAM_DEV_NOT_THERE;
xpt_done(ccb);
+ mtx_unlock(&softc->state_lock);
return;
}
switch (softc->atadev[ccb_h->target_id]->mode) {
@@ -375,6 +377,7 @@ atapi_action(struct cam_sim *sim, union ccb *ccb)
default:
break;
}
+ mtx_unlock(&softc->state_lock);
}
ccb->ccb_h.status = CAM_REQ_CMP;
xpt_done(ccb);
@@ -595,15 +598,19 @@ action_oom:
ata_free_request(request);
if (hcb != NULL)
free_hcb(hcb);
+ mtx_unlock(&softc->state_lock);
+ mtx_lock(&Giant);
xpt_print_path(ccb_h->path);
printf("out of memory, freezing queue.\n");
softc->flags |= RESOURCE_SHORTAGE;
xpt_freeze_simq(sim, /*count*/ 1);
+ mtx_unlock(&Giant);
ccb_h->status = CAM_REQUEUE_REQ;
xpt_done(ccb);
return;
action_invalid:
+ mtx_unlock(&softc->state_lock);
ccb_h->status = CAM_REQ_INVALID;
xpt_done(ccb);
return;
@@ -619,14 +626,16 @@ atapi_poll(struct cam_sim *sim)
static void
atapi_cb(struct ata_request *request)
{
+ struct atapi_xpt_softc *scp;
struct atapi_hcb *hcb;
struct ccb_scsiio *csio;
u_int32_t rc;
hcb = (struct atapi_hcb *)request->driver;
+ scp = hcb->softc;
csio = &hcb->ccb->csio;
-#ifdef XXXCAMDEBUG
+#ifdef CAMDEBUG
# define err (request->u.atapi.sense_key)
if (CAM_DEBUGGED(csio->ccb_h.path, CAM_DEBUG_CDB)) {
printf("atapi_cb: hcb@%p error = %02x: (sk = %02x%s%s%s)\n",
@@ -635,7 +644,7 @@ atapi_cb(struct ata_request *request)
(err & 2) ? " EOM" : "",
(err & 1) ? " ILI" : "");
printf("dev %s: cmd %02x status %02x result %02x\n",
- request->device->name, request->u.atapi.ccb[0],
+ device_get_nameunit(request->dev), request->u.atapi.ccb[0],
request->status, request->result);
}
#endif
@@ -685,9 +694,9 @@ atapi_cb(struct ata_request *request)
}
}
- mtx_lock(&hcb->softc->state_lock);
+ mtx_lock(&scp->state_lock);
free_hcb_and_ccb_done(hcb, rc);
- mtx_unlock(&hcb->softc->state_lock);
+ mtx_unlock(&scp->state_lock);
ata_free_request(request);
}
OpenPOWER on IntegriCloud