MFC:
>r268205 | imp | 2014-07-02 23:22:13 -0600 (Wed, 02 Jul 2014) | 9 lines >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.
This commit is contained in:
parent
07bb5d08f3
commit
ae99afdd7d
@ -727,8 +727,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."));
|
||||
if (ADA_SIO)
|
||||
bioq_disksort(&softc->trim_queue, bp);
|
||||
else
|
||||
@ -1385,6 +1388,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)
|
||||
{
|
||||
@ -1402,76 +1495,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;
|
||||
@ -1606,25 +1638,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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user