summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/geom/geom.h30
-rw-r--r--sys/geom/geom_bsd.c16
-rw-r--r--sys/geom/geom_dump.c19
-rw-r--r--sys/geom/geom_mbr.c8
-rw-r--r--sys/geom/geom_subr.c33
-rw-r--r--sys/geom/geom_sunlabel.c5
6 files changed, 108 insertions, 3 deletions
diff --git a/sys/geom/geom.h b/sys/geom/geom.h
index dafe65e..8fdf07d 100644
--- a/sys/geom/geom.h
+++ b/sys/geom/geom.h
@@ -61,6 +61,7 @@ struct g_event;
struct thread;
struct bio;
struct sbuf;
+struct g_magicspaces;
typedef struct g_geom * g_create_geom_t (struct g_class *mp,
@@ -122,6 +123,7 @@ struct g_geom {
void *softc;
struct g_event *event;
unsigned flags;
+ struct g_magicspaces *magicspaces;
#define G_GEOM_WITHER 1
};
@@ -172,6 +174,32 @@ struct g_provider {
off_t mediasize;
};
+/*
+ * Some methods may implement various "magic spaces", this is reserved
+ * or magic areas on the disk, set a side for various and sundry purposes.
+ * A good example is the BSD disklabel and boot code on i386 which occupies
+ * a total of four magic spaces: boot1, the disklabel, the padding behind
+ * the disklabel and boot2. The reason we don't simply tell people to
+ * write the appropriate stuff on the underlying device is that (some of)
+ * the magic spaces might be real-time modifiable. It is for instance
+ * possible to change a disklabel while partitions are open, provided
+ * the open partitions do not get trampled in the process.
+ */
+
+struct g_magicspace {
+ char name[8];
+ off_t offset;
+ u_int len;
+ u_int flags;
+};
+
+struct g_magicspaces {
+ uintptr_t geom_id;
+ char class[8];
+ uint nmagic;
+ struct g_magicspace *magicspace;
+};
+
/* geom_dump.c */
void g_hexdump(void *ptr, int length);
void g_trace(int level, char *, ...);
@@ -195,6 +223,7 @@ void g_silence(void);
int g_access_abs(struct g_consumer *cp, int read, int write, int exclusive);
int g_access_rel(struct g_consumer *cp, int read, int write, int exclusive);
void g_add_class(struct g_class *mp);
+int g_add_magicspace(struct g_geom *gp, u_int index, const char *name, off_t start, u_int len, u_int flags);
int g_attach(struct g_consumer *cp, struct g_provider *pp);
struct g_geom *g_create_geomf(char *class, struct g_provider *, char *fmt, ...);
void g_destroy_consumer(struct g_consumer *cp);
@@ -210,6 +239,7 @@ int g_haveattr_off_t(struct bio *bp, char *attribute, off_t val);
struct g_geom * g_insert_geom(char *class, struct g_consumer *cp);
struct g_consumer * g_new_consumer(struct g_geom *gp);
struct g_geom * g_new_geomf(struct g_class *mp, char *fmt, ...);
+int g_new_magicspaces(struct g_geom *gp, int nspaces);
struct g_provider * g_new_providerf(struct g_geom *gp, char *fmt, ...);
void g_sanity(void *ptr);
void g_spoil(struct g_provider *pp, struct g_consumer *cp);
diff --git a/sys/geom/geom_bsd.c b/sys/geom/geom_bsd.c
index 9b94e45..3e5ed6f 100644
--- a/sys/geom/geom_bsd.c
+++ b/sys/geom/geom_bsd.c
@@ -338,8 +338,22 @@ g_bsd_taste(struct g_class *mp, struct g_provider *pp, int flags)
error, (long long)mediasize);
}
error = g_bsd_try(gsp, cp, secsize, ms, secsize);
- if (error)
+ if (!error) {
+ g_new_magicspaces(gp, 4);
+ g_add_magicspace(gp, 0, "boot1", 0, 512, 0);
+ g_add_magicspace(gp, 1, "label", 512, 276, 0);
+ g_add_magicspace(gp, 2, "fill0", 748, 236, 0);
+ g_add_magicspace(gp, 3, "boot2", 1024, 7168, 0);
+ }
+ if (error) {
error = g_bsd_try(gsp, cp, secsize, ms, 64);
+ if (!error) {
+ g_new_magicspaces(gp, 3);
+ g_add_magicspace(gp, 0, "fill0", 0, 64, 0);
+ g_add_magicspace(gp, 1, "label", 64, 276, 0);
+ g_add_magicspace(gp, 2, "fill1", 340, 172, 0);
+ }
+ }
if (error)
break;
dl = &ms->ondisk;
diff --git a/sys/geom/geom_dump.c b/sys/geom/geom_dump.c
index 619e0ed..dcaee02 100644
--- a/sys/geom/geom_dump.c
+++ b/sys/geom/geom_dump.c
@@ -157,11 +157,30 @@ g_conf_geom(struct sbuf *sb, struct g_geom *gp, struct g_provider *pp, struct g_
{
struct g_consumer *cp2;
struct g_provider *pp2;
+ struct g_magicspace *gsp;
+ u_int u;
sbuf_printf(sb, " <geom id=\"%p\">\n", gp);
sbuf_printf(sb, " <class ref=\"%p\"/>\n", gp->class);
sbuf_printf(sb, " <name>%s</name>\n", gp->name);
sbuf_printf(sb, " <rank>%d</rank>\n", gp->rank);
+ if (gp->magicspaces) {
+ for (u = 0; u < gp->magicspaces->nmagic; u++) {
+ gsp = &gp->magicspaces->magicspace[u];
+ if (gsp->len == 0 || gsp->name == NULL)
+ continue;
+ sbuf_printf(sb, " <magicspace>\n");
+ sbuf_printf(sb, " <name>%.8s</name>\n",
+ gsp->name);
+ sbuf_printf(sb, " <offset>%lld</offset>\n",
+ (long long)gsp->offset);
+ sbuf_printf(sb, " <length>%u</length>\n",
+ gsp->len);
+ sbuf_printf(sb, " <flags>%u</flags>\n",
+ gsp->flags);
+ sbuf_printf(sb, " </magicspace>\n");
+ }
+ }
if (gp->dumpconf) {
sbuf_printf(sb, " <config>\n");
gp->dumpconf(sb, "\t", gp, NULL, NULL);
diff --git a/sys/geom/geom_mbr.c b/sys/geom/geom_mbr.c
index 2143bf0..fdb98aa 100644
--- a/sys/geom/geom_mbr.c
+++ b/sys/geom/geom_mbr.c
@@ -234,6 +234,10 @@ g_mbr_taste(struct g_class *mp, struct g_provider *pp, int insist)
g_topology_lock();
error = g_access_rel(cp, -1, 0, 0);
if (npart > 0) {
+ g_new_magicspaces(gp, 3);
+ g_add_magicspace(gp, 0, "boot", 0, DOSPARTOFF, 0);
+ g_add_magicspace(gp, 1, "mbr", DOSPARTOFF, 4 * 16, 0);
+ g_add_magicspace(gp, 2, "signature", 510, 2, 0);
LIST_FOREACH(pp, &gp->provider, provider)
g_error_provider(pp, 0);
return (gp);
@@ -380,8 +384,10 @@ g_mbrext_taste(struct g_class *mp, struct g_provider *pp, int insist __unused)
}
g_topology_lock();
error = g_access_rel(cp, -1, 0, 0);
- if (slice > 0)
+ if (slice > 0) {
+ /* XXX: add magic spaces */
return (gp);
+ }
g_topology_assert();
g_std_spoiled(cp);
diff --git a/sys/geom/geom_subr.c b/sys/geom/geom_subr.c
index d672c3d..1b2dc2e 100644
--- a/sys/geom/geom_subr.c
+++ b/sys/geom/geom_subr.c
@@ -114,6 +114,35 @@ g_new_geomf(struct g_class *mp, char *fmt, ...)
return (gp);
}
+int
+g_new_magicspaces(struct g_geom *gp, int nspaces)
+{
+ gp->magicspaces = g_malloc(sizeof *gp->magicspaces, M_WAITOK | M_ZERO);
+ gp->magicspaces->magicspace =
+ g_malloc(sizeof *gp->magicspaces->magicspace * nspaces,
+ M_WAITOK | M_ZERO);
+ gp->magicspaces->geom_id = (uintptr_t)gp;
+ strncpy(gp->magicspaces->class, gp->class->name,
+ sizeof gp->magicspaces->class);
+ gp->magicspaces->nmagic = nspaces;
+ return (0);
+}
+
+int
+g_add_magicspace(struct g_geom *gp, u_int index, const char *name, off_t start, u_int len, u_int flags)
+{
+ struct g_magicspace *msp;
+
+ /* KASSERT gp->magicspaces != NULL */
+ /* KASSERT index < gp->magicspaces->nmagic */
+ msp = &gp->magicspaces->magicspace[index];
+ strncpy(msp->name, name, sizeof msp->name);
+ msp->offset = start;
+ msp->len = len;
+ msp->flags = flags;
+ return (0);
+}
+
void
g_destroy_geom(struct g_geom *gp)
{
@@ -129,6 +158,10 @@ g_destroy_geom(struct g_geom *gp)
gp->name, LIST_FIRST(&gp->consumer)));
LIST_REMOVE(gp, geom);
TAILQ_REMOVE(&geoms, gp, geoms);
+ if (gp->magicspaces) {
+ g_free(gp->magicspaces->magicspace);
+ g_free(gp->magicspaces);
+ }
g_free(gp->name);
g_free(gp);
}
diff --git a/sys/geom/geom_sunlabel.c b/sys/geom/geom_sunlabel.c
index b966e5b..6171ac8 100644
--- a/sys/geom/geom_sunlabel.c
+++ b/sys/geom/geom_sunlabel.c
@@ -179,8 +179,11 @@ g_sunlabel_taste(struct g_class *mp, struct g_provider *pp, int flags)
}
g_topology_lock();
error = g_access_rel(cp, -1, 0, 0);
- if (npart > 0)
+ if (npart > 0) {
+ g_new_magicspaces(gp, 1);
+ g_add_magicspace(gp, 0, "label", 0, 512, 0);
return (gp);
+ }
g_std_spoiled(cp);
return (NULL);
}
OpenPOWER on IntegriCloud