Oops, forgot to implement cache_abort_transaction(); every failing transaction
could have destroyed the BFS integrity... (just happened to me, that's how I noticed it) git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@12867 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
8380e999e7
commit
b3ef4fb41a
37
src/system/kernel/cache/block_cache.cpp
vendored
37
src/system/kernel/cache/block_cache.cpp
vendored
@ -393,18 +393,18 @@ get_writable_cached_block(block_cache *cache, off_t blockNumber, off_t base, off
|
||||
if (block->transaction != NULL && block->transaction->id != transactionID) {
|
||||
// ToDo: we have to wait here until the other transaction is done.
|
||||
// Maybe we should even panic, since we can't prevent any deadlocks.
|
||||
panic("block_cache_get_writable(): asked to get busy writable block\n");
|
||||
panic("get_writable_cached_block(): asked to get busy writable block (transaction %ld)\n", block->transaction->id);
|
||||
return NULL;
|
||||
}
|
||||
if (block->transaction == NULL && transactionID != -1) {
|
||||
// get new transaction
|
||||
cache_transaction *transaction = lookup_transaction(cache, transactionID);
|
||||
if (transaction == NULL) {
|
||||
panic("block_cache_get_writable(): invalid transaction %ld!\n", transactionID);
|
||||
panic("get_writable_cached_block(): invalid transaction %ld!\n", transactionID);
|
||||
return NULL;
|
||||
}
|
||||
if (!transaction->open) {
|
||||
panic("block_cache_get_writable(): transaction already done!\n");
|
||||
panic("get_writable_cached_block(): transaction already done!\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -554,11 +554,11 @@ cache_end_transaction(void *_cache, int32 id, transaction_notification_hook hook
|
||||
block_cache *cache = (block_cache *)_cache;
|
||||
BenaphoreLocker locker(cache);
|
||||
|
||||
TRACE(("cache_transaction_end(id = %ld)\n", id));
|
||||
TRACE(("cache_end_transaction(id = %ld)\n", id));
|
||||
|
||||
cache_transaction *transaction = lookup_transaction(cache, id);
|
||||
if (transaction == NULL) {
|
||||
panic("cache_transaction_end(): invalid transaction ID\n");
|
||||
panic("cache_end_transaction(): invalid transaction ID\n");
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
@ -601,6 +601,33 @@ cache_abort_transaction(void *_cache, int32 id)
|
||||
block_cache *cache = (block_cache *)_cache;
|
||||
BenaphoreLocker locker(cache);
|
||||
|
||||
TRACE(("cache_abort_transaction(id = %ld)\n", id));
|
||||
|
||||
cache_transaction *transaction = lookup_transaction(cache, id);
|
||||
if (transaction == NULL) {
|
||||
panic("cache_abort_transaction(): invalid transaction ID\n");
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
// iterate through all blocks and restore their original contents
|
||||
|
||||
cached_block *block = transaction->first_block, *next;
|
||||
for (; block != NULL; block = next) {
|
||||
next = block->transaction_next;
|
||||
|
||||
if (block->original != NULL) {
|
||||
TRACE(("cache_abort_transaction(id = %ld): restored contents of block %Ld\n",
|
||||
transaction->id, block->block_number));
|
||||
memcpy(block->data, block->original, cache->block_size);
|
||||
cache->allocator->Put(block->data);
|
||||
block->original = NULL;
|
||||
}
|
||||
|
||||
block->transaction_next = NULL;
|
||||
block->transaction = NULL;
|
||||
}
|
||||
|
||||
delete_transaction(cache, transaction);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user