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:
@@ -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
|
status_t
|
||||||
Journal::_CheckRunArray(const run_array *array)
|
Journal::_CheckRunArray(const run_array *array)
|
||||||
{
|
{
|
||||||
@@ -402,27 +406,28 @@ Journal::_ReplayRunArray(int32 *_start)
|
|||||||
PRINT(("ReplayRunArray(start = %ld)\n", *_start));
|
PRINT(("ReplayRunArray(start = %ld)\n", *_start));
|
||||||
|
|
||||||
off_t logOffset = fVolume->ToBlock(fVolume->Log());
|
off_t logOffset = fVolume->ToBlock(fVolume->Log());
|
||||||
off_t blockNumber = *_start % fLogSize;
|
off_t firstBlockNumber = *_start % fLogSize;
|
||||||
int32 blockSize = fVolume->BlockSize();
|
|
||||||
int32 count = 1;
|
|
||||||
|
|
||||||
CachedBlock cachedArray(fVolume);
|
CachedBlock cachedArray(fVolume);
|
||||||
|
|
||||||
const run_array *array = (const run_array *)cachedArray.SetTo(logOffset
|
const run_array *array = (const run_array *)cachedArray.SetTo(logOffset
|
||||||
+ blockNumber);
|
+ firstBlockNumber);
|
||||||
if (array == NULL)
|
if (array == NULL)
|
||||||
return B_IO_ERROR;
|
return B_IO_ERROR;
|
||||||
|
|
||||||
if (_CheckRunArray(array) < B_OK)
|
if (_CheckRunArray(array) < B_OK)
|
||||||
return B_BAD_DATA;
|
return B_BAD_DATA;
|
||||||
|
|
||||||
blockNumber = (blockNumber + 1) % fLogSize;
|
// First pass: check integrity of the blocks in the run array
|
||||||
|
|
||||||
CachedBlock cached(fVolume);
|
CachedBlock cached(fVolume);
|
||||||
|
|
||||||
|
firstBlockNumber = (firstBlockNumber + 1) % fLogSize;
|
||||||
|
off_t blockNumber = firstBlockNumber;
|
||||||
|
int32 blockSize = fVolume->BlockSize();
|
||||||
|
|
||||||
for (int32 index = 0; index < array->CountRuns(); index++) {
|
for (int32 index = 0; index < array->CountRuns(); index++) {
|
||||||
const block_run &run = array->RunAt(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);
|
off_t offset = fVolume->ToOffset(run);
|
||||||
for (int32 i = 0; i < run.Length(); i++) {
|
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,
|
ssize_t written = write_pos(fVolume->Device(), offset, data,
|
||||||
blockSize);
|
blockSize);
|
||||||
if (written != blockSize)
|
if (written != blockSize)
|
||||||
|
|||||||
Reference in New Issue
Block a user