linux-btrfs.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Qu Wenruo <wqu@suse.com>
To: Nikolay Borisov <nborisov@suse.com>, linux-btrfs@vger.kernel.org
Cc: David Sterba <dsterba@suse.com>
Subject: Re: [PATCH 01/32] btrfs: extent_io: remove the extent_start/extent_len for end_bio_extent_readpage()
Date: Thu, 5 Nov 2020 18:15:56 +0800	[thread overview]
Message-ID: <1e7bf8d5-30d0-a944-c400-b5fe870f1cb5@suse.com> (raw)
In-Reply-To: <831ff919-f4f4-7f1b-1e60-ce8df4697651@suse.com>



On 2020/11/5 下午5:46, Nikolay Borisov wrote:
> 
> 
> On 3.11.20 г. 15:30 ч., Qu Wenruo wrote:
>> In end_bio_extent_readpage() we had a strange dance around
>> extent_start/extent_len.
>>
>> Hides behind the strange dance is, it's just calling
>> endio_readpage_release_extent() on each bvec range.
>>
>> Here is an example to explain the original work flow:
>>   Bio is for inode 257, containing 2 pages, for range [1M, 1M+8K)
>>
>>   end_bio_extent_extent_readpage() entered
>>   |- extent_start = 0;
>>   |- extent_end = 0;
>>   |- bio_for_each_segment_all() {
>>   |  |- /* Got the 1st bvec */
>>   |  |- start = SZ_1M;
>>   |  |- end = SZ_1M + SZ_4K - 1;
>>   |  |- update = 1;
>>   |  |- if (extent_len == 0) {
>>   |  |  |- extent_start = start; /* SZ_1M */
>>   |  |  |- extent_len = end + 1 - start; /* SZ_1M */
>>   |  |  }
>>   |  |
>>   |  |- /* Got the 2nd bvec */
>>   |  |- start = SZ_1M + 4K;
>>   |  |- end = SZ_1M + 4K - 1;
>>   |  |- update = 1;
>>   |  |- if (extent_start + extent_len == start) {
>>   |  |  |- extent_len += end + 1 - start; /* SZ_8K */
>>   |  |  }
>>   |  } /* All bio vec iterated */
>>   |
>>   |- if (extent_len) {
>>      |- endio_readpage_release_extent(tree, extent_start, extent_len,
>> 				      update);
>> 	/* extent_start == SZ_1M, extent_len == SZ_8K, uptodate = 1 */
>>
>> As the above flow shows, the existing code in end_bio_extent_readpage()
>> is just accumulate extent_start/extent_len, and when the contiguous range
>> breaks, call endio_readpage_release_extent() for the range.
>>
>> The contiguous range breaks at two locations:
>> - The total else {} branch
>>   This means we had a page in a bio where it's not contiguous.
>>   Currently this branch will never be triggered. As all our bio is
>>   submitted as contiguous pages.
>>
> 
> The endio routine cares about logical file contiguity as evidenced by
> the fact it uses page_offset() to calculate 'start', however our recent
> discussion on irc with the contiguity in csums bios clearly showed that
> we can have bios which contains pages that are contiguous in their disk
> byte nr but not in their logical offset, in fact Josef even mentioned on
> slack that a single bio can contain pages for different inodes so long
> as their logical disk byte nr are contiguous. I think this is not an
> issue in this case because you are doing the unlock on a bvec
> granularity but just the above statement is somewhat misleading.

Right, forgot the recent discovered bvec contig problem.

But still, the contig check condition is still correct, just the commit
message needs some update.

Another off-topic question is, should we allow such on-disk bytenr only
merge (to improve the IO output), or don't allow them to provide a
simpler endio function?

> 
>> - After the bio_for_each_segment_all() loop ends
>>   This is the normal call sites where we iterated all bvecs of a bio,
>>   and all pages should be contiguous, thus we can call
>>   endio_readpage_release_extent() on the full range.
>>
>> The original code has also considered cases like (!uptodate), so it will
>> mark the uptodate range with EXTENT_UPTODATE.
>>
>> So this patch will remove the extent_start/extent_len dancing, replace
>> it with regular endio_readpage_release_extent() call on each bvec.
>>
>> This brings one behavior change:
>> - Temporary memory usage increase
>>   Unlike the old call which only modify the extent tree once, now we
>>   update the extent tree for each bvec.
> 
> I suspect for large bios with a lot of bvecs this would likely increase
> latency because we will now invoke endio_readpage_release_extent
> proportionally to the number of bvecs.

I believe the same situation.

Now we need to do extent_io tree operations for each bvec.
We can slightly reduce the overhead if we have something like globally
cached extent_state.

Your comment indeed implies we should do better extent contig cache,
other than completely relying on extent io tree.

Maybe I could find some good way to improve the situation, while still
avoid doing the existing dancing.

> 
>>
>>   Although the end result is the same, since we may need more extent
>>   state split/allocation, we need more temporary memory during that
>>   bvec iteration.
> 
> Also bear in mind that this happens in a critical endio context, which
> uses GFP_ATOMIC allocations so if we get ENOSPC it would be rather bad.

I know you mean -ENOMEM.

But the true is, except the leading/tailing sector of the extent, we
shouldn't really cause extra split/allocation.

Each remaining extent should only enlarge previously modified extent_state.
Thus the end result for the extent io tree operation should not change much.

> 
>>
>> But considering how streamline the new code is, the temporary memory
>> usage increase should be acceptable.
> 
> I definitely like the new code however without quantifying what's the
> increase of number of calls of endio_readpage_release_extent I'd rather
> not merge it.

Your point stands.

I could add a new wrapper to do the same thing, but with a small help
from some new structure to really record the
inode/extent_start/extent_len internally.

The end result should be the same in the endio function, but much easier
to read. (The complex part would definite have more comment)

What about this solution?

Thanks,
Qu
> 
> On a different note, one minor cleanup that could be done is replace all
> those "end + 1 - start" expressions with simply "len" as this is
> effectively the length of the current bvec.
> 
> <snip>
> 


  reply	other threads:[~2020-11-05 10:16 UTC|newest]

Thread overview: 98+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-11-03 13:30 [PATCH 00/32] btrfs: preparation patches for subpage support Qu Wenruo
2020-11-03 13:30 ` [PATCH 01/32] btrfs: extent_io: remove the extent_start/extent_len for end_bio_extent_readpage() Qu Wenruo
2020-11-05  9:46   ` Nikolay Borisov
2020-11-05 10:15     ` Qu Wenruo [this message]
2020-11-05 10:32       ` Nikolay Borisov
2020-11-06  2:01         ` Qu Wenruo
2020-11-06  7:19           ` Qu Wenruo
2020-11-05 19:40   ` Josef Bacik
2020-11-06  1:52     ` Qu Wenruo
2020-11-03 13:30 ` [PATCH 02/32] btrfs: extent_io: integrate page status update into endio_readpage_release_extent() Qu Wenruo
2020-11-05 10:26   ` Nikolay Borisov
2020-11-05 11:15     ` Qu Wenruo
2020-11-05 10:35   ` Nikolay Borisov
2020-11-05 11:25     ` Qu Wenruo
2020-11-05 19:34   ` Josef Bacik
2020-11-03 13:30 ` [PATCH 03/32] btrfs: extent_io: add lockdep_assert_held() for attach_extent_buffer_page() Qu Wenruo
2020-11-03 13:30 ` [PATCH 04/32] btrfs: extent_io: extract the btree page submission code into its own helper function Qu Wenruo
2020-11-05 10:47   ` Nikolay Borisov
2020-11-06 18:11     ` David Sterba
2020-11-03 13:30 ` [PATCH 05/32] btrfs: extent-io-tests: remove invalid tests Qu Wenruo
2020-11-03 13:30 ` [PATCH 06/32] btrfs: extent_io: calculate inline extent buffer page size based on page size Qu Wenruo
2020-11-05 12:54   ` Nikolay Borisov
2020-11-03 13:30 ` [PATCH 07/32] btrfs: extent_io: make btrfs_fs_info::buffer_radix to take sector size devided values Qu Wenruo
2020-11-03 13:30 ` [PATCH 08/32] btrfs: extent_io: sink less common parameters for __set_extent_bit() Qu Wenruo
2020-11-05 13:35   ` Nikolay Borisov
2020-11-05 13:55     ` Qu Wenruo
2020-11-03 13:30 ` [PATCH 09/32] btrfs: extent_io: sink less common parameters for __clear_extent_bit() Qu Wenruo
2020-11-03 13:30 ` [PATCH 10/32] btrfs: disk_io: grab fs_info from extent_buffer::fs_info directly for btrfs_mark_buffer_dirty() Qu Wenruo
2020-11-05 13:45   ` Nikolay Borisov
2020-11-05 13:49   ` Nikolay Borisov
2020-11-03 13:30 ` [PATCH 11/32] btrfs: disk-io: make csum_tree_block() handle sectorsize smaller than page size Qu Wenruo
2020-11-06 18:58   ` David Sterba
2020-11-07  0:04     ` Qu Wenruo
2020-11-10 14:33       ` David Sterba
2020-11-11  0:08         ` Qu Wenruo
2020-11-03 13:30 ` [PATCH 12/32] btrfs: disk-io: extract the extent buffer verification from btrfs_validate_metadata_buffer() Qu Wenruo
2020-11-05 13:57   ` Nikolay Borisov
2020-11-06 19:03     ` David Sterba
2020-11-09  6:44       ` Qu Wenruo
2020-11-10 14:37         ` David Sterba
2020-11-03 13:30 ` [PATCH 13/32] btrfs: disk-io: accept bvec directly for csum_dirty_buffer() Qu Wenruo
2020-11-05 14:13   ` Nikolay Borisov
2020-11-03 13:30 ` [PATCH 14/32] btrfs: inode: make btrfs_readpage_end_io_hook() follow sector size Qu Wenruo
2020-11-05 14:28   ` Nikolay Borisov
2020-11-06 19:16     ` David Sterba
2020-11-06 19:20       ` David Sterba
2020-11-06 19:28   ` David Sterba
2020-11-03 13:30 ` [PATCH 15/32] btrfs: introduce a helper to determine if the sectorsize is smaller than PAGE_SIZE Qu Wenruo
2020-11-05 15:01   ` Nikolay Borisov
2020-11-05 22:52     ` Qu Wenruo
2020-11-06 17:28       ` David Sterba
2020-11-07  0:00         ` Qu Wenruo
2020-11-10 14:53           ` David Sterba
2020-11-11  1:34             ` Qu Wenruo
2020-11-11  2:21               ` Qu Wenruo
2020-11-03 13:30 ` [PATCH 16/32] btrfs: extent_io: allow find_first_extent_bit() to find a range with exact bits match Qu Wenruo
2020-11-05 15:03   ` Nikolay Borisov
2020-11-05 22:55     ` Qu Wenruo
2020-11-03 13:30 ` [PATCH 17/32] btrfs: extent_io: don't allow tree block to cross page boundary for subpage support Qu Wenruo
2020-11-06 11:54   ` Nikolay Borisov
2020-11-06 12:03     ` Nikolay Borisov
2020-11-06 13:25     ` Qu Wenruo
2020-11-06 14:04       ` Nikolay Borisov
2020-11-06 23:56         ` Qu Wenruo
2020-11-03 13:30 ` [PATCH 18/32] btrfs: extent_io: update num_extent_pages() to support subpage sized extent buffer Qu Wenruo
2020-11-06 12:09   ` Nikolay Borisov
2020-11-03 13:30 ` [PATCH 19/32] btrfs: handle sectorsize < PAGE_SIZE case for extent buffer accessors Qu Wenruo
2020-11-06 12:51   ` Nikolay Borisov
2020-11-09  5:49     ` Qu Wenruo
2020-11-03 13:30 ` [PATCH 20/32] btrfs: disk-io: only clear EXTENT_LOCK bit for extent_invalidatepage() Qu Wenruo
2020-11-06 13:17   ` Nikolay Borisov
2020-11-03 13:30 ` [PATCH 21/32] btrfs: extent-io: make type of extent_state::state to be at least 32 bits Qu Wenruo
2020-11-06 13:38   ` Nikolay Borisov
2020-11-03 13:30 ` [PATCH 22/32] btrfs: file-item: use nodesize to determine whether we need readahead for btrfs_lookup_bio_sums() Qu Wenruo
2020-11-06 13:55   ` Nikolay Borisov
2020-11-03 13:30 ` [PATCH 23/32] btrfs: file-item: remove the btrfs_find_ordered_sum() call in btrfs_lookup_bio_sums() Qu Wenruo
2020-11-06 14:28   ` Nikolay Borisov
2020-11-03 13:31 ` [PATCH 24/32] btrfs: file-item: refactor btrfs_lookup_bio_sums() to handle out-of-order bvecs Qu Wenruo
2020-11-06 15:22   ` Nikolay Borisov
2020-11-03 13:31 ` [PATCH 25/32] btrfs: scrub: distinguish scrub_page from regular page Qu Wenruo
2020-11-03 13:31 ` [PATCH 26/32] btrfs: scrub: remove the @force parameter of scrub_pages() Qu Wenruo
2020-11-03 13:31 ` [PATCH 27/32] btrfs: scrub: use flexible array for scrub_page::csums Qu Wenruo
2020-11-09 17:44   ` David Sterba
2020-11-10  0:53     ` Qu Wenruo
2020-11-10 14:22       ` David Sterba
2020-11-03 13:31 ` [PATCH 28/32] btrfs: scrub: refactor scrub_find_csum() Qu Wenruo
2020-11-03 13:31 ` [PATCH 29/32] btrfs: scrub: introduce scrub_page::page_len for subpage support Qu Wenruo
2020-11-09 18:17   ` David Sterba
2020-11-10  0:54     ` Qu Wenruo
2020-11-09 18:25   ` David Sterba
2020-11-10  0:56     ` Qu Wenruo
2020-11-10 14:27       ` David Sterba
2020-11-03 13:31 ` [PATCH 30/32] btrfs: scrub: always allocate one full page for one sector for RAID56 Qu Wenruo
2020-11-03 13:31 ` [PATCH 31/32] btrfs: scrub: support subpage tree block scrub Qu Wenruo
2020-11-09 18:31   ` David Sterba
2020-11-03 13:31 ` [PATCH 32/32] btrfs: scrub: support subpage data scrub Qu Wenruo
2020-11-05 19:28 ` [PATCH 00/32] btrfs: preparation patches for subpage support Josef Bacik
2020-11-06  0:02   ` Qu Wenruo

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=1e7bf8d5-30d0-a944-c400-b5fe870f1cb5@suse.com \
    --to=wqu@suse.com \
    --cc=dsterba@suse.com \
    --cc=linux-btrfs@vger.kernel.org \
    --cc=nborisov@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;
as well as URLs for NNTP newsgroup(s).