diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2003-08-10 19:48:08 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2003-08-10 19:48:08 +0000 |
commit | ffafacc1f6e403b81180aa20d0a4184ce92beef8 (patch) | |
tree | a85699334c2bcffee5ccaec9d4b37e90de438d67 /src/backend/storage/buffer/bufmgr.c | |
parent | 18c10877a9b7d5e3766f6f34c827892a33872567 (diff) | |
download | postgresql-ffafacc1f6e403b81180aa20d0a4184ce92beef8.tar.gz postgresql-ffafacc1f6e403b81180aa20d0a4184ce92beef8.zip |
Repair potential deadlock created by recent changes to recycle btree
index pages: when _bt_getbuf asks the FSM for a free index page, it is
possible (and, in some cases, even moderately likely) that the answer
will be the same page that _bt_split is trying to split. _bt_getbuf
already knew that the returned page might not be free, but it wasn't
prepared for the possibility that even trying to lock the page could
be problematic. Fix by doing a conditional rather than unconditional
grab of the page lock.
Diffstat (limited to 'src/backend/storage/buffer/bufmgr.c')
-rw-r--r-- | src/backend/storage/buffer/bufmgr.c | 33 |
1 files changed, 32 insertions, 1 deletions
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c index 2da3b4e364d..1be30d30e2b 100644 --- a/src/backend/storage/buffer/bufmgr.c +++ b/src/backend/storage/buffer/bufmgr.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.139 2003/08/04 02:40:03 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.140 2003/08/10 19:48:08 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1937,6 +1937,37 @@ LockBuffer(Buffer buffer, int mode) } /* + * Acquire the cntx_lock for the buffer, but only if we don't have to wait. + * + * This assumes the caller wants BUFFER_LOCK_EXCLUSIVE mode. + */ +bool +ConditionalLockBuffer(Buffer buffer) +{ + BufferDesc *buf; + + Assert(BufferIsValid(buffer)); + if (BufferIsLocal(buffer)) + return true; /* act as though we got it */ + + buf = &(BufferDescriptors[buffer - 1]); + + if (LWLockConditionalAcquire(buf->cntx_lock, LW_EXCLUSIVE)) + { + /* + * This is not the best place to set cntxDirty flag (eg indices do + * not always change buffer they lock in excl mode). But please + * remember that it's critical to set cntxDirty *before* logging + * changes with XLogInsert() - see comments in BufferSync(). + */ + buf->cntxDirty = true; + + return true; + } + return false; +} + +/* * LockBufferForCleanup - lock a buffer in preparation for deleting items * * Items may be deleted from a disk page only when the caller (a) holds an |