aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorSteven Whitehouse <swhiteho@redhat.com>2011-07-27 05:58:48 -0400
committerSteven Whitehouse <swhiteho@redhat.com>2011-10-21 07:39:18 -0400
commit2f0264d592e34cde99efbad7d616b04af138e913 (patch)
treec3839570b304396513c8cc296a3fc7130b6066f1 /fs
parent4c28d33803d4aeaff32b4ac502af11a9b2aed8f4 (diff)
GFS2: Split data write & wait in fsync
Now that the data writing is part of fsync proper, we can split the waiting part out and do it later on. This reduces the number of waits that we do during fsync on average. There is also no need to take the i_mutex unless we are flushing metadata to disk, so we can move that to within the metadata flushing code. Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/gfs2/file.c34
1 files changed, 24 insertions, 10 deletions
diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c
index edeb9e80290..92c3db424b4 100644
--- a/fs/gfs2/file.c
+++ b/fs/gfs2/file.c
@@ -551,8 +551,16 @@ static int gfs2_close(struct inode *inode, struct file *file)
551 * @end: the end position in the file to sync 551 * @end: the end position in the file to sync
552 * @datasync: set if we can ignore timestamp changes 552 * @datasync: set if we can ignore timestamp changes
553 * 553 *
554 * The VFS will flush data for us. We only need to worry 554 * We split the data flushing here so that we don't wait for the data
555 * about metadata here. 555 * until after we've also sent the metadata to disk. Note that for
556 * data=ordered, we will write & wait for the data at the log flush
557 * stage anyway, so this is unlikely to make much of a difference
558 * except in the data=writeback case.
559 *
560 * If the fdatawrite fails due to any reason except -EIO, we will
561 * continue the remainder of the fsync, although we'll still report
562 * the error at the end. This is to match filemap_write_and_wait_range()
563 * behaviour.
556 * 564 *
557 * Returns: errno 565 * Returns: errno
558 */ 566 */
@@ -560,30 +568,36 @@ static int gfs2_close(struct inode *inode, struct file *file)
560static int gfs2_fsync(struct file *file, loff_t start, loff_t end, 568static int gfs2_fsync(struct file *file, loff_t start, loff_t end,
561 int datasync) 569 int datasync)
562{ 570{
563 struct inode *inode = file->f_mapping->host; 571 struct address_space *mapping = file->f_mapping;
572 struct inode *inode = mapping->host;
564 int sync_state = inode->i_state & (I_DIRTY_SYNC|I_DIRTY_DATASYNC); 573 int sync_state = inode->i_state & (I_DIRTY_SYNC|I_DIRTY_DATASYNC);
565 struct gfs2_inode *ip = GFS2_I(inode); 574 struct gfs2_inode *ip = GFS2_I(inode);
566 int ret; 575 int ret, ret1 = 0;
567 576
568 ret = filemap_write_and_wait_range(inode->i_mapping, start, end); 577 if (mapping->nrpages) {
569 if (ret) 578 ret1 = filemap_fdatawrite_range(mapping, start, end);
570 return ret; 579 if (ret1 == -EIO)
571 mutex_lock(&inode->i_mutex); 580 return ret1;
581 }
572 582
573 if (datasync) 583 if (datasync)
574 sync_state &= ~I_DIRTY_SYNC; 584 sync_state &= ~I_DIRTY_SYNC;
575 585
576 if (sync_state) { 586 if (sync_state) {
587 mutex_lock(&inode->i_mutex);
577 ret = sync_inode_metadata(inode, 1); 588 ret = sync_inode_metadata(inode, 1);
578 if (ret) { 589 if (ret) {
579 mutex_unlock(&inode->i_mutex); 590 mutex_unlock(&inode->i_mutex);
580 return ret; 591 return ret;
581 } 592 }
582 gfs2_ail_flush(ip->i_gl); 593 gfs2_ail_flush(ip->i_gl);
594 mutex_unlock(&inode->i_mutex);
583 } 595 }
584 596
585 mutex_unlock(&inode->i_mutex); 597 if (mapping->nrpages)
586 return 0; 598 ret = filemap_fdatawait_range(mapping, start, end);
599
600 return ret ? ret : ret1;
587} 601}
588 602
589/** 603/**