From: David Sterba <dsterba@suse.cz>
To: Qu Wenruo <wqu@suse.com>
Cc: linux-btrfs@vger.kernel.org
Subject: Re: [PATCH v3] btrfs: Flush before reflinking any extent to prevent NOCOW write falling back to CoW without data reservation
Date: Thu, 9 May 2019 16:49:15 +0200 [thread overview]
Message-ID: <20190509144915.GV20156@twin.jikos.cz> (raw)
In-Reply-To: <20190508104958.18363-1-wqu@suse.com>
On Wed, May 08, 2019 at 06:49:58PM +0800, Qu Wenruo wrote:
> [BUG]
> The following script can cause unexpected fsync failure:
>
> #!/bin/bash
>
> dev=/dev/test/test
> mnt=/mnt/btrfs
>
> mkfs.btrfs -f $dev -b 512M > /dev/null
> mount $dev $mnt -o nospace_cache
>
> # Prealloc one extent
> xfs_io -f -c "falloc 8k 64m" $mnt/file1
> # Fill the remaining data space
> xfs_io -f -c "pwrite 0 -b 4k 512M" $mnt/padding
> sync
>
> # Write into the prealloc extent
> xfs_io -c "pwrite 1m 16m" $mnt/file1
>
> # Reflink then fsync, fsync would fail due to ENOSPC
> xfs_io -c "reflink $mnt/file1 8k 0 4k" -c "fsync" $mnt/file1
> umount $dev
>
> The fsync fails with ENOSPC, and the last page of the buffered write is
> lost.
>
> [CAUSE]
> This is caused by:
> - Btrfs' back reference only has extent level granularity
> So write into shared extent must be CoWed even only part of the extent
> is shared.
>
> So for above script we have:
> - fallocate
> Create a preallocated extent where we can do NOCOW write.
>
> - fill all the remaining data and unallocated space
>
> - buffered write into preallocated space
> As we have not enough space available for data and the extent is not
> shared (yet) we fall into NOCOW mode.
>
> - reflink
> Now part of the large preallocated extent is shared, later write
> into that extent must be CoWed.
>
> - fsync triggers writeback
> But now the extent is shared and therefore we must fallback into COW
> mode, which fails with ENOSPC since there's not enough space to
> allocate data extents.
>
> [WORKAROUND]
> The workaround is to ensure any buffered write in the related extents
> (not just the reflink source range) get flushed before reflink/dedupe,
> so that NOCOW writes succeed that happened before reflinking succeed.
>
> The workaround is expensive
Can you please quantify that, how big the performance drop is going to
be?
If the fsync comes soon after reflink, then it's effectively no change.
In case the buffered writes happen on a different range than reflink and
fsync comes later, the buffered writes will stall reflink, right?
If there are other similar corner cases we'd better know them in advance
and estimate the impact, that'll be something to look for when we get
complaints that reflink is suddenly slow.
> NOCOW range, but that needs extra accounting for NOCOW range.
> For now, fix the possible data loss first.
filemap_flush says
437 /**
438 * filemap_flush - mostly a non-blocking flush
439 * @mapping: target address_space
440 *
441 * This is a mostly non-blocking flush. Not suitable for data-integrity
442 * purposes - I/O may not be started against all dirty pages.
443 *
444 * Return: %0 on success, negative error code otherwise.
445 */
so how does this work together with the statement about preventing data
loss?
next prev parent reply other threads:[~2019-05-09 14:48 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-05-08 10:49 [PATCH v3] btrfs: Flush before reflinking any extent to prevent NOCOW write falling back to CoW without data reservation Qu Wenruo
2019-05-08 17:03 ` Filipe Manana
2019-05-09 14:49 ` David Sterba [this message]
2019-05-09 23:28 ` Qu Wenruo
2019-05-15 14:56 ` Filipe Manana
2019-05-31 10:56 ` Qu Wenruo
2019-05-31 12:26 ` David Sterba
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=20190509144915.GV20156@twin.jikos.cz \
--to=dsterba@suse.cz \
--cc=linux-btrfs@vger.kernel.org \
--cc=wqu@suse.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox