summaryrefslogtreecommitdiffstats
path: root/sbin
diff options
context:
space:
mode:
authorae <ae@FreeBSD.org>2011-05-15 16:16:48 +0000
committerae <ae@FreeBSD.org>2011-05-15 16:16:48 +0000
commit43b24a4ea434e9576e34bd111e557e5b66af4b1e (patch)
tree117adb425267d9cd62fe404c42c345ee8f1129a9 /sbin
parentf3617a6eefeeab421bc921ddfa695525c7866213 (diff)
downloadFreeBSD-src-43b24a4ea434e9576e34bd111e557e5b66af4b1e.zip
FreeBSD-src-43b24a4ea434e9576e34bd111e557e5b66af4b1e.tar.gz
Some partitioning schemes want to have partitions that are aligned
with geometry. And they do recalculation of user specified parameters. MBR, PC98, VTOC8, EBR schemes are doing that. For these schemes an auto alignment feature (ie. gpart add -a alignment) would not work. But it can work for GPT and BSD schemes. BSD scheme usualy is created inside MBR, so we can use knowledge about offset of MBR partition to calculate aligned values for BSD partitions. Use "offset" attribute of the parent provider for better alignment. MFC after: 2 weeks
Diffstat (limited to 'sbin')
-rw-r--r--sbin/geom/class/part/geom_part.c24
1 files changed, 14 insertions, 10 deletions
diff --git a/sbin/geom/class/part/geom_part.c b/sbin/geom/class/part/geom_part.c
index 81d0291..19d1502 100644
--- a/sbin/geom/class/part/geom_part.c
+++ b/sbin/geom/class/part/geom_part.c
@@ -416,7 +416,7 @@ gpart_autofill(struct gctl_req *req)
struct gprovider *pp;
off_t first, last, a_first;
off_t size, start, a_lba;
- off_t lba, len, alignment;
+ off_t lba, len, alignment, offset;
uintmax_t grade;
const char *s;
int error, has_size, has_start, has_alignment;
@@ -467,8 +467,6 @@ 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");
@@ -478,22 +476,29 @@ 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 && !has_alignment)
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);
+
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);
+ a_first = ALIGNUP(first + offset, alignment);
+ last = ALIGNDOWN(last + offset, alignment);
while ((pp = find_provider(gp, first)) != NULL) {
s = find_provcfg(pp, "start");
lba = (off_t)strtoimax(s, NULL, 0);
- a_lba = ALIGNDOWN(lba, alignment);
+ a_lba = ALIGNDOWN(lba + offset, alignment);
if (first < a_lba && a_first < a_lba) {
/* Free space [first, lba> */
len = a_lba - a_first;
@@ -519,7 +524,7 @@ gpart_autofill(struct gctl_req *req)
s = find_provcfg(pp, "end");
first = (off_t)strtoimax(s, NULL, 0) + 1;
- a_first = ALIGNUP(first, alignment);
+ a_first = ALIGNUP(first + offset, alignment);
}
if (a_first <= last) {
/* Free space [first-last] */
@@ -543,12 +548,11 @@ gpart_autofill(struct gctl_req *req)
}
}
}
-
if (grade == ~0ULL) {
geom_deletetree(&mesh);
return (ENOSPC);
}
-
+ start -= offset; /* Return back to real offset */
done:
snprintf(ssize, sizeof(ssize), "%jd", (intmax_t)size);
gctl_change_param(req, "size", -1, ssize);
OpenPOWER on IntegriCloud