|author||Joey Hess||2017-12-21 16:59:57 -0400|
|committer||Joey Hess||2017-12-21 16:59:57 -0400|
fuzzy partition end location for parted
This should fix the reversion in GPT partition creation. See my long comment for the gory details. This commit was sponsored by Peter on Patreon.
2 files changed, 81 insertions, 4 deletions
diff --git a/doc/forum/imageBuiltFor_mount_points_not_automatically_created/comment_7_ad9ea2799890df2dfce4f0cc99e397e9/comment_1_68b3d9ca04283c2400f5b23e486bb4b7._comment b/doc/forum/imageBuiltFor_mount_points_not_automatically_created/comment_7_ad9ea2799890df2dfce4f0cc99e397e9/comment_1_68b3d9ca04283c2400f5b23e486bb4b7._comment
new file mode 100644
@@ -0,0 +1,62 @@
+ subject="""comment 1"""
+Reproduced it with that information.
+ ghci> calcPartedParamsSize guexPartTable
+ joey@darkstar:~>dd if=/dev/zero of=test bs=1M count=1584
+ joey@darkstar:~>parted test
+ (parted) p
+ Model: (file)
+ Disk /home/joey/test: 1661MB
+ Sector size (logical/physical): 512B/512B
+ (parted) mklabel gpt
+ (parted) mkpart primary fat32 4194304B 16777215B
+ (parted) mkpart primary ext2 16777216B 167772159B
+ (parted) mkpart primary ext4 167772160B 1660944383B
+ Warning: You requested a partition from 168MB to 1661MB (sectors 327680..3244031).
+ The closest location we can manage is 168MB to 1661MB (sectors 327680..3243998).
+The problem only occurs with the gpt partition table. With "mklabel msdos",
+the mkpart command succeeds.
+So, gpt must have an additional restriction
+of some kind. I don't know what. The highest end position that parted
+will accept for that partition is 1660927487B; slightly smaller partitions
+are accepted. It's not a requirement that the position or size be divisible
+by anything in particular. Perhaps gpt needs some amount of reserved space
+at the end of the disk or something.
+Before 4MiB alignment was added, here's what
+propellor did for the same PartTable, which worked.
+ mkpart primary ext4 160MB 1649MB
+It would be good for propellor to not need to know about all the minutia of
+partition tables. Seems that the way it used to call parted gave it enough
+wiggle room that it avoided this kind of problem.
+To make parititions well aligned, propellor needs to precisely control where
+they begin (since parted does not have a way to configure modern
+alignment requirments). Perhaps propellor could precisely specify where a
+partition begins, but use the "MB" to leave wiggle room in where it ends
+so parted can pick a suitable end point.
+Let's see.. this works with the gpt example:
+ (parted) mkpart primary fat32 4194304B 16.777215MB
+ (parted) mkpart primary ext2 16777216B 167.772159MB
+ (parted) mkpart primary ext4 167772160B 660.944383MB
+That lets parted end the last partition right at the ideal 1660927487B.
+The previous two partitions end right where propellor expects.
+(Hopefully parted never rounds a MB value *up*!)
+Ok, I've convinced myself to make propellor use this wacky technique
+of B for the start position and fractional MB for the end position!
+I've implemented it, hopefully my analysis above is good to make
+this work with all the different kinds of partition tables.
diff --git a/src/Propellor/Property/Parted.hs b/src/Propellor/Property/Parted.hs
index 38c55b93..be12933d 100644
@@ -85,8 +85,8 @@ calcPartedParamsSize (PartTable tabletype alignment parts) =
, pval (partType p)
, pval (partFs p)
- , partpos startpos
- , partpos endpos
+ , partposexact startpos
+ , partposfuzzy endpos
] ++ case partName p of
Just n -> ["name", show partnum, n]
Nothing -> 
@@ -95,14 +95,29 @@ calcPartedParamsSize (PartTable tabletype alignment parts) =
in calcparts (partnum+1) endpos ps
(c ++ mkpart partnum startpos (endpos-1) p : map (mkflag partnum) (partFlags p))
calcparts _ endpos  c = (c, endpos)
- partpos n
- | n > 0 = val n ++ "B"
+ -- Exact partition position value for parted.
+ -- For alignment to work, the start of a partition must be
+ -- specified exactly.
+ partposexact n
+ | n > 0 = show n ++ "B"
-- parted can't make partitions smaller than 1MB;
-- avoid failure in edge cases
| otherwise = "1MB"
+ -- Fuzzy partition position valie for parted.
+ -- This is used to specify the end of the partition,
+ -- parted takes the "MB" as license to slightly reduce the
+ -- partition size when something about the partition table
+ -- does not allow the partition to end exactly at the position.
+ partposfuzzy n
+ | n > 0 = show (fromIntegral n / 1000000) ++ "MB"
+ | otherwise = "1MB"
-- Location of the start of the first partition,
-- leaving space for the partition table, and aligning.
firstpos = align partitionTableOverhead
align = alignTo alignment
-- | Runs parted on a disk with the specified parameters.