diff options
author | Chris Mason <chris.mason@oracle.com> | 2007-10-25 15:43:18 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-09-25 11:03:57 -0400 |
commit | 5708b9591617486bf1aa5b1a97f2c0549ec87933 (patch) | |
tree | e2d5f219c090ecda4bc9265027b41be2c70a57ad | |
parent | 18f16f7ba62a01c29e09b40ac6ad6d92a8955859 (diff) |
Btrfs: Tune the automatic defrag code
1) Forced defrag wasn't working properly (btrfsctl -d) because some
cache only checks were incorrect.
2) Defrag only the leaves unless in forced defrag mode.
3) Don't use complex logic to figure out if a leaf is needs defrag
Signed-off-by: Chris Mason <chris.mason@oracle.com>
-rw-r--r-- | fs/btrfs/ctree.c | 69 | ||||
-rw-r--r-- | fs/btrfs/tree-defrag.c | 1 |
2 files changed, 26 insertions, 44 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 3eb5a9f30d14..516b90224a1b 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c | |||
@@ -161,34 +161,6 @@ static int close_blocks(u64 blocknr, u64 other, u32 blocksize) | |||
161 | return 0; | 161 | return 0; |
162 | } | 162 | } |
163 | 163 | ||
164 | static int should_defrag_leaf(struct extent_buffer *leaf) | ||
165 | { | ||
166 | struct btrfs_key key; | ||
167 | u32 nritems; | ||
168 | |||
169 | if (btrfs_buffer_defrag(leaf)) | ||
170 | return 1; | ||
171 | |||
172 | nritems = btrfs_header_nritems(leaf); | ||
173 | if (nritems == 0) | ||
174 | return 0; | ||
175 | |||
176 | btrfs_item_key_to_cpu(leaf, &key, 0); | ||
177 | if (key.type == BTRFS_DIR_ITEM_KEY) | ||
178 | return 1; | ||
179 | |||
180 | |||
181 | btrfs_item_key_to_cpu(leaf, &key, nritems - 1); | ||
182 | if (key.type == BTRFS_DIR_ITEM_KEY) | ||
183 | return 1; | ||
184 | if (nritems > 4) { | ||
185 | btrfs_item_key_to_cpu(leaf, &key, nritems / 2); | ||
186 | if (key.type == BTRFS_DIR_ITEM_KEY) | ||
187 | return 1; | ||
188 | } | ||
189 | return 0; | ||
190 | } | ||
191 | |||
192 | int btrfs_realloc_node(struct btrfs_trans_handle *trans, | 164 | int btrfs_realloc_node(struct btrfs_trans_handle *trans, |
193 | struct btrfs_root *root, struct extent_buffer *parent, | 165 | struct btrfs_root *root, struct extent_buffer *parent, |
194 | int start_slot, int cache_only, u64 *last_ret, | 166 | int start_slot, int cache_only, u64 *last_ret, |
@@ -208,6 +180,10 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans, | |||
208 | int uptodate; | 180 | int uptodate; |
209 | u32 blocksize; | 181 | u32 blocksize; |
210 | 182 | ||
183 | parent_level = btrfs_header_level(parent); | ||
184 | if (cache_only && parent_level != 1) | ||
185 | return 0; | ||
186 | |||
211 | if (trans->transaction != root->fs_info->running_transaction) { | 187 | if (trans->transaction != root->fs_info->running_transaction) { |
212 | printk(KERN_CRIT "trans %Lu running %Lu\n", trans->transid, | 188 | printk(KERN_CRIT "trans %Lu running %Lu\n", trans->transid, |
213 | root->fs_info->running_transaction->transid); | 189 | root->fs_info->running_transaction->transid); |
@@ -218,7 +194,6 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans, | |||
218 | root->fs_info->generation); | 194 | root->fs_info->generation); |
219 | WARN_ON(1); | 195 | WARN_ON(1); |
220 | } | 196 | } |
221 | parent_level = btrfs_header_level(parent); | ||
222 | 197 | ||
223 | parent_nritems = btrfs_header_nritems(parent); | 198 | parent_nritems = btrfs_header_nritems(parent); |
224 | blocksize = btrfs_level_size(root, parent_level - 1); | 199 | blocksize = btrfs_level_size(root, parent_level - 1); |
@@ -227,27 +202,26 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans, | |||
227 | if (parent_nritems == 1) | 202 | if (parent_nritems == 1) |
228 | return 0; | 203 | return 0; |
229 | 204 | ||
230 | if (root != root->fs_info->extent_root) { | ||
231 | struct btrfs_key first_key; | ||
232 | struct btrfs_key last_key; | ||
233 | |||
234 | btrfs_node_key_to_cpu(parent, &first_key, 0); | ||
235 | btrfs_node_key_to_cpu(parent, &last_key, parent_nritems - 1); | ||
236 | if (first_key.objectid != last_key.objectid) | ||
237 | return 0; | ||
238 | } | ||
239 | |||
240 | for (i = start_slot; i < end_slot; i++) { | 205 | for (i = start_slot; i < end_slot; i++) { |
241 | int close = 1; | 206 | int close = 1; |
242 | 207 | ||
208 | if (!parent->map_token) { | ||
209 | map_extent_buffer(parent, | ||
210 | btrfs_node_key_ptr_offset(i), | ||
211 | sizeof(struct btrfs_key_ptr), | ||
212 | &parent->map_token, &parent->kaddr, | ||
213 | &parent->map_start, &parent->map_len, | ||
214 | KM_USER1); | ||
215 | } | ||
243 | blocknr = btrfs_node_blockptr(parent, i); | 216 | blocknr = btrfs_node_blockptr(parent, i); |
244 | if (last_block == 0) | 217 | if (last_block == 0) |
245 | last_block = blocknr; | 218 | last_block = blocknr; |
219 | |||
246 | if (i > 0) { | 220 | if (i > 0) { |
247 | other = btrfs_node_blockptr(parent, i - 1); | 221 | other = btrfs_node_blockptr(parent, i - 1); |
248 | close = close_blocks(blocknr, other, blocksize); | 222 | close = close_blocks(blocknr, other, blocksize); |
249 | } | 223 | } |
250 | if (close && i < end_slot - 1) { | 224 | if (close && i < end_slot - 2) { |
251 | other = btrfs_node_blockptr(parent, i + 1); | 225 | other = btrfs_node_blockptr(parent, i + 1); |
252 | close = close_blocks(blocknr, other, blocksize); | 226 | close = close_blocks(blocknr, other, blocksize); |
253 | } | 227 | } |
@@ -255,15 +229,18 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans, | |||
255 | last_block = blocknr; | 229 | last_block = blocknr; |
256 | continue; | 230 | continue; |
257 | } | 231 | } |
232 | if (parent->map_token) { | ||
233 | unmap_extent_buffer(parent, parent->map_token, | ||
234 | KM_USER1); | ||
235 | parent->map_token = NULL; | ||
236 | } | ||
258 | 237 | ||
259 | cur = btrfs_find_tree_block(root, blocknr, blocksize); | 238 | cur = btrfs_find_tree_block(root, blocknr, blocksize); |
260 | if (cur) | 239 | if (cur) |
261 | uptodate = btrfs_buffer_uptodate(cur); | 240 | uptodate = btrfs_buffer_uptodate(cur); |
262 | else | 241 | else |
263 | uptodate = 0; | 242 | uptodate = 0; |
264 | if (!cur || !uptodate || | 243 | if (!cur || !uptodate) { |
265 | (parent_level != 1 && !btrfs_buffer_defrag(cur)) || | ||
266 | (parent_level == 1 && !should_defrag_leaf(cur))) { | ||
267 | if (cache_only) { | 244 | if (cache_only) { |
268 | free_extent_buffer(cur); | 245 | free_extent_buffer(cur); |
269 | continue; | 246 | continue; |
@@ -287,11 +264,17 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans, | |||
287 | break; | 264 | break; |
288 | } | 265 | } |
289 | search_start = tmp->start; | 266 | search_start = tmp->start; |
267 | last_block = tmp->start; | ||
290 | *last_ret = search_start; | 268 | *last_ret = search_start; |
291 | if (parent_level == 1) | 269 | if (parent_level == 1) |
292 | btrfs_clear_buffer_defrag(tmp); | 270 | btrfs_clear_buffer_defrag(tmp); |
293 | free_extent_buffer(tmp); | 271 | free_extent_buffer(tmp); |
294 | } | 272 | } |
273 | if (parent->map_token) { | ||
274 | unmap_extent_buffer(parent, parent->map_token, | ||
275 | KM_USER1); | ||
276 | parent->map_token = NULL; | ||
277 | } | ||
295 | return err; | 278 | return err; |
296 | } | 279 | } |
297 | 280 | ||
diff --git a/fs/btrfs/tree-defrag.c b/fs/btrfs/tree-defrag.c index b02355a7b143..65ef12351566 100644 --- a/fs/btrfs/tree-defrag.c +++ b/fs/btrfs/tree-defrag.c | |||
@@ -183,7 +183,6 @@ int btrfs_defrag_leaves(struct btrfs_trans_handle *trans, | |||
183 | if (level == 0) { | 183 | if (level == 0) { |
184 | goto out; | 184 | goto out; |
185 | } | 185 | } |
186 | |||
187 | if (root->defrag_progress.objectid == 0) { | 186 | if (root->defrag_progress.objectid == 0) { |
188 | extent_buffer_get(root->node); | 187 | extent_buffer_get(root->node); |
189 | ret = btrfs_cow_block(trans, root, root->node, NULL, 0, &tmp); | 188 | ret = btrfs_cow_block(trans, root, root->node, NULL, 0, &tmp); |