Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit579cef5

Browse files
committed
Harden TAP tests that intentionally corrupt page checksums.
The previous method for doing that was to write zeroes into apredetermined set of page locations. However, there's a roughly1-in-64K chance that the existing checksum will match by chance,and yesterday several buildfarm animals started to reproduciblysee that, resulting in test failures because no checksum mismatchwas reported.Since the checksum includes the page LSN, test success depends onthe length of the installation's WAL history, which is affected by(at least) the initial catalog contents, the set of locales installedon the system, and the length of the pathname of the test directory.Sooner or later we were going to hit a chance match, and today isthat day.Harden these tests by specifically inverting the checksum field andleaving all else alone, thereby guaranteeing that the checksum isincorrect.In passing, fix places that were using seek() to set up for syswrite(),a combination that the Perl docs very explicitly warn against. We'veprobably escaped problems because no regular buffered I/O is done onthese filehandles; but if it ever breaks, we wouldn't deserve or getmuch sympathy.Although we've only seen problems in HEAD, now that we recognize theenvironmental dependencies it seems like it might be just a matterof time until someone manages to hit this in back-branch testing.Hence, back-patch to v11 where we started doing this kind of test.Discussion:https://postgr.es/m/3192026.1648185780@sss.pgh.pa.us
1 parentffd2851 commit579cef5

File tree

6 files changed

+52
-42
lines changed

6 files changed

+52
-42
lines changed

‎contrib/amcheck/t/001_verify_heapam.pl

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
use PostgresNode;
88
use TestLib;
99

10-
use Fcntlqw(:seek);
1110
use Test::Moretests=> 80;
1211

