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