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

Commit5378d55

Browse files
committed
pageinspect: Fix handling of all-zero pages
Getting from get_raw_page() an all-zero page is considered as a validcase by the buffer manager and it can happen for example when finding acorrupted page with zero_damaged_pages enabled (using zero_damaged_pagesto look at corrupted pages happens), or after a crash when a relationfile is extended before any WAL for its new data is generated (before avacuum or autovacuum job comes in to do some cleanup).However, all the functions of pageinspect, as of the index AMs (excepthash that has its own idea of new pages), heap, the FSM or the pageheader have never worked with all-zero pages, causing various crasheswhen going through the page internals.This commit changes all the pageinspect functions to be compliant withall-zero pages, where the choice is made to return NULL or no rows forSRFs when finding a new page. get_raw_page() still works the same way,returning a batch of zeros in the bytea of the page retrieved. A harderror could be used but NULL, while more invasive, is useful whenscanning relation files in full to get a batch of results for a singlerelation in one query. Tests are added for all the code pathsimpacted.Reported-by: Daria LepikhovaAuthor: Michael PaquierDiscussion:https://postgr.es/m/561e187b-3549-c8d5-03f5-525c14e65bd0@postgrespro.ruBackpatch-through: 10
1 parente0ed20d commit5378d55

File tree

15 files changed

+154
-0
lines changed

15 files changed

+154
-0
lines changed

‎contrib/pageinspect/brinfuncs.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ brin_page_type(PG_FUNCTION_ARGS)
6060

6161
page=get_page_from_raw(raw_page);
6262

