aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/btrfs/btrfs_inode.h3
-rw-r--r--fs/btrfs/file.c8
-rw-r--r--fs/btrfs/inode.c11
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 }
1565out: 1569out:
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
1660mapit: 1665mapit:
@@ -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);