Divided the _ReplayRunArray() method into two passes: first, the integrity

of the blocks in the log entry will be checked, and only if this passed,
all log entries are written back together; if the whole run array contained
bad data, it's no longer written to disk at all if it's detectable.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@24402 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2008-03-15 16:35:10 +00:00
parent f426071223
commit 772506f830

View File

@ -367,6 +367,10 @@ Journal::InitCheck()
}
/*! \brief Does a very basic consistency check of the run array.
It will check the maximum run count as well as if all of the runs fall
within a the volume.
*/
status_t
Journal::_CheckRunArray(const run_array *array)
{
@ -402,27 +406,28 @@ Journal::_ReplayRunArray(int32 *_start)
PRINT(("ReplayRunArray(start = %ld)\n", *_start));
off_t logOffset = fVolume->ToBlock(fVolume->Log());
off_t blockNumber = *_start % fLogSize;
int32 blockSize = fVolume->BlockSize();
int32 count = 1;
off_t firstBlockNumber = *_start % fLogSize;
CachedBlock cachedArray(fVolume);
const run_array *array = (const run_array *)cachedArray.SetTo(logOffset
+ blockNumber);
+ firstBlockNumber);
if (array == NULL)
return B_IO_ERROR;
if (_CheckRunArray(array) < B_OK)
return B_BAD_DATA;
blockNumber = (blockNumber + 1) % fLogSize;
// First pass: check integrity of the blocks in the run array
CachedBlock cached(fVolume);
firstBlockNumber = (firstBlockNumber + 1) % fLogSize;
off_t blockNumber = firstBlockNumber;
int32 blockSize = fVolume->BlockSize();
for (int32 index = 0; index < array->CountRuns(); index++) {
const block_run &run = array->RunAt(index);
INFORM(("replay block run %u:%u:%u in log at %Ld!\n",
(int)run.AllocationGroup(), run.Start(), run.Length(), blockNumber));
off_t offset = fVolume->ToOffset(run);
for (int32 i = 0; i < run.Length(); i++) {
@ -441,6 +446,27 @@ Journal::_ReplayRunArray(int32 *_start)
}
}
blockNumber = (blockNumber + 1) % fLogSize;
offset += blockSize;
}
}
// Second pass: write back its blocks
blockNumber = firstBlockNumber;
int32 count = 1;
for (int32 index = 0; index < array->CountRuns(); index++) {
const block_run &run = array->RunAt(index);
INFORM(("replay block run %u:%u:%u in log at %Ld!\n",
(int)run.AllocationGroup(), run.Start(), run.Length(), blockNumber));
off_t offset = fVolume->ToOffset(run);
for (int32 i = 0; i < run.Length(); i++) {
const uint8 *data = cached.SetTo(logOffset + blockNumber);
if (data == NULL)
RETURN_ERROR(B_IO_ERROR);
ssize_t written = write_pos(fVolume->Device(), offset, data,
blockSize);
if (written != blockSize)