Add "-a alignment" option to gpart(8). When it specified gpart(8)

tries to align partition start offset and size to be multiple of
alignment value.

MFC after:	2 weeks
This commit is contained in:
Andrey V. Elsukov 2011-05-03 07:33:39 +00:00
parent a7ad07bff3
commit d9711c28ef
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=221363
2 changed files with 99 additions and 27 deletions

View File

@ -93,6 +93,7 @@ static void gpart_restore(struct gctl_req *, unsigned int);
struct g_command PUBSYM(class_commands)[] = {
{ "add", 0, gpart_issue, {
{ 'a', "alignment", GPART_AUTOFILL, G_TYPE_STRING },
{ 'b', "start", GPART_AUTOFILL, G_TYPE_STRING },
{ 's', "size", GPART_AUTOFILL, G_TYPE_STRING },
{ 't', "type", NULL, G_TYPE_STRING },
@ -100,7 +101,8 @@ struct g_command PUBSYM(class_commands)[] = {
{ 'l', "label", G_VAL_OPTIONAL, G_TYPE_STRING },
{ 'f', "flags", GPART_FLAGS, G_TYPE_STRING },
G_OPT_SENTINEL },
"[-b start] [-s size] -t type [-i index] [-l label] [-f flags] geom"
"[-a alignment] [-b start] [-s size] -t type [-i index] "
"[-l label] [-f flags] geom"
},
{ "backup", 0, gpart_backup, G_NULL_OPTS,
"geom"
@ -168,11 +170,12 @@ struct g_command PUBSYM(class_commands)[] = {
"-a attrib -i index [-f flags] geom"
},
{ "resize", 0, gpart_issue, {
{ 'a', "alignment", GPART_AUTOFILL, G_TYPE_STRING },
{ 's', "size", GPART_AUTOFILL, G_TYPE_STRING },
{ 'i', GPART_PARAM_INDEX, NULL, G_TYPE_NUMBER },
{ 'f', "flags", GPART_FLAGS, G_TYPE_STRING },
G_OPT_SENTINEL },
"[-s size] -i index [-f flags] geom"
"[-a alignment] [-s size] -i index [-f flags] geom"
},
{ "restore", 0, gpart_restore, {
{ 'F', "force", NULL, G_TYPE_BOOL },
@ -298,6 +301,9 @@ fmtattrib(struct gprovider *pp)
return (buf);
}
#define ALIGNDOWN(d, a) (-(a) & (d))
#define ALIGNUP(d, a) (-(-(a) & -(d)))
static int
gpart_autofill_resize(struct gctl_req *req)
{
@ -306,7 +312,7 @@ gpart_autofill_resize(struct gctl_req *req)
struct ggeom *gp;
struct gprovider *pp;
off_t last, size, start, new_size;
off_t lba, new_lba;
off_t lba, new_lba, alignment;
const char *s;
int error, idx;
@ -333,6 +339,19 @@ gpart_autofill_resize(struct gctl_req *req)
if (pp == NULL)
errx(EXIT_FAILURE, "Provider for geom %s not found.", s);
s = gctl_get_ascii(req, "alignment");
alignment = 1;
if (*s != '*') {
error = g_parse_lba(s, pp->lg_sectorsize, &alignment);
if (error)
errc(EXIT_FAILURE, error, "Invalid alignment param");
if (alignment == 0)
errx(EXIT_FAILURE, "Invalid alignment param");
}
error = gctl_delete_param(req, "alignment");
if (error)
errc(EXIT_FAILURE, error, "internal error");
s = gctl_get_ascii(req, "size");
if (*s == '*')
new_size = 0;
@ -341,10 +360,14 @@ gpart_autofill_resize(struct gctl_req *req)
if (error)
errc(EXIT_FAILURE, error, "Invalid size param");
/* no autofill necessary. */
goto done;
if (alignment == 1)
goto done;
if (new_size > alignment)
new_size = ALIGNDOWN(new_size, alignment);
}
last = (off_t)strtoimax(find_geomcfg(gp, "last"), NULL, 0);
last = ALIGNDOWN(last, alignment);
LIST_FOREACH(pp, &gp->lg_provider, lg_provider) {
s = find_provcfg(pp, "index");
if (s == NULL)
@ -376,7 +399,7 @@ gpart_autofill_resize(struct gctl_req *req)
size = lba - start;
pp = find_provider(gp, lba);
if (pp == NULL)
new_size = last - start + 1;
new_size = ALIGNDOWN(last - start + 1, alignment);
else {
s = find_provcfg(pp, "start");
if (s == NULL) {
@ -389,6 +412,7 @@ gpart_autofill_resize(struct gctl_req *req)
* Is there any free space between current and
* next providers?
*/
new_lba = ALIGNUP(new_lba, alignment);
if (new_lba > lba)
new_size = new_lba - start;
else {
@ -410,12 +434,12 @@ gpart_autofill(struct gctl_req *req)
struct gclass *cp;
struct ggeom *gp;
struct gprovider *pp;
off_t first, last;
off_t size, start;
off_t lba, len;
off_t first, last, a_first;
off_t size, start, a_lba;
off_t lba, len, alignment;
uintmax_t grade;
const char *s;
int error, has_size, has_start;
int error, has_size, has_start, has_alignment;
s = gctl_get_ascii(req, "verb");
if (strcmp(s, "resize") == 0)
@ -442,6 +466,20 @@ gpart_autofill(struct gctl_req *req)
if (pp == NULL)
errx(EXIT_FAILURE, "Provider for geom %s not found.", s);
s = gctl_get_ascii(req, "alignment");
has_alignment = (*s == '*') ? 0 : 1;
alignment = 1;
if (has_alignment) {
error = g_parse_lba(s, pp->lg_sectorsize, &alignment);
if (error)
errc(EXIT_FAILURE, error, "Invalid alignment param");
if (alignment == 0)
errx(EXIT_FAILURE, "Invalid alignment param");
}
error = gctl_delete_param(req, "alignment");
if (error)
errc(EXIT_FAILURE, error, "internal error");
s = gctl_get_ascii(req, "size");
has_size = (*s == '*') ? 0 : 1;
size = 0;
@ -449,6 +487,8 @@ gpart_autofill(struct gctl_req *req)
error = g_parse_lba(s, pp->lg_sectorsize, &size);
if (error)
errc(EXIT_FAILURE, error, "Invalid size param");
if (size > alignment)
size = ALIGNDOWN(size, alignment);
}
s = gctl_get_ascii(req, "start");
@ -458,15 +498,18 @@ gpart_autofill(struct gctl_req *req)
error = g_parse_lba(s, pp->lg_sectorsize, &start);
if (error)
errc(EXIT_FAILURE, error, "Invalid start param");
start = ALIGNUP(start, alignment);
}
/* No autofill necessary. */
if (has_size && has_start)
if (has_size && has_start && !has_alignment)
goto done;
first = (off_t)strtoimax(find_geomcfg(gp, "first"), NULL, 0);
last = (off_t)strtoimax(find_geomcfg(gp, "last"), NULL, 0);
grade = ~0ULL;
a_first = ALIGNUP(first, alignment);
last = ALIGNDOWN(last, alignment);
while ((pp = find_provider(gp, first)) != NULL) {
s = find_provcfg(pp, "start");
if (s == NULL) {
@ -475,23 +518,24 @@ gpart_autofill(struct gctl_req *req)
} else
lba = (off_t)strtoimax(s, NULL, 0);
if (first < lba) {
a_lba = ALIGNDOWN(lba, alignment);
if (first < a_lba && a_first < a_lba) {
/* Free space [first, lba> */
len = lba - first;
len = a_lba - a_first;
if (has_size) {
if (len >= size &&
(uintmax_t)(len - size) < grade) {
start = first;
start = a_first;
grade = len - size;
}
} else if (has_start) {
if (start >= first && start < lba) {
size = lba - start;
grade = start - first;
if (start >= a_first && start < a_lba) {
size = a_lba - start;
grade = start - a_first;
}
} else {
if (grade == ~0ULL || len > size) {
start = first;
start = a_first;
size = len;
grade = 0;
}
@ -505,24 +549,25 @@ gpart_autofill(struct gctl_req *req)
(off_t)strtoimax(s, NULL, 0) / pp->lg_sectorsize;
} else
first = (off_t)strtoimax(s, NULL, 0) + 1;
a_first = ALIGNUP(first, alignment);
}
if (first <= last) {
if (a_first <= last) {
/* Free space [first-last] */
len = last - first + 1;
len = ALIGNDOWN(last - a_first + 1, alignment);
if (has_size) {
if (len >= size &&
(uintmax_t)(len - size) < grade) {
start = first;
start = a_first;
grade = len - size;
}
} else if (has_start) {
if (start >= first && start <= last) {
size = last - start + 1;
grade = start - first;
if (start >= a_first && start <= last) {
size = ALIGNDOWN(last - start + 1, alignment);
grade = start - a_first;
}
} else {
if (grade == ~0ULL || len > size) {
start = first;
start = a_first;
size = len;
grade = 0;
}

View File

@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd March 12, 2011
.Dd May 03, 2011
.Dt GPART 8
.Os
.Sh NAME
@ -91,6 +91,7 @@ utility:
.Nm
.Cm add
.Fl t Ar type
.Op Fl a Ar alignment
.Op Fl b Ar start
.Op Fl s Ar size
.Op Fl i Ar index
@ -148,6 +149,7 @@ utility:
.Nm
.Cm resize
.Fl i Ar index
.Op Fl a Ar alignment
.Op Fl s Ar size
.Op Fl f Ar flags
.Ar geom
@ -209,7 +211,17 @@ Partition types are discussed below in the section entitled
.Sx "PARTITION TYPES" .
.Pp
Additional options include:
.Bl -tag -width 10n
.Bl -tag -width 12n
.It Fl a Ar alignment
If specified, then
.Nm
utility tries to align
.Ar start
offset and partition
.Ar size
to be multiple of
.Ar alignment
value.
.It Fl i Ar index
The index in the partition table at which the new partition is to be
placed.
@ -416,7 +428,15 @@ to maximum available from given geom
.Ar geom .
.Pp
Additional options include:
.Bl -tag -width 10n
.Bl -tag -width 12n
.It Fl a Ar alignment
If specified, then
.Nm
utility tries to align partition
.Ar size
to be multiple of
.Ar alignment
value.
.It Fl f Ar flags
Additional operational flags.
See the section entitled
@ -834,6 +854,13 @@ partition that would contain UFS where the system boots from.
/sbin/gpart add -s 512M -t freebsd-ufs da0
.Ed
.Pp
Create a 15GB-sized
.Cm freebsd-ufs
partition that would contain UFS and aligned on 4KB boundaries:
.Bd -literal -offset indent
/sbin/gpart add -s 15G -t freebsd-ufs -a 4k da0
.Ed
.Pp
After having created all required partitions, embed bootstrap code into them.
.Bd -literal -offset indent
/sbin/gpart bootcode -p /boot/boot1 da0