Some changes to support asynchronous fetching of inodes.
authorMichael Vrable <mvrable@cs.ucsd.edu>
Tue, 26 Jan 2010 19:16:11 +0000 (11:16 -0800)
committerMichael Vrable <mvrable@cs.ucsd.edu>
Tue, 26 Jan 2010 19:16:11 +0000 (11:16 -0800)
Not 100% done yet, but almost there.

bluesky/bluesky-private.h
bluesky/bluesky.h
bluesky/init.c
bluesky/inode.c
bluesky/serialize.c
nfs3/nfsd.c

index d5e5d4f..95fc7d5 100644 (file)
@@ -27,7 +27,7 @@ BlueSkyFS *bluesky_new_fs(gchar *name);
 void bluesky_serialize_superblock(GString *out, BlueSkyFS *fs);
 BlueSkyFS *bluesky_deserialize_superblock(const gchar *buf);
 void bluesky_serialize_inode(GString *out, BlueSkyInode *inode);
-BlueSkyInode *bluesky_deserialize_inode(BlueSkyFS *fs, const gchar *buf);
+gboolean bluesky_deserialize_inode(BlueSkyInode *inode, const gchar *buf);
 
 /* Storage layer.  Requests can be performed asynchronously, so these objects
  * help keep track of operations in progress. */
index 6324ce2..6ddf605 100644 (file)
@@ -24,6 +24,11 @@ typedef struct {
 
     /* Write data in cache immediately after file is modified. */
     int writethrough_cache;
+
+    /* Can inodes be fetched asynchronously?  (Inode object is initially
+     * created in a pending state, and not unlocked until the data is actually
+     * available.) */
+    int async_inode_fetches;
 } BlueSkyOptions;
 
 extern BlueSkyOptions bluesky_options;
@@ -87,6 +92,10 @@ typedef enum {
     BLUESKY_SYMLINK = 5,
     BLUESKY_SOCKET = 6,
     BLUESKY_FIFO = 7,
+
+    /* Special types used only internally. */
+    BLUESKY_PENDING = 0,    /* Inode being loaded; type not yet determined */
+    BLUESKY_INVALID = -1,   /* Inode is invalid (failed to load) */
 } BlueSkyFileType;
 
 /* Filesystem state.  Each filesystem which is exported is represented by a
@@ -212,6 +221,7 @@ void bluesky_superblock_flush(BlueSkyFS *fs);
 int64_t bluesky_get_current_time();
 void bluesky_inode_update_ctime(BlueSkyInode *inode, gboolean update_mtime);
 uint64_t bluesky_fs_alloc_inode(BlueSkyFS *fs);
+void bluesky_init_inode(BlueSkyInode *i, BlueSkyFileType type);
 BlueSkyInode *bluesky_new_inode(uint64_t inum, BlueSkyFS *fs, BlueSkyFileType type);
 
 BlueSkyInode *bluesky_get_inode(BlueSkyFS *fs, uint64_t inum);
index 82cb3aa..69fbe62 100644 (file)
@@ -25,8 +25,9 @@ void bluesky_init(void)
     g_thread_init(NULL);
     bluesky_crypt_init();
 
-    bluesky_options.synchronous_stores = 1;
-    bluesky_options.writethrough_cache = 1;
+    bluesky_options.synchronous_stores = 0;
+    bluesky_options.writethrough_cache = 0;
+    bluesky_options.async_inode_fetches = 0;
 
     bluesky_store_init();
     bluesky_store_init_s3();
index 9b6160a..a052fb4 100644 (file)
@@ -138,17 +138,12 @@ uint64_t bluesky_fs_alloc_inode(BlueSkyFS *fs)
     return inum;
 }
 
-BlueSkyInode *bluesky_new_inode(uint64_t inum, BlueSkyFS *fs,
-                                BlueSkyFileType type)
+/* Perform type-specification initialization of an inode.  Normally performed
+ * in bluesky_new_inode, but can be separated if an inode is created first,
+ * then deserialized. */
+void bluesky_init_inode(BlueSkyInode *i, BlueSkyFileType type)
 {
-    BlueSkyInode *i = g_new0(BlueSkyInode, 1);
-
-    i->lock = g_mutex_new();
-    i->refcount = 1;
     i->type = type;
-    i->fs = fs;
-    i->inum = inum;
-    i->change_count = 1;
 
     switch (type) {
     case BLUESKY_REGULAR:
@@ -159,13 +154,22 @@ BlueSkyInode *bluesky_new_inode(uint64_t inum, BlueSkyFS *fs,
         i->dirhash = g_hash_table_new(g_str_hash, g_str_equal);
         i->dirhash_folded = g_hash_table_new(g_str_hash, g_str_equal);
         break;
-    case BLUESKY_BLOCK:
-    case BLUESKY_CHARACTER:
-    case BLUESKY_SYMLINK:
-    case BLUESKY_SOCKET:
-    case BLUESKY_FIFO:
+    default:
         break;
     }
+}
+
+BlueSkyInode *bluesky_new_inode(uint64_t inum, BlueSkyFS *fs,
+                                BlueSkyFileType type)
+{
+    BlueSkyInode *i = g_new0(BlueSkyInode, 1);
+
+    i->lock = g_mutex_new();
+    i->refcount = 1;
+    i->fs = fs;
+    i->inum = inum;
+    i->change_count = 1;
+    bluesky_init_inode(i, type);
 
     return i;
 }
@@ -257,10 +261,18 @@ void bluesky_inode_fetch(BlueSkyFS *fs, uint64_t inum)
     if (data == NULL)
         return;
 
-    BlueSkyInode *inode = bluesky_deserialize_inode(fs, data->data);
-    if (inode != NULL) {
-        bluesky_insert_inode(fs, inode);
+    BlueSkyInode *inode = bluesky_new_inode(inum, fs, BLUESKY_PENDING);
+    bluesky_inode_ref(inode);
+    g_mutex_lock(inode->lock);
+    bluesky_insert_inode(fs, inode);
+
+    if (!bluesky_deserialize_inode(inode, data->data)) {
+        g_hash_table_remove(fs->inodes, &inode->inum);
+        bluesky_inode_unref(inode);
     }
+
+    g_mutex_unlock(inode->lock);
+    bluesky_inode_unref(inode);
 }
 
 /* Synchronize filesystem superblock to stable storage. */
index e3abc14..5eb7c1d 100644 (file)
@@ -137,15 +137,21 @@ void bluesky_serialize_inode(GString *out, BlueSkyInode *inode)
     }
 }
 
