kern/68315: atacontrol addspare for 4.x
Rene de Vries
rene at tunix.nl
Fri Jun 25 10:50:52 GMT 2004
>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 at 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:
More information about the freebsd-bugs
mailing list