diff options
-rw-r--r-- | sbin/atacontrol/atacontrol.8 | 5 | ||||
-rw-r--r-- | sbin/atacontrol/atacontrol.c | 67 | ||||
-rw-r--r-- | sys/dev/ata/ata-all.c | 3 | ||||
-rw-r--r-- | sys/dev/ata/ata-raid.c | 45 | ||||
-rw-r--r-- | sys/dev/ata/ata-raid.h | 1 | ||||
-rw-r--r-- | sys/sys/ata.h | 16 |
6 files changed, 125 insertions, 12 deletions
diff --git a/sbin/atacontrol/atacontrol.8 b/sbin/atacontrol/atacontrol.8 index 44aad43..6ec13e2 100644 --- a/sbin/atacontrol/atacontrol.8 +++ b/sbin/atacontrol/atacontrol.8 @@ -55,6 +55,9 @@ .Ic rebuild .Ar raid .Nm +.Ic status +.Ar raid +.Nm .Ic mode .Ar channel .Op Ar mastermode slavemode @@ -124,6 +127,8 @@ reside on the first disk in the SPAN. Deletes a RAID array on a RAID capable ATA controller. .It Ic rebuild Rebuild a RAID1 array on a RAID capable ATA controller. +.It Ic status +Get the status of an ATA RAID. .It Ic mode Without the two mode arguments the current transfer modes of both devices are printed. diff --git a/sbin/atacontrol/atacontrol.c b/sbin/atacontrol/atacontrol.c index 9fe2201..43d0f95 100644 --- a/sbin/atacontrol/atacontrol.c +++ b/sbin/atacontrol/atacontrol.c @@ -248,6 +248,7 @@ main(int argc, char **argv) int chan; if (!strcmp(argv[1], "delete") || + !strcmp(argv[1], "status") || !strcmp(argv[1], "rebuild")) { if (!(sscanf(argv[2], "%d", &chan) == 1 || sscanf(argv[2], "ar%d", &chan) == 1)) @@ -300,16 +301,6 @@ main(int argc, char **argv) warn("ioctl(ATAREINIT)"); info_print(fd, iocmd.channel, 0); } - else if (!strcmp(argv[1], "rebuild") && argc == 3) { - iocmd.cmd = ATARAIDREBUILD; - if (ioctl(fd, IOCATA, &iocmd) < 0) - warn("ioctl(ATARAIDREBUILD)"); - } - else if (!strcmp(argv[1], "delete") && argc == 3) { - iocmd.cmd = ATARAIDDELETE; - if (ioctl(fd, IOCATA, &iocmd) < 0) - warn("ioctl(ATARAIDDELETE)"); - } else if (!strcmp(argv[1], "create")) { int disk, dev, offset; @@ -342,10 +333,64 @@ main(int argc, char **argv) } iocmd.u.raid_setup.total_disks = disk; if (ioctl(fd, IOCATA, &iocmd) < 0) - warn("ioctl(ATARAIDCREATE)"); + err(1, "ioctl(ATARAIDCREATE)"); else printf("ar%d created\n", iocmd.u.raid_setup.unit); } + else if (!strcmp(argv[1], "delete") && argc == 3) { + iocmd.cmd = ATARAIDDELETE; + if (ioctl(fd, IOCATA, &iocmd) < 0) + warn("ioctl(ATARAIDDELETE)"); + } + else if (!strcmp(argv[1], "rebuild") && argc == 3) { + iocmd.cmd = ATARAIDREBUILD; + if (ioctl(fd, IOCATA, &iocmd) < 0) + warn("ioctl(ATARAIDREBUILD)"); + } + else if (!strcmp(argv[1], "status") && argc == 3) { + int i; + + iocmd.cmd = ATARAIDSTATUS; + if (ioctl(fd, IOCATA, &iocmd) < 0) + err(1, "ioctl(ATARAIDSTATUS)"); + printf("ar%d: ATA ", iocmd.channel); + switch (iocmd.u.raid_status.type) { + case AR_RAID0: + printf("RAID0"); + break; + case AR_RAID1: + printf("RAID1"); + break; + case AR_RAID0 | AR_RAID1: + printf("RAID0+1"); + break; + case AR_SPAN: + printf("SPAN"); + break; + } + printf(" subdisks: "); + for (i = 0; i < iocmd.u.raid_status.total_disks; i++) { + if (iocmd.u.raid_status.disks[i] >= 0) + printf("ad%d ", iocmd.u.raid_status.disks[i]); + else + printf("DOWN "); + } + printf("status: "); + switch (iocmd.u.raid_status.status) { + case AR_READY: + printf("READY\n"); + break; + case AR_READY | AR_DEGRADED: + printf("DEGRADED\n"); + break; + case AR_READY | AR_DEGRADED | AR_REBUILDING: + printf("REBUILDING %d%% completed\n", + iocmd.u.raid_status.progress); + break; + default: + printf("BROKEN\n"); + } + } else if (!strcmp(argv[1], "mode") && (argc == 3 || argc == 5)) { if (argc == 5) { iocmd.cmd = ATASMODE; diff --git a/sys/dev/ata/ata-all.c b/sys/dev/ata/ata-all.c index 1dae0c4..9d4d1e9 100644 --- a/sys/dev/ata/ata-all.c +++ b/sys/dev/ata/ata-all.c @@ -415,6 +415,9 @@ ataioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct thread *td) case ATARAIDDELETE: return ata_raid_delete(iocmd->channel); + + case ATARAIDSTATUS: + return ata_raid_status(iocmd->channel, &iocmd->u.raid_status); #endif #if defined(DEV_ATAPICD) || defined(DEV_ATAPIFD) || defined(DEV_ATAPIST) case ATAPICMD: { diff --git a/sys/dev/ata/ata-raid.c b/sys/dev/ata/ata-raid.c index 13e17e4..14ee7b0 100644 --- a/sys/dev/ata/ata-raid.c +++ b/sys/dev/ata/ata-raid.c @@ -404,7 +404,50 @@ ata_raid_delete(int array) ar_table[array] = NULL; return 0; } - + +int +ata_raid_status(int array, struct raid_status *status) +{ + struct ar_softc *rdp; + int i; + + if (!ar_table || !(rdp = ar_table[array])) + return ENXIO; + + switch (rdp->flags & (AR_F_RAID0 | AR_F_RAID1 | AR_F_SPAN)) { + case AR_F_RAID0: + status->type = AR_RAID0; + break; + case AR_F_RAID1: + status->type = AR_RAID1; + break; + case AR_F_RAID0 | AR_F_RAID1: + status->type = AR_RAID0 | AR_RAID1; + break; + case AR_F_SPAN: + status->type = AR_SPAN; + break; + } + 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].device) + status->disks[i] = AD_SOFTC(rdp->disks[i])->lun; + else + status->disks[i] = -1; + } + status->interleave = rdp->interleave; + status->status = 0; + if (rdp->flags & AR_F_READY) + status->status |= AR_READY; + if (rdp->flags & AR_F_DEGRADED) + status->status |= AR_DEGRADED; + if (rdp->flags & AR_F_REBUILDING) { + status->status |= AR_REBUILDING; + status->progress = 100*rdp->lock_start/(rdp->total_sectors/rdp->width); + } + return 0; +} + int ata_raid_rebuild(int array) { diff --git a/sys/dev/ata/ata-raid.h b/sys/dev/ata/ata-raid.h index 85f91c7..8755acc 100644 --- a/sys/dev/ata/ata-raid.h +++ b/sys/dev/ata/ata-raid.h @@ -228,4 +228,5 @@ int ata_raiddisk_detach(struct ad_softc *); void ata_raid_attach(void); int ata_raid_create(struct raid_setup *); int ata_raid_delete(int); +int ata_raid_status(int array, struct raid_status *); int ata_raid_rebuild(int); diff --git a/sys/sys/ata.h b/sys/sys/ata.h index 82c79c1..d0a584a 100644 --- a/sys/sys/ata.h +++ b/sys/sys/ata.h @@ -250,11 +250,27 @@ struct ata_cmd { } param; struct raid_setup { int type; +#define AR_RAID0 1 +#define AR_RAID1 2 +#define AR_SPAN 4 + int total_disks; int disks[16]; int interleave; int unit; } raid_setup; + struct raid_status { + int type; + int total_disks; + int disks[16]; + int interleave; + int status; +#define AR_READY 1 +#define AR_DEGRADED 2 +#define AR_REBUILDING 4 + + int progress; + } raid_status; struct { int fan; int temp; |