diff options
Diffstat (limited to 'fs/btrfs/ordered-data.c')
-rw-r--r-- | fs/btrfs/ordered-data.c | 90 |
1 files changed, 63 insertions, 27 deletions
diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c index 7772f02ba28e..f10731297040 100644 --- a/fs/btrfs/ordered-data.c +++ b/fs/btrfs/ordered-data.c | |||
@@ -211,6 +211,8 @@ static int __btrfs_add_ordered_extent(struct inode *inode, u64 file_offset, | |||
211 | init_waitqueue_head(&entry->wait); | 211 | init_waitqueue_head(&entry->wait); |
212 | INIT_LIST_HEAD(&entry->list); | 212 | INIT_LIST_HEAD(&entry->list); |
213 | INIT_LIST_HEAD(&entry->root_extent_list); | 213 | INIT_LIST_HEAD(&entry->root_extent_list); |
214 | INIT_LIST_HEAD(&entry->work_list); | ||
215 | init_completion(&entry->completion); | ||
214 | 216 | ||
215 | trace_btrfs_ordered_extent_add(inode, entry); | 217 | trace_btrfs_ordered_extent_add(inode, entry); |
216 | 218 | ||
@@ -464,18 +466,28 @@ void btrfs_remove_ordered_extent(struct inode *inode, | |||
464 | wake_up(&entry->wait); | 466 | wake_up(&entry->wait); |
465 | } | 467 | } |
466 | 468 | ||
469 | static void btrfs_run_ordered_extent_work(struct btrfs_work *work) | ||
470 | { | ||
471 | struct btrfs_ordered_extent *ordered; | ||
472 | |||
473 | ordered = container_of(work, struct btrfs_ordered_extent, flush_work); | ||
474 | btrfs_start_ordered_extent(ordered->inode, ordered, 1); | ||
475 | complete(&ordered->completion); | ||
476 | } | ||
477 | |||
467 | /* | 478 | /* |
468 | * wait for all the ordered extents in a root. This is done when balancing | 479 | * wait for all the ordered extents in a root. This is done when balancing |
469 | * space between drives. | 480 | * space between drives. |
470 | */ | 481 | */ |
471 | void btrfs_wait_ordered_extents(struct btrfs_root *root, int delay_iput) | 482 | void btrfs_wait_ordered_extents(struct btrfs_root *root, int delay_iput) |
472 | { | 483 | { |
473 | struct list_head splice; | 484 | struct list_head splice, works; |
474 | struct list_head *cur; | 485 | struct list_head *cur; |
475 | struct btrfs_ordered_extent *ordered; | 486 | struct btrfs_ordered_extent *ordered, *next; |
476 | struct inode *inode; | 487 | struct inode *inode; |
477 | 488 | ||
478 | INIT_LIST_HEAD(&splice); | 489 | INIT_LIST_HEAD(&splice); |
490 | INIT_LIST_HEAD(&works); | ||
479 | 491 | ||
480 | spin_lock(&root->fs_info->ordered_extent_lock); | 492 | spin_lock(&root->fs_info->ordered_extent_lock); |
481 | list_splice_init(&root->fs_info->ordered_extents, &splice); | 493 | list_splice_init(&root->fs_info->ordered_extents, &splice); |
@@ -494,19 +506,32 @@ void btrfs_wait_ordered_extents(struct btrfs_root *root, int delay_iput) | |||
494 | spin_unlock(&root->fs_info->ordered_extent_lock); | 506 | spin_unlock(&root->fs_info->ordered_extent_lock); |
495 | 507 | ||
496 | if (inode) { | 508 | if (inode) { |
497 | btrfs_start_ordered_extent(inode, ordered, 1); | 509 | ordered->flush_work.func = btrfs_run_ordered_extent_work; |
498 | btrfs_put_ordered_extent(ordered); | 510 | list_add_tail(&ordered->work_list, &works); |
499 | if (delay_iput) | 511 | btrfs_queue_worker(&root->fs_info->flush_workers, |
500 | btrfs_add_delayed_iput(inode); | 512 | &ordered->flush_work); |
501 | else | ||
502 | iput(inode); | ||
503 | } else { | 513 | } else { |
504 | btrfs_put_ordered_extent(ordered); | 514 | btrfs_put_ordered_extent(ordered); |
505 | } | 515 | } |
506 | 516 | ||
517 | cond_resched(); | ||
507 | spin_lock(&root->fs_info->ordered_extent_lock); | 518 | spin_lock(&root->fs_info->ordered_extent_lock); |
508 | } | 519 | } |
509 | spin_unlock(&root->fs_info->ordered_extent_lock); | 520 | spin_unlock(&root->fs_info->ordered_extent_lock); |
521 | |||
522 | list_for_each_entry_safe(ordered, next, &works, work_list) { | ||
523 | list_del_init(&ordered->work_list); | ||
524 | wait_for_completion(&ordered->completion); | ||
525 | |||
526 | inode = ordered->inode; | ||
527 | btrfs_put_ordered_extent(ordered); | ||
528 | if (delay_iput) | ||
529 | btrfs_add_delayed_iput(inode); | ||
530 | else | ||
531 | iput(inode); | ||
532 | |||
533 | cond_resched(); | ||
534 | } | ||
510 | } | 535 | } |
511 | 536 | ||
512 | /* | 537 | /* |
@@ -519,13 +544,17 @@ void btrfs_wait_ordered_extents(struct btrfs_root *root, int delay_iput) | |||
519 | * extra check to make sure the ordered operation list really is empty | 544 | * extra check to make sure the ordered operation list really is empty |
520 | * before we return | 545 | * before we return |
521 | */ | 546 | */ |
522 | void btrfs_run_ordered_operations(struct btrfs_root *root, int wait) | 547 | int btrfs_run_ordered_operations(struct btrfs_root *root, int wait) |
523 | { | 548 | { |
524 | struct btrfs_inode *btrfs_inode; | 549 | struct btrfs_inode *btrfs_inode; |
525 | struct inode *inode; | 550 | struct inode *inode; |
526 | struct list_head splice; | 551 | struct list_head splice; |
552 | struct list_head works; | ||
553 | struct btrfs_delalloc_work *work, *next; | ||
554 | int ret = 0; | ||
527 | 555 | ||
528 | INIT_LIST_HEAD(&splice); | 556 | INIT_LIST_HEAD(&splice); |
557 | INIT_LIST_HEAD(&works); | ||
529 | 558 | ||
530 | mutex_lock(&root->fs_info->ordered_operations_mutex); | 559 | mutex_lock(&root->fs_info->ordered_operations_mutex); |
531 | spin_lock(&root->fs_info->ordered_extent_lock); | 560 | spin_lock(&root->fs_info->ordered_extent_lock); |
@@ -533,6 +562,7 @@ again: | |||
533 | list_splice_init(&root->fs_info->ordered_operations, &splice); | 562 | list_splice_init(&root->fs_info->ordered_operations, &splice); |
534 | 563 | ||
535 | while (!list_empty(&splice)) { | 564 | while (!list_empty(&splice)) { |
565 | |||
536 | btrfs_inode = list_entry(splice.next, struct btrfs_inode, | 566 | btrfs_inode = list_entry(splice.next, struct btrfs_inode, |
537 | ordered_operations); | 567 | ordered_operations); |
538 | 568 | ||
@@ -549,15 +579,26 @@ again: | |||
549 | list_add_tail(&BTRFS_I(inode)->ordered_operations, | 579 | list_add_tail(&BTRFS_I(inode)->ordered_operations, |
550 | &root->fs_info->ordered_operations); | 580 | &root->fs_info->ordered_operations); |
551 | } | 581 | } |
582 | |||
583 | if (!inode) | ||
584 | continue; | ||
552 | spin_unlock(&root->fs_info->ordered_extent_lock); | 585 | spin_unlock(&root->fs_info->ordered_extent_lock); |
553 | 586 | ||
554 | if (inode) { | 587 | work = btrfs_alloc_delalloc_work(inode, wait, 1); |
555 | if (wait) | 588 | if (!work) { |
556 | btrfs_wait_ordered_range(inode, 0, (u64)-1); | 589 | if (list_empty(&BTRFS_I(inode)->ordered_operations)) |
557 | else | 590 | list_add_tail(&btrfs_inode->ordered_operations, |
558 | filemap_flush(inode->i_mapping); | 591 | &splice); |
559 | btrfs_add_delayed_iput(inode); | 592 | spin_lock(&root->fs_info->ordered_extent_lock); |
593 | list_splice_tail(&splice, | ||
594 | &root->fs_info->ordered_operations); | ||
595 | spin_unlock(&root->fs_info->ordered_extent_lock); | ||
596 | ret = -ENOMEM; | ||
597 | goto out; | ||
560 | } | 598 | } |
599 | list_add_tail(&work->list, &works); | ||
600 | btrfs_queue_worker(&root->fs_info->flush_workers, | ||
601 | &work->work); | ||
561 | 602 | ||
562 | cond_resched(); | 603 | cond_resched(); |
563 | spin_lock(&root->fs_info->ordered_extent_lock); | 604 | spin_lock(&root->fs_info->ordered_extent_lock); |
@@ -566,7 +607,13 @@ again: | |||
566 | goto again; | 607 | goto again; |
567 | 608 | ||
568 | spin_unlock(&root->fs_info->ordered_extent_lock); | 609 | spin_unlock(&root->fs_info->ordered_extent_lock); |
610 | out: | ||
611 | list_for_each_entry_safe(work, next, &works, list) { | ||
612 | list_del_init(&work->list); | ||
613 | btrfs_wait_and_free_delalloc_work(work); | ||
614 | } | ||
569 | mutex_unlock(&root->fs_info->ordered_operations_mutex); | 615 | mutex_unlock(&root->fs_info->ordered_operations_mutex); |
616 | return ret; | ||
570 | } | 617 | } |
571 | 618 | ||
572 | /* | 619 | /* |
@@ -606,7 +653,6 @@ void btrfs_wait_ordered_range(struct inode *inode, u64 start, u64 len) | |||
606 | u64 end; | 653 | u64 end; |
607 | u64 orig_end; | 654 | u64 orig_end; |
608 | struct btrfs_ordered_extent *ordered; | 655 | struct btrfs_ordered_extent *ordered; |
609 | int found; | ||
610 | 656 | ||
611 | if (start + len < start) { | 657 | if (start + len < start) { |
612 | orig_end = INT_LIMIT(loff_t); | 658 | orig_end = INT_LIMIT(loff_t); |
@@ -642,7 +688,6 @@ void btrfs_wait_ordered_range(struct inode *inode, u64 start, u64 len) | |||
642 | filemap_fdatawait_range(inode->i_mapping, start, orig_end); | 688 | filemap_fdatawait_range(inode->i_mapping, start, orig_end); |
643 | 689 | ||
644 | end = orig_end; | 690 | end = orig_end; |
645 | found = 0; | ||
646 | while (1) { | 691 | while (1) { |
647 | ordered = btrfs_lookup_first_ordered_extent(inode, end); | 692 | ordered = btrfs_lookup_first_ordered_extent(inode, end); |
648 | if (!ordered) | 693 | if (!ordered) |
@@ -655,7 +700,6 @@ void btrfs_wait_ordered_range(struct inode *inode, u64 start, u64 len) | |||
655 | btrfs_put_ordered_extent(ordered); | 700 | btrfs_put_ordered_extent(ordered); |
656 | break; | 701 | break; |
657 | } | 702 | } |
658 | found++; | ||
659 | btrfs_start_ordered_extent(inode, ordered, 1); | 703 | btrfs_start_ordered_extent(inode, ordered, 1); |
660 | end = ordered->file_offset; | 704 | end = ordered->file_offset; |
661 | btrfs_put_ordered_extent(ordered); | 705 | btrfs_put_ordered_extent(ordered); |
@@ -934,15 +978,6 @@ void btrfs_add_ordered_operation(struct btrfs_trans_handle *trans, | |||
934 | if (last_mod < root->fs_info->last_trans_committed) | 978 | if (last_mod < root->fs_info->last_trans_committed) |
935 | return; | 979 | return; |
936 | 980 | ||
937 | /* | ||
938 | * the transaction is already committing. Just start the IO and | ||
939 | * don't bother with all of this list nonsense | ||
940 | */ | ||
941 | if (trans && root->fs_info->running_transaction->blocked) { | ||
942 | btrfs_wait_ordered_range(inode, 0, (u64)-1); | ||
943 | return; | ||
944 | } | ||
945 | |||
946 | spin_lock(&root->fs_info->ordered_extent_lock); | 981 | spin_lock(&root->fs_info->ordered_extent_lock); |
947 | if (list_empty(&BTRFS_I(inode)->ordered_operations)) { | 982 | if (list_empty(&BTRFS_I(inode)->ordered_operations)) { |
948 | list_add_tail(&BTRFS_I(inode)->ordered_operations, | 983 | list_add_tail(&BTRFS_I(inode)->ordered_operations, |
@@ -959,6 +994,7 @@ int __init ordered_data_init(void) | |||
959 | NULL); | 994 | NULL); |
960 | if (!btrfs_ordered_extent_cache) | 995 | if (!btrfs_ordered_extent_cache) |
961 | return -ENOMEM; | 996 | return -ENOMEM; |
997 | |||
962 | return 0; | 998 | return 0; |
963 | } | 999 | } |
964 | 1000 | ||