aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>2014-01-24 10:42:38 +0200
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>2014-01-24 10:48:45 +0200
commit398cf255ad50db86ca665b75582317d4e795242a (patch)
tree3ee0fcb797d98273d0d14687e69542257a8f4724
parentfbe19ee3b87590f1006d072be5fecf8a33d4e9f5 (diff)
downloadpostgresql-398cf255ad50db86ca665b75582317d4e795242a.tar.gz
postgresql-398cf255ad50db86ca665b75582317d4e795242a.zip
In GIN recompression code, use mmemove rather than memcpy, for vacuum.
When vacuuming a data leaf page, any compressed posting lists that are not modified, are copied back to the buffer from a later location in the same buffer rather than from a palloc'd copy. IOW, they are just moved downwards in the same buffer. Because the source and destination addresses can overlap, we must use memmove rather than memcpy. Report and fix by Alexander Korotkov.
-rw-r--r--src/backend/access/gin/gindatapage.c15
1 files changed, 14 insertions, 1 deletions
diff --git a/src/backend/access/gin/gindatapage.c b/src/backend/access/gin/gindatapage.c
index 8504f4c7afc..ebdacd40c55 100644
--- a/src/backend/access/gin/gindatapage.c
+++ b/src/backend/access/gin/gindatapage.c
@@ -753,6 +753,13 @@ ginVacuumPostingTreeLeaf(Relation indexrel, Buffer buffer, GinVacuumState *gvs)
* *prdata is filled with WAL information about this operation. The caller
* is responsible for inserting to the WAL, along with any other information
* about the operation that triggered this recompression.
+ *
+ * NOTE: The segment pointers can point directly to the same buffer, with
+ * the limitation that any earlier segment must not overlap with an original,
+ * later segment. In other words, some segments may point the original buffer
+ * as long as you don't make any segments larger. Currently, leafRepackItems
+ * satisies this rule because it rewrites all segments after the first
+ * modified one, and vacuum can only make segments shorter.
*/
static void
dataPlaceToPageLeafRecompress(Buffer buf, disassembledLeaf *leaf,
@@ -798,7 +805,13 @@ dataPlaceToPageLeafRecompress(Buffer buf, disassembledLeaf *leaf,
if (!modified)
unmodifiedsize += segsize;
else
- memcpy(ptr, seginfo->seg, segsize);
+ {
+ /*
+ * Use memmove rather than memcpy, in case the segment points
+ * to the same buffer
+ */
+ memmove(ptr, seginfo->seg, segsize);
+ }
ptr += segsize;
newsize += segsize;
}