svn commit: r264869 - stable/9/sys/geom/raid

Alexander Motin mav at FreeBSD.org
Thu Apr 24 10:23:12 UTC 2014


Author: mav
Date: Thu Apr 24 10:23:11 2014
New Revision: 264869
URL: http://svnweb.freebsd.org/changeset/base/264869

Log:
  MFC r264318:
  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.

Modified:
  stable/9/sys/geom/raid/md_ddf.c
Directory Properties:
  stable/9/   (props changed)
  stable/9/sys/   (props changed)

Modified: stable/9/sys/geom/raid/md_ddf.c
==============================================================================
--- stable/9/sys/geom/raid/md_ddf.c	Thu Apr 24 10:22:00 2014	(r264868)
+++ stable/9/sys/geom/raid/md_ddf.c	Thu Apr 24 10:23:11 2014	(r264869)
@@ -1182,6 +1182,28 @@ hdrerror:
 	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 @@ nofit:
 	/* 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 @@ nofit:
 		/* 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,
@@ -2832,24 +2854,24 @@ g_raid_md_write_ddf(struct g_raid_md_obj
 			    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);
 		}
 	}
@@ -2862,8 +2884,8 @@ g_raid_md_write_ddf(struct g_raid_md_obj
 		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)
@@ -2880,8 +2902,8 @@ g_raid_md_write_ddf(struct g_raid_md_obj
 			    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);
 	}
 


More information about the svn-src-stable-9 mailing list