diff options
Diffstat (limited to 'fs/gfs2')
-rw-r--r-- | fs/gfs2/file.c | 34 |
1 files changed, 24 insertions, 10 deletions
diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c index edeb9e802903..92c3db424b40 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) | |||
560 | static int gfs2_fsync(struct file *file, loff_t start, loff_t end, | 568 | static 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 | /** |