소스 검색

Btrfs: change btrfs_del_leaf to drop locks earlier

btrfs_del_leaf does two things.  First it removes the pointer in the
parent, and then it frees the block that has the leaf.  It has the
parent node locked for both operations.

But, it only needs the parent locked while it is deleting the pointer.
After that it can safely free the block without the parent locked.

Signed-off-by: Chris Mason <chris.mason@oracle.com>
Chris Mason 17 년 전
부모
커밋
4d081c41a4
1개의 변경된 파일9개의 추가작업 그리고 2개의 파일을 삭제
  1. 9 2
      fs/btrfs/ctree.c

+ 9 - 2
fs/btrfs/ctree.c

@@ -3630,15 +3630,22 @@ noinline int btrfs_del_leaf(struct btrfs_trans_handle *trans,
 {
 {
 	int ret;
 	int ret;
 	u64 root_gen = btrfs_header_generation(path->nodes[1]);
 	u64 root_gen = btrfs_header_generation(path->nodes[1]);
+	u64 parent_start = path->nodes[1]->start;
+	u64 parent_owner = btrfs_header_owner(path->nodes[1]);
 
 
 	ret = del_ptr(trans, root, path, 1, path->slots[1]);
 	ret = del_ptr(trans, root, path, 1, path->slots[1]);
 	if (ret)
 	if (ret)
 		return ret;
 		return ret;
 
 
+	/*
+	 * btrfs_free_extent is expensive, we want to make sure we
+	 * aren't holding any locks when we call it
+	 */
+	btrfs_unlock_up_safe(path, 0);
+
 	ret = btrfs_free_extent(trans, root, bytenr,
 	ret = btrfs_free_extent(trans, root, bytenr,
 				btrfs_level_size(root, 0),
 				btrfs_level_size(root, 0),
-				path->nodes[1]->start,
-				btrfs_header_owner(path->nodes[1]),
+				parent_start, parent_owner,
 				root_gen, 0, 1);
 				root_gen, 0, 1);
 	return ret;
 	return ret;
 }
 }