1312
my ($node,$result);
@@ -127,8 +126,8 @@ sub corrupt_first_page
127126
# Corrupt some line pointers. The values are chosen to hit the
128127
# various line-pointer-corruption checks in verify_heapam.c
129128
# on both little-endian and big-endian architectures.
130-
seek($fh, 32,SEEK_SET)
131-
or BAIL_OUT("seek failed:$!");
129+
sysseek($fh, 32,0)
130+
or BAIL_OUT("sysseek failed:$!");
132131
syswrite(
133132
$fh,
134133
pack("L*",

‎src/bin/pg_amcheck/t/003_check.pl

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
use PostgresNode;
88
use TestLib;
99

10-
use Fcntlqw(:seek);
1110
use Test::Moretests=> 63;
1211

1312
my ($node,$port,%corrupt_page,%remove_relation);
@@ -90,8 +89,8 @@ sub corrupt_first_page
9089
# Corrupt some line pointers. The values are chosen to hit the
9190
# various line-pointer-corruption checks in verify_heapam.c
9291
# on both little-endian and big-endian architectures.
93-
seek($fh, 32,SEEK_SET)
94-
or BAIL_OUT("seek failed:$!");
92+
sysseek($fh, 32,0)
93+
or BAIL_OUT("sysseek failed:$!");
9594
syswrite(
9695
$fh,
9796
pack("L*",

‎src/bin/pg_amcheck/t/004_verify_heapam.pl

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
use PostgresNode;
88
use TestLib;
99

10-
use Fcntlqw(:seek);
1110
use Test::More;
1211

1312
# This regression test demonstrates that the pg_amcheck binary correctly
@@ -99,8 +98,8 @@ sub read_tuple
9998
{
10099
my ($fh,$offset) =@_;
101100
my ($buffer,%tup);
102-
seek($fh,$offset,SEEK_SET)
103-
or BAIL_OUT("seek failed:$!");
101+
sysseek($fh,$offset,0)
102+
or BAIL_OUT("sysseek failed:$!");
104103
defined(sysread($fh,$buffer, HEAPTUPLE_PACK_LENGTH))
105104
or BAIL_OUT("sysread failed:$!");
106105

@@ -165,8 +164,8 @@ sub write_tuple
165164
$tup->{c_va_header},$tup->{c_va_vartag},
166165
$tup->{c_va_rawsize},$tup->{c_va_extinfo},
167166
$tup->{c_va_valueid},$tup->{c_va_toastrelid});
168-
seek($fh,$offset,SEEK_SET)
169-
or BAIL_OUT("seek failed:$!");
167+
sysseek($fh,$offset,0)
168+
or BAIL_OUT("sysseek failed:$!");
170169
defined(syswrite($fh,$buffer, HEAPTUPLE_PACK_LENGTH))
171170
or BAIL_OUT("syswrite failed:$!");
172171
return;

‎src/bin/pg_basebackup/t/010_pg_basebackup.pl

Lines changed: 11 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
use Config;
88
use File::Basenameqw(basename dirname);
99
use File::Pathqw(rmtree);
10-
use Fcntlqw(:seek);
1110
use PostgresNode;
1211
use TestLib;
1312
use Test::Moretests=> 110;
@@ -40,7 +39,7 @@
4039
}
4140

4241
$node->set_replication_conf();
43-
system_or_bail'pg_ctl','-D',$pgdata,'reload';
42+
$node->reload;
4443

4544
$node->command_fails(
4645
['pg_basebackup','-D',"$tempdir/backup" ],
@@ -555,17 +554,13 @@
555554
q{CREATE TABLE corrupt2 AS SELECT b FROM generate_series(1,2) AS b; ALTER TABLE corrupt2 SET (autovacuum_enabled=false); SELECT pg_relation_filepath('corrupt2')}
556555
);
557556

558-
# set page header and block sizes
559-
my$pageheader_size = 24;
557+
# get block size for corruption steps
560558
my$block_size =$node->safe_psql('postgres','SHOW block_size;');
561559

562560
# induce corruption
563-
system_or_bail'pg_ctl','-D',$pgdata,'stop';
564-
open$file,'+<',"$pgdata/$file_corrupt1";
565-
seek($file,$pageheader_size, SEEK_SET);
566-
syswrite($file,"\0\0\0\0\0\0\0\0\0");
567-
close$file;
568-
system_or_bail'pg_ctl','-D',$pgdata,'start';
561+
$node->stop;
562+
$node->corrupt_page_checksum($file_corrupt1, 0);
563+
$node->start;
569564

570565
$node->command_checks_all(
571566
['pg_basebackup','-D',"$tempdir/backup_corrupt" ],
@@ -576,16 +571,12 @@
576571
rmtree("$tempdir/backup_corrupt");
577572

578573
# induce further corruption in 5 more blocks
579-
system_or_bail'pg_ctl','-D',$pgdata,'stop';
580-
open$file,'+<',"$pgdata/$file_corrupt1";
574+
$node->stop;
581575
formy$i (1 .. 5)
582576
{
583-
my$offset =$pageheader_size +$i *$block_size;
584-
seek($file,$offset, SEEK_SET);
585-
syswrite($file,"\0\0\0\0\0\0\0\0\0");
577+
$node->corrupt_page_checksum($file_corrupt1,$i *$block_size);
586578
}
587-
close$file;
588-
system_or_bail'pg_ctl','-D',$pgdata,'start';
579+
$node->start;
589580

590581
$node->command_checks_all(
591582
['pg_basebackup','-D',"$tempdir/backup_corrupt2" ],
@@ -596,12 +587,9 @@
596587
rmtree("$tempdir/backup_corrupt2");
597588

598589
# induce corruption in a second file
599-
system_or_bail'pg_ctl','-D',$pgdata,'stop';
600-
open$file,'+<',"$pgdata/$file_corrupt2";
601-
seek($file,$pageheader_size, SEEK_SET);
602-
syswrite($file,"\0\0\0\0\0\0\0\0\0");
603-
close$file;
604-
system_or_bail'pg_ctl','-D',$pgdata,'start';
590+
$node->stop;
591+
$node->corrupt_page_checksum($file_corrupt2, 0);
592+
$node->start;
605593

606594
$node->command_checks_all(
607595
['pg_basebackup','-D',"$tempdir/backup_corrupt3" ],

‎src/bin/pg_checksums/t/002_actions.pl

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
use PostgresNode;
1010
use TestLib;
1111

12-
use Fcntlqw(:seek);
1312
use Test::Moretests=> 63;
1413

1514

@@ -24,6 +23,7 @@ sub check_relation_corruption
2423
my$tablespace =shift;
2524
my$pgdata =$node->data_dir;
2625

26+
# Create table and discover its filesystem location.
2727
$node->safe_psql(
2828
'postgres',
2929
"CREATE TABLE$table AS SELECT a FROM generate_series(1,10000) AS a;
@@ -37,9 +37,6 @@ sub check_relation_corruption
3737
my$relfilenode_corrupted =$node->safe_psql('postgres',
3838
"SELECT relfilenode FROM pg_class WHERE relname = '$table';");
3939

40-
# Set page header and block size
41-
my$pageheader_size = 24;
42-
my$block_size =$node->safe_psql('postgres','SHOW block_size;');
4340
$node->stop;
4441

4542
# Checksums are correct for single relfilenode as the table is not
@@ -54,10 +51,7 @@ sub check_relation_corruption
5451
);
5552

5653
# Time to create some corruption
57-
openmy$file,'+<',"$pgdata/$file_corrupted";
58-
seek($file,$pageheader_size, SEEK_SET);
59-
syswrite($file,"\0\0\0\0\0\0\0\0\0");
60-
close$file;
54+
$node->corrupt_page_checksum($file_corrupted, 0);
6155

6256
# Checksum checks on single relfilenode fail
6357
$node->command_checks_all(

‎src/test/perl/PostgresNode.pm

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2726,6 +2726,37 @@ sub pg_recvlogical_upto
27262726

27272727
=pod
27282728
2729+
=item$node->corrupt_page_checksum(self, file, page_offset)
2730+
2731+
Intentionally corrupt the checksum field of one page in a file.
2732+
The server must be stopped for this to work reliably.
2733+
2734+
The file name should be specified relative to the cluster datadir.
2735+
page_offset had better be a multiple of the cluster's block size.
2736+
2737+
=cut
2738+
2739+
subcorrupt_page_checksum
2740+
{
2741+
my ($self,$file,$page_offset) =@_;
2742+
my$pgdata =$self->data_dir;
2743+
my$pageheader;
2744+
2745+
openmy$fh,'+<',"$pgdata/$file"ordie"open($file) failed:$!";
2746+
binmode$fh;
2747+
sysseek($fh,$page_offset, 0)ordie"sysseek failed:$!";
2748+
sysread($fh,$pageheader, 24)ordie"sysread failed:$!";
2749+
# This inverts the pd_checksum field (only); see struct PageHeaderData
2750+
$pageheader ^="\0\0\0\0\0\0\0\0\xff\xff";
2751+
sysseek($fh,$page_offset, 0)ordie"sysseek failed:$!";
2752+
syswrite($fh,$pageheader)ordie"syswrite failed:$!";
2753+
close$fh;
2754+
2755+
return;
2756+
}
2757+
2758+
=pod
2759+
27292760
=back
27302761
27312762
=cut

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp