Date: Fri, 25 Jun 2004 12:44:18 +0200 (CEST) From: Rene de Vries <rene@tunix.nl> To: FreeBSD-gnats-submit@FreeBSD.org Subject: kern/68315: atacontrol addspare for 4.x Message-ID: <200406251044.i5PAiI3e063275@upsilix.tunix.nl> Resent-Message-ID: <200406251050.i5PAoUI6043463@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 68315 >Category: kern >Synopsis: atacontrol addspare for 4.x >Confidential: no >Severity: non-critical >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: change-request >Submitter-Id: current-users >Arrival-Date: Fri Jun 25 10:50:30 GMT 2004 >Closed-Date: >Last-Modified: >Originator: Rene de Vries >Release: FreeBSD 4.8 i386 >Organization: Tunix Internet Security & Training >Environment: System: FreeBSD upsilix.tunix.nl 4.8 FreeBSD 4.8-RELEASE-p16 #7: Wed Mar 3 15:00:31 CET 2004 rene@upsilix.tunix.nl:/usr/obj/usr/src/sys/UPSILIX i386 >Description: When an ata mirror is lost and a new disk needs to be added as spare the command allows the system manager to do so. UI modeled after 5.x version, code is different. Diff against FreeBSD 4.8: Index: sbin/atacontrol/atacontrol.c =================================================================== RCS file: sbin/atacontrol/atacontrol.c,v retrieving revision 1.1.1.3 retrieving revision 1.3 diff -u -r1.1.1.3 -r1.3 --- sbin/atacontrol/atacontrol.c 2002/10/15 10:21:01 1.1.1.3 +++ sbin/atacontrol/atacontrol.c 2004/04/13 09:13:18 1.3 @@ -251,7 +251,8 @@ if (!strcmp(argv[1], "delete") || !strcmp(argv[1], "status") || - !strcmp(argv[1], "rebuild")) { + !strcmp(argv[1], "rebuild") || + !strcmp(argv[1], "addspare")) { if (!(sscanf(argv[2], "%d", &chan) == 1 || sscanf(argv[2], "ar%d", &chan) == 1)) usage(); @@ -338,6 +339,21 @@ err(1, "ioctl(ATARAIDCREATE)"); else printf("ar%d created\n", iocmd.u.raid_setup.unit); + } + else if (!strcmp(argv[1], "addspare")) { + int disk, dev; + iocmd.cmd = ATARAIDADD; + for (disk = 0; disk < 16 && (3 + disk) < argc; disk++) { + if (!(sscanf(argv[3 + disk], "%d", &dev) == 1 || + sscanf(argv[3 + 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) + err(1, "ioctl(ATARAIDADD)"); + else + printf("ar%d modified\n", iocmd.u.raid_setup.unit); } else if (!strcmp(argv[1], "delete") && argc == 3) { iocmd.cmd = ATARAIDDELETE; Index: sys/dev/ata/ata-all.c =================================================================== RCS file: /usr/local/cvs/cvsroot/fw/os/freebsd/sys/dev/ata/ata-all.c,v retrieving revision 1.1.1.6 retrieving revision 1.2 diff -u -r1.1.1.6 -r1.2 --- sys/dev/ata/ata-all.c 2003/04/17 15:43:54 1.1.1.6 +++ sys/dev/ata/ata-all.c 2004/03/02 13:52:28 1.2 @@ -417,6 +417,9 @@ case ATARAIDSTATUS: return ata_raid_status(iocmd->channel, &iocmd->u.raid_status); + + case ATARAIDADD: + return ata_raid_add(iocmd->channel, &iocmd->u.raid_setup); #endif #if DEV_ATAPIALL case ATAPICMD: { Index: sys/dev/ata/ata-raid.c =================================================================== RCS file: /usr/local/cvs/cvsroot/fw/os/freebsd/sys/dev/ata/ata-raid.c,v retrieving revision 1.1.1.6 retrieving revision 1.2 diff -u -r1.1.1.6 -r1.2 --- sys/dev/ata/ata-raid.c 2003/04/17 15:43:54 1.1.1.6 +++ sys/dev/ata/ata-raid.c 2004/03/02 13:52:28 1.2 @@ -466,6 +466,93 @@ return ar_rebuild(rdp); } +int ata_raid_add(int array, struct raid_setup *setup) +{ + struct ata_device *atadev; + struct ar_softc *rdp; + int disk, rdisk; + int ctlr = 0, total_disks = 0; + + if (!ar_table) { + printf("ar: no memory for ATA raid array\n"); + return 0; + } + if (!(rdp = ar_table[array])) + return ENXIO; + + if (!(rdp->flags & AR_F_RAID1)) + return EINVAL; + + total_disks = rdp->total_disks; + for (disk = 0; disk < setup->total_disks; disk++) { + for (rdisk = 0; rdisk < total_disks; rdisk++) { + if (!((rdp->disks[rdisk].flags & AR_DF_PRESENT) && rdp->disks[rdisk].device)) + break; + } + + if ((rdisk + 1) > total_disks) + total_disks = rdisk + 1; + else + total_disks = rdp->total_disks; + + if ((atadev = ar_locate_disk(setup->disks[disk]))) { + rdp->disks[rdisk].device = atadev; + if (AD_SOFTC(rdp->disks[rdisk])->flags & AD_F_RAID_SUBDISK) { + setup->disks[disk] = -1; + return EBUSY; + } + + switch (rdp->disks[rdisk].device->channel->chiptype & 0xffff) { + case 0x1103: + ctlr |= AR_F_HIGHPOINT_RAID; + rdp->disks[rdisk].disk_sectors = + AD_SOFTC(rdp->disks[rdisk])->total_secs; + break; + + default: + ctlr |= AR_F_FREEBSD_RAID; + /* FALLTHROUGH */ + + case 0x105a: + ctlr |= AR_F_PROMISE_RAID; + rdp->disks[rdisk].disk_sectors = + PR_LBA(AD_SOFTC(rdp->disks[rdisk])); + break; + } + if ((rdp->flags & (AR_F_PROMISE_RAID|AR_F_HIGHPOINT_RAID)) && + (rdp->flags & (AR_F_PROMISE_RAID|AR_F_HIGHPOINT_RAID)) != + (ctlr & (AR_F_PROMISE_RAID|AR_F_HIGHPOINT_RAID))) { + return EXDEV; + } + else + rdp->flags |= ctlr; + + if (rdp->disks[rdisk].disk_sectors < rdp->total_sectors) { + ata_prtdev(rdp->disks[rdisk].device, + "ar%d: too small for mirror\n", array); + setup->disks[disk] = -1; + return EINVAL; + } + rdp->disks[rdisk].flags = (AR_DF_PRESENT | AR_DF_SPARE); + AD_SOFTC(rdp->disks[rdisk])->flags = AD_F_RAID_SUBDISK; + ata_prtdev(rdp->disks[rdisk].device, + "inserted into ar%d disk%d as spare\n", array, rdisk); + } + else { + setup->disks[disk] = -1; + return ENXIO; + } + } + if (!total_disks) { + return ENODEV; + } + rdp->total_disks = total_disks; + ar_config_changed(rdp, 1); + setup->unit = array; + return 0; +} + + static int aropen(dev_t dev, int flags, int fmt, struct proc *p) { Index: sys/dev/ata/ata-raid.h =================================================================== RCS file: /usr/local/cvs/cvsroot/fw/os/freebsd/sys/dev/ata/ata-raid.h,v retrieving revision 1.1.1.4 retrieving revision 1.2 diff -u -r1.1.1.4 -r1.2 --- sys/dev/ata/ata-raid.h 2002/08/28 08:58:38 1.1.1.4 +++ sys/dev/ata/ata-raid.h 2004/03/02 13:52:28 1.2 @@ -230,4 +230,5 @@ int ata_raid_delete(int); int ata_raid_status(int array, struct raid_status *); int ata_raid_rebuild(int); +int ata_raid_add(int array, struct raid_setup *); Index: sys/sys/ata.h =================================================================== RCS file: /usr/local/cvs/cvsroot/fw/os/freebsd/sys/sys/ata.h,v retrieving revision 1.1.1.3 retrieving revision 1.2 diff -u -r1.1.1.3 -r1.2 --- sys/sys/ata.h 2002/08/28 08:59:31 1.1.1.3 +++ sys/sys/ata.h 2004/03/02 14:27:16 1.2 @@ -238,6 +238,7 @@ #define ATARAIDDELETE 10 #define ATARAIDSTATUS 11 #define ATAENCSTAT 12 +#define ATARAIDADD 1000 union { struct { >How-To-Repeat: >Fix: >Release-Note: >Audit-Trail: >Unformatted:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200406251044.i5PAiI3e063275>