From: Michael Vrable Date: Wed, 27 Jan 2010 22:13:43 +0000 (-0800) Subject: Support for sync operations on an inode. X-Git-Url: http://git.vrable.net/?p=bluesky.git;a=commitdiff_plain;h=3175b881ccd14a39c4a206147cc99ecc80de3412 Support for sync operations on an inode. --- diff --git a/bluesky/bluesky.h b/bluesky/bluesky.h index 6ddf605..58ff29f 100644 --- a/bluesky/bluesky.h +++ b/bluesky/bluesky.h @@ -252,6 +252,7 @@ gint bluesky_dirent_compare(gconstpointer a, gconstpointer b, gpointer unused); void bluesky_flushd_invoke(BlueSkyFS *fs); +void bluesky_inode_do_sync(BlueSkyInode *inode); void bluesky_debug_dump(BlueSkyFS *fs); diff --git a/bluesky/cache.c b/bluesky/cache.c index 4fe4671..41348e2 100644 --- a/bluesky/cache.c +++ b/bluesky/cache.c @@ -42,18 +42,24 @@ static void flushd_inode(gpointer key, gpointer value, gpointer user_data) BlueSkyInode *inode = (BlueSkyInode *)value; - if (inode->change_count == inode->change_commit) + g_mutex_lock(inode->lock); + + if (inode->change_count == inode->change_commit) { + g_mutex_unlock(inode->lock); return; + } if (inode->change_pending) { /* Waiting for an earlier writeback to finish, so don't start a new * writeback yet. */ + g_mutex_unlock(inode->lock); return; } uint64_t elapsed = bluesky_get_current_time() - inode->change_time; if (elapsed < WRITEBACK_DELAY) { /* Give a bit more time before starting writeback. */ + g_mutex_unlock(inode->lock); return; } @@ -73,6 +79,8 @@ static void flushd_inode(gpointer key, gpointer value, gpointer user_data) bluesky_store_async_add_notifier(barrier, writeback_complete, inode); bluesky_store_async_submit(barrier); bluesky_store_async_unref(barrier); + + g_mutex_unlock(inode->lock); } /* Scan through the cache for dirty data and start flushing it to stable diff --git a/bluesky/inode.c b/bluesky/inode.c index 3c6fa3c..a568ae0 100644 --- a/bluesky/inode.c +++ b/bluesky/inode.c @@ -252,6 +252,23 @@ void bluesky_inode_start_sync(BlueSkyInode *inode, BlueSkyStoreAsync *barrier) bluesky_store_async_unref(async); } +/* Write back an inode and all associated data and wait for completion. Inode + * should already be locked. */ +void bluesky_inode_do_sync(BlueSkyInode *inode) +{ + BlueSkyStoreAsync *barrier = bluesky_store_async_new(inode->fs->store); + barrier->op = STORE_OP_BARRIER; + + g_log("bluesky/inode", G_LOG_LEVEL_DEBUG, + "Synchronous writeback for inode %"PRIu64"...", inode->inum); + bluesky_inode_start_sync(inode, barrier); + bluesky_store_async_submit(barrier); + bluesky_store_async_wait(barrier); + bluesky_store_async_unref(barrier); + g_log("bluesky/inode", G_LOG_LEVEL_DEBUG, + "Writeback for inode %"PRIu64" complete", inode->inum); +} + /* Fetch an inode from stable storage. */ void bluesky_inode_fetch(BlueSkyFS *fs, uint64_t inum) { diff --git a/nfs3/nfs3.c b/nfs3/nfs3.c index 72ec9cb..1b7e594 100644 --- a/nfs3/nfs3.c +++ b/nfs3/nfs3.c @@ -1074,5 +1074,22 @@ void nfsproc3_commit_3_svc(commit3args *argp, RPCRequest *req) result.status = NFS3ERR_NOTSUPP; + BlueSkyInode *inode = lookup_fh(req, &argp->file); + if (inode == NULL) { + result.status = NFS3ERR_STALE; + async_rpc_send_reply(req, &result); + return; + } + + g_mutex_lock(inode->lock); + encode_pre_wcc(&result.commit3res_u.resok.file_wcc, inode); + + bluesky_inode_do_sync(inode); + + result.commit3res_u.resok.file_wcc.after.present = TRUE; + encode_fattr3(&result.commit3res_u.resok.file_wcc.after.post_op_attr_u.attributes, inode); + + g_mutex_unlock(inode->lock); + async_rpc_send_reply(req, &result); }