Fix wrong sizes used to access PD_Type and PD_State DDF metadata fields.
This caused incorrect behavior of arrays with big-endian DDF metadata. Little-endian (like used by Adaptec controllers) should not be harmed. Add workaround should be enough to manage compatibility. MFC after: 2 weeks
This commit is contained in:
parent
ed8023f58b
commit
1229e83d2b
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=264318
@ -1182,6 +1182,28 @@ ddf_meta_read(struct g_consumer *cp, struct ddf_meta *meta)
|
||||
g_free(buf);
|
||||
if (GET32(meta, pdr->Signature) != DDF_PDR_SIGNATURE)
|
||||
goto hdrerror;
|
||||
/*
|
||||
* Workaround for reading metadata corrupted due to graid bug.
|
||||
* XXX: Remove this before we have disks above 128PB. :)
|
||||
*/
|
||||
if (meta->bigendian) {
|
||||
for (i = 0; i < GET16(meta, pdr->Populated_PDEs); i++) {
|
||||
if (isff(meta->pdr->entry[i].PD_GUID, 24))
|
||||
continue;
|
||||
if (GET32(meta, pdr->entry[i].PD_Reference) ==
|
||||
0xffffffff)
|
||||
continue;
|
||||
if (GET64(meta, pdr->entry[i].Configured_Size) >=
|
||||
(1ULL << 48)) {
|
||||
SET16(meta, pdr->entry[i].PD_State,
|
||||
GET16(meta, pdr->entry[i].PD_State) &
|
||||
~DDF_PDE_FAILED);
|
||||
SET64(meta, pdr->entry[i].Configured_Size,
|
||||
GET64(meta, pdr->entry[i].Configured_Size) &
|
||||
((1ULL << 48) - 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Read virtual disk records. */
|
||||
buf = g_read_data(cp, (lba + GET32(meta, hdr->vdr_section)) * ss,
|
||||
@ -1711,7 +1733,7 @@ g_raid_md_ddf_start_disk(struct g_raid_disk *disk, struct g_raid_volume *vol)
|
||||
/* Welcome the new disk. */
|
||||
if (resurrection)
|
||||
g_raid_change_disk_state(disk, G_RAID_DISK_S_ACTIVE);
|
||||
else if (GET8(gmeta, pdr->entry[md_pde_pos].PD_State) & DDF_PDE_PFA)
|
||||
else if (GET16(gmeta, pdr->entry[md_pde_pos].PD_State) & DDF_PDE_PFA)
|
||||
g_raid_change_disk_state(disk, G_RAID_DISK_S_FAILED);
|
||||
else
|
||||
g_raid_change_disk_state(disk, G_RAID_DISK_S_ACTIVE);
|
||||
@ -1730,11 +1752,11 @@ g_raid_md_ddf_start_disk(struct g_raid_disk *disk, struct g_raid_volume *vol)
|
||||
/* Stale disk, almost same as new. */
|
||||
g_raid_change_subdisk_state(sd,
|
||||
G_RAID_SUBDISK_S_NEW);
|
||||
} else if (GET8(gmeta, pdr->entry[md_pde_pos].PD_State) & DDF_PDE_PFA) {
|
||||
} else if (GET16(gmeta, pdr->entry[md_pde_pos].PD_State) & DDF_PDE_PFA) {
|
||||
/* Failed disk. */
|
||||
g_raid_change_subdisk_state(sd,
|
||||
G_RAID_SUBDISK_S_FAILED);
|
||||
} else if ((GET8(gmeta, pdr->entry[md_pde_pos].PD_State) &
|
||||
} else if ((GET16(gmeta, pdr->entry[md_pde_pos].PD_State) &
|
||||
(DDF_PDE_FAILED | DDF_PDE_REBUILD)) != 0) {
|
||||
/* Rebuilding disk. */
|
||||
g_raid_change_subdisk_state(sd,
|
||||
@ -2833,24 +2855,24 @@ g_raid_md_write_ddf(struct g_raid_md_object *md, struct g_raid_volume *tvol,
|
||||
GET32(vmeta, bvdc[bvd]->Physical_Disk_Sequence[pos]));
|
||||
if (j < 0)
|
||||
continue;
|
||||
SET32(gmeta, pdr->entry[j].PD_Type,
|
||||
GET32(gmeta, pdr->entry[j].PD_Type) |
|
||||
SET16(gmeta, pdr->entry[j].PD_Type,
|
||||
GET16(gmeta, pdr->entry[j].PD_Type) |
|
||||
DDF_PDE_PARTICIPATING);
|
||||
if (sd->sd_state == G_RAID_SUBDISK_S_NONE)
|
||||
SET32(gmeta, pdr->entry[j].PD_State,
|
||||
GET32(gmeta, pdr->entry[j].PD_State) |
|
||||
SET16(gmeta, pdr->entry[j].PD_State,
|
||||
GET16(gmeta, pdr->entry[j].PD_State) |
|
||||
(DDF_PDE_FAILED | DDF_PDE_MISSING));
|
||||
else if (sd->sd_state == G_RAID_SUBDISK_S_FAILED)
|
||||
SET32(gmeta, pdr->entry[j].PD_State,
|
||||
GET32(gmeta, pdr->entry[j].PD_State) |
|
||||
SET16(gmeta, pdr->entry[j].PD_State,
|
||||
GET16(gmeta, pdr->entry[j].PD_State) |
|
||||
(DDF_PDE_FAILED | DDF_PDE_PFA));
|
||||
else if (sd->sd_state <= G_RAID_SUBDISK_S_REBUILD)
|
||||
SET32(gmeta, pdr->entry[j].PD_State,
|
||||
GET32(gmeta, pdr->entry[j].PD_State) |
|
||||
SET16(gmeta, pdr->entry[j].PD_State,
|
||||
GET16(gmeta, pdr->entry[j].PD_State) |
|
||||
DDF_PDE_REBUILD);
|
||||
else
|
||||
SET32(gmeta, pdr->entry[j].PD_State,
|
||||
GET32(gmeta, pdr->entry[j].PD_State) |
|
||||
SET16(gmeta, pdr->entry[j].PD_State,
|
||||
GET16(gmeta, pdr->entry[j].PD_State) |
|
||||
DDF_PDE_ONLINE);
|
||||
}
|
||||
}
|
||||
@ -2863,8 +2885,8 @@ g_raid_md_write_ddf(struct g_raid_md_object *md, struct g_raid_volume *tvol,
|
||||
if (i < 0)
|
||||
continue;
|
||||
if (disk->d_state == G_RAID_DISK_S_FAILED) {
|
||||
SET32(gmeta, pdr->entry[i].PD_State,
|
||||
GET32(gmeta, pdr->entry[i].PD_State) |
|
||||
SET16(gmeta, pdr->entry[i].PD_State,
|
||||
GET16(gmeta, pdr->entry[i].PD_State) |
|
||||
(DDF_PDE_FAILED | DDF_PDE_PFA));
|
||||
}
|
||||
if (disk->d_state != G_RAID_DISK_S_SPARE)
|
||||
@ -2881,8 +2903,8 @@ g_raid_md_write_ddf(struct g_raid_md_object *md, struct g_raid_volume *tvol,
|
||||
GET16(gmeta, pdr->entry[i].PD_Type) |
|
||||
DDF_PDE_CONFIG_SPARE);
|
||||
}
|
||||
SET32(gmeta, pdr->entry[i].PD_State,
|
||||
GET32(gmeta, pdr->entry[i].PD_State) |
|
||||
SET16(gmeta, pdr->entry[i].PD_State,
|
||||
GET16(gmeta, pdr->entry[i].PD_State) |
|
||||
DDF_PDE_ONLINE);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user