Index: head/sys/geom/part/g_part_mbr.c =================================================================== --- head/sys/geom/part/g_part_mbr.c (revision 222275) +++ head/sys/geom/part/g_part_mbr.c (working copy) @@ -194,38 +194,18 @@ g_part_mbr_add(struct g_part_table *basetable, str { struct g_part_mbr_entry *entry; struct g_part_mbr_table *table; - uint32_t start, size, sectors; if (gpp->gpp_parms & G_PART_PARM_LABEL) return (EINVAL); - sectors = basetable->gpt_sectors; - entry = (struct g_part_mbr_entry *)baseentry; table = (struct g_part_mbr_table *)basetable; - - start = gpp->gpp_start; - size = gpp->gpp_size; - if (size < sectors) - return (EINVAL); - if (start % sectors) { - size = size - sectors + (start % sectors); - start = start - (start % sectors) + sectors; - } - if (size % sectors) - size = size - (size % sectors); - if (size < sectors) - return (EINVAL); - if (baseentry->gpe_deleted) bzero(&entry->ent, sizeof(entry->ent)); - - KASSERT(baseentry->gpe_start <= start, ("%s", __func__)); - KASSERT(baseentry->gpe_end >= start + size - 1, ("%s", __func__)); - baseentry->gpe_start = start; - baseentry->gpe_end = start + size - 1; - entry->ent.dp_start = start; - entry->ent.dp_size = size; + baseentry->gpe_start = gpp->gpp_start; + baseentry->gpe_end = gpp->gpp_start + gpp->gpp_size - 1; + entry->ent.dp_start = gpp->gpp_start; + entry->ent.dp_size = gpp->gpp_size; mbr_set_chs(basetable, baseentry->gpe_start, &entry->ent.dp_scyl, &entry->ent.dp_shd, &entry->ent.dp_ssect); mbr_set_chs(basetable, baseentry->gpe_end, &entry->ent.dp_ecyl, @@ -253,15 +233,14 @@ g_part_mbr_create(struct g_part_table *basetable, { struct g_provider *pp; struct g_part_mbr_table *table; - uint32_t msize; pp = gpp->gpp_provider; if (pp->sectorsize < MBRSIZE) return (ENOSPC); - msize = MIN(pp->mediasize / pp->sectorsize, UINT32_MAX); basetable->gpt_first = basetable->gpt_sectors; - basetable->gpt_last = msize - (msize % basetable->gpt_sectors) - 1; + basetable->gpt_last = MIN(pp->mediasize / pp->sectorsize, + UINT32_MAX) - 1; table = (struct g_part_mbr_table *)basetable; le16enc(table->mbr + DOSMAGICOFFSET, DOSMAGIC); @@ -328,21 +307,10 @@ g_part_mbr_resize(struct g_part_table *basetable, struct g_part_entry *baseentry, struct g_part_parms *gpp) { struct g_part_mbr_entry *entry; - uint32_t size, sectors; - sectors = basetable->gpt_sectors; - size = gpp->gpp_size; - - if (size < sectors) - return (EINVAL); - if (size % sectors) - size = size - (size % sectors); - if (size < sectors) - return (EINVAL); - entry = (struct g_part_mbr_entry *)baseentry; - baseentry->gpe_end = baseentry->gpe_start + size - 1; - entry->ent.dp_size = size; + baseentry->gpe_end = baseentry->gpe_start + gpp->gpp_size - 1; + entry->ent.dp_size = gpp->gpp_size; mbr_set_chs(basetable, baseentry->gpe_end, &entry->ent.dp_ecyl, &entry->ent.dp_ehd, &entry->ent.dp_esect); return (0); @@ -424,13 +392,14 @@ g_part_mbr_read(struct g_part_table *basetable, st struct g_part_mbr_table *table; struct g_part_mbr_entry *entry; u_char *buf, *p; - off_t chs, msize; + off_t chs, msize, first; u_int sectors, heads; int error, index; pp = cp->provider; table = (struct g_part_mbr_table *)basetable; msize = MIN(pp->mediasize / pp->sectorsize, UINT32_MAX); + first = basetable->gpt_sectors; buf = g_read_data(cp, 0L, pp->sectorsize, &error); if (buf == NULL) @@ -462,15 +431,17 @@ g_part_mbr_read(struct g_part_table *basetable, st basetable->gpt_heads = heads; } } - + if (first > ent.dp_start) + first = ent.dp_start; entry = (struct g_part_mbr_entry *)g_part_new_entry(basetable, index + 1, ent.dp_start, ent.dp_start + ent.dp_size - 1); entry->ent = ent; } basetable->gpt_entries = NDOSPART; - basetable->gpt_first = basetable->gpt_sectors; - basetable->gpt_last = msize - (msize % basetable->gpt_sectors) - 1; + basetable->gpt_first = (first < basetable->gpt_sectors) ? 1: + basetable->gpt_sectors; + basetable->gpt_last = msize - 1; g_free(buf); return (0); Index: head/sbin/geom/class/part/gpart.8 =================================================================== --- head/sbin/geom/class/part/gpart.8 (revision 222275) +++ head/sbin/geom/class/part/gpart.8 (working copy) @@ -91,7 +91,7 @@ utility: .Nm .Cm add .Fl t Ar type -.Op Fl a Ar alignment +.Op Fl a Ar alignment | Fl g .Op Fl b Ar start .Op Fl s Ar size .Op Fl i Ar index @@ -149,7 +149,7 @@ utility: .Nm .Cm resize .Fl i Ar index -.Op Fl a Ar alignment +.Op Fl a Ar alignment | Fl g .Op Fl s Ar size .Op Fl f Ar flags .Ar geom @@ -222,6 +222,16 @@ offset and partition to be multiple of .Ar alignment value. +.It Fl g +This option is similar to +.Fl a +option, but +.Nm +utitlity uses information about disk geometry to align +.Ar start +offset and partition +.Ar size +to track boundaries. .It Fl i Ar index The index in the partition table at which the new partition is to be placed. @@ -437,6 +447,14 @@ utility tries to align partition to be multiple of .Ar alignment value. +.It Fl g +This option is similar to +.Fl a +option, but +.Nm +utitlity uses information about disk geometry to align partition +.Ar size +to track boundary. .It Fl f Ar flags Additional operational flags. See the section entitled Index: head/sbin/geom/class/part/geom_part.c =================================================================== --- head/sbin/geom/class/part/geom_part.c (revision 222275) +++ head/sbin/geom/class/part/geom_part.c (working copy) @@ -95,13 +95,14 @@ struct g_command PUBSYM(class_commands)[] = { { "add", 0, gpart_issue, { { 'a', "alignment", GPART_AUTOFILL, G_TYPE_STRING }, { 'b', "start", GPART_AUTOFILL, G_TYPE_STRING }, + { 'g', "geometry", NULL, G_TYPE_BOOL }, { 's', "size", GPART_AUTOFILL, G_TYPE_STRING }, { 't', "type", NULL, G_TYPE_STRING }, { 'i', GPART_PARAM_INDEX, G_VAL_OPTIONAL, G_TYPE_NUMBER }, { 'l', "label", G_VAL_OPTIONAL, G_TYPE_STRING }, { 'f', "flags", GPART_FLAGS, G_TYPE_STRING }, G_OPT_SENTINEL }, - "[-a alignment] [-b start] [-s size] -t type [-i index] " + "[-a alignment | -g] [-b start] [-s size] -t type [-i index] " "[-l label] [-f flags] geom" }, { "backup", 0, gpart_backup, G_NULL_OPTS, @@ -171,11 +172,12 @@ struct g_command PUBSYM(class_commands)[] = { }, { "resize", 0, gpart_issue, { { 'a', "alignment", GPART_AUTOFILL, G_TYPE_STRING }, + { 'g', "geometry", NULL, G_TYPE_BOOL }, { '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 }, - "[-a alignment] [-s size] -i index [-f flags] geom" + "[-a alignment | -g] [-s size] -i index [-f flags] geom" }, { "restore", 0, gpart_restore, { { 'F', "force", NULL, G_TYPE_BOOL }, @@ -308,7 +310,7 @@ gpart_autofill_resize(struct gctl_req *req) off_t last, size, start, new_size; off_t lba, new_lba, alignment; const char *s; - int error, idx; + int error, idx, has_alignment; idx = (int)gctl_get_intmax(req, GPART_PARAM_INDEX); if (idx < 1) @@ -334,8 +336,9 @@ gpart_autofill_resize(struct gctl_req *req) errx(EXIT_FAILURE, "Provider for geom %s not found.", s); s = gctl_get_ascii(req, "alignment"); + has_alignment = (*s == '*') ? 0 : 1; alignment = 1; - if (*s != '*') { + if (has_alignment) { error = g_parse_lba(s, pp->lg_sectorsize, &alignment); if (error) errc(EXIT_FAILURE, error, "Invalid alignment param"); @@ -345,6 +348,17 @@ gpart_autofill_resize(struct gctl_req *req) error = gctl_delete_param(req, "alignment"); if (error) errc(EXIT_FAILURE, error, "internal error"); + if (gctl_get_int(req, "geometry") != 0) { + if (has_alignment != 0) + errx(EXIT_FAILURE, "-a and -g are mutually exclusive"); + s = find_geomcfg(gp, "fwsectors"); + alignment = atoi(s); + if (alignment == 0) + errx(EXIT_FAILURE, "Invalid disk geometry"); + } + error = gctl_delete_param(req, "geometry"); + if (error) + errc(EXIT_FAILURE, error, "internal error"); s = gctl_get_ascii(req, "size"); if (*s == '*') @@ -449,16 +463,32 @@ gpart_autofill(struct gctl_req *req) s = gctl_get_ascii(req, "alignment"); has_alignment = (*s == '*') ? 0 : 1; alignment = 1; + offset = 0; 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"); + /* Adjust parameters to offset value for better alignment */ + s = find_provcfg(pp, "offset"); + offset = (s == NULL) ? 0: + (off_t)strtoimax(s, NULL, 0) / pp->lg_sectorsize; } error = gctl_delete_param(req, "alignment"); if (error) errc(EXIT_FAILURE, error, "internal error"); + if (gctl_get_int(req, "geometry") != 0) { + if (has_alignment != 0) + errx(EXIT_FAILURE, "-a and -g are mutually exclusive"); + s = find_geomcfg(gp, "fwsectors"); + alignment = atoi(s); + if (alignment == 0) + errx(EXIT_FAILURE, "Invalid disk geometry"); + } + error = gctl_delete_param(req, "geometry"); + if (error) + errc(EXIT_FAILURE, error, "internal error"); s = gctl_get_ascii(req, "size"); has_size = (*s == '*') ? 0 : 1; @@ -479,13 +509,9 @@ gpart_autofill(struct gctl_req *req) } /* No autofill necessary. */ - if (has_size && has_start && !has_alignment) + if (has_size && has_start && alignment == 1) goto done; - /* Adjust parameters to offset value for better alignment */ - s = find_provcfg(pp, "offset"); - offset = (s == NULL) ? 0: - (off_t)strtoimax(s, NULL, 0) / pp->lg_sectorsize; start = ALIGNUP(start + offset, alignment); if (size + offset > alignment) size = ALIGNDOWN(size + offset, alignment);