-BlueSkyInode *bluesky_deserialize_inode(BlueSkyFS *fs, const gchar *buf)
+/* Deserialize an inode into an in-memory representation.  Returns a boolean
+ * indicating whether the deserialization was successful. */
+gboolean bluesky_deserialize_inode(BlueSkyInode *inode, const gchar *buf)
 {
+    g_print("Deserializing inode %lld...\n", (long long)inode->inum);
+
     struct serialized_inode *raw = (struct serialized_inode *)buf;
 
     if (GUINT64_FROM_LE(raw->signature) != INODE_MAGIC)
-        return NULL;
+        return FALSE;
 
-    BlueSkyInode *inode = bluesky_new_inode(GUINT64_FROM_LE(raw->inum),
-                                            fs, GUINT32_FROM_LE(raw->type));
+    if (inode->inum != GUINT64_FROM_LE(raw->inum))
+        return FALSE;
+
+    bluesky_init_inode(inode, GUINT32_FROM_LE(raw->type));
 
     inode->mode = GUINT32_FROM_LE(raw->mode);
     inode->uid = GUINT32_FROM_LE(raw->uid);
@@ -160,8 +166,6 @@ BlueSkyInode *bluesky_deserialize_inode(BlueSkyFS *fs, const gchar *buf)
 
     buf += sizeof(struct serialized_inode);
 
-    g_print("Deserializing inode %lld...\n", (long long)inode->inum);
-
     /* TODO: Bounds checking */
     switch (inode->type) {
     case BLUESKY_REGULAR:
@@ -219,5 +223,5 @@ BlueSkyInode *bluesky_deserialize_inode(BlueSkyFS *fs, const gchar *buf)
                   inode->type);
     }
 
-    return inode;
+    return TRUE;
 }
index f028459..e43f530 100644 (file)
@@ -32,7 +32,7 @@ int main(int argc, char *argv[])
     bluesky_init();
     register_rpc();
 
-    bluesky_options.synchronous_stores = 1;
+    bluesky_options.async_inode_fetches = 1;
 
     store = bluesky_store_new("s3");
     fs = bluesky_init_fs("export", store);