summaryrefslogtreecommitdiffstats
path: root/sbin/geom
diff options
context:
space:
mode:
authorae <ae@FreeBSD.org>2010-09-24 08:40:43 +0000
committerae <ae@FreeBSD.org>2010-09-24 08:40:43 +0000
commit0bc1967ac361bb3cd4aa82a92583d4f9ea180aaf (patch)
tree91283dfa145840d5ef9d4227982052262c720d92 /sbin/geom
parent722a516400bd9a03211f28a90b2dd42b7dce5d0e (diff)
downloadFreeBSD-src-0bc1967ac361bb3cd4aa82a92583d4f9ea180aaf.zip
FreeBSD-src-0bc1967ac361bb3cd4aa82a92583d4f9ea180aaf.tar.gz
Implement "force" (-F) option for gpart destroy verb.
This option doesn't passed to kernel and handled in user-space. With -F option gpart creates new "delete" request for each partition in table. Each request has flags="X" that disables auto-commit feature. Last request is the original "destroy" request. It has own flags and can have disabled or enabled auto-commit feature. If error is occurred when deleting partitions, then new "undo" request is created and all changes will be rolled back. Approved by: kib (mentor)
Diffstat (limited to 'sbin/geom')
-rw-r--r--sbin/geom/class/part/geom_part.c116
-rw-r--r--sbin/geom/class/part/gpart.85
2 files changed, 106 insertions, 15 deletions
diff --git a/sbin/geom/class/part/geom_part.c b/sbin/geom/class/part/geom_part.c
index 64abf4c..dd5567c 100644
--- a/sbin/geom/class/part/geom_part.c
+++ b/sbin/geom/class/part/geom_part.c
@@ -67,6 +67,7 @@ static char ssize[32];
#define GPART_PARAM_BOOTCODE "bootcode"
#define GPART_PARAM_INDEX "index"
#define GPART_PARAM_PARTCODE "partcode"
+#define GPART_PARAM_FORCE "force"
static struct gclass *find_class(struct gmesh *, const char *);
static struct ggeom * find_geom(struct gclass *, const char *);
@@ -84,6 +85,8 @@ static void gpart_show_geom(struct ggeom *, const char *);
static int gpart_show_hasopt(struct gctl_req *, const char *, const char *);
static void gpart_write_partcode(struct ggeom *, int, void *, ssize_t);
static void gpart_write_partcode_vtoc8(struct ggeom *, int, void *);
+static void gpart_destroy(struct gctl_req *, unsigned int);
+static void gpart_print_error(const char *);
struct g_command PUBSYM(class_commands)[] = {
{ "add", 0, gpart_issue, {
@@ -120,10 +123,11 @@ struct g_command PUBSYM(class_commands)[] = {
G_OPT_SENTINEL },
"-i index [-f flags] geom"
},
- { "destroy", 0, gpart_issue, {
+ { "destroy", 0, gpart_destroy, {
+ { 'F', GPART_PARAM_FORCE, NULL, G_TYPE_BOOL },
{ 'f', "flags", GPART_FLAGS, G_TYPE_STRING },
G_OPT_SENTINEL },
- "[-f flags] geom"
+ "[-F] [-f flags] geom"
},
{ "modify", 0, gpart_issue, {
{ 'i', GPART_PARAM_INDEX, NULL, G_TYPE_NUMBER },
@@ -854,10 +858,104 @@ gpart_bootcode(struct gctl_req *req, unsigned int fl)
}
static void
+gpart_destroy(struct gctl_req *req, unsigned int fl)
+{
+ struct gmesh mesh;
+ struct gclass *classp;
+ struct gctl_req *req2;
+ struct ggeom *gp;
+ struct gprovider *pp;
+ const char *s;
+ int error, val;
+ intmax_t idx;
+
+ if (gctl_has_param(req, GPART_PARAM_FORCE)) {
+ val = gctl_get_int(req, GPART_PARAM_FORCE);
+ error = gctl_delete_param(req, GPART_PARAM_FORCE);
+ if (error)
+ errc(EXIT_FAILURE, error, "internal error");
+ if (val == 0)
+ goto done;
+ s = gctl_get_ascii(req, "class");
+ if (s == NULL)
+ abort();
+ error = geom_gettree(&mesh);
+ if (error != 0)
+ errc(EXIT_FAILURE, error, "Cannot get GEOM tree");
+ classp = find_class(&mesh, s);
+ if (classp == NULL) {
+ geom_deletetree(&mesh);
+ errx(EXIT_FAILURE, "Class %s not found.", s);
+ }
+ s = gctl_get_ascii(req, "arg0");
+ if (s == NULL)
+ abort();
+ gp = find_geom(classp, s);
+ if (gp == NULL)
+ errx(EXIT_FAILURE, "No such geom: %s.", s);
+ val = 0;
+ LIST_FOREACH(pp, &gp->lg_provider, lg_provider){
+ s = find_provcfg(pp, "index");
+ if (s == NULL)
+ errx(EXIT_FAILURE, "Index not found for %s.",
+ pp->lg_name);
+ idx = strtoimax(s, NULL, 0);
+ req2 = gctl_get_handle();
+ gctl_ro_param(req2, "class", -1, classp->lg_name);
+ gctl_ro_param(req2, "arg0", -1, gp->lg_name);
+ gctl_ro_param(req2, "verb", -1, "delete");
+ gctl_ro_param(req2, GPART_PARAM_INDEX,
+ sizeof(intmax_t), &idx);
+ gctl_ro_param(req2, "flags", -1, "X");
+ s = gctl_issue(req2);
+ if (s != NULL && s[0] != '\0') {
+ gpart_print_error(s);
+ gctl_free(req2);
+ if (val) { /* try to undo changes */
+ req2 = gctl_get_handle();
+ gctl_ro_param(req2, "verb", -1,
+ "undo");
+ gctl_ro_param(req2, "class", -1,
+ classp->lg_name);
+ gctl_ro_param(req2, "arg0", -1,
+ gp->lg_name);
+ gctl_issue(req2);
+ gctl_free(req2);
+ }
+ geom_deletetree(&mesh);
+ exit(EXIT_FAILURE);
+ }
+ gctl_free(req2);
+ val = 1;
+ }
+ geom_deletetree(&mesh);
+ }
+done:
+ gpart_issue(req, fl);
+}
+
+static void
+gpart_print_error(const char *errstr)
+{
+ char *errmsg;
+ int error;
+
+ error = strtol(errstr, &errmsg, 0);
+ if (errmsg != errstr) {
+ while (errmsg[0] == ' ')
+ errmsg++;
+ if (errmsg[0] != '\0')
+ warnc(error, "%s", errmsg);
+ else
+ warnc(error, NULL);
+ } else
+ warnx("%s", errmsg);
+}
+
+static void
gpart_issue(struct gctl_req *req, unsigned int fl __unused)
{
char buf[4096];
- char *errmsg;
const char *errstr;
int error, status;
@@ -883,17 +981,7 @@ gpart_issue(struct gctl_req *req, unsigned int fl __unused)
goto done;
}
- error = strtol(errstr, &errmsg, 0);
- if (errmsg != errstr) {
- while (errmsg[0] == ' ')
- errmsg++;
- if (errmsg[0] != '\0')
- warnc(error, "%s", errmsg);
- else
- warnc(error, NULL);
- } else
- warnx("%s", errmsg);
-
+ gpart_print_error(errstr);
status = EXIT_FAILURE;
done:
diff --git a/sbin/geom/class/part/gpart.8 b/sbin/geom/class/part/gpart.8
index 6a62618..311f485 100644
--- a/sbin/geom/class/part/gpart.8
+++ b/sbin/geom/class/part/gpart.8
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd July 27, 2010
+.Dd Sep 24, 2010
.Dt GPART 8
.Os
.Sh NAME
@@ -118,6 +118,7 @@ utility:
.\" ==== DESTROY ====
.Nm
.Cm destroy
+.Op Fl F
.Op Fl f Ar flags
.Ar geom
.\" ==== MODIFY ====
@@ -317,6 +318,8 @@ Destroy the partitioning scheme as implemented by geom
.Pp
Additional options include:
.Bl -tag -width 10n
+.It Fl F
+Forced destroying of the partition table even if it is not empty.
.It Fl f Ar flags
Additional operational flags.
See the section entitled
OpenPOWER on IntegriCloud