summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsos <sos@FreeBSD.org>2003-05-02 12:41:44 +0000
committersos <sos@FreeBSD.org>2003-05-02 12:41:44 +0000
commit66a49a9d90fddf3a454394837073218ec971ac4b (patch)
tree4b09eae0061923301227391b42c8daa8744fcfac
parent9d68e427c54c8be6327f67456f42a477b1177dec (diff)
downloadFreeBSD-src-66a49a9d90fddf3a454394837073218ec971ac4b.zip
FreeBSD-src-66a49a9d90fddf3a454394837073218ec971ac4b.tar.gz
Add ioctl to add a spare disk to a RAID array.
Fix the discovery of RAID's to not grap unused disks. Change the probe printing of a RAID a bit.
-rw-r--r--sys/dev/ata/ata-all.c3
-rw-r--r--sys/dev/ata/ata-disk.c12
-rw-r--r--sys/dev/ata/ata-raid.c107
-rw-r--r--sys/dev/ata/ata-raid.h1
4 files changed, 90 insertions, 33 deletions
diff --git a/sys/dev/ata/ata-all.c b/sys/dev/ata/ata-all.c
index 3cebd3b..54ae090 100644
--- a/sys/dev/ata/ata-all.c
+++ b/sys/dev/ata/ata-all.c
@@ -383,6 +383,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 ATARAIDADDSPARE:
+ return ata_raid_addspare(iocmd->channel, iocmd->u.raid_spare.disk);
+
case ATARAIDSTATUS:
return ata_raid_status(iocmd->channel, &iocmd->u.raid_status);
#endif
diff --git a/sys/dev/ata/ata-disk.c b/sys/dev/ata/ata-disk.c
index 1d622af..cb4e163 100644
--- a/sys/dev/ata/ata-disk.c
+++ b/sys/dev/ata/ata-disk.c
@@ -202,11 +202,9 @@ ad_attach(struct ata_device *atadev)
atadev->flags = 0;
ata_enclosure_print(atadev);
-
- /* only print probe banner if we are not part of a RAID array */
- if (!ata_raiddisk_attach(adp))
- if (atadev->driver)
- ad_print(adp);
+ if (atadev->driver)
+ ad_print(adp);
+ ata_raiddisk_attach(adp);
}
void
@@ -248,9 +246,9 @@ adopen(struct disk *dp)
struct ad_softc *adp = dp->d_drv1;
if (adp->flags & AD_F_RAID_SUBDISK)
- return EBUSY;
+ return EPERM;
- /* hold off access to we are fully attached */
+ /* hold off access until we are fully attached */
while (ata_delayed_attach)
tsleep(&ata_delayed_attach, PRIBIO, "adopn", 1);
return 0;
diff --git a/sys/dev/ata/ata-raid.c b/sys/dev/ata/ata-raid.c
index 102526e..417e69b 100644
--- a/sys/dev/ata/ata-raid.c
+++ b/sys/dev/ata/ata-raid.c
@@ -208,20 +208,63 @@ ar_attach_raid(struct ar_softc *rdp, int update)
}
printf(" subdisks:\n");
for (disk = 0; disk < rdp->total_disks; disk++) {
- if (rdp->disks[disk].flags & AR_DF_PRESENT) {
- if (rdp->disks[disk].flags & AR_DF_ONLINE)
- printf(" %d READY ", disk);
- else if (rdp->disks[disk].flags & AR_DF_SPARE)
- printf(" %d SPARE ", disk);
+ if (rdp->disks[disk].device &&
+ AD_SOFTC(rdp->disks[disk])->flags & AD_F_RAID_SUBDISK) {
+ if (rdp->disks[disk].flags & AR_DF_PRESENT) {
+ if (rdp->disks[disk].flags & AR_DF_ONLINE)
+ printf(" disk%d READY ", disk);
+ else if (rdp->disks[disk].flags & AR_DF_SPARE)
+ printf(" disk%d SPARE ", disk);
+ else
+ printf(" disk%d FREE ", disk);
+ printf("on %s at ata%d-%s\n", rdp->disks[disk].device->name,
+ device_get_unit(rdp->disks[disk].device->channel->dev),
+ (rdp->disks[disk].device->unit == ATA_MASTER) ?
+ "master" : "slave");
+ }
+ else if (rdp->disks[disk].flags & AR_DF_ASSIGNED)
+ printf(" disk%d DOWN\n", disk);
else
- printf(" %d FREE ", disk);
- ad_print(AD_SOFTC(rdp->disks[disk]));
+ printf(" disk%d INVALID no RAID config on this disk\n", disk);
}
- else if (rdp->disks[disk].flags & AR_DF_ASSIGNED)
- printf(" %d DOWN\n", disk);
else
- printf(" %d INVALID no RAID config info on this disk\n", disk);
+ printf(" disk%d DOWN no device found for this disk\n", disk);
+ }
+}
+
+int
+ata_raid_addspare(int array, int disk)
+{
+ struct ar_softc *rdp;
+ struct ata_device *atadev;
+ int i;
+
+ if (!ar_table || !(rdp = ar_table[array]))
+ return ENXIO;
+ if (!(rdp->flags & AR_F_RAID1))
+ return EPERM;
+ if (rdp->flags & AR_F_REBUILDING)
+ return EBUSY;
+ if (!(rdp->flags & AR_F_DEGRADED) || !(rdp->flags & AR_F_READY))
+ return ENXIO;
+
+ for (i = 0; i < rdp->total_disks; i++ ) {
+ if (((rdp->disks[i].flags & (AR_DF_PRESENT | AR_DF_ONLINE)) ==
+ (AR_DF_PRESENT | AR_DF_ONLINE)) && rdp->disks[i].device)
+ continue;
+ if ((atadev = ar_locate_disk(disk))) {
+ if (((struct ad_softc*)(atadev->driver))->flags & AD_F_RAID_SUBDISK)
+ return EBUSY;
+ rdp->disks[i].device = atadev;
+ rdp->disks[i].flags |= (AR_DF_PRESENT|AR_DF_ASSIGNED|AR_DF_SPARE);
+ AD_SOFTC(rdp->disks[i])->flags |= AD_F_RAID_SUBDISK;
+ ata_prtdev(rdp->disks[i].device,
+ "inserted into ar%d disk%d as spare\n", array, i);
+ ar_config_changed(rdp, 1);
+ return 0;
+ }
}
+ return ENXIO;
}
int
@@ -362,12 +405,13 @@ ata_raid_create(struct raid_setup *setup)
rdp->flags |= AR_F_READY;
ar_table[array] = rdp;
-
+#if 0
/* kick off rebuild here */
if (setup->type == 2) {
rdp->disks[1].flags &= ~AR_DF_ONLINE;
rdp->disks[1].flags |= AR_DF_SPARE;
}
+#endif
ar_attach_raid(rdp, 1);
ata_raid_rebuild(array);
setup->unit = array;
@@ -1238,14 +1282,20 @@ ar_promise_read_conf(struct ad_softc *adp, struct ar_softc **raidp, int local)
goto promise_out;
}
}
- if (raid->disks[info->raid.disk_number].flags && adp->device) {
- raid->disks[info->raid.disk_number].device = adp->device;
- raid->disks[info->raid.disk_number].flags |= AR_DF_PRESENT;
- raid->disks[info->raid.disk_number].disk_sectors =
- info->raid.disk_sectors;
- AD_SOFTC(raid->disks[info->raid.disk_number])->flags |=
- AD_F_RAID_SUBDISK;
- retval = 1;
+ if (info->raid.generation >= raid->generation) {
+ if (raid->disks[info->raid.disk_number].flags && adp->device) {
+ raid->disks[info->raid.disk_number].device = adp->device;
+ raid->disks[info->raid.disk_number].flags |= AR_DF_PRESENT;
+ raid->disks[info->raid.disk_number].disk_sectors =
+ info->raid.disk_sectors;
+ if ((raid->disks[info->raid.disk_number].flags &
+ (AR_DF_PRESENT | AR_DF_ASSIGNED | AR_DF_ONLINE)) ==
+ (AR_DF_PRESENT | AR_DF_ASSIGNED | AR_DF_ONLINE)) {
+ AD_SOFTC(raid->disks[info->raid.disk_number])->flags |=
+ AD_F_RAID_SUBDISK;
+ retval = 1;
+ }
+ }
}
break;
}
@@ -1276,10 +1326,6 @@ ar_promise_write_conf(struct ar_softc *rdp)
for (count = 0; count < sizeof(struct promise_raid_conf); count++)
*(((u_int8_t *)config) + count) = 255 - (count % 256);
- if (local)
- bcopy(ATA_MAGIC, config->promise_id, sizeof(ATA_MAGIC));
- else
- bcopy(PR_MAGIC, config->promise_id, sizeof(PR_MAGIC));
config->dummy_0 = 0x00020000;
config->magic_0 = PR_MAGIC0(rdp->disks[disk]) | timestamp.tv_sec;
config->magic_1 = timestamp.tv_sec >> 16;
@@ -1362,11 +1408,20 @@ ar_promise_write_conf(struct ar_softc *rdp)
PR_MAGIC0(rdp->disks[drive]) | timestamp.tv_sec;
}
- config->checksum = 0;
- for (ckptr = (int32_t *)config, count = 0; count < 511; count++)
- config->checksum += *ckptr++;
if (rdp->disks[disk].device && rdp->disks[disk].device->driver &&
!(rdp->disks[disk].device->flags & ATA_D_DETACHING)) {
+ if ((rdp->disks[disk].flags & (AR_DF_PRESENT | AR_DF_ONLINE)) ==
+ (AR_DF_PRESENT | AR_DF_ONLINE)) {
+ if (local)
+ bcopy(ATA_MAGIC, config->promise_id, sizeof(ATA_MAGIC));
+ else
+ bcopy(PR_MAGIC, config->promise_id, sizeof(PR_MAGIC));
+ }
+ else
+ bzero(config->promise_id, sizeof(config->promise_id));
+ config->checksum = 0;
+ for (ckptr = (int32_t *)config, count = 0; count < 511; count++)
+ config->checksum += *ckptr++;
if (ar_rw(AD_SOFTC(rdp->disks[disk]),
PR_LBA(AD_SOFTC(rdp->disks[disk])),
sizeof(struct promise_raid_conf),
diff --git a/sys/dev/ata/ata-raid.h b/sys/dev/ata/ata-raid.h
index b4cf301..f6bab6e8 100644
--- a/sys/dev/ata/ata-raid.h
+++ b/sys/dev/ata/ata-raid.h
@@ -227,4 +227,5 @@ void ata_raid_attach(void);
int ata_raid_create(struct raid_setup *);
int ata_raid_delete(int);
int ata_raid_status(int, struct raid_status *);
+int ata_raid_addspare(int, int);
int ata_raid_rebuild(int);
OpenPOWER on IntegriCloud