summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPascal Rigaux <pixel@mandriva.com>2004-01-15 11:27:12 +0000
committerPascal Rigaux <pixel@mandriva.com>2004-01-15 11:27:12 +0000
commita0092a3d667863341339645f5d0bc9bc4b4b5108 (patch)
treed9a24e421b0ed945ff3d3bced57634cd68e5776f
parent28a23a084b62594b9acf2d0f4d2dd3e7dad60ed8 (diff)
downloaddrakx-a0092a3d667863341339645f5d0bc9bc4b4b5108.tar
drakx-a0092a3d667863341339645f5d0bc9bc4b4b5108.tar.gz
drakx-a0092a3d667863341339645f5d0bc9bc4b4b5108.tar.bz2
drakx-a0092a3d667863341339645f5d0bc9bc4b4b5108.tar.xz
drakx-a0092a3d667863341339645f5d0bc9bc4b4b5108.zip
- remove the use of BLKRRPART (telling the kernel to re-read the partition table) in most cases
- replace with tell_kernel() and will_tell_kernel() - correctly handle in standalone the need to reboot, with no way to forget it (telling the WM to quit nicely then call reboot when it's done)
-rw-r--r--perl-install/c/stuff.xs.pl17
-rw-r--r--perl-install/diskdrake/interactive.pm52
-rw-r--r--perl-install/fsedit.pm4
-rw-r--r--perl-install/install_interactive.pm2
-rw-r--r--perl-install/partition_table.pm107
-rw-r--r--perl-install/partition_table/raw.pm18
6 files changed, 143 insertions, 57 deletions
diff --git a/perl-install/c/stuff.xs.pl b/perl-install/c/stuff.xs.pl
index dc162af36..ec4047b0c 100644
--- a/perl-install/c/stuff.xs.pl
+++ b/perl-install/c/stuff.xs.pl
@@ -229,11 +229,24 @@ dgettext(domainname, msgid)
char * msgid
int
-add_partition(hd, start_sector, size_sector, part_number)
+del_partition(hd, part_number)
int hd
+ int part_number
+ CODE:
+ {
+ struct blkpg_partition p = { 0, 0, part_number, "", "" };
+ struct blkpg_ioctl_arg s = { BLKPG_DEL_PARTITION, 0, sizeof(struct blkpg_partition), (void *) &p };
+ RETVAL = ioctl(hd, BLKPG, &s) == 0;
+ }
+ OUTPUT:
+ RETVAL
+
+int
+add_partition(hd, part_number, start_sector, size_sector)
+ int hd
+ int part_number
unsigned long start_sector
unsigned long size_sector
- int part_number
CODE:
{
long long start = start_sector * 512;
diff --git a/perl-install/diskdrake/interactive.pm b/perl-install/diskdrake/interactive.pm
index 67c9cb721..e9acaf4e6 100644
--- a/perl-install/diskdrake/interactive.pm
+++ b/perl-install/diskdrake/interactive.pm
@@ -110,7 +110,7 @@ struct hd {
bool readonly # is it allowed to modify the partition table
bool getting_rid_of_readonly_allowed # is it forbidden to write because the partition table is badly handled, or is it because we MUST not change the partition table
bool isDirty # does it need to be written to the disk
- bool needKernelReread # must we tell the kernel to reread the partition table
+ list will_tell_kernel # list of actions to tell to the kernel so that it knows the new partition table
bool hasBeenDirty # for undo
bool rebootNeeded # happens when a kernel reread failed
bool partitionsRenumbered # happens when you
@@ -142,7 +142,7 @@ struct raw_hd inherits hd {
string mntpoint # '/', '/usr' ...
string options # 'defaults', 'noauto'
- # invalid: isDirty, needKernelReread, hasBeenDirty, rebootNeeded, primary, extended
+ # invalid: isDirty, will_tell_kernel, hasBeenDirty, rebootNeeded, primary, extended
}
struct all_hds {
@@ -259,7 +259,7 @@ sub Done {
$in->ask_okcancel('', [ formatError($err), N("Continue anyway?") ]) or return;
}
foreach (@{$all_hds->{hds}}) {
- if (!write_partitions($in, $_)) {
+ if (!write_partitions($in, $_, 'skip_check_rebootNeeded')) {
return if !$::isStandalone;
$in->ask_yesorno(N("Quit without saving"), N("Quit without writing the partition table?"), 1) or return;
}
@@ -270,6 +270,10 @@ sub Done {
$all_hds->{current_fstab} = $new;
fs::write_fstab($all_hds);
}
+ if (any { $_->{rebootNeeded} } @{$all_hds->{hds}}) {
+ $in->ask_warn('', N("You need to reboot for the partition table modifications to take place"));
+ tell_wm_and_reboot();
+ }
}
1;
}
@@ -705,7 +709,6 @@ sub Resize {
$part->{size} == $size and return;
my $oldsize = $part->{size};
- $hd->{isDirty} = $hd->{needKernelReread} = 1;
$part->{size} = $size;
$hd->adjustEnd($part);
@@ -715,6 +718,8 @@ sub Resize {
my $adjust = sub {
my ($write_partitions) = @_;
+ partition_table::will_tell_kernel($hd, resize => $part);
+
if (isLVM($hd)) {
lvm::lv_resize($part, $oldsize);
} else {
@@ -1043,16 +1048,20 @@ sub check {
check_mntpoint($in, $part->{mntpoint}, $hd, $part, $all_hds);
}
+sub check_rebootNeeded {
+ my ($_in, $hd) = @_;
+ $hd->{rebootNeeded} and die \N("You'll need to reboot before the modification can take place");
+}
+
sub write_partitions {
- my ($in, $hd) = @_;
+ my ($in, $hd, $b_skip_check_rebootNeeded) = @_;
+ check_rebootNeeded($in, $hd) if !$b_skip_check_rebootNeeded;
$hd->{isDirty} or return 1;
isLVM($hd) and return 1;
$in->ask_okcancel(N("Read carefully!"), N("Partition table of drive %s is going to be written to disk!", $hd->{device}), 1) or return;
- if (!$::testing) {
- partition_table::write($hd);
- }
- $hd->{rebootNeeded} and die \N("You'll need to reboot before the modification can take place");
+ partition_table::write($hd) if !$::testing;
+ check_rebootNeeded($in, $hd) if !$b_skip_check_rebootNeeded;
1;
}
@@ -1244,3 +1253,28 @@ sub choose_encrypt_key {
{ label => N("Encryption key (again)"), val => \$encrypt_key2, hidden => 1 },
]) && $encrypt_key;
}
+
+
+sub tell_wm_and_reboot() {
+ my ($wm, $pid) = any::running_window_manager();
+
+ if (!$wm) {
+ system('reboot');
+ } else {
+ if (fork()) {
+ any::ask_window_manager_to_logout($wm);
+ return;
+ }
+
+ open STDIN, "</dev/zero";
+ open STDOUT, ">/dev/null";
+ open STDERR, ">&STDERR";
+ c::setsid();
+ exec 'perl', '-e', q(
+ my ($wm, $pid) = @ARGV;
+ my $nb;
+ for ($nb = 20; $nb && -e "/proc/$pid"; $nb--) { sleep 1 }
+ exec 'reboot';
+ ), $wm, $pid;
+ }
+}
diff --git a/perl-install/fsedit.pm b/perl-install/fsedit.pm
index dcba0d267..58143023a 100644
--- a/perl-install/fsedit.pm
+++ b/perl-install/fsedit.pm
@@ -682,7 +682,9 @@ sub undo {
my $h; eval $code;
@$_{@partition_table::fields2save} = @$h;
- $_->{isDirty} = $_->{needKernelReread} = 1 if $_->{hasBeenDirty};
+ if ($_->{hasBeenDirty}) {
+ partition_table::will_tell_kernel($_, 'force_reboot'); #- next action needing write_partitions will force it. We can't do it now since more undo may occur, and we must not needReboot now
+ }
}
}
diff --git a/perl-install/install_interactive.pm b/perl-install/install_interactive.pm
index 3b8e350e4..154f1bde1 100644
--- a/perl-install/install_interactive.pm
+++ b/perl-install/install_interactive.pm
@@ -195,7 +195,7 @@ When sure, press Ok."))) or return;
filesystem checks will be run on your next boot into Windows(TM)")) if !isFat($part);
$part->{isFormatted} = 1;
- $hd->{isDirty} = $hd->{needKernelReread} = 1;
+ partition_table::will_tell_kernel($hd, resize => $part); #- down-sizing, write_partitions is not needed
partition_table::adjust_local_extended($hd, $part);
partition_table::adjust_main_extended($hd);
diff --git a/perl-install/partition_table.pm b/perl-install/partition_table.pm
index 2d3fe168d..fd911f7b0 100644
--- a/perl-install/partition_table.pm
+++ b/perl-install/partition_table.pm
@@ -23,7 +23,7 @@ use log;
if_(arch() =~ /ppc/, 'Journalised FS: ext3', 'Journalised FS: ReiserFS', 'Journalised FS: JFS', 'Journalised FS: XFS', 'Apple HFS Partition', 'Apple Bootstrap'));
@important_types2 = ('Linux RAID', 'Linux Logical Volume Manager partition');
-@fields2save = qw(primary extended totalsectors isDirty needKernelReread);
+@fields2save = qw(primary extended totalsectors isDirty will_tell_kernel);
@bad_types = ('Empty', 'DOS 3.3+ Extended Partition', 'Win95: Extended partition, LBA-mapped', 'Linux extended partition');
@@ -374,9 +374,18 @@ sub assign_device_numbers {
}
foreach (map { $_->{normal} } @{$hd->{extended} || []}) {
my $dev = $hd->{prefix} . $i;
- push @{$hd->{partitionsRenumbered}}, [ $_->{device}, $dev ] if $_->{device} && $dev ne $_->{device};
+ my $renumbered = $_->{device} && $dev ne $_->{device};
+ if ($renumbered) {
+ require fs;
+ eval { fs::umount_part($_) }; #- at least try to umount it
+ will_tell_kernel($hd, del => $_, 'delay_del');
+ push @{$hd->{partitionsRenumbered}}, [ $_->{device}, $dev ];
+ }
$_->{device} = $dev;
$_->{devfs_device} = $hd->{devfs_prefix} . '/part' . $i;
+ if ($renumbered) {
+ will_tell_kernel($hd, add => $_, 'delay_add');
+ }
$i++;
}
}
@@ -576,6 +585,64 @@ sub read_extended {
}
}
+sub will_tell_kernel {
+ my ($hd, $action, $o_part, $o_delay) = @_;
+
+ if ($action eq 'resize') {
+ 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)) };
+ push @{$hd->{'will_tell_kernel' . ($o_delay || '')} ||= []},
+ [
+ $action,
+ $action eq 'force_reboot' ? () :
+ $action eq 'add' ? ($part_number->(), $o_part->{start}, $o_part->{size}) :
+ $action eq 'del' ? $part_number->() :
+ internal_error("unknown action $action")
+ ];
+ }
+ if (!$o_delay) {
+ foreach my $delay ('delay_del', 'delay_add') {
+ my $l = delete $hd->{"will_tell_kernel$delay"} or next;
+ push @{$hd->{will_tell_kernel} ||= []}, @$l;
+ }
+ }
+ $hd->{isDirty} = 1;
+}
+
+sub tell_kernel {
+ my ($hd, $tell_kernel) = @_;
+
+ my $F = partition_table::raw::openit($hd);
+
+ my $force_reboot = any { $_->[0] eq 'force_reboot' } @$tell_kernel;
+ if (!$force_reboot) {
+ foreach (@$tell_kernel) {
+ my ($action, $part_number, $o_start, $o_size) = @$_;
+
+ if ($action eq 'add') {
+ $force_reboot ||= !c::add_partition(fileno $F, $part_number, $o_start, $o_size);
+ } elsif ($action eq 'del') {
+ $force_reboot ||= !c::del_partition(fileno $F, $part_number);
+ }
+ log::l("tell kernel $action ($part_number $o_start $o_size), rebootNeeded is now $hd->{rebootNeeded}.");
+ }
+ }
+ if ($force_reboot) {
+ my @magic_parts = grep { $_->{isMounted} && $_->{real_mntpoint} } get_normal_parts($hd);
+ foreach (@magic_parts) {
+ syscall_('umount', $_->{real_mntpoint}) or log::l(N("error unmounting %s: %s", $_->{real_mntpoint}, $!));
+ }
+ $hd->{rebootNeeded} = !ioctl($F, c::BLKRRPART(), 0);
+ log::l("tell kernel force_reboot, rebootNeeded is now $hd->{rebootNeeded}.");
+
+ foreach (@magic_parts) {
+ syscall_('mount', $_->{real_mntpoint}, type2fs($_), c::MS_MGC_VAL()) or log::l(N("mount failed: ") . $!);
+ }
+ }
+}
+
# write the partition table
sub write {
my ($hd) = @_;
@@ -610,29 +677,9 @@ sub write {
$hd->{isDirty} = 0;
$hd->{hasBeenDirty} = 1; #- used in undo (to know if undo should believe isDirty or not)
- if ($hd->{needKernelReread} && ref($hd->{needKernelReread}) eq 'ARRAY' && $::isStandalone) {
- #- we've only been adding partitions. Try special add_partition (using BLKPG_ADD_PARTITION)
- my $F = partition_table::raw::openit($hd) or goto force_reread;
-
- foreach (@{$hd->{needKernelReread}}) {
- c::add_partition(fileno $F, $_->{start}, $_->{size}, $_->{device} =~ /(\d+)$/)
- or goto force_reread;
- }
- } elsif ($hd->{needKernelReread}) {
- force_reread:
- #- now sync disk and re-read the partition table
- common::sync();
-
- my @magic_parts = grep { $_->{isMounted} && $_->{real_mntpoint} } get_normal_parts($hd);
- foreach (@magic_parts) {
- syscall_('umount', $_->{real_mntpoint}) or log::l(N("error unmounting %s: %s", $_->{real_mntpoint}, $!));
- }
- $hd->kernel_read;
- foreach (@magic_parts) {
- syscall_('mount', $_->{real_mntpoint}, type2fs($_), c::MS_MGC_VAL()) or log::l(N("mount failed: ") . $!);
- }
+ if (my $tell_kernel = delete $hd->{will_tell_kernel}) {
+ tell_kernel($hd, $tell_kernel);
}
- $hd->{needKernelReread} = 0;
}
sub active {
@@ -652,11 +699,13 @@ sub remove {
#- first search it in the primary partitions
$i = 0; foreach (@{$hd->{primary}{normal}}) {
if ($_ eq $part) {
+ will_tell_kernel($hd, del => $_);
+
splice(@{$hd->{primary}{normal}}, $i, 1);
%$_ = (); #- blank it
$hd->raw_removed($hd->{primary}{raw});
- return $hd->{isDirty} = $hd->{needKernelReread} = 1;
+ return 1;
}
$i++;
}
@@ -674,7 +723,8 @@ sub remove {
remove_empty_extended($hd);
assign_device_numbers($hd);
- return $hd->{isDirty} = $hd->{needKernelReread} = 1;
+ will_tell_kernel($hd, del => $part);
+ return 1;
}
0;
}
@@ -769,8 +819,7 @@ sub add {
}
success:
assign_device_numbers($hd);
- $hd->{isDirty} = 1;
- push @{$hd->{needKernelReread} ||= []}, $part if !$hd->{needKernelReread} || ref($hd->{needKernelReread}) eq 'ARRAY'
+ will_tell_kernel($hd, add => $part);
}
# search for the next partition
@@ -813,7 +862,7 @@ sub load {
@$hd{@fields2save} = @$h;
delete @$_{qw(isMounted isFormatted notFormatted toFormat toFormatUnsure)} foreach get_normal_parts($hd);
- $hd->{isDirty} = $hd->{needKernelReread} = 1;
+ will_tell_kernel($hd, 'force_reboot'); #- just like undo, do not force write_partitions so that user can see the new partition table but can still discard it
}
sub save {
diff --git a/perl-install/partition_table/raw.pm b/perl-install/partition_table/raw.pm
index 5713e69d6..d8bcf8954 100644
--- a/perl-install/partition_table/raw.pm
+++ b/perl-install/partition_table/raw.pm
@@ -113,18 +113,6 @@ sub openit {
my $F; sysopen($F, $hd->{file}, $o_mode || 0) && $F;
}
-# cause kernel to re-read partition table
-sub kernel_read($) {
- my ($hd) = @_;
- common::sync();
- my $F = openit($hd) or return 0;
- common::sync(); sleep(1);
- $hd->{rebootNeeded} = !ioctl($F, c::BLKRRPART(), 0);
- common::sync();
- close $F;
- common::sync(); sleep(1);
-}
-
sub raw_removed {
my ($_hd, $_raw) = @_;
}
@@ -157,10 +145,10 @@ sub zero_MBR {
}
sub zero_MBR_and_dirty {
- my ($hd) = @_;
+ my ($hd) = @_;
+ my @parts = (partition_table::get_normal_parts($hd), if_($hd->{primary}{extended}, $hd->{primary}{extended}));
+ partition_table::will_tell_kernel($hd, del => $_) foreach @parts;
zero_MBR($hd);
- $hd->{isDirty} = $hd->{needKernelReread} = 1;
-
}
#- ugly stuff needed mainly for Western Digital IDE drives