Btrfs: Add btree locking to the tree defragmentation code

The online btree defragger is simplified and rewritten to use
standard btree searches instead of a walk up / down mechanism.

Signed-off-by: Chris Mason <chris.mason@oracle.com>
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index 40f0e0c..7f4cc2b 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -354,7 +354,6 @@
 		       struct btrfs_key *progress)
 {
 	struct extent_buffer *cur;
-	struct extent_buffer *tmp;
 	u64 blocknr;
 	u64 gen;
 	u64 search_start = *last_ret;
@@ -370,9 +369,6 @@
 	int progress_passed = 0;
 	struct btrfs_disk_key disk_key;
 
-	/* FIXME this code needs locking */
-	return 0;
-
 	parent_level = btrfs_header_level(parent);
 	if (cache_only && parent_level != 1)
 		return 0;
@@ -454,20 +450,23 @@
 		if (search_start == 0)
 			search_start = last_block;
 
+		btrfs_tree_lock(cur);
 		err = __btrfs_cow_block(trans, root, cur, parent, i,
-					&tmp, search_start,
+					&cur, search_start,
 					min(16 * blocksize,
 					    (end_slot - i) * blocksize));
 		if (err) {
+			btrfs_tree_unlock(cur);
 			free_extent_buffer(cur);
 			break;
 		}
-		search_start = tmp->start;
-		last_block = tmp->start;
+		search_start = cur->start;
+		last_block = cur->start;
 		*last_ret = search_start;
 		if (parent_level == 1)
-			btrfs_clear_buffer_defrag(tmp);
-		free_extent_buffer(tmp);
+			btrfs_clear_buffer_defrag(cur);
+		btrfs_tree_unlock(cur);
+		free_extent_buffer(cur);
 	}
 	if (parent->map_token) {
 		unmap_extent_buffer(parent, parent->map_token,
@@ -2970,6 +2969,35 @@
 	return 1;
 }
 
+int btrfs_find_next_key(struct btrfs_root *root, struct btrfs_path *path,
+			struct btrfs_key *key, int lowest_level)
+{
+	int level = lowest_level;
+	int slot;
+	struct extent_buffer *c;
+
+	while(level < BTRFS_MAX_LEVEL) {
+		if (!path->nodes[level])
+			return 1;
+
+		slot = path->slots[level] + 1;
+		c = path->nodes[level];
+		if (slot >= btrfs_header_nritems(c)) {
+			level++;
+			if (level == BTRFS_MAX_LEVEL) {
+				return 1;
+			}
+			continue;
+		}
+		if (level == 0)
+			btrfs_item_key_to_cpu(c, key, slot);
+		else
+			btrfs_node_key_to_cpu(c, key, slot);
+		return 0;
+	}
+	return 1;
+}
+
 /*
  * search the tree again to find a leaf with greater keys
  * returns 0 if it found something or 1 if there are no greater leaves.