svn commit: r254369 - in projects/camlock/sys/cam: ata scsi
Alexander Motin
mav at FreeBSD.org
Thu Aug 15 15:12:15 UTC 2013
Author: mav
Date: Thu Aug 15 15:12:14 2013
New Revision: 254369
URL: http://svnweb.freebsd.org/changeset/base/254369
Log:
Make da(4) and ada(4) drivers call biodone() without holding any locks.
That both reduces lock hold time improving performance, and makes devices
reenterable, that may be needed for direct-dispatching GEOM.
As side effect this removes limit on number of BIO_DELETEs aggregated in
single ATA TRIM command.
Modified:
projects/camlock/sys/cam/ata/ata_da.c
projects/camlock/sys/cam/scsi/scsi_da.c
Modified: projects/camlock/sys/cam/ata/ata_da.c
==============================================================================
--- projects/camlock/sys/cam/ata/ata_da.c Thu Aug 15 14:41:39 2013 (r254368)
+++ projects/camlock/sys/cam/ata/ata_da.c Thu Aug 15 15:12:14 2013 (r254369)
@@ -122,10 +122,9 @@ struct disk_params {
#define TRIM_MAX_BLOCKS 8
#define TRIM_MAX_RANGES (TRIM_MAX_BLOCKS * ATA_DSM_BLK_RANGES)
-#define TRIM_MAX_BIOS (TRIM_MAX_RANGES * 4)
struct trim_request {
uint8_t data[TRIM_MAX_RANGES * ATA_DSM_RANGE_SIZE];
- struct bio *bps[TRIM_MAX_BIOS];
+ TAILQ_HEAD(, bio) bps;
};
struct ada_softc {
@@ -1375,10 +1374,11 @@ adastart(struct cam_periph *periph, unio
struct trim_request *req = &softc->trim_req;
struct bio *bp1;
uint64_t lastlba = (uint64_t)-1;
- int bps = 0, c, lastcount = 0, off, ranges = 0;
+ int c, lastcount = 0, off, ranges = 0;
softc->trim_running = 1;
bzero(req, sizeof(*req));
+ TAILQ_INIT(&req->bps);
bp1 = bp;
do {
uint64_t lba = bp1->bio_pblkno;
@@ -1421,10 +1421,9 @@ adastart(struct cam_periph *periph, unio
*/
}
lastlba = lba;
- req->bps[bps++] = bp1;
+ TAILQ_INSERT_TAIL(&req->bps, bp1, bio_queue);
bp1 = bioq_first(&softc->trim_queue);
- if (bps >= TRIM_MAX_BIOS ||
- bp1 == NULL ||
+ if (bp1 == NULL ||
bp1->bio_bcount / softc->params.secsize >
(softc->trim_max_ranges - ranges) *
ATA_DSM_RANGE_MAX)
@@ -1443,6 +1442,7 @@ adastart(struct cam_periph *periph, unio
ATA_DSM_TRIM, 0, (ranges + ATA_DSM_BLK_RANGES -
1) / ATA_DSM_BLK_RANGES);
start_ccb->ccb_h.ccb_state = ADA_CCB_TRIM;
+ start_ccb->ccb_h.flags |= CAM_UNLOCKED;
goto out;
}
/* Run regular command. */
@@ -1611,6 +1611,7 @@ adastart(struct cam_periph *periph, unio
break;
}
start_ccb->ccb_h.ccb_state = ADA_CCB_BUFFER_IO;
+ start_ccb->ccb_h.flags |= CAM_UNLOCKED;
out:
start_ccb->ccb_h.ccb_bp = bp;
softc->outstanding_cmds++;
@@ -1678,10 +1679,12 @@ adadone(struct cam_periph *periph, union
struct bio *bp;
int error;
+ cam_periph_lock(periph);
if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
error = adaerror(done_ccb, 0, 0);
if (error == ERESTART) {
/* A retry was scheduled, so just return. */
+ cam_periph_unlock(periph);
return;
}
if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
@@ -1711,14 +1714,18 @@ adadone(struct cam_periph *periph, union
softc->outstanding_cmds--;
if (softc->outstanding_cmds == 0)
softc->flags |= ADA_FLAG_WENT_IDLE;
+ xpt_release_ccb(done_ccb);
if (state == ADA_CCB_TRIM) {
- struct trim_request *req =
- (struct trim_request *)ataio->data_ptr;
- int i;
-
- for (i = 1; i < TRIM_MAX_BIOS && req->bps[i]; i++) {
- struct bio *bp1 = req->bps[i];
+ TAILQ_HEAD(, bio) queue;
+ struct bio *bp1;
+ TAILQ_INIT(&queue);
+ TAILQ_CONCAT(&queue, &softc->trim_req.bps, bio_queue);
+ softc->trim_running = 0;
+ adaschedule(periph);
+ cam_periph_unlock(periph);
+ while ((bp1 = TAILQ_FIRST(&queue)) != NULL) {
+ TAILQ_REMOVE(&queue, bp1, bio_queue);
bp1->bio_error = bp->bio_error;
if (bp->bio_flags & BIO_ERROR) {
bp1->bio_flags |= BIO_ERROR;
@@ -1727,12 +1734,11 @@ adadone(struct cam_periph *periph, union
bp1->bio_resid = 0;
biodone(bp1);
}
- softc->trim_running = 0;
- biodone(bp);
- adaschedule(periph);
- } else
+ } else {
+ cam_periph_unlock(periph);
biodone(bp);
- break;
+ }
+ return;
}
case ADA_CCB_RAHEAD:
{
Modified: projects/camlock/sys/cam/scsi/scsi_da.c
==============================================================================
--- projects/camlock/sys/cam/scsi/scsi_da.c Thu Aug 15 14:41:39 2013 (r254368)
+++ projects/camlock/sys/cam/scsi/scsi_da.c Thu Aug 15 15:12:14 2013 (r254369)
@@ -2271,6 +2271,7 @@ skipstate:
break;
}
start_ccb->ccb_h.ccb_state = DA_CCB_BUFFER_IO;
+ start_ccb->ccb_h.flags |= CAM_UNLOCKED;
out:
/*
@@ -2583,6 +2584,7 @@ da_delete_unmap(struct cam_periph *perip
/*sense_len*/SSD_FULL_SIZE,
da_default_timeout * 1000);
ccb->ccb_h.ccb_state = DA_CCB_DELETE;
+ ccb->ccb_h.flags |= CAM_UNLOCKED;
}
static void
@@ -2663,6 +2665,7 @@ da_delete_trim(struct cam_periph *periph
/*sense_len*/SSD_FULL_SIZE,
da_default_timeout * 1000);
ccb->ccb_h.ccb_state = DA_CCB_DELETE;
+ ccb->ccb_h.flags |= CAM_UNLOCKED;
}
/*
@@ -2719,6 +2722,7 @@ da_delete_ws(struct cam_periph *periph,
/*sense_len*/SSD_FULL_SIZE,
da_default_timeout * 1000);
ccb->ccb_h.ccb_state = DA_CCB_DELETE;
+ ccb->ccb_h.flags |= CAM_UNLOCKED;
}
static int
@@ -2853,6 +2857,7 @@ dadone(struct cam_periph *periph, union
{
struct bio *bp, *bp1;
+ cam_periph_lock(periph);
bp = (struct bio *)done_ccb->ccb_h.ccb_bp;
if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
int error;
@@ -2869,6 +2874,7 @@ dadone(struct cam_periph *periph, union
* A retry was scheduled, so
* just return.
*/
+ cam_periph_unlock(periph);
return;
}
bp = (struct bio *)done_ccb->ccb_h.ccb_bp;
@@ -2945,9 +2951,18 @@ dadone(struct cam_periph *periph, union
if (softc->outstanding_cmds == 0)
softc->flags |= DA_FLAG_WENT_IDLE;
+ xpt_release_ccb(done_ccb);
if (state == DA_CCB_DELETE) {
- while ((bp1 = bioq_takefirst(&softc->delete_run_queue))
- != NULL) {
+ TAILQ_HEAD(, bio) queue;
+
+ TAILQ_INIT(&queue);
+ TAILQ_CONCAT(&queue, &softc->delete_run_queue.queue, bio_queue);
+ softc->delete_run_queue.insert_point = NULL;
+ softc->delete_running = 0;
+ daschedule(periph);
+ cam_periph_unlock(periph);
+ while ((bp1 = TAILQ_FIRST(&queue)) != NULL) {
+ TAILQ_REMOVE(&queue, bp1, bio_queue);
bp1->bio_error = bp->bio_error;
if (bp->bio_flags & BIO_ERROR) {
bp1->bio_flags |= BIO_ERROR;
@@ -2956,13 +2971,11 @@ dadone(struct cam_periph *periph, union
bp1->bio_resid = 0;
biodone(bp1);
}
- softc->delete_running = 0;
- if (bp != NULL)
- biodone(bp);
- daschedule(periph);
- } else if (bp != NULL)
+ } else
+ cam_periph_unlock(periph);
+ if (bp != NULL)
biodone(bp);
- break;
+ return;
}
case DA_CCB_PROBE_RC:
case DA_CCB_PROBE_RC16:
More information about the svn-src-projects
mailing list