Implement BIO_FLUSH handling for da(4), amr(4), ata(4) and ataraid(4).
Sponsored by: home.pl
This commit is contained in:
parent
1d2aee20b8
commit
9cd394ea96
@ -1179,6 +1179,8 @@ daregister(struct cam_periph *periph, void *arg)
|
||||
softc->disk->d_maxsize = DFLTPHYS; /* XXX: probably not arbitrary */
|
||||
softc->disk->d_unit = periph->unit_number;
|
||||
softc->disk->d_flags = DISKFLAG_NEEDSGIANT;
|
||||
if ((softc->quirks & DA_Q_NO_SYNC_CACHE) == 0)
|
||||
softc->disk->d_flags |= DISKFLAG_CANFLUSHCACHE;
|
||||
disk_create(softc->disk, DISK_VERSION);
|
||||
|
||||
/*
|
||||
@ -1250,20 +1252,35 @@ dastart(struct cam_periph *periph, union ccb *start_ccb)
|
||||
} else {
|
||||
tag_code = MSG_SIMPLE_Q_TAG;
|
||||
}
|
||||
scsi_read_write(&start_ccb->csio,
|
||||
/*retries*/da_retry_count,
|
||||
/*cbfcnp*/dadone,
|
||||
/*tag_action*/tag_code,
|
||||
/*read_op*/bp->bio_cmd == BIO_READ,
|
||||
/*byte2*/0,
|
||||
softc->minimum_cmd_size,
|
||||
/*lba*/bp->bio_pblkno,
|
||||
/*block_count*/bp->bio_bcount /
|
||||
softc->params.secsize,
|
||||
/*data_ptr*/ bp->bio_data,
|
||||
/*dxfer_len*/ bp->bio_bcount,
|
||||
/*sense_len*/SSD_FULL_SIZE,
|
||||
/*timeout*/da_default_timeout*1000);
|
||||
switch (bp->bio_cmd) {
|
||||
case BIO_READ:
|
||||
case BIO_WRITE:
|
||||
scsi_read_write(&start_ccb->csio,
|
||||
/*retries*/da_retry_count,
|
||||
/*cbfcnp*/dadone,
|
||||
/*tag_action*/tag_code,
|
||||
/*read_op*/bp->bio_cmd == BIO_READ,
|
||||
/*byte2*/0,
|
||||
softc->minimum_cmd_size,
|
||||
/*lba*/bp->bio_pblkno,
|
||||
/*block_count*/bp->bio_bcount /
|
||||
softc->params.secsize,
|
||||
/*data_ptr*/ bp->bio_data,
|
||||
/*dxfer_len*/ bp->bio_bcount,
|
||||
/*sense_len*/SSD_FULL_SIZE,
|
||||
/*timeout*/da_default_timeout*1000);
|
||||
break;
|
||||
case BIO_FLUSH:
|
||||
scsi_synchronize_cache(&start_ccb->csio,
|
||||
/*retries*/1,
|
||||
/*cbfcnp*/dadone,
|
||||
MSG_SIMPLE_Q_TAG,
|
||||
/*begin_lba*/0,/* Cover the whole disk */
|
||||
/*lb_count*/0,
|
||||
SSD_FULL_SIZE,
|
||||
/*timeout*/da_default_timeout*1000);
|
||||
break;
|
||||
}
|
||||
start_ccb->ccb_h.ccb_state = DA_CCB_BUFFER_IO;
|
||||
|
||||
/*
|
||||
|
@ -1287,7 +1287,7 @@ amr_bio_command(struct amr_softc *sc, struct amr_command **acp)
|
||||
int driveno;
|
||||
int cmd;
|
||||
|
||||
ac = NULL;
|
||||
*acp = NULL;
|
||||
error = 0;
|
||||
|
||||
/* get a command */
|
||||
@ -1305,39 +1305,50 @@ amr_bio_command(struct amr_softc *sc, struct amr_command **acp)
|
||||
ac->ac_bio = bio;
|
||||
ac->ac_data = bio->bio_data;
|
||||
ac->ac_length = bio->bio_bcount;
|
||||
if (bio->bio_cmd == BIO_READ) {
|
||||
cmd = 0;
|
||||
switch (bio->bio_cmd) {
|
||||
case BIO_READ:
|
||||
ac->ac_flags |= AMR_CMD_DATAIN;
|
||||
if (AMR_IS_SG64(sc)) {
|
||||
cmd = AMR_CMD_LREAD64;
|
||||
ac->ac_flags |= AMR_CMD_SG64;
|
||||
} else
|
||||
cmd = AMR_CMD_LREAD;
|
||||
} else {
|
||||
break;
|
||||
case BIO_WRITE:
|
||||
ac->ac_flags |= AMR_CMD_DATAOUT;
|
||||
if (AMR_IS_SG64(sc)) {
|
||||
cmd = AMR_CMD_LWRITE64;
|
||||
ac->ac_flags |= AMR_CMD_SG64;
|
||||
} else
|
||||
cmd = AMR_CMD_LWRITE;
|
||||
break;
|
||||
case BIO_FLUSH:
|
||||
ac->ac_flags |= AMR_CMD_PRIORITY | AMR_CMD_DATAOUT;
|
||||
cmd = AMR_CMD_FLUSH;
|
||||
break;
|
||||
}
|
||||
amrd = (struct amrd_softc *)bio->bio_disk->d_drv1;
|
||||
driveno = amrd->amrd_drive - sc->amr_drive;
|
||||
blkcount = (bio->bio_bcount + AMR_BLKSIZE - 1) / AMR_BLKSIZE;
|
||||
|
||||
ac->ac_mailbox.mb_command = cmd;
|
||||
ac->ac_mailbox.mb_blkcount = blkcount;
|
||||
ac->ac_mailbox.mb_lba = bio->bio_pblkno;
|
||||
if (bio->bio_cmd & (BIO_READ|BIO_WRITE)) {
|
||||
ac->ac_mailbox.mb_blkcount = blkcount;
|
||||
ac->ac_mailbox.mb_lba = bio->bio_pblkno;
|
||||
if ((bio->bio_pblkno + blkcount) > sc->amr_drive[driveno].al_size) {
|
||||
device_printf(sc->amr_dev,
|
||||
"I/O beyond end of unit (%lld,%d > %lu)\n",
|
||||
(long long)bio->bio_pblkno, blkcount,
|
||||
(u_long)sc->amr_drive[driveno].al_size);
|
||||
}
|
||||
}
|
||||
ac->ac_mailbox.mb_drive = driveno;
|
||||
if (sc->amr_state & AMR_STATE_REMAP_LD)
|
||||
ac->ac_mailbox.mb_drive |= 0x80;
|
||||
|
||||
/* we fill in the s/g related data when the command is mapped */
|
||||
|
||||
if ((bio->bio_pblkno + blkcount) > sc->amr_drive[driveno].al_size)
|
||||
device_printf(sc->amr_dev, "I/O beyond end of unit (%lld,%d > %lu)\n",
|
||||
(long long)bio->bio_pblkno, blkcount,
|
||||
(u_long)sc->amr_drive[driveno].al_size);
|
||||
|
||||
*acp = ac;
|
||||
return(error);
|
||||
}
|
||||
|
@ -236,7 +236,7 @@ amrd_attach(device_t dev)
|
||||
sc->amrd_disk->d_name = "amrd";
|
||||
sc->amrd_disk->d_dump = (dumper_t *)amrd_dump;
|
||||
sc->amrd_disk->d_unit = sc->amrd_unit;
|
||||
sc->amrd_disk->d_flags = 0;
|
||||
sc->amrd_disk->d_flags = DISKFLAG_CANFLUSHCACHE;
|
||||
sc->amrd_disk->d_sectorsize = AMR_BLKSIZE;
|
||||
sc->amrd_disk->d_mediasize = (off_t)sc->amrd_drive->al_size * AMR_BLKSIZE;
|
||||
sc->amrd_disk->d_fwsectors = sc->amrd_drive->al_sectors;
|
||||
|
@ -159,6 +159,8 @@ ad_attach(device_t dev)
|
||||
adp->disk->d_fwsectors = adp->sectors;
|
||||
adp->disk->d_fwheads = adp->heads;
|
||||
adp->disk->d_unit = device_get_unit(dev);
|
||||
if (atadev->param.support.command2 & ATA_SUPPORT_FLUSHCACHE)
|
||||
adp->disk->d_flags = DISKFLAG_CANFLUSHCACHE;
|
||||
disk_create(adp->disk, DISK_VERSION);
|
||||
device_add_child(dev, "subdisk", device_get_unit(dev));
|
||||
ad_firmware_geom_adjust(dev, adp->disk);
|
||||
@ -269,6 +271,17 @@ ad_strategy(struct bio *bp)
|
||||
else
|
||||
request->u.ata.command = ATA_WRITE;
|
||||
break;
|
||||
case BIO_FLUSH:
|
||||
request->u.ata.lba = 0;
|
||||
request->u.ata.count = 0;
|
||||
request->u.ata.feature = 0;
|
||||
request->bytecount = 0;
|
||||
request->transfersize = 0;
|
||||
request->timeout = 1;
|
||||
request->retries = 0;
|
||||
request->flags = ATA_R_CONTROL;
|
||||
request->u.ata.command = ATA_FLUSHCACHE;
|
||||
break;
|
||||
default:
|
||||
device_printf(dev, "FAILURE - unknown BIO operation\n");
|
||||
ata_free_request(request);
|
||||
|
@ -146,6 +146,21 @@ ata_raid_attach(struct ar_softc *rdp, int writeback)
|
||||
rdp->disk->d_maxsize = 128 * DEV_BSIZE;
|
||||
rdp->disk->d_drv1 = rdp;
|
||||
rdp->disk->d_unit = rdp->lun;
|
||||
/* we support flushing cache if all components support it */
|
||||
/* XXX: not all components can be connected at this point */
|
||||
rdp->disk->d_flags = DISKFLAG_CANFLUSHCACHE;
|
||||
for (disk = 0; disk < rdp->total_disks; disk++) {
|
||||
struct ata_device *atadev;
|
||||
|
||||
if (rdp->disks[disk].dev == NULL)
|
||||
continue;
|
||||
if ((atadev = device_get_softc(rdp->disks[disk].dev)) == NULL)
|
||||
continue;
|
||||
if (atadev->param.support.command2 & ATA_SUPPORT_FLUSHCACHE)
|
||||
continue;
|
||||
rdp->disk->d_flags = 0;
|
||||
break;
|
||||
}
|
||||
disk_create(rdp->disk, DISK_VERSION);
|
||||
|
||||
printf("ar%d: %juMB <%s %s%s> status: %s\n", rdp->lun,
|
||||
@ -229,6 +244,39 @@ ata_raid_ioctl(u_long cmd, caddr_t data)
|
||||
return error;
|
||||
}
|
||||
|
||||
static int
|
||||
ata_raid_flush(struct bio *bp)
|
||||
{
|
||||
struct ar_softc *rdp = bp->bio_disk->d_drv1;
|
||||
struct ata_request *request;
|
||||
device_t dev;
|
||||
int disk, error;
|
||||
|
||||
error = 0;
|
||||
bp->bio_pflags = 0;
|
||||
|
||||
for (disk = 0; disk < rdp->total_disks; disk++) {
|
||||
if ((dev = rdp->disks[disk].dev) != NULL)
|
||||
bp->bio_pflags++;
|
||||
}
|
||||
for (disk = 0; disk < rdp->total_disks; disk++) {
|
||||
if ((dev = rdp->disks[disk].dev) == NULL)
|
||||
continue;
|
||||
if (!(request = ata_raid_init_request(rdp, bp)))
|
||||
return ENOMEM;
|
||||
request->dev = dev;
|
||||
request->u.ata.command = ATA_FLUSHCACHE;
|
||||
request->u.ata.lba = 0;
|
||||
request->u.ata.count = 0;
|
||||
request->u.ata.feature = 0;
|
||||
request->timeout = 1;
|
||||
request->retries = 0;
|
||||
request->flags |= ATA_R_ORDERED | ATA_R_DIRECT;
|
||||
ata_queue_request(request);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
ata_raid_strategy(struct bio *bp)
|
||||
{
|
||||
@ -238,6 +286,15 @@ ata_raid_strategy(struct bio *bp)
|
||||
u_int64_t blkno, lba, blk = 0;
|
||||
int count, chunk, drv, par = 0, change = 0;
|
||||
|
||||
if (bp->bio_cmd == BIO_FLUSH) {
|
||||
int error;
|
||||
|
||||
error = ata_raid_flush(bp);
|
||||
if (error != 0)
|
||||
biofinish(bp, NULL, error);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(rdp->status & AR_S_READY) ||
|
||||
(bp->bio_cmd != BIO_READ && bp->bio_cmd != BIO_WRITE)) {
|
||||
biofinish(bp, NULL, EIO);
|
||||
@ -554,6 +611,15 @@ ata_raid_done(struct ata_request *request)
|
||||
struct bio *bp = request->bio;
|
||||
int i, mirror, finished = 0;
|
||||
|
||||
if (bp->bio_cmd == BIO_FLUSH) {
|
||||
if (bp->bio_error == 0)
|
||||
bp->bio_error = request->result;
|
||||
ata_free_request(request);
|
||||
if (--bp->bio_pflags == 0)
|
||||
biodone(bp);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (rdp->type) {
|
||||
case AR_T_JBOD:
|
||||
case AR_T_SPAN:
|
||||
@ -3957,6 +4023,9 @@ ata_raid_init_request(struct ar_softc *rdp, struct bio *bio)
|
||||
case BIO_WRITE:
|
||||
request->flags = ATA_R_WRITE;
|
||||
break;
|
||||
case BIO_FLUSH:
|
||||
request->flags = ATA_R_CONTROL;
|
||||
break;
|
||||
}
|
||||
return request;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user