Date: Sat, 06 Sep 2008 02:15:39 +0900 From: Hideki SAKAMOTO <hsakamt@tsnr.com> To: Remko Lodder <remko@FreeBSD.org> Cc: freebsd-bugs@FreeBSD.org Subject: Re: kern/95459: Rebooting the system while rebuilding RAID (Intel MatrixRAID) results in data loss Message-ID: <48C1693B.3020307@tsnr.com> In-Reply-To: <48C13376.8060408@FreeBSD.org> References: <200809050240.m852e3rY083906@freefall.freebsd.org> <48C13376.8060408@FreeBSD.org>
next in thread | previous in thread | raw e-mail | index | archive | help
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@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);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?48C1693B.3020307>