Commit 037b78e5 authored by Jan Lindström's avatar Jan Lindström

MDEV-9242: Innodb reports Assertion failure in file buf0dblwr.cc line 579

Analysis: When pages in doublewrite buffer are analyzed compressed
pages do not have correct checksum.

Fix: Decompress page before checksum is compared. If decompression
fails we still check checksum and corrupted pages are found.
If decompression succeeds, page now contains the original
checksum.
parent d5822a3a
/***************************************************************************** /*****************************************************************************
Copyright (c) 1995, 2014, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1995, 2014, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2013, 2015, MariaDB Corporation. All Rights Reserved. Copyright (c) 2013, 2016, MariaDB Corporation. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
...@@ -37,6 +37,7 @@ Created 2011/12/19 ...@@ -37,6 +37,7 @@ Created 2011/12/19
#include "page0zip.h" #include "page0zip.h"
#include "trx0sys.h" #include "trx0sys.h"
#include "fil0crypt.h" #include "fil0crypt.h"
#include "fil0pagecompress.h"
#ifndef UNIV_HOTBACKUP #ifndef UNIV_HOTBACKUP
...@@ -500,6 +501,7 @@ buf_dblwr_process() ...@@ -500,6 +501,7 @@ buf_dblwr_process()
for (std::list<byte*>::iterator i = recv_dblwr.pages.begin(); for (std::list<byte*>::iterator i = recv_dblwr.pages.begin();
i != recv_dblwr.pages.end(); ++i, ++page_no_dblwr ) { i != recv_dblwr.pages.end(); ++i, ++page_no_dblwr ) {
bool is_compressed = false;
page = *i; page = *i;
page_no = mach_read_from_4(page + FIL_PAGE_OFFSET); page_no = mach_read_from_4(page + FIL_PAGE_OFFSET);
...@@ -533,6 +535,16 @@ buf_dblwr_process() ...@@ -533,6 +535,16 @@ buf_dblwr_process()
NULL, NULL,
0); 0);
/* Is page compressed ? */
is_compressed = fil_page_is_compressed_encrypted(read_buf) |
fil_page_is_compressed(read_buf);
/* If page was compressed, decompress it before we
check checksum. */
if (is_compressed) {
fil_decompress_page(NULL, read_buf, UNIV_PAGE_SIZE, NULL, true);
}
if (fil_space_verify_crypt_checksum(read_buf, zip_size)) { if (fil_space_verify_crypt_checksum(read_buf, zip_size)) {
/* page is encrypted and checksum is OK */ /* page is encrypted and checksum is OK */
} else if (buf_page_is_corrupted(true, read_buf, zip_size)) { } else if (buf_page_is_corrupted(true, read_buf, zip_size)) {
...@@ -546,6 +558,16 @@ buf_dblwr_process() ...@@ -546,6 +558,16 @@ buf_dblwr_process()
" the doublewrite buffer.\n", " the doublewrite buffer.\n",
(ulong) space_id, (ulong) page_no); (ulong) space_id, (ulong) page_no);
/* Is page compressed ? */
is_compressed = fil_page_is_compressed_encrypted(page) |
fil_page_is_compressed(page);
/* If page was compressed, decompress it before we
check checksum. */
if (is_compressed) {
fil_decompress_page(NULL, page, UNIV_PAGE_SIZE, NULL, true);
}
if (fil_space_verify_crypt_checksum(page, zip_size)) { if (fil_space_verify_crypt_checksum(page, zip_size)) {
/* the doublewrite buffer page is encrypted and OK */ /* the doublewrite buffer page is encrypted and OK */
} else if (buf_page_is_corrupted(true, } else if (buf_page_is_corrupted(true,
......
/***************************************************************************** /*****************************************************************************
Copyright (C) 2013, 2015, MariaDB Corporation. All Rights Reserved. Copyright (C) 2013, 2016, MariaDB Corporation. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
...@@ -447,8 +447,11 @@ fil_decompress_page( ...@@ -447,8 +447,11 @@ fil_decompress_page(
byte* buf, /*!< out: buffer from which to read; in aio byte* buf, /*!< out: buffer from which to read; in aio
this must be appropriately aligned */ this must be appropriately aligned */
ulong len, /*!< in: length of output buffer.*/ ulong len, /*!< in: length of output buffer.*/
ulint* write_size) /*!< in/out: Actual payload size of ulint* write_size, /*!< in/out: Actual payload size of
the compressed data. */ the compressed data. */
bool return_error) /*!< in: true if only an error should
be produced when decompression fails.
By default this parameter is false. */
{ {
int err = 0; int err = 0;
ulint actual_size = 0; ulint actual_size = 0;
...@@ -493,6 +496,9 @@ fil_decompress_page( ...@@ -493,6 +496,9 @@ fil_decompress_page(
mach_read_from_2(buf+FIL_PAGE_TYPE), len); mach_read_from_2(buf+FIL_PAGE_TYPE), len);
fflush(stderr); fflush(stderr);
if (return_error) {
goto error_return;
}
ut_error; ut_error;
} }
...@@ -512,6 +518,9 @@ fil_decompress_page( ...@@ -512,6 +518,9 @@ fil_decompress_page(
" actual size %lu compression %s.", " actual size %lu compression %s.",
actual_size, fil_get_compression_alg_name(compression_alg)); actual_size, fil_get_compression_alg_name(compression_alg));
fflush(stderr); fflush(stderr);
if (return_error) {
goto error_return;
}
ut_error; ut_error;
} }
...@@ -543,6 +552,9 @@ fil_decompress_page( ...@@ -543,6 +552,9 @@ fil_decompress_page(
fflush(stderr); fflush(stderr);
if (return_error) {
goto error_return;
}
ut_error; ut_error;
} }
break; break;
...@@ -559,6 +571,9 @@ fil_decompress_page( ...@@ -559,6 +571,9 @@ fil_decompress_page(
err, actual_size, len); err, actual_size, len);
fflush(stderr); fflush(stderr);
if (return_error) {
goto error_return;
}
ut_error; ut_error;
} }
break; break;
...@@ -577,6 +592,9 @@ fil_decompress_page( ...@@ -577,6 +592,9 @@ fil_decompress_page(
olen, actual_size, len); olen, actual_size, len);
fflush(stderr); fflush(stderr);
if (return_error) {
goto error_return;
}
ut_error; ut_error;
} }
break; break;
...@@ -610,6 +628,9 @@ fil_decompress_page( ...@@ -610,6 +628,9 @@ fil_decompress_page(
dst_pos, actual_size, len); dst_pos, actual_size, len);
fflush(stderr); fflush(stderr);
if (return_error) {
goto error_return;
}
ut_error; ut_error;
} }
...@@ -636,6 +657,9 @@ fil_decompress_page( ...@@ -636,6 +657,9 @@ fil_decompress_page(
dst_pos, actual_size, len, err); dst_pos, actual_size, len, err);
fflush(stderr); fflush(stderr);
if (return_error) {
goto error_return;
}
ut_error; ut_error;
} }
break; break;
...@@ -661,6 +685,9 @@ fil_decompress_page( ...@@ -661,6 +685,9 @@ fil_decompress_page(
olen, actual_size, len, (int)cstatus); olen, actual_size, len, (int)cstatus);
fflush(stderr); fflush(stderr);
if (return_error) {
goto error_return;
}
ut_error; ut_error;
} }
break; break;
...@@ -674,6 +701,9 @@ fil_decompress_page( ...@@ -674,6 +701,9 @@ fil_decompress_page(
,fil_get_compression_alg_name(compression_alg)); ,fil_get_compression_alg_name(compression_alg));
fflush(stderr); fflush(stderr);
if (return_error) {
goto error_return;
}
ut_error; ut_error;
break; break;
} }
...@@ -684,6 +714,7 @@ fil_decompress_page( ...@@ -684,6 +714,7 @@ fil_decompress_page(
really any other options. */ really any other options. */
memcpy(buf, in_buf, len); memcpy(buf, in_buf, len);
error_return:
// Need to free temporal buffer if no buffer was given // Need to free temporal buffer if no buffer was given
if (page_buf == NULL) { if (page_buf == NULL) {
ut_free(in_buf); ut_free(in_buf);
......
/***************************************************************************** /*****************************************************************************
Copyright (C) 2013, 2015 MariaDB Corporation. All Rights Reserved. Copyright (C) 2013, 2016 MariaDB Corporation. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
...@@ -117,8 +117,12 @@ fil_decompress_page( ...@@ -117,8 +117,12 @@ fil_decompress_page(
byte* buf, /*!< out: buffer from which to read; in aio byte* buf, /*!< out: buffer from which to read; in aio
this must be appropriately aligned */ this must be appropriately aligned */
ulong len, /*!< in: length of output buffer.*/ ulong len, /*!< in: length of output buffer.*/
ulint* write_size); /*!< in/out: Actual payload size of ulint* write_size, /*!< in/out: Actual payload size of
the compressed data. */ the compressed data. */
bool return_error=false);
/*!< in: true if only an error should
be produced when decompression fails.
By default this parameter is false. */
/****************************************************************//** /****************************************************************//**
Get space id from fil node Get space id from fil node
......
/***************************************************************************** /*****************************************************************************
Copyright (c) 1995, 2014, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1995, 2014, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2013, 2015, MariaDB Corporation. All Rights Reserved. Copyright (c) 2013, 2016, MariaDB Corporation. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
...@@ -37,6 +37,7 @@ Created 2011/12/19 ...@@ -37,6 +37,7 @@ Created 2011/12/19
#include "page0zip.h" #include "page0zip.h"
#include "trx0sys.h" #include "trx0sys.h"
#include "fil0crypt.h" #include "fil0crypt.h"
#include "fil0pagecompress.h"
#ifndef UNIV_HOTBACKUP #ifndef UNIV_HOTBACKUP
...@@ -500,6 +501,7 @@ buf_dblwr_process() ...@@ -500,6 +501,7 @@ buf_dblwr_process()
for (std::list<byte*>::iterator i = recv_dblwr.pages.begin(); for (std::list<byte*>::iterator i = recv_dblwr.pages.begin();
i != recv_dblwr.pages.end(); ++i, ++page_no_dblwr ) { i != recv_dblwr.pages.end(); ++i, ++page_no_dblwr ) {
bool is_compressed = false;
page = *i; page = *i;
page_no = mach_read_from_4(page + FIL_PAGE_OFFSET); page_no = mach_read_from_4(page + FIL_PAGE_OFFSET);
...@@ -533,6 +535,16 @@ buf_dblwr_process() ...@@ -533,6 +535,16 @@ buf_dblwr_process()
NULL, NULL,
0); 0);
/* Is page compressed ? */
is_compressed = fil_page_is_compressed_encrypted(read_buf) |
fil_page_is_compressed(read_buf);
/* If page was compressed, decompress it before we
check checksum. */
if (is_compressed) {
fil_decompress_page(NULL, read_buf, UNIV_PAGE_SIZE, NULL, true);
}
if (fil_space_verify_crypt_checksum(read_buf, zip_size)) { if (fil_space_verify_crypt_checksum(read_buf, zip_size)) {
/* page is encrypted and checksum is OK */ /* page is encrypted and checksum is OK */
} else if (buf_page_is_corrupted(true, read_buf, zip_size)) { } else if (buf_page_is_corrupted(true, read_buf, zip_size)) {
...@@ -546,6 +558,16 @@ buf_dblwr_process() ...@@ -546,6 +558,16 @@ buf_dblwr_process()
" the doublewrite buffer.\n", " the doublewrite buffer.\n",
(ulong) space_id, (ulong) page_no); (ulong) space_id, (ulong) page_no);
/* Is page compressed ? */
is_compressed = fil_page_is_compressed_encrypted(page) |
fil_page_is_compressed(page);
/* If page was compressed, decompress it before we
check checksum. */
if (is_compressed) {
fil_decompress_page(NULL, page, UNIV_PAGE_SIZE, NULL, true);
}
if (fil_space_verify_crypt_checksum(page, zip_size)) { if (fil_space_verify_crypt_checksum(page, zip_size)) {
/* the doublewrite buffer page is encrypted and OK */ /* the doublewrite buffer page is encrypted and OK */
} else if (buf_page_is_corrupted(true, } else if (buf_page_is_corrupted(true,
......
/***************************************************************************** /*****************************************************************************
Copyright (C) 2013, 2015, MariaDB Corporation. All Rights Reserved. Copyright (C) 2013, 2016, MariaDB Corporation. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
...@@ -446,8 +446,11 @@ fil_decompress_page( ...@@ -446,8 +446,11 @@ fil_decompress_page(
byte* buf, /*!< out: buffer from which to read; in aio byte* buf, /*!< out: buffer from which to read; in aio
this must be appropriately aligned */ this must be appropriately aligned */
ulong len, /*!< in: length of output buffer.*/ ulong len, /*!< in: length of output buffer.*/
ulint* write_size) /*!< in/out: Actual payload size of ulint* write_size, /*!< in/out: Actual payload size of
the compressed data. */ the compressed data. */
bool return_error) /*!< in: true if only an error should
be produced when decompression fails.
By default this parameter is false. */
{ {
int err = 0; int err = 0;
ulint actual_size = 0; ulint actual_size = 0;
...@@ -492,6 +495,9 @@ fil_decompress_page( ...@@ -492,6 +495,9 @@ fil_decompress_page(
mach_read_from_2(buf+FIL_PAGE_TYPE), len); mach_read_from_2(buf+FIL_PAGE_TYPE), len);
fflush(stderr); fflush(stderr);
if (return_error) {
goto error_return;
}
ut_error; ut_error;
} }
...@@ -511,6 +517,9 @@ fil_decompress_page( ...@@ -511,6 +517,9 @@ fil_decompress_page(
" actual size %lu compression %s.", " actual size %lu compression %s.",
actual_size, fil_get_compression_alg_name(compression_alg)); actual_size, fil_get_compression_alg_name(compression_alg));
fflush(stderr); fflush(stderr);
if (return_error) {
goto error_return;
}
ut_error; ut_error;
} }
...@@ -542,6 +551,9 @@ fil_decompress_page( ...@@ -542,6 +551,9 @@ fil_decompress_page(
fflush(stderr); fflush(stderr);
if (return_error) {
goto error_return;
}
ut_error; ut_error;
} }
break; break;
...@@ -558,6 +570,9 @@ fil_decompress_page( ...@@ -558,6 +570,9 @@ fil_decompress_page(
err, actual_size, len); err, actual_size, len);
fflush(stderr); fflush(stderr);
if (return_error) {
goto error_return;
}
ut_error; ut_error;
} }
break; break;
...@@ -576,6 +591,9 @@ fil_decompress_page( ...@@ -576,6 +591,9 @@ fil_decompress_page(
olen, actual_size, len); olen, actual_size, len);
fflush(stderr); fflush(stderr);
if (return_error) {
goto error_return;
}
ut_error; ut_error;
} }
break; break;
...@@ -609,6 +627,9 @@ fil_decompress_page( ...@@ -609,6 +627,9 @@ fil_decompress_page(
dst_pos, actual_size, len); dst_pos, actual_size, len);
fflush(stderr); fflush(stderr);
if (return_error) {
goto error_return;
}
ut_error; ut_error;
} }
...@@ -635,6 +656,9 @@ fil_decompress_page( ...@@ -635,6 +656,9 @@ fil_decompress_page(
dst_pos, actual_size, len, err); dst_pos, actual_size, len, err);
fflush(stderr); fflush(stderr);
if (return_error) {
goto error_return;
}
ut_error; ut_error;
} }
break; break;
...@@ -660,6 +684,9 @@ fil_decompress_page( ...@@ -660,6 +684,9 @@ fil_decompress_page(
olen, actual_size, len, (int)cstatus); olen, actual_size, len, (int)cstatus);
fflush(stderr); fflush(stderr);
if (return_error) {
goto error_return;
}
ut_error; ut_error;
} }
break; break;
...@@ -673,6 +700,9 @@ fil_decompress_page( ...@@ -673,6 +700,9 @@ fil_decompress_page(
,fil_get_compression_alg_name(compression_alg)); ,fil_get_compression_alg_name(compression_alg));
fflush(stderr); fflush(stderr);
if (return_error) {
goto error_return;
}
ut_error; ut_error;
break; break;
} }
...@@ -683,6 +713,7 @@ fil_decompress_page( ...@@ -683,6 +713,7 @@ fil_decompress_page(
really any other options. */ really any other options. */
memcpy(buf, in_buf, len); memcpy(buf, in_buf, len);
error_return:
// Need to free temporal buffer if no buffer was given // Need to free temporal buffer if no buffer was given
if (page_buf == NULL) { if (page_buf == NULL) {
ut_free(in_buf); ut_free(in_buf);
......
/***************************************************************************** /*****************************************************************************
Copyright (C) 2013, 2015 MariaDB Corporation. All Rights Reserved. Copyright (C) 2013, 2016 MariaDB Corporation. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
...@@ -117,8 +117,12 @@ fil_decompress_page( ...@@ -117,8 +117,12 @@ fil_decompress_page(
byte* buf, /*!< out: buffer from which to read; in aio byte* buf, /*!< out: buffer from which to read; in aio
this must be appropriately aligned */ this must be appropriately aligned */
ulong len, /*!< in: length of output buffer.*/ ulong len, /*!< in: length of output buffer.*/
ulint* write_size); /*!< in/out: Actual payload size of ulint* write_size, /*!< in/out: Actual payload size of
the compressed data. */ the compressed data. */
bool return_error=false);
/*!< in: true if only an error should
be produced when decompression fails.
By default this parameter is false. */
/****************************************************************//** /****************************************************************//**
Get space id from fil node Get space id from fil node
......
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