* Brought the fs_shell block_cache implementation up to date, and incorporate
the fixes applied to the kernel version of it (most notably a correctly working block_cache_discard(), and cache_detach_sub_transaction()). Also switched to the new notification functions, even though it still works synchronously in the fs_shell. * Minor cleanup. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@28617 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
+57
-57
@@ -471,6 +471,61 @@ get_next_pending_event(cache_notification* notification, int32* _event)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
flush_pending_notifications(block_cache* cache)
|
||||||
|
{
|
||||||
|
ASSERT_LOCKED_MUTEX(&sCachesLock);
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
MutexLocker locker(sNotificationsLock);
|
||||||
|
|
||||||
|
cache_notification* notification = cache->pending_notifications.Head();
|
||||||
|
if (notification == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
bool deleteAfterEvent = false;
|
||||||
|
int32 event = -1;
|
||||||
|
if (!get_next_pending_event(notification, &event)) {
|
||||||
|
// remove the notification if this was the last pending event
|
||||||
|
cache->pending_notifications.Remove(notification);
|
||||||
|
deleteAfterEvent = notification->delete_after_event;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event >= 0) {
|
||||||
|
// Notify listener, we need to copy the notification, as it might
|
||||||
|
// be removed when we unlock the list.
|
||||||
|
cache_notification copy = *notification;
|
||||||
|
locker.Unlock();
|
||||||
|
|
||||||
|
copy.hook(copy.transaction_id, event, copy.data);
|
||||||
|
|
||||||
|
locker.Lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (deleteAfterEvent)
|
||||||
|
delete notification;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! Flushes all pending notifications by calling the appropriate hook
|
||||||
|
functions.
|
||||||
|
Must not be called with a cache lock held.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
flush_pending_notifications()
|
||||||
|
{
|
||||||
|
MutexLocker _(sCachesLock);
|
||||||
|
|
||||||
|
DoublyLinkedList<block_cache>::Iterator iterator = sCaches.GetIterator();
|
||||||
|
while (iterator.HasNext()) {
|
||||||
|
block_cache* cache = iterator.Next();
|
||||||
|
|
||||||
|
flush_pending_notifications(cache);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! Initializes the \a notification as specified. */
|
/*! Initializes the \a notification as specified. */
|
||||||
static void
|
static void
|
||||||
set_notification(cache_transaction* transaction,
|
set_notification(cache_transaction* transaction,
|
||||||
@@ -563,61 +618,6 @@ notify_transaction_listeners(block_cache* cache, cache_transaction* transaction,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
flush_pending_notifications(block_cache* cache)
|
|
||||||
{
|
|
||||||
ASSERT_LOCKED_MUTEX(&sCachesLock);
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
MutexLocker locker(sNotificationsLock);
|
|
||||||
|
|
||||||
cache_notification* notification = cache->pending_notifications.Head();
|
|
||||||
if (notification == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
bool deleteAfterEvent = false;
|
|
||||||
int32 event = -1;
|
|
||||||
if (!get_next_pending_event(notification, &event)) {
|
|
||||||
// remove the notification if this was the last pending event
|
|
||||||
cache->pending_notifications.Remove(notification);
|
|
||||||
deleteAfterEvent = notification->delete_after_event;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event >= 0) {
|
|
||||||
// Notify listener, we need to copy the notification, as it might
|
|
||||||
// be removed when we unlock the list.
|
|
||||||
cache_notification copy = *notification;
|
|
||||||
locker.Unlock();
|
|
||||||
|
|
||||||
copy.hook(copy.transaction_id, event, copy.data);
|
|
||||||
|
|
||||||
locker.Lock();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (deleteAfterEvent)
|
|
||||||
delete notification;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*! Flushes all pending notifications by calling the appropriate hook
|
|
||||||
functions.
|
|
||||||
Must not be called with a cache lock held.
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
flush_pending_notifications()
|
|
||||||
{
|
|
||||||
MutexLocker _(sCachesLock);
|
|
||||||
|
|
||||||
DoublyLinkedList<block_cache>::Iterator iterator = sCaches.GetIterator();
|
|
||||||
while (iterator.HasNext()) {
|
|
||||||
block_cache* cache = iterator.Next();
|
|
||||||
|
|
||||||
flush_pending_notifications(cache);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*! Removes and deletes all listeners that are still monitoring this
|
/*! Removes and deletes all listeners that are still monitoring this
|
||||||
transaction.
|
transaction.
|
||||||
*/
|
*/
|
||||||
@@ -1218,7 +1218,7 @@ get_writable_cached_block(block_cache* cache, off_t blockNumber, off_t base,
|
|||||||
cache_transaction* transaction = block->transaction;
|
cache_transaction* transaction = block->transaction;
|
||||||
|
|
||||||
if (transaction != NULL && transaction->id != transactionID) {
|
if (transaction != NULL && transaction->id != transactionID) {
|
||||||
// ToDo: we have to wait here until the other transaction is done.
|
// TODO: we have to wait here until the other transaction is done.
|
||||||
// Maybe we should even panic, since we can't prevent any deadlocks.
|
// Maybe we should even panic, since we can't prevent any deadlocks.
|
||||||
panic("get_writable_cached_block(): asked to get busy writable block (transaction %ld)\n", block->transaction->id);
|
panic("get_writable_cached_block(): asked to get busy writable block (transaction %ld)\n", block->transaction->id);
|
||||||
put_cached_block(cache, block);
|
put_cached_block(cache, block);
|
||||||
@@ -2594,7 +2594,7 @@ block_cache_make_writable(void* _cache, off_t blockNumber, int32 transaction)
|
|||||||
if (cache->read_only)
|
if (cache->read_only)
|
||||||
panic("tried to make block writable on a read-only cache!");
|
panic("tried to make block writable on a read-only cache!");
|
||||||
|
|
||||||
// ToDo: this can be done better!
|
// TODO: this can be done better!
|
||||||
void* block = get_writable_cached_block(cache, blockNumber,
|
void* block = get_writable_cached_block(cache, blockNumber,
|
||||||
blockNumber, 1, transaction, false);
|
blockNumber, 1, transaction, false);
|
||||||
if (block != NULL) {
|
if (block != NULL) {
|
||||||
|
|||||||
+560
-285
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user