Btrfs: fix an oops when we fail to merge reloc roots
authorWang Shilong <wangsl.fnst@cn.fujitsu.com>
Thu, 26 Dec 2013 05:10:50 +0000 (13:10 +0800)
committerChris Mason <clm@fb.com>
Tue, 28 Jan 2014 21:20:13 +0000 (13:20 -0800)
Previously, we will free reloc root memory and then force filesystem
to be readonly. The problem is that there may be another thread commiting
transaction which will try to access freed reloc root during merging reloc
roots process.

To keep consistency snapshots shared space, we should allow snapshot
finished if possible, so here we don't free reloc root memory.

signed-off-by: Wang Shilong <wangsl.fnst@cn.fujitsu.com>

Signed-off-by: Josef Bacik <jbacik@fb.com>
Signed-off-by: Chris Mason <clm@fb.com>
fs/btrfs/relocation.c

index 277b8e371fa5e3fdf0efb2272fa89e7526511839..9189f9e3c3598fb5ce517fc09cde7ac8a36a0862 100644 (file)
@@ -2311,9 +2311,6 @@ void free_reloc_roots(struct list_head *list)
                reloc_root = list_entry(list->next, struct btrfs_root,
                                        root_list);
                __del_reloc_root(reloc_root);
-               free_extent_buffer(reloc_root->node);
-               free_extent_buffer(reloc_root->commit_root);
-               kfree(reloc_root);
        }
 }
 
@@ -2355,10 +2352,9 @@ again:
 
                        ret = merge_reloc_root(rc, root);
                        if (ret) {
-                               __del_reloc_root(reloc_root);
-                               free_extent_buffer(reloc_root->node);
-                               free_extent_buffer(reloc_root->commit_root);
-                               kfree(reloc_root);
+                               if (list_empty(&reloc_root->root_list))
+                                       list_add_tail(&reloc_root->root_list,
+                                                     &reloc_roots);
                                goto out;
                        }
                } else {