Author: ae
Date: Tue May  3 07:33:39 2011
New Revision: 221363
URL: http://svn.freebsd.org/changeset/base/221363

Log:
  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

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       Tue May  3 07:32:58 2011        
(r221362)
+++ head/sbin/geom/class/part/geom_part.c       Tue May  3 07:33:39 2011        
(r221363)
@@ -93,6 +93,7 @@ static void gpart_restore(struct gctl_re
 
 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 *r
        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 *r
        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 *r
                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 *r
        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 *r
                 * 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;
                        }

Modified: head/sbin/geom/class/part/gpart.8
==============================================================================
--- head/sbin/geom/class/part/gpart.8   Tue May  3 07:32:58 2011        
(r221362)
+++ head/sbin/geom/class/part/gpart.8   Tue May  3 07:33:39 2011        
(r221363)
@@ -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 t
 .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 t
 /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
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to