aboutsummaryrefslogtreecommitdiff
path: root/sbin/geom/class
diff options
context:
space:
mode:
authorMarcel Moolenaar <marcel@FreeBSD.org>2010-04-23 03:14:04 +0000
committerMarcel Moolenaar <marcel@FreeBSD.org>2010-04-23 03:14:04 +0000
commit783310e6d9ad66127ae3fc49e27f6994c993366e (patch)
tree6b6b61063ba1e0f37fbfe75b56adaea64cb8602d /sbin/geom/class
parent3f71c319f4771ce63279b8464aee835cdeca6846 (diff)
downloadsrc-783310e6d9ad66127ae3fc49e27f6994c993366e.tar.gz
src-783310e6d9ad66127ae3fc49e27f6994c993366e.zip
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" <bu7cher@yandex.ru>
Notes
Notes: svn path=/head/; revision=207095
Diffstat (limited to 'sbin/geom/class')
-rw-r--r--sbin/geom/class/part/geom_part.c102
-rw-r--r--sbin/geom/class/part/gpart.833
2 files changed, 134 insertions, 1 deletions
diff --git a/sbin/geom/class/part/geom_part.c b/sbin/geom/class/part/geom_part.c
index e2a045e3cfae..3ddbd7aa5cb3 100644
--- a/sbin/geom/class/part/geom_part.c
+++ b/sbin/geom/class/part/geom_part.c
@@ -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);
diff --git a/sbin/geom/class/part/gpart.8 b/sbin/geom/class/part/gpart.8
index 3de658c775b7..0e6a1b97f901 100644
--- a/sbin/geom/class/part/gpart.8
+++ b/sbin/geom/class/part/gpart.8
@@ -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.