Author: marcel
Date: Fri Apr 23 03:14:04 2010
New Revision: 207095
URL: http://svn.freebsd.org/changeset/base/207095

Log:
  Implement the resize command for resizing partitions. Without new
  size, the partition in question is resized to fill all available
  space. Quality work by Andrey!
  
  Submitted by: "Andrey V. Elsukov" <bu7c...@yandex.ru>

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 Apr 23 03:11:39 2010        
(r207094)
+++ head/sbin/geom/class/part/geom_part.c       Fri Apr 23 03:14:04 2010        
(r207095)
@@ -133,6 +133,13 @@ struct g_command PUBSYM(class_commands)[
                G_OPT_SENTINEL },
          "geom", NULL
         },
+       { "resize", 0, gpart_issue, {
+               { 's', "size", autofill, G_TYPE_ASCLBA },
+               { 'i', index_param, NULL, G_TYPE_ASCNUM },
+               { 'f', "flags", flags, G_TYPE_STRING },
+               G_OPT_SENTINEL },
+         "geom", NULL
+       },
        G_CMD_SENTINEL
 };
 
@@ -243,6 +250,99 @@ fmtattrib(struct gprovider *pp)
 }
 
 static int
+gpart_autofill_resize(struct gctl_req *req)
+{
+       struct gmesh mesh;
+       struct gclass *cp;
+       struct ggeom *gp;
+       struct gprovider *pp;
+       unsigned long long last, size, start, new_size;
+       unsigned long long lba, new_lba;
+       const char *s;
+       char *val;
+       int error, idx;
+
+       s = gctl_get_ascii(req, "size");
+       if (*s == '*')
+               new_size = (unsigned long long)atoll(s);
+       else
+               return (0);
+
+       s = gctl_get_ascii(req, index_param);
+       idx = strtol(s, &val, 10);
+       if (idx < 1 || *s == '\0' || *val != '\0')
+               errx(EXIT_FAILURE, "invalid partition index");
+
+       error = geom_gettree(&mesh);
+       if (error)
+               return (error);
+       s = gctl_get_ascii(req, "class");
+       if (s == NULL)
+               abort();
+       cp = find_class(&mesh, s);
+       if (cp == NULL)
+               errx(EXIT_FAILURE, "Class %s not found.", s);
+       s = gctl_get_ascii(req, "geom");
+       if (s == NULL)
+               abort();
+       gp = find_geom(cp, s);
+       if (gp == NULL)
+               errx(EXIT_FAILURE, "No such geom: %s.", s);
+       last = atoll(find_geomcfg(gp, "last"));
+
+       LIST_FOREACH(pp, &gp->lg_provider, lg_provider) {
+               s = find_provcfg(pp, "index");
+               if (s == NULL)
+                       continue;
+               if (atoi(s) == idx)
+                       break;
+       }
+       if (pp == NULL)
+               errx(EXIT_FAILURE, "invalid partition index");
+
+       s = find_provcfg(pp, "start");
+       if (s == NULL) {
+               s = find_provcfg(pp, "offset");
+               start = atoll(s) / pp->lg_sectorsize;
+       } else
+               start = atoll(s);
+       s = find_provcfg(pp, "end");
+       if (s == NULL) {
+               s = find_provcfg(pp, "length");
+               lba = start + atoll(s) / pp->lg_sectorsize;
+       } else
+               lba = atoll(s) + 1;
+
+       if (lba > last)
+               return (ENOSPC);
+       size = lba - start;
+       pp = find_provider(gp, lba);
+       if (pp == NULL)
+               new_size = last - start + 1;
+       else {
+               s = find_provcfg(pp, "start");
+               if (s == NULL) {
+                       s = find_provcfg(pp, "offset");
+                       new_lba = atoll(s) / pp->lg_sectorsize;
+               } else
+                       new_lba = atoll(s);
+               /* Is there any free space between current and
+                * next providers?
+                */
+               if (new_lba > lba)
+                       new_size = new_lba - start;
+               else
+                       return (ENOSPC);
+       }
+       asprintf(&val, "%llu", new_size);
+       if (val == NULL)
+               return (ENOMEM);
+       gctl_change_param(req, "size", -1, val);
+
+       return (0);
+}
+
+static int
 gpart_autofill(struct gctl_req *req)
 {
        struct gmesh mesh;
@@ -257,6 +357,8 @@ gpart_autofill(struct gctl_req *req)
        int error, has_size, has_start;
 
        s = gctl_get_ascii(req, "verb");
+       if (strcmp(s, "resize") == 0)
+               return gpart_autofill_resize(req);
        if (strcmp(s, "add") != 0)
                return (0);
 

Modified: head/sbin/geom/class/part/gpart.8
==============================================================================
--- head/sbin/geom/class/part/gpart.8   Fri Apr 23 03:11:39 2010        
(r207094)
+++ head/sbin/geom/class/part/gpart.8   Fri Apr 23 03:14:04 2010        
(r207095)
@@ -24,7 +24,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd November 18, 2008
+.Dd April 22, 2010
 .Dt GPART 8
 .Os
 .Sh NAME
@@ -120,6 +120,13 @@ utility:
 .Op Fl t Ar type
 .Op Fl f Ar flags
 .Ar geom
+.\" ==== RESIZE ====
+.Nm
+.Cm resize
+.Fl i Ar index
+.Op Fl s Ar size
+.Op Fl f Ar flags
+.Ar geom
 .\" ==== SET ====
 .Nm
 .Cm set
@@ -325,6 +332,30 @@ See the section entitled
 below for a discussion
 about its use.
 .El
+.\" ==== RESIZE ====
+.It Cm resize
+Resize a partition from geom
+.Ar geom
+and further identified by the
+.Fl i Ar index
+option. New partition size is expressed in logical block
+numbers and can be given by the 
+.Fl s Ar size
+option. If
+.Fl s
+option is ommited then new size is automatically calculated
+to maximum available from given geom
+.Ar geom .
+.Pp
+Additional options include:
+.Bl -tag -width 10n
+.It Fl f Ar flags
+Additional operational flags.
+See the section entitled
+.Sx "OPERATIONAL FLAGS"
+below for a discussion
+about its use.
+.El
 .\" ==== SET ====
 .It Cm set
 Set the named attribute on the partition entry.
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to