diff options
Diffstat (limited to 'fs/btrfs/file.c')
-rw-r--r-- | fs/btrfs/file.c | 57 |
1 files changed, 47 insertions, 10 deletions
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 4b241fe9d2fe..af1d0605a5c1 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c | |||
@@ -30,11 +30,11 @@ | |||
30 | #include <linux/statfs.h> | 30 | #include <linux/statfs.h> |
31 | #include <linux/compat.h> | 31 | #include <linux/compat.h> |
32 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
33 | #include <linux/btrfs.h> | ||
33 | #include "ctree.h" | 34 | #include "ctree.h" |
34 | #include "disk-io.h" | 35 | #include "disk-io.h" |
35 | #include "transaction.h" | 36 | #include "transaction.h" |
36 | #include "btrfs_inode.h" | 37 | #include "btrfs_inode.h" |
37 | #include "ioctl.h" | ||
38 | #include "print-tree.h" | 38 | #include "print-tree.h" |
39 | #include "tree-log.h" | 39 | #include "tree-log.h" |
40 | #include "locking.h" | 40 | #include "locking.h" |
@@ -374,6 +374,11 @@ int btrfs_run_defrag_inodes(struct btrfs_fs_info *fs_info) | |||
374 | 374 | ||
375 | atomic_inc(&fs_info->defrag_running); | 375 | atomic_inc(&fs_info->defrag_running); |
376 | while(1) { | 376 | while(1) { |
377 | /* Pause the auto defragger. */ | ||
378 | if (test_bit(BTRFS_FS_STATE_REMOUNTING, | ||
379 | &fs_info->fs_state)) | ||
380 | break; | ||
381 | |||
377 | if (!__need_auto_defrag(fs_info->tree_root)) | 382 | if (!__need_auto_defrag(fs_info->tree_root)) |
378 | break; | 383 | break; |
379 | 384 | ||
@@ -505,8 +510,7 @@ int btrfs_dirty_pages(struct btrfs_root *root, struct inode *inode, | |||
505 | loff_t isize = i_size_read(inode); | 510 | loff_t isize = i_size_read(inode); |
506 | 511 | ||
507 | start_pos = pos & ~((u64)root->sectorsize - 1); | 512 | start_pos = pos & ~((u64)root->sectorsize - 1); |
508 | num_bytes = (write_bytes + pos - start_pos + | 513 | num_bytes = ALIGN(write_bytes + pos - start_pos, root->sectorsize); |
509 | root->sectorsize - 1) & ~((u64)root->sectorsize - 1); | ||
510 | 514 | ||
511 | end_of_last_block = start_pos + num_bytes - 1; | 515 | end_of_last_block = start_pos + num_bytes - 1; |
512 | err = btrfs_set_extent_delalloc(inode, start_pos, end_of_last_block, | 516 | err = btrfs_set_extent_delalloc(inode, start_pos, end_of_last_block, |
@@ -1544,7 +1548,7 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb, | |||
1544 | * although we have opened a file as writable, we have | 1548 | * although we have opened a file as writable, we have |
1545 | * to stop this write operation to ensure FS consistency. | 1549 | * to stop this write operation to ensure FS consistency. |
1546 | */ | 1550 | */ |
1547 | if (root->fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR) { | 1551 | if (test_bit(BTRFS_FS_STATE_ERROR, &root->fs_info->fs_state)) { |
1548 | mutex_unlock(&inode->i_mutex); | 1552 | mutex_unlock(&inode->i_mutex); |
1549 | err = -EROFS; | 1553 | err = -EROFS; |
1550 | goto out; | 1554 | goto out; |
@@ -1627,7 +1631,20 @@ int btrfs_release_file(struct inode *inode, struct file *filp) | |||
1627 | */ | 1631 | */ |
1628 | if (test_and_clear_bit(BTRFS_INODE_ORDERED_DATA_CLOSE, | 1632 | if (test_and_clear_bit(BTRFS_INODE_ORDERED_DATA_CLOSE, |
1629 | &BTRFS_I(inode)->runtime_flags)) { | 1633 | &BTRFS_I(inode)->runtime_flags)) { |
1630 | btrfs_add_ordered_operation(NULL, BTRFS_I(inode)->root, inode); | 1634 | struct btrfs_trans_handle *trans; |
1635 | struct btrfs_root *root = BTRFS_I(inode)->root; | ||
1636 | |||
1637 | /* | ||
1638 | * We need to block on a committing transaction to keep us from | ||
1639 | * throwing a ordered operation on to the list and causing | ||
1640 | * something like sync to deadlock trying to flush out this | ||
1641 | * inode. | ||
1642 | */ | ||
1643 | trans = btrfs_start_transaction(root, 0); | ||
1644 | if (IS_ERR(trans)) | ||
1645 | return PTR_ERR(trans); | ||
1646 | btrfs_add_ordered_operation(trans, BTRFS_I(inode)->root, inode); | ||
1647 | btrfs_end_transaction(trans, root); | ||
1631 | if (inode->i_size > BTRFS_ORDERED_OPERATIONS_FLUSH_LIMIT) | 1648 | if (inode->i_size > BTRFS_ORDERED_OPERATIONS_FLUSH_LIMIT) |
1632 | filemap_flush(inode->i_mapping); | 1649 | filemap_flush(inode->i_mapping); |
1633 | } | 1650 | } |
@@ -1654,16 +1671,21 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) | |||
1654 | struct btrfs_root *root = BTRFS_I(inode)->root; | 1671 | struct btrfs_root *root = BTRFS_I(inode)->root; |
1655 | int ret = 0; | 1672 | int ret = 0; |
1656 | struct btrfs_trans_handle *trans; | 1673 | struct btrfs_trans_handle *trans; |
1674 | bool full_sync = 0; | ||
1657 | 1675 | ||
1658 | trace_btrfs_sync_file(file, datasync); | 1676 | trace_btrfs_sync_file(file, datasync); |
1659 | 1677 | ||
1660 | /* | 1678 | /* |
1661 | * We write the dirty pages in the range and wait until they complete | 1679 | * We write the dirty pages in the range and wait until they complete |
1662 | * out of the ->i_mutex. If so, we can flush the dirty pages by | 1680 | * out of the ->i_mutex. If so, we can flush the dirty pages by |
1663 | * multi-task, and make the performance up. | 1681 | * multi-task, and make the performance up. See |
1682 | * btrfs_wait_ordered_range for an explanation of the ASYNC check. | ||
1664 | */ | 1683 | */ |
1665 | atomic_inc(&BTRFS_I(inode)->sync_writers); | 1684 | atomic_inc(&BTRFS_I(inode)->sync_writers); |
1666 | ret = filemap_write_and_wait_range(inode->i_mapping, start, end); | 1685 | ret = filemap_fdatawrite_range(inode->i_mapping, start, end); |
1686 | if (!ret && test_bit(BTRFS_INODE_HAS_ASYNC_EXTENT, | ||
1687 | &BTRFS_I(inode)->runtime_flags)) | ||
1688 | ret = filemap_fdatawrite_range(inode->i_mapping, start, end); | ||
1667 | atomic_dec(&BTRFS_I(inode)->sync_writers); | 1689 | atomic_dec(&BTRFS_I(inode)->sync_writers); |
1668 | if (ret) | 1690 | if (ret) |
1669 | return ret; | 1691 | return ret; |
@@ -1675,7 +1697,10 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) | |||
1675 | * range being left. | 1697 | * range being left. |
1676 | */ | 1698 | */ |
1677 | atomic_inc(&root->log_batch); | 1699 | atomic_inc(&root->log_batch); |
1678 | btrfs_wait_ordered_range(inode, start, end - start + 1); | 1700 | full_sync = test_bit(BTRFS_INODE_NEEDS_FULL_SYNC, |
1701 | &BTRFS_I(inode)->runtime_flags); | ||
1702 | if (full_sync) | ||
1703 | btrfs_wait_ordered_range(inode, start, end - start + 1); | ||
1679 | atomic_inc(&root->log_batch); | 1704 | atomic_inc(&root->log_batch); |
1680 | 1705 | ||
1681 | /* | 1706 | /* |
@@ -1742,13 +1767,25 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) | |||
1742 | 1767 | ||
1743 | if (ret != BTRFS_NO_LOG_SYNC) { | 1768 | if (ret != BTRFS_NO_LOG_SYNC) { |
1744 | if (ret > 0) { | 1769 | if (ret > 0) { |
1770 | /* | ||
1771 | * If we didn't already wait for ordered extents we need | ||
1772 | * to do that now. | ||
1773 | */ | ||
1774 | if (!full_sync) | ||
1775 | btrfs_wait_ordered_range(inode, start, | ||
1776 | end - start + 1); | ||
1745 | ret = btrfs_commit_transaction(trans, root); | 1777 | ret = btrfs_commit_transaction(trans, root); |
1746 | } else { | 1778 | } else { |
1747 | ret = btrfs_sync_log(trans, root); | 1779 | ret = btrfs_sync_log(trans, root); |
1748 | if (ret == 0) | 1780 | if (ret == 0) { |
1749 | ret = btrfs_end_transaction(trans, root); | 1781 | ret = btrfs_end_transaction(trans, root); |
1750 | else | 1782 | } else { |
1783 | if (!full_sync) | ||
1784 | btrfs_wait_ordered_range(inode, start, | ||
1785 | end - | ||
1786 | start + 1); | ||
1751 | ret = btrfs_commit_transaction(trans, root); | 1787 | ret = btrfs_commit_transaction(trans, root); |
1788 | } | ||
1752 | } | 1789 | } |
1753 | } else { | 1790 | } else { |
1754 | ret = btrfs_end_transaction(trans, root); | 1791 | ret = btrfs_end_transaction(trans, root); |