diff options
author | Chris Mason <chris.mason@fusionio.com> | 2013-02-20 14:05:45 -0500 |
---|---|---|
committer | Chris Mason <chris.mason@fusionio.com> | 2013-02-20 14:05:45 -0500 |
commit | b2c6b3e0611c58fbeb6b9c0892b6249f7bdfaf6b (patch) | |
tree | de7cf0825605aa6acf33a8d107003efd7aedbe72 /fs/btrfs/file.c | |
parent | 19f949f52599ba7c3f67a5897ac6be14bfcb1200 (diff) | |
parent | 272d26d0ad8c0e326689f2fa3cdc6a5fcc8e74e0 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/josef/btrfs-next into for-linus-3.9
Signed-off-by: Chris Mason <chris.mason@fusionio.com>
Conflicts:
fs/btrfs/disk-io.c
Diffstat (limited to 'fs/btrfs/file.c')
-rw-r--r-- | fs/btrfs/file.c | 49 |
1 files changed, 41 insertions, 8 deletions
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index aeb84469d2c4..9f67e623206d 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" |
@@ -1544,7 +1544,7 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb, | |||
1544 | * although we have opened a file as writable, we have | 1544 | * although we have opened a file as writable, we have |
1545 | * to stop this write operation to ensure FS consistency. | 1545 | * to stop this write operation to ensure FS consistency. |
1546 | */ | 1546 | */ |
1547 | if (root->fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR) { | 1547 | if (test_bit(BTRFS_FS_STATE_ERROR, &root->fs_info->fs_state)) { |
1548 | mutex_unlock(&inode->i_mutex); | 1548 | mutex_unlock(&inode->i_mutex); |
1549 | err = -EROFS; | 1549 | err = -EROFS; |
1550 | goto out; | 1550 | goto out; |
@@ -1627,7 +1627,20 @@ int btrfs_release_file(struct inode *inode, struct file *filp) | |||
1627 | */ | 1627 | */ |
1628 | if (test_and_clear_bit(BTRFS_INODE_ORDERED_DATA_CLOSE, | 1628 | if (test_and_clear_bit(BTRFS_INODE_ORDERED_DATA_CLOSE, |
1629 | &BTRFS_I(inode)->runtime_flags)) { | 1629 | &BTRFS_I(inode)->runtime_flags)) { |
1630 | btrfs_add_ordered_operation(NULL, BTRFS_I(inode)->root, inode); | 1630 | struct btrfs_trans_handle *trans; |
1631 | struct btrfs_root *root = BTRFS_I(inode)->root; | ||
1632 | |||
1633 | /* | ||
1634 | * We need to block on a committing transaction to keep us from | ||
1635 | * throwing a ordered operation on to the list and causing | ||
1636 | * something like sync to deadlock trying to flush out this | ||
1637 | * inode. | ||
1638 | */ | ||
1639 | trans = btrfs_start_transaction(root, 0); | ||
1640 | if (IS_ERR(trans)) | ||
1641 | return PTR_ERR(trans); | ||
1642 | btrfs_add_ordered_operation(trans, BTRFS_I(inode)->root, inode); | ||
1643 | btrfs_end_transaction(trans, root); | ||
1631 | if (inode->i_size > BTRFS_ORDERED_OPERATIONS_FLUSH_LIMIT) | 1644 | if (inode->i_size > BTRFS_ORDERED_OPERATIONS_FLUSH_LIMIT) |
1632 | filemap_flush(inode->i_mapping); | 1645 | filemap_flush(inode->i_mapping); |
1633 | } | 1646 | } |
@@ -1654,16 +1667,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; | 1667 | struct btrfs_root *root = BTRFS_I(inode)->root; |
1655 | int ret = 0; | 1668 | int ret = 0; |
1656 | struct btrfs_trans_handle *trans; | 1669 | struct btrfs_trans_handle *trans; |
1670 | bool full_sync = 0; | ||
1657 | 1671 | ||
1658 | trace_btrfs_sync_file(file, datasync); | 1672 | trace_btrfs_sync_file(file, datasync); |
1659 | 1673 | ||
1660 | /* | 1674 | /* |
1661 | * We write the dirty pages in the range and wait until they complete | 1675 | * 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 | 1676 | * out of the ->i_mutex. If so, we can flush the dirty pages by |
1663 | * multi-task, and make the performance up. | 1677 | * multi-task, and make the performance up. See |
1678 | * btrfs_wait_ordered_range for an explanation of the ASYNC check. | ||
1664 | */ | 1679 | */ |
1665 | atomic_inc(&BTRFS_I(inode)->sync_writers); | 1680 | atomic_inc(&BTRFS_I(inode)->sync_writers); |
1666 | ret = filemap_write_and_wait_range(inode->i_mapping, start, end); | 1681 | ret = filemap_fdatawrite_range(inode->i_mapping, start, end); |
1682 | if (!ret && test_bit(BTRFS_INODE_HAS_ASYNC_EXTENT, | ||
1683 | &BTRFS_I(inode)->runtime_flags)) | ||
1684 | ret = filemap_fdatawrite_range(inode->i_mapping, start, end); | ||
1667 | atomic_dec(&BTRFS_I(inode)->sync_writers); | 1685 | atomic_dec(&BTRFS_I(inode)->sync_writers); |
1668 | if (ret) | 1686 | if (ret) |
1669 | return ret; | 1687 | return ret; |
@@ -1675,7 +1693,10 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) | |||
1675 | * range being left. | 1693 | * range being left. |
1676 | */ | 1694 | */ |
1677 | atomic_inc(&root->log_batch); | 1695 | atomic_inc(&root->log_batch); |
1678 | btrfs_wait_ordered_range(inode, start, end - start + 1); | 1696 | full_sync = test_bit(BTRFS_INODE_NEEDS_FULL_SYNC, |
1697 | &BTRFS_I(inode)->runtime_flags); | ||
1698 | if (full_sync) | ||
1699 | btrfs_wait_ordered_range(inode, start, end - start + 1); | ||
1679 | atomic_inc(&root->log_batch); | 1700 | atomic_inc(&root->log_batch); |
1680 | 1701 | ||
1681 | /* | 1702 | /* |
@@ -1742,13 +1763,25 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) | |||
1742 | 1763 | ||
1743 | if (ret != BTRFS_NO_LOG_SYNC) { | 1764 | if (ret != BTRFS_NO_LOG_SYNC) { |
1744 | if (ret > 0) { | 1765 | if (ret > 0) { |
1766 | /* | ||
1767 | * If we didn't already wait for ordered extents we need | ||
1768 | * to do that now. | ||
1769 | */ | ||
1770 | if (!full_sync) | ||
1771 | btrfs_wait_ordered_range(inode, start, | ||
1772 | end - start + 1); | ||
1745 | ret = btrfs_commit_transaction(trans, root); | 1773 | ret = btrfs_commit_transaction(trans, root); |
1746 | } else { | 1774 | } else { |
1747 | ret = btrfs_sync_log(trans, root); | 1775 | ret = btrfs_sync_log(trans, root); |
1748 | if (ret == 0) | 1776 | if (ret == 0) { |
1749 | ret = btrfs_end_transaction(trans, root); | 1777 | ret = btrfs_end_transaction(trans, root); |
1750 | else | 1778 | } else { |
1779 | if (!full_sync) | ||
1780 | btrfs_wait_ordered_range(inode, start, | ||
1781 | end - | ||
1782 | start + 1); | ||
1751 | ret = btrfs_commit_transaction(trans, root); | 1783 | ret = btrfs_commit_transaction(trans, root); |
1784 | } | ||
1752 | } | 1785 | } |
1753 | } else { | 1786 | } else { |
1754 | ret = btrfs_end_transaction(trans, root); | 1787 | ret = btrfs_end_transaction(trans, root); |