mirror of
https://github.com/torvalds/linux.git
synced 2026-09-13 15:40:03 +02:00
xfs: avoid extra cache flushes for multi-device file systems in xfs_fsync
When xlog_force_lsn sets log_flushed, it has just called xlog_force_iclog through xlog_force_and_check_iclog, which sets XLOG_ICL_NEED_FLUSH before writing out the head iclog. This means that we already flushed the log, data, and (with the recent fix) RT devices before writing out the iclog start record and no extra cache flushed is required. This optimizes the external log case, and fixes a performance regression due to double RT dev flushes with "xfs: also flush the RT device cache in xlog_write_iclog". The explicit flush of the data that the device resides on when no iclog was written out is still required. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Darrick J. Wong <djwong@kernel.org> Reviewed-by: Carlos Maiolino <cmaiolino@redhat.com> Signed-off-by: Carlos Maiolino <cem@kernel.org>
This commit is contained in:
parent
c84455c683
commit
761e015e5a
|
|
@ -129,7 +129,6 @@ xfs_file_fsync(
|
|||
int datasync)
|
||||
{
|
||||
struct xfs_inode *ip = XFS_I(file->f_mapping->host);
|
||||
struct xfs_mount *mp = ip->i_mount;
|
||||
int log_flushed = 0;
|
||||
int error;
|
||||
|
||||
|
|
@ -139,27 +138,17 @@ xfs_file_fsync(
|
|||
if (error)
|
||||
return error;
|
||||
|
||||
if (xfs_is_shutdown(mp))
|
||||
if (xfs_is_shutdown(ip->i_mount))
|
||||
return -EIO;
|
||||
|
||||
xfs_iflags_clear(ip, XFS_ITRUNCATED);
|
||||
|
||||
/*
|
||||
* If we have an RT and/or log subvolume we need to make sure to flush
|
||||
* the write cache the device used for file data first. This is to
|
||||
* ensure newly written file data make it to disk before logging the new
|
||||
* inode size in case of an extending write.
|
||||
*/
|
||||
if (XFS_IS_REALTIME_INODE(ip) && mp->m_rtdev_targp != mp->m_ddev_targp)
|
||||
error = blkdev_issue_flush(mp->m_rtdev_targp->bt_bdev);
|
||||
else if (mp->m_logdev_targp != mp->m_ddev_targp)
|
||||
error = blkdev_issue_flush(mp->m_ddev_targp->bt_bdev);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
/*
|
||||
* If the inode has a inode log item attached, it may need the journal
|
||||
* flushed to persist any changes the log item might be tracking.
|
||||
* If the inode has a log item attached, we must force the log up to the
|
||||
* last LSN in which the inode was modified to ensure all metadata is
|
||||
* persisted. The log force will flush the caches for all devices
|
||||
* before writing the log records unless it is a no-op because there are
|
||||
* no modifications to this inode that need to be pushed out.
|
||||
*/
|
||||
if (ip->i_itemp) {
|
||||
error = xfs_fsync_flush_log(ip, datasync, &log_flushed);
|
||||
|
|
@ -173,17 +162,10 @@ xfs_file_fsync(
|
|||
* when no metadata needed to be committed.
|
||||
*
|
||||
* Use the inode's actual file data target rather than assuming the
|
||||
* main data device. Realtime inodes with a separate realtime device
|
||||
* are flushed before the log force, so this fallback only applies
|
||||
* when the file data target is the same as the log target.
|
||||
* main data device.
|
||||
*/
|
||||
if (!log_flushed) {
|
||||
struct xfs_buftarg *file_targp = xfs_inode_buftarg(ip);
|
||||
|
||||
if (mp->m_logdev_targp == file_targp)
|
||||
return blkdev_issue_flush(file_targp->bt_bdev);
|
||||
}
|
||||
|
||||
if (!log_flushed)
|
||||
return blkdev_issue_flush(xfs_inode_buftarg(ip)->bt_bdev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user