diff options
-rw-r--r-- | fs/btrfs/btrfs_inode.h | 3 | ||||
-rw-r--r-- | fs/btrfs/file.c | 8 | ||||
-rw-r--r-- | fs/btrfs/inode.c | 11 |
3 files changed, 21 insertions, 1 deletions
diff --git a/fs/btrfs/btrfs_inode.h b/fs/btrfs/btrfs_inode.h index 2411baf35220..2a8c242bc4f5 100644 --- a/fs/btrfs/btrfs_inode.h +++ b/fs/btrfs/btrfs_inode.h | |||
@@ -91,6 +91,9 @@ struct btrfs_inode { | |||
91 | 91 | ||
92 | unsigned long runtime_flags; | 92 | unsigned long runtime_flags; |
93 | 93 | ||
94 | /* Keep track of who's O_SYNC/fsycing currently */ | ||
95 | atomic_t sync_writers; | ||
96 | |||
94 | /* full 64 bit generation number, struct vfs_inode doesn't have a big | 97 | /* full 64 bit generation number, struct vfs_inode doesn't have a big |
95 | * enough field for this. | 98 | * enough field for this. |
96 | */ | 99 | */ |
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 71c2dc1ea15a..7f4654a15207 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c | |||
@@ -1472,6 +1472,7 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb, | |||
1472 | ssize_t num_written = 0; | 1472 | ssize_t num_written = 0; |
1473 | ssize_t err = 0; | 1473 | ssize_t err = 0; |
1474 | size_t count, ocount; | 1474 | size_t count, ocount; |
1475 | bool sync = (file->f_flags & O_DSYNC) || IS_SYNC(file->f_mapping->host); | ||
1475 | 1476 | ||
1476 | sb_start_write(inode->i_sb); | 1477 | sb_start_write(inode->i_sb); |
1477 | 1478 | ||
@@ -1529,6 +1530,9 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb, | |||
1529 | } | 1530 | } |
1530 | } | 1531 | } |
1531 | 1532 | ||
1533 | if (sync) | ||
1534 | atomic_inc(&BTRFS_I(inode)->sync_writers); | ||
1535 | |||
1532 | if (unlikely(file->f_flags & O_DIRECT)) { | 1536 | if (unlikely(file->f_flags & O_DIRECT)) { |
1533 | num_written = __btrfs_direct_write(iocb, iov, nr_segs, | 1537 | num_written = __btrfs_direct_write(iocb, iov, nr_segs, |
1534 | pos, ppos, count, ocount); | 1538 | pos, ppos, count, ocount); |
@@ -1563,6 +1567,8 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb, | |||
1563 | num_written = err; | 1567 | num_written = err; |
1564 | } | 1568 | } |
1565 | out: | 1569 | out: |
1570 | if (sync) | ||
1571 | atomic_dec(&BTRFS_I(inode)->sync_writers); | ||
1566 | sb_end_write(inode->i_sb); | 1572 | sb_end_write(inode->i_sb); |
1567 | current->backing_dev_info = NULL; | 1573 | current->backing_dev_info = NULL; |
1568 | return num_written ? num_written : err; | 1574 | return num_written ? num_written : err; |
@@ -1613,7 +1619,9 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) | |||
1613 | * out of the ->i_mutex. If so, we can flush the dirty pages by | 1619 | * out of the ->i_mutex. If so, we can flush the dirty pages by |
1614 | * multi-task, and make the performance up. | 1620 | * multi-task, and make the performance up. |
1615 | */ | 1621 | */ |
1622 | atomic_inc(&BTRFS_I(inode)->sync_writers); | ||
1616 | ret = filemap_write_and_wait_range(inode->i_mapping, start, end); | 1623 | ret = filemap_write_and_wait_range(inode->i_mapping, start, end); |
1624 | atomic_dec(&BTRFS_I(inode)->sync_writers); | ||
1617 | if (ret) | 1625 | if (ret) |
1618 | return ret; | 1626 | return ret; |
1619 | 1627 | ||
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 123815f3b454..7855aac36706 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -1622,6 +1622,7 @@ static int btrfs_submit_bio_hook(struct inode *inode, int rw, struct bio *bio, | |||
1622 | int ret = 0; | 1622 | int ret = 0; |
1623 | int skip_sum; | 1623 | int skip_sum; |
1624 | int metadata = 0; | 1624 | int metadata = 0; |
1625 | int async = !atomic_read(&BTRFS_I(inode)->sync_writers); | ||
1625 | 1626 | ||
1626 | skip_sum = BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM; | 1627 | skip_sum = BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM; |
1627 | 1628 | ||
@@ -1644,7 +1645,7 @@ static int btrfs_submit_bio_hook(struct inode *inode, int rw, struct bio *bio, | |||
1644 | goto out; | 1645 | goto out; |
1645 | } | 1646 | } |
1646 | goto mapit; | 1647 | goto mapit; |
1647 | } else if (!skip_sum) { | 1648 | } else if (async && !skip_sum) { |
1648 | /* csum items have already been cloned */ | 1649 | /* csum items have already been cloned */ |
1649 | if (root->root_key.objectid == BTRFS_DATA_RELOC_TREE_OBJECTID) | 1650 | if (root->root_key.objectid == BTRFS_DATA_RELOC_TREE_OBJECTID) |
1650 | goto mapit; | 1651 | goto mapit; |
@@ -1655,6 +1656,10 @@ static int btrfs_submit_bio_hook(struct inode *inode, int rw, struct bio *bio, | |||
1655 | __btrfs_submit_bio_start, | 1656 | __btrfs_submit_bio_start, |
1656 | __btrfs_submit_bio_done); | 1657 | __btrfs_submit_bio_done); |
1657 | goto out; | 1658 | goto out; |
1659 | } else if (!skip_sum) { | ||
1660 | ret = btrfs_csum_one_bio(root, inode, bio, 0, 0); | ||
1661 | if (ret) | ||
1662 | goto out; | ||
1658 | } | 1663 | } |
1659 | 1664 | ||
1660 | mapit: | 1665 | mapit: |
@@ -6333,6 +6338,9 @@ static inline int __btrfs_submit_dio_bio(struct bio *bio, struct inode *inode, | |||
6333 | struct btrfs_root *root = BTRFS_I(inode)->root; | 6338 | struct btrfs_root *root = BTRFS_I(inode)->root; |
6334 | int ret; | 6339 | int ret; |
6335 | 6340 | ||
6341 | if (async_submit) | ||
6342 | async_submit = !atomic_read(&BTRFS_I(inode)->sync_writers); | ||
6343 | |||
6336 | bio_get(bio); | 6344 | bio_get(bio); |
6337 | 6345 | ||
6338 | if (!write) { | 6346 | if (!write) { |
@@ -7113,6 +7121,7 @@ struct inode *btrfs_alloc_inode(struct super_block *sb) | |||
7113 | extent_io_tree_init(&ei->io_failure_tree, &inode->i_data); | 7121 | extent_io_tree_init(&ei->io_failure_tree, &inode->i_data); |
7114 | ei->io_tree.track_uptodate = 1; | 7122 | ei->io_tree.track_uptodate = 1; |
7115 | ei->io_failure_tree.track_uptodate = 1; | 7123 | ei->io_failure_tree.track_uptodate = 1; |
7124 | atomic_set(&ei->sync_writers, 0); | ||
7116 | mutex_init(&ei->log_mutex); | 7125 | mutex_init(&ei->log_mutex); |
7117 | mutex_init(&ei->delalloc_mutex); | 7126 | mutex_init(&ei->delalloc_mutex); |
7118 | btrfs_ordered_inode_tree_init(&ei->ordered_tree); | 7127 | btrfs_ordered_inode_tree_init(&ei->ordered_tree); |