xfs: add datasync and log_flushed arguments to xfs_log_force_inode()

Add datasync and log_flushed arguments to xfs_log_force_inode() and
move the body of xfs_fsync_flush_log() into it. The next patch needs a
datasync log force in the pNFS LAYOUTCOMMIT path. xfs_file_fsync()
calls it instead, and the other callers pass false and NULL. No
functional change.

Suggested-by: Christoph Hellwig <hch@lst.de>
Link: https://lore.kernel.org/r/20261014130124.GA15407@lst.de
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:
Daejun Park 2026-10-29 11:23:05 +09:00 committed by Carlos Maiolino
parent 23ba20ef28
commit 199eee7c67
6 changed files with 41 additions and 54 deletions

View File

@ -234,7 +234,7 @@ STATIC int
xfs_fs_nfs_commit_metadata(
struct inode *inode)
{
return xfs_log_force_inode(XFS_I(inode));
return xfs_log_force_inode(XFS_I(inode), false, NULL);
}
const struct export_operations xfs_export_operations = {

View File

@ -76,49 +76,7 @@ xfs_dir_fsync(
struct xfs_inode *ip = XFS_I(file->f_mapping->host);
trace_xfs_dir_fsync(ip);
return xfs_log_force_inode(ip);
}
/*
* All metadata updates are logged, which means that we just have to push the
* journal to the required sequence number than holds the updates. We track
* datasync commits separately to full sync commits, and hence only need to
* select the correct sequence number for the log force here.
*
* We don't have to serialise against concurrent modifications, as we do not
* have to wait for modifications that have not yet completed. We define a
* transaction commit as completing when the commit sequence number is updated,
* hence if the sequence number has not updated, the sync operation has been
* run before the commit completed and we don't have to wait for it.
*
* If we have concurrent fsync/fdatasync() calls, the sequence numbers remain
* set on the log item until - at least - the journal flush completes. In
* reality, they are only cleared when the inode is fully unpinned (i.e.
* persistent in the journal and not dirty in the CIL), and so we rely on
* xfs_log_force_seq() either skipping sequences that have been persisted or
* waiting on sequences that are still in flight to correctly order concurrent
* sync operations.
*/
static int
xfs_fsync_flush_log(
struct xfs_inode *ip,
bool datasync,
int *log_flushed)
{
struct xfs_inode_log_item *iip = ip->i_itemp;
xfs_csn_t seq = 0;
spin_lock(&iip->ili_lock);
if (datasync)
seq = iip->ili_datasync_seq;
else
seq = iip->ili_commit_seq;
spin_unlock(&iip->ili_lock);
if (!seq)
return 0;
return xfs_log_force_seq(ip->i_mount, seq, XFS_LOG_SYNC, log_flushed);
return xfs_log_force_inode(ip, false, NULL);
}
STATIC int
@ -151,7 +109,7 @@ xfs_file_fsync(
* no modifications to this inode that need to be pushed out.
*/
if (ip->i_itemp) {
error = xfs_fsync_flush_log(ip, datasync, &log_flushed);
error = xfs_log_force_inode(ip, datasync, &log_flushed);
if (error)
return error;
}
@ -1600,7 +1558,7 @@ __xfs_file_fallocate(
}
if (!error && xfs_file_sync_writes(file))
error = xfs_log_force_inode(ip);
error = xfs_log_force_inode(ip, false, NULL);
out_unlock:
xfs_iunlock(ip, iolock);
@ -1751,7 +1709,7 @@ xfs_file_remap_range(
goto out_unlock;
if (xfs_file_sync_writes(file_in) || xfs_file_sync_writes(file_out))
xfs_log_force_inode(dest);
xfs_log_force_inode(dest, false, NULL);
out_unlock:
xfs_iunlock2_remapping(src, dest);
if (ret)

View File

@ -2678,11 +2678,36 @@ xfs_irele(
}
/*
* Ensure all committed transactions touching the inode are written to the log.
* Ensure all committed transactions touching the inode are written to the log,
* or with @datasync only those that fdatasync has to wait for.
*
* All metadata updates are logged, which means that we just have to push the
* journal to the required sequence number that holds the updates. We track
* datasync commits separately to full sync commits, and hence only need to
* select the correct sequence number for the log force here.
*
* We don't have to serialise against concurrent modifications, as we do not
* have to wait for modifications that have not yet completed. We define a
* transaction commit as completing when the commit sequence number is updated,
* hence if the sequence number has not updated, the sync operation has been
* run before the commit completed and we don't have to wait for it.
*
* If we have concurrent fsync/fdatasync() calls, the sequence numbers remain
* set on the log item until - at least - the journal flush completes. In
* reality, they are only cleared when the inode is fully unpinned (i.e.
* persistent in the journal and not dirty in the CIL), and so we rely on
* xfs_log_force_seq() either skipping sequences that have been persisted or
* waiting on sequences that are still in flight to correctly order concurrent
* sync operations.
*
* If @log_flushed is not NULL, it is set when the log force wrote an iclog,
* which flushes the device caches before the log write.
*/
int
xfs_log_force_inode(
struct xfs_inode *ip)
struct xfs_inode *ip,
bool datasync,
int *log_flushed)
{
struct xfs_inode_log_item *iip = ip->i_itemp;
xfs_csn_t seq = 0;
@ -2691,12 +2716,15 @@ xfs_log_force_inode(
return 0;
spin_lock(&iip->ili_lock);
seq = iip->ili_commit_seq;
if (datasync)
seq = iip->ili_datasync_seq;
else
seq = iip->ili_commit_seq;
spin_unlock(&iip->ili_lock);
if (!seq)
return 0;
return xfs_log_force_seq(ip->i_mount, seq, XFS_LOG_SYNC, NULL);
return xfs_log_force_seq(ip->i_mount, seq, XFS_LOG_SYNC, log_flushed);
}
/*

View File

@ -595,7 +595,8 @@ int xfs_ifree(struct xfs_trans *, struct xfs_inode *);
int xfs_itruncate_extents_flags(struct xfs_trans **,
struct xfs_inode *, int, xfs_fsize_t, int);
int xfs_log_force_inode(struct xfs_inode *ip);
int xfs_log_force_inode(struct xfs_inode *ip, bool datasync,
int *log_flushed);
void xfs_iunpin_wait(xfs_inode_t *);
#define xfs_ipincount(ip) ((unsigned int) atomic_read(&ip->i_pincount))

View File

@ -118,7 +118,7 @@ xfs_fs_map_update_inode(
* Force the log so that the blocks handed out to the client are
* guaranteed to be present even after a server crash.
*/
return xfs_log_force_inode(ip);
return xfs_log_force_inode(ip, false, NULL);
}
/*

View File

@ -1018,7 +1018,7 @@ xfs_zone_gc_reset_zones(
struct xfs_gc_bio *chunk;
struct bio *bio;
xfs_log_force_inode(rtg_rmap(rtg));
xfs_log_force_inode(rtg_rmap(rtg), false, NULL);
next = rtg_group(rtg)->xg_next_reset;
rtg_group(rtg)->xg_next_reset = NULL;