Flesh out BUF_CMD_FLUSH support.
authorMatthew Dillon <dillon@dragonflybsd.org>
Sat, 30 Aug 2008 02:56:12 +0000 (02:56 +0000)
committerMatthew Dillon <dillon@dragonflybsd.org>
Sat, 30 Aug 2008 02:56:12 +0000 (02:56 +0000)
Obtained-from: Ported from FreeBSD.

sys/dev/disk/nata/ata-raid.c
sys/dev/disk/nata/atapi-fd.c
sys/dev/disk/nata/atapi-tape.c
sys/dev/raid/amr/amr.c

index 603e7a8..36b0f5c 100644 (file)
@@ -24,7 +24,7 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/dev/ata/ata-raid.c,v 1.120 2006/04/15 10:27:41 maxim Exp $
- * $DragonFly: src/sys/dev/disk/nata/ata-raid.c,v 1.10 2008/06/27 01:24:46 dillon Exp $
+ * $DragonFly: src/sys/dev/disk/nata/ata-raid.c,v 1.11 2008/08/30 02:56:11 dillon Exp $
  */
 
 #include "opt_ata.h"
@@ -253,6 +253,38 @@ ata_raid_ioctl(u_long cmd, caddr_t data)
     return error;
 }
 
+static int
+ata_raid_flush(struct ar_softc *rdp, struct bio *bp)
+{
+    struct ata_request *request;
+    device_t dev;
+    int disk, error;
+
+    error = 0;
+    bp->bio_driver_info = (void *)0;
+
+    for (disk = 0; disk < rdp->total_disks; disk++) {
+       if ((dev = rdp->disks[disk].dev) != NULL)
+           bp->bio_driver_info = (void *)((intptr_t)bp->bio_driver_info + 1);
+    }
+    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;
+}
+
 /*
  * XXX TGEN there are a lot of offset -> block number conversions going on
  * here, which is suboptimal.
@@ -268,6 +300,18 @@ ata_raid_strategy(struct dev_strategy_args *ap)
     u_int64_t blkno, lba, blk = 0;
     int count, chunk, drv, par = 0, change = 0;
 
+    if (bbp->b_cmd == BUF_CMD_FLUSH) {
+       int error;
+
+       error = ata_raid_flush(rdp, bp);
+       if (error != 0) {
+               bbp->b_flags |= B_ERROR;
+               bbp->b_error = error;
+               biodone(bp);
+       }
+       return(0);
+    }
+
     if (!(rdp->status & AR_S_READY) ||
        (bbp->b_cmd != BUF_CMD_READ && bbp->b_cmd != BUF_CMD_WRITE)) {
        bbp->b_flags |= B_ERROR;
@@ -602,6 +646,19 @@ ata_raid_done(struct ata_request *request)
     struct buf *bbp = bp->bio_buf;
     int i, mirror, finished = 0;
 
+    if (bbp->b_cmd == BUF_CMD_FLUSH) {
+       if (bbp->b_error == 0)
+               bbp->b_error = request->result;
+       ata_free_request(request);
+       bp->bio_driver_info = (void *)((intptr_t)bp->bio_driver_info - 1);
+       if ((intptr_t)bp->bio_driver_info == 0) {
+               if (bbp->b_error)
+                       bbp->b_flags |= B_ERROR;
+               biodone(bp);
+       }
+       return;
+    }
+
     switch (rdp->type) {
     case AR_T_JBOD:
     case AR_T_SPAN:
@@ -3966,6 +4023,9 @@ ata_raid_init_request(struct ar_softc *rdp, struct bio *bio)
     case BUF_CMD_WRITE:
        request->flags = ATA_R_WRITE;
        break;
+    case BUF_CMD_FLUSH:
+       request->flags = ATA_R_CONTROL;
+       break;
     default:
        kprintf("ar%d: FAILURE - unknown BUF operation\n", rdp->lun);
        ata_free_request(request);
index 254c290..a2072e3 100644 (file)
@@ -24,7 +24,7 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/dev/ata/atapi-fd.c,v 1.109 2006/03/30 05:29:57 marcel Exp $
- * $DragonFly: src/sys/dev/disk/nata/atapi-fd.c,v 1.4 2007/06/03 04:48:29 dillon Exp $
+ * $DragonFly: src/sys/dev/disk/nata/atapi-fd.c,v 1.5 2008/08/30 02:56:11 dillon Exp $
  */
 
 #include <sys/param.h>
@@ -257,10 +257,20 @@ afd_strategy(struct dev_strategy_args *ap)
 
     bzero(ccb, sizeof(ccb));
 
-    if (bbp->b_cmd == BUF_CMD_READ)
+    switch(bbp->b_cmd) {
+    case BUF_CMD_READ:
        ccb[0] = ATAPI_READ_BIG;
-    else
+       break;
+    case BUF_CMD_WRITE:
        ccb[0] = ATAPI_WRITE_BIG;
+       break;
+    default:
+       device_printf(dev, "unknown BUF operation\n");
+       bbp->b_flags |= B_ERROR;
+       bbp->b_error = EIO;
+       biodone(bp);
+       return 0;
+    }
 
     ccb[2] = lba >> 24;
     ccb[3] = lba >> 16;
