--- //depot/yahoo/ybsd_6/src/sbin/atacontrol/atacontrol.8 2007/12/06 12:44:41 +++ //depot/jhb/bsd6/src/sbin/atacontrol/atacontrol.8 2007/12/12 16:54:00 @@ -55,6 +55,12 @@ .Ic addspare .Ar raid disk .Nm +.Ic rmspare +.Ar raid disk +.Nm +.Ic fail +.Ar raid disk +.Nm .Ic rebuild .Ar raid .Nm @@ -153,6 +159,10 @@ Delete a RAID array on a RAID capable ATA controller. .It Ic addspare Add a spare disk to an existing RAID. +.It Ic rmspare +Remove a spare disk from an existing RAID. +.It Ic +Fail a disk in an existing RAID. .It Ic rebuild Rebuild a RAID1 array on a RAID capable ATA controller. .It Ic status --- //depot/yahoo/ybsd_6/src/sbin/atacontrol/atacontrol.c 2007/08/28 08:23:11 +++ //depot/jhb/bsd6/src/sbin/atacontrol/atacontrol.c 2007/08/28 11:20:02 @@ -107,6 +107,8 @@ " atacontrol create type [interleave] disk0 ... diskN\n" " atacontrol delete array\n" " atacontrol addspare array disk\n" + " atacontrol rmspare array disk\n" + " atacontrol fail array disk\n" " atacontrol rebuild array\n" " atacontrol status array\n" " atacontrol mode device [mode]\n" @@ -507,6 +509,40 @@ warn("ioctl(IOCATARAIDADDSPARE)"); exit(EX_OK); } + if (!strcmp(argv[1], "rmspare") && argc == 4) { + struct ata_ioc_raid_config config; + + if (!(sscanf(argv[2], "ar%d", &config.lun) == 1)) { + fprintf(stderr, + "atacontrol: Invalid array %s\n", argv[2]); + usage(); + } + if (!(sscanf(argv[3], "ad%d", &config.disks[0]) == 1)) { + fprintf(stderr, + "atacontrol: Invalid disk %s\n", argv[3]); + usage(); + } + if (ioctl(fd, IOCATARAIDRMSPARE, &config) < 0) + warn("ioctl(IOCATARAIDRMSPARE)"); + exit(EX_OK); + } + if (!strcmp(argv[1], "fail") && argc == 4) { + struct ata_ioc_raid_config config; + + if (!(sscanf(argv[2], "ar%d", &config.lun) == 1)) { + fprintf(stderr, + "atacontrol: Invalid array %s\n", argv[2]); + usage(); + } + if (!(sscanf(argv[3], "ad%d", &config.disks[0]) == 1)) { + fprintf(stderr, + "atacontrol: Invalid disk %s\n", argv[3]); + usage(); + } + if (ioctl(fd, IOCATARAIDFAIL, &config) < 0) + warn("ioctl(IOCATARAIDFAIL)"); + exit(EX_OK); + } if (!strcmp(argv[1], "rebuild") && argc == 3) { int array; --- //depot/yahoo/ybsd_6/src/sys/dev/ata/ata-raid.c 2008/07/30 14:54:10 +++ //depot/jhb/bsd6/src/sys/dev/ata/ata-raid.c 2008/09/18 11:45:40 @@ -63,6 +63,8 @@ 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); +static int ata_raid_rmspare(struct ata_ioc_raid_config *config); +static int ata_raid_fail(struct ata_ioc_raid_config *config); static int ata_raid_rebuild(int array); static int ata_raid_read_metadata(device_t subdisk); static int ata_raid_write_metadata(struct ar_softc *rdp); @@ -231,6 +233,14 @@ case IOCATARAIDADDSPARE: error = ata_raid_addspare(config); break; + + case IOCATARAIDRMSPARE: + error = ata_raid_rmspare(config); + break; + + case IOCATARAIDFAIL: + error = ata_raid_fail(config); + break; case IOCATARAIDREBUILD: error = ata_raid_rebuild(*lun); @@ -1212,7 +1222,8 @@ static int ata_raid_addspare(struct ata_ioc_raid_config *config) { - struct ar_softc *rdp; + struct ata_raid_subdisk *ars; + struct ar_softc *rdp; device_t subdisk; int disk; @@ -1226,32 +1237,41 @@ case AR_T_RAID1: case AR_T_RAID01: case AR_T_RAID5: + subdisk = devclass_get_device(ata_raid_sub_devclass, config->disks[0]); + if (subdisk == NULL) + return ENXIO; + ars = device_get_softc(subdisk); + if (ars->raid[rdp->volume]) { + for (disk = 0; disk < rdp->total_disks; disk++ ) { + if (rdp->disks[disk].dev == device_get_parent(subdisk) && + (rdp->disks[disk].flags & (AR_DF_PRESENT | AR_DF_ONLINE | + AR_DF_SPARE)) == AR_DF_PRESENT) { + rdp->disks[disk].flags |= (AR_DF_ASSIGNED | AR_DF_SPARE); + device_printf(rdp->disks[disk].dev, + "converted to spare disk%d in ar%d\n", disk, rdp->lun); + ata_raid_config_changed(rdp, 1); + return 0; + } + } + return EBUSY; + } for (disk = 0; disk < rdp->total_disks; disk++ ) { if (((rdp->disks[disk].flags & (AR_DF_PRESENT | AR_DF_ONLINE)) == (AR_DF_PRESENT | AR_DF_ONLINE)) && rdp->disks[disk].dev) continue; - if ((subdisk = devclass_get_device(ata_raid_sub_devclass, - config->disks[0] ))) { - struct ata_raid_subdisk *ars = device_get_softc(subdisk); + /* XXX SOS validate size etc etc */ + ars->raid[rdp->volume] = rdp; + ars->disk_number[rdp->volume] = disk; + rdp->disks[disk].dev = device_get_parent(subdisk); + rdp->disks[disk].flags = + (AR_DF_PRESENT | AR_DF_ASSIGNED | AR_DF_SPARE); - if (ars->raid[rdp->volume]) - return EBUSY; - - /* XXX SOS validate size etc etc */ - ars->raid[rdp->volume] = rdp; - ars->disk_number[rdp->volume] = disk; - rdp->disks[disk].dev = device_get_parent(subdisk); - rdp->disks[disk].flags = - (AR_DF_PRESENT | AR_DF_ASSIGNED | AR_DF_SPARE); - - device_printf(rdp->disks[disk].dev, - "inserted into ar%d disk%d as spare\n", - rdp->lun, disk); - ata_raid_config_changed(rdp, 1); - return 0; - } + device_printf(rdp->disks[disk].dev, + "inserted into ar%d disk%d as spare\n", rdp->lun, disk); + ata_raid_config_changed(rdp, 1); + return 0; } return ENXIO; @@ -1259,7 +1279,65 @@ return EPERM; } } - + +static int +ata_raid_rmspare(struct ata_ioc_raid_config *config) +{ + struct ar_softc *rdp; + int disk; + + if (!(rdp = ata_raid_arrays[config->lun])) + return ENXIO; + if (rdp->status & AR_S_REBUILDING) + return EBUSY; + + for (disk = 0; disk < rdp->total_disks; disk++ ) { + if ((rdp->disks[disk].flags & (AR_DF_PRESENT | AR_DF_SPARE)) != + (AR_DF_PRESENT | AR_DF_SPARE)) + continue; + if (!rdp->disks[disk].dev) + continue; + if (device_get_unit(rdp->disks[disk].dev) != config->disks[0]) + continue; + + rdp->disks[disk].flags &= ~AR_DF_SPARE; + device_printf(rdp->disks[disk].dev, "removed as spare from ar%d\n", + rdp->lun); + ata_raid_config_changed(rdp, 1); + return 0; + } + return ENXIO; +} + +static int +ata_raid_fail(struct ata_ioc_raid_config *config) +{ + struct ar_softc *rdp; + int disk; + + if (!(rdp = ata_raid_arrays[config->lun])) + return ENXIO; + if (rdp->status & AR_S_REBUILDING) + return EBUSY; + + for (disk = 0; disk < rdp->total_disks; disk++ ) { + if ((rdp->disks[disk].flags & (AR_DF_PRESENT | AR_DF_ONLINE)) != + (AR_DF_PRESENT | AR_DF_ONLINE)) + continue; + if (!rdp->disks[disk].dev) + continue; + if (device_get_unit(rdp->disks[disk].dev) != config->disks[0]) + continue; + + rdp->disks[disk].flags &= ~AR_DF_ONLINE; + device_printf(rdp->disks[disk].dev, "marked as offline from ar%d\n", + rdp->lun); + ata_raid_config_changed(rdp, 1); + return 0; + } + return ENXIO; +} + static int ata_raid_rebuild(int array) { --- //depot/yahoo/ybsd_6/src/sys/sys/ata.h 2007/08/28 08:23:11 +++ //depot/jhb/bsd6/src/sys/sys/ata.h 2007/08/28 11:20:02 @@ -470,5 +470,7 @@ #define IOCATARAIDSTATUS _IOWR('a', 202, struct ata_ioc_raid_status) #define IOCATARAIDADDSPARE _IOW('a', 203, struct ata_ioc_raid_config) #define IOCATARAIDREBUILD _IOW('a', 204, int) +#define IOCATARAIDRMSPARE _IOW('a', 205, struct ata_ioc_raid_config) +#define IOCATARAIDFAIL _IOW('a', 206, struct ata_ioc_raid_config) #endif /* _SYS_ATA_H_ */