Olav,
Simple and elegant solution. OK to push.
Olav Sandstaa wrote:
> #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)
>
>
>
> ------------------------------------------------------------------------
>
>