Bug#353258: partman-auto sometimes tries to allocate too much diskspace
Package: partman-auto
Version: 41
Hello,
While trying to create 3 primary partitions using a preseeded recipe,
I discovered that partman-auto tried to allocate more diskspace than was
actually available. This caused parted_server to throw back an error and
caused the Debian installation to fail with an error "too many primary
partitions".
I've tracked down the bug to perform_recipe and found that partman-auto
precalculates the amount of free diskspace at the start, and for every
partition created, it subtracts the requested partition size instead of
the real partition size.
The result is that partman-auto wrongly believes there is more diskspace
left than there actually is.
I've patched the code to make use of the real free diskspace and I
attached the patch.
For more information, check my blog at
http://www.singularity.be/node/6157 (and all other posts called
"automated installations")
greets,
-- Steven
--- perform_recipe 2006-02-17 09:13:32.626225504 +0100
+++ perform_recipe.orig 2006-02-17 09:14:32.461129216 +0100
@@ -7,6 +7,50 @@
free_space=$2
recipe=$3
+original_free_space=$free_space
+
+# This function calculates the amount of free space
+# by looking at how big the partition after the last created partition is
+# if -1 is passed, the size of the disk is returned (to create the first partition)
+steven_free_space() {
+ local steven_part neighbour x
+ steven_part=$1
+
+ if [ $steven_part -lt 0 ];
+ then
+ x=$original_free_size_bytes
+ else
+ neighbour=$(partition_after $steven_part)
+ if [ "$neighbour" ]; then
+ open_dialog PARTITION_INFO $neighbour
+ read_line x1 x2 x x3 x4 x5 x6
+ close_dialog
+ fi
+ fi
+ echo $x
+}
+
+# This function trims the requested size of the next partition to be created
+# it looks at the maximum allowed size and returns that if the requested size is over it
+# ATTENTION: bash has problems with values over MAXINT/2 (32 bit), so in order to compare
+# 2 values of large size, we convert them first to MB
+steven_resize_if_needed() {
+ local x max xmb maxmb
+ x=$1
+ max=$(steven_free_space $steven_last_id)
+
+ xmb=$(expr 0000000"$x" : '0*\(..*\)......$')
+ maxmb=$(expr 0000000"$max" : '0*\(..*\)......$')
+
+ if [ $xmb -gt $maxmb ];
+ then
+ x=$max
+ fi
+
+ echo $x
+}
+
+
# Let us be safe and update the directories
update_all
@@ -15,6 +59,7 @@
read_line x1 x2 free_size free_type x3 x4 x5
close_dialog
+original_free_size_bytes=$free_size
free_size=$(expr 0000000"$free_size" : '0*\(..*\)......$') # convert to megabytes
if [ "$free_type" = unusable ]; then
@@ -97,38 +142,45 @@
cd $dev
+steven_last_id=-1
+
while
[ "$free_type" = pri/log ] \
&& echo $scheme | grep '\$primary{' >/dev/null
do
pull_primary
set -- $primary
- open_dialog NEW_PARTITION primary $4 $free_space beginning ${1}000001
+ toadd=$(steven_resize_if_needed ${1}000001)
+ open_dialog NEW_PARTITION primary $4 $free_space beginning $toadd
read_line num id size type fs path name
close_dialog
if [ -z "$id" ]; then
db_progress STOP
autopartitioning_failed
fi
+ steven_last_id=$id
neighbour=$(partition_after $id)
if [ "$neighbour" ]; then
open_dialog PARTITION_INFO $neighbour
read_line x1 new_free_space x2 new_free_type fs x3 x4
close_dialog
fi
+
if
[ -z "$neighbour" -o "$fs" != free \
-o "$new_free_type" = primary -o "$new_free_type" = unusable ]
then
open_dialog DELETE_PARTITION $id
close_dialog
- open_dialog NEW_PARTITION primary $4 $free_space end ${1}000001
+ toadd=$(steven_resize_if_needed ${1}000001)
+ open_dialog NEW_PARTITION primary $4 $free_space end $toadd
read_line num id size type fs path name
close_dialog
if [ -z "$id" ]; then
db_progress STOP
autopartitioning_failed
fi
+ steven_last_id=$id
neighbour=$(partition_before $id)
if [ "$neighbour" ]; then
open_dialog PARTITION_INFO $neighbour
@@ -176,10 +228,11 @@
autopartitioning_failed
;;
esac
+ toadd=$(steven_resize_if_needed ${1}000001)
if [ "$last" = yes ]; then
- open_dialog NEW_PARTITION $type $4 $free_space full ${1}000001
+ open_dialog NEW_PARTITION $type $4 $free_space full $toadd
else
- open_dialog NEW_PARTITION $type $4 $free_space beginning ${1}000001
+ open_dialog NEW_PARTITION $type $4 $free_space beginning $toadd
fi
read_line num id size type fs path name
close_dialog
@@ -187,6 +240,7 @@
db_progress STOP
autopartitioning_failed
fi
+ steven_last_id=$id
shift; shift; shift; shift
setup_partition $id $*
free_space=$(partition_after $id)'
Reply to: