X-Git-Url: http://git.vrable.net/?a=blobdiff_plain;f=bluesky%2Finode.c;h=bdf01a1240ff53ab3691bd372465f6a188cd0fad;hb=8a2ef6b448a40c790e7df154c12b54932f3e62e0;hp=d8b80cf5dd18f3801e1aca07c62abbf563a350fa;hpb=a5a9eca66728d271a442125ac52098378c70cf42;p=bluesky.git diff --git a/bluesky/inode.c b/bluesky/inode.c index d8b80cf..bdf01a1 100644 --- a/bluesky/inode.c +++ b/bluesky/inode.c @@ -6,11 +6,13 @@ * TODO: Licensing */ +#include #include +#include #include #include -#include "bluesky.h" +#include "bluesky-private.h" /* 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 @@ -27,7 +29,8 @@ int64_t bluesky_get_current_time() /* Update an inode to indicate that a modification was made. This increases * the change counter, updates the ctime to the current time, and optionally - * updates the mtime. */ + * updates the mtime. This also makes the inode contents subject to writeback + * to storage in the future. inode must already be locked. */ void bluesky_inode_update_ctime(BlueSkyInode *inode, gboolean update_mtime) { int64_t now = bluesky_get_current_time(); @@ -35,54 +38,9 @@ void bluesky_inode_update_ctime(BlueSkyInode *inode, gboolean update_mtime) inode->ctime = now; if (update_mtime) inode->mtime = now; -} - -/* Compute the HMAC keyed-hash function using the given hash algorithm, data, - * and key. */ -void compute_hmac(GChecksumType algo, - const guchar *data, gsize data_len, - const guchar *key, gsize key_len, - guint8 *buffer, gsize *digest_len) -{ - int block_size; - - switch (algo) { - case G_CHECKSUM_MD5: - case G_CHECKSUM_SHA1: - case G_CHECKSUM_SHA256: - block_size = 64; - break; - default: - g_error("Unknown hash algorithm for HMAC: %d\n", algo); - } - - gsize digest_size = g_checksum_type_get_length(algo); - guchar keybuf[block_size]; - memset(keybuf, 0, block_size); - memcpy(keybuf, key, MIN(block_size, key_len)); - for (int i = 0; i < block_size; i++) - keybuf[i] ^= 0x36; - - GChecksum *csum1 = g_checksum_new(algo); - g_checksum_update(csum1, keybuf, block_size); - g_checksum_update(csum1, data, data_len); - guint8 digest[digest_size]; - g_checksum_get_digest(csum1, digest, &digest_size); - - memset(keybuf, 0, block_size); - memcpy(keybuf, key, MIN(block_size, key_len)); - for (int i = 0; i < block_size; i++) - keybuf[i] ^= 0x5c; - - GChecksum *csum2 = g_checksum_new(algo); - g_checksum_update(csum2, keybuf, block_size); - g_checksum_update(csum2, digest, digest_size); - - g_checksum_get_digest(csum2, buffer, digest_len); - - g_checksum_free(csum1); - g_checksum_free(csum2); + if (inode->change_time == 0) + inode->change_time = now; } /* Unfortunately a glib hash table is only guaranteed to be able to store @@ -119,6 +77,36 @@ BlueSkyFS *bluesky_new_fs(gchar *name) return fs; } +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; + g_print("Loaded filesystem superblock\n"); + g_free(fs->name); + fs->name = g_strdup(name); + return fs; + } + } + + g_print("Initializing fresh filesystem\n"); + BlueSkyFS *fs = bluesky_new_fs(name); + fs->store = store; + + BlueSkyInode *root = bluesky_new_inode(BLUESKY_ROOT_INUM, fs, + BLUESKY_DIRECTORY); + root->nlink = 1; + root->mode = 0755; + bluesky_insert_inode(fs, root); + + bluesky_inode_flush(fs, root); + bluesky_superblock_flush(fs); + + return fs; +} + /* Inode reference counting. */ void bluesky_inode_ref(BlueSkyInode *inode) { @@ -128,21 +116,21 @@ void bluesky_inode_ref(BlueSkyInode *inode) void bluesky_inode_unref(BlueSkyInode *inode) { if (g_atomic_int_dec_and_test(&inode->refcount)) { - g_error("Reference count for inode %lld dropped to zero!\n", + g_error("Reference count for inode %"PRIu64" dropped to zero!\n", inode->inum); } } /* Allocate a fresh inode number which has not been used before within a - * filesystem. */ + * filesystem. fs must already be locked. */ uint64_t bluesky_fs_alloc_inode(BlueSkyFS *fs) { uint64_t inum; - g_mutex_lock(fs->lock); inum = fs->next_inum; fs->next_inum++; - g_mutex_unlock(fs->lock); + + bluesky_superblock_flush(fs); return inum; } @@ -165,6 +153,7 @@ BlueSkyInode *bluesky_new_inode(uint64_t inum, BlueSkyFS *fs, case BLUESKY_DIRECTORY: i->dirents = g_sequence_new(bluesky_dirent_destroy); 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: @@ -179,22 +168,110 @@ BlueSkyInode *bluesky_new_inode(uint64_t inum, BlueSkyFS *fs, /* 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. */ + * filesystem state is stored here. inode is returned locked with a reference + * held. */ BlueSkyInode *bluesky_get_inode(BlueSkyFS *fs, uint64_t inum) { BlueSkyInode *inode = NULL; + if (inum == 0) { + return NULL; + } + g_mutex_lock(fs->lock); inode = (BlueSkyInode *)g_hash_table_lookup(fs->inodes, &inum); + + if (inode == NULL) { + bluesky_inode_fetch(fs, inum); + inode = (BlueSkyInode *)g_hash_table_lookup(fs->inodes, &inum); + } + + if (inode != NULL) { + bluesky_inode_ref(inode); + } + g_mutex_unlock(fs->lock); return inode; } -/* Insert an inode into the filesystem inode cache. */ +/* Insert an inode into the filesystem inode cache. fs should be locked. */ void bluesky_insert_inode(BlueSkyFS *fs, BlueSkyInode *inode) { - g_mutex_lock(fs->lock); g_hash_table_insert(fs->inodes, &inode->inum, inode); - g_mutex_unlock(fs->lock); +} + +/* Deprecated: Synchronize an inode to stable storage. */ +void bluesky_inode_flush(BlueSkyFS *fs, BlueSkyInode *inode) +{ + GString *buf = g_string_new(""); + bluesky_serialize_inode(buf, inode); + BlueSkyRCStr *data = bluesky_string_new_from_gstring(buf); + + char key[64]; + sprintf(key, "inode-%016"PRIx64, inode->inum); + + BlueSkyStoreAsync *async = bluesky_store_async_new(fs->store); + async->op = STORE_OP_PUT; + async->key = g_strdup(key); + async->data = data; + bluesky_store_async_submit(async); + bluesky_store_async_unref(async); +} + +/* Start writeback of an inode and all associated data. */ +void bluesky_inode_start_sync(BlueSkyInode *inode, BlueSkyStoreAsync *barrier) +{ + BlueSkyFS *fs = inode->fs; + + GString *buf = g_string_new(""); + bluesky_serialize_inode(buf, inode); + BlueSkyRCStr *data = bluesky_string_new_from_gstring(buf); + + if (inode->type == BLUESKY_REGULAR) + bluesky_file_flush(inode, barrier); + + char key[64]; + sprintf(key, "inode-%016"PRIx64, inode->inum); + + BlueSkyStoreAsync *async = bluesky_store_async_new(fs->store); + async->op = STORE_OP_PUT; + async->key = g_strdup(key); + async->data = data; + bluesky_store_async_submit(async); + if (barrier != NULL) + bluesky_store_add_barrier(barrier, async); + bluesky_store_async_unref(async); +} + +/* Fetch an inode from stable storage. */ +void bluesky_inode_fetch(BlueSkyFS *fs, uint64_t inum) +{ + char key[64]; + sprintf(key, "inode-%016"PRIx64, inum); + BlueSkyRCStr *data = bluesky_store_get(fs->store, key); + if (data == NULL) + return; + + BlueSkyInode *inode = bluesky_deserialize_inode(fs, data->data); + if (inode != NULL) { + bluesky_insert_inode(fs, inode); + } +} + +/* Synchronize filesystem superblock to stable storage. */ +void bluesky_superblock_flush(BlueSkyFS *fs) +{ + 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); }