aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/ctree.c
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/btrfs/ctree.c
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/btrfs/ctree.c')
-rw-r--r--fs/btrfs/ctree.c22
1 files changed, 12 insertions, 10 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 }