]> granicus.if.org Git - postgresql/commitdiff
Fix two bugs in setting the vm bit of empty pages.
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>
Wed, 23 Oct 2013 11:03:54 +0000 (14:03 +0300)
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>
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);