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>
This commit is contained in:
Marcel Moolenaar 2010-04-23 03:14:04 +00:00
parent 3f71c319f4
commit 783310e6d9
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=207095
2 changed files with 134 additions and 1 deletions

View File

@ -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
};
@ -242,6 +249,99 @@ fmtattrib(struct gprovider *pp)
return (buf);
}
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)
{
@ -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);

View File

@ -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.