Skip to content

Commit 6842005

Browse files
committed
Revert "Move page initialization from RelationAddExtraBlocks() to use."
This reverts commit fc02e67 and e6799d5. Parts of the buildfarm error out with ERROR: page %u of relation "%s" should be empty but is not errors, and so far I/we do not know why. fc02e67 didn't fix the issue. As I cannot reproduce the issue locally, it seems best to get the buildfarm green again, and reproduce the issue without time pressure.
1 parent fc02e67 commit 6842005

File tree

2 files changed

+42
-78
lines changed

2 files changed

+42
-78
lines changed

src/backend/access/heap/hio.c

Lines changed: 10 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -204,8 +204,7 @@ RelationAddExtraBlocks(Relation relation, BulkInsertState bistate)
204204
/*
205205
* Extend by one page. This should generally match the main-line
206206
* extension code in RelationGetBufferForTuple, except that we hold
207-
* the relation extension lock throughout, and we don't immediately
208-
* initialize the page (see below).
207+
* the relation extension lock throughout.
209208
*/
210209
buffer = ReadBufferBI(relation, P_NEW, bistate);
211210

@@ -217,16 +216,18 @@ RelationAddExtraBlocks(Relation relation, BulkInsertState bistate)
217216
BufferGetBlockNumber(buffer),
218217
RelationGetRelationName(relation));
219218

219+
PageInit(page, BufferGetPageSize(buffer), 0);
220+
220221
/*
221-
* Add the page to the FSM without initializing. If we were to
222-
* initialize here the page would potentially get flushed out to disk
223-
* before we add any useful content. There's no guarantee that that'd
224-
* happen before a potential crash, so we need to deal with
225-
* uninitialized pages anyway, thus avoid the potential for
226-
* unnecessary writes.
222+
* We mark all the new buffers dirty, but do nothing to write them
223+
* out; they'll probably get used soon, and even if they are not, a
224+
* crash will leave an okay all-zeroes page on disk.
227225
*/
226+
MarkBufferDirty(buffer);
227+
228+
/* we'll need this info below */
228229
blockNum = BufferGetBlockNumber(buffer);
229-
freespace = BufferGetPageSize(buffer) - SizeOfPageHeaderData;
230+
freespace = PageGetHeapFreeSpace(page);
230231

231232
UnlockReleaseBuffer(buffer);
232233

