diff options
author | Chris Mason <chris.mason@oracle.com> | 2007-08-10 14:06:19 -0400 |
---|---|---|
committer | David Woodhouse <dwmw2@hera.kernel.org> | 2007-08-10 14:06:19 -0400 |
commit | e9d0b13b5bbb58c9b840e407a8d181442f799966 (patch) | |
tree | d51a7e111a824e883c347c83745109400231de1c /fs/btrfs/transaction.c | |
parent | 409eb95d7f6632d5af32b795244ce68a29e49319 (diff) |
Btrfs: Btree defrag on the extent-mapping tree as well
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/transaction.c')
-rw-r--r-- | fs/btrfs/transaction.c | 91 |
1 files changed, 49 insertions, 42 deletions
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 204337c5ca0f..c9d52dc83e48 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
@@ -317,18 +317,47 @@ static int add_dirty_roots(struct btrfs_trans_handle *trans, | |||
317 | return err; | 317 | return err; |
318 | } | 318 | } |
319 | 319 | ||
320 | int btrfs_defrag_root(struct btrfs_root *root, int cacheonly) | ||
321 | { | ||
322 | struct btrfs_fs_info *info = root->fs_info; | ||
323 | int ret; | ||
324 | struct btrfs_trans_handle *trans; | ||
325 | |||
326 | if (root->defrag_running) | ||
327 | return 0; | ||
328 | |||
329 | trans = btrfs_start_transaction(root, 1); | ||
330 | while (1) { | ||
331 | root->defrag_running = 1; | ||
332 | ret = btrfs_defrag_leaves(trans, root, cacheonly); | ||
333 | btrfs_end_transaction(trans, root); | ||
334 | mutex_unlock(&info->fs_mutex); | ||
335 | |||
336 | btrfs_btree_balance_dirty(root); | ||
337 | cond_resched(); | ||
338 | |||
339 | mutex_lock(&info->fs_mutex); | ||
340 | trans = btrfs_start_transaction(root, 1); | ||
341 | if (ret != -EAGAIN) | ||
342 | break; | ||
343 | } | ||
344 | root->defrag_running = 0; | ||
345 | radix_tree_tag_clear(&info->fs_roots_radix, | ||
346 | (unsigned long)root->root_key.objectid, | ||
347 | BTRFS_ROOT_DEFRAG_TAG); | ||
348 | btrfs_end_transaction(trans, root); | ||
349 | return 0; | ||
350 | } | ||
351 | |||
320 | int btrfs_defrag_dirty_roots(struct btrfs_fs_info *info) | 352 | int btrfs_defrag_dirty_roots(struct btrfs_fs_info *info) |
321 | { | 353 | { |
322 | struct btrfs_root *gang[1]; | 354 | struct btrfs_root *gang[1]; |
323 | struct btrfs_root *root; | 355 | struct btrfs_root *root; |
324 | struct btrfs_root *tree_root = info->tree_root; | ||
325 | struct btrfs_trans_handle *trans; | ||
326 | int i; | 356 | int i; |
327 | int ret; | 357 | int ret; |
328 | int err = 0; | 358 | int err = 0; |
329 | u64 last = 0; | 359 | u64 last = 0; |
330 | 360 | ||
331 | trans = btrfs_start_transaction(tree_root, 1); | ||
332 | while(1) { | 361 | while(1) { |
333 | ret = radix_tree_gang_lookup_tag(&info->fs_roots_radix, | 362 | ret = radix_tree_gang_lookup_tag(&info->fs_roots_radix, |
334 | (void **)gang, last, | 363 | (void **)gang, last, |
@@ -339,37 +368,10 @@ int btrfs_defrag_dirty_roots(struct btrfs_fs_info *info) | |||
339 | for (i = 0; i < ret; i++) { | 368 | for (i = 0; i < ret; i++) { |
340 | root = gang[i]; | 369 | root = gang[i]; |
341 | last = root->root_key.objectid + 1; | 370 | last = root->root_key.objectid + 1; |
342 | radix_tree_tag_clear(&info->fs_roots_radix, | 371 | btrfs_defrag_root(root, 1); |
343 | (unsigned long)root->root_key.objectid, | ||
344 | BTRFS_ROOT_DEFRAG_TAG); | ||
345 | if (root->defrag_running) | ||
346 | continue; | ||
347 | |||
348 | while (1) { | ||
349 | mutex_lock(&root->fs_info->trans_mutex); | ||
350 | record_root_in_trans(root); | ||
351 | mutex_unlock(&root->fs_info->trans_mutex); | ||
352 | |||
353 | root->defrag_running = 1; | ||
354 | err = btrfs_defrag_leaves(trans, root, 1); | ||
355 | btrfs_end_transaction(trans, tree_root); | ||
356 | mutex_unlock(&info->fs_mutex); | ||
357 | |||
358 | btrfs_btree_balance_dirty(root); | ||
359 | cond_resched(); | ||
360 | |||
361 | mutex_lock(&info->fs_mutex); | ||
362 | trans = btrfs_start_transaction(tree_root, 1); | ||
363 | if (err != -EAGAIN) | ||
364 | break; | ||
365 | } | ||
366 | root->defrag_running = 0; | ||
367 | radix_tree_tag_clear(&info->fs_roots_radix, | ||
368 | (unsigned long)root->root_key.objectid, | ||
369 | BTRFS_ROOT_DEFRAG_TAG); | ||
370 | } | 372 | } |
371 | } | 373 | } |
372 | btrfs_end_transaction(trans, tree_root); | 374 | btrfs_defrag_root(info->extent_root, 1); |
373 | return err; | 375 | return err; |
374 | } | 376 | } |
375 | 377 | ||
@@ -527,6 +529,20 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
527 | return ret; | 529 | return ret; |
528 | } | 530 | } |
529 | 531 | ||
532 | int btrfs_clean_old_snapshots(struct btrfs_root *root) | ||
533 | { | ||
534 | struct list_head dirty_roots; | ||
535 | INIT_LIST_HEAD(&dirty_roots); | ||
536 | |||
537 | mutex_lock(&root->fs_info->trans_mutex); | ||
538 | list_splice_init(&root->fs_info->dead_roots, &dirty_roots); | ||
539 | mutex_unlock(&root->fs_info->trans_mutex); | ||
540 | |||
541 | if (!list_empty(&dirty_roots)) { | ||
542 | drop_dirty_roots(root, &dirty_roots); | ||
543 | } | ||
544 | return 0; | ||
545 | } | ||
530 | void btrfs_transaction_cleaner(struct work_struct *work) | 546 | void btrfs_transaction_cleaner(struct work_struct *work) |
531 | { | 547 | { |
532 | struct btrfs_fs_info *fs_info = container_of(work, | 548 | struct btrfs_fs_info *fs_info = container_of(work, |
@@ -536,12 +552,10 @@ void btrfs_transaction_cleaner(struct work_struct *work) | |||
536 | struct btrfs_root *root = fs_info->tree_root; | 552 | struct btrfs_root *root = fs_info->tree_root; |
537 | struct btrfs_transaction *cur; | 553 | struct btrfs_transaction *cur; |
538 | struct btrfs_trans_handle *trans; | 554 | struct btrfs_trans_handle *trans; |
539 | struct list_head dirty_roots; | ||
540 | unsigned long now; | 555 | unsigned long now; |
541 | unsigned long delay = HZ * 30; | 556 | unsigned long delay = HZ * 30; |
542 | int ret; | 557 | int ret; |
543 | 558 | ||
544 | INIT_LIST_HEAD(&dirty_roots); | ||
545 | mutex_lock(&root->fs_info->fs_mutex); | 559 | mutex_lock(&root->fs_info->fs_mutex); |
546 | mutex_lock(&root->fs_info->trans_mutex); | 560 | mutex_lock(&root->fs_info->trans_mutex); |
547 | cur = root->fs_info->running_transaction; | 561 | cur = root->fs_info->running_transaction; |
@@ -561,14 +575,7 @@ void btrfs_transaction_cleaner(struct work_struct *work) | |||
561 | ret = btrfs_commit_transaction(trans, root); | 575 | ret = btrfs_commit_transaction(trans, root); |
562 | out: | 576 | out: |
563 | mutex_unlock(&root->fs_info->fs_mutex); | 577 | mutex_unlock(&root->fs_info->fs_mutex); |
564 | 578 | btrfs_clean_old_snapshots(root); | |
565 | mutex_lock(&root->fs_info->trans_mutex); | ||
566 | list_splice_init(&root->fs_info->dead_roots, &dirty_roots); | ||
567 | mutex_unlock(&root->fs_info->trans_mutex); | ||
568 | |||
569 | if (!list_empty(&dirty_roots)) { | ||
570 | drop_dirty_roots(root, &dirty_roots); | ||
571 | } | ||
572 | btrfs_transaction_queue_work(root, delay); | 579 | btrfs_transaction_queue_work(root, delay); |
573 | } | 580 | } |
574 | 581 | ||