svn commit: r219908 - projects/graid/head/sys/geom/raid

Alexander Motin mav at FreeBSD.org
Wed Mar 23 15:05:48 UTC 2011


Author: mav
Date: Wed Mar 23 15:05:48 2011
New Revision: 219908
URL: http://svn.freebsd.org/changeset/base/219908

Log:
  Add dedicated spare disks support. Some sources report about global spares
  also, but Windows drivers I've tried allow to create only dedicated spares,
  while RAID BIOS can't create any.

Modified:
  projects/graid/head/sys/geom/raid/md_nvidia.c

Modified: projects/graid/head/sys/geom/raid/md_nvidia.c
==============================================================================
--- projects/graid/head/sys/geom/raid/md_nvidia.c	Wed Mar 23 14:18:59 2011	(r219907)
+++ projects/graid/head/sys/geom/raid/md_nvidia.c	Wed Mar 23 15:05:48 2011	(r219908)
@@ -73,7 +73,6 @@ struct nvidia_raid_conf {
 	uint8_t		total_disks;
 	uint8_t		orig_array_width;
 	uint16_t	type;
-#define NVIDIA_T_UNKNOWN	0x0000
 #define NVIDIA_T_RAID0		0x0080
 #define NVIDIA_T_RAID1		0x0081
 #define NVIDIA_T_RAID3		0x0083
@@ -340,23 +339,6 @@ nvidia_meta_erase(struct g_consumer *cp)
 	return (error);
 }
 
