From fd85cd910533626a04a5a3687af3953404645e15 Mon Sep 17 00:00:00 2001 From: rpokala Date: Wed, 8 Feb 2017 08:37:43 +0000 Subject: [PATCH] MFC r304142: ensure stripe size is non-zero multiple of 4096 Ensure that the sector size is a multiple of 4096 to avoid creating unaligned partitions when the actual sector size is hidden from us. NOTE: This change was MFCed to stable/11 months ago as as r304448; I'm just MFCing it back one more stream. git-svn-id: svn://svn.freebsd.org/base/stable/10@313433 ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f --- usr.sbin/bsdinstall/partedit/gpart_ops.c | 26 ++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/usr.sbin/bsdinstall/partedit/gpart_ops.c b/usr.sbin/bsdinstall/partedit/gpart_ops.c index 48bbb68ca..624077d79 100644 --- a/usr.sbin/bsdinstall/partedit/gpart_ops.c +++ b/usr.sbin/bsdinstall/partedit/gpart_ops.c @@ -795,6 +795,7 @@ gpart_max_free(struct ggeom *geom, intmax_t *npartstart) { struct gconfig *gc; struct gprovider *pp, **providers; + intmax_t sectorsize, stripesize, offset; intmax_t lastend; intmax_t start, end; intmax_t maxsize, maxstart; @@ -845,12 +846,25 @@ gpart_max_free(struct ggeom *geom, intmax_t *npartstart) pp = LIST_FIRST(&geom->lg_consumer)->lg_provider; - /* Compute beginning of new partition and maximum available space */ - if (pp->lg_stripesize > 0 && - (maxstart*pp->lg_sectorsize % pp->lg_stripesize) != 0) { - intmax_t offset = (pp->lg_stripesize - - ((maxstart*pp->lg_sectorsize) % pp->lg_stripesize)) / - pp->lg_sectorsize; + /* + * Round the start and size of the largest available space up to + * the nearest multiple of the adjusted stripe size. + * + * The adjusted stripe size is the least common multiple of the + * actual stripe size, or the sector size if no stripe size was + * reported, and 4096. The reason for this is that contemporary + * disks often have 4096-byte physical sectors but report 512 + * bytes instead for compatibility with older / broken operating + * systems and BIOSes. For the same reasons, virtualized storage + * may also report a 512-byte stripe size, or none at all. + */ + sectorsize = pp->lg_sectorsize; + if ((stripesize = pp->lg_stripesize) == 0) + stripesize = sectorsize; + while (stripesize % 4096 != 0) + stripesize *= 2; + if ((offset = maxstart * sectorsize % stripesize) != 0) { + offset = (stripesize - offset) / sectorsize; maxstart += offset; maxsize -= offset; } -- 2.45.0