[Midnightbsd-cvs] src: ata-raid.c: support flush on raid

laffer1 at midnightbsd.org laffer1 at midnightbsd.org
Mon Dec 1 12:26:22 EST 2008


Log Message:
-----------
support flush on raid

Modified Files:
--------------
    src/sys/dev/ata:
        ata-raid.c (r1.5 -> r1.6)

-------------- next part --------------
Index: ata-raid.c
===================================================================
RCS file: /home/cvs/src/sys/dev/ata/ata-raid.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -L sys/dev/ata/ata-raid.c -L sys/dev/ata/ata-raid.c -u -r1.5 -r1.6
--- sys/dev/ata/ata-raid.c
+++ sys/dev/ata/ata-raid.c
@@ -56,7 +56,7 @@
 /* prototypes */
 static void ata_raid_done(struct ata_request *request);
 static void ata_raid_config_changed(struct ar_softc *rdp, int writeback);
-static int ata_raid_status(struct ata_ioc_raid_config *config);
+static int ata_raid_status(struct ata_ioc_raid_status *status);
 static int ata_raid_create(struct ata_ioc_raid_config *config);
 static int ata_raid_delete(int array);
 static int ata_raid_addspare(struct ata_ioc_raid_config *config);
@@ -146,6 +146,21 @@
     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,
@@ -201,13 +216,14 @@
 static int
 ata_raid_ioctl(u_long cmd, caddr_t data)
 {
+    struct ata_ioc_raid_status *status = (struct ata_ioc_raid_status *)data;
     struct ata_ioc_raid_config *config = (struct ata_ioc_raid_config *)data;
     int *lun = (int *)data;
     int error = EOPNOTSUPP;
 
     switch (cmd) {
     case IOCATARAIDSTATUS:
-	error = ata_raid_status(config);
+	error = ata_raid_status(status);
 	break;
 			
     case IOCATARAIDCREATE:
@@ -229,6 +245,39 @@
     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 +287,15 @@
     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 +612,15 @@
     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:
@@ -863,25 +930,32 @@
 }
 
 static int
-ata_raid_status(struct ata_ioc_raid_config *config)
+ata_raid_status(struct ata_ioc_raid_status *status)
 {
     struct ar_softc *rdp;
     int i;
 	
-    if (!(rdp = ata_raid_arrays[config->lun]))
+    if (!(rdp = ata_raid_arrays[status->lun]))
 	return ENXIO;
 	
-    config->type = rdp->type;
-    config->total_disks = rdp->total_disks;
+    status->type = rdp->type;
+    status->total_disks = rdp->total_disks;
     for (i = 0; i < rdp->total_disks; i++ ) {
-	if ((rdp->disks[i].flags & AR_DF_PRESENT) && rdp->disks[i].dev)  
-	    config->disks[i] = device_get_unit(rdp->disks[i].dev);
-	else
-	    config->disks[i] = -1;
-    }
-    config->interleave = rdp->interleave;
-    config->status = rdp->status;
-    config->progress = 100 * rdp->rebuild_lba / rdp->total_sectors;
+	status->disks[i].state = 0;
+	if ((rdp->disks[i].flags & AR_DF_PRESENT) && rdp->disks[i].dev) {
+	    status->disks[i].lun = device_get_unit(rdp->disks[i].dev);
+	    if (rdp->disks[i].flags & AR_DF_PRESENT)
+		status->disks[i].state |= AR_DISK_PRESENT;
+	    if (rdp->disks[i].flags & AR_DF_ONLINE)
+		status->disks[i].state |= AR_DISK_ONLINE;
+	    if (rdp->disks[i].flags & AR_DF_SPARE)
+		status->disks[i].state |= AR_DISK_SPARE;
+	} else
+	    status->disks[i].lun = -1;
+    }
+    status->interleave = rdp->interleave;
+    status->status = rdp->status;
+    status->progress = 100 * rdp->rebuild_lba / rdp->total_sectors;
     return 0;
 }
 
@@ -3957,6 +4031,9 @@
     case BIO_WRITE:
 	request->flags = ATA_R_WRITE;
 	break;
+    case BIO_FLUSH:
+	request->flags = ATA_R_CONTROL;
+	break;
     }
     return request;
 }


More information about the Midnightbsd-cvs mailing list