aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosef Bacik <jbacik@fusionio.com>2012-11-09 10:53:21 -0500
committerChris Mason <chris.mason@fusionio.com>2012-12-16 20:46:27 -0500
commit6c760c072403f446ff829ec9e89568943a3c2ef2 (patch)
treec751a0aeb81809401df1fd87a36376034ef53a87
parent5124e00ec5b0be56155a11aec416fcc5125339f1 (diff)
Btrfs: do not call file_update_time in aio_write
This starts a transaction and dirties the inode everytime we call it, which is super expensive if you have a write heavy workload. We will be updating the inode when the IO completes and we reserve the space for the inode update when we reserve space for the write, so there is no chance of loss of information or enospc issues. Thanks, Signed-off-by: Josef Bacik <jbacik@fusionio.com> Signed-off-by: Chris Mason <chris.mason@fusionio.com>
-rw-r--r--fs/btrfs/file.c35
-rw-r--r--fs/btrfs/inode.c42
2 files changed, 48 insertions, 29 deletions
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index c56088ece500..20452c110d7d 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -1464,6 +1464,24 @@ out:
1464 return written ? written : err; 1464 return written ? written : err;
1465} 1465}
1466 1466
1467static void update_time_for_write(struct inode *inode)
1468{
1469 struct timespec now;
1470
1471 if (IS_NOCMTIME(inode))
1472 return;
1473
1474 now = current_fs_time(inode->i_sb);
1475 if (!timespec_equal(&inode->i_mtime, &now))
1476 inode->i_mtime = now;
1477
1478 if (!timespec_equal(&inode->i_ctime, &now))
1479 inode->i_ctime = now;
1480
1481 if (IS_I_VERSION(inode))
1482 inode_inc_iversion(inode);
1483}
1484
1467static ssize_t btrfs_file_aio_write(struct kiocb *iocb, 1485static ssize_t btrfs_file_aio_write(struct kiocb *iocb,
1468 const struct iovec *iov, 1486 const struct iovec *iov,
1469 unsigned long nr_segs, loff_t pos) 1487 unsigned long nr_segs, loff_t pos)
@@ -1519,11 +1537,13 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb,
1519 goto out; 1537 goto out;
1520 } 1538 }
1521 1539
1522 err = file_update_time(file); 1540 /*
1523 if (err) { 1541 * We reserve space for updating the inode when we reserve space for the
1524 mutex_unlock(&inode->i_mutex); 1542 * extent we are going to write, so we will enospc out there. We don't
1525 goto out; 1543 * need to start yet another transaction to update the inode as we will
1526 } 1544 * update the inode when we finish writing whatever data we write.
1545 */
1546 update_time_for_write(inode);
1527 1547
1528 start_pos = round_down(pos, root->sectorsize); 1548 start_pos = round_down(pos, root->sectorsize);
1529 if (start_pos > i_size_read(inode)) { 1549 if (start_pos > i_size_read(inode)) {
@@ -1563,8 +1583,13 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb,
1563 * this will either be one more than the running transaction 1583 * this will either be one more than the running transaction
1564 * or the generation used for the next transaction if there isn't 1584 * or the generation used for the next transaction if there isn't
1565 * one running right now. 1585 * one running right now.
1586 *
1587 * We also have to set last_sub_trans to the current log transid,
1588 * otherwise subsequent syncs to a file that's been synced in this
1589 * transaction will appear to have already occured.
1566 */ 1590 */
1567 BTRFS_I(inode)->last_trans = root->fs_info->generation + 1; 1591 BTRFS_I(inode)->last_trans = root->fs_info->generation + 1;
1592 BTRFS_I(inode)->last_sub_trans = root->log_transid;
1568 if (num_written > 0 || num_written == -EIOCBQUEUED) { 1593 if (num_written > 0 || num_written == -EIOCBQUEUED) {
1569 err = generic_write_sync(file, pos, num_written); 1594 err = generic_write_sync(file, pos, num_written);
1570 if (err < 0 && num_written > 0) 1595 if (err < 0 && num_written > 0)
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 355a297e7988..1673dbdf1f76 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -1922,22 +1922,20 @@ static int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent)
1922 1922
1923 if (test_bit(BTRFS_ORDERED_NOCOW, &ordered_extent->flags)) { 1923 if (test_bit(BTRFS_ORDERED_NOCOW, &ordered_extent->flags)) {
1924 BUG_ON(!list_empty(&ordered_extent->list)); /* Logic error */ 1924 BUG_ON(!list_empty(&ordered_extent->list)); /* Logic error */
1925 ret = btrfs_ordered_update_i_size(inode, 0, ordered_extent); 1925 btrfs_ordered_update_i_size(inode, 0, ordered_extent);
1926 if (!ret) { 1926 if (nolock)
1927 if (nolock) 1927 trans = btrfs_join_transaction_nolock(root);
1928 trans = btrfs_join_transaction_nolock(root); 1928 else
1929 else 1929 trans = btrfs_join_transaction(root);
1930 trans = btrfs_join_transaction(root); 1930 if (IS_ERR(trans)) {
1931 if (IS_ERR(trans)) { 1931 ret = PTR_ERR(trans);
1932 ret = PTR_ERR(trans); 1932 trans = NULL;
1933 trans = NULL; 1933 goto out;
1934 goto out;
1935 }
1936 trans->block_rsv = &root->fs_info->delalloc_block_rsv;
1937 ret = btrfs_update_inode_fallback(trans, root, inode);
1938 if (ret) /* -ENOMEM or corruption */
1939 btrfs_abort_transaction(trans, root, ret);
1940 } 1934 }
1935 trans->block_rsv = &root->fs_info->delalloc_block_rsv;
1936 ret = btrfs_update_inode_fallback(trans, root, inode);
1937 if (ret) /* -ENOMEM or corruption */
1938 btrfs_abort_transaction(trans, root, ret);
1941 goto out; 1939 goto out;
1942 } 1940 }
1943 1941
@@ -1986,15 +1984,11 @@ static int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent)
1986 add_pending_csums(trans, inode, ordered_extent->file_offset, 1984 add_pending_csums(trans, inode, ordered_extent->file_offset,
1987 &ordered_extent->list); 1985 &ordered_extent->list);
1988 1986
1989 ret = btrfs_ordered_update_i_size(inode, 0, ordered_extent); 1987 btrfs_ordered_update_i_size(inode, 0, ordered_extent);
1990 if (!ret || !test_bit(BTRFS_ORDERED_PREALLOC, &ordered_extent->flags)) { 1988 ret = btrfs_update_inode_fallback(trans, root, inode);
1991 ret = btrfs_update_inode_fallback(trans, root, inode); 1989 if (ret) { /* -ENOMEM or corruption */
1992 if (ret) { /* -ENOMEM or corruption */ 1990 btrfs_abort_transaction(trans, root, ret);
1993 btrfs_abort_transaction(trans, root, ret); 1991 goto out_unlock;
1994 goto out_unlock;
1995 }
1996 } else {
1997 btrfs_set_inode_last_trans(trans, inode);
1998 } 1992 }
1999 ret = 0; 1993 ret = 0;
2000out_unlock: 1994out_unlock: