Rework the BIO_DELETE code slightly. Always queue the BIO_DELETE
requests on the trim_queue, even for the CFA ERASE. This allows us, in the future, to collapse adjacent requests. Since CFA ERASE is only for CF cards, and it is so restrictive in what it can do, the collapse code is not presently here. This also brings the ada driver more in line with the da driver's treatment of BIO_DELETEs. Reviewed by: mav@
This commit is contained in:
+103
-90
@@ -719,8 +719,11 @@ adastrategy(struct bio *bp)
|
||||
/*
|
||||
* Place it in the queue of disk activities for this disk
|
||||
*/
|
||||
if (bp->bio_cmd == BIO_DELETE &&
|
||||
(softc->flags & ADA_FLAG_CAN_TRIM)) {
|
||||
if (bp->bio_cmd == BIO_DELETE) {
|
||||
KASSERT((softc->flags & ADA_FLAG_CAN_TRIM) ||
|
||||
((softc->flags & ADA_FLAG_CAN_CFA) &&
|
||||
!(softc->flags & ADA_FLAG_CAN_48BIT)),
|
||||
("BIO_DELETE but no supported TRIM method."));
|
||||
bioq_disksort(&softc->trim_queue, bp);
|
||||
} else {
|
||||
if (ADA_SIO)
|
||||
@@ -1375,6 +1378,96 @@ adaregister(struct cam_periph *periph, void *arg)
|
||||
return(CAM_REQ_CMP);
|
||||
}
|
||||
|
||||
static void
|
||||
ada_dsmtrim(struct ada_softc *softc, struct bio *bp, struct ccb_ataio *ataio)
|
||||
{
|
||||
struct trim_request *req = &softc->trim_req;
|
||||
uint64_t lastlba = (uint64_t)-1;
|
||||
int c, lastcount = 0, off, ranges = 0;
|
||||
|
||||
bzero(req, sizeof(*req));
|
||||
TAILQ_INIT(&req->bps);
|
||||
do {
|
||||
uint64_t lba = bp->bio_pblkno;
|
||||
int count = bp->bio_bcount / softc->params.secsize;
|
||||
|
||||
bioq_remove(&softc->trim_queue, bp);
|
||||
|
||||
/* Try to extend the previous range. */
|
||||
if (lba == lastlba) {
|
||||
c = min(count, ATA_DSM_RANGE_MAX - lastcount);
|
||||
lastcount += c;
|
||||
off = (ranges - 1) * ATA_DSM_RANGE_SIZE;
|
||||
req->data[off + 6] = lastcount & 0xff;
|
||||
req->data[off + 7] =
|
||||
(lastcount >> 8) & 0xff;
|
||||
count -= c;
|
||||
lba += c;
|
||||
}
|
||||
|
||||
while (count > 0) {
|
||||
c = min(count, ATA_DSM_RANGE_MAX);
|
||||
off = ranges * ATA_DSM_RANGE_SIZE;
|
||||
req->data[off + 0] = lba & 0xff;
|
||||
req->data[off + 1] = (lba >> 8) & 0xff;
|
||||
req->data[off + 2] = (lba >> 16) & 0xff;
|
||||
req->data[off + 3] = (lba >> 24) & 0xff;
|
||||
req->data[off + 4] = (lba >> 32) & 0xff;
|
||||
req->data[off + 5] = (lba >> 40) & 0xff;
|
||||
req->data[off + 6] = c & 0xff;
|
||||
req->data[off + 7] = (c >> 8) & 0xff;
|
||||
lba += c;
|
||||
count -= c;
|
||||
lastcount = c;
|
||||
ranges++;
|
||||
/*
|
||||
* Its the caller's responsibility to ensure the
|
||||
* request will fit so we don't need to check for
|
||||
* overrun here
|
||||
*/
|
||||
}
|
||||
lastlba = lba;
|
||||
TAILQ_INSERT_TAIL(&req->bps, bp, bio_queue);
|
||||
bp = bioq_first(&softc->trim_queue);
|
||||
if (bp == NULL ||
|
||||
bp->bio_bcount / softc->params.secsize >
|
||||
(softc->trim_max_ranges - ranges) * ATA_DSM_RANGE_MAX)
|
||||
break;
|
||||
} while (1);
|
||||
cam_fill_ataio(ataio,
|
||||
ada_retry_count,
|
||||
adadone,
|
||||
CAM_DIR_OUT,
|
||||
0,
|
||||
req->data,
|
||||
((ranges + ATA_DSM_BLK_RANGES - 1) /
|
||||
ATA_DSM_BLK_RANGES) * ATA_DSM_BLK_SIZE,
|
||||
ada_default_timeout * 1000);
|
||||
ata_48bit_cmd(ataio, ATA_DATA_SET_MANAGEMENT,
|
||||
ATA_DSM_TRIM, 0, (ranges + ATA_DSM_BLK_RANGES -
|
||||
1) / ATA_DSM_BLK_RANGES);
|
||||
}
|
||||
|
||||
static void
|
||||
ada_cfaerase(struct ada_softc *softc, struct bio *bp, struct ccb_ataio *ataio)
|
||||
{
|
||||
uint64_t lba = bp->bio_pblkno;
|
||||
uint16_t count = bp->bio_bcount / softc->params.secsize;
|
||||
|
||||
cam_fill_ataio(ataio,
|
||||
ada_retry_count,
|
||||
adadone,
|
||||
CAM_DIR_NONE,
|
||||
0,
|
||||
NULL,
|
||||
0,
|
||||
ada_default_timeout*1000);
|
||||
|
||||
if (count >= 256)
|
||||
count = 0;
|
||||
ata_28bit_cmd(ataio, ATA_CFA_ERASE, 0, lba, count);
|
||||
}
|
||||
|
||||
static void
|
||||
adastart(struct cam_periph *periph, union ccb *start_ccb)
|
||||
{
|
||||
@@ -1392,76 +1485,15 @@ adastart(struct cam_periph *periph, union ccb *start_ccb)
|
||||
/* Run TRIM if not running yet. */
|
||||
if (!softc->trim_running &&
|
||||
(bp = bioq_first(&softc->trim_queue)) != 0) {
|
||||
struct trim_request *req = &softc->trim_req;
|
||||
struct bio *bp1;
|
||||
uint64_t lastlba = (uint64_t)-1;
|
||||
int c, lastcount = 0, off, ranges = 0;
|
||||
|
||||
if (softc->flags & ADA_FLAG_CAN_TRIM) {
|
||||
ada_dsmtrim(softc, bp, ataio);
|
||||
} else if ((softc->flags & ADA_FLAG_CAN_CFA) &&
|
||||
!(softc->flags & ADA_FLAG_CAN_48BIT)) {
|
||||
ada_cfaerase(softc, bp, ataio);
|
||||
} else {
|
||||
panic("adastart: BIO_DELETE without method, not possible.");
|
||||
}
|
||||
softc->trim_running = 1;
|
||||
bzero(req, sizeof(*req));
|
||||
TAILQ_INIT(&req->bps);
|
||||
bp1 = bp;
|
||||
do {
|
||||
uint64_t lba = bp1->bio_pblkno;
|
||||
int count = bp1->bio_bcount /
|
||||
softc->params.secsize;
|
||||
|
||||
bioq_remove(&softc->trim_queue, bp1);
|
||||
|
||||
/* Try to extend the previous range. */
|
||||
if (lba == lastlba) {
|
||||
c = min(count, ATA_DSM_RANGE_MAX - lastcount);
|
||||
lastcount += c;
|
||||
off = (ranges - 1) * ATA_DSM_RANGE_SIZE;
|
||||
req->data[off + 6] = lastcount & 0xff;
|
||||
req->data[off + 7] =
|
||||
(lastcount >> 8) & 0xff;
|
||||
count -= c;
|
||||
lba += c;
|
||||
}
|
||||
|
||||
while (count > 0) {
|
||||
c = min(count, ATA_DSM_RANGE_MAX);
|
||||
off = ranges * ATA_DSM_RANGE_SIZE;
|
||||
req->data[off + 0] = lba & 0xff;
|
||||
req->data[off + 1] = (lba >> 8) & 0xff;
|
||||
req->data[off + 2] = (lba >> 16) & 0xff;
|
||||
req->data[off + 3] = (lba >> 24) & 0xff;
|
||||
req->data[off + 4] = (lba >> 32) & 0xff;
|
||||
req->data[off + 5] = (lba >> 40) & 0xff;
|
||||
req->data[off + 6] = c & 0xff;
|
||||
req->data[off + 7] = (c >> 8) & 0xff;
|
||||
lba += c;
|
||||
count -= c;
|
||||
lastcount = c;
|
||||
ranges++;
|
||||
/*
|
||||
* Its the caller's responsibility to ensure the
|
||||
* request will fit so we don't need to check for
|
||||
* overrun here
|
||||
*/
|
||||
}
|
||||
lastlba = lba;
|
||||
TAILQ_INSERT_TAIL(&req->bps, bp1, bio_queue);
|
||||
bp1 = bioq_first(&softc->trim_queue);
|
||||
if (bp1 == NULL ||
|
||||
bp1->bio_bcount / softc->params.secsize >
|
||||
(softc->trim_max_ranges - ranges) *
|
||||
ATA_DSM_RANGE_MAX)
|
||||
break;
|
||||
} while (1);
|
||||
cam_fill_ataio(ataio,
|
||||
ada_retry_count,
|
||||
adadone,
|
||||
CAM_DIR_OUT,
|
||||
0,
|
||||
req->data,
|
||||
((ranges + ATA_DSM_BLK_RANGES - 1) /
|
||||
ATA_DSM_BLK_RANGES) * ATA_DSM_BLK_SIZE,
|
||||
ada_default_timeout * 1000);
|
||||
ata_48bit_cmd(ataio, ATA_DATA_SET_MANAGEMENT,
|
||||
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;
|
||||
@@ -1596,25 +1628,6 @@ adastart(struct cam_periph *periph, union ccb *start_ccb)
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BIO_DELETE:
|
||||
{
|
||||
uint64_t lba = bp->bio_pblkno;
|
||||
uint16_t count = bp->bio_bcount / softc->params.secsize;
|
||||
|
||||
cam_fill_ataio(ataio,
|
||||
ada_retry_count,
|
||||
adadone,
|
||||
CAM_DIR_NONE,
|
||||
0,
|
||||
NULL,
|
||||
0,
|
||||
ada_default_timeout*1000);
|
||||
|
||||
if (count >= 256)
|
||||
count = 0;
|
||||
ata_28bit_cmd(ataio, ATA_CFA_ERASE, 0, lba, count);
|
||||
break;
|
||||
}
|
||||
case BIO_FLUSH:
|
||||
cam_fill_ataio(ataio,
|
||||
1,
|
||||
|
||||
Reference in New Issue
Block a user