@@ -286,6 +296,7 @@ afd_strategy(struct dev_strategy_args *ap)
     request->timeout = (ccb[0] == ATAPI_WRITE_BIG) ? 60 : 30;
     request->retries = 2;
     request->callback = afd_done;
+
     switch (bbp->b_cmd) {
     case BUF_CMD_READ:
        request->flags = (ATA_R_ATAPI | ATA_R_READ);
@@ -294,12 +305,7 @@ afd_strategy(struct dev_strategy_args *ap)
        request->flags = (ATA_R_ATAPI | ATA_R_WRITE);
        break;
     default:
-       device_printf(dev, "unknown BUF operation\n");
-       ata_free_request(request);
-       bbp->b_flags |= B_ERROR;
-       bbp->b_error = EIO;
-       biodone(bp);
-       return 0;
+       panic("bbp->b_cmd");
     }
     if (atadev->mode >= ATA_DMA)
        request->flags |= ATA_R_DMA;
index 43fc81a..7dba8a3 100644 (file)
@@ -24,7 +24,7 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/dev/ata/atapi-tape.c,v 1.101 2006/01/05 21:27:19 sos Exp $
- * $DragonFly: src/sys/dev/disk/nata/atapi-tape.c,v 1.3 2007/06/03 04:48:29 dillon Exp $
+ * $DragonFly: src/sys/dev/disk/nata/atapi-tape.c,v 1.4 2008/08/30 02:56:11 dillon Exp $
  */
 
 #include "opt_ata.h"
@@ -398,12 +398,18 @@ ast_strategy(struct dev_strategy_args *ap)
        biodone(bp);
        return 0;
     }
-    if (!(bbp->b_cmd == BUF_CMD_READ) && stp->flags & F_WRITEPROTECT) {
+    if (!(bbp->b_cmd == BUF_CMD_READ) && (stp->flags & F_WRITEPROTECT)) {
        bbp->b_flags |= B_ERROR;
        bbp->b_error = EPERM;
        biodone(bp);
        return 0;
     }
+    if (bbp->b_cmd != BUF_CMD_READ && bbp->b_cmd != BUF_CMD_WRITE) {
+       bbp->b_flags |= B_ERROR;
+       bbp->b_error = EIO;
+       biodone(bp);
+       return 0;
+    }
        
     /* check for != blocksize requests */
     if (bbp->b_bcount % stp->blksize) {
@@ -454,6 +460,7 @@ ast_strategy(struct dev_strategy_args *ap)
     request->timeout = (ccb[0] == ATAPI_WRITE_BIG) ? 180 : 120;
     request->retries = 2;
     request->callback = ast_done;
+
     switch (bbp->b_cmd) {
     case BUF_CMD_READ:
        request->flags |= (ATA_R_ATAPI | ATA_R_READ);
@@ -462,12 +469,7 @@ ast_strategy(struct dev_strategy_args *ap)
        request->flags |= (ATA_R_ATAPI | ATA_R_WRITE);
        break;
     default:
-       device_printf(dev, "unknown BUF operation\n");
-       ata_free_request(request);
-       bbp->b_flags |= B_ERROR;
-       bbp->b_error = EIO;
-       biodone(bp);
-       return 0;
+       panic("bbp->b_cmd");
     }
     devstat_start_transaction(&stp->stats);
     ata_queue_request(request);
index 2e03fa1..e00c768 100644 (file)
@@ -53,7 +53,7 @@
  * SUCH DAMAGE.
  *
  *     $FreeBSD: src/sys/dev/amr/amr.c,v 1.7.2.13 2003/01/15 13:41:18 emoore Exp $
- *     $DragonFly: src/sys/dev/raid/amr/amr.c,v 1.25 2008/01/06 16:55:50 swildner Exp $
+ *     $DragonFly: src/sys/dev/raid/amr/amr.c,v 1.26 2008/08/30 02:56:12 dillon Exp $
  */
 
 /*
@@ -867,16 +867,26 @@ amr_bio_command(struct amr_softc *sc, struct amr_command **acp)
     ac->ac_bio = bio;
     ac->ac_data = bio->bio_buf->b_data;
     ac->ac_length = bio->bio_buf->b_bcount;
-    if (bio->bio_buf->b_cmd == BUF_CMD_READ) {
+
+    cmd = 0;
+    switch(bio->bio_buf->b_cmd) {
+    case BUF_CMD_READ:
        ac->ac_flags |= AMR_CMD_DATAIN;
        cmd = AMR_CMD_LREAD;
-    } else {
+       break;
+    case BUF_CMD_WRITE:
        ac->ac_flags |= AMR_CMD_DATAOUT;
        cmd = AMR_CMD_LWRITE;
+       break;
+    case BUF_CMD_FLUSH:
+       ac->ac_flags |= AMR_CMD_PRIORITY | AMR_CMD_DATAOUT;
+       cmd = AMR_CMD_FLUSH;
+       break;
     }
     amrd = (struct amrd_softc *)bio->bio_driver_info;
     driveno = amrd->amrd_drive - sc->amr_drive;
     blkcount = (bio->bio_buf->b_bcount + AMR_BLKSIZE - 1) / AMR_BLKSIZE;
+
     lba = bio->bio_offset / AMR_BLKSIZE;
     KKASSERT(lba < 0x100000000ULL);