summaryrefslogtreecommitdiffstats
path: root/sbin/geom
diff options
context:
space:
mode:
authorae <ae@FreeBSD.org>2011-05-03 07:33:39 +0000
committerae <ae@FreeBSD.org>2011-05-03 07:33:39 +0000
commit1e83b293bb7c54580e10a143adc648a694365267 (patch)
tree4f2e017c7b83f7d5d4d02ed33c95ab59b8084967 /sbin/geom
parent752ffacc695ca593f052934a2881be57dec92419 (diff)
downloadFreeBSD-src-1e83b293bb7c54580e10a143adc648a694365267.zip
FreeBSD-src-1e83b293bb7c54580e10a143adc648a694365267.tar.gz
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
Diffstat (limited to 'sbin/geom')
-rw-r--r--sbin/geom/class/part/geom_part.c93
-rw-r--r--sbin/geom/class/part/gpart.833
2 files changed, 99 insertions, 27 deletions
diff --git a/sbin/geom/class/part/geom_part.c b/sbin/geom/class/part/geom_part.c
index 8593d20..ed7b8f8 100644
--- a/sbin/geom/class/part/geom_part.c
+++ b/sbin/geom/class/part/geom_part.c
@@ -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;
}
diff --git a/sbin/geom/class/part/gpart.8 b/sbin/geom/class/part/gpart.8
index 51b1af5..436a1a0 100644
--- a/sbin/geom/class/part/gpart.8
+++ b/sbin/geom/class/part/gpart.8
@@ -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
OpenPOWER on IntegriCloud