@@ -478,18 +479,6 @@ RelationGetBufferForTuple(Relation relation, Size len,
478479
* we're done.
479480
*/
480481
page = BufferGetPage(buffer);
481-
482-
/*
483-
* Initialize page, it'll be used soon. We could avoid dirtying the
484-
* buffer here, and rely on the caller to do so whenever it puts a
485-
* tuple onto the page, but there seems not much benefit in doing so.
486-
*/
487-
if (PageIsNew(page))
488-
{
489-
PageInit(page, BufferGetPageSize(buffer), 0);
490-
MarkBufferDirty(buffer);
491-
}
492-
493482
pageFreeSpace = PageGetHeapFreeSpace(page);
494483
if (len + saveFreeSpace <= pageFreeSpace)
495484
{

src/backend/access/heap/vacuumlazy.c

Lines changed: 32 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -860,65 +860,43 @@ lazy_scan_heap(Relation onerel, int options, LVRelStats *vacrelstats,
860860

861861
if (PageIsNew(page))
862862
{
863-
bool still_new;
864-
865863
/*
866-
* All-zeroes pages can be left over if either a backend extends
867-
* the relation by a single page, but crashes before the newly
868-
* initialized page has been written out, or when bulk-extending
869-
* the relation (which creates a number of empty pages at the tail
870-
* end of the relation, but enters them into the FSM).
871-
*
872-
* Make sure these pages are in the FSM, to ensure they can be
873-
* reused. Do that by testing if there's any space recorded for
874-
* the page. If not, enter it.
875-
*
876-
* Note we do not enter the page into the visibilitymap. That has
877-
* the downside that we repeatedly visit this page in subsequent
878-
* vacuums, but otherwise we'll never not discover the space on a
879-
* promoted standby. The harm of repeated checking ought to
880-
* normally not be too bad - the space usually should be used at
881-
* some point, otherwise there wouldn't be any regular vacuums.
864+
* An all-zeroes page could be left over if a backend extends the
865+
* relation but crashes before initializing the page. Reclaim such
866+
* pages for use.
882867
*
883868
* We have to be careful here because we could be looking at a
884-
* page that someone has just added to the relation and the
885-
* extending backend might not yet have been able to lock the page
886-
* (see RelationGetBufferForTuple), which is problematic because
887-
* of cross-checks that new pages are actually new. If we add this
888-
* page to the FSM, this page could be reused, and such
889-
* crosschecks could fail. To protect against that, release the
890-
* buffer lock, grab the relation extension lock momentarily, and
891-
* re-lock the buffer. If the page is still empty and not in the
892-
* FSM by then, it must be left over from a from a crashed
893-
* backend, and we can record the free space.
869+
* page that someone has just added to the relation and not yet
870+
* been able to initialize (see RelationGetBufferForTuple). To
871+
* protect against that, release the buffer lock, grab the
872+
* relation extension lock momentarily, and re-lock the buffer. If
873+
* the page is still uninitialized by then, it must be left over
874+
* from a crashed backend, and we can initialize it.
875+
*
876+
* We don't really need the relation lock when this is a new or
877+
* temp relation, but it's probably not worth the code space to
878+
* check that, since this surely isn't a critical path.
894879
*
895880
* Note: the comparable code in vacuum.c need not worry because
896-
* it's got an exclusive lock on the whole relation.
881+
* it's got exclusive lock on the whole relation.
897882
*/
898883
LockBuffer(buf, BUFFER_LOCK_UNLOCK);
899884
LockRelationForExtension(onerel, ExclusiveLock);
900885
UnlockRelationForExtension(onerel, ExclusiveLock);
901886
LockBufferForCleanup(buf);
902-
903-
/*
904-
* Perform checking of FSM after releasing lock, the fsm is
905-
* approximate, after all.
906-
*/
907-
still_new = PageIsNew(page);
908-
UnlockReleaseBuffer(buf);
909-
910-
if (still_new)
887+
if (PageIsNew(page))
911888
{
889+
ereport(WARNING,
890+
(errmsg("relation \"%s\" page %u is uninitialized --- fixing",
891+
relname, blkno)));
892+
PageInit(page, BufferGetPageSize(buf), 0);
912893
empty_pages++;
913-
914-
if (GetRecordedFreeSpace(onerel, blkno) == 0)
915-
{
916-
Size freespace;
917-
918-
freespace = BufferGetPageSize(buf) - SizeOfPageHeaderData;
919-
RecordPageWithFreeSpace(onerel, blkno, freespace);
920-
}
921894
}
895+
freespace = PageGetHeapFreeSpace(page);
896+
MarkBufferDirty(buf);
897+
UnlockReleaseBuffer(buf);
898+
899+
RecordPageWithFreeSpace(onerel, blkno, freespace);
922900
continue;
923901
}
924902

@@ -927,10 +905,7 @@ lazy_scan_heap(Relation onerel, int options, LVRelStats *vacrelstats,
927905
empty_pages++;
928906
freespace = PageGetHeapFreeSpace(page);
929907

930-
/*
931-
* Empty pages are always all-visible and all-frozen (note that
932-
* the same is currently not true for new pages, see above).
933-
*/
908+
/* empty pages are always all-visible and all-frozen */
934909
if (!PageIsAllVisible(page))
935910
{
936911
START_CRIT_SECTION();
@@ -1664,13 +1639,12 @@ lazy_check_needs_freeze(Buffer buf, bool *hastup)
16641639

16651640
*hastup = false;
16661641

1667-
/*
1668-
* New and empty pages, obviously, don't contain tuples. We could make
1669-
* sure that the page is registered in the FSM, but it doesn't seem worth
1670-
* waiting for a cleanup lock just for that, especially because it's
1671-
* likely that the pin holder will do so.
1672-
*/
1673-
if (PageIsNew(page) || PageIsEmpty(page))
1642+
/* If we hit an uninitialized page, we want to force vacuuming it. */
1643+
if (PageIsNew(page))
1644+
return true;
1645+
1646+
/* Quick out for ordinary empty page. */
1647+
if (PageIsEmpty(page))
16741648
return false;
16751649

16761650
maxoff = PageGetMaxOffsetNumber(page);
@@ -2055,6 +2029,7 @@ count_nondeletable_pages(Relation onerel, LVRelStats *vacrelstats)
20552029

20562030
if (PageIsNew(page) || PageIsEmpty(page))
20572031
{
2032+
/* PageIsNew probably shouldn't happen... */
20582033
UnlockReleaseBuffer(buf);
20592034
continue;
20602035
}

0 commit comments

Comments
 (0)