#At file:///home/os136802/mysql/develop/repo/falcon-bug45297/ based on revid:kevin.lewis@stripped
2739 Olav Sandstaa 2009-06-22
Fix for Bug#44744 "Recovery stage 3: segfault in RecoveryObjects::findRecoveryObject" and Bug#45297 "Crash
during recovery due to pread reading beyond EOF"
These crashes was both caused by an inconsistency between the Record Locator Page and the Data page. The record
locator page claimed that the record was stored in a data page while the record was not present in the data page.
This situation can happen during recovery if the Record Locator page has been written to disk while the
data page has not been written to disk when a server crash occurs. The recovery crash happened when the code
had locate the record by a lookup in the Record Locator page and then called DataPage::updateRecord() where the
record was not present. In the crash situation the record expected to be located on the same line number as
the maxLine of the data page. This lead to reading "garbage" from the data page and resulted in an invalid
overflow page number.
This patch fixes this problem by handling that DataPage::updateRecord and DataPage::deleteLine handles to
be called also when the record is not present in the data page. In this situation both the functions will
just ignore the call. DataPage::updateRecord() will return that there was not room for the record. This will
result in the inconsistency between the data page and the Record Locator page being resolved since
the "failing" call to DataPage::updateRecord() will trigger removal of the record's entry in the Record Locator
page - and the record will be inserted somewhere else.
@ storage/falcon/DataPage.cpp
During recovery: extend DataPage::updateRecord() and DataPage::deleteLine() so that they handle to
be called with a line number that is equal or larger than the current maxLine. If this is the case
the call will just be ignored.
modified:
storage/falcon/DataPage.cpp
=== modified file 'storage/falcon/DataPage.cpp'
--- a/storage/falcon/DataPage.cpp 2009-06-12 13:34:24 +0000
+++ b/storage/falcon/DataPage.cpp 2009-06-22 12:23:12 +0000
@@ -43,7 +43,18 @@ static const char THIS_FILE[]=__FILE__;
int DataPage::updateRecord(Section *section, int lineNumber, Stream *stream, TransId transId, bool earlyWrite)
{
- ASSERT(lineNumber < maxLine);
+ /* During recovery we might be asked to update a record that does
+ not exist on the page. This situation can happen when the
+ Record Locator page was written to disk while this data page
+ was not written to disk before the server crash. We handle this
+ by returning that there is no rom for this record on this
+ page. */
+
+ if (lineNumber >= maxLine)
+ {
+ ASSERT(section->dbb->serialLog->recovering);
+ return 0;
+ }
Dbb *dbb = section->dbb;
LineIndex *index = lineIndex + lineNumber;
@@ -295,6 +306,17 @@ int DataPage::storeRecord(Dbb *dbb, Bdb
int DataPage::deleteLine (Dbb *dbb, int line, TransId transId)
{
+ /* During recovery we might be asked to delete a record that does
+ not exists on the page. This situation can happen when the
+ Record Locator page was written to disk while this data
+ page was not written to disk before the server crashed. */
+
+ if (line >= maxLine)
+ {
+ ASSERT(dbb->serialLog->recovering);
+ return 0;
+ }
+
// Handle overflow pages first
if (lineIndex [line].length < 0)
Attachment: [text/bzr-bundle] bzr/olav@sun.com-20090622122312-3wp689bpd17avscj.bundle