*
*
* IDENTIFICATION
- * $Id: hio.c,v 1.46 2002/08/06 02:36:33 tgl Exp $
+ * $Id: hio.c,v 1.46.2.1 2005/05/07 21:33:47 tgl Exp $
*
*-------------------------------------------------------------------------
*/
*/
buffer = ReadBuffer(relation, P_NEW);
- /*
- * Release the file-extension lock; it's now OK for someone else to
- * extend the relation some more.
- */
- if (needLock)
- UnlockPage(relation, 0, ExclusiveLock);
-
/*
* We can be certain that locking the otherBuffer first is OK, since
* it must have a lower page number.
LockBuffer(otherBuffer, BUFFER_LOCK_EXCLUSIVE);
/*
- * We need to initialize the empty new page.
+ * Now acquire lock on the new page.
*/
LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
+
+ /*
+ * Release the file-extension lock; it's now OK for someone else to
+ * extend the relation some more. Note that we cannot release this
+ * lock before we have buffer lock on the new page, or we risk a
+ * race condition against vacuumlazy.c --- see comments therein.
+ */
+ if (needLock)
+ UnlockPage(relation, 0, ExclusiveLock);
+
+ /*
+ * We need to initialize the empty new page.
+ */
pageHeader = (Page) BufferGetPage(buffer);
Assert(PageIsNew((PageHeader) pageHeader));
PageInit(pageHeader, BufferGetPageSize(buffer), 0);
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/vacuumlazy.c,v 1.20 2002/09/20 19:56:01 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/vacuumlazy.c,v 1.20.2.1 2005/05/07 21:33:47 tgl Exp $
*
*-------------------------------------------------------------------------
*/
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))
{