Add support for creating/deleting ATA RAID's

Sponsored by: Advanis
This commit is contained in:
sos 2002-03-27 10:59:53 +00:00
parent 3bb9163271
commit 143359e917
2 changed files with 152 additions and 73 deletions

View File

@ -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

View File

@ -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("\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(" number of cylinders %d\n", parm->cylinders);
printf(" number of heads %d\n", parm->heads);
printf(" sectors per track %d\n", parm->sectors);
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("lba%ssupported ", parm->support_lba ? " " : " not ");
if (parm->lba_size)
printf("%d sectors\n", parm->lba_size);
else
printf("\n");
printf(" SMART support %s\n", parm->support.smart ? "yes" : "no");
if(parm->support.smart)
printf(" enabled %s\n", parm->enabled.smart ? "yes" : "no");
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(" security support %s\n", parm->support.smart ? "yes" : "no");
if(parm->support.smart)
printf(" enabled %s\n", parm->enabled.smart ? "yes" : "no");
printf("overlap%ssupported\n", parm->support_queueing ? " " : " not ");
printf("\nFeature Support Enable Value Vendor\n");
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 %s %s\n",
parm->support.write_cache ? "yes" : "no",
parm->enabled.write_cache ? "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("read ahead %s %s\n",
parm->support.look_ahead ? "yes" : "no",
parm->enabled.look_ahead ? "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("dma queued %s %s %d/%02X\n",
parm->support.queued ? "yes" : "no",
parm->enabled.queued ? "yes" : "no",
parm->queuelen, parm->queuelen);
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("SMART %s %s\n",
parm->support.smart ? "yes" : "no",
parm->enabled.smart ? "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("microcode download %s %s\n",
parm->support.microcode ? "yes" : "no",
parm->enabled.microcode ? "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("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(ATAREBUILD)");
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(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) {