aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlvaro Herrera <alvherre@alvh.no-ip.org>2017-05-30 17:32:53 -0400
committerAlvaro Herrera <alvherre@alvh.no-ip.org>2017-05-30 18:17:09 -0400
commitb4da9d0e1ee45a1d157dc7fd24b24745b16ebe9f (patch)
tree399a92e4050035b98cab5918a557200f762d8c9c
parente6785a5ca16bfe67b9c74d168ae6e88c6e55c8ac (diff)
downloadpostgresql-b4da9d0e1ee45a1d157dc7fd24b24745b16ebe9f.tar.gz
postgresql-b4da9d0e1ee45a1d157dc7fd24b24745b16ebe9f.zip
brin: Don't crash on auto-summarization
We were trying to free a pointer into a shared buffer, which never works; and we were failing to release the buffer lock appropriately. Fix those omissions. While at it, improve documentation for brinGetTupleForHeapBlock, the inadequacy of which evidently caused these bugs in the first place. Reported independently by Zhou Digoal (bug #14668) and Alexander Sosna. Discussion: https://postgr.es/m/8c31c11b-6adb-228d-22c2-4ace89fc9209@credativ.de Discussion: https://postgr.es/m/20170524063323.29941.46339@wrigleys.postgresql.org
-rw-r--r--src/backend/access/brin/brin.c3
-rw-r--r--src/backend/access/brin/brin_revmap.c13
2 files changed, 10 insertions, 6 deletions
diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 442a46140db..b0e89ace5e2 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -190,7 +190,8 @@ brininsert(Relation idxRel, Datum *values, bool *nulls,
AutoVacuumRequestWork(AVW_BRINSummarizeRange,
RelationGetRelid(idxRel),
lastPageRange);
- brin_free_tuple(lastPageTuple);
+ else
+ LockBuffer(buf, BUFFER_LOCK_UNLOCK);
}
brtup = brinGetTupleForHeapBlock(revmap, heapBlk, &buf, &off,
diff --git a/src/backend/access/brin/brin_revmap.c b/src/backend/access/brin/brin_revmap.c
index fc8b10ab396..e778cbcacdc 100644
--- a/src/backend/access/brin/brin_revmap.c
+++ b/src/backend/access/brin/brin_revmap.c
@@ -179,13 +179,16 @@ brinSetHeapBlockItemptr(Buffer buf, BlockNumber pagesPerRange,
/*
* Fetch the BrinTuple for a given heap block.
*
- * The buffer containing the tuple is locked, and returned in *buf. As an
- * optimization, the caller can pass a pinned buffer *buf on entry, which will
- * avoid a pin-unpin cycle when the next tuple is on the same page as a
- * previous one.
+ * The buffer containing the tuple is locked, and returned in *buf. The
+ * returned tuple points to the shared buffer and must not be freed; if caller
+ * wants to use it after releasing the buffer lock, it must create its own
+ * palloc'ed copy. As an optimization, the caller can pass a pinned buffer
+ * *buf on entry, which will avoid a pin-unpin cycle when the next tuple is on
+ * the same page as a previous one.
*
* If no tuple is found for the given heap range, returns NULL. In that case,
- * *buf might still be updated, but it's not locked.
+ * *buf might still be updated (and pin must be released by caller), but it's
+ * not locked.
*
* The output tuple offset within the buffer is returned in *off, and its size
* is returned in *size.