summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormarcel <marcel@FreeBSD.org>2007-05-15 20:14:55 +0000
committermarcel <marcel@FreeBSD.org>2007-05-15 20:14:55 +0000
commit8ea441aed588aa6eb59168cf5f54cf2931aaf6e1 (patch)
tree1c42411b1ca59a0b94f31ef69242bf18a7b2116d
parenta3a9e4130c768ac97044193ad7a95266390ba347 (diff)
downloadFreeBSD-src-8ea441aed588aa6eb59168cf5f54cf2931aaf6e1.zip
FreeBSD-src-8ea441aed588aa6eb59168cf5f54cf2931aaf6e1.tar.gz
o Implement automatic commit. It's enabled when the flags parameter
exists and contains the 'C' flag. o The partition label can be the empty string. It's how labels are cleared. o When an action fails, lower permissions when they were raised in order to allow the action. A failed action will not result in any uncommitted changes. o Allow the flags paremeter to be present but empty. It's the equivalent of not being present.
-rw-r--r--sys/geom/part/g_part.c45
1 files changed, 35 insertions, 10 deletions
diff --git a/sys/geom/part/g_part.c b/sys/geom/part/g_part.c
index f7e4eb1..2a972ad 100644
--- a/sys/geom/part/g_part.c
+++ b/sys/geom/part/g_part.c
@@ -592,6 +592,13 @@ g_part_ctl_create(struct gctl_req *req, struct g_part_parms *gpp)
if (null != NULL)
kobj_delete((kobj_t)null, M_GEOM);
+ /*
+ * Support automatic commit by filling in the gpp_geom
+ * parameter.
+ */
+ gpp->gpp_parms |= G_PART_PARM_GEOM;
+ gpp->gpp_geom = gp;
+
/* Provide feedback if so requested. */
if (gpp->gpp_parms & G_PART_PARM_OUTPUT) {
sb = sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND);
@@ -899,20 +906,20 @@ g_part_ctlreq(struct gctl_req *req, struct g_class *mp, const char *verb)
const char *p;
enum g_part_ctl ctlreq;
unsigned int i, mparms, oparms, parm;
+ int auto_commit, close_on_error;
int error, modifies;
G_PART_TRACE((G_T_TOPOLOGY, "%s(%s,%s)", __func__, mp->name, verb));
g_topology_assert();
ctlreq = G_PART_CTL_NONE;
- modifies = 0;
+ modifies = 1;
mparms = 0;
oparms = G_PART_PARM_FLAGS | G_PART_PARM_OUTPUT | G_PART_PARM_VERSION;
switch (*verb) {
case 'a':
if (!strcmp(verb, "add")) {
ctlreq = G_PART_CTL_ADD;
- modifies = 1;
mparms |= G_PART_PARM_GEOM | G_PART_PARM_SIZE |
G_PART_PARM_START | G_PART_PARM_TYPE;
oparms |= G_PART_PARM_INDEX | G_PART_PARM_LABEL;
@@ -922,9 +929,9 @@ g_part_ctlreq(struct gctl_req *req, struct g_class *mp, const char *verb)
if (!strcmp(verb, "commit")) {
ctlreq = G_PART_CTL_COMMIT;
mparms |= G_PART_PARM_GEOM;
+ modifies = 0;
} else if (!strcmp(verb, "create")) {
ctlreq = G_PART_CTL_CREATE;
- modifies = 1;
mparms |= G_PART_PARM_PROVIDER | G_PART_PARM_SCHEME;
oparms |= G_PART_PARM_ENTRIES;
}
@@ -932,34 +939,28 @@ g_part_ctlreq(struct gctl_req *req, struct g_class *mp, const char *verb)
case 'd':
if (!strcmp(verb, "delete")) {
ctlreq = G_PART_CTL_DELETE;
- modifies = 1;
mparms |= G_PART_PARM_GEOM | G_PART_PARM_INDEX;
} else if (!strcmp(verb, "destroy")) {
ctlreq = G_PART_CTL_DESTROY;
- modifies = 1;
mparms |= G_PART_PARM_GEOM;
}
break;
case 'm':
if (!strcmp(verb, "modify")) {
ctlreq = G_PART_CTL_MODIFY;
- modifies = 1;
mparms |= G_PART_PARM_GEOM | G_PART_PARM_INDEX;
oparms |= G_PART_PARM_LABEL | G_PART_PARM_TYPE;
} else if (!strcmp(verb, "move")) {
ctlreq = G_PART_CTL_MOVE;
- modifies = 1;
mparms |= G_PART_PARM_GEOM | G_PART_PARM_INDEX;
}
break;
case 'r':
if (!strcmp(verb, "recover")) {
ctlreq = G_PART_CTL_RECOVER;
- modifies = 1;
mparms |= G_PART_PARM_GEOM;
} else if (!strcmp(verb, "resize")) {
ctlreq = G_PART_CTL_RESIZE;
- modifies = 1;
mparms |= G_PART_PARM_GEOM | G_PART_PARM_INDEX;
}
break;
@@ -967,6 +968,7 @@ g_part_ctlreq(struct gctl_req *req, struct g_class *mp, const char *verb)
if (!strcmp(verb, "undo")) {
ctlreq = G_PART_CTL_UNDO;
mparms |= G_PART_PARM_GEOM;
+ modifies = 0;
}
break;
}
@@ -1045,6 +1047,8 @@ g_part_ctlreq(struct gctl_req *req, struct g_class *mp, const char *verb)
error = g_part_parm_uint(p, &gpp.gpp_entries);
break;
case G_PART_PARM_FLAGS:
+ if (p[0] == '\0')
+ continue;
error = g_part_parm_str(p, &gpp.gpp_flags);
break;
case G_PART_PARM_GEOM:
@@ -1054,7 +1058,9 @@ g_part_ctlreq(struct gctl_req *req, struct g_class *mp, const char *verb)
error = g_part_parm_uint(p, &gpp.gpp_index);
break;
case G_PART_PARM_LABEL:
- error = g_part_parm_str(p, &gpp.gpp_label);
+ /* An empty label is always valid. */
+ gpp.gpp_label = p;
+ error = 0;
break;
case G_PART_PARM_OUTPUT:
error = 0; /* Write-only parameter */
@@ -1094,6 +1100,8 @@ g_part_ctlreq(struct gctl_req *req, struct g_class *mp, const char *verb)
}
/* Obtain permissions if possible/necessary. */
+ close_on_error = 0;
+ table = NULL; /* Suppress uninit. warning. */
if (modifies && (gpp.gpp_parms & G_PART_PARM_GEOM)) {
table = gpp.gpp_geom->softc;
if (table != NULL && !table->gpt_opened) {
@@ -1105,6 +1113,7 @@ g_part_ctlreq(struct gctl_req *req, struct g_class *mp, const char *verb)
return;
}
table->gpt_opened = 1;
+ close_on_error = 1;
}
}
@@ -1143,6 +1152,22 @@ g_part_ctlreq(struct gctl_req *req, struct g_class *mp, const char *verb)
error = g_part_ctl_undo(req, &gpp);
break;
}
+
+ /* Implement automatic commit. */
+ if (!error) {
+ auto_commit = (modifies &&
+ (gpp.gpp_parms & G_PART_PARM_FLAGS) &&
+ strchr(gpp.gpp_flags, 'C') != NULL) ? 1 : 0;
+ if (auto_commit) {
+ KASSERT(gpp->gpp_parms & G_PART_PARM_GEOM, (__func__));
+ error = g_part_ctl_commit(req, &gpp);
+ }
+ }
+
+ if (error && close_on_error) {
+ g_access(LIST_FIRST(&gpp.gpp_geom->consumer), -1, -1, -1);
+ table->gpt_opened = 0;
+ }
}
static int
OpenPOWER on IntegriCloud