Message ID | 20240817094800.776408-7-john.g.garry@oracle.com (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | block atomic writes for xfs | expand |
On Sat, Aug 17, 2024 at 09:47:59AM +0000, John Garry wrote: > Validate that an atomic write adheres to length/offset rules. Since we > require extent alignment for atomic writes, this effectively also enforces > that the BIO which iomap produces is aligned. > > For an IOCB with IOCB_ATOMIC set to get as far as xfs_file_dio_write(), > FMODE_CAN_ATOMIC_WRITE will need to be set for the file; for this, > FORCEALIGN and also ATOMICWRITES flags would also need to be set for the > inode. > > Signed-off-by: John Garry <john.g.garry@oracle.com> > --- > fs/xfs/xfs_file.c | 13 ++++++++++++- > 1 file changed, 12 insertions(+), 1 deletion(-) > > diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c > index 4cdc54dc9686..9b6530a4eb4a 100644 > --- a/fs/xfs/xfs_file.c > +++ b/fs/xfs/xfs_file.c > @@ -684,9 +684,20 @@ xfs_file_dio_write( > struct kiocb *iocb, > struct iov_iter *from) > { > - struct xfs_inode *ip = XFS_I(file_inode(iocb->ki_filp)); > + struct inode *inode = file_inode(iocb->ki_filp); > + struct xfs_inode *ip = XFS_I(inode); > struct xfs_buftarg *target = xfs_inode_buftarg(ip); > size_t count = iov_iter_count(from); > + struct xfs_mount *mp = ip->i_mount; > + > + if (iocb->ki_flags & IOCB_ATOMIC) { > + if (count < i_blocksize(inode)) > + return -EINVAL; > + if (count > XFS_FSB_TO_B(mp, ip->i_extsize)) > + return -EINVAL; Here's also the place to check the dynamic things like dalign/swidth alignment. Other than that, this looks good. --D > + if (!generic_atomic_write_valid(iocb, from)) > + return -EINVAL; > + } > > /* direct I/O must be aligned to device logical sector size */ > if ((iocb->ki_pos | count) & target->bt_logical_sectormask) > -- > 2.31.1 > >
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index 4cdc54dc9686..9b6530a4eb4a 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c @@ -684,9 +684,20 @@ xfs_file_dio_write( struct kiocb *iocb, struct iov_iter *from) { - struct xfs_inode *ip = XFS_I(file_inode(iocb->ki_filp)); + struct inode *inode = file_inode(iocb->ki_filp); + struct xfs_inode *ip = XFS_I(inode); struct xfs_buftarg *target = xfs_inode_buftarg(ip); size_t count = iov_iter_count(from); + struct xfs_mount *mp = ip->i_mount; + + if (iocb->ki_flags & IOCB_ATOMIC) { + if (count < i_blocksize(inode)) + return -EINVAL; + if (count > XFS_FSB_TO_B(mp, ip->i_extsize)) + return -EINVAL; + if (!generic_atomic_write_valid(iocb, from)) + return -EINVAL; + } /* direct I/O must be aligned to device logical sector size */ if ((iocb->ki_pos | count) & target->bt_logical_sectormask)
Validate that an atomic write adheres to length/offset rules. Since we require extent alignment for atomic writes, this effectively also enforces that the BIO which iomap produces is aligned. For an IOCB with IOCB_ATOMIC set to get as far as xfs_file_dio_write(), FMODE_CAN_ATOMIC_WRITE will need to be set for the file; for this, FORCEALIGN and also ATOMICWRITES flags would also need to be set for the inode. Signed-off-by: John Garry <john.g.garry@oracle.com> --- fs/xfs/xfs_file.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-)