summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/geom/geom_bsd.c38
1 files changed, 26 insertions, 12 deletions
diff --git a/sys/geom/geom_bsd.c b/sys/geom/geom_bsd.c
index 7d51896..27c4c8a 100644
--- a/sys/geom/geom_bsd.c
+++ b/sys/geom/geom_bsd.c
@@ -36,7 +36,7 @@
*
* This is the method for dealing with BSD disklabels. It has been
* extensively (by my standards at least) commented, in the vain hope that
- * it will server as the source in future copy&paste operations.
+ * it will serve as the source in future copy&paste operations.
*/
#include <sys/param.h>
@@ -56,6 +56,7 @@
#include <sys/mutex.h>
#endif
#include <sys/stdint.h>
+#include <sys/md5.h>
#include <sys/errno.h>
#include <sys/disklabel.h>
#include <geom/geom.h>
@@ -76,6 +77,7 @@ struct g_bsd_softc {
off_t rawoffset;
struct disklabel ondisk;
struct disklabel inram;
+ u_char labelsum[16];
};
/*
@@ -627,6 +629,10 @@ g_bsd_start(struct bio *bp)
g_call_me(g_bsd_hotwrite, bp);
return (EJUSTRETURN);
case BIO_GETATTR:
+ if (g_handleattr(bp, "BSD::labelsum", ms->labelsum,
+ sizeof(ms->labelsum)))
+ return (1);
+ break;
case BIO_SETATTR:
break;
default:
@@ -723,6 +729,8 @@ g_bsd_taste(struct g_class *mp, struct g_provider *pp, int flags)
struct disklabel *dl;
u_int secsize;
struct g_slicer *gsp;
+ MD5_CTX md5sum;
+ u_char hash[16];
g_trace(G_T_TOPOLOGY, "bsd_taste(%s,%s)", mp->name, pp->name);
g_topology_assert();
@@ -732,15 +740,6 @@ g_bsd_taste(struct g_class *mp, struct g_provider *pp, int flags)
return (NULL);
/*
- * The BSD-method will not automatically configure itself recursively
- * Note that it is legal to examine the class-name of our provider,
- * nothing else should ever be examined inside the provider.
- */
- if (flags == G_TF_NORMAL &&
- !strcmp(pp->geom->class->name, BSD_CLASS_NAME))
- return (NULL);
-
- /*
* BSD labels are a subclass of the general "slicing" topology so
* a lot of the work can be done by the common "slice" code.
* Create a geom with space for MAXPARTITIONS providers, one consumer
@@ -779,7 +778,7 @@ g_bsd_taste(struct g_class *mp, struct g_provider *pp, int flags)
/*
* If the provider is an MBR we will only auto attach
* to type 165 slices in the G_TF_NORMAL case. We will
- * attach to any other type (BSD was handles above)
+ * attach to any other type.
*/
error = g_getattr("MBR::type", cp, &i);
if (!error) {
@@ -818,10 +817,25 @@ g_bsd_taste(struct g_class *mp, struct g_provider *pp, int flags)
break;
/*
+ * In order to avoid recursively attaching to the same
+ * on-disk label (it's usually visible through the 'c'
+ * partition) we calculate an MD5 and ask if other BSD's
+ * below us love that label. If they do, we don't.
+ */
+
+ dl = &ms->inram;
+ MD5Init(&md5sum);
+ MD5Update(&md5sum, (u_char *)dl, sizeof(dl));
+ MD5Final(ms->labelsum, &md5sum);
+
+ error = g_getattr("BSD::labelsum", cp, &hash);
+ if (!error && !strncmp(ms->labelsum, hash, sizeof(hash)))
+ break;
+
+ /*
* Process the found disklabel, and modify our "slice"
* instance to match it, if possible.
*/
- dl = &ms->inram;
error = g_bsd_modify(gp, dl); /* Picks up topology lock. */
if (!error)
g_topology_unlock();
OpenPOWER on IntegriCloud