summaryrefslogtreecommitdiffstats
path: root/sys/geom/geom_sunlabel.c
diff options
context:
space:
mode:
authorphk <phk@FreeBSD.org>2003-04-23 08:23:01 +0000
committerphk <phk@FreeBSD.org>2003-04-23 08:23:01 +0000
commit15a332bfd66ed15bc8442e1d7a034e2d61d13085 (patch)
tree773a136e14f41ce5809ee8b803cba1103ffab6e7 /sys/geom/geom_sunlabel.c
parentcc4a9d46fe628594b066944a0ed0e706fe477fda (diff)
downloadFreeBSD-src-15a332bfd66ed15bc8442e1d7a034e2d61d13085.zip
FreeBSD-src-15a332bfd66ed15bc8442e1d7a034e2d61d13085.tar.gz
Implement CONFIG_GEOM verbs "write label" and "write bootcode".
Diffstat (limited to 'sys/geom/geom_sunlabel.c')
-rw-r--r--sys/geom/geom_sunlabel.c83
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
};
OpenPOWER on IntegriCloud