/[fai]/people/michael/features/setup_harddisks_2/implementation/lib/sizes.pm
ViewVC logotype

Diff of /people/michael/features/setup_harddisks_2/implementation/lib/sizes.pm

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 4613 by michael-guest, Thu May 31 07:27:20 2007 UTC revision 4614 by andreas, Tue Oct 9 18:36:33 2007 UTC
# Line 49  package FAI; Line 49  package FAI;
49  ################################################################################  ################################################################################
50  sub estimate_size  sub estimate_size
51  {  {
52    my ( $dev ) = @_;    my ($dev) = @_;
53    
54    # try the entire disk first; we then use the data from the current    # try the entire disk first; we then use the data from the current
55    # configuration; this matches in fact for than the allowable strings, but    # configuration; this matches in fact for than the allowable strings, but
56    # this should be caught later on    # this should be caught later on
57    if ( $dev =~ /^\/dev\/[sh]d[a-z]$/ )    if ( $dev =~ /^\/dev\/[sh]d[a-z]$/ )
58    {    {
59      defined( $FAI::current_config{$dev}{"end_byte"} ) or die      defined( $FAI::current_config{$dev}{"end_byte"} )
60        "$dev is not a valid block device\n";        or die "$dev is not a valid block device\n";
61    
62      # the size is known, return it      # the size is known, return it
63      return ( $FAI::current_config{$dev}{"end_byte"} -      return ( $FAI::current_config{$dev}{"end_byte"} -
64        $FAI::current_config{$dev}{"begin_byte"} ) / ( 1024 * 1024 );          $FAI::current_config{$dev}{"begin_byte"} ) / ( 1024 * 1024 );
65    }    }
66    
67    # try a partition    # try a partition
68    elsif ( $dev =~ /^(\/dev\/[sh]d[a-z])(\d+)$/ )    elsif ( $dev =~ /^(\/dev\/[sh]d[a-z])(\d+)$/ )
69    {    {
70    
71      # the size is configured, return it      # the size is configured, return it
72      defined( $FAI::configs{"PHY_$1"}{"partitions"}{$2}{"size"}{"eff_size"} ) and      defined( $FAI::configs{"PHY_$1"}{"partitions"}{$2}{"size"}{"eff_size"} )
73        return $FAI::configs{"PHY_$1"}{"partitions"}{$2}{"size"}{"eff_size"} / ( 1024 * 1024 );        and return $FAI::configs{"PHY_$1"}{"partitions"}{$2}{"size"}{"eff_size"} /
74          ( 1024 * 1024 );
75    
76      # the size is known from the current configuration on disk, return it      # the size is known from the current configuration on disk, return it
77      defined( $FAI::current_config{$1}{"partitions"}{$2}{"count_byte"} ) and      defined( $FAI::current_config{$1}{"partitions"}{$2}{"count_byte"} )
78        return $FAI::current_config{$1}{"partitions"}{$2}{"count_byte"} / ( 1024 * 1024 );        and return $FAI::current_config{$1}{"partitions"}{$2}{"count_byte"} /
79          ( 1024 * 1024 );
80    
81      # the size is not known (yet?)      # the size is not known (yet?)
82      die "Cannot determine size of $dev\n";      die "Cannot determine size of $dev\n";
83    }    }
84    
85    # try RAID; estimations here are very limited and possible imprecise    # try RAID; estimations here are very limited and possible imprecise
86    elsif ( $dev =~ /^\/dev\/md(\d+)$/ )    elsif ( $dev =~ /^\/dev\/md(\d+)$/ )
87    {    {
88    
89      # the list of underlying devices      # the list of underlying devices
90      my @devs = ();      my @devs = ();
91    
92      # the raid level, like raid0, raid5, linear, etc.      # the raid level, like raid0, raid5, linear, etc.
93      my $level = "";      my $level = "";
94    
95      # let's see, whether there is a configuration of this volume      # let's see, whether there is a configuration of this volume
96      if ( defined( $FAI::configs{"RAID"}{"volumes"}{$1}{"devices"} ) )      if ( defined( $FAI::configs{"RAID"}{"volumes"}{$1}{"devices"} ) )
97      {      {
98        @devs = keys %{ $FAI::configs{"RAID"}{"volumes"}{$1}{"devices"} };        @devs  = keys %{ $FAI::configs{"RAID"}{"volumes"}{$1}{"devices"} };
99        $level = $FAI::configs{"RAID"}{"volumes"}{$1}{"mode"};        $level = $FAI::configs{"RAID"}{"volumes"}{$1}{"mode"};
100      }      }
101      elsif( defined( $FAI::current_raid_config{$1}{"devices"} ) )      elsif ( defined( $FAI::current_raid_config{$1}{"devices"} ) )
102      {      {
103        @devs = $FAI::current_raid_config{$1}{"devices"};        @devs  = $FAI::current_raid_config{$1}{"devices"};
104        $level = $FAI::current_raid_config{$1}{"mode"};        $level = $FAI::current_raid_config{$1}{"mode"};
105      }      }
106      else      else
107      {      {
108        die "$dev is not a known RAID device\n";        die "$dev is not a known RAID device\n";
109      }      }
110    
111      # prepend "raid", if the mode is numeric-only      # prepend "raid", if the mode is numeric-only
112      $level = "raid" . $level if ( $level =~ /^\d+$/ );      $level = "raid" . $level if ( $level =~ /^\d+$/ );
113    
114      # the number of devices in the volume      # the number of devices in the volume
115      my $dev_count = scalar( @devs );      my $dev_count = scalar(@devs);
116    
117      # now do the mode-specific size estimations      # now do the mode-specific size estimations
118      if ( $level =~ /^raid[015]$/ )      if ( $level =~ /^raid[015]$/ )
119      {      {
120        my $min_size = &estimate_size( shift @devs );        my $min_size = &estimate_size( shift @devs );
121        foreach ( @devs )        foreach (@devs)
122        {        {
123          my $s = &estimate_size( $_ );          my $s = &estimate_size($_);
124          $min_size = $s if ( $s < $min_size );          $min_size = $s if ( $s < $min_size );
125        }        }
126    
127        return $min_size * POSIX::floor( $dev_count / 2 ) if ( $level eq "raid1" );        return $min_size * POSIX::floor( $dev_count / 2 )
128            if ( $level eq "raid1" );
129        return $min_size * $dev_count if ( $level eq "raid0" );        return $min_size * $dev_count if ( $level eq "raid0" );
130        return $min_size * ( $dev_count - 1 ) if ( $level eq "raid5" );        return $min_size * ( $dev_count - 1 ) if ( $level eq "raid5" );
131      }      }
132      else      else
133      {      {
134    
135        # probably some more should be implemented        # probably some more should be implemented
136        die "Don't know how to estimate the size of a $level device\n";        die "Don't know how to estimate the size of a $level device\n";
137      }      }
138    }    }
139    
140    # otherwise we are clueless    # otherwise we are clueless
141    else    else
142    {    {
# Line 139  sub estimate_size Line 151  sub estimate_size
151  ################################################################################  ################################################################################
152  sub compute_lv_sizes  sub compute_lv_sizes
153  {  {
154    
155    # loop through all device configurations    # loop through all device configurations
156    foreach my $config ( keys %FAI::configs )    foreach my $config ( keys %FAI::configs )
157    {    {
158    
159      # for RAID, there is nothing to be done here      # for RAID, there is nothing to be done here
160      next if ( $config eq "RAID" );      next if ( $config eq "RAID" );
161    
162      # device is an effective disk      # device is an effective disk
163      next if ( $config =~ /^PHY_(.+)$/ );      next if ( $config =~ /^PHY_(.+)$/ );
164    
165      # configure a volume group      # configure a volume group
166      ( $config =~ /^VG_(.+)$/ ) or die      ( $config =~ /^VG_(.+)$/ )
167        "INTERNAL ERROR: invalid config entry $config.\n";        or die "INTERNAL ERROR: invalid config entry $config.\n";
168    
169      # the volume group name      # the volume group name
170      my $vg = $1;      my $vg = $1;
171    
172      # compute the size of the volume group; this is not exact, but should at      # compute the size of the volume group; this is not exact, but should at
173      # least give a rough estimation, we assume 1 % of overhead; the value is      # least give a rough estimation, we assume 1 % of overhead; the value is
174      # stored in megabytes      # stored in megabytes
175      my $vg_size = 0;      my $vg_size = 0;
176      foreach my $dev ( keys %{ $FAI::configs{$config}{"devices"} } )      foreach my $dev ( keys %{ $FAI::configs{$config}{"devices"} } )
177      {      {
178    
179        # $dev may be a partition, an entire disk or a RAID device; otherwise we        # $dev may be a partition, an entire disk or a RAID device; otherwise we
180        # cannot deal with it        # cannot deal with it
181        $vg_size += &estimate_size( $dev );        $vg_size += &estimate_size($dev);
182      }      }
183    
184      # now subtract 1% of overhead      # now subtract 1% of overhead
185      $vg_size *= 0.99;      $vg_size *= 0.99;
186    
# Line 172  sub compute_lv_sizes Line 189  sub compute_lv_sizes
189    
190      # the minimum space required in this volume group      # the minimum space required in this volume group
191      my $min_space = 0;      my $min_space = 0;
192    
193      # the maximum space used in this volume group      # the maximum space used in this volume group
194      my $max_space = 0;      my $max_space = 0;
195    
196      # set effective sizes where available      # set effective sizes where available
197      foreach      foreach my $lv ( keys %{ $FAI::configs{$config}{"volumes"} } )
       my $lv ( keys %{ $FAI::configs{$config}{"volumes"} } )  
198      {      {
199    
200        # make sure the size specification is a range (even though it might be        # make sure the size specification is a range (even though it might be
201        # something like x-x) and store the dimensions        # something like x-x) and store the dimensions
202        ( $FAI::configs{$config}{"volumes"}{$lv}{"size"}{"range"} =~        ( $FAI::configs{$config}{"volumes"}{$lv}{"size"}{"range"} =~
# Line 189  sub compute_lv_sizes Line 206  sub compute_lv_sizes
206        my $end   = $2;        my $end   = $2;
207    
208        # start may be given in percents of the size, rewrite it to megabytes        # start may be given in percents of the size, rewrite it to megabytes
209        $start = POSIX::floor( $vg_size * $1 / 100 ) if ( $start =~ /^(\d+)%$/);        $start = POSIX::floor( $vg_size * $1 / 100 ) if ( $start =~ /^(\d+)%$/ );
210    
211        # end may be given in percents of the size, rewrite it to megabytes        # end may be given in percents of the size, rewrite it to megabytes
212        $end = POSIX::ceil( $vg_size * $1 / 100 ) if ( $end =~ /^(\d+)%$/);        $end = POSIX::ceil( $vg_size * $1 / 100 ) if ( $end =~ /^(\d+)%$/ );
213    
214        # make sure that $end >= $start        # make sure that $end >= $start
215        ( $end >= $start ) or die "INTERNAL ERROR: end < start\n";        ( $end >= $start ) or die "INTERNAL ERROR: end < start\n";
# Line 200  sub compute_lv_sizes Line 217  sub compute_lv_sizes
217        # increase the used space        # increase the used space
218        $min_space += $start;        $min_space += $start;
219        $max_space += $end;        $max_space += $end;
220    
221        # write back the range in MB        # write back the range in MB
222        $FAI::configs{$config}{"volumes"}{$lv}{"size"}{"range"} = "$start-$end";        $FAI::configs{$config}{"volumes"}{$lv}{"size"}{"range"} = "$start-$end";
223    
224        # the size is fixed        # the size is fixed
225        if ( $start == $end )        if ( $start == $end )
226        {        {
227    
228          # write the size back to the configuration          # write the size back to the configuration
229          $FAI::configs{$config}{"volumes"}{$lv}{"size"}{"eff_size"} = $start;          $FAI::configs{$config}{"volumes"}{$lv}{"size"}{"eff_size"} = $start;
230        }        }
231        else        else
232        {        {
233    
234          # add this volume to the redistribution list          # add this volume to the redistribution list
235          push @redist_list, $lv;          push @redist_list, $lv;
236        }        }
237      }      }
238    
239      # test, whether the configuration fits on the volume group at all      # test, whether the configuration fits on the volume group at all
240      ( $min_space < $vg_size ) or die      ( $min_space < $vg_size )
241        "Volume group $vg requires $min_space MB\n";        or die "Volume group $vg requires $min_space MB\n";
242    
243      # the extension factor      # the extension factor
244      my $redist_factor = 0;      my $redist_factor = 0;
245      $redist_factor = ( $vg_size - $min_space ) / ( $max_space - $min_space ) if      $redist_factor = ( $vg_size - $min_space ) / ( $max_space - $min_space )
246        ( $max_space > $min_space );        if ( $max_space > $min_space );
247    
248      # update all sizes that are still ranges      # update all sizes that are still ranges
249      foreach my $lv ( @redist_list )      foreach my $lv (@redist_list)
250      {      {
251    
252        # get the range again        # get the range again
253        ( $FAI::configs{$config}{"volumes"}{$lv}{"size"}{"range"} =~        ( $FAI::configs{$config}{"volumes"}{$lv}{"size"}{"range"} =~
254            /^(\d+%?)-(\d+%?)$/ )            /^(\d+%?)-(\d+%?)$/ )
# Line 237  sub compute_lv_sizes Line 257  sub compute_lv_sizes
257        my $end   = $2;        my $end   = $2;
258    
259        # write the final size        # write the final size
260        $FAI::configs{$config}{"volumes"}{$lv}{"size"}{"eff_size"} = $start + ( (        $FAI::configs{$config}{"volumes"}{$lv}{"size"}{"eff_size"} =
261          $end - $start ) * $redist_factor );          $start + ( ( $end - $start ) * $redist_factor );
262      }      }
263    }    }
264  }  }
# Line 255  sub compute_partition_sizes Line 275  sub compute_partition_sizes
275    # loop through all device configurations    # loop through all device configurations
276    foreach my $config ( keys %FAI::configs )    foreach my $config ( keys %FAI::configs )
277    {    {
278    
279      # for RAID, there is nothing to be done here      # for RAID, there is nothing to be done here
280      next if ( $config eq "RAID" );      next if ( $config eq "RAID" );
281    
282      # don't configure the sizes of logical volumes here      # don't configure the sizes of logical volumes here
283      next if ( $config =~ /^VG_(.+)$/ );      next if ( $config =~ /^VG_(.+)$/ );
284    
285      # device is an effective disk      # device is an effective disk
286      ( $config =~ /^PHY_(.+)$/ ) or die      ( $config =~ /^PHY_(.+)$/ )
287        "INTERNAL ERROR: invalid config entry $config.\n";        or die "INTERNAL ERROR: invalid config entry $config.\n";
288    
289      # nothing to be done, if this is a configuration for a virtual disk      # nothing to be done, if this is a configuration for a virtual disk
290      next if ( $FAI::configs{$config}{"virtual"} == 1 );      next if ( $FAI::configs{$config}{"virtual"} == 1 );
291    
292      # the device name of the disk      # the device name of the disk
293      my $disk = $1;      my $disk = $1;
294    
295      # at various points the following code highly depends on the desired disk label!  # at various points the following code highly depends on the desired disk label!
296      # initialise variables  # initialise variables
297      # the id of the extended partition to be created, if required  # the id of the extended partition to be created, if required
298      my $extended = -1;      my $extended = -1;
299    
300      # the id of the current extended partition, if any; this setup only caters      # the id of the current extended partition, if any; this setup only caters
301      # for a single existing extended partition!      # for a single existing extended partition!
302      my $current_extended = -1;      my $current_extended = -1;
303    
304      # find the first existing extended partition      # find the first existing extended partition
305      foreach      foreach
306        my $part_id ( sort keys %{ $FAI::current_config{$disk}{"partitions"} } )        my $part_id ( sort keys %{ $FAI::current_config{$disk}{"partitions"} } )
307      {      {
308        if ( 1 == $FAI::current_config{$disk}{"partitions"}{$part_id}{"is_extended"} )        if ( 1 ==
309            $FAI::current_config{$disk}{"partitions"}{$part_id}{"is_extended"} )
310        {        {
311          $current_extended = $part_id;          $current_extended = $part_id;
312          last;          last;
# Line 295  sub compute_partition_sizes Line 318  sub compute_partition_sizes
318    
319      # the start byte for the next partition      # the start byte for the next partition
320      my $next_start = 0;      my $next_start = 0;
321    
322      # on msdos disk labels, the first partitions starts at head #1      # on msdos disk labels, the first partitions starts at head #1
323      if ( $FAI::configs{$config}{"disklabel"} eq "msdos" )      if ( $FAI::configs{$config}{"disklabel"} eq "msdos" )
324      {      {
# Line 303  sub compute_partition_sizes Line 326  sub compute_partition_sizes
326          $FAI::current_config{$disk}{"sector_size"};          $FAI::current_config{$disk}{"sector_size"};
327    
328        # the MBR requires space, too        # the MBR requires space, too
329        $min_req_total_space += $FAI::current_config{$disk}{"bios_sectors_per_track"} *        $min_req_total_space +=
330            $FAI::current_config{$disk}{"bios_sectors_per_track"} *
331          $FAI::current_config{$disk}{"sector_size"};          $FAI::current_config{$disk}{"sector_size"};
332      }      }
333    
# Line 311  sub compute_partition_sizes Line 335  sub compute_partition_sizes
335      if ( $FAI::configs{$config}{"disklabel"} eq "gpt" )      if ( $FAI::configs{$config}{"disklabel"} eq "gpt" )
336      {      {
337        $next_start = 34 * $FAI::current_config{$disk}{"sector_size"};        $next_start = 34 * $FAI::current_config{$disk}{"sector_size"};
338    
339        # modify the disk to claim the space for the second partition table        # modify the disk to claim the space for the second partition table
340        $FAI::current_config{$disk}{"end_byte"} -= 34 *        $FAI::current_config{$disk}{"end_byte"} -=
341          $FAI::current_config{$disk}{"sector_size"};          34 * $FAI::current_config{$disk}{"sector_size"};
342    
343        # the space required by the GPTs        # the space required by the GPTs
344        $min_req_total_space += 2 * 34 * $FAI::current_config{$disk}{"sector_size"};        $min_req_total_space +=
345            2 * 34 * $FAI::current_config{$disk}{"sector_size"};
346      }      }
347    
348      # the list of partitions that we need to find start and end bytes for      # the list of partitions that we need to find start and end bytes for
349      my @worklist = ( sort keys %{ $FAI::configs{$config}{"partitions"} } );      my @worklist = ( sort keys %{ $FAI::configs{$config}{"partitions"} } );
350    
351      while ( scalar( @worklist ) > 0 )      while ( scalar(@worklist) > 0 )
352      {      {
353    
354        # work on the first entry of the list        # work on the first entry of the list
355        my $part_id = $worklist[ 0 ];        my $part_id = $worklist[0];
356    
357        # the partition $part_id must be preserved        # the partition $part_id must be preserved
358        if (        if ( $FAI::configs{$config}{"partitions"}{$part_id}{"size"}{"preserve"} ==
         $FAI::configs{$config}{"partitions"}{$part_id}{"size"}{"preserve"} ==  
359          1 )          1 )
360        {        {
361    
# Line 339  sub compute_partition_sizes Line 364  sub compute_partition_sizes
364            or die "$part_id can't be preserved, it does not exist.\n";            or die "$part_id can't be preserved, it does not exist.\n";
365    
366          ( $next_start >          ( $next_start >
367            $FAI::current_config{$disk}{"partitions"}{$part_id}{"begin_byte"} )              $FAI::current_config{$disk}{"partitions"}{$part_id}{"begin_byte"} )
368            and die            and die
369            "Previous partitions overflow begin of preserved partition $part_id\n";  "Previous partitions overflow begin of preserved partition $part_id\n";
370    
371          # set the effective size to the value known already          # set the effective size to the value known already
372          $FAI::configs{$config}{"partitions"}{$part_id}{"size"}{"eff_size"} =          $FAI::configs{$config}{"partitions"}{$part_id}{"size"}{"eff_size"} =
# Line 360  sub compute_partition_sizes Line 385  sub compute_partition_sizes
385          # set the next start          # set the next start
386          $next_start =          $next_start =
387            $FAI::configs{$config}{"partitions"}{$part_id}{"end_byte"} + 1;            $FAI::configs{$config}{"partitions"}{$part_id}{"end_byte"} + 1;
388    
389          # several msdos specific parts          # several msdos specific parts
390          if ( $FAI::configs{$config}{"disklabel"} eq "msdos" )          if ( $FAI::configs{$config}{"disklabel"} eq "msdos" )
391          {          {
392    
393            # make sure the partition ends at a cylinder boundary            # make sure the partition ends at a cylinder boundary
394            ( 0 == ( $FAI::current_config{$disk}{"partitions"}{$part_id}{"end_byte"} + 1 ) %            (
395              ( $FAI::current_config{$disk}{"sector_size"} *              0 == (
396                $FAI::current_config{$disk}{"bios_sectors_per_track"} *                $FAI::current_config{$disk}{"partitions"}{$part_id}{"end_byte"} +
397                $FAI::current_config{$disk}{"bios_heads"} ) ) or die                  1
398              "Preserved partition $part_id does not end at a cylinder boundary\n";                ) % (
399                  $FAI::current_config{$disk}{"sector_size"} *
400                    $FAI::current_config{$disk}{"bios_sectors_per_track"} *
401                    $FAI::current_config{$disk}{"bios_heads"}
402                  )
403                )
404                or die
405    "Preserved partition $part_id does not end at a cylinder boundary\n";
406    
407            # add one head of disk usage if this is a logical partition            # add one head of disk usage if this is a logical partition
408            $min_req_total_space += $FAI::current_config{$disk}{"bios_sectors_per_track"} *            $min_req_total_space +=
409              $FAI::current_config{$disk}{"sector_size"} if ( $part_id > 4);              $FAI::current_config{$disk}{"bios_sectors_per_track"} *
410                $FAI::current_config{$disk}{"sector_size"}
411                if ( $part_id > 4 );
412    
413            # extended partitions consume no space            # extended partitions consume no space
414            if (            if ( $FAI::configs{$config}{"partitions"}{$part_id}{"size"}
415              $FAI::configs{$config}{"partitions"}{$part_id}{"size"}{"extended"} ==              {"extended"} == 1 )
             1 )  
416            {            {
417    
418              # revert the addition of the size              # revert the addition of the size
419              $min_req_total_space -=              $min_req_total_space -=
420                $FAI::configs{$config}{"partitions"}{$part_id}{"size"}{"eff_size"};                $FAI::configs{$config}{"partitions"}{$part_id}{"size"}
421                  {"eff_size"};
422    
423              # set the next start to the start of the extended partition              # set the next start to the start of the extended partition
424              $next_start =              $next_start =
425                $FAI::configs{$config}{"partitions"}{$part_id}{"start_byte"};                $FAI::configs{$config}{"partitions"}{$part_id}{"start_byte"};
426            }            }
427    
428          }          }
429    
430          # on gpt, ensure that the partition ends at a sector boundary          # on gpt, ensure that the partition ends at a sector boundary
431          if ( $FAI::configs{$config}{"disklabel"} eq "gpt" )          if ( $FAI::configs{$config}{"disklabel"} eq "gpt" )
432          {          {
433            ( 0 == ( $FAI::current_config{$disk}{"partitions"}{$part_id}{"end_byte"} + 1 ) %            (
434              $FAI::current_config{$disk}{"sector_size"} ) or die              0 == (
435                  $FAI::current_config{$disk}{"partitions"}{$part_id}{"end_byte"} +
436                    1
437                  ) % $FAI::current_config{$disk}{"sector_size"}
438                )
439                or die
440              "Preserved partition $part_id does not end at a sector boundary\n";              "Preserved partition $part_id does not end at a sector boundary\n";
441          }          }
442    
443          # partition done          # partition done
444          shift @worklist;          shift @worklist;
445        }        }
446    
447        # msdos specific: deal with extended partitions        # msdos specific: deal with extended partitions
448        elsif (        elsif (
449          $FAI::configs{$config}{"partitions"}{$part_id}{"size"}{"extended"} ==          $FAI::configs{$config}{"partitions"}{$part_id}{"size"}{"extended"} ==
450          1 )          1 )
451        {        {
452          ( $FAI::configs{$config}{"disklabel"} eq "msdos" ) or die          ( $FAI::configs{$config}{"disklabel"} eq "msdos" )
453            "found an extended partition on a non-msdos disklabel\n";            or die "found an extended partition on a non-msdos disklabel\n";
454    
455          # make sure that there is only one extended partition          # make sure that there is only one extended partition
456          ( $extended == -1 || 1 == scalar( @worklist ) )          ( $extended == -1 || 1 == scalar(@worklist) )
457            or die "INTERNAL ERROR: More than 1 extended partition\n";            or die "INTERNAL ERROR: More than 1 extended partition\n";
458    
459          # ensure that it is a primary partition          # ensure that it is a primary partition
460          ( $part_id <= 4 ) or die          ( $part_id <= 4 )
461              or die
462            "INTERNAL ERROR: Extended partition wouldn't be a primary one\n";            "INTERNAL ERROR: Extended partition wouldn't be a primary one\n";
463    
464          # set the local variable to this id          # set the local variable to this id
# Line 425  sub compute_partition_sizes Line 467  sub compute_partition_sizes
467          # the size cannot be determined now, push it to the end of the          # the size cannot be determined now, push it to the end of the
468          # worklist; the check against $extended being == -1 ensures that          # worklist; the check against $extended being == -1 ensures that
469          # there is no indefinite loop          # there is no indefinite loop
470          if( scalar( @worklist ) > 1 )          if ( scalar(@worklist) > 1 )
471          {          {
472            push @worklist, shift @worklist;            push @worklist, shift @worklist;
473          }          }
474    
475          # determine the size of the extended partition          # determine the size of the extended partition
476          else          else
477          {          {
478            my $epbr_size = $FAI::current_config{$disk}{"bios_sectors_per_track"} *            my $epbr_size =
479                $FAI::current_config{$disk}{"bios_sectors_per_track"} *
480              $FAI::current_config{$disk}{"sector_size"};              $FAI::current_config{$disk}{"sector_size"};
481    
482            # initialise the size and the start byte            # initialise the size and the start byte
483            $FAI::configs{$config}{"partitions"}{$part_id}{"size"}{"eff_size"} = 0;            $FAI::configs{$config}{"partitions"}{$part_id}{"size"}{"eff_size"} =
484                0;
485            $FAI::configs{$config}{"partitions"}{$part_id}{"start_byte"} = -1;            $FAI::configs{$config}{"partitions"}{$part_id}{"start_byte"} = -1;
486    
487            foreach my $p ( sort keys %{ $FAI::configs{$config}{"partitions"} } )            foreach my $p ( sort keys %{ $FAI::configs{$config}{"partitions"} } )
# Line 450  sub compute_partition_sizes Line 495  sub compute_partition_sizes
495                  $FAI::configs{$config}{"partitions"}{$p}{"start_byte"} -                  $FAI::configs{$config}{"partitions"}{$p}{"start_byte"} -
496                  $epbr_size;                  $epbr_size;
497              }              }
498    
499              $FAI::configs{$config}{"partitions"}{$part_id}{"size"}{"eff_size"} +=              $FAI::configs{$config}{"partitions"}{$part_id}{"size"}
500                  {"eff_size"} +=
501                $FAI::configs{$config}{"partitions"}{$p}{"size"}{"eff_size"} +                $FAI::configs{$config}{"partitions"}{$p}{"size"}{"eff_size"} +
502                $epbr_size;                $epbr_size;
503    
504              $FAI::configs{$config}{"partitions"}{$part_id}{"end_byte"} =              $FAI::configs{$config}{"partitions"}{$part_id}{"end_byte"} =
505                $FAI::configs{$config}{"partitions"}{$p}{"end_byte"};                $FAI::configs{$config}{"partitions"}{$p}{"end_byte"};
506            }            }
507    
508            ( $FAI::configs{$config}{"partitions"}{$part_id}{"size"}{"eff_size"}            ( $FAI::configs{$config}{"partitions"}{$part_id}{"size"}{"eff_size"} >
509              > 0 ) or die                0 )
510              "Extended partition has a size of 0\n";              or die "Extended partition has a size of 0\n";
511    
512            # partition done            # partition done
513            shift @worklist;            shift @worklist;
514          }          }
515        }        }
516        else        else
517        {        {
518    
519          # make sure the size specification is a range (even though it might be          # make sure the size specification is a range (even though it might be
520          # something like x-x) and store the dimensions          # something like x-x) and store the dimensions
521          ( $FAI::configs{$config}{"partitions"}{$part_id}{"size"}{"range"} =~          ( $FAI::configs{$config}{"partitions"}{$part_id}{"size"}{"range"} =~
# Line 482  sub compute_partition_sizes Line 529  sub compute_partition_sizes
529          {          {
530    
531            # rewrite it to bytes            # rewrite it to bytes
532            $start = POSIX::floor(            $start =
533              $FAI::current_config{$disk}{"size"} * $1 / 100 );              POSIX::floor( $FAI::current_config{$disk}{"size"} * $1 / 100 );
534          }          }
535          else          else
536          {          {
# Line 497  sub compute_partition_sizes Line 544  sub compute_partition_sizes
544          {          {
545    
546            # rewrite it to bytes            # rewrite it to bytes
547            $end =            $end = POSIX::ceil( $FAI::current_config{$disk}{"size"} * $1 / 100 );
             POSIX::ceil( $FAI::current_config{$disk}{"size"} * $1 / 100 );  
548          }          }
549          else          else
550          {          {
# Line 506  sub compute_partition_sizes Line 552  sub compute_partition_sizes
552            # it is given in megabytes, make it bytes            # it is given in megabytes, make it bytes
553            $end = $end * 1024.0 * 1024.0;            $end = $end * 1024.0 * 1024.0;
554          }          }
555    
556          # make sure that $end >= $start          # make sure that $end >= $start
557          ( $end >= $start ) or die "INTERNAL ERROR: end < start\n";          ( $end >= $start ) or die "INTERNAL ERROR: end < start\n";
558    
559          # check, whether the size is fixed          # check, whether the size is fixed
560          if ( $end != $start )          if ( $end != $start )
561          {          {
562    
563            # the end of the current range (may be the end of the disk or some            # the end of the current range (may be the end of the disk or some
564            # preserved partition            # preserved partition
565            my $end_of_range = -1;            my $end_of_range = -1;
566    
567            # minimum space required by all partitions, i.e., the lower ends of the           # minimum space required by all partitions, i.e., the lower ends of the
568            # ranges           # ranges
569            # $min_req_space counts up to the next preserved partition or the           # $min_req_space counts up to the next preserved partition or the
570            # end of the disk           # end of the disk
571            my $min_req_space = 0;            my $min_req_space = 0;
572    
573            # maximum useful space            # maximum useful space
574            my $max_space = 0;            my $max_space = 0;
575    
576            # inspect all remaining entries in the worklist            # inspect all remaining entries in the worklist
577            foreach my $p ( @worklist )            foreach my $p (@worklist)
578            {            {
579    
580              # we have found the delimiter              # we have found the delimiter
581              if (              if ( $FAI::configs{$config}{"partitions"}{$p}{"size"}{"preserve"} ==
               $FAI::configs{$config}{"partitions"}{$p}{"size"}{"preserve"} ==  
582                1 )                1 )
583              {              {
584                $end_of_range =                $end_of_range =
585                  $FAI::current_config{$disk}{"partitions"}{$p}{"begin_byte"};                  $FAI::current_config{$disk}{"partitions"}{$p}{"begin_byte"};
586    
587                # logical partitions require the space for the EPBR to be left                # logical partitions require the space for the EPBR to be left
588                # out                # out
589                if ( ( $FAI::configs{$config}{"disklabel"} eq "msdos" ) &&                if ( ( $FAI::configs{$config}{"disklabel"} eq "msdos" )
590                  ( $p > 4 ) )                  && ( $p > 4 ) )
591                {                {
592                  $end_of_range -= $FAI::current_config{$disk}{"bios_sectors_per_track"} *                  $end_of_range -=
593                      $FAI::current_config{$disk}{"bios_sectors_per_track"} *
594                    $FAI::current_config{$disk}{"sector_size"};                    $FAI::current_config{$disk}{"sector_size"};
595                }                }
596                last;                last;
597              }              }
598              elsif (              elsif (
599                $FAI::configs{$config}{"partitions"}{$p}{"size"}{"extended"} == 1 )                $FAI::configs{$config}{"partitions"}{$p}{"size"}{"extended"} ==
600                  1 )
601              {              {
602                next;                next;
603              }              }
604              else              else
605              {              {
606                # below is a slight duplication of the code  
607                # make sure the size specification is a range (even though it might be            # below is a slight duplication of the code
608                # something like x-x) and store the dimensions            # make sure the size specification is a range (even though it might be
609              # something like x-x) and store the dimensions
610                ( $FAI::configs{$config}{"partitions"}{$p}{"size"}{"range"} =~                ( $FAI::configs{$config}{"partitions"}{$p}{"size"}{"range"} =~
611                    /^(\d+%?)-(\d+%?)$/ )                    /^(\d+%?)-(\d+%?)$/ )
612                  or die "INTERNAL ERROR: Invalid range\n";                  or die "INTERNAL ERROR: Invalid range\n";
# Line 567  sub compute_partition_sizes Line 618  sub compute_partition_sizes
618                {                {
619    
620                  # rewrite it to bytes                  # rewrite it to bytes
621                  $min_size = POSIX::floor(                  $min_size =
622                      POSIX::floor(
623                    $FAI::current_config{$disk}{"size"} * $1 / 100 );                    $FAI::current_config{$disk}{"size"} * $1 / 100 );
624                }                }
625                else                else
# Line 576  sub compute_partition_sizes Line 628  sub compute_partition_sizes
628                  # it is given in megabytes, make it bytes                  # it is given in megabytes, make it bytes
629                  $min_size *= 1024.0 * 1024.0;                  $min_size *= 1024.0 * 1024.0;
630                }                }
631    
632                # end may be given in percents of the size                # end may be given in percents of the size
633                if ( $max_size =~ /^(\d+)%$/ )                if ( $max_size =~ /^(\d+)%$/ )
634                {                {
# Line 594  sub compute_partition_sizes Line 646  sub compute_partition_sizes
646    
647                # logical partitions require the space for the EPBR to be left                # logical partitions require the space for the EPBR to be left
648                # out                # out
649                if ( ( $FAI::configs{$config}{"disklabel"} eq "msdos" ) &&                if ( ( $FAI::configs{$config}{"disklabel"} eq "msdos" )
650                  ( $p > 4 ) )                  && ( $p > 4 ) )
651                {                {
652                  $min_size += $FAI::current_config{$disk}{"bios_sectors_per_track"} *                  $min_size +=
653                      $FAI::current_config{$disk}{"bios_sectors_per_track"} *
654                    $FAI::current_config{$disk}{"sector_size"};                    $FAI::current_config{$disk}{"sector_size"};
655                  $max_size += $FAI::current_config{$disk}{"bios_sectors_per_track"} *                  $max_size +=
656                      $FAI::current_config{$disk}{"bios_sectors_per_track"} *
657                    $FAI::current_config{$disk}{"sector_size"};                    $FAI::current_config{$disk}{"sector_size"};
658                }                }
659    
660                $min_req_space += $min_size;                $min_req_space += $min_size;
661                $max_space += $max_size;                $max_space     += $max_size;
662              }              }
663            }            }
664    
665            # set the end if we have reached the end of the disk            # set the end if we have reached the end of the disk
666            $end_of_range = $FAI::current_config{$disk}{"end_byte"} if ( -1 ==            $end_of_range = $FAI::current_config{$disk}{"end_byte"}
667              $end_of_range );              if ( -1 == $end_of_range );
668    
669            my $available_space = $end_of_range - $next_start + 1;            my $available_space = $end_of_range - $next_start + 1;
670    
671            # the next boundary is closer than the minimal space that we need            # the next boundary is closer than the minimal space that we need
672            ( $available_space < $min_req_space ) and die            ( $available_space < $min_req_space )
673              "Insufficient space available for partition $part_id\n";              and die "Insufficient space available for partition $part_id\n";
674    
675            # the new size            # the new size
676            my $scaled_size = $end;            my $scaled_size = $end;
677            $scaled_size = POSIX::floor( ( $end - $start ) * ( ( $available_space -            $scaled_size = POSIX::floor(
678                  $min_req_space ) / ( $max_space - $min_req_space ) ) ) +              ( $end - $start ) * (
679                  $start if ( $max_space > $available_space );                ( $available_space - $min_req_space ) /
680                    ( $max_space - $min_req_space )
681                )
682                ) + $start
683                if ( $max_space > $available_space );
684    
685            ( $scaled_size >= $start ) or die            ( $scaled_size >= $start )
686                or die
687              "INTERNAL ERROR: scaled size is smaller than the desired minimum\n";              "INTERNAL ERROR: scaled size is smaller than the desired minimum\n";
688    
689            $start = $scaled_size;            $start = $scaled_size;
690            $end = $start;            $end   = $start;
691          }          }
692    
693          # now we compute the effective locations on the disk          # now we compute the effective locations on the disk
694          # msdos specific offset for logical partitions          # msdos specific offset for logical partitions
695          if ( ( $FAI::configs{$config}{"disklabel"} eq "msdos" ) &&          if ( ( $FAI::configs{$config}{"disklabel"} eq "msdos" )
696            ( $part_id > 4 ) )            && ( $part_id > 4 ) )
697          {          {
698    
699            # add one head of disk usage if this is a logical partition            # add one head of disk usage if this is a logical partition
700            $min_req_total_space += $FAI::current_config{$disk}{"bios_sectors_per_track"} *            $min_req_total_space +=
701                $FAI::current_config{$disk}{"bios_sectors_per_track"} *
702              $FAI::current_config{$disk}{"sector_size"};              $FAI::current_config{$disk}{"sector_size"};
703    
704            # move the start byte as well            # move the start byte as well
705            $next_start += $FAI::current_config{$disk}{"bios_sectors_per_track"} *            $next_start += $FAI::current_config{$disk}{"bios_sectors_per_track"} *
706              $FAI::current_config{$disk}{"sector_size"};              $FAI::current_config{$disk}{"sector_size"};
# Line 654  sub compute_partition_sizes Line 716  sub compute_partition_sizes
716          # on msdos, ensure that the partition ends at a cylinder boundary          # on msdos, ensure that the partition ends at a cylinder boundary
717          if ( $FAI::configs{$config}{"disklabel"} eq "msdos" )          if ( $FAI::configs{$config}{"disklabel"} eq "msdos" )
718          {          {
719            $end_byte -= ( $end_byte + 1 ) %            $end_byte -=
720              ( $FAI::current_config{$disk}{"sector_size"} *              ( $end_byte + 1 ) % ( $FAI::current_config{$disk}{"sector_size"} *
721                $FAI::current_config{$disk}{"bios_sectors_per_track"} *                $FAI::current_config{$disk}{"bios_sectors_per_track"} *
722                $FAI::current_config{$disk}{"bios_heads"} );                $FAI::current_config{$disk}{"bios_heads"} );
723          }          }
# Line 663  sub compute_partition_sizes Line 725  sub compute_partition_sizes
725          # on gpt, ensure that the partition ends at a sector boundary          # on gpt, ensure that the partition ends at a sector boundary
726          if ( $FAI::configs{$config}{"disklabel"} eq "gpt" )          if ( $FAI::configs{$config}{"disklabel"} eq "gpt" )
727          {          {
728            $end_byte -= ( $end_byte + 1 ) %            $end_byte -=
729              $FAI::current_config{$disk}{"sector_size"};              ( $end_byte + 1 ) % $FAI::current_config{$disk}{"sector_size"};
730          }          }
731    
732          # set $start and $end to the effective values          # set $start and $end to the effective values
733          $start = $end_byte - $next_start + 1;          $start = $end_byte - $next_start + 1;
734          $end = $start;          $end   = $start;
735    
736          # write back the size spec in bytes          # write back the size spec in bytes
737          $FAI::configs{$config}{"partitions"}{$part_id}{"size"}{"range"} =          $FAI::configs{$config}{"partitions"}{$part_id}{"size"}{"range"} =
738            $start . "-" . $end;            $start . "-" . $end;
# Line 680  sub compute_partition_sizes Line 742  sub compute_partition_sizes
742            $start;            $start;
743    
744          # write the end byte to the configuration          # write the end byte to the configuration
745          $FAI::configs{$config}{"partitions"}{$part_id}{"end_byte"} =          $FAI::configs{$config}{"partitions"}{$part_id}{"end_byte"} = $end_byte;
746            $end_byte;  
   
747          # and add it to the total disk space required by this config          # and add it to the total disk space required by this config
748          $min_req_total_space +=          $min_req_total_space +=
749            $FAI::configs{$config}{"partitions"}{$part_id}{"size"}{"eff_size"};            $FAI::configs{$config}{"partitions"}{$part_id}{"size"}{"eff_size"};
# Line 690  sub compute_partition_sizes Line 751  sub compute_partition_sizes
751          # set the next start          # set the next start
752          $next_start =          $next_start =
753            $FAI::configs{$config}{"partitions"}{$part_id}{"end_byte"} + 1;            $FAI::configs{$config}{"partitions"}{$part_id}{"end_byte"} + 1;
754    
755          # partition done          # partition done
756          shift @worklist;          shift @worklist;
757        }        }
# Line 699  sub compute_partition_sizes Line 760  sub compute_partition_sizes
760      # check, whether there is sufficient space on the disk      # check, whether there is sufficient space on the disk
761      ( $min_req_total_space > $FAI::current_config{$disk}{"size"} )      ( $min_req_total_space > $FAI::current_config{$disk}{"size"} )
762        and die        and die
763        "Disk $disk is too small - at least $min_req_total_space bytes are required\n";  "Disk $disk is too small - at least $min_req_total_space bytes are required\n";
764    
765      # make sure, extended partitions are only created on msdos disklabels      # make sure, extended partitions are only created on msdos disklabels
766      ( $FAI::configs{$config}{"disklabel"} ne "msdos" && $extended > -1 )      ( $FAI::configs{$config}{"disklabel"} ne "msdos" && $extended > -1 )
767        and die        and die
768        "INTERNAL ERROR: extended partitions are not supported by this disklabel\n";  "INTERNAL ERROR: extended partitions are not supported by this disklabel\n";
769    
770      # ensure that we have done our work      # ensure that we have done our work
771      foreach      foreach my $part_id ( sort keys %{ $FAI::configs{$config}{"partitions"} } )
       my $part_id ( sort keys %{ $FAI::configs{$config}{"partitions"} } )  
772      {      {
773        ( defined( $FAI::configs{$config}{"partitions"}{$part_id}{"start_byte"} ) &&        ( defined( $FAI::configs{$config}{"partitions"}{$part_id}{"start_byte"} )
774          defined( $FAI::configs{$config}{"partitions"}{$part_id}{"end_byte"} ) )            && defined(
775              $FAI::configs{$config}{"partitions"}{$part_id}{"end_byte"} ) )
776          or die "INTERNAL ERROR: start or end of partition $part_id not set\n";          or die "INTERNAL ERROR: start or end of partition $part_id not set\n";
777      }      }
778    

Legend:
Removed from v.4613  
changed lines
  Added in v.4614

  ViewVC Help
Powered by ViewVC 1.1.5