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

Commit6236991

Browse files
committed
Add simple sanity checks on newly-read pages to GiST, too.
1 parent766dc45 commit6236991

File tree

5 files changed

+119
-46
lines changed

5 files changed

+119
-46
lines changed

‎src/backend/access/gist/gist.c

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/access/gist/gist.c,v 1.127 2005/10/18 01:06:22 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/access/gist/gist.c,v 1.128 2005/11/06 22:39:20 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -529,12 +529,12 @@ gistfindleaf(GISTInsertState *state, GISTSTATE *giststate)
529529
* ready to recheck path in a bad case... We remember, that page->lsn
530530
* should never be invalid.
531531
*/
532-
while (true)
532+
for (;;)
533533
{
534-
535534
if (XLogRecPtrIsInvalid(state->stack->lsn))
536535
state->stack->buffer=ReadBuffer(state->r,state->stack->blkno);
537536
LockBuffer(state->stack->buffer,GIST_SHARE);
537+
gistcheckpage(state->r,state->stack->buffer);
538538

539539
state->stack->page= (Page)BufferGetPage(state->stack->buffer);
540540
opaque=GistPageGetOpaque(state->stack->page);
@@ -555,7 +555,6 @@ gistfindleaf(GISTInsertState *state, GISTSTATE *giststate)
555555
continue;
556556
}
557557

