Fix two bugs in setting the vm bit of empty pages.
authorHeikki Linnakangas <[email protected]>
Wed, 23 Oct 2013 11:03:54 +0000 (14:03 +0300)
committerHeikki Linnakangas <[email protected]>
Wed, 23 Oct 2013 11:25:50 +0000 (14:25 +0300)
Use a critical section when setting the all-visible flag on an empty page,
and WAL-logging it. log_newpage_buffer() contains an assertion that it
must be called inside a critical section, and it's the right thing to do
when modifying a buffer anyway.

Also, the page should be marked dirty before calling log_newpage_buffer(),
per the comment in log_newpage_buffer() and src/backend/access/transam/README.

Patch by Andres Freund, in response to my report. Backpatch to 9.2, like
the patch that introduced these bugs (a6370fd9).

src/backend/commands/vacuumlazy.c

index 402e76e72bfce5ed171b0edfcd421d73c6bf0987..28f169e59c58b8c369c0ba98c11cdb44df2237ae 100644 (file)
@@ -650,6 +650,11 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats,
            /* empty pages are always all-visible */
            if (!PageIsAllVisible(page))
            {
+               START_CRIT_SECTION();
+
+               /* mark buffer dirty before writing a WAL record */
+               MarkBufferDirty(buf);
+
                /*
                 * It's possible that another backend has extended the heap,
                 * initialized the page, and then failed to WAL-log the page
@@ -669,9 +674,9 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats,
                    log_newpage_buffer(buf);
 
                PageSetAllVisible(page);
-               MarkBufferDirty(buf);
                visibilitymap_set(onerel, blkno, InvalidXLogRecPtr, vmbuffer,
                                  InvalidTransactionId);
+               END_CRIT_SECTION();
            }
 
            UnlockReleaseBuffer(buf);