From d514caf49faff9295d0e497d3b6b8856fe83f8d0 Mon Sep 17 00:00:00 2001 From: Michael Vrable Date: Tue, 26 Jan 2010 11:16:11 -0800 Subject: [PATCH] Some changes to support asynchronous fetching of inodes. Not 100% done yet, but almost there. --- bluesky/bluesky-private.h | 2 +- bluesky/bluesky.h | 10 +++++++++ bluesky/init.c | 5 +++-- bluesky/inode.c | 46 ++++++++++++++++++++++++--------------- bluesky/serialize.c | 18 +++++++++------ nfs3/nfsd.c | 2 +- 6 files changed, 55 insertions(+), 28 deletions(-) diff --git a/bluesky/bluesky-private.h b/bluesky/bluesky-private.h index d5e5d4f..95fc7d5 100644 --- a/bluesky/bluesky-private.h +++ b/bluesky/bluesky-private.h @@ -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. */ diff --git a/bluesky/bluesky.h b/bluesky/bluesky.h index 6324ce2..6ddf605 100644 --- a/bluesky/bluesky.h +++ b/bluesky/bluesky.h @@ -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); diff --git a/bluesky/init.c b/bluesky/init.c index 82cb3aa..69fbe62 100644 --- a/bluesky/init.c +++ b/bluesky/init.c @@ -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(); diff --git a/bluesky/inode.c b/bluesky/inode.c index 9b6160a..a052fb4 100644 --- a/bluesky/inode.c +++ b/bluesky/inode.c @@ -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. */ diff --git a/bluesky/serialize.c b/bluesky/serialize.c index e3abc14..5eb7c1d 100644 --- a/bluesky/serialize.c +++ b/bluesky/serialize.c @@ -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; } diff --git a/nfs3/nfsd.c b/nfs3/nfsd.c index f028459..e43f530 100644 --- a/nfs3/nfsd.c +++ b/nfs3/nfsd.c @@ -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); -- 2.20.1