X-Git-Url: http://git.vrable.net/?a=blobdiff_plain;f=bluesky%2Finode.c;h=e11bfeb3c0a8b898387f295ffdb4e146b9db93b4;hb=6955b27db8185d222adb07e57d207f7f421037e6;hp=9878559d9f35235a7d950108bfac325a525649e0;hpb=337e1b04c921c92697b74aed630343c86fabfcbd;p=bluesky.git diff --git a/bluesky/inode.c b/bluesky/inode.c index 9878559..e11bfeb 100644 --- a/bluesky/inode.c +++ b/bluesky/inode.c @@ -99,38 +99,26 @@ BlueSkyFS *bluesky_new_fs(gchar *name) BlueSkyFS *bluesky_init_fs(gchar *name, BlueSkyStore *store) { - 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->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); - - bluesky_inode_do_sync(root); - bluesky_superblock_flush(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); + } return fs; } @@ -141,6 +129,50 @@ void bluesky_inode_ref(BlueSkyInode *inode) g_atomic_int_inc(&inode->refcount); } +/* Free most of the resources used by an inode structure, but do not free the + * inode itself. Can be used if the inode data will be reloaded from + * serialized form to clear out old information first. */ +void bluesky_inode_free_resources(BlueSkyInode *inode) +{ + switch (inode->type) { + case BLUESKY_REGULAR: + if (inode->blocks != NULL) { + for (int i = 0; i < inode->blocks->len; i++) { + BlueSkyBlock *b = &g_array_index(inode->blocks, + BlueSkyBlock, i); + if (b->type == BLUESKY_BLOCK_DIRTY) { + g_error("Deleting an inode with dirty file data!"); + } + bluesky_cloudlog_unref(b->ref); + bluesky_string_unref(b->dirty); + } + g_array_unref(inode->blocks); + inode->blocks = NULL; + } + break; + + case BLUESKY_DIRECTORY: + if (inode->dirhash != NULL) + g_hash_table_destroy(inode->dirhash); + inode->dirhash = NULL; + if (inode->dirhash_folded != NULL) + g_hash_table_destroy(inode->dirhash_folded); + inode->dirhash_folded = NULL; + if (inode->dirents != NULL) + g_sequence_free(inode->dirents); + inode->dirents = NULL; + break; + + case BLUESKY_SYMLINK: + g_free(inode->symlink_contents); + inode->symlink_contents = NULL; + break; + + default: + break; + } +} + void bluesky_inode_unref(BlueSkyInode *inode) { if (g_atomic_int_dec_and_test(&inode->refcount)) { @@ -167,38 +199,9 @@ void bluesky_inode_unref(BlueSkyInode *inode) bluesky_list_unlink(&inode->fs->unlogged_list, inode->unlogged_list); g_mutex_unlock(inode->fs->lock); - /* Free file type specific data. It should be an error for there to be - * dirty data to commit when the reference count has reaches zero. */ - switch (inode->type) { - case BLUESKY_REGULAR: - for (int i = 0; i < inode->blocks->len; i++) { - BlueSkyBlock *b = &g_array_index(inode->blocks, - BlueSkyBlock, i); - if (b->type == BLUESKY_BLOCK_DIRTY) { - g_error("Deleting an inode with dirty file data!"); - } - bluesky_cloudlog_unref(b->ref); - bluesky_string_unref(b->dirty); - } - g_array_unref(inode->blocks); - break; - - case BLUESKY_DIRECTORY: - g_hash_table_destroy(inode->dirhash); - g_hash_table_destroy(inode->dirhash_folded); - g_sequence_free(inode->dirents); - break; - - case BLUESKY_SYMLINK: - g_free(inode->symlink_contents); - break; - - default: - break; - } + bluesky_inode_free_resources(inode); g_mutex_free(inode->lock); - g_free(inode); } } @@ -212,8 +215,6 @@ uint64_t bluesky_fs_alloc_inode(BlueSkyFS *fs) inum = fs->next_inum; fs->next_inum++; - bluesky_superblock_flush(fs); - return inum; } @@ -343,26 +344,17 @@ void bluesky_inode_do_sync(BlueSkyInode *inode) } } -static void complete_inode_fetch(BlueSkyStoreAsync *async, BlueSkyInode *inode) +static void complete_inode_fetch(BlueSkyInode *inode) { - if (bluesky_verbose) { - g_log("bluesky/inode", G_LOG_LEVEL_DEBUG, - "Completing fetch of inode %"PRIu64"...", inode->inum); - } + BlueSkyCloudLog *item = inode->committed_item; + inode->committed_item = NULL; + g_print("Completing fetch of inode %"PRIu64"...", inode->inum); - 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); - } + 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); @@ -371,6 +363,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); } @@ -381,44 +374,19 @@ 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; 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); + inode->committed_item = entry->item; + bluesky_cloudlog_ref(entry->item); - 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); -} - -/* 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 + /* TODO: Thread pool or other better async method. */ + g_thread_create((GThreadFunc)complete_inode_fetch, + (gpointer)inode, FALSE, NULL); }