On 25/02/2025 17:47, Darrick J. Wong wrote:
I can try, and would then need to try to factor out what would be much
duplicated code.
<nod> I think it's pretty straightforward:
Yeah, I already had done sometime like this since.
xfs_direct_cow_write_iomap_begin()
{
ASSERT(flags & IOMAP_WRITE);
ASSERT(flags & IOMAP_DIRECT);
ASSERT(flags & IOMAP_ATOMIC_SW);
if (xfs_is_shutdown(mp))
return -EIO;
/*
* Writes that span EOF might trigger an IO size update on
* completion, so consider them to be dirty for the purposes of
* O_DSYNC even if there is no other metadata changes pending or
* have been made here.
*/
if (offset + length > i_size_read(inode))
iomap_flags |= IOMAP_F_DIRTY;
lockmode = XFS_ILOCK_EXCL;
error = xfs_ilock_for_iomap(ip, flags, &lockmode);
if (error)
return error;
error = xfs_bmapi_read(ip, offset_fsb, end_fsb - offset_fsb,
&imap, &nimaps, 0);
if (error)
goto out_unlock;
error = xfs_reflink_allocate_cow(ip, &imap, &cmap, &shared,
&lockmode, true, true);
if (error)
goto out_unlock;
endoff = XFS_FSB_TO_B(mp, cmap.br_startoff + cmap.br_blockcount);
trace_xfs_iomap_found(ip, offset, endoff - offset, XFS_COW_FORK,
&cmap);
if (imap.br_startblock != HOLESTARTBLOCK) {
note: As you know, all this is common to xfs_direct_write_iomap_begin(),
but unfortunately can't neatly be factored out due to the xfs_iunlock()
calls.
seq = xfs_iomap_inode_sequence(ip, 0);
error = xfs_bmbt_to_iomap(ip, srcmap, &imap, flags, 0,
seq);
if (error)
goto out_unlock;
}
seq = xfs_iomap_inode_sequence(ip, IOMAP_F_SHARED);
xfs_iunlock(ip, lockmode);
return xfs_bmbt_to_iomap(ip, iomap, &cmap, flags,
IOMAP_F_SHARED, seq);
out_unlock:
if (lockmode)
xfs_iunlock(ip, lockmode);
return error;
}
Cheers,
John