diff options
Diffstat (limited to 'fs/btrfs/ordered-data.c')
-rw-r--r-- | fs/btrfs/ordered-data.c | 68 |
1 files changed, 49 insertions, 19 deletions
diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c index b16450b840e7..a94b05f72869 100644 --- a/fs/btrfs/ordered-data.c +++ b/fs/btrfs/ordered-data.c | |||
@@ -349,10 +349,13 @@ int btrfs_dec_test_first_ordered_pending(struct inode *inode, | |||
349 | if (!uptodate) | 349 | if (!uptodate) |
350 | set_bit(BTRFS_ORDERED_IOERR, &entry->flags); | 350 | set_bit(BTRFS_ORDERED_IOERR, &entry->flags); |
351 | 351 | ||
352 | if (entry->bytes_left == 0) | 352 | if (entry->bytes_left == 0) { |
353 | ret = test_and_set_bit(BTRFS_ORDERED_IO_DONE, &entry->flags); | 353 | ret = test_and_set_bit(BTRFS_ORDERED_IO_DONE, &entry->flags); |
354 | else | 354 | if (waitqueue_active(&entry->wait)) |
355 | wake_up(&entry->wait); | ||
356 | } else { | ||
355 | ret = 1; | 357 | ret = 1; |
358 | } | ||
356 | out: | 359 | out: |
357 | if (!ret && cached && entry) { | 360 | if (!ret && cached && entry) { |
358 | *cached = entry; | 361 | *cached = entry; |
@@ -410,10 +413,13 @@ have_entry: | |||
410 | if (!uptodate) | 413 | if (!uptodate) |
411 | set_bit(BTRFS_ORDERED_IOERR, &entry->flags); | 414 | set_bit(BTRFS_ORDERED_IOERR, &entry->flags); |
412 | 415 | ||
413 | if (entry->bytes_left == 0) | 416 | if (entry->bytes_left == 0) { |
414 | ret = test_and_set_bit(BTRFS_ORDERED_IO_DONE, &entry->flags); | 417 | ret = test_and_set_bit(BTRFS_ORDERED_IO_DONE, &entry->flags); |
415 | else | 418 | if (waitqueue_active(&entry->wait)) |
419 | wake_up(&entry->wait); | ||
420 | } else { | ||
416 | ret = 1; | 421 | ret = 1; |
422 | } | ||
417 | out: | 423 | out: |
418 | if (!ret && cached && entry) { | 424 | if (!ret && cached && entry) { |
419 | *cached = entry; | 425 | *cached = entry; |
@@ -424,27 +430,48 @@ out: | |||
424 | } | 430 | } |
425 | 431 | ||
426 | /* Needs to either be called under a log transaction or the log_mutex */ | 432 | /* Needs to either be called under a log transaction or the log_mutex */ |
427 | void btrfs_get_logged_extents(struct btrfs_root *log, struct inode *inode) | 433 | void btrfs_get_logged_extents(struct inode *inode, |
434 | struct list_head *logged_list) | ||
428 | { | 435 | { |
429 | struct btrfs_ordered_inode_tree *tree; | 436 | struct btrfs_ordered_inode_tree *tree; |
430 | struct btrfs_ordered_extent *ordered; | 437 | struct btrfs_ordered_extent *ordered; |
431 | struct rb_node *n; | 438 | struct rb_node *n; |
432 | int index = log->log_transid % 2; | ||
433 | 439 | ||
434 | tree = &BTRFS_I(inode)->ordered_tree; | 440 | tree = &BTRFS_I(inode)->ordered_tree; |
435 | spin_lock_irq(&tree->lock); | 441 | spin_lock_irq(&tree->lock); |
436 | for (n = rb_first(&tree->tree); n; n = rb_next(n)) { | 442 | for (n = rb_first(&tree->tree); n; n = rb_next(n)) { |
437 | ordered = rb_entry(n, struct btrfs_ordered_extent, rb_node); | 443 | ordered = rb_entry(n, struct btrfs_ordered_extent, rb_node); |
438 | spin_lock(&log->log_extents_lock[index]); | 444 | if (!list_empty(&ordered->log_list)) |
439 | if (list_empty(&ordered->log_list)) { | 445 | continue; |
440 | list_add_tail(&ordered->log_list, &log->logged_list[index]); | 446 | list_add_tail(&ordered->log_list, logged_list); |
441 | atomic_inc(&ordered->refs); | 447 | atomic_inc(&ordered->refs); |
442 | } | ||
443 | spin_unlock(&log->log_extents_lock[index]); | ||
444 | } | 448 | } |
445 | spin_unlock_irq(&tree->lock); | 449 | spin_unlock_irq(&tree->lock); |
446 | } | 450 | } |
447 | 451 | ||
452 | void btrfs_put_logged_extents(struct list_head *logged_list) | ||
453 | { | ||
454 | struct btrfs_ordered_extent *ordered; | ||
455 | |||
456 | while (!list_empty(logged_list)) { | ||
457 | ordered = list_first_entry(logged_list, | ||
458 | struct btrfs_ordered_extent, | ||
459 | log_list); | ||
460 | list_del_init(&ordered->log_list); | ||
461 | btrfs_put_ordered_extent(ordered); | ||
462 | } | ||
463 | } | ||
464 | |||
465 | void btrfs_submit_logged_extents(struct list_head *logged_list, | ||
466 | struct btrfs_root *log) | ||
467 | { | ||
468 | int index = log->log_transid % 2; | ||
469 | |||
470 | spin_lock_irq(&log->log_extents_lock[index]); | ||
471 | list_splice_tail(logged_list, &log->logged_list[index]); | ||
472 | spin_unlock_irq(&log->log_extents_lock[index]); | ||
473 | } | ||
474 | |||
448 | void btrfs_wait_logged_extents(struct btrfs_root *log, u64 transid) | 475 | void btrfs_wait_logged_extents(struct btrfs_root *log, u64 transid) |
449 | { | 476 | { |
450 | struct btrfs_ordered_extent *ordered; | 477 | struct btrfs_ordered_extent *ordered; |
@@ -577,7 +604,7 @@ int btrfs_wait_ordered_extents(struct btrfs_root *root, int nr) | |||
577 | INIT_LIST_HEAD(&splice); | 604 | INIT_LIST_HEAD(&splice); |
578 | INIT_LIST_HEAD(&works); | 605 | INIT_LIST_HEAD(&works); |
579 | 606 | ||
580 | mutex_lock(&root->fs_info->ordered_operations_mutex); | 607 | mutex_lock(&root->ordered_extent_mutex); |
581 | spin_lock(&root->ordered_extent_lock); | 608 | spin_lock(&root->ordered_extent_lock); |
582 | list_splice_init(&root->ordered_extents, &splice); | 609 | list_splice_init(&root->ordered_extents, &splice); |
583 | while (!list_empty(&splice) && nr) { | 610 | while (!list_empty(&splice) && nr) { |
@@ -588,10 +615,11 @@ int btrfs_wait_ordered_extents(struct btrfs_root *root, int nr) | |||
588 | atomic_inc(&ordered->refs); | 615 | atomic_inc(&ordered->refs); |
589 | spin_unlock(&root->ordered_extent_lock); | 616 | spin_unlock(&root->ordered_extent_lock); |
590 | 617 | ||
591 | ordered->flush_work.func = btrfs_run_ordered_extent_work; | 618 | btrfs_init_work(&ordered->flush_work, |
619 | btrfs_run_ordered_extent_work, NULL, NULL); | ||
592 | list_add_tail(&ordered->work_list, &works); | 620 | list_add_tail(&ordered->work_list, &works); |
593 | btrfs_queue_worker(&root->fs_info->flush_workers, | 621 | btrfs_queue_work(root->fs_info->flush_workers, |
594 | &ordered->flush_work); | 622 | &ordered->flush_work); |
595 | 623 | ||
596 | cond_resched(); | 624 | cond_resched(); |
597 | spin_lock(&root->ordered_extent_lock); | 625 | spin_lock(&root->ordered_extent_lock); |
@@ -608,7 +636,7 @@ int btrfs_wait_ordered_extents(struct btrfs_root *root, int nr) | |||
608 | btrfs_put_ordered_extent(ordered); | 636 | btrfs_put_ordered_extent(ordered); |
609 | cond_resched(); | 637 | cond_resched(); |
610 | } | 638 | } |
611 | mutex_unlock(&root->fs_info->ordered_operations_mutex); | 639 | mutex_unlock(&root->ordered_extent_mutex); |
612 | 640 | ||
613 | return count; | 641 | return count; |
614 | } | 642 | } |
@@ -621,6 +649,7 @@ void btrfs_wait_ordered_roots(struct btrfs_fs_info *fs_info, int nr) | |||
621 | 649 | ||
622 | INIT_LIST_HEAD(&splice); | 650 | INIT_LIST_HEAD(&splice); |
623 | 651 | ||
652 | mutex_lock(&fs_info->ordered_operations_mutex); | ||
624 | spin_lock(&fs_info->ordered_root_lock); | 653 | spin_lock(&fs_info->ordered_root_lock); |
625 | list_splice_init(&fs_info->ordered_roots, &splice); | 654 | list_splice_init(&fs_info->ordered_roots, &splice); |
626 | while (!list_empty(&splice) && nr) { | 655 | while (!list_empty(&splice) && nr) { |
@@ -643,6 +672,7 @@ void btrfs_wait_ordered_roots(struct btrfs_fs_info *fs_info, int nr) | |||
643 | } | 672 | } |
644 | list_splice_tail(&splice, &fs_info->ordered_roots); | 673 | list_splice_tail(&splice, &fs_info->ordered_roots); |
645 | spin_unlock(&fs_info->ordered_root_lock); | 674 | spin_unlock(&fs_info->ordered_root_lock); |
675 | mutex_unlock(&fs_info->ordered_operations_mutex); | ||
646 | } | 676 | } |
647 | 677 | ||
648 | /* | 678 | /* |
@@ -704,8 +734,8 @@ int btrfs_run_ordered_operations(struct btrfs_trans_handle *trans, | |||
704 | goto out; | 734 | goto out; |
705 | } | 735 | } |
706 | list_add_tail(&work->list, &works); | 736 | list_add_tail(&work->list, &works); |
707 | btrfs_queue_worker(&root->fs_info->flush_workers, | 737 | btrfs_queue_work(root->fs_info->flush_workers, |
708 | &work->work); | 738 | &work->work); |
709 | 739 | ||
710 | cond_resched(); | 740 | cond_resched(); |
711 | spin_lock(&root->fs_info->ordered_root_lock); | 741 | spin_lock(&root->fs_info->ordered_root_lock); |