-static int
-nvidia_meta_write_spare(struct g_consumer *cp)
-{
-	struct nvidia_raid_conf *meta;
-	int error;
-
-	meta = malloc(sizeof(*meta), M_MD_NVIDIA, M_WAITOK | M_ZERO);
-	memcpy(meta->nvidia_id, NVIDIA_MAGIC, sizeof(NVIDIA_MAGIC));
-	meta->config_size = 30;
-	meta->version = 0x0064;
-	meta->magic_0 = NVIDIA_MAGIC0;
-	meta->type = NVIDIA_T_UNKNOWN;
-	error = nvidia_meta_write(cp, meta);
-	free(meta, M_MD_NVIDIA);
-	return (error);
-}
-
 static struct g_raid_disk *
 g_raid_md_nvidia_get_disk(struct g_raid_softc *sc, int id)
 {
@@ -436,9 +418,11 @@ g_raid_md_nvidia_start_disk(struct g_rai
 	olddisk = NULL;
 
 	/* Find disk position in metadata by it's serial. */
-	if (pd->pd_meta != NULL)
+	if (pd->pd_meta != NULL) {
 		disk_pos = pd->pd_meta->disk_number;
-	else
+		if (disk_pos >= meta->total_disks)
+			disk_pos = -3;
+	} else
 		disk_pos = -3;
 	if (disk_pos < 0) {
 		G_RAID_DEBUG1(1, sc, "Unknown, probably new or stale disk");
@@ -474,15 +458,8 @@ g_raid_md_nvidia_start_disk(struct g_rai
 		}
 		if (olddisk == NULL) {
 nofit:
-			if (disk_pos == -3 || pd->pd_disk_pos == -3) {
-				g_raid_change_disk_state(disk,
-				    G_RAID_DISK_S_SPARE);
-				return (1);
-			} else {
-				g_raid_change_disk_state(disk,
-				    G_RAID_DISK_S_STALE);
-				return (0);
-			}
+			g_raid_change_disk_state(disk, G_RAID_DISK_S_SPARE);
+			return (1);
 		}
 		oldpd = (struct g_raid_md_nvidia_perdisk *)olddisk->d_md_data;
 		disk_pos = oldpd->pd_disk_pos;
@@ -543,7 +520,7 @@ nofit:
 			    G_RAID_SUBDISK_S_NEW);
 		} else if (mdi->mdio_started) {
 			/*
-			 * As soon as we have no generations - treat
+			 * As soon as we have no generations --
 			 * treat every hot-plugged disk as new.
 			 */
 			g_raid_change_subdisk_state(sd,
@@ -555,9 +532,8 @@ nofit:
 			    G_RAID_SUBDISK_S_REBUILD);
 			sd->sd_rebuild_pos = pd->pd_meta->rebuild_lba *
 			    pd->pd_meta->sector_size;
-		} else if (meta->state == NVIDIA_S_SYNC &&
-		    (pd->pd_meta->disk_status & 0x100)) {
-			/* Resyncing disk. */
+		} else if (meta->state == NVIDIA_S_SYNC) {
+			/* Resyncing/dirty disk. */
 			g_raid_change_subdisk_state(sd,
 			    G_RAID_SUBDISK_S_RESYNC);
 			sd->sd_rebuild_pos = pd->pd_meta->rebuild_lba *
@@ -769,19 +745,21 @@ g_raid_md_nvidia_new_disk(struct g_raid_
 		if (g_raid_md_nvidia_start_disk(disk))
 			g_raid_md_write_nvidia(md, NULL, NULL, NULL);
 	} else {
-		if (mdi->mdio_meta == NULL) {
+		if (mdi->mdio_meta == NULL ||
+		    mdi->mdio_meta->disk_number >= mdi->mdio_meta->total_disks) {
 			G_RAID_DEBUG1(1, sc, "Newer disk");
 			if (mdi->mdio_meta != NULL)
 				free(mdi->mdio_meta, M_MD_NVIDIA);
 			mdi->mdio_meta = nvidia_meta_copy(pdmeta);
 			mdi->mdio_total_disks = pdmeta->total_disks;
 			mdi->mdio_disks_present = 1;
-		} else {
+		} else if (pdmeta->disk_number < mdi->mdio_meta->total_disks) {
 			mdi->mdio_disks_present++;
 			G_RAID_DEBUG1(1, sc, "Matching disk (%d of %d up)",
 			    mdi->mdio_disks_present,
 			    mdi->mdio_total_disks);
-		}
+		} else
+			G_RAID_DEBUG1(1, sc, "Spare disk");
 
 		/* If we collected all needed disks - start array. */
 		if (mdi->mdio_disks_present == mdi->mdio_total_disks)
@@ -861,14 +839,14 @@ g_raid_md_taste_nvidia(struct g_raid_md_
 	g_access(cp, -1, 0, 0);
 	if (meta == NULL) {
 		if (g_raid_aggressive_spare) {
-			if (vendor == 0x1095) {
+			if (vendor == 0x10de) {
 				G_RAID_DEBUG(1,
 				    "No NVidia metadata, forcing spare.");
 				spare = 2;
 				goto search;
 			} else {
 				G_RAID_DEBUG(1,
-				    "NVidia vendor mismatch 0x%04x != 0x1095",
+				    "NVidia vendor mismatch 0x%04x != 0x10de",
 				    vendor);
 			}
 		}
@@ -1390,10 +1368,8 @@ g_raid_md_ctl_nvidia(struct g_raid_md_ob
 
 			/* Welcome the "new" disk. */
 			update += g_raid_md_nvidia_start_disk(disk);
-			if (disk->d_state == G_RAID_DISK_S_SPARE) {
-				nvidia_meta_write_spare(cp);
-				g_raid_destroy_disk(disk);
-			} else if (disk->d_state != G_RAID_DISK_S_ACTIVE) {
+			if (disk->d_state != G_RAID_DISK_S_SPARE &&
+			    disk->d_state != G_RAID_DISK_S_ACTIVE) {
 				gctl_error(req, "Disk '%s' doesn't fit.",
 				    diskname);
 				g_raid_destroy_disk(disk);
@@ -1422,7 +1398,7 @@ g_raid_md_write_nvidia(struct g_raid_md_
 	struct g_raid_md_nvidia_object *mdi;
 	struct g_raid_md_nvidia_perdisk *pd;
 	struct nvidia_raid_conf *meta;
-	int i;
+	int i, spares;
 
 	sc = md->mdo_softc;
 	mdi = (struct g_raid_md_nvidia_object *)md;
@@ -1483,7 +1459,8 @@ g_raid_md_write_nvidia(struct g_raid_md_
 	for (i = 0; i < vol->v_disks_count; i++) {
 		sd = &vol->v_subdisks[i];
 		if ((sd->sd_state == G_RAID_SUBDISK_S_STALE ||
-		     sd->sd_state == G_RAID_SUBDISK_S_RESYNC) &&
+		     sd->sd_state == G_RAID_SUBDISK_S_RESYNC ||
+		     vol->v_dirty) &&
 		     meta->state != NVIDIA_S_REBUILD)
 			meta->state = NVIDIA_S_SYNC;
 		else if (sd->sd_state == G_RAID_SUBDISK_S_NEW ||
@@ -1495,10 +1472,11 @@ g_raid_md_write_nvidia(struct g_raid_md_
 	if (mdi->mdio_meta != NULL)
 		free(mdi->mdio_meta, M_MD_NVIDIA);
 	mdi->mdio_meta = meta;
-	i = 0;
+	spares = 0;
 	TAILQ_FOREACH(disk, &sc->sc_disks, d_next) {
 		pd = (struct g_raid_md_nvidia_perdisk *)disk->d_md_data;
-		if (disk->d_state != G_RAID_DISK_S_ACTIVE)
+		if (disk->d_state != G_RAID_DISK_S_ACTIVE &&
+		    disk->d_state != G_RAID_DISK_S_SPARE)
 			continue;
 		if (pd->pd_meta != NULL) {
 			free(pd->pd_meta, M_MD_NVIDIA);
@@ -1512,7 +1490,8 @@ g_raid_md_write_nvidia(struct g_raid_md_
 				pd->pd_meta->rebuild_lba =
 				    sd->sd_rebuild_pos / vol->v_sectorsize;
 			}
-		}
+		} else
+			pd->pd_meta->disk_number = meta->total_disks + spares++;
 		G_RAID_DEBUG(1, "Writing NVidia metadata to %s",
 		    g_raid_get_diskname(disk));
 		g_raid_md_nvidia_print(pd->pd_meta);


More information about the svn-src-projects mailing list