From 651a256ee82c18578c3f551e89d3bcadaf68ab43 Mon Sep 17 00:00:00 2001 From: Pascal Rigaux Date: Mon, 20 Sep 2004 09:46:40 +0000 Subject: - add field {part_number} for partitions (handle it in subpart_from_wild_device_name(), partition_table::read()) - create migrate_device_names() to handle the change of device names when changing kernel&modules (eg: hde->hda or hda->sda) - change prototype of install_any::use_root_part() (prefix is dropped, optional $in is added) - create fs::type::can_be_this_fs_type() and use it - create devices::part_number() and devices::part_prefix() and use them --- perl-install/devices.pm | 13 ++++ perl-install/diskdrake/interactive.pm | 1 + perl-install/fs.pm | 10 ++- perl-install/fs/mount_options.pm | 4 +- perl-install/fs/type.pm | 5 ++ perl-install/install_any.pm | 112 ++++++++++++++++++++++++++---- perl-install/install_steps.pm | 2 +- perl-install/install_steps_interactive.pm | 2 +- perl-install/partition_table.pm | 20 ++++-- perl-install/standalone/drakupdate_fstab | 1 + 10 files changed, 142 insertions(+), 28 deletions(-) diff --git a/perl-install/devices.pm b/perl-install/devices.pm index 8a3654566..c7be884c2 100644 --- a/perl-install/devices.pm +++ b/perl-install/devices.pm @@ -239,4 +239,17 @@ sub from_devfs { undef; } +sub simple_partition_scan { + my ($part) = @_; + $part->{device} =~ /([hs]d[a-z])(\d+)$/; +} +sub part_number { + my ($part) = @_; + (simple_partition_scan($part))[1]; +} +sub part_prefix { + my ($part) = @_; + (simple_partition_scan($part))[0]; +} + 1; diff --git a/perl-install/diskdrake/interactive.pm b/perl-install/diskdrake/interactive.pm index 679235d95..412258eed 100644 --- a/perl-install/diskdrake/interactive.pm +++ b/perl-install/diskdrake/interactive.pm @@ -27,6 +27,7 @@ struct part { int size # in sectors int pt_type # 0x82, 0x83, 0x6 ... string fs_type # 'ext2', 'nfs', ... + int part_number # 1 for hda1... string device # 'hda5', 'sdc1' ... string devfs_device # 'ide/host0/bus0/target0/lun0/part5', ... string prefer_devfs_name # should the {devfs_device} or the {device} be used in fstab diff --git a/perl-install/fs.pm b/perl-install/fs.pm index 8d76939b8..2f8eb0057 100644 --- a/perl-install/fs.pm +++ b/perl-install/fs.pm @@ -157,8 +157,14 @@ sub subpart_from_wild_device_name { } $dev =~ s!/(tmp|u?dev)/!!; - my $is_devfs = $dev =~ m!/(disc|part\d+)$!; - $part{$is_devfs ? 'devfs_device' : 'device'} = $dev; + if (my ($is_devfs, $part_number) = $dev =~ m!/(disc|part(\d+))$!) { + $part{part_number} = $part_number if $part_number; + $part{devfs_device} = $dev; + } else { + $part{device} = $dev; + my $part_number = devices::part_number(\%part); + $part{part_number} = $part_number if $part_number; + } return \%part; } elsif ($dev =~ m!^/! && -f "$::prefix$dev") { #- loopback file diff --git a/perl-install/fs/mount_options.pm b/perl-install/fs/mount_options.pm index c7baa4e7b..b4890e877 100644 --- a/perl-install/fs/mount_options.pm +++ b/perl-install/fs/mount_options.pm @@ -195,7 +195,7 @@ sub set_default { if ($part->{fs_type} eq 'smbfs') { add2hash($options, { 'username=' => '%' }) if !$options->{'credentials='}; } - if (member('vfat', split(':', $part->{fs_type})) || $part->{fs_type} eq 'auto') { + if (fs::type::can_be_this_fs_type($part, 'vfat')) { put_in_hash($options, { users => 1, noexec => 0, @@ -211,7 +211,7 @@ sub set_default { 'umask=0' => $opts{security} < 3, 'umask=0022' => $opts{security} < 4, }); } - if (member('iso9660', split(':', $part->{fs_type})) || $part->{fs_type} eq 'auto') { + if (fs::type::can_be_this_fs_type($part, 'iso9660')) { put_in_hash($options, { user => 1, noexec => 0, 'iocharset=' => $opts{iocharset} }); } if ($part->{fs_type} eq 'reiserfs') { diff --git a/perl-install/fs/type.pm b/perl-install/fs/type.pm index 0b361b8f2..70aace58f 100644 --- a/perl-install/fs/type.pm +++ b/perl-install/fs/type.pm @@ -341,6 +341,11 @@ sub isMounted { $_[0]{isMounted} } sub isBusy { isMounted($_[0]) || isPartOfRAID($_[0]) || isPartOfLVM($_[0]) || isPartOfLoopback($_[0]) } sub isSpecial { isRAID($_[0]) || isLVM($_[0]) || isLoopback($_[0]) || isUBD($_[0]) } +sub can_be_this_fs_type { + my ($part, $fs_type) = @_; + $part->{fs_type} && ($part->{fs_type} eq 'auto' || member($fs_type, split(':', $part->{fs_type}))); +} + sub maybeFormatted { my ($part) = @_; $part->{isFormatted} || !$part->{notFormatted} && !$part->{bad_fs_type_magic}; diff --git a/perl-install/install_any.pm b/perl-install/install_any.pm index fa73a4a7b..ac074414e 100644 --- a/perl-install/install_any.pm +++ b/perl-install/install_any.pm @@ -1270,24 +1270,106 @@ sub find_root_parts { } else { () } } @$fstab; } + +sub migrate_device_names { + my ($all_hds, $from_fstab, $new_root, $root_from_fstab, $o_in) = @_; + + log::l("warning: fstab says root partition is $root_from_fstab->{device}, whereas we were reading fstab from $new_root->{device}"); + my ($old_prefix, $old_part_number) = devices::simple_partition_scan($root_from_fstab); + my ($new_prefix, $new_part_number) = devices::simple_partition_scan($new_root); + + if ($old_part_number != $new_part_number) { + log::l("argh, $root_from_fstab->{device} and $old_part_number->{device} are not the same partition number"); + return; + } + + log::l("replacing $old_prefix with $new_prefix"); + + my %h; + foreach (@$from_fstab) { + if ($_->{device} =~ s!^\Q$old_prefix!$new_prefix!) { + #- this is simple to handle, nothing more to do + } elsif ($_->{part_number}) { + my $device_prefix = devices::part_prefix($_); + push @{$h{$device_prefix}}, $_; + } else { + #- hopefully this doesn't need anything special + } + }; + my @from_fstab_per_hds = values %h or return; + + + my @current_hds = grep { $new_root->{rootDevice} ne $_->{device} } fs::get::hds($all_hds); + + found_one: + @from_fstab_per_hds or return; + + foreach my $from_fstab_per_hd (@from_fstab_per_hds) { + my ($matching, $other) = partition { + my $hd = $_; + every { + my $wanted = $_; + my $part = find { $_->{part_number} eq $wanted->{part_number} } partition_table::get_normal_parts($hd); + $part && $part->{fs_type} && fs::type::can_be_this_fs_type($wanted, $part->{fs_type}); + } @$from_fstab_per_hd; + } @current_hds; + @$matching == 1 or next; + + my ($hd) = @$matching; + @current_hds = @$other; + @from_fstab_per_hds = grep { $_ != $from_fstab_per_hd } @from_fstab_per_hds; + + log::l("$hd->{device} nicely corresponds to " . join(' ', map { $_->{device} } @$from_fstab_per_hd)); + foreach (@$from_fstab_per_hd) { + partition_table::compute_device_name($_, $hd); + } + goto found_one; + } + + #- we can't find one and only one matching hd + my @from_fstab_not_handled = map { @$_ } @from_fstab_per_hds; + log::l("we still don't know what to do with: " . join(' ', map { $_->{device} } @from_fstab_not_handled)); + + + if (!$o_in) { + die 'still have'; + log::l("well, ignoring them!"); + return; + } + + my $propositions_valid = every { + my $wanted = $_; + my @parts = grep { $_->{part_number} eq $wanted->{part_number} + && $_->{fs_type} && fs::type::can_be_this_fs_type($wanted, $_->{fs_type}) } fs::get::hds_fstab(@current_hds); + $wanted->{propositions} = \@parts; + @parts > 0; + } @from_fstab_not_handled; + + $o_in->ask_from('', + N("The "), + [ map { + { label => N("%s (was %s)", $_->{mntpoint}, $_->{device}), val => \$_->{device}, + format => sub { $_[0] && $_->{device} }, + list => [ '', + $propositions_valid ? @{$_->{propositions}} : + fs::get::hds_fstab(@current_hds) ] }; + } @from_fstab_not_handled ]); +} + sub use_root_part { - my ($all_hds, $part, $prefix) = @_; + my ($all_hds, $part, $o_in) = @_; { - my $handle = any::inspect($part, $prefix) or die; - - my @l = fs::read_fstab($handle->{dir}, '/etc/fstab', 'keep_default'); - - my $root = fs::get::root_(\@l); - if (!fsedit::is_same_hd($root, $part)) { - log::l("warning: fstab says root partition is $root->{device}, whereas we were reading fstab from $part->{device}"); - my ($old, $new) = map { my $s = $_->{device}; $s =~ s/\d+$//; $s } ($root, $part); - if ($old && $new) { - log::l("replacing $old with $new"); - $_->{device} =~ s!^\Q$old!$new! foreach @l; - log::l("l contains: $_->{device} $_->{mntpoint}") foreach @l; - } + my $handle = any::inspect($part, $::prefix) or die; + + my @from_fstab = fs::read_fstab($handle->{dir}, '/etc/fstab', 'keep_default'); + + my $root_from_fstab = fs::get::root_(\@from_fstab); + if (!fsedit::is_same_hd($root_from_fstab, $part)) { + log::l("from_fstab contained: $_->{device} $_->{mntpoint}") foreach @from_fstab; + migrate_device_names($all_hds, \@from_fstab, $part, $root_from_fstab, $o_in); + log::l("from_fstab now contains: $_->{device} $_->{mntpoint}") foreach @from_fstab; } - fs::add2all_hds($all_hds, @l); + fs::add2all_hds($all_hds, @from_fstab); log::l("fstab is now: $_->{device} $_->{mntpoint}") foreach fs::get::fstab($all_hds); } isSwap($_) and $_->{mntpoint} = 'swap' foreach fs::get::really_all_fstab($all_hds); #- use all available swap. diff --git a/perl-install/install_steps.pm b/perl-install/install_steps.pm index fe8f207e2..f1198479f 100644 --- a/perl-install/install_steps.pm +++ b/perl-install/install_steps.pm @@ -170,7 +170,7 @@ sub selectInstallClass { if ($o->{partitioning}{use_existing_root} || $o->{isUpgrade}) { # either one root is defined (and all is ok), or we take the first one we find my $p = fs::get::root_($o->{fstab}) || (first(install_any::find_root_parts($o->{fstab}, $o->{prefix})) || die)->{part}; - install_any::use_root_part($o->{all_hds}, $p, $o->{prefix}); + install_any::use_root_part($o->{all_hds}, $p); } } diff --git a/perl-install/install_steps_interactive.pm b/perl-install/install_steps_interactive.pm index b7ac7847c..afee41a6f 100644 --- a/perl-install/install_steps_interactive.pm +++ b/perl-install/install_steps_interactive.pm @@ -162,7 +162,7 @@ sub selectInstallClass { if (ref $p) { my $part = $p->{part}; log::l("choosing to upgrade partition $part->{device}"); - install_any::use_root_part($o->{all_hds}, $part, $o->{prefix}); + install_any::use_root_part($o->{all_hds}, $part, $o); foreach (grep { $_->{mntpoint} } @{$o->{fstab}}) { my ($options, $_unknown) = fs::mount_options::unpack($_); $options->{encrypted} or next; diff --git a/perl-install/partition_table.pm b/perl-install/partition_table.pm index edb061bdb..26995921d 100644 --- a/perl-install/partition_table.pm +++ b/perl-install/partition_table.pm @@ -86,6 +86,12 @@ sub verifyPrimary { verifyParts_(@{$pt->{normal}}, $pt->{extended}); } +sub compute_device_name { + my ($part, $hd) = @_; + $part->{device} = $hd->{prefix} . $part->{part_number}; + $part->{devfs_device} = $hd->{devfs_prefix} . '/part' . $part->{part_number}; +} + sub assign_device_numbers { my ($hd) = @_; @@ -104,15 +110,15 @@ sub assign_device_numbers { log::l("PPC: found a hole on $hd->{prefix} before $_->{start}, skipping device..."); $i++; } - $_->{device} = $hd->{prefix} . $i; - $_->{devfs_device} = $hd->{devfs_prefix} . '/part' . $i; + $_->{part_number} = $i; + compute_device_name($_, $hd); $start = $_->{start} + $_->{size}; $i++; } } else { foreach (@{$hd->{primary}{raw}}) { - $_->{device} = $hd->{prefix} . $i; - $_->{devfs_device} = $hd->{devfs_prefix} . '/part' . $i; + $_->{part_number} = $i; + compute_device_name($_, $hd); $i++; } foreach (map { $_->{normal} } @{$hd->{extended} || []}) { @@ -124,8 +130,8 @@ sub assign_device_numbers { will_tell_kernel($hd, del => $_, 'delay_del'); push @{$hd->{partitionsRenumbered}}, [ $_->{device}, $dev ]; } - $_->{device} = $dev; - $_->{devfs_device} = $hd->{devfs_prefix} . '/part' . $i; + $_->{part_number} = $i; + compute_device_name($_, $hd); if ($renumbered) { will_tell_kernel($hd, add => $_, 'delay_add'); } @@ -338,7 +344,7 @@ sub will_tell_kernel { will_tell_kernel($hd, del => $o_part); will_tell_kernel($hd, add => $o_part); } else { - my $part_number = sub { $o_part->{device} =~ /(\d+)$/ ? $1 : internal_error("bad device " . description($o_part)) }; + my $part_number = sub { devices::part_number($o_part) || internal_error("bad device " . description($o_part)) }; push @{$hd->{'will_tell_kernel' . ($o_delay || '')} ||= []}, [ $action, diff --git a/perl-install/standalone/drakupdate_fstab b/perl-install/standalone/drakupdate_fstab index 25fa7ad1c..938800437 100755 --- a/perl-install/standalone/drakupdate_fstab +++ b/perl-install/standalone/drakupdate_fstab @@ -82,6 +82,7 @@ sub device_name_to_entry { my $e; if (my ($devfs_prefix, $nb) = $name =~ m,(.*)/(?:cd|disc|part(\d+))$,) { $e = find { $_->{devfs_prefix} eq $devfs_prefix } @l; + $e->{part_number} = $nb; $e->{devfs_prefix} ||= $devfs_prefix; $e->{devfs_device} = $e->{devfs_prefix} . '/part' . $nb; if ($e->{devfs_device} eq $name) { -- cgit v1.2.1