linux/fs/xfs/xfs_exchrange.h
Darrick J. Wong 398597c3ef xfs: introduce new file range commit ioctls
This patch introduces two more new ioctls to manage atomic updates to
file contents -- XFS_IOC_START_COMMIT and XFS_IOC_COMMIT_RANGE.  The
commit mechanism here is exactly the same as what XFS_IOC_EXCHANGE_RANGE
does, but with the additional requirement that file2 cannot have changed
since some sampling point.  The start-commit ioctl performs the sampling
of file attributes.

Note: This patch currently samples i_ctime during START_COMMIT and
checks that it hasn't changed during COMMIT_RANGE.  This isn't entirely
safe in kernels prior to 6.12 because ctime only had coarse grained
granularity and very fast updates could collide with a COMMIT_RANGE.
With the multi-granularity ctime introduced by Jeff Layton, it's now
possible to update ctime such that this does not happen.

It is critical, then, that this patch must not be backported to any
kernel that does not support fine-grained file change timestamps.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Acked-by: Jeff Layton <jlayton@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
2024-09-01 08:58:19 -07:00

53 lines
1.5 KiB
C

/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Copyright (c) 2020-2024 Oracle. All Rights Reserved.
* Author: Darrick J. Wong <djwong@kernel.org>
*/
#ifndef __XFS_EXCHRANGE_H__
#define __XFS_EXCHRANGE_H__
/* Update the mtime/cmtime of file1 and file2 */
#define __XFS_EXCHANGE_RANGE_UPD_CMTIME1 (1ULL << 63)
#define __XFS_EXCHANGE_RANGE_UPD_CMTIME2 (1ULL << 62)
/* Freshness check required */
#define __XFS_EXCHANGE_RANGE_CHECK_FRESH2 (1ULL << 61)
#define XFS_EXCHANGE_RANGE_PRIV_FLAGS (__XFS_EXCHANGE_RANGE_UPD_CMTIME1 | \
__XFS_EXCHANGE_RANGE_UPD_CMTIME2 | \
__XFS_EXCHANGE_RANGE_CHECK_FRESH2)
struct xfs_exchrange {
struct file *file1;
struct file *file2;
loff_t file1_offset;
loff_t file2_offset;
u64 length;
u64 flags; /* XFS_EXCHANGE_RANGE flags */
/* file2 metadata for freshness checks */
u64 file2_ino;
struct timespec64 file2_mtime;
struct timespec64 file2_ctime;
u32 file2_gen;
};
long xfs_ioc_exchange_range(struct file *file,
struct xfs_exchange_range __user *argp);
long xfs_ioc_start_commit(struct file *file,
struct xfs_commit_range __user *argp);
long xfs_ioc_commit_range(struct file *file,
struct xfs_commit_range __user *argp);
struct xfs_exchmaps_req;
void xfs_exchrange_ilock(struct xfs_trans *tp, struct xfs_inode *ip1,
struct xfs_inode *ip2);
void xfs_exchrange_iunlock(struct xfs_inode *ip1, struct xfs_inode *ip2);
int xfs_exchrange_estimate(struct xfs_exchmaps_req *req);
#endif /* __XFS_EXCHRANGE_H__ */