On 04/02/2025 12:01, John Garry wrote:
+static noinline ssize_t
+xfs_file_dio_write_atomic(
+ struct xfs_inode *ip,
+ struct kiocb *iocb,
+ struct iov_iter *from)
+{
+ unsigned int iolock = XFS_IOLOCK_SHARED;
+ bool use_cow = false;
+ unsigned int dio_flags;
+ ssize_t ret;
+
+retry:
+ ret = xfs_ilock_iocb_for_write(iocb, &iolock);
+ if (ret)
+ return ret;
+
+ ret = xfs_file_write_checks(iocb, from, &iolock);
+ if (ret)
+ goto out_unlock;
+
+ if (use_cow) {
+ ret = xfs_reflink_unshare(ip, iocb->ki_pos,
+ iov_iter_count(from));
+ if (ret)
+ goto out_unlock;
+ }
+
+ trace_xfs_file_direct_write(iocb, from);
+ if (use_cow)
+ dio_flags = IOMAP_DIO_ATOMIC_COW;
note to self:
We should also set IOMAP_DIO_FORCE_WAIT and call inode_dio_wait() here,
similar to xfs_file_dio_write_unaligned()
+ else
+ dio_flags = 0;
+
+ ret = iomap_dio_rw(iocb, from, &xfs_direct_write_iomap_ops,
+ &xfs_dio_write_ops, dio_flags, NULL, 0);
+
+ if (ret == -EAGAIN && !(iocb->ki_flags & IOCB_NOWAIT) && !use_cow) {
+ xfs_iunlock(ip, iolock);
+ iolock = XFS_IOLOCK_EXCL;
+ use_cow = true;
+ goto retry;
+ }
+
+out_unlock:
+ if (iolock)
+ xfs_iunlock(ip, iolock);
+ return ret;
+}
+