summaryrefslogtreecommitdiffstats
path: root/sys/geom/geom_sunlabel.c
diff options
context:
space:
mode:
authorpjd <pjd@FreeBSD.org>2005-04-12 08:14:15 +0000
committerpjd <pjd@FreeBSD.org>2005-04-12 08:14:15 +0000
commitc3333321cc1408dc01b34bbe5e4e00a958bbb90f (patch)
treecf787aa779e121f745f54932f5e942e9c525a2c9 /sys/geom/geom_sunlabel.c
parent8d4424715df1d7399125ea9cbeccfb715f2ab731 (diff)
downloadFreeBSD-src-c3333321cc1408dc01b34bbe5e4e00a958bbb90f.zip
FreeBSD-src-c3333321cc1408dc01b34bbe5e4e00a958bbb90f.tar.gz
Protect against recursive labels creation in simlar way as it is done
in BSD and MBR classes, ie. if provider below us uses the same metadata, don't create labels based on the metadata. This allows to create labels on geoms with rank != 1 without hacks. Tested by: Chris Elsworth <chris@shagged.org> on sparc64 OK'ed by: phk MFC after: 2 weeks
Diffstat (limited to 'sys/geom/geom_sunlabel.c')
-rw-r--r--sys/geom/geom_sunlabel.c52
1 files changed, 46 insertions, 6 deletions
diff --git a/sys/geom/geom_sunlabel.c b/sys/geom/geom_sunlabel.c
index ece8e1e..4c453cd 100644
--- a/sys/geom/geom_sunlabel.c
+++ b/sys/geom/geom_sunlabel.c
@@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$");
#include <sys/malloc.h>
#include <sys/lock.h>
#include <sys/mutex.h>
+#include <sys/md5.h>
#include <sys/sun_disklabel.h>
#include <geom/geom.h>
#include <geom/geom_slice.h>
@@ -57,6 +58,7 @@ struct g_sunlabel_softc {
int nheads;
int nsects;
int nalt;
+ u_char labelsum[16];
};
static int
@@ -65,6 +67,7 @@ g_sunlabel_modify(struct g_geom *gp, struct g_sunlabel_softc *ms, u_char *sec0)
int i, error;
u_int u, v, csize;
struct sun_disklabel sl;
+ MD5_CTX md5sum;
error = sunlabel_dec(sec0, &sl);
if (error)
@@ -96,6 +99,14 @@ g_sunlabel_modify(struct g_geom *gp, struct g_sunlabel_softc *ms, u_char *sec0)
ms->nheads = sl.sl_ntracks;
ms->nsects = sl.sl_nsectors;
+ /*
+ * Calculate MD5 from the first sector and use it for avoiding
+ * recursive labels creation.
+ */
+ MD5Init(&md5sum);
+ MD5Update(&md5sum, sec0, ms->sectorsize);
+ MD5Final(ms->labelsum, &md5sum);
+
return (0);
}
@@ -224,28 +235,43 @@ g_sunlabel_config(struct gctl_req *req, struct g_class *mp, const char *verb)
}
}
+static int
+g_sunlabel_start(struct bio *bp)
+{
+ struct g_sunlabel_softc *mp;
+ struct g_slicer *gsp;
+
+ gsp = bp->bio_to->geom->softc;
+ mp = gsp->softc;
+ if (bp->bio_cmd == BIO_GETATTR) {
+ if (g_handleattr(bp, "SUN::labelsum", mp->labelsum,
+ sizeof(mp->labelsum)))
+ return (1);
+ }
+ return (0);
+}
+
static struct g_geom *
g_sunlabel_taste(struct g_class *mp, struct g_provider *pp, int flags)
{
struct g_geom *gp;
struct g_consumer *cp;
- int error;
- u_char *buf;
struct g_sunlabel_softc *ms;
struct g_slicer *gsp;
+ u_char *buf, hash[16];
+ MD5_CTX md5sum;
+ int error;
g_trace(G_T_TOPOLOGY, "g_sunlabel_taste(%s,%s)", mp->name, pp->name);
g_topology_assert();
if (flags == G_TF_NORMAL &&
!strcmp(pp->geom->class->name, SUNLABEL_CLASS_NAME))
return (NULL);
- gp = g_slice_new(mp, 8, pp, &cp, &ms, sizeof *ms, NULL);
+ gp = g_slice_new(mp, 8, pp, &cp, &ms, sizeof *ms, g_sunlabel_start);
if (gp == NULL)
return (NULL);
gsp = gp->softc;
do {
- if (gp->rank != 2 && flags == G_TF_NORMAL)
- break;
ms->sectorsize = cp->provider->sectorsize;
if (ms->sectorsize < 512)
break;
@@ -254,7 +280,21 @@ g_sunlabel_taste(struct g_class *mp, struct g_provider *pp, int flags)
g_topology_lock();
if (buf == NULL || error != 0)
break;
-
+
+ /*
+ * Calculate MD5 from the first sector and use it for avoiding
+ * recursive labels creation.
+ */
+ MD5Init(&md5sum);
+ MD5Update(&md5sum, buf, ms->sectorsize);
+ MD5Final(ms->labelsum, &md5sum);
+
+ error = g_getattr("SUN::labelsum", cp, &hash);
+ if (!error && !bcmp(ms->labelsum, hash, sizeof(hash))) {
+ g_free(buf);
+ break;
+ }
+
g_sunlabel_modify(gp, ms, buf);
g_free(buf);
OpenPOWER on IntegriCloud