aboutsummaryrefslogtreecommitdiff
path: root/src/include
diff options
context:
space:
mode:
authorNoah Misch <noah@leadboat.com>2021-01-16 12:21:35 -0800
committerNoah Misch <noah@leadboat.com>2021-01-16 12:21:38 -0800
commit6eb3fc7fcd89258c2f4bb3dde03e41e6ede2be5f (patch)
tree87a22533637e76d7a354d3b0035701d8a4b6c2e5 /src/include
parentd26d4c717dbfb24cc9dfd83044b5c9a377dc954a (diff)
downloadpostgresql-6eb3fc7fcd89258c2f4bb3dde03e41e6ede2be5f.tar.gz
postgresql-6eb3fc7fcd89258c2f4bb3dde03e41e6ede2be5f.zip
Prevent excess SimpleLruTruncate() deletion.
Every core SLRU wraps around. With the exception of pg_notify, the wrap point can fall in the middle of a page. Account for this in the PagePrecedes callback specification and in SimpleLruTruncate()'s use of said callback. Update each callback implementation to fit the new specification. This changes SerialPagePrecedesLogically() from the style of asyncQueuePagePrecedes() to the style of CLOGPagePrecedes(). (Whereas pg_clog and pg_serial share a key space, pg_serial is nothing like pg_notify.) The bug fixed here has the same symptoms and user followup steps as 592a589a04bd456410b853d86bd05faa9432cbbb. Back-patch to 9.5 (all supported versions). Reviewed by Andrey Borodin and (in earlier versions) by Tom Lane. Discussion: https://postgr.es/m/20190202083822.GC32531@gust.leadboat.com
Diffstat (limited to 'src/include')
-rw-r--r--src/include/access/slru.h16
1 files changed, 13 insertions, 3 deletions
diff --git a/src/include/access/slru.h b/src/include/access/slru.h
index 61fbc80ef0d..19982f6e226 100644
--- a/src/include/access/slru.h
+++ b/src/include/access/slru.h
@@ -117,9 +117,14 @@ typedef struct SlruCtlData
bool do_fsync;
/*
- * Decide which of two page numbers is "older" for truncation purposes. We
- * need to use comparison of TransactionIds here in order to do the right
- * thing with wraparound XID arithmetic.
+ * Decide whether a page is "older" for truncation and as a hint for
+ * evicting pages in LRU order. Return true if every entry of the first
+ * argument is older than every entry of the second argument. Note that
+ * !PagePrecedes(a,b) && !PagePrecedes(b,a) need not imply a==b; it also
+ * arises when some entries are older and some are not. For SLRUs using
+ * SimpleLruTruncate(), this must use modular arithmetic. (For others,
+ * the behavior of this callback has no functional implications.) Use
+ * SlruPagePrecedesUnitTests() in SLRUs meeting its criteria.
*/
bool (*PagePrecedes) (int, int);
@@ -143,6 +148,11 @@ extern int SimpleLruReadPage_ReadOnly(SlruCtl ctl, int pageno,
TransactionId xid);
extern void SimpleLruWritePage(SlruCtl ctl, int slotno);
extern void SimpleLruFlush(SlruCtl ctl, bool allow_redirtied);
+#ifdef USE_ASSERT_CHECKING
+extern void SlruPagePrecedesUnitTests(SlruCtl ctl, int per_page);
+#else
+#define SlruPagePrecedesUnitTests(ctl, per_page) do {} while (0)
+#endif
extern void SimpleLruTruncate(SlruCtl ctl, int cutoffPage);
extern bool SimpleLruDoesPhysicalPageExist(SlruCtl ctl, int pageno);