Commit 5708b9591617486bf1aa5b1a97f2c0549ec87933
1 parent
18f16f7ba6
Exists in
master
and in
7 other branches
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>
Showing 2 changed files with 26 additions and 44 deletions Side-by-side Diff
fs/btrfs/ctree.c
... | ... | @@ -161,34 +161,6 @@ |
161 | 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 | 164 | int btrfs_realloc_node(struct btrfs_trans_handle *trans, |
193 | 165 | struct btrfs_root *root, struct extent_buffer *parent, |
194 | 166 | int start_slot, int cache_only, u64 *last_ret, |
... | ... | @@ -208,6 +180,10 @@ |
208 | 180 | int uptodate; |
209 | 181 | u32 blocksize; |
210 | 182 | |
183 | + parent_level = btrfs_header_level(parent); | |
184 | + if (cache_only && parent_level != 1) | |
185 | + return 0; | |
186 | + | |
211 | 187 | if (trans->transaction != root->fs_info->running_transaction) { |
212 | 188 | printk(KERN_CRIT "trans %Lu running %Lu\n", trans->transid, |
213 | 189 | root->fs_info->running_transaction->transid); |
... | ... | @@ -218,7 +194,6 @@ |
218 | 194 | root->fs_info->generation); |
219 | 195 | WARN_ON(1); |
220 | 196 | } |
221 | - parent_level = btrfs_header_level(parent); | |
222 | 197 | |
223 | 198 | parent_nritems = btrfs_header_nritems(parent); |
224 | 199 | blocksize = btrfs_level_size(root, parent_level - 1); |
225 | 200 | |
226 | 201 | |
227 | 202 | |
... | ... | @@ -227,27 +202,26 @@ |
227 | 202 | if (parent_nritems == 1) |
228 | 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 | 205 | for (i = start_slot; i < end_slot; i++) { |
241 | 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 | 216 | blocknr = btrfs_node_blockptr(parent, i); |
244 | 217 | if (last_block == 0) |
245 | 218 | last_block = blocknr; |
219 | + | |
246 | 220 | if (i > 0) { |
247 | 221 | other = btrfs_node_blockptr(parent, i - 1); |
248 | 222 | close = close_blocks(blocknr, other, blocksize); |
249 | 223 | } |
250 | - if (close && i < end_slot - 1) { | |
224 | + if (close && i < end_slot - 2) { | |
251 | 225 | other = btrfs_node_blockptr(parent, i + 1); |
252 | 226 | close = close_blocks(blocknr, other, blocksize); |
253 | 227 | } |
254 | 228 | |
... | ... | @@ -255,15 +229,18 @@ |
255 | 229 | last_block = blocknr; |
256 | 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 | 238 | cur = btrfs_find_tree_block(root, blocknr, blocksize); |
260 | 239 | if (cur) |
261 | 240 | uptodate = btrfs_buffer_uptodate(cur); |
262 | 241 | else |
263 | 242 | uptodate = 0; |
264 | - if (!cur || !uptodate || | |
265 | - (parent_level != 1 && !btrfs_buffer_defrag(cur)) || | |
266 | - (parent_level == 1 && !should_defrag_leaf(cur))) { | |
243 | + if (!cur || !uptodate) { | |
267 | 244 | if (cache_only) { |
268 | 245 | free_extent_buffer(cur); |
269 | 246 | continue; |
270 | 247 | |
... | ... | @@ -287,10 +264,16 @@ |
287 | 264 | break; |
288 | 265 | } |
289 | 266 | search_start = tmp->start; |
267 | + last_block = tmp->start; | |
290 | 268 | *last_ret = search_start; |
291 | 269 | if (parent_level == 1) |
292 | 270 | btrfs_clear_buffer_defrag(tmp); |
293 | 271 | free_extent_buffer(tmp); |
272 | + } | |
273 | + if (parent->map_token) { | |
274 | + unmap_extent_buffer(parent, parent->map_token, | |
275 | + KM_USER1); | |
276 | + parent->map_token = NULL; | |
294 | 277 | } |
295 | 278 | return err; |
296 | 279 | } |
fs/btrfs/tree-defrag.c