Btrfs: CPU usage optimizations in push and the extent_map code

Signed-off-by: Chris Mason <chris.mason@oracle.com>
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index 17a3226..e846694 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -1588,6 +1588,11 @@
 	if (!path->nodes[1])
 		return 1;
 
+	right_nritems = btrfs_header_nritems(right);
+	if (right_nritems == 0) {
+		return 1;
+	}
+
 	left = read_tree_block(root, btrfs_node_blockptr(path->nodes[1],
 			       slot - 1), root->leafsize);
 	free_space = btrfs_leaf_free_space(root, left);
@@ -1604,18 +1609,13 @@
 		free_extent_buffer(left);
 		return 1;
 	}
+
 	free_space = btrfs_leaf_free_space(root, left);
 	if (free_space < data_size + sizeof(struct btrfs_item)) {
 		free_extent_buffer(left);
 		return 1;
 	}
 
-	right_nritems = btrfs_header_nritems(right);
-	if (right_nritems == 0) {
-		free_extent_buffer(left);
-		return 1;
-	}
-
 	for (i = 0; i < right_nritems - 1; i++) {
 		item = btrfs_item_nr(right, i);
 		if (!right->map_token) {
@@ -1772,21 +1772,25 @@
 	struct btrfs_disk_key disk_key;
 
 	/* first try to make some room by pushing left and right */
-	wret = push_leaf_left(trans, root, path, data_size);
-	if (wret < 0) {
-		return wret;
-	}
-	if (wret) {
+	if (ins_key->type != BTRFS_DIR_ITEM_KEY) {
 		wret = push_leaf_right(trans, root, path, data_size);
-		if (wret < 0)
+		if (wret < 0) {
 			return wret;
-	}
-	l = path->nodes[0];
+		}
+		if (wret) {
+			wret = push_leaf_left(trans, root, path, data_size);
+			if (wret < 0)
+				return wret;
+		}
+		l = path->nodes[0];
 
-	/* did the pushes work? */
-	if (btrfs_leaf_free_space(root, l) >=
-	    sizeof(struct btrfs_item) + data_size) {
-		return 0;
+		/* did the pushes work? */
+		if (btrfs_leaf_free_space(root, l) >=
+		    sizeof(struct btrfs_item) + data_size) {
+			return 0;
+		}
+	} else {
+		l = path->nodes[0];
 	}
 
 	if (!path->nodes[1]) {
@@ -2388,13 +2392,13 @@
 			slot = path->slots[1];
 			extent_buffer_get(leaf);
 
-			wret = push_leaf_left(trans, root, path, 1);
+			wret = push_leaf_right(trans, root, path, 1);
 			if (wret < 0 && wret != -ENOSPC)
 				ret = wret;
 
 			if (path->nodes[0] == leaf &&
 			    btrfs_header_nritems(leaf)) {
-				wret = push_leaf_right(trans, root, path, 1);
+				wret = push_leaf_left(trans, root, path, 1);
 				if (wret < 0 && wret != -ENOSPC)
 					ret = wret;
 			}
diff --git a/fs/btrfs/extent_map.c b/fs/btrfs/extent_map.c
index 3c81f5e..caaf0bf 100644
--- a/fs/btrfs/extent_map.c
+++ b/fs/btrfs/extent_map.c
@@ -1986,12 +1986,15 @@
 					      unsigned long i)
 {
 	struct page *p;
+	struct address_space *mapping;
 
 	if (i == 0)
 		return eb->first_page;
 	i += eb->start >> PAGE_CACHE_SHIFT;
-	p = find_get_page(eb->first_page->mapping, i);
-	page_cache_release(p);
+	mapping = eb->first_page->mapping;
+	read_lock_irq(&mapping->tree_lock);
+	p = radix_tree_lookup(&mapping->page_tree, i);
+	read_unlock_irq(&mapping->tree_lock);
 	return p;
 }
 
@@ -2365,9 +2368,7 @@
 	WARN_ON(start > eb->len);
 	WARN_ON(start + len > eb->start + eb->len);
 
-	offset = start & ((unsigned long)PAGE_CACHE_SIZE - 1);
-	if (i == 0)
-		offset += start_offset;
+	offset = (start_offset + start) & ((unsigned long)PAGE_CACHE_SIZE - 1);
 
 	while(len > 0) {
 		page = extent_buffer_page(eb, i);
@@ -2475,9 +2476,7 @@
 	WARN_ON(start > eb->len);
 	WARN_ON(start + len > eb->start + eb->len);
 
-	offset = start & ((unsigned long)PAGE_CACHE_SIZE - 1);
-	if (i == 0)
-		offset += start_offset;
+	offset = (start_offset + start) & ((unsigned long)PAGE_CACHE_SIZE - 1);
 
 	while(len > 0) {
 		page = extent_buffer_page(eb, i);
@@ -2514,9 +2513,7 @@
 	WARN_ON(start > eb->len);
 	WARN_ON(start + len > eb->start + eb->len);
 
-	offset = start & ((unsigned long)PAGE_CACHE_SIZE - 1);
-	if (i == 0)
-		offset += start_offset;
+	offset = (start_offset + start) & ((unsigned long)PAGE_CACHE_SIZE - 1);
 
 	while(len > 0) {
 		page = extent_buffer_page(eb, i);
@@ -2548,9 +2545,7 @@
 	WARN_ON(start > eb->len);
 	WARN_ON(start + len > eb->start + eb->len);
 
-	offset = start & ((unsigned long)PAGE_CACHE_SIZE - 1);
-	if (i == 0)
-		offset += start_offset;
+	offset = (start_offset + start) & ((unsigned long)PAGE_CACHE_SIZE - 1);
 
 	while(len > 0) {
 		page = extent_buffer_page(eb, i);
@@ -2582,9 +2577,8 @@
 
 	WARN_ON(src->len != dst_len);
 
-	offset = dst_offset & ((unsigned long)PAGE_CACHE_SIZE - 1);
-	if (i == 0)
-		offset += start_offset;
+	offset = (start_offset + dst_offset) &
+		((unsigned long)PAGE_CACHE_SIZE - 1);
 
 	while(len > 0) {
 		page = extent_buffer_page(dst, i);
@@ -2664,19 +2658,14 @@
 	}
 
 	while(len > 0) {
-		dst_off_in_page = dst_offset &
+		dst_off_in_page = (start_offset + dst_offset) &
 			((unsigned long)PAGE_CACHE_SIZE - 1);
-		src_off_in_page = src_offset &
+		src_off_in_page = (start_offset + src_offset) &
 			((unsigned long)PAGE_CACHE_SIZE - 1);
 
 		dst_i = (start_offset + dst_offset) >> PAGE_CACHE_SHIFT;
 		src_i = (start_offset + src_offset) >> PAGE_CACHE_SHIFT;
 
-		if (src_i == 0)
-			src_off_in_page += start_offset;
-		if (dst_i == 0)
-			dst_off_in_page += start_offset;
-
 		cur = min(len, (unsigned long)(PAGE_CACHE_SIZE -
 					       src_off_in_page));
 		cur = min_t(unsigned long, cur,
@@ -2723,14 +2712,10 @@
 		dst_i = (start_offset + dst_end) >> PAGE_CACHE_SHIFT;
 		src_i = (start_offset + src_end) >> PAGE_CACHE_SHIFT;
 
-		dst_off_in_page = dst_end &
+		dst_off_in_page = (start_offset + dst_end) &
 			((unsigned long)PAGE_CACHE_SIZE - 1);
-		src_off_in_page = src_end &
+		src_off_in_page = (start_offset + src_end) &
 			((unsigned long)PAGE_CACHE_SIZE - 1);
-		if (src_i == 0)
-			src_off_in_page += start_offset;
-		if (dst_i == 0)
-			dst_off_in_page += start_offset;
 
 		cur = min_t(unsigned long, len, src_off_in_page + 1);
 		cur = min(cur, dst_off_in_page + 1);