Date: Thu, 15 Aug 2013 15:12:14 +0000 (UTC) From: Alexander Motin <mav@FreeBSD.org> To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r254369 - in projects/camlock/sys/cam: ata scsi Message-ID: <201308151512.r7FFCE8k079140@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
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:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201308151512.r7FFCE8k079140>