diff options
author | phk <phk@FreeBSD.org> | 2003-04-23 08:23:01 +0000 |
---|---|---|
committer | phk <phk@FreeBSD.org> | 2003-04-23 08:23:01 +0000 |
commit | 15a332bfd66ed15bc8442e1d7a034e2d61d13085 (patch) | |
tree | 773a136e14f41ce5809ee8b803cba1103ffab6e7 | |
parent | cc4a9d46fe628594b066944a0ed0e706fe477fda (diff) | |
download | FreeBSD-src-15a332bfd66ed15bc8442e1d7a034e2d61d13085.zip FreeBSD-src-15a332bfd66ed15bc8442e1d7a034e2d61d13085.tar.gz |
Implement CONFIG_GEOM verbs "write label" and "write bootcode".
-rw-r--r-- | sys/geom/geom_sunlabel.c | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/sys/geom/geom_sunlabel.c b/sys/geom/geom_sunlabel.c index 478a4a8..c5d4409 100644 --- a/sys/geom/geom_sunlabel.c +++ b/sys/geom/geom_sunlabel.c @@ -147,6 +147,88 @@ g_sunlabel_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp, stru } } +struct h0h0 { + struct g_geom *gp; + struct g_sunlabel_softc *ms; + u_char *label; + int error; +}; + +static void +g_sunlabel_callconfig(void *arg, int flag) +{ + struct h0h0 *hp; + + hp = arg; + hp->error = g_sunlabel_modify(hp->gp, hp->ms, hp->label); + if (!hp->error) + hp->error = g_write_data(LIST_FIRST(&hp->gp->consumer), + 0, hp->label, SUN_SIZE); + wakeup(hp); +} + +/* + * NB! curthread is user process which GCTL'ed. + */ +static int +g_sunlabel_config(struct gctl_req *req, struct g_geom *gp, const char *verb) +{ + u_char *label; + int error, i; + struct h0h0 h0h0; + struct g_slicer *gsp; + struct g_consumer *cp; + + g_topology_assert(); + cp = LIST_FIRST(&gp->consumer); + gsp = gp->softc; + if (!strcmp(verb, "write label")) { + label = gctl_get_paraml(req, "label", SUN_SIZE); + if (label == NULL) + return (EINVAL); + h0h0.gp = gp; + h0h0.ms = gsp->softc; + h0h0.label = label; + h0h0.error = -1; + /* XXX: Does this reference register with our selfdestruct code ? */ + error = g_access_rel(cp, 1, 1, 1); + if (error) + return (error); + error = g_call_me(g_sunlabel_callconfig, &h0h0, gp, NULL); + if (!error) { + g_topology_unlock(); + do + tsleep(&h0h0, PRIBIO, "g_sunlabel_config", hz); + while (h0h0.error == -1); + g_topology_lock(); + error = h0h0.error; + } + g_access_rel(cp, -1, -1, -1); + g_free(label); + } else if (!strcmp(verb, "write bootcode")) { + label = gctl_get_paraml(req, "bootcode", SUN_BOOTSIZE); + if (label == NULL) + return (EINVAL); + /* XXX: Does this reference register with our selfdestruct code ? */ + error = g_access_rel(cp, 1, 1, 1); + if (error) + return (error); + for (i = 0; i < SUN_NPART; i++) { + if (gsp->slices[i].length <= SUN_BOOTSIZE) + continue; + g_write_data(cp, + gsp->slices[i].offset + SUN_SIZE, label + SUN_SIZE, + SUN_BOOTSIZE - SUN_SIZE); + } + g_access_rel(cp, -1, -1, -1); + g_free(label); + } else { + return (gctl_error(req, "Unknown verb parameter")); + } + + return (error); +} + static struct g_geom * g_sunlabel_taste(struct g_class *mp, struct g_provider *pp, int flags) { @@ -201,6 +283,7 @@ g_sunlabel_taste(struct g_class *mp, struct g_provider *pp, int flags) static struct g_class g_sunlabel_class = { .name = SUNLABEL_CLASS_NAME, .taste = g_sunlabel_taste, + .config_geom = g_sunlabel_config, G_CLASS_INITIALIZER }; |