Fix some resource leaks in journal replay.
authorMichael Vrable <mvrable@cs.ucsd.edu>
Tue, 31 Aug 2010 22:00:09 +0000 (15:00 -0700)
committerMichael Vrable <mvrable@cs.ucsd.edu>
Tue, 31 Aug 2010 22:00:09 +0000 (15:00 -0700)
bluesky/bluesky-private.h
bluesky/inode.c
bluesky/log.c

index fcdba98..3cfec78 100644 (file)
@@ -33,6 +33,8 @@ extern int bluesky_watermark_high_total;
 /* TODO: Make this go away entirely. */
 BlueSkyFS *bluesky_new_fs(gchar *name);
 
+void bluesky_inode_free_resources(BlueSkyInode *inode);
+
 /* Linked list update functions for LRU lists. */
 void bluesky_list_unlink(GList *head, GList *item);
 GList *bluesky_list_prepend(GList *head, BlueSkyInode *inode);
index 9878559..7560010 100644 (file)
@@ -141,6 +141,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 +211,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);
     }
 }
index f8062cf..c94794c 100644 (file)
@@ -757,6 +757,7 @@ static void bluesky_replay_scan_journal2(BlueSkyFS *fs, GList **objects,
                 bluesky_insert_inode(fs, inode);
             }
             g_mutex_lock(inode->lock);
+            bluesky_inode_free_resources(inode);
             if (!bluesky_deserialize_inode(inode, log_item))
                 g_print("Error deserializing inode %"PRIu64"\n", inum);
             fs->next_inum = MAX(fs->next_inum, inum + 1);