558-
559558
if (!GistPageIsLeaf(state->stack->page))
560559
{
561560
/*
@@ -649,14 +648,18 @@ gistReadAndLockBuffer(Relation r, BlockNumber blkno)
649648
}
650649

651650
/*
652-
* Traverse the tree to find path from root page,
653-
* to prevent deadlocks, it should lock only one page simultaneously.
654-
* Function uses in recovery and usial mode, so should work with different
655-
* read functions (gistReadAndLockBuffer and XLogReadBuffer)
651+
* Traverse the tree to find path from root page.
652+
*
656653
* returns from the begining of closest parent;
654+
*
655+
* Function is used in both regular and recovery mode, so must work with
656+
* different read functions (gistReadAndLockBuffer and XLogReadBuffer)
657+
*
658+
* To prevent deadlocks, this should lock only one page simultaneously.
657659
*/
658660
GISTInsertStack*
659-
gistFindPath(Relationr,BlockNumberchild,Buffer (*myReadBuffer) (Relation,BlockNumber))
661+
gistFindPath(Relationr,BlockNumberchild,
662+
Buffer (*myReadBuffer) (Relation,BlockNumber))
660663
{
661664
Pagepage;
662665
Bufferbuffer;
@@ -674,7 +677,8 @@ gistFindPath(Relation r, BlockNumber child, Buffer (*myReadBuffer) (Relation, Bl
674677

675678
while (top&&top->blkno!=child)
676679
{
677-
buffer=myReadBuffer(r,top->blkno);/* buffer locked */
680+
buffer=myReadBuffer(r,top->blkno);/* locks buffer */
681+
gistcheckpage(r,buffer);
678682
page= (Page)BufferGetPage(buffer);
679683

680684
if (GistPageIsLeaf(page))
@@ -771,9 +775,9 @@ gistFindCorrectParent(Relation r, GISTInsertStack *child)
771775
GISTInsertStack*parent=child->parent;
772776

773777
LockBuffer(parent->buffer,GIST_EXCLUSIVE);
778+
gistcheckpage(r,parent->buffer);
774779
parent->page= (Page)BufferGetPage(parent->buffer);
775780

776-
777781
/* here we don't need to distinguish between split and page update */
778782
if (parent->childoffnum==InvalidOffsetNumber|| !XLByteEQ(parent->lsn,PageGetLSN(parent->page)))
779783
{
@@ -811,6 +815,7 @@ gistFindCorrectParent(Relation r, GISTInsertStack *child)
811815
break;
812816
parent->buffer=ReadBuffer(r,parent->blkno);
813817
LockBuffer(parent->buffer,GIST_EXCLUSIVE);
818+
gistcheckpage(r,parent->buffer);
814819
parent->page= (Page)BufferGetPage(parent->buffer);
815820
}
816821

@@ -831,7 +836,8 @@ gistFindCorrectParent(Relation r, GISTInsertStack *child)
831836
ptr=parent=gistFindPath(r,child->blkno,gistReadAndLockBuffer);
832837
Assert(ptr!=NULL);
833838

834-
/* read all buffers as supposed in caller */
839+
/* read all buffers as expected by caller */
840+
/* note we don't lock them or gistcheckpage them here! */
835841
while (ptr)
836842
{
837843
ptr->buffer=ReadBuffer(r,ptr->blkno);

‎src/backend/access/gist/gistget.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/access/gist/gistget.c,v 1.52 2005/10/0602:29:07 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/access/gist/gistget.c,v 1.53 2005/11/0622:39:20 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -40,6 +40,7 @@ killtuple(Relation r, GISTScanOpaque so, ItemPointer iptr)
4040
maxoff;
4141

4242
LockBuffer(buffer,GIST_SHARE);
43+
gistcheckpage(r,buffer);
4344
p= (Page)BufferGetPage(buffer);
4445

4546
if (buffer==so->curbuf&&XLByteEQ(so->stack->lsn,PageGetLSN(p)))
@@ -176,6 +177,7 @@ gistnext(IndexScanDesc scan, ScanDirection dir, ItemPointer tids, int maxtids, b
176177
/* First of all, we need lock buffer */
177178
Assert(so->curbuf!=InvalidBuffer);
178179
LockBuffer(so->curbuf,GIST_SHARE);
180+
gistcheckpage(scan->indexRelation,so->curbuf);
179181
p=BufferGetPage(so->curbuf);
180182
opaque=GistPageGetOpaque(p);
181183
resetoffset= false;
@@ -224,7 +226,8 @@ gistnext(IndexScanDesc scan, ScanDirection dir, ItemPointer tids, int maxtids, b
224226
continue;
225227
}
226228

227-
if (!GistPageIsLeaf(p)||resetoffset||ItemPointerIsValid(&scan->currentItemData)== false)
229+
if (!GistPageIsLeaf(p)||resetoffset||
230+
!ItemPointerIsValid(&scan->currentItemData))
228231
{
229232
if (ScanDirectionIsBackward(dir))
230233
n=PageGetMaxOffsetNumber(p);
@@ -268,7 +271,8 @@ gistnext(IndexScanDesc scan, ScanDirection dir, ItemPointer tids, int maxtids, b
268271
returnntids;
269272
}
270273

271-
so->curbuf=ReleaseAndReadBuffer(so->curbuf,scan->indexRelation,
274+
so->curbuf=ReleaseAndReadBuffer(so->curbuf,
275+
scan->indexRelation,
272276
stk->block);
273277
/* XXXgo up */
274278
break;

‎src/backend/access/gist/gistutil.c

Lines changed: 82 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
1010
* IDENTIFICATION
11-
*$PostgreSQL: pgsql/src/backend/access/gist/gistutil.c,v 1.7 2005/09/22 20:44:36 momjian Exp $
11+
*$PostgreSQL: pgsql/src/backend/access/gist/gistutil.c,v 1.8 2005/11/06 22:39:20 tgl Exp $
1212
*-------------------------------------------------------------------------
1313
*/
1414
#include"postgres.h"
@@ -798,23 +798,6 @@ gistpenalty(GISTSTATE *giststate, int attno,
798798
PointerGetDatum(penalty));
799799
}
800800

801-
void
802-
GISTInitBuffer(Bufferb,uint32f)
803-
{
804-
GISTPageOpaqueopaque;
805-
Pagepage;
806-
SizepageSize;
807-
808-
pageSize=BufferGetPageSize(b);
809-
page=BufferGetPage(b);
810-
PageInit(page,pageSize,sizeof(GISTPageOpaqueData));
811-
812-
opaque=GistPageGetOpaque(page);
813-
opaque->flags=f;
814-
opaque->rightlink=InvalidBlockNumber;
815-
memset(&(opaque->nsn),0,sizeof(GistNSN));
816-
}
817-
818801
void
819802
gistUserPicksplit(Relationr,GistEntryVector*entryvec,GIST_SPLITVEC*v,
820803
IndexTuple*itup,intlen,GISTSTATE*giststate)
@@ -864,36 +847,108 @@ gistUserPicksplit(Relation r, GistEntryVector *entryvec, GIST_SPLITVEC *v,
864847
}
865848
}
866849

850+
/*
851+
* Initialize a new index page
852+
*/
853+
void
854+
GISTInitBuffer(Bufferb,uint32f)
855+
{
856+
GISTPageOpaqueopaque;
857+
Pagepage;
858+
SizepageSize;
859+
860+
pageSize=BufferGetPageSize(b);
861+
page=BufferGetPage(b);
862+
PageInit(page,pageSize,sizeof(GISTPageOpaqueData));
863+
864+
opaque=GistPageGetOpaque(page);
865+
opaque->flags=f;
866+
opaque->rightlink=InvalidBlockNumber;
867+
/* page was already zeroed by PageInit, so this is not needed: */
868+
/* memset(&(opaque->nsn), 0, sizeof(GistNSN)); */
869+
}
870+
871+
/*
872+
* Verify that a freshly-read page looks sane.
873+
*/
874+
void
875+
gistcheckpage(Relationrel,Bufferbuf)
876+
{
877+
Pagepage=BufferGetPage(buf);
878+
879+
/*
880+
* ReadBuffer verifies that every newly-read page passes PageHeaderIsValid,
881+
* which means it either contains a reasonably sane page header or is
882+
* all-zero. We have to defend against the all-zero case, however.
883+
*/
884+
if (PageIsNew(page))
885+
ereport(ERROR,
886+
(errcode(ERRCODE_INDEX_CORRUPTED),
887+
errmsg("index \"%s\" contains unexpected zero page at block %u",
888+
RelationGetRelationName(rel),
889+
BufferGetBlockNumber(buf)),
890+
errhint("Please REINDEX it.")));
891+
892+
/*
893+
* Additionally check that the special area looks sane.
894+
*/
895+
if (((PageHeader) (page))->pd_special!=
896+
(BLCKSZ-MAXALIGN(sizeof(GISTPageOpaqueData))))
897+
ereport(ERROR,
898+
(errcode(ERRCODE_INDEX_CORRUPTED),
899+
errmsg("index \"%s\" contains corrupted page at block %u",
900+
RelationGetRelationName(rel),
901+
BufferGetBlockNumber(buf)),
902+
errhint("Please REINDEX it.")));
903+
}
904+
905+
906+
/*
907+
* Allocate a new page (either by recycling, or by extending the index file)
908+
*
909+
* The returned buffer is already pinned and exclusive-locked
910+
*
911+
* Caller is responsible for initializing the page by calling GISTInitBuffer
912+
*/
867913
Buffer
868914
gistNewBuffer(Relationr)
869915
{
870-
Bufferbuffer=InvalidBuffer;
916+
Bufferbuffer;
871917
boolneedLock;
872918

873-
while (true)
919+
/* First, try to get a page from FSM */
920+
for (;;)
874921
{
875922
BlockNumberblkno=GetFreeIndexPage(&r->rd_node);
876923

877924
if (blkno==InvalidBlockNumber)
878-
break;
925+
break;/* nothing left in FSM */
879926

880927
buffer=ReadBuffer(r,blkno);
928+
/*
929+
* We have to guard against the possibility that someone else already
930+
* recycled this page; the buffer may be locked if so.
931+
*/
881932
if (ConditionalLockBuffer(buffer))
882933
{
883934
Pagepage=BufferGetPage(buffer);
884935

936+
if (PageIsNew(page))
937+
returnbuffer;/* OK to use, if never initialized */
938+
939+
gistcheckpage(r,buffer);
940+
885941
if (GistPageIsDeleted(page))
886-
{
887-
GistPageSetNonDeleted(page);
888-
returnbuffer;
889-
}
890-
else
891-
LockBuffer(buffer,GIST_UNLOCK);
942+
returnbuffer;/* OK to use */
943+
944+
LockBuffer(buffer,GIST_UNLOCK);
892945
}
893946

947+
/* Can't use it, so release buffer and try again */
894948
ReleaseBuffer(buffer);
895949
}
896950

951+
/* Must extend the file */
897952
needLock= !RELATION_IS_LOCAL(r);
898953

899954
if (needLock)

‎src/backend/access/gist/gistvacuum.c

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/access/gist/gistvacuum.c,v 1.9 2005/09/22 20:44:36 momjian Exp $
11+
* $PostgreSQL: pgsql/src/backend/access/gist/gistvacuum.c,v 1.10 2005/11/06 22:39:20 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -65,6 +65,11 @@ gistVacuumUpdate(GistVacuum *gv, BlockNumber blkno, bool needunion)
6565
lencompleted=16;
6666

6767
buffer=ReadBuffer(gv->index,blkno);
68+
/*
69+
* This is only used during VACUUM FULL, so we need not bother to lock
70+
* individual index pages
71+
*/
72+
gistcheckpage(gv->index,buffer);
6873
page= (Page)BufferGetPage(buffer);
6974
maxoff=PageGetMaxOffsetNumber(page);
7075

@@ -378,9 +383,10 @@ gistvacuumcleanup(PG_FUNCTION_ARGS)
378383

379384
needFullVacuum= false;
380385

381-
needLock= !RELATION_IS_LOCAL(rel);
382386
if (info->vacuum_full)
383387
needLock= false;/* relation locked with AccessExclusiveLock */
388+
else
389+
needLock= !RELATION_IS_LOCAL(rel);
384390

385391
/* try to find deleted pages */
386392
if (needLock)
@@ -403,7 +409,7 @@ gistvacuumcleanup(PG_FUNCTION_ARGS)
403409
LockBuffer(buffer,GIST_SHARE);
404410
page= (Page)BufferGetPage(buffer);
405411

406-
if (GistPageIsDeleted(page))
412+
if (PageIsNew(page)||GistPageIsDeleted(page))
407413
{
408414
if (nFreePages<maxFreePages)
409415
{
@@ -513,6 +519,7 @@ gistbulkdelete(PG_FUNCTION_ARGS)
513519
ItemIdiid;
514520

515521
LockBuffer(buffer,GIST_SHARE);
522+
gistcheckpage(rel,buffer);
516523
page= (Page)BufferGetPage(buffer);
517524

518525
if (GistPageIsLeaf(page))

‎src/include/access/gist_private.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/include/access/gist_private.h,v 1.8 2005/10/15 02:49:42 momjian Exp $
10+
* $PostgreSQL: pgsql/src/include/access/gist_private.h,v 1.9 2005/11/06 22:39:21 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -263,6 +263,7 @@ extern Datum gistgettuple(PG_FUNCTION_ARGS);
263263
externDatumgistgetmulti(PG_FUNCTION_ARGS);
264264

265265
/* gistutil.c */
266+
externvoidgistcheckpage(Relationrel,Bufferbuf);
266267
externBuffergistNewBuffer(Relationr);
267268
externOffsetNumbergistfillbuffer(Relationr,Pagepage,IndexTuple*itup,
268269
intlen,OffsetNumberoff);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp