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"

Reply via email to