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

View File

@ -24,7 +24,7 @@
.\" .\"
.\" $FreeBSD$ .\" $FreeBSD$
.\" .\"
.Dd March 12, 2011 .Dd May 03, 2011
.Dt GPART 8 .Dt GPART 8
.Os .Os
.Sh NAME .Sh NAME
@ -91,6 +91,7 @@ utility:
.Nm .Nm
.Cm add .Cm add
.Fl t Ar type .Fl t Ar type
.Op Fl a Ar alignment
.Op Fl b Ar start .Op Fl b Ar start
.Op Fl s Ar size .Op Fl s Ar size
.Op Fl i Ar index .Op Fl i Ar index
@ -148,6 +149,7 @@ utility:
.Nm .Nm
.Cm resize .Cm resize
.Fl i Ar index .Fl i Ar index
.Op Fl a Ar alignment
.Op Fl s Ar size .Op Fl s Ar size
.Op Fl f Ar flags .Op Fl f Ar flags
.Ar geom .Ar geom
@ -209,7 +211,17 @@ Partition types are discussed below in the section entitled
.Sx "PARTITION TYPES" . .Sx "PARTITION TYPES" .
.Pp .Pp
Additional options include: 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 .It Fl i Ar index
The index in the partition table at which the new partition is to be The index in the partition table at which the new partition is to be
placed. placed.
@ -416,7 +428,15 @@ to maximum available from given geom
.Ar geom . .Ar geom .
.Pp .Pp
Additional options include: 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 .It Fl f Ar flags
Additional operational flags. Additional operational flags.
See the section entitled 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 /sbin/gpart add -s 512M -t freebsd-ufs da0
.Ed .Ed
.Pp .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. After having created all required partitions, embed bootstrap code into them.
.Bd -literal -offset indent .Bd -literal -offset indent
/sbin/gpart bootcode -p /boot/boot1 da0 /sbin/gpart bootcode -p /boot/boot1 da0