Support for sync operations on an inode.
authorMichael Vrable <mvrable@cs.ucsd.edu>
Wed, 27 Jan 2010 22:13:43 +0000 (14:13 -0800)
committerMichael Vrable <mvrable@cs.ucsd.edu>
Wed, 27 Jan 2010 22:13:43 +0000 (14:13 -0800)
bluesky/bluesky.h
bluesky/cache.c
bluesky/inode.c
nfs3/nfs3.c

index 6ddf605..58ff29f 100644 (file)
@@ -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);
 
index 4fe4671..41348e2 100644 (file)
@@ -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
index 3c6fa3c..a568ae0 100644 (file)
@@ -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)
 {
index 72ec9cb..1b7e594 100644 (file)
@@ -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);
 }