63+
if (PageIsNew(page))
64+
PG_RETURN_NULL();
65+
6366
/* verify the special space has the expected size */
6467
if (PageGetSpecialSize(page)!=MAXALIGN(sizeof(BrinSpecialSpace)))
6568
ereport(ERROR,
@@ -97,6 +100,9 @@ verify_brin_page(bytea *raw_page, uint16 type, const char *strtype)
97100
{
98101
Pagepage=get_page_from_raw(raw_page);
99102

103+
if (PageIsNew(page))
104+
returnpage;
105+
100106
/* verify the special space has the expected size */
101107
if (PageGetSpecialSize(page)!=MAXALIGN(sizeof(BrinSpecialSpace)))
102108
ereport(ERROR,
@@ -184,6 +190,13 @@ brin_page_items(PG_FUNCTION_ARGS)
184190
/* minimally verify the page we got */
185191
page=verify_brin_page(raw_page,BRIN_PAGETYPE_REGULAR,"regular");
186192

193+
if (PageIsNew(page))
194+
{
195+
brin_free_desc(bdesc);
196+
index_close(indexRel,AccessShareLock);
197+
PG_RETURN_NULL();
198+
}
199+
187200
/*
188201
* Initialize output functions for all indexed datatypes; simplifies
189202
* calling them later.
@@ -350,6 +363,9 @@ brin_metapage_info(PG_FUNCTION_ARGS)
350363

351364
page=verify_brin_page(raw_page,BRIN_PAGETYPE_META,"metapage");
352365

366+
if (PageIsNew(page))
367+
PG_RETURN_NULL();
368+
353369
/* Build a tuple descriptor for our result type */
354370
if (get_call_result_type(fcinfo,NULL,&tupdesc)!=TYPEFUNC_COMPOSITE)
355371
elog(ERROR,"return type must be a row type");
@@ -401,6 +417,12 @@ brin_revmap_data(PG_FUNCTION_ARGS)
401417
/* minimally verify the page we got */
402418
page=verify_brin_page(raw_page,BRIN_PAGETYPE_REVMAP,"revmap");
403419

420+
if (PageIsNew(page))
421+
{
422+
MemoryContextSwitchTo(mctx);
423+
PG_RETURN_NULL();
424+
}
425+
404426
state=palloc(sizeof(*state));
405427
state->tids= ((RevmapContents*)PageGetContents(page))->rm_tids;
406428
state->idx=0;

‎contrib/pageinspect/btreefuncs.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -448,6 +448,12 @@ bt_page_items_bytea(PG_FUNCTION_ARGS)
448448

449449
uargs->page=get_page_from_raw(raw_page);
450450

451+
if (PageIsNew(uargs->page))
452+
{
453+
MemoryContextSwitchTo(mctx);
454+
PG_RETURN_NULL();
455+
}
456+
451457
uargs->offset=FirstOffsetNumber;
452458

453459
/* verify the special space has the expected size */

‎contrib/pageinspect/expected/brin.out

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,4 +62,29 @@ ERROR: input page is not a valid BRIN page
6262
SELECT * FROM brin_revmap_data(get_raw_page('test1', 0));
6363
ERROR: input page is not a valid BRIN page
6464
\set VERBOSITY default
65+
-- Tests with all-zero pages.
66+
SHOW block_size \gset
67+
SELECT brin_page_type(decode(repeat('00', :block_size), 'hex'));
68+
brin_page_type
69+
----------------
70+
71+
(1 row)
72+
73+
SELECT brin_page_items(decode(repeat('00', :block_size), 'hex'), 'test1_a_idx');
74+
brin_page_items
75+
-----------------
76+
(0 rows)
77+
78+
SELECT brin_metapage_info(decode(repeat('00', :block_size), 'hex'));
79+
brin_metapage_info
80+
--------------------
81+
82+
(1 row)
83+
84+
SELECT brin_revmap_data(decode(repeat('00', :block_size), 'hex'));
85+
brin_revmap_data
86+
------------------
87+
88+
(1 row)
89+
6590
DROP TABLE test1;

‎contrib/pageinspect/expected/btree.out

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,4 +86,10 @@ ERROR: input page is not a valid btree page
8686
SELECT bt_page_items(get_raw_page('test1_a_brin', 0));
8787
ERROR: input page is not a valid btree page
8888
\set VERBOSITY default
89+
-- Tests with all-zero pages.
90+
SHOW block_size \gset
91+
SELECT bt_page_items(decode(repeat('00', :block_size), 'hex'));
92+
-[ RECORD 1 ]-+-
93+
bt_page_items |
94+
8995
DROP TABLE test1;

‎contrib/pageinspect/expected/gin.out

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,17 @@ ERROR: input page is not a valid GIN data leaf page
5454
SELECT * FROM gin_leafpage_items(get_raw_page('test1', 0));
5555
ERROR: input page is not a valid GIN data leaf page
5656
\set VERBOSITY default
57+
-- Tests with all-zero pages.
58+
SHOW block_size \gset
59+
SELECT gin_leafpage_items(decode(repeat('00', :block_size), 'hex'));
60+
-[ RECORD 1 ]------+-
61+
gin_leafpage_items |
62+
63+
SELECT gin_metapage_info(decode(repeat('00', :block_size), 'hex'));
64+
-[ RECORD 1 ]-----+-
65+
gin_metapage_info |
66+
67+
SELECT gin_page_opaque_info(decode(repeat('00', :block_size), 'hex'));
68+
-[ RECORD 1 ]--------+-
69+
gin_page_opaque_info |
70+

‎contrib/pageinspect/expected/hash.out

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,4 +186,16 @@ ERROR: input page is not a valid hash page
186186
SELECT hash_page_type(get_raw_page('test_hash', 0));
187187
ERROR: input page is not a valid hash page
188188
\set VERBOSITY default
189+
-- Tests with all-zero pages.
190+
SHOW block_size \gset
191+
SELECT hash_metapage_info(decode(repeat('00', :block_size), 'hex'));
192+
ERROR: page is not a hash meta page
193+
SELECT hash_page_items(decode(repeat('00', :block_size), 'hex'));
194+
ERROR: page is not a hash bucket or overflow page
195+
SELECT hash_page_stats(decode(repeat('00', :block_size), 'hex'));
196+
ERROR: page is not a hash bucket or overflow page
197+
SELECT hash_page_type(decode(repeat('00', :block_size), 'hex'));
198+
-[ RECORD 1 ]--+-------
199+
hash_page_type | unused
200+
189201
DROP TABLE test_hash;

‎contrib/pageinspect/expected/page.out

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,3 +124,23 @@ ERROR: invalid page size
124124
SELECT page_header('ccc'::bytea);
125125
ERROR: invalid page size
126126
\set VERBOSITY default
127+
-- Tests with all-zero pages.
128+
SHOW block_size \gset
129+
SELECT fsm_page_contents(decode(repeat('00', :block_size), 'hex'));
130+
fsm_page_contents
131+
-------------------
132+
133+
(1 row)
134+
135+
SELECT page_header(decode(repeat('00', :block_size), 'hex'));
136+
page_header
137+
-----------------------
138+
(0/0,0,0,0,0,0,0,0,0)
139+
(1 row)
140+
141+
SELECT page_checksum(decode(repeat('00', :block_size), 'hex'), 1);
142+
page_checksum
143+
---------------
144+
145+
(1 row)
146+

‎contrib/pageinspect/fsmfuncs.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@ fsm_page_contents(PG_FUNCTION_ARGS)
4747
(errmsg("must be superuser to use raw page functions"))));
4848

4949
page=get_page_from_raw(raw_page);
50+
51+
if (PageIsNew(page))
52+
PG_RETURN_NULL();
53+
5054
fsmpage= (FSMPage)PageGetContents(page);
5155

5256
initStringInfo(&sinfo);

‎contrib/pageinspect/ginfuncs.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ gin_metapage_info(PG_FUNCTION_ARGS)
5050

5151
page=get_page_from_raw(raw_page);
5252

53+
if (PageIsNew(page))
54+
PG_RETURN_NULL();
55+
5356
if (PageGetSpecialSize(page)!=MAXALIGN(sizeof(GinPageOpaqueData)))
5457
ereport(ERROR,
5558
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
@@ -116,6 +119,9 @@ gin_page_opaque_info(PG_FUNCTION_ARGS)
116119

117120
page=get_page_from_raw(raw_page);
118121

122+
if (PageIsNew(page))
123+
PG_RETURN_NULL();
124+
119125
if (PageGetSpecialSize(page)!=MAXALIGN(sizeof(GinPageOpaqueData)))
120126
ereport(ERROR,
121127
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
@@ -200,6 +206,12 @@ gin_leafpage_items(PG_FUNCTION_ARGS)
200206

201207
page=get_page_from_raw(raw_page);
202208

209+
if (PageIsNew(page))
210+
{
211+
MemoryContextSwitchTo(mctx);
212+
PG_RETURN_NULL();
213+
}
214+
203215
if (PageGetSpecialSize(page)!=MAXALIGN(sizeof(GinPageOpaqueData)))
204216
ereport(ERROR,
205217
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),

‎contrib/pageinspect/rawpage.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,5 +297,8 @@ page_checksum(PG_FUNCTION_ARGS)
297297

298298
page=get_page_from_raw(raw_page);
299299

300+
if (PageIsNew(page))
301+
PG_RETURN_NULL();
302+
300303
PG_RETURN_INT16(pg_checksum_page((char*)page,blkno));
301304
}

‎contrib/pageinspect/sql/brin.sql

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,11 @@ SELECT * FROM brin_metapage_info(get_raw_page('test1', 0));
2727
SELECT*FROM brin_revmap_data(get_raw_page('test1',0));
2828
\set VERBOSITY default
2929

30+
-- Tests with all-zero pages.
31+
SHOW block_size \gset
32+
SELECT brin_page_type(decode(repeat('00', :block_size),'hex'));
33+
SELECT brin_page_items(decode(repeat('00', :block_size),'hex'),'test1_a_idx');
34+
SELECT brin_metapage_info(decode(repeat('00', :block_size),'hex'));
35+
SELECT brin_revmap_data(decode(repeat('00', :block_size),'hex'));
36+
3037
DROPTABLE test1;

‎contrib/pageinspect/sql/btree.sql

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,8 @@ SELECT bt_page_items(get_raw_page('test1', 0));
4141
SELECT bt_page_items(get_raw_page('test1_a_brin',0));
4242
\set VERBOSITY default
4343

44+
-- Tests with all-zero pages.
45+
SHOW block_size \gset
46+
SELECT bt_page_items(decode(repeat('00', :block_size),'hex'));
47+
4448
DROPTABLE test1;

‎contrib/pageinspect/sql/gin.sql

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,9 @@ SELECT * FROM gin_metapage_info(get_raw_page('test1', 0));
3131
SELECT*FROM gin_page_opaque_info(get_raw_page('test1',0));
3232
SELECT*FROM gin_leafpage_items(get_raw_page('test1',0));
3333
\set VERBOSITY default
34+
35+
-- Tests with all-zero pages.
36+
SHOW block_size \gset
37+
SELECT gin_leafpage_items(decode(repeat('00', :block_size),'hex'));
38+
SELECT gin_metapage_info(decode(repeat('00', :block_size),'hex'));
39+
SELECT gin_page_opaque_info(decode(repeat('00', :block_size),'hex'));

‎contrib/pageinspect/sql/hash.sql

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,4 +96,11 @@ SELECT hash_page_stats(get_raw_page('test_hash', 0));
9696
SELECT hash_page_type(get_raw_page('test_hash',0));
9797
\set VERBOSITY default
9898

99+
-- Tests with all-zero pages.
100+
SHOW block_size \gset
101+
SELECT hash_metapage_info(decode(repeat('00', :block_size),'hex'));
102+
SELECT hash_page_items(decode(repeat('00', :block_size),'hex'));
103+
SELECT hash_page_stats(decode(repeat('00', :block_size),'hex'));
104+
SELECT hash_page_type(decode(repeat('00', :block_size),'hex'));
105+
99106
DROPTABLE test_hash;

‎contrib/pageinspect/sql/page.sql

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,3 +61,9 @@ SELECT fsm_page_contents('aaa'::bytea);
6161
SELECT page_checksum('bbb'::bytea,0);
6262
SELECT page_header('ccc'::bytea);
6363
\set VERBOSITY default
64+
65+
-- Tests with all-zero pages.
66+
SHOW block_size \gset
67+
SELECT fsm_page_contents(decode(repeat('00', :block_size),'hex'));
68+
SELECT page_header(decode(repeat('00', :block_size),'hex'));
69+
SELECT page_checksum(decode(repeat('00', :block_size),'hex'),1);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp