diff options
Diffstat (limited to 'fs/btrfs/ordered-data.c')
| -rw-r--r-- | fs/btrfs/ordered-data.c | 98 |
1 files changed, 80 insertions, 18 deletions
diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c index e5ed56729607..dc08d77b717e 100644 --- a/fs/btrfs/ordered-data.c +++ b/fs/btrfs/ordered-data.c | |||
| @@ -196,6 +196,9 @@ static int __btrfs_add_ordered_extent(struct inode *inode, u64 file_offset, | |||
| 196 | entry->file_offset = file_offset; | 196 | entry->file_offset = file_offset; |
| 197 | entry->start = start; | 197 | entry->start = start; |
| 198 | entry->len = len; | 198 | entry->len = len; |
| 199 | if (!(BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM) && | ||
| 200 | !(type == BTRFS_ORDERED_NOCOW)) | ||
| 201 | entry->csum_bytes_left = disk_len; | ||
| 199 | entry->disk_len = disk_len; | 202 | entry->disk_len = disk_len; |
| 200 | entry->bytes_left = len; | 203 | entry->bytes_left = len; |
| 201 | entry->inode = igrab(inode); | 204 | entry->inode = igrab(inode); |
| @@ -213,6 +216,7 @@ static int __btrfs_add_ordered_extent(struct inode *inode, u64 file_offset, | |||
| 213 | INIT_LIST_HEAD(&entry->root_extent_list); | 216 | INIT_LIST_HEAD(&entry->root_extent_list); |
| 214 | INIT_LIST_HEAD(&entry->work_list); | 217 | INIT_LIST_HEAD(&entry->work_list); |
| 215 | init_completion(&entry->completion); | 218 | init_completion(&entry->completion); |
| 219 | INIT_LIST_HEAD(&entry->log_list); | ||
| 216 | 220 | ||
| 217 | trace_btrfs_ordered_extent_add(inode, entry); | 221 | trace_btrfs_ordered_extent_add(inode, entry); |
| 218 | 222 | ||
| @@ -270,6 +274,10 @@ void btrfs_add_ordered_sum(struct inode *inode, | |||
| 270 | tree = &BTRFS_I(inode)->ordered_tree; | 274 | tree = &BTRFS_I(inode)->ordered_tree; |
| 271 | spin_lock_irq(&tree->lock); | 275 | spin_lock_irq(&tree->lock); |
| 272 | list_add_tail(&sum->list, &entry->list); | 276 | list_add_tail(&sum->list, &entry->list); |
| 277 | WARN_ON(entry->csum_bytes_left < sum->len); | ||
| 278 | entry->csum_bytes_left -= sum->len; | ||
| 279 | if (entry->csum_bytes_left == 0) | ||
| 280 | wake_up(&entry->wait); | ||
| 273 | spin_unlock_irq(&tree->lock); | 281 | spin_unlock_irq(&tree->lock); |
| 274 | } | 282 | } |
| 275 | 283 | ||
| @@ -405,6 +413,66 @@ out: | |||
| 405 | return ret == 0; | 413 | return ret == 0; |
| 406 | } | 414 | } |
| 407 | 415 | ||
| 416 | /* Needs to either be called under a log transaction or the log_mutex */ | ||
| 417 | void btrfs_get_logged_extents(struct btrfs_root *log, struct inode *inode) | ||
| 418 | { | ||
| 419 | struct btrfs_ordered_inode_tree *tree; | ||
| 420 | struct btrfs_ordered_extent *ordered; | ||
| 421 | struct rb_node *n; | ||
| 422 | int index = log->log_transid % 2; | ||
| 423 | |||
| 424 | tree = &BTRFS_I(inode)->ordered_tree; | ||
| 425 | spin_lock_irq(&tree->lock); | ||
| 426 | for (n = rb_first(&tree->tree); n; n = rb_next(n)) { | ||
| 427 | ordered = rb_entry(n, struct btrfs_ordered_extent, rb_node); | ||
| 428 | spin_lock(&log->log_extents_lock[index]); | ||
| 429 | if (list_empty(&ordered->log_list)) { | ||
| 430 | list_add_tail(&ordered->log_list, &log->logged_list[index]); | ||
| 431 | atomic_inc(&ordered->refs); | ||
| 432 | } | ||
| 433 | spin_unlock(&log->log_extents_lock[index]); | ||
| 434 | } | ||
| 435 | spin_unlock_irq(&tree->lock); | ||
| 436 | } | ||
| 437 | |||
| 438 | void btrfs_wait_logged_extents(struct btrfs_root *log, u64 transid) | ||
| 439 | { | ||
| 440 | struct btrfs_ordered_extent *ordered; | ||
| 441 | int index = transid % 2; | ||
| 442 | |||
| 443 | spin_lock_irq(&log->log_extents_lock[index]); | ||
| 444 | while (!list_empty(&log->logged_list[index])) { | ||
| 445 | ordered = list_first_entry(&log->logged_list[index], | ||
| 446 | struct btrfs_ordered_extent, | ||
| 447 | log_list); | ||
| 448 | list_del_init(&ordered->log_list); | ||
| 449 | spin_unlock_irq(&log->log_extents_lock[index]); | ||
| 450 | wait_event(ordered->wait, test_bit(BTRFS_ORDERED_IO_DONE, | ||
| 451 | &ordered->flags)); | ||
| 452 | btrfs_put_ordered_extent(ordered); | ||
| 453 | spin_lock_irq(&log->log_extents_lock[index]); | ||
| 454 | } | ||
| 455 | spin_unlock_irq(&log->log_extents_lock[index]); | ||
| 456 | } | ||
| 457 | |||
| 458 | void btrfs_free_logged_extents(struct btrfs_root *log, u64 transid) | ||
| 459 | { | ||
| 460 | struct btrfs_ordered_extent *ordered; | ||
| 461 | int index = transid % 2; | ||
| 462 | |||
| 463 | spin_lock_irq(&log->log_extents_lock[index]); | ||
| 464 | while (!list_empty(&log->logged_list[index])) { | ||
| 465 | ordered = list_first_entry(&log->logged_list[index], | ||
| 466 | struct btrfs_ordered_extent, | ||
| 467 | log_list); | ||
| 468 | list_del_init(&ordered->log_list); | ||
| 469 | spin_unlock_irq(&log->log_extents_lock[index]); | ||
| 470 | btrfs_put_ordered_extent(ordered); | ||
| 471 | spin_lock_irq(&log->log_extents_lock[index]); | ||
| 472 | } | ||
| 473 | spin_unlock_irq(&log->log_extents_lock[index]); | ||
| 474 | } | ||
| 475 | |||
| 408 | /* | 476 | /* |
| 409 | * used to drop a reference on an ordered extent. This will free | 477 | * used to drop a reference on an ordered extent. This will free |
| 410 | * the extent if the last reference is dropped | 478 | * the extent if the last reference is dropped |
| @@ -544,10 +612,12 @@ void btrfs_wait_ordered_extents(struct btrfs_root *root, int delay_iput) | |||
| 544 | * extra check to make sure the ordered operation list really is empty | 612 | * extra check to make sure the ordered operation list really is empty |
| 545 | * before we return | 613 | * before we return |
| 546 | */ | 614 | */ |
| 547 | int btrfs_run_ordered_operations(struct btrfs_root *root, int wait) | 615 | int btrfs_run_ordered_operations(struct btrfs_trans_handle *trans, |
| 616 | struct btrfs_root *root, int wait) | ||
| 548 | { | 617 | { |
| 549 | struct btrfs_inode *btrfs_inode; | 618 | struct btrfs_inode *btrfs_inode; |
| 550 | struct inode *inode; | 619 | struct inode *inode; |
| 620 | struct btrfs_transaction *cur_trans = trans->transaction; | ||
| 551 | struct list_head splice; | 621 | struct list_head splice; |
| 552 | struct list_head works; | 622 | struct list_head works; |
| 553 | struct btrfs_delalloc_work *work, *next; | 623 | struct btrfs_delalloc_work *work, *next; |
| @@ -558,14 +628,10 @@ int btrfs_run_ordered_operations(struct btrfs_root *root, int wait) | |||
| 558 | 628 | ||
| 559 | mutex_lock(&root->fs_info->ordered_operations_mutex); | 629 | mutex_lock(&root->fs_info->ordered_operations_mutex); |
| 560 | spin_lock(&root->fs_info->ordered_extent_lock); | 630 | spin_lock(&root->fs_info->ordered_extent_lock); |
| 561 | again: | 631 | list_splice_init(&cur_trans->ordered_operations, &splice); |
| 562 | list_splice_init(&root->fs_info->ordered_operations, &splice); | ||
| 563 | |||
| 564 | while (!list_empty(&splice)) { | 632 | while (!list_empty(&splice)) { |
| 565 | |||
| 566 | btrfs_inode = list_entry(splice.next, struct btrfs_inode, | 633 | btrfs_inode = list_entry(splice.next, struct btrfs_inode, |
| 567 | ordered_operations); | 634 | ordered_operations); |
| 568 | |||
| 569 | inode = &btrfs_inode->vfs_inode; | 635 | inode = &btrfs_inode->vfs_inode; |
| 570 | 636 | ||
| 571 | list_del_init(&btrfs_inode->ordered_operations); | 637 | list_del_init(&btrfs_inode->ordered_operations); |
| @@ -574,24 +640,22 @@ again: | |||
| 574 | * the inode may be getting freed (in sys_unlink path). | 640 | * the inode may be getting freed (in sys_unlink path). |
| 575 | */ | 641 | */ |
| 576 | inode = igrab(inode); | 642 | inode = igrab(inode); |
| 577 | |||
| 578 | if (!wait && inode) { | ||
| 579 | list_add_tail(&BTRFS_I(inode)->ordered_operations, | ||
| 580 | &root->fs_info->ordered_operations); | ||
| 581 | } | ||
| 582 | |||
| 583 | if (!inode) | 643 | if (!inode) |
| 584 | continue; | 644 | continue; |
| 645 | |||
| 646 | if (!wait) | ||
| 647 | list_add_tail(&BTRFS_I(inode)->ordered_operations, | ||
| 648 | &cur_trans->ordered_operations); | ||
| 585 | spin_unlock(&root->fs_info->ordered_extent_lock); | 649 | spin_unlock(&root->fs_info->ordered_extent_lock); |
| 586 | 650 | ||
| 587 | work = btrfs_alloc_delalloc_work(inode, wait, 1); | 651 | work = btrfs_alloc_delalloc_work(inode, wait, 1); |
| 588 | if (!work) { | 652 | if (!work) { |
| 653 | spin_lock(&root->fs_info->ordered_extent_lock); | ||
| 589 | if (list_empty(&BTRFS_I(inode)->ordered_operations)) | 654 | if (list_empty(&BTRFS_I(inode)->ordered_operations)) |
| 590 | list_add_tail(&btrfs_inode->ordered_operations, | 655 | list_add_tail(&btrfs_inode->ordered_operations, |
| 591 | &splice); | 656 | &splice); |
| 592 | spin_lock(&root->fs_info->ordered_extent_lock); | ||
| 593 | list_splice_tail(&splice, | 657 | list_splice_tail(&splice, |
| 594 | &root->fs_info->ordered_operations); | 658 | &cur_trans->ordered_operations); |
| 595 | spin_unlock(&root->fs_info->ordered_extent_lock); | 659 | spin_unlock(&root->fs_info->ordered_extent_lock); |
| 596 | ret = -ENOMEM; | 660 | ret = -ENOMEM; |
| 597 | goto out; | 661 | goto out; |
| @@ -603,9 +667,6 @@ again: | |||
| 603 | cond_resched(); | 667 | cond_resched(); |
| 604 | spin_lock(&root->fs_info->ordered_extent_lock); | 668 | spin_lock(&root->fs_info->ordered_extent_lock); |
| 605 | } | 669 | } |
| 606 | if (wait && !list_empty(&root->fs_info->ordered_operations)) | ||
| 607 | goto again; | ||
| 608 | |||
| 609 | spin_unlock(&root->fs_info->ordered_extent_lock); | 670 | spin_unlock(&root->fs_info->ordered_extent_lock); |
| 610 | out: | 671 | out: |
| 611 | list_for_each_entry_safe(work, next, &works, list) { | 672 | list_for_each_entry_safe(work, next, &works, list) { |
| @@ -974,6 +1035,7 @@ out: | |||
| 974 | void btrfs_add_ordered_operation(struct btrfs_trans_handle *trans, | 1035 | void btrfs_add_ordered_operation(struct btrfs_trans_handle *trans, |
| 975 | struct btrfs_root *root, struct inode *inode) | 1036 | struct btrfs_root *root, struct inode *inode) |
| 976 | { | 1037 | { |
| 1038 | struct btrfs_transaction *cur_trans = trans->transaction; | ||
| 977 | u64 last_mod; | 1039 | u64 last_mod; |
| 978 | 1040 | ||
| 979 | last_mod = max(BTRFS_I(inode)->generation, BTRFS_I(inode)->last_trans); | 1041 | last_mod = max(BTRFS_I(inode)->generation, BTRFS_I(inode)->last_trans); |
| @@ -988,7 +1050,7 @@ void btrfs_add_ordered_operation(struct btrfs_trans_handle *trans, | |||
| 988 | spin_lock(&root->fs_info->ordered_extent_lock); | 1050 | spin_lock(&root->fs_info->ordered_extent_lock); |
| 989 | if (list_empty(&BTRFS_I(inode)->ordered_operations)) { | 1051 | if (list_empty(&BTRFS_I(inode)->ordered_operations)) { |
| 990 | list_add_tail(&BTRFS_I(inode)->ordered_operations, | 1052 | list_add_tail(&BTRFS_I(inode)->ordered_operations, |
| 991 | &root->fs_info->ordered_operations); | 1053 | &cur_trans->ordered_operations); |
| 992 | } | 1054 | } |
| 993 | spin_unlock(&root->fs_info->ordered_extent_lock); | 1055 | spin_unlock(&root->fs_info->ordered_extent_lock); |
| 994 | } | 1056 | } |
