@@ -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