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
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;
                        }
_______________________________________________
[EMAIL PROTECTED] mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to "[EMAIL PROTECTED]"

Reply via email to