Author: ae Date: Fri Sep 24 08:40:43 2010 New Revision: 213097 URL: http://svn.freebsd.org/changeset/base/213097
Log: 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) Modified: head/sbin/geom/class/part/geom_part.c head/sbin/geom/class/part/gpart.8 Modified: head/sbin/geom/class/part/geom_part.c ============================================================================== --- head/sbin/geom/class/part/geom_part.c Fri Sep 24 07:52:07 2010 (r213096) +++ head/sbin/geom/class/part/geom_part.c Fri Sep 24 08:40:43 2010 (r213097) @@ -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 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, uns } 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, unsign 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: Modified: head/sbin/geom/class/part/gpart.8 ============================================================================== --- head/sbin/geom/class/part/gpart.8 Fri Sep 24 07:52:07 2010 (r213096) +++ head/sbin/geom/class/part/gpart.8 Fri Sep 24 08:40:43 2010 (r213097) @@ -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 imple .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 _______________________________________________ svn-src-all@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/svn-src-all To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"