aboutsummaryrefslogtreecommitdiff
path: root/src/backend/commands/vacuumlazy.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/commands/vacuumlazy.c')
-rw-r--r--src/backend/commands/vacuumlazy.c26
1 files changed, 24 insertions, 2 deletions
diff --git a/src/backend/commands/vacuumlazy.c b/src/backend/commands/vacuumlazy.c
index cc1852f65a1..891def15344 100644
--- a/src/backend/commands/vacuumlazy.c
+++ b/src/backend/commands/vacuumlazy.c
@@ -31,7 +31,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/vacuumlazy.c,v 1.32 2003/09/25 06:57:59 petere Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/vacuumlazy.c,v 1.32.2.1 2005/05/07 21:33:21 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -254,8 +254,30 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats,
if (PageIsNew(page))
{
- /* Not sure we still need to handle this case, but... */
+ /*
+ * An all-zeroes page could be left over if a backend extends
+ * the relation but crashes before initializing the page.
+ * Reclaim such pages for use.
+ *
+ * We have to be careful here because we could be looking at
+ * a page that someone has just added to the relation and not
+ * yet been able to initialize (see RelationGetBufferForTuple).
+ * To interlock against that, release the buffer read lock
+ * (which we must do anyway) and grab the relation extension
+ * lock before re-locking in exclusive mode. If the page is
+ * still uninitialized by then, it must be left over from a
+ * crashed backend, and we can initialize it.
+ *
+ * We don't really need the relation lock when this is a new
+ * or temp relation, but it's probably not worth the code space
+ * to check that, since this surely isn't a critical path.
+ *
+ * Note: the comparable code in vacuum.c need not do all this
+ * because it's got exclusive lock on the whole relation.
+ */
LockBuffer(buf, BUFFER_LOCK_UNLOCK);
+ LockPage(onerel, 0, ExclusiveLock);
+ UnlockPage(onerel, 0, ExclusiveLock);
LockBuffer(buf, BUFFER_LOCK_EXCLUSIVE);
if (PageIsNew(page))
{