mirror of
https://github.com/torvalds/linux.git
synced 2026-11-06 21:58:01 +01:00
xfs: make pNFS LAYOUTCOMMIT stable the way fdatasync does
Every LAYOUTCOMMIT commits a synchronous transaction and forces the log. fdatasync after the same overwrite does not, because timestamps alone do not set ili_datasync_seq. Do what fdatasync does. Commit without XFS_TRANS_SYNC, force the log up to ili_datasync_seq, and flush the data device cache if that wrote no iclog. Conversions and size changes still force the log. As with fdatasync, a crash before the next log write can lose the new timestamps and the change attribute that nfsd derives from the ctime. Signed-off-by: Daejun Park <daejun7.park@samsung.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Carlos Maiolino <cem@kernel.org>
This commit is contained in:
parent
199eee7c67
commit
9cc3b0eda9
|
|
@ -295,10 +295,12 @@ xfs_pnfs_validate_isize(
|
|||
* converting any unwritten extents, flushing the disk cache and updating the
|
||||
* time stamps.
|
||||
*
|
||||
* Note that we rely on the caller to always send us a timestamp update so that
|
||||
* we always commit a transaction here. If that stops being true we will have
|
||||
* to manually flush the cache here similar to what the fsync code path does
|
||||
* for datasyncs on files that have no dirty metadata.
|
||||
* Like fdatasync, a commit that only updates the timestamps does not force the
|
||||
* log: they are logged as XFS_ILOG_TIMESTAMP and reach the disk with a later
|
||||
* log write. The log is forced up to the last change that a datasync needs,
|
||||
* such as the unwritten extent conversions or a new size, and the cache of the
|
||||
* device holding the file data is flushed if that log force did not write an
|
||||
* iclog itself.
|
||||
*/
|
||||
static int
|
||||
xfs_fs_commit_blocks(
|
||||
|
|
@ -312,6 +314,7 @@ xfs_fs_commit_blocks(
|
|||
struct xfs_trans *tp;
|
||||
struct timespec64 now;
|
||||
bool update_isize = false;
|
||||
int log_flushed = 0;
|
||||
int error, i;
|
||||
loff_t size;
|
||||
|
||||
|
|
@ -368,7 +371,8 @@ xfs_fs_commit_blocks(
|
|||
|
||||
xfs_ilock(ip, XFS_ILOCK_EXCL);
|
||||
xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
|
||||
xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
|
||||
xfs_trans_log_inode(tp, ip,
|
||||
update_isize ? XFS_ILOG_CORE : XFS_ILOG_TIMESTAMP);
|
||||
|
||||
now = inode_set_ctime_current(inode);
|
||||
inode_set_atime_to_ts(inode, now);
|
||||
|
|
@ -379,8 +383,13 @@ xfs_fs_commit_blocks(
|
|||
ip->i_disk_size = new_size;
|
||||
}
|
||||
|
||||
xfs_trans_set_sync(tp);
|
||||
error = xfs_trans_commit(tp);
|
||||
if (error)
|
||||
goto out_drop_iolock;
|
||||
|
||||
error = xfs_log_force_inode(ip, true, &log_flushed);
|
||||
if (!error && !log_flushed)
|
||||
error = blkdev_issue_flush(xfs_inode_buftarg(ip)->bt_bdev);
|
||||
|
||||
out_drop_iolock:
|
||||
xfs_iunlock(ip, XFS_IOLOCK_EXCL);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user