diff options
author | phk <phk@FreeBSD.org> | 2003-01-06 20:10:41 +0000 |
---|---|---|
committer | phk <phk@FreeBSD.org> | 2003-01-06 20:10:41 +0000 |
commit | 158843e06da15c99544420a8a5f176634ea91063 (patch) | |
tree | 5e1e01ed3133ed18ef48f7f90e6a4a977e434544 /sys | |
parent | d68eff9b1bd702ddc58ae0e55c33002de530ed7e (diff) | |
download | FreeBSD-src-158843e06da15c99544420a8a5f176634ea91063.zip FreeBSD-src-158843e06da15c99544420a8a5f176634ea91063.tar.gz |
BSD disklabels expose the controling label though the 'c' partition, and
some trick is necessary to prevent further BSD geoms from attaching to
that. Our old trick was to make sure we don't attach to a geom from
the "BSD" class, but this doesn't work if an intermediary geom obscures
this fact. Instead, calculate the MD5 checksum of the label we target
and ask if anybody below us loves that label. If they do we don't.
Coded by: gordon.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/geom/geom_bsd.c | 38 |
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(); |