*TL;DR – Subtract the minimum size from the priority and compare this to other partitions to work out how much of the free space will be assigned to a partition.*

I’ve been trying to create a simple recipe for partitioning disks on new machines when using the Debian/Ubuntu automated installer. This looks like it should be fairly straightforward, but the documentation makes it more confusing that it needs to be. First, here’s an example:

d-i partman-auto/expert_recipe string \ root :: \ 8192 8241 16384 linux-swap \ $primary{ } \ method{ swap } format{ } \ . \ 16384 16386 -1 ext4 \ $primary{ } $bootable{ } \ method{ format } format{ } \ use_filesystem{ } filesystem{ ext4 } \ mountpoint{ / } \ . \ 8192 8241 16384 ext4 \ $primary{ } \ method{ format } format{ } \ use_filesystem{ } filesystem{ ext4 } \ mountpoint{ /var } \ .

I want at least 8GiB of swap and /var, and at least 16GiB for the root filesystem. I don’t want swap or /var to grow beyond 16GiB, but I’m happy for the root filesystem to grow to fill the disk. The first number for each partition is the *minimum* size, the second is the *priority*, and the third is the *maximum* (-1 being no maximum). The *minimum* and *maximum* definitions should be clear, but what does the *priority* field mean? Let’s consult the documentation:

<priority> is some size usually between <minimal size> and <maximal size>. It determines the priority of this partition in the contest with the other partitions for size. Notice that if <priority> is too small (relative to the priority of the other partitions) then this partition will have size close to <minimal size>. That’s why it is recommended to give small partitions a <priority> larger than their <maximal size>.

So it makes it clear what this number is about – it’s used to decide how much of the free space is assigned to a partition compared to the others – but it doesn’t explain how it does that, how the numbers are compared, or what they actually mean. There’s plenty of misinformation about this online, so I read through the code to work out what was really going on.

The algorithm is actually fairly straightforward. First it works out a percentage weight for each partition. It does this by subtracting the *minimum* value from the *priority*. If the *priority* is less than the *minimum* the *minimum* is used instead, which results in a zero value for this calculation. The values for all partitions are then added together and a percentage calculated for each one. So in the above example we have percentages of 49%, 2% and 49% for each partition in turn (yes, it’s no coincidence that the priorities were chosen to make percentage calculations easy).

Next, with a percentage weight for each partition it moves on to looking at the free space. It starts by giving each partition its *minimum* value (there must be enough disk space for that, otherwise the process fails) and then works out what space is left over. Each partition is then assigned a percentage of that left over space based on the figure from the previous step. That’s it – it’s as simple as that! Assuming none have gone over their *maximum* value we’re done.

If a partition does get assigned a value over its *maximum* then the *maximum* is taken as the new size instead and the *priority* for that partition becomes zero. Another pass around the loop is done, ignoring that partition completely for the percentage calculations, and the remaining free space assigned to the other partitions. This process repeats until there is no more space, or until all have hit their *maximum* values.

As a side note, when all partitions hit their *maximum* values the remaining space gets assigned to the last partition when the partitions are created. Personally I’d prefer it was left free on the disk, but it’s not configurable.

So here’s my advice – use percentages yourself. Work out what percentage of the space you’d like assigned to each partition in each pass and then add this amount to the *minimum* value to work out the *priority*.

The above was all deduced by reading the source code here, specifically the expand_scheme() function. Thank goodness for Open Source!