Btrfs: Do snapshot deletion in smaller chunks.

Before, snapshot deletion was a single atomic unit.  This caused considerable
lock contention and required an unbounded amount of space.  Now,
the drop_progress field in the root item is used to indicate how far along
snapshot deletion is, and to resume where it left off.

Signed-off-by: Chris Mason <chris.mason@oracle.com>
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index 19a30b7..aa824e2 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -659,9 +659,16 @@
 	struct buffer_head *b;
 	struct buffer_head *cow_buf;
 	struct btrfs_node *c;
+	struct btrfs_root_item *root_item = &root->root_item;
 	int slot;
 	int ret;
 	int level;
+	u8 lowest_level = 0;
+
+	if (btrfs_root_refs(root_item) == 0 && root->ref_cows) {
+		lowest_level = root_item->drop_level;
+		WARN_ON(ins_len || cow);
+	}
 
 	WARN_ON(p->nodes[0] != NULL);
 	WARN_ON(!mutex_is_locked(&root->fs_info->fs_mutex));
@@ -718,6 +725,9 @@
 				slot = p->slots[level];
 				BUG_ON(btrfs_header_nritems(&c->header) == 1);
 			}
+			/* this is only true while dropping a snapshot */
+			if (level == lowest_level)
+				break;
 			b = read_tree_block(root, btrfs_node_blockptr(c, slot));
 		} else {
 			struct btrfs_leaf *l = (struct btrfs_leaf *)c;