From 77511ae98a27a2db081b6e8b5374c4bf955b655f Mon Sep 17 00:00:00 2001 From: Michael Vrable Date: Thu, 9 Dec 2010 18:26:15 -0800 Subject: [PATCH] Mostly implement inode merging for the in-proxy cleaner component. This doesn't yet ensure modifications are serialized out again later. --- bluesky/cleaner.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 68 insertions(+), 1 deletion(-) diff --git a/bluesky/cleaner.c b/bluesky/cleaner.c index e2eccc5..ec2b5dd 100644 --- a/bluesky/cleaner.c +++ b/bluesky/cleaner.c @@ -197,6 +197,73 @@ gboolean needs_merging(BlueSkyFS *fs, BlueSkyCloudPointer location) return TRUE; } +static void merge_inode(BlueSkyFS *fs, BlueSkyCleanerItem *cleaner_inode) +{ + /* There are two versions we are concerned with: cleaner_ is for the data + * stored in the cleaner's log, and proxy_ is for our most recent version, + * which the cleaner might or might not know about. */ + uint64_t inum = cleaner_inode->inum; + + g_print("Merging inode %"PRIu64" from cleaner\n", inum); + + g_mutex_lock(fs->lock); + InodeMapEntry *entry = bluesky_inode_map_lookup(fs->inode_map, inum, 0); + if (entry == NULL) { + /* Inode doesn't exist: it was probably deleted so keep it that way. */ + g_mutex_unlock(fs->lock); + return; + } + + BlueSkyCloudLog *proxy_item = entry->item; + g_mutex_lock(proxy_item->lock); + BlueSkyCloudPointer proxy_location = entry->item->location; + BlueSkyCloudID proxy_id = entry->item->id; + g_mutex_unlock(proxy_item->lock); + g_mutex_unlock(fs->lock); + + /* If the cleaner and the proxy have the same ID, and if the proxy's + * in-memory copy is unmodified, then we can simply use the cleaner's + * version of the inode. */ + /* TODO */ + + /* Merge file data together for a regular file. Iterate over the file + * blocks in the proxy's copy of the inode. If the block ID is unchanged + * in the cleaner but the location was updated, then update the location in + * the cleaner because the block was relocated. Otherwise ignore the + * cleaner's version for that block because the proxy's information is more + * recent. */ + BlueSkyInode *proxy_inode = bluesky_get_inode(fs, inum); + g_mutex_lock(proxy_inode->lock); + if (proxy_inode->type == BLUESKY_REGULAR) { + for (int i = 0; i < proxy_inode->blocks->len; i++) { + BlueSkyBlock *b = &g_array_index(proxy_inode->blocks, + BlueSkyBlock, i); + if (b->type != BLUESKY_BLOCK_REF) + continue; + if (i >= cleaner_inode->links->len) + continue; + BlueSkyCleanerLink *cb = &g_array_index(cleaner_inode->links, + BlueSkyCleanerLink, i); + if (memcmp(&b->ref->id, &cb->id, sizeof(BlueSkyCloudPointer)) != 0) + continue; + + g_print(" Updating block %d pointer\n", i); + b->ref->location = cb->location; + } + } + g_mutex_unlock(proxy_inode->lock); + + /* Mark the inode as modified so it will get written back to the cloud. We + * don't actually need to force a synchronous write to our local journal + * since there have been no logical modifications. */ +#if 0 + g_mutex_lock(inode->fs->lock); + bluesky_list_unlink(&inode->fs->unlogged_list, inode->unlogged_list); + inode->unlogged_list = bluesky_list_prepend(&inode->fs->unlogged_list, inode); + g_mutex_unlock(inode->fs->lock); +#endif +} + void bluesky_cleaner_merge(BlueSkyFS *fs) { BlueSkyCleanerItem *checkpoint = bluesky_cleaner_find_checkpoint(fs); @@ -227,7 +294,7 @@ void bluesky_cleaner_merge(BlueSkyFS *fs) continue; BlueSkyCleanerItem *inode = cleaner_load_item(fs, link->location); if (inode != NULL) { - g_print("Got inode %"PRIu64"\n", inode->inum); + merge_inode(fs, inode); } bluesky_cleaner_item_free(inode); } -- 2.20.1