[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

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: