瀏覽代碼

Btrfs: search for an allocation hint while filling file COW

The allocator has some nice knobs for sending hints about where
to try and allocate new blocks, but when we're doing file allocations
we're not sending any hint at all.

This commit adds a simple extent map search to see if we can
quickly and easily find a hint for the allocator.

Signed-off-by: Chris Mason <chris.mason@oracle.com>
Chris Mason 15 年之前
父節點
當前提交
b917b7c3be
共有 3 個文件被更改,包括 59 次插入1 次删除
  1. 48 0
      fs/btrfs/extent_map.c
  2. 2 0
      fs/btrfs/extent_map.h
  3. 9 1
      fs/btrfs/inode.c

+ 48 - 0
fs/btrfs/extent_map.c

@@ -366,6 +366,54 @@ out:
 	return em;
 	return em;
 }
 }
 
 
+/**
+ * search_extent_mapping - find a nearby extent map
+ * @tree:	tree to lookup in
+ * @start:	byte offset to start the search
+ * @len:	length of the lookup range
+ *
+ * Find and return the first extent_map struct in @tree that intersects the
+ * [start, len] range.
+ *
+ * If one can't be found, any nearby extent may be returned
+ */
+struct extent_map *search_extent_mapping(struct extent_map_tree *tree,
+					 u64 start, u64 len)
+{
+	struct extent_map *em;
+	struct rb_node *rb_node;
+	struct rb_node *prev = NULL;
+	struct rb_node *next = NULL;
+
+	rb_node = __tree_search(&tree->map, start, &prev, &next);
+	if (!rb_node && prev) {
+		em = rb_entry(prev, struct extent_map, rb_node);
+		goto found;
+	}
+	if (!rb_node && next) {
+		em = rb_entry(next, struct extent_map, rb_node);
+		goto found;
+	}
+	if (!rb_node) {
+		em = NULL;
+		goto out;
+	}
+	if (IS_ERR(rb_node)) {
+		em = ERR_PTR(PTR_ERR(rb_node));
+		goto out;
+	}
+	em = rb_entry(rb_node, struct extent_map, rb_node);
+	goto found;
+
+	em = NULL;
+	goto out;
+
+found:
+	atomic_inc(&em->refs);
+out:
+	return em;
+}
+
 /**
 /**
  * remove_extent_mapping - removes an extent_map from the extent tree
  * remove_extent_mapping - removes an extent_map from the extent tree
  * @tree:	extent tree to remove from
  * @tree:	extent tree to remove from

+ 2 - 0
fs/btrfs/extent_map.h

@@ -60,4 +60,6 @@ void free_extent_map(struct extent_map *em);
 int __init extent_map_init(void);
 int __init extent_map_init(void);
 void extent_map_exit(void);
 void extent_map_exit(void);
 int unpin_extent_cache(struct extent_map_tree *tree, u64 start, u64 len);
 int unpin_extent_cache(struct extent_map_tree *tree, u64 start, u64 len);
+struct extent_map *search_extent_mapping(struct extent_map_tree *tree,
+					 u64 start, u64 len);
 #endif
 #endif

+ 9 - 1
fs/btrfs/inode.c

@@ -726,6 +726,15 @@ static noinline int cow_file_range(struct inode *inode,
 	BUG_ON(disk_num_bytes >
 	BUG_ON(disk_num_bytes >
 	       btrfs_super_total_bytes(&root->fs_info->super_copy));
 	       btrfs_super_total_bytes(&root->fs_info->super_copy));
 
 
+
+	read_lock(&BTRFS_I(inode)->extent_tree.lock);
+	em = search_extent_mapping(&BTRFS_I(inode)->extent_tree,
+				   start, num_bytes);
+	if (em) {
+		alloc_hint = em->block_start;
+		free_extent_map(em);
+	}
+	read_unlock(&BTRFS_I(inode)->extent_tree.lock);
 	btrfs_drop_extent_cache(inode, start, start + num_bytes - 1, 0);
 	btrfs_drop_extent_cache(inode, start, start + num_bytes - 1, 0);
 
 
 	while (disk_num_bytes > 0) {
 	while (disk_num_bytes > 0) {
@@ -738,7 +747,6 @@ static noinline int cow_file_range(struct inode *inode,
 		em = alloc_extent_map(GFP_NOFS);
 		em = alloc_extent_map(GFP_NOFS);
 		em->start = start;
 		em->start = start;
 		em->orig_start = em->start;
 		em->orig_start = em->start;
-
 		ram_size = ins.offset;
 		ram_size = ins.offset;
 		em->len = ins.offset;
 		em->len = ins.offset;