Mageia Bugzilla – Attachment 8880 Details for
Bug 20074
Partitions with Type: Empty corrupt the partition table
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
Log In
[x]
|
New Account
|
Forgot Password
Patch to prevent kernel rescanning part way though writing the partition table
0001-Ensure-the-kernel-doesn-t-rescan-a-partially-written.patch (text/plain), 6.33 KB, created by
Martin Whitaker
on 2017-01-22 01:55:04 CET
(
hide
)
Description:
Patch to prevent kernel rescanning part way though writing the partition table
Filename:
MIME Type:
Creator:
Martin Whitaker
Created:
2017-01-22 01:55:04 CET
Size:
6.33 KB
patch
obsolete
>From 12dc6ddbf274551bcbfc114bb83bba8ecd0d17b2 Mon Sep 17 00:00:00 2001 >From: Martin Whitaker <mageia@martin-whitaker.me.uk> >Date: Sat, 21 Jan 2017 19:38:55 +0000 >Subject: [PATCH 1/4] Ensure the kernel doesn't rescan a partially written > partition table (mga#20074). > >When no partitions on a DOS-partitioned disk are mounted, the kernel >automatically rescans the partition table when the file handle to the >raw device is released. Currently the code opens and closes the raw >device when writing the primary partition table and when writing each >extended partition table segment. As the extended partition table >segments form a linked list, this allows the kernel to get in and >rescan the table when the list is not in a coherent state. This patch >changes the code to open the raw device before writing the primary >partition table and to close it only after writing the last extended >partition table segment. > >The behaviour for other partition table types is unchanged. > >diff --git a/perl-install/partition_table.pm b/perl-install/partition_table.pm >index 5cd0ec2..8a85e7d 100644 >--- a/perl-install/partition_table.pm >+++ b/perl-install/partition_table.pm >@@ -428,16 +428,17 @@ sub write { > #- it will never be writed back on partition table. > verifyParts($hd); > >- $hd->write(0, $hd->{primary}{raw}, $hd->{primary}{info}) or die "writing of partition table failed"; >- >+ my $handle = $hd->start_write(); >+ $hd->write($handle, 0, $hd->{primary}{raw}, $hd->{primary}{info}) or die "writing of partition table failed"; > #- should be fixed but a extended exist with no real extended partition, that blanks mbr! > foreach (@{$hd->{extended}}) { > # in case of extended partitions, the start sector must be local to the partition > $_->{normal}{local_start} = $_->{normal}{start} - $_->{start}; > $_->{extended} and $_->{extended}{local_start} = $_->{extended}{start} - $hd->{primary}{extended}{start}; > >- $hd->write($_->{start}, $_->{raw}) or die "writing of partition table failed"; >+ $hd->write($handle, $_->{start}, $_->{raw}) or die "writing of partition table failed"; > } >+ $hd->end_write($handle); > $hd->{isDirty} = 0; > > if (my $tell_kernel = delete $hd->{will_tell_kernel}) { >diff --git a/perl-install/partition_table/bsd.pm b/perl-install/partition_table/bsd.pm >index b27df6d..678de01 100644 >--- a/perl-install/partition_table/bsd.pm >+++ b/perl-install/partition_table/bsd.pm >@@ -87,10 +87,15 @@ sub read_one { > [ @pt ], \%info; > } > >+sub start_write { >+ my ($_hd) = @_; >+ 1; >+} >+ > # write the partition table (and extended ones) > # for each entry, it uses fields: start, size, pt_type, active > sub write($$$;$) { >- my ($hd, $sector, $pt, $info) = @_; >+ my ($hd, $_handle, $sector, $pt, $info) = @_; > > #- handle testing for writing partition table on file only! > my $F; >@@ -116,6 +121,11 @@ sub write($$$;$) { > 1; > } > >+sub end_write { >+ my ($_hd, $_handle) = @_; >+ 1; >+} >+ > sub info { > my ($hd) = @_; > my $dtype_scsi = 4; #- taken from fdisk, removed unused one, >diff --git a/perl-install/partition_table/dos.pm b/perl-install/partition_table/dos.pm >index 004c8a1..c56cdab 100644 >--- a/perl-install/partition_table/dos.pm >+++ b/perl-install/partition_table/dos.pm >@@ -236,10 +236,9 @@ sub read_one { > [ @pt ]; > } > >-# write the partition table (and extended ones) >-# for each entry, it uses fields: start, size, pt_type, active >-sub write { >- my ($hd, $sector, $pt) = @_; >+# prepare to write the partition table (and extended ones) >+sub start_write { >+ my ($hd) = @_; > > log::l("partition::dos::write $hd->{device}"); > >@@ -250,6 +249,16 @@ sub write { > open $F, ">$file" or die "error opening test file $file"; > } else { > $F = partition_table::raw::openit($hd, 2) or die "error opening device $hd->{device} for writing"; >+ } >+ $F; >+} >+ >+# write the partition table (and extended ones) >+# for each entry, it uses fields: start, size, pt_type, active >+sub write { >+ my ($hd, $F, $sector, $pt) = @_; >+ >+ if (!$::testing) { > c::lseek_sector(fileno($F), $sector, $offset) or return 0; > } > >@@ -264,6 +273,11 @@ sub write { > 1; > } > >+sub end_write { >+ my ($hd, $F) = @_; >+ close $F; >+} >+ > sub empty_raw { { raw => [ ({}) x $nb_primary ] } } > > sub initialize { >diff --git a/perl-install/partition_table/gpt.pm b/perl-install/partition_table/gpt.pm >index 3ac6673..df591d5 100644 >--- a/perl-install/partition_table/gpt.pm >+++ b/perl-install/partition_table/gpt.pm >@@ -70,8 +70,13 @@ sub read_one { > \@pt; > } > >+sub start_write { >+ my ($_hd) = @_; >+ 1; >+} >+ > sub write { >- my ($hd, $_sector, $pt, $_info) = @_; >+ my ($hd, $_handle, $_sector, $pt, $_info) = @_; > > my $partitions_killed; > >@@ -116,6 +121,11 @@ sub write { > 1; > } > >+sub end_write { >+ my ($_hd, $_handle) = @_; >+ 1; >+} >+ > sub initialize { > my ($class, $hd) = @_; > # sync libparted view with diskdrake one in order to prevent overlapping errors when adding partitions: >diff --git a/perl-install/partition_table/mac.pm b/perl-install/partition_table/mac.pm >index 547704b..450c803 100644 >--- a/perl-install/partition_table/mac.pm >+++ b/perl-install/partition_table/mac.pm >@@ -192,8 +192,13 @@ sub read_one { > [ @pt ], \%info; > } > >+sub start_write { >+ my ($_hd) = @_; >+ 1; >+} >+ > sub write($$$;$) { >- my ($hd, $sector, $pt, $info) = @_; >+ my ($hd, $_handle, $sector, $pt, $info) = @_; > > #- handle testing for writing partition table on file only! > my $F; >@@ -339,6 +344,11 @@ sub write($$$;$) { > 1; > } > >+sub end_write { >+ my ($_hd, $_handle) = @_; >+ 1; >+} >+ > sub info { > my ($hd) = @_; > >diff --git a/perl-install/partition_table/sun.pm b/perl-install/partition_table/sun.pm >index e2fd747..e476d09 100644 >--- a/perl-install/partition_table/sun.pm >+++ b/perl-install/partition_table/sun.pm >@@ -116,10 +116,15 @@ sub read_one { > [ @pt ], \%info; > } > >+sub start_write { >+ my ($_hd) = @_; >+ 1; >+} >+ > # write the partition table (and extended ones) > # for each entry, it uses fields: start, size, pt_type, active > sub write($$$;$) { >- my ($hd, $sector, $pt, $info) = @_; >+ my ($hd, $_handle, $sector, $pt, $info) = @_; > # my ($csize, $wdsize) = (0, 0); > > #- handle testing for writing partition table on file only! >@@ -155,6 +160,11 @@ sub write($$$;$) { > 1; > } > >+sub end_write { >+ my ($_hd, $_handle) = @_; >+ 1; >+} >+ > sub info { > my ($hd) = @_; > >-- >2.10.2 >
From 12dc6ddbf274551bcbfc114bb83bba8ecd0d17b2 Mon Sep 17 00:00:00 2001 From: Martin Whitaker <mageia@martin-whitaker.me.uk> Date: Sat, 21 Jan 2017 19:38:55 +0000 Subject: [PATCH 1/4] Ensure the kernel doesn't rescan a partially written partition table (mga#20074). When no partitions on a DOS-partitioned disk are mounted, the kernel automatically rescans the partition table when the file handle to the raw device is released. Currently the code opens and closes the raw device when writing the primary partition table and when writing each extended partition table segment. As the extended partition table segments form a linked list, this allows the kernel to get in and rescan the table when the list is not in a coherent state. This patch changes the code to open the raw device before writing the primary partition table and to close it only after writing the last extended partition table segment. The behaviour for other partition table types is unchanged. diff --git a/perl-install/partition_table.pm b/perl-install/partition_table.pm index 5cd0ec2..8a85e7d 100644 --- a/perl-install/partition_table.pm +++ b/perl-install/partition_table.pm @@ -428,16 +428,17 @@ sub write { #- it will never be writed back on partition table. verifyParts($hd); - $hd->write(0, $hd->{primary}{raw}, $hd->{primary}{info}) or die "writing of partition table failed"; - + my $handle = $hd->start_write(); + $hd->write($handle, 0, $hd->{primary}{raw}, $hd->{primary}{info}) or die "writing of partition table failed"; #- should be fixed but a extended exist with no real extended partition, that blanks mbr! foreach (@{$hd->{extended}}) { # in case of extended partitions, the start sector must be local to the partition $_->{normal}{local_start} = $_->{normal}{start} - $_->{start}; $_->{extended} and $_->{extended}{local_start} = $_->{extended}{start} - $hd->{primary}{extended}{start}; - $hd->write($_->{start}, $_->{raw}) or die "writing of partition table failed"; + $hd->write($handle, $_->{start}, $_->{raw}) or die "writing of partition table failed"; } + $hd->end_write($handle); $hd->{isDirty} = 0; if (my $tell_kernel = delete $hd->{will_tell_kernel}) { diff --git a/perl-install/partition_table/bsd.pm b/perl-install/partition_table/bsd.pm index b27df6d..678de01 100644 --- a/perl-install/partition_table/bsd.pm +++ b/perl-install/partition_table/bsd.pm @@ -87,10 +87,15 @@ sub read_one { [ @pt ], \%info; } +sub start_write { + my ($_hd) = @_; + 1; +} + # write the partition table (and extended ones) # for each entry, it uses fields: start, size, pt_type, active sub write($$$;$) { - my ($hd, $sector, $pt, $info) = @_; + my ($hd, $_handle, $sector, $pt, $info) = @_; #- handle testing for writing partition table on file only! my $F; @@ -116,6 +121,11 @@ sub write($$$;$) { 1; } +sub end_write { + my ($_hd, $_handle) = @_; + 1; +} + sub info { my ($hd) = @_; my $dtype_scsi = 4; #- taken from fdisk, removed unused one, diff --git a/perl-install/partition_table/dos.pm b/perl-install/partition_table/dos.pm index 004c8a1..c56cdab 100644 --- a/perl-install/partition_table/dos.pm +++ b/perl-install/partition_table/dos.pm @@ -236,10 +236,9 @@ sub read_one { [ @pt ]; } -# write the partition table (and extended ones) -# for each entry, it uses fields: start, size, pt_type, active -sub write { - my ($hd, $sector, $pt) = @_; +# prepare to write the partition table (and extended ones) +sub start_write { + my ($hd) = @_; log::l("partition::dos::write $hd->{device}"); @@ -250,6 +249,16 @@ sub write { open $F, ">$file" or die "error opening test file $file"; } else { $F = partition_table::raw::openit($hd, 2) or die "error opening device $hd->{device} for writing"; + } + $F; +} + +# write the partition table (and extended ones) +# for each entry, it uses fields: start, size, pt_type, active +sub write { + my ($hd, $F, $sector, $pt) = @_; + + if (!$::testing) { c::lseek_sector(fileno($F), $sector, $offset) or return 0; } @@ -264,6 +273,11 @@ sub write { 1; } +sub end_write { + my ($hd, $F) = @_; + close $F; +} + sub empty_raw { { raw => [ ({}) x $nb_primary ] } } sub initialize { diff --git a/perl-install/partition_table/gpt.pm b/perl-install/partition_table/gpt.pm index 3ac6673..df591d5 100644 --- a/perl-install/partition_table/gpt.pm +++ b/perl-install/partition_table/gpt.pm @@ -70,8 +70,13 @@ sub read_one { \@pt; } +sub start_write { + my ($_hd) = @_; + 1; +} + sub write { - my ($hd, $_sector, $pt, $_info) = @_; + my ($hd, $_handle, $_sector, $pt, $_info) = @_; my $partitions_killed; @@ -116,6 +121,11 @@ sub write { 1; } +sub end_write { + my ($_hd, $_handle) = @_; + 1; +} + sub initialize { my ($class, $hd) = @_; # sync libparted view with diskdrake one in order to prevent overlapping errors when adding partitions: diff --git a/perl-install/partition_table/mac.pm b/perl-install/partition_table/mac.pm index 547704b..450c803 100644 --- a/perl-install/partition_table/mac.pm +++ b/perl-install/partition_table/mac.pm @@ -192,8 +192,13 @@ sub read_one { [ @pt ], \%info; } +sub start_write { + my ($_hd) = @_; + 1; +} + sub write($$$;$) { - my ($hd, $sector, $pt, $info) = @_; + my ($hd, $_handle, $sector, $pt, $info) = @_; #- handle testing for writing partition table on file only! my $F; @@ -339,6 +344,11 @@ sub write($$$;$) { 1; } +sub end_write { + my ($_hd, $_handle) = @_; + 1; +} + sub info { my ($hd) = @_; diff --git a/perl-install/partition_table/sun.pm b/perl-install/partition_table/sun.pm index e2fd747..e476d09 100644 --- a/perl-install/partition_table/sun.pm +++ b/perl-install/partition_table/sun.pm @@ -116,10 +116,15 @@ sub read_one { [ @pt ], \%info; } +sub start_write { + my ($_hd) = @_; + 1; +} + # write the partition table (and extended ones) # for each entry, it uses fields: start, size, pt_type, active sub write($$$;$) { - my ($hd, $sector, $pt, $info) = @_; + my ($hd, $_handle, $sector, $pt, $info) = @_; # my ($csize, $wdsize) = (0, 0); #- handle testing for writing partition table on file only! @@ -155,6 +160,11 @@ sub write($$$;$) { 1; } +sub end_write { + my ($_hd, $_handle) = @_; + 1; +} + sub info { my ($hd) = @_; -- 2.10.2
View Attachment As Raw
Actions:
View
Attachments on
bug 20074
: 8880 |
8881
|
8882
|
8883
|
8901
|
8906
|
8907
|
8908
|
8909
|
8926
|
8927
|
8972