From 0b928fb91b5b3aa527372495e9fa4778c5b5bfab Mon Sep 17 00:00:00 2001 From: Craig Ringer Date: Thu, 25 Aug 2016 10:59:57 +0800 Subject: [PATCH 1/4] Release SLRU control lock before reporting I/O error To allow callers to trap SLRU I/O errors with a PG_TRY() / PG_CATCH() block, slru.c functions that acquire the SLRU control lock now also release the SLRU control LWLock before reporting I/O errors. Many SLRU functions previously took the LWLock and threw exceptions with it still held. --- src/backend/access/transam/slru.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/backend/access/transam/slru.c b/src/backend/access/transam/slru.c index bbae584..f020522 100644 --- a/src/backend/access/transam/slru.c +++ b/src/backend/access/transam/slru.c @@ -366,7 +366,8 @@ SimpleLruWaitIO(SlruCtl ctl, int slotno) * Return value is the shared-buffer slot number now holding the page. * The buffer's LRU access info is updated. * - * Control lock must be held at entry, and will be held at exit. + * Control lock must be held at entry, and will be held at normal exit. + * The control lock is released if an exception is thrown. */ int SimpleLruReadPage(SlruCtl ctl, int pageno, bool write_ok, @@ -439,7 +440,10 @@ SimpleLruReadPage(SlruCtl ctl, int pageno, bool write_ok, /* Now it's okay to ereport if we failed */ if (!ok) + { + LWLockRelease(shared->ControlLock); SlruReportIOError(ctl, pageno, xid); + } SlruRecentlyUsed(shared, slotno); return slotno; @@ -457,8 +461,9 @@ SimpleLruReadPage(SlruCtl ctl, int pageno, bool write_ok, * Return value is the shared-buffer slot number now holding the page. * The buffer's LRU access info is updated. * - * Control lock must NOT be held at entry, but will be held at exit. - * It is unspecified whether the lock will be shared or exclusive. + * Control lock must NOT be held at entry, but will be held at exit + * unless an exception is thrown. It is unspecified whether the lock + * will be shared or exclusive. */ int SimpleLruReadPage_ReadOnly(SlruCtl ctl, int pageno, TransactionId xid) @@ -498,7 +503,8 @@ SimpleLruReadPage_ReadOnly(SlruCtl ctl, int pageno, TransactionId xid) * the write). However, we *do* attempt a fresh write even if the page * is already being written; this is for checkpoints. * - * Control lock must be held at entry, and will be held at exit. + * Control lock must be held at entry, and will be held at normal exit. + * The lock is released if an exception is thrown. */ static void SlruInternalWritePage(SlruCtl ctl, int slotno, SlruFlush fdata) @@ -564,7 +570,10 @@ SlruInternalWritePage(SlruCtl ctl, int slotno, SlruFlush fdata) /* Now it's okay to ereport if we failed */ if (!ok) + { + LWLockRelease(shared->ControlLock); SlruReportIOError(ctl, pageno, InvalidTransactionId); + } } /* -- 2.5.5