aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2007-08-10 14:42:37 -0400
committerDavid Woodhouse <dwmw2@hera.kernel.org>2007-08-10 14:42:37 -0400
commitf2183bde1a918d338337955c8e8ba29bd8f5e7b1 (patch)
treee27baea3779112618d2158902270c460444feeff /fs
parente9d0b13b5bbb58c9b840e407a8d181442f799966 (diff)
Btrfs: Add BH_Defrag to mark buffers that are in need of defragging
This allows the tree walking code to defrag only the newly allocated buffers, it seems to be a good balance between perfect defragging and the performance hit of repeatedly reallocating blocks. Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/btrfs/ctree.c22
-rw-r--r--fs/btrfs/disk-io.h2
-rw-r--r--fs/btrfs/extent-tree.c2
-rw-r--r--fs/btrfs/tree-defrag.c3
4 files changed, 18 insertions, 11 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index ee1ae00d2827..7cf43da5e78e 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -175,6 +175,7 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans,
175 int end_slot; 175 int end_slot;
176 int i; 176 int i;
177 int err = 0; 177 int err = 0;
178 int parent_level;
178 179
179 if (trans->transaction != root->fs_info->running_transaction) { 180 if (trans->transaction != root->fs_info->running_transaction) {
180 printk(KERN_CRIT "trans %Lu running %Lu\n", trans->transid, 181 printk(KERN_CRIT "trans %Lu running %Lu\n", trans->transid,
@@ -188,6 +189,7 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans,
188 } 189 }
189 parent_node = btrfs_buffer_node(parent); 190 parent_node = btrfs_buffer_node(parent);
190 parent_nritems = btrfs_header_nritems(&parent_node->header); 191 parent_nritems = btrfs_header_nritems(&parent_node->header);
192 parent_level = btrfs_header_level(&parent_node->header);
191 193
192 start_slot = 0; 194 start_slot = 0;
193 end_slot = parent_nritems; 195 end_slot = parent_nritems;
@@ -215,13 +217,16 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans,
215 217
216 cur_bh = btrfs_find_tree_block(root, blocknr); 218 cur_bh = btrfs_find_tree_block(root, blocknr);
217 if (!cur_bh || !buffer_uptodate(cur_bh) || 219 if (!cur_bh || !buffer_uptodate(cur_bh) ||
218 buffer_locked(cur_bh)) { 220 buffer_locked(cur_bh) || !buffer_defrag(cur_bh)) {
219 if (cache_only) { 221 if (cache_only) {
220 brelse(cur_bh); 222 brelse(cur_bh);
221 continue; 223 continue;
222 } 224 }
223 brelse(cur_bh); 225 if (!cur_bh || !buffer_uptodate(cur_bh) ||
224 cur_bh = read_tree_block(root, blocknr); 226 buffer_locked(cur_bh)) {
227 brelse(cur_bh);
228 cur_bh = read_tree_block(root, blocknr);
229 }
225 } 230 }
226 if (search_start == 0) 231 if (search_start == 0)
227 search_start = last_block & ~((u64)65535); 232 search_start = last_block & ~((u64)65535);
@@ -232,6 +237,9 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans,
232 if (err) 237 if (err)
233 break; 238 break;
234 search_start = bh_blocknr(tmp_bh); 239 search_start = bh_blocknr(tmp_bh);
240 *last_ret = search_start;
241 if (parent_level == 1)
242 clear_buffer_defrag(tmp_bh);
235 brelse(tmp_bh); 243 brelse(tmp_bh);
236 } 244 }
237 return err; 245 return err;
@@ -811,16 +819,10 @@ static void reada_for_search(struct btrfs_root *root, struct btrfs_path *path,
811 clear_radix_bit(&found, blocknr); 819 clear_radix_bit(&found, blocknr);
812 if (nread > 32) 820 if (nread > 32)
813 continue; 821 continue;
814 if (direction > 0 && cluster_start <= blocknr && 822 if (close_blocks(cluster_start, blocknr)) {
815 cluster_start + 8 > blocknr) {
816 cluster_start = blocknr;
817 readahead_tree_block(root, blocknr); 823 readahead_tree_block(root, blocknr);
818 nread++; 824 nread++;
819 } else if (direction < 0 && cluster_start >= blocknr &&
820 blocknr + 8 > cluster_start) {
821 cluster_start = blocknr; 825 cluster_start = blocknr;
822 readahead_tree_block(root, blocknr);
823 nread++;
824 } 826 }
825 } 827 }
826 } 828 }
diff --git a/fs/btrfs/disk-io.h b/fs/btrfs/disk-io.h
index 9e2c261b41ae..81fd18cbd824 100644
--- a/fs/btrfs/disk-io.h
+++ b/fs/btrfs/disk-io.h
@@ -25,8 +25,10 @@
25 25
26enum btrfs_bh_state_bits { 26enum btrfs_bh_state_bits {
27 BH_Checked = BH_PrivateStart, 27 BH_Checked = BH_PrivateStart,
28 BH_Defrag,
28}; 29};
29BUFFER_FNS(Checked, checked); 30BUFFER_FNS(Checked, checked);
31BUFFER_FNS(Defrag, defrag);
30 32
31static inline struct btrfs_node *btrfs_buffer_node(struct buffer_head *bh) 33static inline struct btrfs_node *btrfs_buffer_node(struct buffer_head *bh)
32{ 34{
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 3418bb62b996..b3641234473f 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -1015,6 +1015,7 @@ check_failed:
1015 ins->objectid = search_start; 1015 ins->objectid = search_start;
1016 ins->offset = 0; 1016 ins->offset = 0;
1017 start_found = 0; 1017 start_found = 0;
1018 path->reada = 1;
1018 1019
1019 ret = btrfs_search_slot(trans, root, ins, path, 0, 0); 1020 ret = btrfs_search_slot(trans, root, ins, path, 0, 0);
1020 if (ret < 0) 1021 if (ret < 0)
@@ -1264,6 +1265,7 @@ struct buffer_head *btrfs_alloc_free_block(struct btrfs_trans_handle *trans,
1264 WARN_ON(buffer_dirty(buf)); 1265 WARN_ON(buffer_dirty(buf));
1265 set_buffer_uptodate(buf); 1266 set_buffer_uptodate(buf);
1266 set_buffer_checked(buf); 1267 set_buffer_checked(buf);
1268 set_buffer_defrag(buf);
1267 set_radix_bit(&trans->transaction->dirty_pages, buf->b_page->index); 1269 set_radix_bit(&trans->transaction->dirty_pages, buf->b_page->index);
1268 return buf; 1270 return buf;
1269} 1271}
diff --git a/fs/btrfs/tree-defrag.c b/fs/btrfs/tree-defrag.c
index a09064a9a41c..35fd20d24645 100644
--- a/fs/btrfs/tree-defrag.c
+++ b/fs/btrfs/tree-defrag.c
@@ -86,7 +86,7 @@ static int defrag_walk_down(struct btrfs_trans_handle *trans,
86 if (cache_only) { 86 if (cache_only) {
87 next = btrfs_find_tree_block(root, blocknr); 87 next = btrfs_find_tree_block(root, blocknr);
88 if (!next || !buffer_uptodate(next) || 88 if (!next || !buffer_uptodate(next) ||
89 buffer_locked(next)) { 89 buffer_locked(next) || !buffer_defrag(next)) {
90 brelse(next); 90 brelse(next);
91 path->slots[*level]++; 91 path->slots[*level]++;
92 continue; 92 continue;
@@ -142,6 +142,7 @@ static int defrag_walk_up(struct btrfs_trans_handle *trans,
142 root->defrag_level = i; 142 root->defrag_level = i;
143 return 0; 143 return 0;
144 } else { 144 } else {
145 clear_buffer_defrag(path->nodes[*level]);
145 btrfs_block_release(root, path->nodes[*level]); 146 btrfs_block_release(root, path->nodes[*level]);
146 path->nodes[*level] = NULL; 147 path->nodes[*level] = NULL;
147 *level = i + 1; 148 *level = i + 1;