From 98e3e399a5cce3d1dd1b2a15d5746d1988943e7f Mon Sep 17 00:00:00 2001 From: Michael Vrable Date: Thu, 29 Oct 2009 15:41:14 -0700 Subject: [PATCH] Add filesystem superblock serialization. Also fix deserialization of case-folded directory entries. Together, these chagnes should allow a filesystem state to be reloaded properly. --- bluesky/bluesky.h | 8 +++++++- bluesky/dir.c | 3 ++- bluesky/inode.c | 46 +++++++++++++++++++++++++++++++++++++++++++++ bluesky/serialize.c | 35 ++++++++++++++++++++++++++++++++++ 4 files changed, 90 insertions(+), 2 deletions(-) diff --git a/bluesky/bluesky.h b/bluesky/bluesky.h index e141dd3..8eff412 100644 --- a/bluesky/bluesky.h +++ b/bluesky/bluesky.h @@ -189,6 +189,9 @@ typedef struct { } BlueSkyBlock; BlueSkyFS *bluesky_new_fs(gchar *name); +BlueSkyFS *bluesky_init_fs(gchar *name, BlueSkyStore *store); +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); @@ -201,7 +204,7 @@ void bluesky_dirent_destroy(gpointer dirent); uint64_t bluesky_directory_hash(gchar *name); uint64_t bluesky_directory_lookup(BlueSkyInode *inode, gchar *name); uint64_t bluesky_directory_ilookup(BlueSkyInode *inode, gchar *name); -gboolean bluesky_directory_insert(BlueSkyInode *dir, gchar *name, +gboolean bluesky_directory_insert(BlueSkyInode *dir, const gchar *name, uint64_t inum); void bluesky_directory_dump(BlueSkyInode *dir); @@ -216,6 +219,9 @@ void bluesky_file_read(BlueSkyInode *inode, uint64_t offset, void bluesky_inode_flush(BlueSkyFS *fs, BlueSkyInode *inode); void bluesky_inode_fetch(BlueSkyFS *fs, uint64_t inum); + +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); diff --git a/bluesky/dir.c b/bluesky/dir.c index 82f3baa..cb3b23f 100644 --- a/bluesky/dir.c +++ b/bluesky/dir.c @@ -69,7 +69,8 @@ uint64_t bluesky_directory_ilookup(BlueSkyInode *inode, gchar *name) /* Insert a new entry into a directory. Should be called with the inode lock * already held. */ -gboolean bluesky_directory_insert(BlueSkyInode *dir, gchar *name, uint64_t inum) +gboolean bluesky_directory_insert(BlueSkyInode *dir, + const gchar *name, uint64_t inum) { g_return_val_if_fail(dir->type == BLUESKY_DIRECTORY, FALSE); diff --git a/bluesky/inode.c b/bluesky/inode.c index b62870d..cc4dc3c 100644 --- a/bluesky/inode.c +++ b/bluesky/inode.c @@ -73,6 +73,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) { @@ -96,6 +126,8 @@ uint64_t bluesky_fs_alloc_inode(BlueSkyFS *fs) inum = fs->next_inum; fs->next_inum++; + bluesky_superblock_flush(fs); + return inum; } @@ -191,3 +223,17 @@ void bluesky_inode_fetch(BlueSkyFS *fs, uint64_t inum) g_print("Loaded inode %"PRIu64"\n", inum); } } + +/* Synchronize filesystem superblock to stable storage. */ +void bluesky_superblock_flush(BlueSkyFS *fs) +{ + GString *buf = g_string_new(""); + bluesky_serialize_superblock(buf, fs); + + g_print("Syncing superblock...\n"); + + gsize len = buf->len; + BlueSkyRCStr *data = bluesky_string_new(g_string_free(buf, FALSE), len); + bluesky_store_put(fs->store, "superblock", data); +} + diff --git a/bluesky/serialize.c b/bluesky/serialize.c index c806d88..7f7f041 100644 --- a/bluesky/serialize.c +++ b/bluesky/serialize.c @@ -17,6 +17,15 @@ * can be written to persistent storage. All data is stored in little-endian * format. */ +/* Magic signature and structure of serialized superblocks. */ + +#define SUPERBLOCK_MAGIC 0x65ca91e91b124234ULL + +struct serialized_superblock { + uint64_t signature; /* SUPERBLOCK_MAGIC */ + uint64_t next_inum; +} __attribute__((packed)); + /* Magic signature for serialized inodes. */ #define INODE_MAGIC 0xa6832100943d71e6ULL @@ -35,6 +44,29 @@ struct serialized_inode { int64_t ntime; } __attribute__((packed)); +void bluesky_serialize_superblock(GString *out, BlueSkyFS *fs) +{ + struct serialized_superblock buf; + + buf.signature = GUINT64_TO_LE(SUPERBLOCK_MAGIC); + buf.next_inum = GUINT64_TO_LE(fs->next_inum); + + g_string_append_len(out, (gchar *)&buf, sizeof(buf)); +} + +BlueSkyFS *bluesky_deserialize_superblock(const gchar *buf) +{ + struct serialized_superblock *raw = (struct serialized_superblock *)buf; + + if (GUINT64_FROM_LE(raw->signature) != SUPERBLOCK_MAGIC) + return NULL; + + BlueSkyFS *fs = bluesky_new_fs("deserialized"); + fs->next_inum = GUINT64_FROM_LE(raw->next_inum); + + return fs; +} + void bluesky_serialize_inode(GString *out, BlueSkyInode *inode) { struct serialized_inode buf; @@ -152,10 +184,13 @@ BlueSkyInode *bluesky_deserialize_inode(BlueSkyFS *fs, const gchar *buf) dirent->cookie = GUINT64_FROM_LE(d->seq); dirent->inum = GUINT64_FROM_LE(d->inum); dirent->name = g_strdup(d->name); + dirent->name_folded = bluesky_lowercase(d->name); g_sequence_insert_sorted(inode->dirents, dirent, bluesky_dirent_compare, NULL); g_hash_table_insert(inode->dirhash, dirent->name, dirent); + g_hash_table_insert(inode->dirhash_folded, dirent->name_folded, + dirent); g_print(" dirent[%08x]: %s -> %"PRIu64"\n", dirent->cookie, dirent->name, dirent->inum); -- 2.20.1