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

Commitcd4868a

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 parenta00fd06 commitcd4868a

File tree

18 files changed

+191
-0
lines changed

18 files changed

+191
-0
lines changed

‎contrib/pageinspect/brinfuncs.c‎

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

5959
page=get_page_from_raw(raw_page);
6060

61+
if (PageIsNew(page))
62+
PG_RETURN_NULL();
63+
6164
/* verify the special space has the expected size */
6265
if (PageGetSpecialSize(page)!=MAXALIGN(sizeof(BrinSpecialSpace)))
6366
ereport(ERROR,
@@ -95,6 +98,9 @@ verify_brin_page(bytea *raw_page, uint16 type, const char *strtype)
9598
{
9699
Pagepage=get_page_from_raw(raw_page);
97100

101+
if (PageIsNew(page))
102+
returnpage;
103+
98104
/* verify the special space has the expected size */
99105
if (PageGetSpecialSize(page)!=MAXALIGN(sizeof(BrinSpecialSpace)))
100106
ereport(ERROR,
@@ -156,6 +162,13 @@ brin_page_items(PG_FUNCTION_ARGS)
156162
/* minimally verify the page we got */
157163
page=verify_brin_page(raw_page,BRIN_PAGETYPE_REGULAR,"regular");
158164

165+
if (PageIsNew(page))
166+
{
167+
brin_free_desc(bdesc);
168+
index_close(indexRel,AccessShareLock);
169+
PG_RETURN_NULL();
170+
}
171+
159172
/*
160173
* Initialize output functions for all indexed datatypes; simplifies
161174
* calling them later.
@@ -331,6 +344,9 @@ brin_metapage_info(PG_FUNCTION_ARGS)
331344

332345
page=verify_brin_page(raw_page,BRIN_PAGETYPE_META,"metapage");
333346

347+
if (PageIsNew(page))
348+
PG_RETURN_NULL();
349+
334350
/* Build a tuple descriptor for our result type */
335351
if (get_call_result_type(fcinfo,NULL,&tupdesc)!=TYPEFUNC_COMPOSITE)
336352
elog(ERROR,"return type must be a row type");
@@ -382,6 +398,12 @@ brin_revmap_data(PG_FUNCTION_ARGS)
382398
/* minimally verify the page we got */
383399
page=verify_brin_page(raw_page,BRIN_PAGETYPE_REVMAP,"revmap");
384400

401+
if (PageIsNew(page))
402+
{
403+
MemoryContextSwitchTo(mctx);
404+
PG_RETURN_NULL();
405+
}
406+
385407
state=palloc(sizeof(*state));
386408
state->tids= ((RevmapContents*)PageGetContents(page))->rm_tids;
387409
state->idx=0;

‎contrib/pageinspect/btreefuncs.c‎

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

612612
uargs->page=get_page_from_raw(raw_page);
613613

614+
if (PageIsNew(uargs->page))
615+
{
616+
MemoryContextSwitchTo(mctx);
617+
PG_RETURN_NULL();
618+
}
619+
614620
uargs->offset=FirstOffsetNumber;
615621

616622
/* 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
@@ -99,4 +99,10 @@ ERROR: input page is not a valid btree page
9999
SELECT bt_page_items(get_raw_page('test1_a_brin', 0));
100100
ERROR: input page is not a valid btree page
101101
\set VERBOSITY default
102+
-- Tests with all-zero pages.
103+
SHOW block_size \gset
104+
SELECT bt_page_items(decode(repeat('00', :block_size), 'hex'));
105+
-[ RECORD 1 ]-+-
106+
bt_page_items |
107+
102108
DROP TABLE test1;

‎contrib/pageinspect/expected/gin.out‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,4 +54,18 @@ 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+
5771
DROP TABLE test1;

‎contrib/pageinspect/expected/gist.out‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,4 +87,22 @@ ERROR: input page is not a valid GiST page
8787
SELECT gist_page_items_bytea(get_raw_page('test_gist_btree', 0));
8888
ERROR: input page is not a valid GiST page
8989
\set VERBOSITY default
90+
-- Tests with all-zero pages.
91+
SHOW block_size \gset
92+
SELECT gist_page_items_bytea(decode(repeat('00', :block_size), 'hex'));
93+
gist_page_items_bytea
94+
-----------------------
95+
(0 rows)
96+
97+
SELECT gist_page_items(decode(repeat('00', :block_size), 'hex'), 'test_gist_idx'::regclass);
98+
gist_page_items
99+
-----------------
100+
(0 rows)
101+
102+
SELECT gist_page_opaque_info(decode(repeat('00', :block_size), 'hex'));
103+
gist_page_opaque_info
104+
-----------------------
105+
106+
(1 row)
107+
90108
DROP TABLE test_gist;

‎contrib/pageinspect/expected/hash.out‎

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

‎contrib/pageinspect/expected/page.out‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,3 +218,23 @@ ERROR: invalid page size
218218
SELECT page_header('ccc'::bytea);
219219
ERROR: invalid page size
220220
\set VERBOSITY default
221+
-- Tests with all-zero pages.
222+
SHOW block_size \gset
223+
SELECT fsm_page_contents(decode(repeat('00', :block_size), 'hex'));
224+
fsm_page_contents
225+
-------------------
226+
227+
(1 row)
228+
229+
SELECT page_header(decode(repeat('00', :block_size), 'hex'));
230+
page_header
231+
-----------------------
232+
(0/0,0,0,0,0,0,0,0,0)
233+
(1 row)
234+
235+
SELECT page_checksum(decode(repeat('00', :block_size), 'hex'), 1);
236+
page_checksum
237+
---------------
238+
239+
(1 row)
240+

‎contrib/pageinspect/fsmfuncs.c‎

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

4848
page=get_page_from_raw(raw_page);
49+
50+
if (PageIsNew(page))
51+
PG_RETURN_NULL();
52+
4953
fsmpage= (FSMPage)PageGetContents(page);
5054

5155
initStringInfo(&sinfo);

‎contrib/pageinspect/ginfuncs.c‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ gin_metapage_info(PG_FUNCTION_ARGS)
4949

5050
page=get_page_from_raw(raw_page);
5151

52+
if (PageIsNew(page))
53+
PG_RETURN_NULL();
54+
5255
if (PageGetSpecialSize(page)!=MAXALIGN(sizeof(GinPageOpaqueData)))
5356
ereport(ERROR,
5457
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
@@ -58,6 +61,7 @@ gin_metapage_info(PG_FUNCTION_ARGS)
5861
(int)PageGetSpecialSize(page))));
5962

6063
opaq=GinPageGetOpaque(page);
64+
6165
if (opaq->flags!=GIN_META)
6266
ereport(ERROR,
6367
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
@@ -115,6 +119,9 @@ gin_page_opaque_info(PG_FUNCTION_ARGS)
115119

116120
page=get_page_from_raw(raw_page);
117121

122+
if (PageIsNew(page))
123+
PG_RETURN_NULL();
124+
118125
if (PageGetSpecialSize(page)!=MAXALIGN(sizeof(GinPageOpaqueData)))
119126
ereport(ERROR,
120127
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
@@ -200,6 +207,12 @@ gin_leafpage_items(PG_FUNCTION_ARGS)
200207

201208
page=get_page_from_raw(raw_page);
202209

210+
if (PageIsNew(page))
211+
{
212+
MemoryContextSwitchTo(mctx);
213+
PG_RETURN_NULL();
214+
}
215+
203216
if (PageGetSpecialSize(page)!=MAXALIGN(sizeof(GinPageOpaqueData)))
204217
ereport(ERROR,
205218
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp