From 37739cc6f4a38ef6241abfea42693fa046f80d1b Mon Sep 17 00:00:00 2001 From: Michael Vrable Date: Sat, 18 Sep 2010 21:22:15 -0700 Subject: [PATCH] Allow cloudlog items to be unreferenced in the background. This is to avoid certain deadlocks, when we don't care if resources are reclaimed immediately or not. --- bluesky/bluesky-private.h | 2 ++ bluesky/bluesky.h | 3 +++ bluesky/cloudlog.c | 29 ++++++++++++++++++++++++++++- bluesky/imap.c | 2 +- bluesky/inode.c | 2 ++ bluesky/serialize.c | 3 +++ 6 files changed, 39 insertions(+), 2 deletions(-) diff --git a/bluesky/bluesky-private.h b/bluesky/bluesky-private.h index fccc7a3..7ebd728 100644 --- a/bluesky/bluesky-private.h +++ b/bluesky/bluesky-private.h @@ -286,8 +286,10 @@ guint bluesky_cloudlog_hash(gconstpointer a); BlueSkyCloudLog *bluesky_cloudlog_new(BlueSkyFS *fs, const BlueSkyCloudID *id); gchar *bluesky_cloudlog_id_to_string(BlueSkyCloudID id); BlueSkyCloudID bluesky_cloudlog_id_from_string(const gchar *idstr); +void bluesky_cloudlog_threads_init(BlueSkyFS *fs); void bluesky_cloudlog_ref(BlueSkyCloudLog *log); void bluesky_cloudlog_unref(BlueSkyCloudLog *log); +void bluesky_cloudlog_unref_delayed(BlueSkyCloudLog *log); void bluesky_cloudlog_erase(BlueSkyCloudLog *log); void bluesky_cloudlog_stats_update(BlueSkyCloudLog *log, int type); void bluesky_cloudlog_sync(BlueSkyCloudLog *log); diff --git a/bluesky/bluesky.h b/bluesky/bluesky.h index 9805086..834097f 100644 --- a/bluesky/bluesky.h +++ b/bluesky/bluesky.h @@ -188,6 +188,9 @@ typedef struct { /* The inode map, which maps inode numbers to the location of the most * recent version. */ GSequence *inode_map; + + /* Queue for asynchronous cloudlog unrefs, where needed. */ + GAsyncQueue *unref_queue; } BlueSkyFS; /* Inode number of the root directory. */ diff --git a/bluesky/cloudlog.c b/bluesky/cloudlog.c index 5d14fc6..e50c269 100644 --- a/bluesky/cloudlog.c +++ b/bluesky/cloudlog.c @@ -165,6 +165,33 @@ void bluesky_cloudlog_unref(BlueSkyCloudLog *log) } } +/* For locking reasons cloudlog unrefs may sometimes need to be performed in + * the future. We launch a thread for handling these delayed unreference + * requests. */ +static gpointer cloudlog_unref_thread(gpointer q) +{ + GAsyncQueue *queue = (GAsyncQueue *)q; + + while (TRUE) { + BlueSkyCloudLog *item = (BlueSkyCloudLog *)g_async_queue_pop(queue); + bluesky_cloudlog_unref(item); + } + + return NULL; +} + +void bluesky_cloudlog_unref_delayed(BlueSkyCloudLog *log) +{ + if (log != NULL) + g_async_queue_push(log->fs->unref_queue, log); +} + +void bluesky_cloudlog_threads_init(BlueSkyFS *fs) +{ + fs->unref_queue = g_async_queue_new(); + g_thread_create(cloudlog_unref_thread, fs->unref_queue, FALSE, NULL); +} + /* Erase the information contained within the in-memory cloud log * representation. This does not free up the item itself, but frees the data * and references to other log items and resets the type back to unknown. If @@ -206,7 +233,7 @@ void bluesky_cloudlog_insert_locked(BlueSkyCloudLog *log) void bluesky_cloudlog_insert(BlueSkyCloudLog *log) { g_mutex_lock(log->fs->lock); - bluesky_cloudlog_insert(log); + bluesky_cloudlog_insert_locked(log); g_mutex_unlock(log->fs->lock); } diff --git a/bluesky/imap.c b/bluesky/imap.c index 5d5be8a..c496f99 100644 --- a/bluesky/imap.c +++ b/bluesky/imap.c @@ -114,7 +114,7 @@ InodeMapEntry *bluesky_inode_map_lookup(GSequence *inode_map, uint64_t inum, } if (action != 0) { - bluesky_cloudlog_unref(range->serialized); + bluesky_cloudlog_unref_delayed(range->serialized); range->serialized = NULL; } diff --git a/bluesky/inode.c b/bluesky/inode.c index 515b72f..0d40da4 100644 --- a/bluesky/inode.c +++ b/bluesky/inode.c @@ -94,6 +94,8 @@ BlueSkyFS *bluesky_new_fs(gchar *name) fs->log_state = g_new0(BlueSkyCloudLogState, 1); fs->log_state->data = g_string_new(""); + bluesky_cloudlog_threads_init(fs); + return fs; } diff --git a/bluesky/serialize.c b/bluesky/serialize.c index dc23cac..b99a35e 100644 --- a/bluesky/serialize.c +++ b/bluesky/serialize.c @@ -313,6 +313,9 @@ void bluesky_deserialize_cloudlog(BlueSkyCloudLog *item, g_assert(data3 + len3 - data <= len); item->type = header->type - '0'; item->inum = GUINT64_FROM_LE(header->inum); + } else { + g_warning("Deserializing garbage cloud log item!"); + return; } BlueSkyFS *fs = item->fs; -- 2.20.1