Commit 731ead1d authored by marko's avatar marko

branches/zip: page_zip_copy(): Copy only those B-tree page header

fields that are related to the records stored in the page.

page_zip_copy() is a fall-back method in certain B-tree operations
(tree compression, splitting or merging nodes).  The contents of a
page may fit in the compressed page frame when it has been modified in
a certain sequence, but not when the page is recompressed.  Sometimes,
copying all or part of the records to an empty page could fail because
of compression overflow.  In such cases, we copy the compressed and
uncompressed pages bit for bit and delete any unwanted records from
the copy.  (Deletion is guaranteed to succeed.)  The method
page_zip_copy() is invoked very rarely.

In one case, page_zip_copy() was called in btr_lift_page_up() to move
the records to the root page of the B-tree.  Because page_zip_copy()
copied all B-tree page header fields, it overwrote the file segment
header fields PAGE_BTR_SEG_LEAF and PAGE_BTR_SEG_TOP.  This is the
probable cause of the corruption that was reported as Mantis issue #63
and others.
parent cbb933cd
......@@ -4316,14 +4316,20 @@ page_zip_copy(
UNIV_MEM_ASSERT_RW(src, UNIV_PAGE_SIZE);
UNIV_MEM_ASSERT_RW(src_zip->data, page_zip_get_size(page_zip));
/* Skip the file page header and trailer. */
memcpy(page + FIL_PAGE_DATA, src + FIL_PAGE_DATA,
UNIV_PAGE_SIZE - FIL_PAGE_DATA
- FIL_PAGE_DATA_END);
memcpy(page_zip->data + FIL_PAGE_DATA,
src_zip->data + FIL_PAGE_DATA,
page_zip_get_size(page_zip) - FIL_PAGE_DATA);
/* Copy those B-tree page header fields that are related to the
records stored in the page. Skip the rest of the page header
and trailer. On the compressed page, there is no trailer. */
memcpy(PAGE_HEADER + page, PAGE_HEADER + src,
PAGE_HEADER_PRIV_END);
memcpy(PAGE_DATA + page, PAGE_DATA + src,
UNIV_PAGE_SIZE - PAGE_DATA - FIL_PAGE_DATA_END);
memcpy(PAGE_HEADER + page_zip->data, PAGE_HEADER + src_zip->data,
PAGE_HEADER_PRIV_END);
memcpy(PAGE_DATA + page_zip->data, PAGE_DATA + src_zip->data,
page_zip_get_size(page_zip) - PAGE_DATA);
/* Copy all fields of src_zip to page_zip, except the pointer
to the compressed data page. */
{
page_zip_t* data = page_zip->data;
memcpy(page_zip, src_zip, sizeof *page_zip);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment