X-Git-Url: http://git.vrable.net/?a=blobdiff_plain;f=bluesky%2Finode.c;h=42ae708399f1fb5506e87f54261e31a97382d588;hb=388030970805a70cb4fad34ade5e3de7a3607a57;hp=7560010d3eaded3106c514b793d10aced0e3fa18;hpb=260a45ace7787128b9b9748fcb9ffd003af00a5d;p=bluesky.git diff --git a/bluesky/inode.c b/bluesky/inode.c index 7560010..42ae708 100644 --- a/bluesky/inode.c +++ b/bluesky/inode.c @@ -14,6 +14,8 @@ #include "bluesky-private.h" +static void inode_fetch_task(gpointer a, gpointer b); + /* Core filesystem. Different proxies, such as the NFSv3 one, interface to * this, but the core actually tracks the data which is stored. So far we just * implement an in-memory filesystem, but eventually this will be state which @@ -93,44 +95,46 @@ BlueSkyFS *bluesky_new_fs(gchar *name) fs->log_state = g_new0(BlueSkyCloudLogState, 1); fs->log_state->data = g_string_new(""); + fs->log_state->latest_cleaner_seq_seen = -1; + fs->log_state->uploads_pending_lock = g_mutex_new(); + fs->log_state->uploads_pending_cond = g_cond_new(); + + bluesky_cloudlog_threads_init(fs); + fs->inode_fetch_thread_pool = g_thread_pool_new(inode_fetch_task, NULL, + bluesky_max_threads, + FALSE, NULL); return fs; } -BlueSkyFS *bluesky_init_fs(gchar *name, BlueSkyStore *store) +BlueSkyFS *bluesky_init_fs(gchar *name, BlueSkyStore *store, + const gchar *master_key) { - BlueSkyRCStr *data = bluesky_store_get(store, "superblock"); - if (data != NULL) { - BlueSkyFS *fs = bluesky_deserialize_superblock(data->data); - if (fs != NULL) { - fs->store = store; - fs->log = bluesky_log_new("journal"); - fs->log->fs = fs; - g_print("Loaded filesystem superblock\n"); - g_free(fs->name); - fs->name = g_strdup(name); - return fs; - } - bluesky_string_unref(data); - } - - g_print("Initializing fresh filesystem\n"); BlueSkyFS *fs = bluesky_new_fs(name); + fs->master_key = g_strdup(master_key); + fs->keys = g_new(BlueSkyCryptKeys, 1); + bluesky_crypt_derive_keys(fs->keys, master_key); fs->store = store; fs->log = bluesky_log_new("journal"); fs->log->fs = fs; - BlueSkyInode *root = bluesky_new_inode(BLUESKY_ROOT_INUM, fs, - BLUESKY_DIRECTORY); - root->nlink = 1; - root->mode = 0755; - bluesky_insert_inode(fs, root); - bluesky_inode_update_ctime(root, TRUE); - - bluesky_replay(fs); + if (bluesky_checkpoint_load(fs)) { + g_print("Filesystem checkpoint loaded, starting journal replay...\n"); + bluesky_replay(fs); + g_print("Journal replay complete, filesystem ready.\n"); + } else { + /* Initialize a fresh filesystem */ + g_print("Initializing new filesystem...\n"); + BlueSkyInode *root = bluesky_new_inode(BLUESKY_ROOT_INUM, fs, + BLUESKY_DIRECTORY); + root->nlink = 1; + root->mode = 0755; + bluesky_insert_inode(fs, root); + bluesky_inode_update_ctime(root, TRUE); + bluesky_inode_do_sync(root); + } - bluesky_inode_do_sync(root); - bluesky_superblock_flush(fs); + bluesky_cleaner_thread_launch(fs); return fs; } @@ -227,8 +231,6 @@ uint64_t bluesky_fs_alloc_inode(BlueSkyFS *fs) inum = fs->next_inum; fs->next_inum++; - bluesky_superblock_flush(fs); - return inum; } @@ -268,6 +270,30 @@ BlueSkyInode *bluesky_new_inode(uint64_t inum, BlueSkyFS *fs, return i; } +/* Issue a prefetch hint for an inode. This signals that the inode may be + * needed soon. Does not return any useful data. */ +void bluesky_inode_prefetch(BlueSkyFS *fs, uint64_t inum) +{ + BlueSkyInode *inode = NULL; + + g_mutex_lock(fs->lock); + inode = (BlueSkyInode *)g_hash_table_lookup(fs->inodes, &inum); + + if (inode != NULL) { + /* Inode is already available, no need for any prefetching... */ + g_mutex_unlock(fs->lock); + return; + } + + InodeMapEntry *entry = bluesky_inode_map_lookup(fs->inode_map, inum, 0); + if (entry != NULL) { + bluesky_cloudlog_prefetch(entry->item); + } + + g_mutex_unlock(fs->lock); + return; +} + /* Retrieve an inode from the filesystem. Eventually this will be a cache and * so we might need to go fetch the inode from elsewhere; for now all * filesystem state is stored here. inode is returned with a reference held @@ -358,26 +384,21 @@ void bluesky_inode_do_sync(BlueSkyInode *inode) } } -static void complete_inode_fetch(BlueSkyStoreAsync *async, BlueSkyInode *inode) +static void inode_fetch_task(gpointer a, gpointer b) { - if (bluesky_verbose) { - g_log("bluesky/inode", G_LOG_LEVEL_DEBUG, - "Completing fetch of inode %"PRIu64"...", inode->inum); - } + BlueSkyInode *inode = (BlueSkyInode *)a; - if (async->result != 0 || FALSE) - { - if (bluesky_verbose) { - g_log("bluesky/inode", G_LOG_LEVEL_DEBUG, - " failed to load inode, cleaning up"); - } - g_mutex_lock(inode->fs->lock); - g_hash_table_remove(inode->fs->inodes, &inode->inum); - bluesky_list_unlink(&inode->fs->accessed_list, inode->accessed_list); - inode->accessed_list = NULL; - g_mutex_unlock(inode->fs->lock); - bluesky_inode_unref(inode); - } + bluesky_profile_set((BlueSkyProfile *)inode->private_data); + + BlueSkyCloudLog *item = inode->committed_item; + inode->committed_item = NULL; + g_print("Completing fetch of inode %"PRIu64"...\n", inode->inum); + + g_mutex_lock(item->lock); + bluesky_cloudlog_fetch(item); + if (!bluesky_deserialize_inode(inode, item)) + g_print("Error deserializing inode %"PRIu64"\n", inode->inum); + g_mutex_unlock(item->lock); inode->access_time = bluesky_get_current_time(); g_mutex_lock(inode->fs->lock); @@ -386,6 +407,7 @@ static void complete_inode_fetch(BlueSkyStoreAsync *async, BlueSkyInode *inode) g_mutex_unlock(inode->fs->lock); g_mutex_unlock(inode->lock); + bluesky_cloudlog_unref(item); bluesky_inode_unref(inode); } @@ -396,44 +418,23 @@ static void complete_inode_fetch(BlueSkyStoreAsync *async, BlueSkyInode *inode) * fs lock must be held. */ void bluesky_inode_fetch(BlueSkyFS *fs, uint64_t inum) { - char key[64]; - sprintf(key, "inode-%016"PRIx64, inum); + InodeMapEntry *entry = bluesky_inode_map_lookup(fs->inode_map, inum, 0); + if (entry == NULL) + return; + + /* Non-portable behavior: We take the inode lock here, and release it in + * the fetching thread. This works with the default Linux pthreads + * implementation but is not guaranteed. */ BlueSkyInode *inode = bluesky_new_inode(inum, fs, BLUESKY_PENDING); inode->change_count = 0; bluesky_inode_ref(inode); // Extra ref held by fetching process g_mutex_lock(inode->lock); - bluesky_insert_inode(fs, inode); - - BlueSkyStoreAsync *async = bluesky_store_async_new(fs->store); - async->op = STORE_OP_GET; - async->key = g_strdup(key); - - bluesky_store_async_add_notifier(async, (GFunc)complete_inode_fetch, inode); - bluesky_store_async_submit(async); - - if (bluesky_options.sync_inode_fetches) { - bluesky_store_async_wait(async); - } - bluesky_store_async_unref(async); -} + inode->committed_item = entry->item; + bluesky_cloudlog_ref(entry->item); + bluesky_insert_inode(fs, inode); -/* Synchronize filesystem superblock to stable storage. */ -void bluesky_superblock_flush(BlueSkyFS *fs) -{ -#if 0 - GString *buf = g_string_new(""); - bluesky_serialize_superblock(buf, fs); - BlueSkyRCStr *data = bluesky_string_new_from_gstring(buf); - - BlueSkyStoreAsync *async = bluesky_store_async_new(fs->store); - async->op = STORE_OP_PUT; - async->key = g_strdup("superblock"); - async->data = data; - bluesky_store_async_submit(async); - bluesky_store_async_unref(async); - - //bluesky_store_sync(fs->store); -#endif + inode->private_data = bluesky_profile_get(); + g_thread_pool_push(fs->inode_fetch_thread_pool, inode, NULL); }