Btrfs: Add block group pinned accounting back

This patch adds a helper function 'update_pinned_extents' to
extent-tree.c. The usage of the helper function is similar to
'update_block_group',  the last parameter of the function indicates
pin vs unpin.

Signed-off-by: Chris Mason <chris.mason@oracle.com>
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 27cadae..56b977f 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -292,8 +292,8 @@
 	struct btrfs_block_group_item item;
 	int data;
 	int cached;
+	u64 pinned;
 };
-
 struct btrfs_fs_info {
 	u8 fsid[BTRFS_FSID_SIZE];
 	struct btrfs_root *extent_root;
@@ -324,8 +324,9 @@
 	struct completion kobj_unregister;
 	int do_barriers;
 	int closing;
-};
 
+	u64 total_pinned;
+};
 /*
  * in ram representation of the tree.  extent_root is used for all allocations
  * and for the extent tree extent_root root.
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 6c8533f..3e16cca 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -569,6 +569,7 @@
 			     fs_info->btree_inode->i_mapping, GFP_NOFS);
 	fs_info->do_barriers = 1;
 	fs_info->closing = 0;
+	fs_info->total_pinned = 0;
 
 	INIT_DELAYED_WORK(&fs_info->trans_work, btrfs_transaction_cleaner);
 	BTRFS_I(fs_info->btree_inode)->root = tree_root;
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 7405bd5..4ef6dc3 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -277,7 +277,8 @@
 		if (shint && (shint->data == data ||
 			      shint->data == BTRFS_BLOCK_GROUP_MIXED)) {
 			used = btrfs_block_group_used(&shint->item);
-			if (used < div_factor(shint->key.offset, factor)) {
+			if (used + shint->pinned <
+			    div_factor(shint->key.offset, factor)) {
 				return shint;
 			}
 		}
@@ -285,7 +286,8 @@
 	if (hint && (hint->data == data ||
 		     hint->data == BTRFS_BLOCK_GROUP_MIXED)) {
 		used = btrfs_block_group_used(&hint->item);
-		if (used < div_factor(hint->key.offset, factor)) {
+		if (used + hint->pinned <
+		    div_factor(hint->key.offset, factor)) {
 			return hint;
 		}
 		last = hint->key.objectid + hint->key.offset;
@@ -317,8 +319,7 @@
 			free_check = cache->key.offset;
 		else
 			free_check = div_factor(cache->key.offset, factor);
-
-		if (used < free_check) {
+		if (used + cache->pinned < free_check) {
 			found_group = cache;
 			goto found;
 		}
@@ -664,6 +665,37 @@
 	}
 	return 0;
 }
+static int update_pinned_extents(struct btrfs_root *root,
+				u64 bytenr, u64 num, int pin)
+{
+	u64 len;
+	struct btrfs_block_group_cache *cache;
+	struct btrfs_fs_info *fs_info = root->fs_info;
+
+	if (pin) {
+		set_extent_dirty(&fs_info->pinned_extents,
+				bytenr, bytenr + num - 1, GFP_NOFS);
+	} else {
+		clear_extent_dirty(&fs_info->pinned_extents,
+				bytenr, bytenr + num - 1, GFP_NOFS);
+	}
+	while (num > 0) {
+		cache = btrfs_lookup_block_group(fs_info, bytenr);
+		WARN_ON(!cache);
+		len = min(num, cache->key.offset -
+			  (bytenr - cache->key.objectid));
+		if (pin) {
+			cache->pinned += len;
+			fs_info->total_pinned += len;
+		} else {
+			cache->pinned -= len;
+			fs_info->total_pinned -= len;
+		}
+		bytenr += len;
+		num -= len;
+	}
+	return 0;
+}
 
 int btrfs_copy_pinned(struct btrfs_root *root, struct extent_map_tree *copy)
 {
@@ -691,9 +723,7 @@
 	u64 start;
 	u64 end;
 	int ret;
-	struct extent_map_tree *pinned_extents = &root->fs_info->pinned_extents;
 	struct extent_map_tree *free_space_cache;
-
 	free_space_cache = &root->fs_info->free_space_cache;
 
 	while(1) {
@@ -701,9 +731,7 @@
 					    EXTENT_DIRTY);
 		if (ret)
 			break;
-
-		clear_extent_dirty(pinned_extents, start, end,
-				   GFP_NOFS);
+		update_pinned_extents(root, start, end + 1 - start, 0);
 		clear_extent_dirty(unpin, start, end, GFP_NOFS);
 		set_extent_dirty(free_space_cache, start, end, GFP_NOFS);
 	}
@@ -761,8 +789,7 @@
 			}
 			free_extent_buffer(buf);
 		}
-		set_extent_dirty(&root->fs_info->pinned_extents,
-				 bytenr, bytenr + num_bytes - 1, GFP_NOFS);
+		update_pinned_extents(root, bytenr, num_bytes, 1);
 	} else {
 		set_extent_bits(&root->fs_info->pending_del,
 				bytenr, bytenr + num_bytes - 1,
@@ -866,8 +893,7 @@
 					    EXTENT_LOCKED);
 		if (ret)
 			break;
-
-		set_extent_dirty(pinned_extents, start, end, GFP_NOFS);
+		update_pinned_extents(extent_root, start, end + 1 - start, 1);
 		clear_extent_bits(pending_del, start, end, EXTENT_LOCKED,
 				  GFP_NOFS);
 		ret = __free_extent(trans, extent_root,
@@ -1579,7 +1605,7 @@
 				   sizeof(cache->item));
 		memcpy(&cache->key, &found_key, sizeof(found_key));
 		cache->cached = 0;
-
+		cache->pinned = 0;
 		key.objectid = found_key.objectid + found_key.offset;
 		btrfs_release_path(root, path);