Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 23 Apr 2010 03:14:04 +0000 (UTC)
From:      Marcel Moolenaar <marcel@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r207095 - head/sbin/geom/class/part
Message-ID:  <201004230314.o3N3E4t1074495@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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" <bu7cher@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.



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201004230314.o3N3E4t1074495>