diff options
-rw-r--r-- | sys/geom/geom.h | 30 | ||||
-rw-r--r-- | sys/geom/geom_bsd.c | 16 | ||||
-rw-r--r-- | sys/geom/geom_dump.c | 19 | ||||
-rw-r--r-- | sys/geom/geom_mbr.c | 8 | ||||
-rw-r--r-- | sys/geom/geom_subr.c | 33 | ||||
-rw-r--r-- | sys/geom/geom_sunlabel.c | 5 |
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); } |