X-Git-Url: http://git.vrable.net/?a=blobdiff_plain;f=bluesky%2Fcache.c;h=912c5fdff743b34638f3c369dc2e86a1b67555aa;hb=ffadf57d27b07d5ba8c0de11649ff08e999f53f4;hp=f953a6455a0736ee6cac142038a270404cbb25f7;hpb=0ef7fc934daee6ded318e3d52023521b758b295e;p=bluesky.git diff --git a/bluesky/cache.c b/bluesky/cache.c index f953a64..912c5fd 100644 --- a/bluesky/cache.c +++ b/bluesky/cache.c @@ -13,8 +13,29 @@ #include "bluesky-private.h" +#define WRITEBACK_DELAY (5 * 1000000) + /* Filesystem caching and cache coherency. */ +static void writeback_complete(gpointer a, gpointer i) +{ + BlueSkyInode *inode = (BlueSkyInode *)i; + + g_log("bluesky/flushd", G_LOG_LEVEL_DEBUG, + "Writeback for inode %"PRIu64" complete", inode->inum); + + g_mutex_lock(inode->lock); + + inode->change_commit = inode->change_pending; + if (inode->change_count == inode->change_commit) { + /* If inode is no longer dirty... */ + inode->change_time = 0; + inode->change_pending = 0; + } + + g_mutex_unlock(inode->lock); +} + static void flushd_inode(gpointer key, gpointer value, gpointer user_data) { BlueSkyFS *fs = (BlueSkyFS *)user_data; @@ -24,12 +45,34 @@ static void flushd_inode(gpointer key, gpointer value, gpointer user_data) if (inode->change_count == inode->change_commit) return; + if (inode->change_pending) { + /* Waiting for an earlier writeback to finish, so don't start a new + * writeback yet. */ + return; + } + + uint64_t elapsed = bluesky_get_current_time() - inode->change_time; + if (elapsed < WRITEBACK_DELAY) { + /* Give a bit more time before starting writeback. */ + return; + } + + inode->change_pending = inode->change_count; + g_log("bluesky/flushd", G_LOG_LEVEL_DEBUG, "Starting flush of inode %"PRIu64, inode->inum); - if (inode->type == BLUESKY_REGULAR) - bluesky_file_flush(inode); - bluesky_inode_flush(fs, inode); + /* Create a store barrier. All operations part of the writeback will be + * added to this barrier, so when the barrier completes we know that the + * writeback is finished. */ + BlueSkyStoreAsync *barrier = bluesky_store_async_new(fs->store); + barrier->op = STORE_OP_BARRIER; + + bluesky_inode_start_sync(inode, barrier); + + bluesky_store_async_add_notifier(barrier, writeback_complete, inode); + bluesky_store_async_submit(barrier); + bluesky_store_async_unref(barrier); } /* Scan through the cache for dirty data and start flushing it to stable