aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/transaction.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2007-08-10 14:06:19 -0400
committerDavid Woodhouse <dwmw2@hera.kernel.org>2007-08-10 14:06:19 -0400
commite9d0b13b5bbb58c9b840e407a8d181442f799966 (patch)
treed51a7e111a824e883c347c83745109400231de1c /fs/btrfs/transaction.c
parent409eb95d7f6632d5af32b795244ce68a29e49319 (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.c91
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
320int 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
320int btrfs_defrag_dirty_roots(struct btrfs_fs_info *info) 352int 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
532int 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}
530void btrfs_transaction_cleaner(struct work_struct *work) 546void 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);
562out: 576out:
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