summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLi Zefan <lizf@cn.fujitsu.com>2012-03-03 07:41:15 -0500
committerChris Mason <chris.mason@oracle.com>2012-03-03 07:41:15 -0500
commitd3b010640e5c59b98d3b11229ba4cc2838dc7cbf (patch)
treeadaa412e6603430b04e104dbafb4ed3e3d32a455
parente77266e4c4be6f9dc91bf688bce015a8babd5fe0 (diff)
downloadlinux-d3b010640e5c59b98d3b11229ba4cc2838dc7cbf.tar.bz2
btrfs: fix locking issues in find_parent_nodes()
- We might unlock head->mutex while it was not locked - We might leave the function without unlocking delayed_refs->lock Signed-off-by: Li Zefan <lizf@cn.fujitsu.com> Signed-off-by: Chris Mason <chris.mason@oracle.com>
-rw-r--r--fs/btrfs/backref.c8
1 files changed, 6 insertions, 2 deletions
diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c
index 98f6bf10bbd4..0436c12da8c2 100644
--- a/fs/btrfs/backref.c
+++ b/fs/btrfs/backref.c
@@ -583,7 +583,7 @@ static int find_parent_nodes(struct btrfs_trans_handle *trans,
struct btrfs_path *path;
struct btrfs_key info_key = { 0 };
struct btrfs_delayed_ref_root *delayed_refs = NULL;
- struct btrfs_delayed_ref_head *head = NULL;
+ struct btrfs_delayed_ref_head *head;
int info_level = 0;
int ret;
struct list_head prefs_delayed;
@@ -607,6 +607,8 @@ static int find_parent_nodes(struct btrfs_trans_handle *trans,
* at a specified point in time
*/
again:
+ head = NULL;
+
ret = btrfs_search_slot(trans, fs_info->extent_root, &key, path, 0, 0);
if (ret < 0)
goto out;
@@ -635,8 +637,10 @@ again:
goto again;
}
ret = __add_delayed_refs(head, seq, &info_key, &prefs_delayed);
- if (ret)
+ if (ret) {
+ spin_unlock(&delayed_refs->lock);
goto out;
+ }
}
spin_unlock(&delayed_refs->lock);