From rene@tunix.nl  Fri Jun 25 10:46:00 2004
Return-Path: <rene@tunix.nl>
Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125])
	by hub.freebsd.org (Postfix) with ESMTP id E1BBA16A4CE
	for <FreeBSD-gnats-submit@freebsd.org>; Fri, 25 Jun 2004 10:46:00 +0000 (GMT)
Received: from bastix.tunix.nl (bastix.tunix.nl [193.79.201.39])
	by mx1.FreeBSD.org (Postfix) with ESMTP id 8A0EB43D53
	for <FreeBSD-gnats-submit@freebsd.org>; Fri, 25 Jun 2004 10:45:59 +0000 (GMT)
	(envelope-from rene@tunix.nl)
Received: (from root@localhost) by bastix.tunix.nl (8.9.3c/8.6.12) id MAA96700 for <FreeBSD-gnats-submit@freebsd.org>; Fri, 25 Jun 2004 12:45:35 +0200 (CEST)
Received: by bastix.tunix.nl (TUNIX txp2/smap)
	for <FreeBSD-gnats-submit@freebsd.org> id sma095708; Fri, 25 Jun 04 12:44:19 +0200
Received: from upsilix.tunix.nl (upsilix.tunix.nl [172.16.2.22])
	by fix.tunix.nl (8.10.2+Sun/8.10.2) with ESMTP id i5PAiJo27552
	for <FreeBSD-gnats-submit@freebsd.org>; Fri, 25 Jun 2004 12:44:19 +0200 (MEST)
Received: from upsilix.tunix.nl (localhost.tunix.nl [127.0.0.1])
	by upsilix.tunix.nl (8.12.8p2/8.12.6) with ESMTP id i5PAiID2063276
	for <FreeBSD-gnats-submit@freebsd.org>; Fri, 25 Jun 2004 12:44:19 +0200 (CEST)
	(envelope-from rene@upsilix.tunix.nl)
Received: (from rene@localhost)
	by upsilix.tunix.nl (8.12.8p2/8.12.6/Submit) id i5PAiI3e063275;
	Fri, 25 Jun 2004 12:44:18 +0200 (CEST)
	(envelope-from rene)
Message-Id: <200406251044.i5PAiI3e063275@upsilix.tunix.nl>
Date: Fri, 25 Jun 2004 12:44:18 +0200 (CEST)
From: Rene de Vries <rene@tunix.nl>
Reply-To: Rene de Vries <rene@tunix.nl>
To: FreeBSD-gnats-submit@freebsd.org
Cc:
Subject: atacontrol addspare for 4.x
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         68315
>Category:       kern
>Synopsis:       [ata] [patch] atacontrol(8) addspare for 4.x
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Fri Jun 25 10:50:30 GMT 2004
>Closed-Date:    Wed Jun 27 06:50:13 GMT 2007
>Last-Modified:  Wed Jun 27 06:50:13 GMT 2007
>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:

From: Michael Ranner <mranner@inode.at>
To: freebsd-gnats-submit@FreeBSD.org, rene@tunix.nl
Cc: sos@freebsd.org, freebsd-stable@freebsd.org
Subject: Re: kern/68315: [patch] atacontrol addspare for 4.x
Date: Tue, 5 Oct 2004 22:44:19 +0200

 Works also well on FreeBSD 4.10, I have it tested at my home machine with 
 defective spare (kernelthread aborts as expexted, some little system hang) 
 and I rebuilded a degraded RAID 1 array with my non-raid-bios onboard-ATA- 
 controller. Who would be able to review it for merge in FreeBSD 4-stable?
 
State-Changed-From-To: open->closed 
State-Changed-By: linimon 
State-Changed-When: Wed Jun 27 06:48:23 UTC 2007 
State-Changed-Why:  
Unfortunately, 4.X is no longer in support; the functionality seems to 
be present in 6.2.  Therefore, I'm going to close this PR as no longer 
relevant.  Sorry that it didn't work out. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=68315 
>Unformatted:
