kern/95459: Rebooting the system while rebuilding RAID (Intel
MatrixRAID) results in data loss
Hideki SAKAMOTO
hsakamt at tsnr.com
Fri Sep 5 17:33:14 UTC 2008
Remko Lodder wrote:
> Hideki SAKAMOTO wrote:
>
> The patch is unreadable. Can you please attach it inline, or make it
> available online somewhere?
>
> Thanks,
> remko
>
Oh, sorry. I sent the mail to bug-followup at FreeBSD.org using "Submit Followup"
link in GNATS website. I can read the patch at:
http://www.freebsd.org/cgi/query-pr.cgi?pr=kern/95459
(I don't know why but download link was broken.)
I attach the patch inline just in case.
Thanks,
---
Hideki Sakamoto
===== ata-raid.h.patch: common file for 6_STABLE and 7_STABLE =====
*** ata-raid.h.orig Sat Sep 30 23:51:49 2006
--- ata-raid.h Thu Sep 4 18:35:15 2008
***************
*** 323,329 ****
u_int64_t total_sectors __packed;
u_int32_t state;
u_int32_t reserved;
! u_int32_t filler_0[20];
u_int32_t offset;
u_int32_t disk_sectors;
u_int32_t stripe_count;
--- 323,336 ----
u_int64_t total_sectors __packed;
u_int32_t state;
u_int32_t reserved;
! u_int32_t filler_0[12];
! u_int32_t rebuild_count;
! u_int32_t dummy;
! u_int32_t rebuild_flag;
! #define INTEL_RF_NORMAL 0x00000100
! #define INTEL_RF_REBUILDING 0x00000001
!
! u_int32_t filler_1[5];
u_int32_t offset;
u_int32_t disk_sectors;
u_int32_t stripe_count;
***************
*** 341,347 ****
u_int8_t total_disks;
u_int8_t magic[3];
! u_int32_t filler_1[7];
u_int32_t disk_idx[1];
} __packed;
--- 348,354 ----
u_int8_t total_disks;
u_int8_t magic[3];
! u_int32_t filler_2[7];
u_int32_t disk_idx[1];
} __packed;
========== ata-raid.c.patch6: for 6_STABLE ==========
*** ata-raid.c.orig Thu Sep 4 18:40:36 2008
--- ata-raid.c Fri Sep 5 10:52:01 2008
***************
*** 1286,1291 ****
--- 1286,1293 ----
if (count) {
rdp->rebuild_lba = 0;
rdp->status |= AR_S_REBUILDING;
+ if (rdp->format == AR_F_INTEL_RAID)
+ ata_raid_config_changed(rdp, 1);
return 0;
}
return EIO;
***************
*** 2135,2140 ****
--- 2137,2153 ----
raid->status |= AR_S_DEGRADED;
break;
case INTEL_S_DISABLED:
+ raid->status |= AR_S_READY;
+ /*
+ * rollback to DEGRADED mode because /bin/dd cann't kick
+ * like atacontrol(8) at this moment.
+ *
+ * I checked the code below by execute /bin/dd on shell.
+ *
+ * if ((map->rebuild_flag & INTEL_RF_REBUILDING) && map->magic[1] != 0xff)
+ * raid->status |= (AR_S_REBUILDING|AR_S_DEGRADED);
+ */
+ break;
case INTEL_S_FAILURE:
raid->status = 0;
}
***************
*** 2164,2171 ****
raid->disks[disk].sectors =
meta->disk[map->disk_idx[disk]].sectors;
raid->disks[disk].flags = 0;
! if (meta->disk[map->disk_idx[disk]].flags & INTEL_F_ONLINE)
! raid->disks[disk].flags |= AR_DF_ONLINE;
if (meta->disk[map->disk_idx[disk]].flags & INTEL_F_ASSIGNED)
raid->disks[disk].flags |= AR_DF_ASSIGNED;
if (meta->disk[map->disk_idx[disk]].flags & INTEL_F_SPARE) {
--- 2177,2190 ----
raid->disks[disk].sectors =
meta->disk[map->disk_idx[disk]].sectors;
raid->disks[disk].flags = 0;
! if (meta->disk[map->disk_idx[disk]].flags & INTEL_F_ONLINE) {
! if ((map->rebuild_flag & INTEL_RF_REBUILDING) && disk == map->magic[1]) {
! raid->disks[disk].flags |= AR_DF_SPARE;
! // raid->rebuild_lba = map->rebuild_count ...;
! } else {
! raid->disks[disk].flags |= AR_DF_ONLINE;
! }
! }
if (meta->disk[map->disk_idx[disk]].flags & INTEL_F_ASSIGNED)
raid->disks[disk].flags |= AR_DF_ASSIGNED;
if (meta->disk[map->disk_idx[disk]].flags & INTEL_F_SPARE) {
***************
*** 2183,2189 ****
if (!strncmp(raid->disks[disk].serial, atadev->param.serial,
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;
ars->disk_number[raid->volume] = disk;
retval = 1;
--- 2202,2208 ----
if (!strncmp(raid->disks[disk].serial, atadev->param.serial,
sizeof(raid->disks[disk].serial))) {
raid->disks[disk].dev = parent;
! raid->disks[disk].flags |= AR_DF_PRESENT;
ars->raid[raid->volume] = raid;
ars->disk_number[raid->volume] = disk;
retval = 1;
***************
*** 2222,2229 ****
struct intel_raid_conf *meta;
struct intel_raid_mapping *map;
struct timeval timestamp;
! u_int32_t checksum, *ptr;
int count, disk, error = 0;
char *tmp;
if (!(meta = (struct intel_raid_conf *)
--- 2241,2249 ----
struct intel_raid_conf *meta;
struct intel_raid_mapping *map;
struct timeval timestamp;
! u_int32_t checksum, *ptr, rebuild_flag = INTEL_RF_NORMAL;
int count, disk, error = 0;
+ u_int8_t rebuild_target = 0xff;
char *tmp;
if (!(meta = (struct intel_raid_conf *)
***************
*** 2253,2282 ****
meta->disk[disk].sectors = rdp->disks[disk].sectors;
meta->disk[disk].id = (ch->unit << 16) | ATA_DEV(atadev->unit);
}
! else
meta->disk[disk].sectors = rdp->total_sectors / rdp->width;
meta->disk[disk].flags = 0;
! if (rdp->disks[disk].flags & AR_DF_SPARE)
meta->disk[disk].flags |= INTEL_F_SPARE;
! else {
! if (rdp->disks[disk].flags & AR_DF_ONLINE)
meta->disk[disk].flags |= INTEL_F_ONLINE;
else
meta->disk[disk].flags |= INTEL_F_DOWN;
if (rdp->disks[disk].flags & AR_DF_ASSIGNED)
meta->disk[disk].flags |= INTEL_F_ASSIGNED;
}
}
map = (struct intel_raid_mapping *)&meta->disk[meta->total_disks];
bcopy(rdp->name, map->name, sizeof(rdp->name));
map->total_sectors = rdp->total_sectors;
! map->state = 12; /* XXX SOS */
map->offset = rdp->offset_sectors;
map->stripe_count = rdp->total_sectors / (rdp->interleave*rdp->total_disks);
map->stripe_sectors = rdp->interleave;
map->disk_sectors = rdp->total_sectors / rdp->width;
! map->status = INTEL_S_READY; /* XXX SOS */
switch (rdp->type) {
case AR_T_RAID0:
map->type = INTEL_T_RAID0;
--- 2273,2330 ----
meta->disk[disk].sectors = rdp->disks[disk].sectors;
meta->disk[disk].id = (ch->unit << 16) | ATA_DEV(atadev->unit);
}
! else {
meta->disk[disk].sectors = rdp->total_sectors / rdp->width;
+ meta->disk[disk].id = 0xffffffff;
+ }
meta->disk[disk].flags = 0;
! /*
! * Rebuilding status:
! * driver:
! * - AR_DF_ONLINE is NOT set on mirror drive.
! * - AR_S_REBUILDING is set.
! * - AR_DF_SPARE is set on mirror drive.
! * BIOS:
! * - INTEL_F_ONLINE is set on both master and mirror drive.
! * - INTEL_RF_REBUILDING is set.
! * - mirror's drive number is in magic[1].
! */
! if ((rdp->disks[disk].flags & AR_DF_SPARE) &&
! (!(rdp->status & AR_S_REBUILDING) || (rebuild_target != 0xff))) {
meta->disk[disk].flags |= INTEL_F_SPARE;
! } else {
! if ((rdp->disks[disk].flags & (AR_DF_ONLINE|AR_DF_SPARE)))
meta->disk[disk].flags |= INTEL_F_ONLINE;
else
meta->disk[disk].flags |= INTEL_F_DOWN;
if (rdp->disks[disk].flags & AR_DF_ASSIGNED)
meta->disk[disk].flags |= INTEL_F_ASSIGNED;
+ if (rdp->disks[disk].flags & AR_DF_SPARE) {
+ rebuild_target = (u_int8_t)disk;
+ rebuild_flag |= INTEL_RF_REBUILDING;
+ }
}
}
map = (struct intel_raid_mapping *)&meta->disk[meta->total_disks];
bcopy(rdp->name, map->name, sizeof(rdp->name));
map->total_sectors = rdp->total_sectors;
! map->state = 268; /* XXX */
map->offset = rdp->offset_sectors;
map->stripe_count = rdp->total_sectors / (rdp->interleave*rdp->total_disks);
map->stripe_sectors = rdp->interleave;
map->disk_sectors = rdp->total_sectors / rdp->width;
! map->rebuild_count = map->stripe_count / 2; /* XXX */
! map->rebuild_flag = rebuild_flag;
! if (rdp->status & AR_S_REBUILDING) { /* keep this order */
! map->status = INTEL_S_DISABLED;
! } else if (rdp->status & AR_S_READY) {
! map->status = INTEL_S_READY;
! } else if (rdp->status & AR_S_DEGRADED) {
! map->status = INTEL_S_DEGRADED;
! } else {
! map->status = INTEL_S_FAILURE;
! }
switch (rdp->type) {
case AR_T_RAID0:
map->type = INTEL_T_RAID0;
***************
*** 2296,2302 ****
}
map->total_disks = rdp->total_disks;
map->magic[0] = 0x02;
! map->magic[1] = 0xff;
map->magic[2] = 0x01;
for (disk = 0; disk < rdp->total_disks; disk++)
map->disk_idx[disk] = disk;
--- 2344,2350 ----
}
map->total_disks = rdp->total_disks;
map->magic[0] = 0x02;
! map->magic[1] = rebuild_target;
map->magic[2] = 0x01;
for (disk = 0; disk < rdp->total_disks; disk++)
map->disk_idx[disk] = disk;
***************
*** 4530,4535 ****
--- 4578,4585 ----
printf("total_sectors %ju\n", map->total_sectors);
printf("state %u\n", map->state);
printf("reserved %u\n", map->reserved);
+ printf("rebuild_count %u\n", map->rebuild_count);
+ printf("rebuild_flag 0x%08x\n", map->rebuild_flag);
printf("offset %u\n", map->offset);
printf("disk_sectors %u\n", map->disk_sectors);
printf("stripe_count %u\n", map->stripe_count);
========== ata-raid.c.patch7: for 7_STABLE ==========
*** ata-raid.c.orig Tue Aug 14 03:46:31 2007
--- ata-raid.c Fri Sep 5 01:21:26 2008
***************
*** 1325,1330 ****
--- 1325,1332 ----
if (count) {
rdp->rebuild_lba = 0;
rdp->status |= AR_S_REBUILDING;
+ if (rdp->format == AR_F_INTEL_RAID)
+ ata_raid_config_changed(rdp, 1);
return 0;
}
return EIO;
***************
*** 2174,2179 ****
--- 2176,2191 ----
raid->status |= AR_S_DEGRADED;
break;
case INTEL_S_DISABLED:
+ raid->status = AR_S_READY;
+ /*
+ * rollback to DEGRADED mode because /bin/dd cann't kick
+ * like atacontrol(8) at this moment.
+ *
+ * I checked the code below by execute /bin/dd on shell.
+ * if (map->rebuild_flag & INTEL_RF_REBUILDING && map->magic[1] != 0xff)
+ * raid->status |= (AR_S_REBUILDING|AR_S_DEGRADED);
+ */
+ break;
case INTEL_S_FAILURE:
raid->status = 0;
}
***************
*** 2203,2210 ****
raid->disks[disk].sectors =
meta->disk[map->disk_idx[disk]].sectors;
raid->disks[disk].flags = 0;
! if (meta->disk[map->disk_idx[disk]].flags & INTEL_F_ONLINE)
! raid->disks[disk].flags |= AR_DF_ONLINE;
if (meta->disk[map->disk_idx[disk]].flags & INTEL_F_ASSIGNED)
raid->disks[disk].flags |= AR_DF_ASSIGNED;
if (meta->disk[map->disk_idx[disk]].flags & INTEL_F_SPARE) {
--- 2215,2228 ----
raid->disks[disk].sectors =
meta->disk[map->disk_idx[disk]].sectors;
raid->disks[disk].flags = 0;
! if (meta->disk[map->disk_idx[disk]].flags & INTEL_F_ONLINE) {
! if ((map->rebuild_flag & INTEL_RF_REBUILDING) && disk == map->magic[1]) {
! raid->disks[disk].flags |= AR_DF_SPARE;
! // raid->rebuild_lba = map->rebuild_count ...;
! } else {
! raid->disks[disk].flags |= AR_DF_ONLINE;
! }
! }
if (meta->disk[map->disk_idx[disk]].flags & INTEL_F_ASSIGNED)
raid->disks[disk].flags |= AR_DF_ASSIGNED;
if (meta->disk[map->disk_idx[disk]].flags & INTEL_F_SPARE) {
***************
*** 2222,2228 ****
if (!strncmp(raid->disks[disk].serial, atadev->param.serial,
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;
ars->disk_number[raid->volume] = disk;
retval = 1;
--- 2240,2246 ----
if (!strncmp(raid->disks[disk].serial, atadev->param.serial,
sizeof(raid->disks[disk].serial))) {
raid->disks[disk].dev = parent;
! raid->disks[disk].flags |= AR_DF_PRESENT;
ars->raid[raid->volume] = raid;
ars->disk_number[raid->volume] = disk;
retval = 1;
***************
*** 2261,2268 ****
struct intel_raid_conf *meta;
struct intel_raid_mapping *map;
struct timeval timestamp;
! u_int32_t checksum, *ptr;
int count, disk, error = 0;
char *tmp;
if (!(meta = (struct intel_raid_conf *)
--- 2279,2287 ----
struct intel_raid_conf *meta;
struct intel_raid_mapping *map;
struct timeval timestamp;
! u_int32_t checksum, *ptr, rebuild_flag = INTEL_RF_NORMAL;
int count, disk, error = 0;
+ u_int8_t rebuild_target = 0xff;
char *tmp;
if (!(meta = (struct intel_raid_conf *)
***************
*** 2292,2321 ****
meta->disk[disk].sectors = rdp->disks[disk].sectors;
meta->disk[disk].id = (ch->unit << 16) | ATA_DEV(atadev->unit);
}
! else
meta->disk[disk].sectors = rdp->total_sectors / rdp->width;
meta->disk[disk].flags = 0;
! if (rdp->disks[disk].flags & AR_DF_SPARE)
meta->disk[disk].flags |= INTEL_F_SPARE;
! else {
! if (rdp->disks[disk].flags & AR_DF_ONLINE)
meta->disk[disk].flags |= INTEL_F_ONLINE;
else
meta->disk[disk].flags |= INTEL_F_DOWN;
if (rdp->disks[disk].flags & AR_DF_ASSIGNED)
meta->disk[disk].flags |= INTEL_F_ASSIGNED;
}
}
map = (struct intel_raid_mapping *)&meta->disk[meta->total_disks];
bcopy(rdp->name, map->name, sizeof(rdp->name));
map->total_sectors = rdp->total_sectors;
! map->state = 12; /* XXX SOS */
map->offset = rdp->offset_sectors;
map->stripe_count = rdp->total_sectors / (rdp->interleave*rdp->total_disks);
map->stripe_sectors = rdp->interleave;
map->disk_sectors = rdp->total_sectors / rdp->width;
! map->status = INTEL_S_READY; /* XXX SOS */
switch (rdp->type) {
case AR_T_RAID0:
map->type = INTEL_T_RAID0;
--- 2311,2368 ----
meta->disk[disk].sectors = rdp->disks[disk].sectors;
meta->disk[disk].id = (ch->unit << 16) | ATA_DEV(atadev->unit);
}
! else {
meta->disk[disk].sectors = rdp->total_sectors / rdp->width;
+ meta->disk[disk].id = 0xffffffff;
+ }
meta->disk[disk].flags = 0;
! /*
! * Rebuilding status:
! * driver:
! * - AR_DF_ONLINE is NOT set on mirror drive.
! * - AR_S_REBUILDING is set.
! * - AR_DF_SPARE is set on mirror drive.
! * BIOS:
! * - INTEL_F_ONLINE is set on both master and mirror drive.
! * - INTEL_RF_REBUILDING is set.
! * - mirror's drive number is in magic[1].
! */
! if ((rdp->disks[disk].flags & AR_DF_SPARE) &&
! (!(rdp->status & AR_S_REBUILDING) || (rebuild_target != 0xff))) {
meta->disk[disk].flags |= INTEL_F_SPARE;
! } else {
! if (rdp->disks[disk].flags & (AR_DF_ONLINE|AR_DF_SPARE))
meta->disk[disk].flags |= INTEL_F_ONLINE;
else
meta->disk[disk].flags |= INTEL_F_DOWN;
if (rdp->disks[disk].flags & AR_DF_ASSIGNED)
meta->disk[disk].flags |= INTEL_F_ASSIGNED;
+ if (rdp->disks[disk].flags & AR_DF_SPARE) {
+ rebuild_target = (u_int8_t)disk;
+ rebuild_flag = INTEL_RF_REBUILDING;
+ }
}
}
map = (struct intel_raid_mapping *)&meta->disk[meta->total_disks];
bcopy(rdp->name, map->name, sizeof(rdp->name));
map->total_sectors = rdp->total_sectors;
! map->state = 268; /* XXX */
map->offset = rdp->offset_sectors;
map->stripe_count = rdp->total_sectors / (rdp->interleave*rdp->total_disks);
map->stripe_sectors = rdp->interleave;
map->disk_sectors = rdp->total_sectors / rdp->width;
! map->rebuild_count = map->stripe_count / 2; /* XXX */
! map->rebuild_flag = rebuild_flag;
! if (rdp->status & AR_S_REBUILDING) { /* keep this order */
! map->status = INTEL_S_DISABLED;
! } else if (rdp->status & AR_S_READY) {
! map->status = INTEL_S_READY;
! } else if (rdp->status & AR_S_DEGRADED) {
! map->status = INTEL_S_DEGRADED;
! } else {
! map->status = INTEL_S_FAILURE;
! }
switch (rdp->type) {
case AR_T_RAID0:
map->type = INTEL_T_RAID0;
***************
*** 2335,2341 ****
}
map->total_disks = rdp->total_disks;
map->magic[0] = 0x02;
! map->magic[1] = 0xff;
map->magic[2] = 0x01;
for (disk = 0; disk < rdp->total_disks; disk++)
map->disk_idx[disk] = disk;
--- 2382,2388 ----
}
map->total_disks = rdp->total_disks;
map->magic[0] = 0x02;
! map->magic[1] = rebuild_target;
map->magic[2] = 0x01;
for (disk = 0; disk < rdp->total_disks; disk++)
map->disk_idx[disk] = disk;
***************
*** 4572,4577 ****
--- 4619,4626 ----
printf("total_sectors %ju\n", map->total_sectors);
printf("state %u\n", map->state);
printf("reserved %u\n", map->reserved);
+ printf("rebuild_count %u\n", map->rebuild_count);
+ printf("rebuild_flag 0x%08x\n", map->rebuild_flag);
printf("offset %u\n", map->offset);
printf("disk_sectors %u\n", map->disk_sectors);
printf("stripe_count %u\n", map->stripe_count);
More information about the freebsd-bugs
mailing list