geom_vol_ffs problems

Per Kristian Hove Per.Hove at math.ntnu.no
Mon Jun 9 13:00:45 PDT 2003


The attached patch changes the behaviour of geom_vol_ffs so that:

 - It works even if the file system doesn't fill the partition
   completely (it only checks for file system > mediasize).
 - It does not attach to providers it doesn't know how to handle.
 - It does not attach to sunlabel providers if the slice number is 2.
 - It does not attach to bsdlabel providers if the partition type
   isn't FS_BSDFFS.
 - It does not attach to providers that are attached to consumers
   of other types than "DEV".

The last check is to avoid connecting to submirrors, components of a
RAID5, one specific path of a multipathed fibre channel disk, etc.
(Hopefully, there will be a GEOM_FCAL class that implements load
sharing and fault tolerance in multipathed systems?:-) )

The big question is how to make sure geom_vol_ffs doesn't get the
chance to taste (and attach) before, say, geom_mirror does.

What do you think about this approach?


-- 
Per Kristian Hove
Dept. of Mathematical Sciences
Norwegian University of Science and Technology
-------------- next part --------------
Index: geom_vol_ffs.c
===================================================================
RCS file: /usr/ncvs/src/sys/geom/geom_vol_ffs.c,v
retrieving revision 1.8
diff -u -r1.8 geom_vol_ffs.c
--- geom_vol_ffs.c	2 May 2003 08:21:02 -0000	1.8
+++ geom_vol_ffs.c	9 Jun 2003 19:30:40 -0000
@@ -34,6 +34,7 @@
 #include <sys/bio.h>
 #include <sys/lock.h>
 #include <sys/mutex.h>
+#include <sys/disklabel.h>
 
 #include <ufs/ufs/dinode.h>
 #include <ufs/ffs/fs.h>
@@ -45,6 +46,16 @@
 
 static int superblocks[] = SBLOCKSEARCH;
 
+#define LABELSIZE (148 + 16 * MAXPARTITIONS)
+struct g_bsd_softc {
+	off_t	labeloffset;
+	off_t	mbroffset;
+	off_t	rawoffset;
+	struct disklabel ondisk;
+	u_char	label[LABELSIZE];
+	u_char	labelsum[16];
+};
+
 struct g_vol_ffs_softc {
 	char *	vol;
 };
@@ -59,10 +70,11 @@
 g_vol_ffs_taste(struct g_class *mp, struct g_provider *pp, int flags)
 {
 	struct g_geom *gp;
-	struct g_consumer *cp;
+	struct g_consumer *cp, *tp;
 	struct g_vol_ffs_softc *ms;
 	int error, sb, superblock;
 	struct fs *fs;
+	const char *pclass;
 
 	g_trace(G_T_TOPOLOGY, "vol_taste(%s,%s)", mp->name, pp->name);
 	g_topology_assert();
@@ -71,18 +83,58 @@
 	 * XXX This is a really weak way to make sure we don't recurse.
 	 * Probably ought to use BIO_GETATTR to check for this.
 	 */
+	pclass = pp->geom->class->name;
 	if (flags == G_TF_NORMAL &&
-	    !strcmp(pp->geom->class->name, VOL_FFS_CLASS_NAME))
+	    !strcmp(pclass, VOL_FFS_CLASS_NAME))
 		return (NULL);
 
 	gp = g_slice_new(mp, 1, pp, &cp, &ms, sizeof(*ms), g_vol_ffs_start);
 	if (gp == NULL)
 		return (NULL);
+	/* We can only attach to providers we know how to handle */
+	if (strcmp(pclass, "APPLE") &&
+	    strcmp(pclass, "BDE") &&
+	    strcmp(pclass, "BSD") &&
+	    strcmp(pclass, "DISK") &&
+	    strcmp(pclass, "GPT") &&
+	    strcmp(pclass, "MBR") &&
+	    strcmp(pclass, "PC98") &&
+	    strcmp(pclass, "SUN")) {
+		return (NULL);
+	}
+	/* Don't attach to slice 2 in sunlabels */
+	if (!strcmp(pclass, "SUN") && pp->index == 2) {
+		return (NULL);
+	}
+	/* Don't attach to non-4.2BSD partitions in bsdlabels */
+	if (!strcmp(pclass, "BSD")) {
+		struct g_bsd_softc *ms;
+		struct g_slicer *gsp;
+		u_int8_t type;
+
+		gsp = pp->geom->softc;
+		ms = gsp->softc;
+		type = ms->ondisk.d_partitions[pp->index].p_fstype;
+		if (type != FS_BSDFFS) {
+			return (NULL);
+		}
+	}
+	/* Don't attach to providers that have consumers of
+	 * types other than "DEV" attached to them */
+	LIST_FOREACH(tp, &pp->consumers, consumers) {
+		const char *name = tp->geom->class->name;
+
+		if (strcmp(name, VOL_FFS_CLASS_NAME) &&
+		    strcmp(name, "DEV")) {
+			return (NULL);
+			continue;
+		}
+	}
 	g_topology_unlock();
 	/*
 	 * Walk through the standard places that superblocks hide and look
 	 * for UFS magic. If we find magic, then check that the size in the
-	 * superblock corresponds to the size of the underlying provider.
+	 * superblock does not exceed the size of the underlying provider.
 	 * Finally, look for a volume label and create an appropriate 
 	 * provider based on that.
 	 */
@@ -93,14 +145,12 @@
 			continue;
 		/* Check for magic and make sure things are the right size */
 		if (fs->fs_magic == FS_UFS1_MAGIC) {
-			if (fs->fs_old_size * fs->fs_fsize !=
-			    (int32_t) pp->mediasize) {
+			if (fs->fs_old_size * fs->fs_fsize > pp->mediasize) {
 				g_free(fs);
 				continue;
 			}
 		} else if (fs->fs_magic == FS_UFS2_MAGIC) {
-			if (fs->fs_size * fs->fs_fsize !=
-			    (int64_t) pp->mediasize) {
+			if (fs->fs_size * fs->fs_fsize > pp->mediasize) {
 				g_free(fs);
 				continue;
 			}


More information about the freebsd-current mailing list