diff options
author | Heikki Linnakangas <heikki.linnakangas@iki.fi> | 2014-01-24 10:42:38 +0200 |
---|---|---|
committer | Heikki Linnakangas <heikki.linnakangas@iki.fi> | 2014-01-24 10:48:45 +0200 |
commit | 398cf255ad50db86ca665b75582317d4e795242a (patch) | |
tree | 3ee0fcb797d98273d0d14687e69542257a8f4724 | |
parent | fbe19ee3b87590f1006d072be5fecf8a33d4e9f5 (diff) | |
download | postgresql-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.c | 15 |
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; } |