summaryrefslogtreecommitdiff
path: root/storage.c
diff options
context:
space:
mode:
authordormando <dormando@rydia.net>2017-12-14 17:51:35 -0800
committerdormando <dormando@rydia.net>2017-12-14 17:51:35 -0800
commitc65a2fbb13bec94313ddf308468b59d8be5db5b0 (patch)
treebdae0fc9ebabde9552ac27d41a1b6f44d6be626a /storage.c
parentbca66424e9f367a57a5bcf5a5707a4d4b33520fb (diff)
downloadmemcached-c65a2fbb13bec94313ddf308468b59d8be5db5b0.tar.gz
extstore: fix crash while moving extstore chunks
ITEM_LINKED was still set on the objects being written to disk. If a page being moved contains a chunk read from extstore currently being written back to the client, it will mistake it for a chunk properly linked and attempt to unlink if if the page has also been jammed in the mover. So you need a cross section of a particular chunk being active the entire time a page is jammed, then it tries to unlink it but the header is partially garbage and it segfaults. The page mover ignores all items which don't either have LINKED or SLABBED, assuming they're in transition. So the fix is to simply remove the LINKED bit after copying into the write buffer.
Diffstat (limited to 'storage.c')
-rw-r--r--storage.c1
1 files changed, 1 insertions, 0 deletions
diff --git a/storage.c b/storage.c
index 6952ae0..fbeb121 100644
--- a/storage.c
+++ b/storage.c
@@ -96,6 +96,7 @@ int lru_maintainer_store(void *storage, const int clsid) {
memcpy((char *)io.buf+32, (char *)it+32, io.len-32);
}
// crc what we copied so we can do it sequentially.
+ buf_it->it_flags &= ~ITEM_LINKED;
buf_it->exptime = crc32c(0, (char*)io.buf+32, orig_ntotal-32);
extstore_write(storage, &io);
item_hdr *hdr = (item_hdr *) ITEM_data(hdr_it);