Ensure that when creating a mapping that we adhere to all the atomic write rules. We check that the mapping covers the complete range of the write to ensure that we'll be just creating a single mapping. Currently minimum granularity is the FS block size, but it should be possibly to support lower in future. Signed-off-by: John Garry <john.g.garry@xxxxxxxxxx> --- I am setting this as an RFC as I am not sure on the change in xfs_iomap_write_direct() - it gives the desired result AFAICS. fs/xfs/xfs_iomap.c | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index 18c8f168b153..758dc1c90a42 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c @@ -289,6 +289,9 @@ xfs_iomap_write_direct( } } + if (xfs_inode_atomicwrites(ip)) + bmapi_flags = XFS_BMAPI_ZERO; + error = xfs_trans_alloc_inode(ip, &M_RES(mp)->tr_write, dblocks, rblocks, force, &tp); if (error) @@ -812,6 +815,44 @@ xfs_direct_write_iomap_begin( if (error) goto out_unlock; + if (flags & IOMAP_ATOMIC) { + xfs_filblks_t unit_min_fsb, unit_max_fsb; + unsigned int unit_min, unit_max; + + xfs_get_atomic_write_attr(ip, &unit_min, &unit_max); + unit_min_fsb = XFS_B_TO_FSBT(mp, unit_min); + unit_max_fsb = XFS_B_TO_FSBT(mp, unit_max); + + if (!imap_spans_range(&imap, offset_fsb, end_fsb)) { + error = -EINVAL; + goto out_unlock; + } + + if ((offset & mp->m_blockmask) || + (length & mp->m_blockmask)) { + error = -EINVAL; + goto out_unlock; + } + + if (imap.br_blockcount == unit_min_fsb || + imap.br_blockcount == unit_max_fsb) { + /* ok if exactly min or max */ + } else if (imap.br_blockcount < unit_min_fsb || + imap.br_blockcount > unit_max_fsb) { + error = -EINVAL; + goto out_unlock; + } else if (!is_power_of_2(imap.br_blockcount)) { + error = -EINVAL; + goto out_unlock; + } + + if (imap.br_startoff && + imap.br_startoff & (imap.br_blockcount - 1)) { + error = -EINVAL; + goto out_unlock; + } + } + if (imap_needs_cow(ip, flags, &imap, nimaps)) { error = -EAGAIN; if (flags & IOMAP_NOWAIT) -- 2.31.1