kern/124064: [ar] cannot handle >16 serial number with Intel MatrixRAID

Hideki Sakamoto hsakamt at tsnr.com
Wed May 28 13:10:03 UTC 2008


>Number:         124064
>Category:       kern
>Synopsis:       [ar] cannot handle >16 serial number with Intel MatrixRAID
>Confidential:   no
>Severity:       critical
>Priority:       high
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Wed May 28 13:10:02 UTC 2008
>Closed-Date:
>Last-Modified:
>Originator:     Hideki Sakamoto
>Release:        FreeBSD 6.2-RELEASE-p11, 7.0 and 8.0-CURRENT i386
>Organization:
Tsukuba Secure Network Research
>Environment:
System: FreeBSD sv.tsnr.com 6.2-RELEASE-p11 FreeBSD 6.2-RELEASE-p11 #3: Sat Feb 16 15:11:43 JST 2008 root at sv.tsnr.com:/usr/obj/usr/src/sys/GENERIC i386

System: FreeBSD inst.tsnr.com 8.0-CURRENT FreeBSD 8.0-CURRENT #12: Tue May 27 00:33:33 JST 2008 root at inst.tsnr.com:/usr/obj/usr/src/sys/GENERIC i386

Intel BOX33TLM(ICH9R)

	
>Description:
By chance I got two HDD those serial numbers are almost same. And I cannot
build raid because ataraid cut off a serial number at 16-th characters and
write it to HDD as RAID information.
Another problem is: I checked source and I found Intel MatrixRAID BIOS use
last 16 character of device's serial number though ataraid use first 16
character of it. So, ataraid cannot recognize raid drive built in BIOS
menu.
	
>How-To-Repeat:
Get HDD which returns serial number longer than 16 chars. And build a raid
with atacontrol command. I confirmed that a HGST 2.5inch HDD(5K250) raise
problems.
	
>Fix:
This is a patch for 8-CURRENT. 
note: HGST HDD returns <real serial nunber> + 0x03 0x00

--- /sys/dev/ata/ata-raid.c	2008-04-17 21:29:35.000000000 +0900
+++ ata/ata-raid.c	2008-05-27 02:37:24.000000000 +0900
@@ -2086,6 +2086,7 @@
     u_int32_t checksum, *ptr;
     int array, count, disk, volume = 1, retval = 0;
     char *tmp;
+    int snlen, snidx;
 
     if (!(meta = (struct intel_raid_conf *)
 	  malloc(1536, M_AR, M_NOWAIT | M_ZERO)))
@@ -2228,8 +2229,18 @@
 	    for (disk = 0; disk < raid->total_disks; disk++) {
 		struct ata_device *atadev = device_get_softc(parent);
 
-		if (!strncmp(raid->disks[disk].serial, atadev->param.serial,
-		    sizeof(raid->disks[disk].serial))) {
+                for (snlen=0;;snlen++) {
+		    if ((char)atadev->param.serial[snlen] == '\0' ||
+		        (char)atadev->param.serial[snlen] == 3) {  /* ascii EOT */
+                        if (snlen < 16)
+			    snidx = 0;
+		        else
+			    snidx = snlen - 16;
+		        break;
+		    }
+	        }
+		if (!strncmp(raid->disks[disk].serial, atadev->param.serial + snidx,
+		    min(snlen,sizeof(raid->disks[disk].serial)))) {
 		    raid->disks[disk].dev = parent;
 		    raid->disks[disk].flags |= (AR_DF_PRESENT | AR_DF_ONLINE);
 		    ars->raid[raid->volume] = raid;
@@ -2273,6 +2284,7 @@
     u_int32_t checksum, *ptr;
     int count, disk, error = 0;
     char *tmp;
+    int snlen,snidx;
 
     if (!(meta = (struct intel_raid_conf *)
 	  malloc(1536, M_AR, M_NOWAIT | M_ZERO))) {
@@ -2299,8 +2311,19 @@
 	    struct ata_device *atadev =
 		device_get_softc(rdp->disks[disk].dev);
 
-	    bcopy(atadev->param.serial, meta->disk[disk].serial,
-		  sizeof(rdp->disks[disk].serial));
+            for (snlen=0;;snlen++) {
+		if ((char)atadev->param.serial[snlen] == '\0' ||
+		    (char)atadev->param.serial[snlen] == 3) {  /* ascii EOT */
+                    if (snlen < 16)
+			snidx = 0;
+		    else {
+			snidx = snlen - 16;
+		    }
+		    break;
+		}
+	    }
+	    bcopy(atadev->param.serial + snidx, meta->disk[disk].serial,
+		  min(snlen,sizeof(rdp->disks[disk].serial)));
 	    meta->disk[disk].sectors = rdp->disks[disk].sectors;
 	    meta->disk[disk].id = (ch->unit << 16) | atadev->unit;
 	}
	

	


>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list