From f642c834f402ead0f63330d6a8cd530c2eb5fdff Mon Sep 17 00:00:00 2001 From: =?utf8?q?S=C3=B8ren=20Schmidt?= Date: Wed, 27 Mar 2002 10:59:53 +0000 Subject: [PATCH] Add support for creating/deleting ATA RAID's Sponsored by: Advanis --- sbin/atacontrol/atacontrol.8 | 36 +++++- sbin/atacontrol/atacontrol.c | 207 ++++++++++++++++++++++------------- 2 files changed, 161 insertions(+), 82 deletions(-) diff --git a/sbin/atacontrol/atacontrol.8 b/sbin/atacontrol/atacontrol.8 index 1b46de927f7..6d8bd534a1c 100644 --- a/sbin/atacontrol/atacontrol.8 +++ b/sbin/atacontrol/atacontrol.8 @@ -34,7 +34,7 @@ .Sh SYNOPSIS .Nm .Aq Ar command -.Ar channel Op Ar args +.Ar args .Pp .Nm .Ic attach @@ -46,6 +46,12 @@ .Ic reinit .Ar channel .Nm +.Ic create +.Ar type [interleave] disk0 ... diskN +.Nm +.Ic delete +.Ar raid +.Nm .Ic rebuild .Ar raid .Nm @@ -56,6 +62,9 @@ .Ic info .Ar channel .Nm +.Ic cap +.Ar channel device +.Nm .Ic list .Sh DESCRIPTION .Nm @@ -92,6 +101,24 @@ initialized to the parameters the ATA driver has stored internally. Devices that has gone bad and no longer responds to the probe, or devices that has physically been removed are removed from the kernel. Likewise are devices that show up during a reset, probed and attached. +.It Ic create +Create a +.Ar type +ATA RAID. The Type can be RAID0 (stripe), RAID1 (mirror), RAID0+1 or +SPAN (JBOD). In case the RAID has a RAID0 component the +.Ar interleave +must be specified in number of sectors. The RAID will be created +of the individual disks named +.Ar disk0 ... diskN. +.Pp +Allthough the ATA driver allows for creating an ATA RAID on disks on any +controller, there are restrictions. It is only possible to boot on +an array if its either located on a "real" ATA RAID controller like +the Promise or Highpoint controllers, or if the RAID declared is of +RAID1 or SPAN type, in case of a SPAN the partition to boot must +reside on the first disk in the SPAN. +.It Ic delete +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 mode @@ -113,8 +140,11 @@ and the mode will remain unchanged. .It Ic info Show info about the attached devices on the .Ar channel , -currently only the device -name and manufacture/version strings are shown. +the device name and manufacture/version strings are shown. +.It Ic cap +Show detailed info about the device on +.Ar channel device +where device is 0 for master and 1 for slave. .It Ic list Show info about all attached devices on all active controllers. .El diff --git a/sbin/atacontrol/atacontrol.c b/sbin/atacontrol/atacontrol.c index f6be4513112..e339a257a0a 100644 --- a/sbin/atacontrol/atacontrol.c +++ b/sbin/atacontrol/atacontrol.c @@ -106,68 +106,77 @@ param_print(struct ata_params *parm) } void -aparam_print(struct ata_params *parm) +cap_print(struct ata_params *parm) { - printf(" disk model name %.40s\n", parm->model); - printf(" firmware revision %.8s\n", parm->revision); - printf(" ata / atapi revision %d\n", version(parm->version_major)); - - printf(" number of cylinders %d\n", parm->cylinders); - printf(" number of heads %d\n", parm->heads); - printf(" sectors per track %d\n", parm->sectors); + printf("\n"); + printf("ATA/ATAPI revision %d\n", version(parm->version_major)); + printf("device model %.40s\n", parm->model); + printf("firmware revision %.8s\n", parm->revision); + + printf("cylinders %d\n", parm->cylinders); + printf("heads %d\n", parm->heads); + printf("sectors/track %d\n", parm->sectors); - printf(" lba support %s\n", parm->support_lba ? "yes" : "no"); - printf(" lba sectors %d\n", parm->lba_size); - printf(" dma support %s\n", parm->support_dma ? "yes" : "no"); - printf(" queueing support %s\n", parm->support_queueing ? "yes" : "no"); - if(parm->support_queueing) - printf(" length %d\n", parm->queuelen); - - printf(" SMART support %s\n", parm->support.smart ? "yes" : "no"); - if(parm->support.smart) - printf(" enabled %s\n", parm->enabled.smart ? "yes" : "no"); - - printf(" security support %s\n", parm->support.smart ? "yes" : "no"); - if(parm->support.smart) - printf(" enabled %s\n", parm->enabled.smart ? "yes" : "no"); - - printf(" power management support %s\n", parm->support.power_mngt ? "yes" : "no"); - if(parm->support.power_mngt) - printf(" enabled %s\n", parm->enabled.power_mngt ? "yes" : "no"); - - printf(" write cache support %s\n", parm->support.write_cache ? "yes" : "no"); - if(parm->support.write_cache) - printf(" enabled %s\n", parm->enabled.write_cache ? "yes" : "no"); - - printf(" look ahead support %s\n", parm->support.look_ahead ? "yes" : "no"); - if(parm->support.look_ahead) - printf(" enabled %s\n", parm->enabled.look_ahead ? "yes" : "no"); - - printf(" microcode download support %s\n", parm->support.microcode ? "yes" : "no"); - if(parm->support.microcode) - printf(" enabled %s\n", parm->enabled.microcode ? "yes" : "no"); - - printf(" rd/wr dma queued support %s\n", parm->support.queued ? "yes" : "no"); - if(parm->support.queued) - printf(" enabled %s\n", parm->enabled.queued ? "yes" : "no"); - - printf(" advanced power management support %s\n", parm->support.apm ? "yes" : "no"); - if(parm->support.apm) - { - printf(" enabled %s\n", parm->enabled.apm ? "yes" : "no"); - printf(" value %d / 0x%02x\n", parm->apm_value, parm->apm_value); - } - printf(" automatic acoustic management support %s\n", parm->support.auto_acoustic ? "yes" : "no"); - if(parm->support.auto_acoustic) - { - printf(" enabled %s\n", parm->enabled.auto_acoustic ? "yes" : "no"); - printf(" automatic acoustic management current value %d / 0x%02x\n", parm->current_acoustic, parm->current_acoustic); - printf(" recommended value %d / 0x%02x\n", parm->vendor_acoustic, parm->vendor_acoustic); - } + printf("lba%ssupported ", parm->support_lba ? " " : " not "); + if (parm->lba_size) + printf("%d sectors\n", parm->lba_size); + else + printf("\n"); + + printf("lba48%ssupported ", parm->support.address48 ? " " : " not "); + if (parm->lba_size48) + printf("%lld sectors\n", parm->lba_size48); + else + printf("\n"); + printf("dma%ssupported\n", parm->support_dma ? " " : " not"); + + printf("overlap%ssupported\n", parm->support_queueing ? " " : " not "); + + printf("\nFeature Support Enable Value Vendor\n"); + + printf("write cache %s %s\n", + parm->support.write_cache ? "yes" : "no", + parm->enabled.write_cache ? "yes" : "no"); + + printf("read ahead %s %s\n", + parm->support.look_ahead ? "yes" : "no", + parm->enabled.look_ahead ? "yes" : "no"); + + printf("dma queued %s %s %d/%02X\n", + parm->support.queued ? "yes" : "no", + parm->enabled.queued ? "yes" : "no", + parm->queuelen, parm->queuelen); + + printf("SMART %s %s\n", + parm->support.smart ? "yes" : "no", + parm->enabled.smart ? "yes" : "no"); + + printf("microcode download %s %s\n", + parm->support.microcode ? "yes" : "no", + parm->enabled.microcode ? "yes" : "no"); + + printf("security %s %s\n", + parm->support.smart ? "yes" : "no", + parm->enabled.smart ? "yes" : "no"); + + printf("power management %s %s\n", + parm->support.power_mngt ? "yes" : "no", + parm->enabled.power_mngt ? "yes" : "no"); + + printf("advanced power management %s %s %d/%02X\n", + parm->support.apm ? "yes" : "no", + parm->enabled.apm ? "yes" : "no", + parm->apm_value, parm->apm_value); + + printf("automatic acoustic management %s %s %d/%02X %d/%02X\n", + parm->support.auto_acoustic ? "yes" : "no", + parm->enabled.auto_acoustic ? "yes" : "no", + parm->current_acoustic, parm->current_acoustic, + parm->vendor_acoustic, parm->vendor_acoustic); } int -ata_params_print(int fd, int channel, int master) +ata_cap_print(int fd, int channel, int device) { struct ata_cmd iocmd; @@ -180,20 +189,14 @@ ata_params_print(int fd, int channel, int master) if (ioctl(fd, IOCATA, &iocmd) < 0) return errno; - if(master) - master = 1; - master = !master; - - printf("ATA channel %d, %s", channel, master==0 ? "Master" : "Slave"); + printf("ATA channel %d, %s", channel, device==0 ? "Master" : "Slave"); - if (iocmd.u.param.type[master]) { - printf(", device %s:\n", iocmd.u.param.name[master]); - aparam_print(&iocmd.u.param.params[master]); + if (iocmd.u.param.type[device]) { + printf(", device %s:\n", iocmd.u.param.name[device]); + cap_print(&iocmd.u.param.params[device]); } else - { printf(": no device present\n"); - } return 0; } @@ -231,7 +234,6 @@ int main(int argc, char **argv) { struct ata_cmd iocmd; - int master; int fd; if ((fd = open("/dev/ata", O_RDWR)) < 0) @@ -242,17 +244,23 @@ main(int argc, char **argv) bzero(&iocmd, sizeof(struct ata_cmd)); - if (argc > 2) { + if (argc > 2 && strcmp(argv[1], "create")) { int chan; - if (!(sscanf(argv[2], "%d", &chan) == 1 || - sscanf(argv[2], "ata%d", &chan) == 1)) - usage(); + + if (!strcmp(argv[1], "delete") || + !strcmp(argv[1], "rebuild")) { + if (!(sscanf(argv[2], "%d", &chan) == 1 || + sscanf(argv[2], "ar%d", &chan) == 1)) + usage(); + } + else { + if (!(sscanf(argv[2], "%d", &chan) == 1 || + sscanf(argv[2], "ata%d", &chan) == 1)) + usage(); + } iocmd.channel = chan; } - if (argc > 3) - master = atoi(argv[3]); - if (!strcmp(argv[1], "list") && argc == 2) { int unit = 0; @@ -261,8 +269,8 @@ main(int argc, char **argv) else if (!strcmp(argv[1], "info") && argc == 3) { info_print(fd, iocmd.channel, 0); } - else if (!strcmp(argv[1], "parm") && argc == 4) { - ata_params_print(fd, iocmd.channel, master); + else if (!strcmp(argv[1], "cap") && argc == 4) { + ata_cap_print(fd, iocmd.channel, atoi(argv[3])); } else if (!strcmp(argv[1], "detach") && argc == 3) { iocmd.cmd = ATADETACH; @@ -282,9 +290,50 @@ main(int argc, char **argv) info_print(fd, iocmd.channel, 0); } else if (!strcmp(argv[1], "rebuild") && argc == 3) { - iocmd.cmd = ATAREBUILD; + 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; + + iocmd.cmd = ATARAIDCREATE; + if (!strcmp(argv[2], "RAID0") || !strcmp(argv[2], "stripe")) + iocmd.u.raid_setup.type = 1; + if (!strcmp(argv[2], "RAID1") || !strcmp(argv[2],"mirror")) + iocmd.u.raid_setup.type = 2; + if (!strcmp(argv[2], "RAID0+1")) + iocmd.u.raid_setup.type = 3; + if (!strcmp(argv[2], "SPAN") || !strcmp(argv[2], "JBOD")) + iocmd.u.raid_setup.type = 4; + if (!iocmd.u.raid_setup.type) + usage(); + + if (iocmd.u.raid_setup.type & 1) { + if (!sscanf(argv[3], "%d", + &iocmd.u.raid_setup.interleave) == 1) + usage(); + offset = 4; + } + else + offset = 3; + + for (disk = 0; disk < 16 && (offset + disk) < argc; disk++) { + if (!(sscanf(argv[offset + disk], "%d", &dev) == 1 || + sscanf(argv[offset + disk], "ad%d", &dev) == 1)) + usage(); + iocmd.u.raid_setup.disks[disk] = dev; + } + iocmd.u.raid_setup.total_disks = disk; if (ioctl(fd, IOCATA, &iocmd) < 0) - warn("ioctl(ATAREBUILD)"); + warn("ioctl(ATARAIDCREATE)"); + else + printf("ar%d created\n", iocmd.u.raid_setup.unit); } else if (!strcmp(argv[1], "mode") && (argc == 3 || argc == 5)) { if (argc == 5) { -- 2.45.2