From: "Darrick J. Wong" <djwong@kernel.org>
To: John Garry <john.g.garry@oracle.com>
Cc: brauner@kernel.org, cem@kernel.org, dchinner@redhat.com,
hch@lst.de, linux-xfs@vger.kernel.org,
linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org,
ojaswin@linux.ibm.com, ritesh.list@gmail.com,
martin.petersen@oracle.com
Subject: Re: [PATCH RFC 08/10] xfs: Commit CoW-based atomic writes atomically
Date: Thu, 6 Feb 2025 13:50:14 -0800 [thread overview]
Message-ID: <20250206215014.GX21808@frogsfrogsfrogs> (raw)
In-Reply-To: <ee8a6ff2-d1e3-4ee8-9949-cf57279ee5d7@oracle.com>
On Thu, Feb 06, 2025 at 10:27:45AM +0000, John Garry wrote:
> On 05/02/2025 19:47, Darrick J. Wong wrote:
> > On Tue, Feb 04, 2025 at 12:01:25PM +0000, John Garry wrote:
> > > When completing a CoW-based write, each extent range mapping update is
> > > covered by a separate transaction.
> > >
> > > For a CoW-based atomic write, all mappings must be changed at once, so
> > > change to use a single transaction.
> > >
> > > Signed-off-by: John Garry <john.g.garry@oracle.com>
> > > ---
> > > fs/xfs/xfs_file.c | 5 ++++-
> > > fs/xfs/xfs_reflink.c | 48 ++++++++++++++++++++++++++++++++++++++++++++
> > > fs/xfs/xfs_reflink.h | 3 +++
> > > 3 files changed, 55 insertions(+), 1 deletion(-)
> > >
> > > diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
> > > index 12af5cdc3094..170d7891f90d 100644
> > > --- a/fs/xfs/xfs_file.c
> > > +++ b/fs/xfs/xfs_file.c
> > > @@ -527,7 +527,10 @@ xfs_dio_write_end_io(
> > > nofs_flag = memalloc_nofs_save();
> > > if (flags & IOMAP_DIO_COW) {
> > > - error = xfs_reflink_end_cow(ip, offset, size);
> > > + if (iocb->ki_flags & IOCB_ATOMIC)
> > > + error = xfs_reflink_end_atomic_cow(ip, offset, size);
> > > + else
> > > + error = xfs_reflink_end_cow(ip, offset, size);
> > > if (error)
> > > goto out;
> > > }
> > > diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c
> > > index dbce333b60eb..60c986300faa 100644
> > > --- a/fs/xfs/xfs_reflink.c
> > > +++ b/fs/xfs/xfs_reflink.c
> > > @@ -990,6 +990,54 @@ xfs_reflink_end_cow(
> > > trace_xfs_reflink_end_cow_error(ip, error, _RET_IP_);
> > > return error;
> > > }
> > > +int
> > > +xfs_reflink_end_atomic_cow(
> > > + struct xfs_inode *ip,
> > > + xfs_off_t offset,
> > > + xfs_off_t count)
> > > +{
> > > + xfs_fileoff_t offset_fsb;
> > > + xfs_fileoff_t end_fsb;
> > > + int error = 0;
> > > + struct xfs_mount *mp = ip->i_mount;
> > > + struct xfs_trans *tp;
> > > + unsigned int resblks;
> > > + bool commit = false;
> > > +
> > > + trace_xfs_reflink_end_cow(ip, offset, count);
> > > +
> > > + offset_fsb = XFS_B_TO_FSBT(ip->i_mount, offset);
> > > + end_fsb = XFS_B_TO_FSB(ip->i_mount, offset + count);
> > > +
> > > + resblks = XFS_NEXTENTADD_SPACE_RES(ip->i_mount,
> > > + (unsigned int)(end_fsb - offset_fsb),
> > > + XFS_DATA_FORK);
> > > +
> > > + error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks, 0,
> >
> > xfs gained reflink support for realtime volumes in 6.14-rc1, so you now
> > have to calculate for that in here too.
> >
> > > + XFS_TRANS_RESERVE, &tp);
> > > + if (error)
> > > + return error;
> > > +
> > > + xfs_ilock(ip, XFS_ILOCK_EXCL);
> > > + xfs_trans_ijoin(tp, ip, 0);
> > > +
> > > + while (end_fsb > offset_fsb && !error)
> > > + error = xfs_reflink_end_cow_extent_locked(ip, &offset_fsb,
> > > + end_fsb, tp, &commit);
> >
> > Hmm. Attaching intent items to a transaction consumes space in that
> > transaction, so we probably ought to limit the amount that we try to do
> > here. Do you know what that limit is? I don't,
>
> nor do I ...
>
> > but it's roughly
> > tr_logres divided by the average size of a log intent item.
>
> So you have a ballpark figure on the average size of a log intent item, or
> an idea on how to get it?
You could add up the size of struct
xfs_{bui,rmap,refcount,efi}_log_format structures and add 20%, that will
give you a ballpark figure of the worst case per-block requirements.
My guess is that 64 blocks is ok provided resblks is big enough. But I
guess we could estimate it (very conservatively) dynamically too.
(also note tr_itruncate declares more logres)
> > This means we need to restrict the size of an untorn write to a
> > double-digit number of fsblocks for safety.
>
> Sure, but won't we also still be liable to suffer the same issue which was
> fixed in commit d6f215f359637?
Yeah, come to think of it, you need to reserve the worst case space
reservation, i.e. each of the blocks between offset_fsb and end_fsb
becomes a separate btree update.
resblks = (end_fsb - offset_fsb) *
XFS_NEXTENTADD_SPACE_RES(mp, 1, XFS_DATA_FORK);
--D
> >
> > The logic in here looks reasonable though.
> >
>
> Thanks,
> John
>
> > --D
> >
> > > +
> > > + if (error || !commit)
> > > + goto out_cancel;
> > > +
> > > + if (error)
> > > + trace_xfs_reflink_end_cow_error(ip, error, _RET_IP_);
> > > + error = xfs_trans_commit(tp);
> > > + xfs_iunlock(ip, XFS_ILOCK_EXCL);
> > > + return error;
> > > +out_cancel:
> > > + xfs_trans_cancel(tp);
> > > + xfs_iunlock(ip, XFS_ILOCK_EXCL);
> > > + return error;
> > > +}
> > > /*
> > > * Free all CoW staging blocks that are still referenced by the ondisk refcount
> > > diff --git a/fs/xfs/xfs_reflink.h b/fs/xfs/xfs_reflink.h
> > > index ef5c8b2398d8..2c3b096c1386 100644
> > > --- a/fs/xfs/xfs_reflink.h
> > > +++ b/fs/xfs/xfs_reflink.h
> > > @@ -45,6 +45,9 @@ extern int xfs_reflink_cancel_cow_range(struct xfs_inode *ip, xfs_off_t offset,
> > > xfs_off_t count, bool cancel_real);
> > > extern int xfs_reflink_end_cow(struct xfs_inode *ip, xfs_off_t offset,
> > > xfs_off_t count);
> > > + int
> > > +xfs_reflink_end_atomic_cow(struct xfs_inode *ip, xfs_off_t offset,
> > > + xfs_off_t count);
> > > extern int xfs_reflink_recover_cow(struct xfs_mount *mp);
> > > extern loff_t xfs_reflink_remap_range(struct file *file_in, loff_t pos_in,
> > > struct file *file_out, loff_t pos_out, loff_t len,
> > > --
> > > 2.31.1
> > >
> > >
>
>
next prev parent reply other threads:[~2025-02-06 21:50 UTC|newest]
Thread overview: 35+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-02-04 12:01 [PATCH RFC 00/10] large atomic writes for xfs with CoW John Garry
2025-02-04 12:01 ` [PATCH RFC 01/10] xfs: Switch atomic write size check in xfs_file_write_iter() John Garry
2025-02-04 12:01 ` [PATCH RFC 02/10] xfs: Refactor xfs_reflink_end_cow_extent() John Garry
2025-02-05 19:50 ` Darrick J. Wong
2025-02-06 10:35 ` John Garry
2025-02-06 21:38 ` Darrick J. Wong
2025-02-04 12:01 ` [PATCH RFC 03/10] iomap: Support CoW-based atomic writes John Garry
2025-02-05 20:11 ` Darrick J. Wong
2025-02-06 11:21 ` John Garry
2025-02-06 21:40 ` Darrick J. Wong
2025-02-04 12:01 ` [PATCH RFC 04/10] xfs: Make xfs_find_trim_cow_extent() public John Garry
2025-02-04 12:01 ` [PATCH RFC 05/10] xfs: Reflink CoW-based atomic write support John Garry
2025-02-04 12:01 ` [PATCH RFC 06/10] xfs: iomap " John Garry
2025-02-05 20:05 ` Darrick J. Wong
2025-02-06 11:10 ` John Garry
2025-02-06 21:44 ` Darrick J. Wong
2025-02-07 11:48 ` John Garry
2025-02-04 12:01 ` [PATCH RFC 07/10] xfs: Add xfs_file_dio_write_atomic() John Garry
2025-02-05 19:55 ` Darrick J. Wong
2025-02-06 10:43 ` John Garry
2025-02-10 16:59 ` John Garry
2025-02-04 12:01 ` [PATCH RFC 08/10] xfs: Commit CoW-based atomic writes atomically John Garry
2025-02-05 19:47 ` Darrick J. Wong
2025-02-06 10:27 ` John Garry
2025-02-06 21:50 ` Darrick J. Wong [this message]
2025-02-07 11:52 ` John Garry
2025-02-04 12:01 ` [PATCH RFC 09/10] xfs: Update atomic write max size John Garry
2025-02-05 19:41 ` Darrick J. Wong
2025-02-06 9:15 ` John Garry
2025-02-06 21:54 ` Darrick J. Wong
2025-02-07 11:53 ` John Garry
2025-02-04 12:01 ` [PATCH RFC 10/10] xfs: Allow block allocator to take an alignment hint John Garry
2025-02-05 19:20 ` Darrick J. Wong
2025-02-06 8:10 ` John Garry
2025-02-06 21:54 ` Darrick J. Wong
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250206215014.GX21808@frogsfrogsfrogs \
--to=djwong@kernel.org \
--cc=brauner@kernel.org \
--cc=cem@kernel.org \
--cc=dchinner@redhat.com \
--cc=hch@lst.de \
--cc=john.g.garry@oracle.com \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-xfs@vger.kernel.org \
--cc=martin.petersen@oracle.com \
--cc=ojaswin@linux.ibm.com \
--cc=ritesh.list@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.