From: David Sterba <dsterba@suse.cz>
To: "Gustavo A. R. Silva" <gustavoars@kernel.org>
Cc: Qu Wenruo <quwenruo.btrfs@gmx.com>,
"Gustavo A. R. Silva" <gustavo@embeddedor.com>,
David Sterba <dsterba@suse.com>,
linux-btrfs@vger.kernel.org
Subject: Re: [PATCH] btrfs: add special case to setget helpers for 64k pages
Date: Fri, 2 Jul 2021 12:22:42 +0200 [thread overview]
Message-ID: <20210702102242.GD2610@twin.jikos.cz> (raw)
In-Reply-To: <20210702003936.GA13456@embeddedor>
On Thu, Jul 01, 2021 at 07:39:36PM -0500, Gustavo A. R. Silva wrote:
> On Fri, Jul 02, 2021 at 08:21:31AM +0800, Qu Wenruo wrote:
> > On 2021/7/2 上午8:09, Gustavo A. R. Silva wrote:
> > > On 7/1/21 18:59, Qu Wenruo wrote:
> > > > On 2021/7/2 上午5:57, Gustavo A. R. Silva wrote:
> > > > > On Thu, Jul 01, 2021 at 06:00:39PM +0200, David Sterba wrote:
> > > > > > On 64K pages the size of the extent_buffer::pages array is 1 and
> > > > > > compilation with -Warray-bounds warns due to
> > > > > >
> > > > > > kaddr = page_address(eb->pages[idx + 1]);
> > > > > >
> > > > > > when reading byte range crossing page boundary.
> > > > > >
> > > > > > This does never actually overflow the array because on 64K because all
> > > > > > the data fit in one page and bounds are checked by check_setget_bounds.
> > > > > >
> > > > > > To fix the reported overflow and warning add a copy of the non-crossing
> > > > > > read/write code and put it behind a condition that's evaluated at
> > > > > > compile time. That way only one implementation remains due to dead code
> > > > > > elimination.
> > > > >
> > > > > Any chance we can use a flexible-array in struct extent_buffer instead,
> > > > > so all the warnings are removed?
> > > > >
> > > > > Something like this:
> > > > >
> > > > > diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h
> > > > > index 62027f551b44..b82e8b694a3b 100644
> > > > > --- a/fs/btrfs/extent_io.h
> > > > > +++ b/fs/btrfs/extent_io.h
> > > > > @@ -94,11 +94,11 @@ struct extent_buffer {
> > > > >
> > > > > struct rw_semaphore lock;
> > > > >
> > > > > - struct page *pages[INLINE_EXTENT_BUFFER_PAGES];
> > > > > struct list_head release_list;
> > > > > #ifdef CONFIG_BTRFS_DEBUG
> > > > > struct list_head leak_list;
> > > > > #endif
> > > > > + struct page *pages[];
> > > > > };
> > > >
> > > > But wouldn't that make the the size of extent_buffer structure change
> > > > and affect the kmem cache for it?
> > >
> > > Could you please point out the places in the code that would be
> > > affected?
> >
> > Sure, the direct code get affected is here:
> >
> > extent_io.c:
> > int __init extent_io_init(void)
> > {
> > extent_buffer_cache = kmem_cache_create("btrfs_extent_buffer",
> > sizeof(struct extent_buffer), 0,
> > SLAB_MEM_SPREAD, NULL);
> >
> > So here we can no longer use sizeof(struct extent_buffer);
> >
> > Furthermore, this function is called at btrfs module load time,
> > at that time we have no idea how large the extent buffer could be, thus we
> > must allocate a large enough cache for extent buffer.
> >
> > Thus the size will be fixed to the current size, no matter if we use flex
> > array or not.
> >
> > Though I'm not sure if using such flex array with fixed real size can silent
> > the warning though.
>
> Yeah; I think this might be the right solution:
>
> diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
> index 9e81d25dea70..4cf0b72fdd9f 100644
> --- a/fs/btrfs/extent_io.c
> +++ b/fs/btrfs/extent_io.c
> @@ -232,8 +232,9 @@ int __init extent_state_cache_init(void)
> int __init extent_io_init(void)
> {
> extent_buffer_cache = kmem_cache_create("btrfs_extent_buffer",
> - sizeof(struct extent_buffer), 0,
> - SLAB_MEM_SPREAD, NULL);
> + struct_size((struct extent_buffer *)0, pages,
> + INLINE_EXTENT_BUFFER_PAGES),
> + 0, SLAB_MEM_SPREAD, NULL);
> if (!extent_buffer_cache)
> return -ENOMEM;
>
> diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h
> index 62027f551b44..b82e8b694a3b 100644
> --- a/fs/btrfs/extent_io.h
> +++ b/fs/btrfs/extent_io.h
> @@ -94,11 +94,11 @@ struct extent_buffer {
>
> struct rw_semaphore lock;
>
> - struct page *pages[INLINE_EXTENT_BUFFER_PAGES];
> struct list_head release_list;
> #ifdef CONFIG_BTRFS_DEBUG
> struct list_head leak_list;
> #endif
> + struct page *pages[];
IMHO this is going the wrong way, INLINE_EXTENT_BUFFER_PAGES is a
compile time constant and the array is not variable sized at all, so
adding the end member and using struct_size is just manually coding
what would compiler do for free.
next prev parent reply other threads:[~2021-07-02 10:25 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-07-01 16:00 [PATCH] btrfs: add special case to setget helpers for 64k pages David Sterba
2021-07-01 21:57 ` Gustavo A. R. Silva
2021-07-01 23:59 ` Qu Wenruo
2021-07-02 0:09 ` Gustavo A. R. Silva
2021-07-02 0:21 ` Qu Wenruo
2021-07-02 0:39 ` Gustavo A. R. Silva
2021-07-02 0:39 ` Qu Wenruo
2021-07-02 1:09 ` Gustavo A. R. Silva
2021-07-02 10:22 ` David Sterba [this message]
2021-07-02 7:10 ` Christoph Hellwig
2021-07-02 11:06 ` David Sterba
2021-07-05 8:33 ` Christoph Hellwig
2021-07-08 14:34 ` David Sterba
2021-07-14 23:37 ` Gustavo A. R. Silva
2021-07-28 15:32 ` David Sterba
2021-07-28 16:00 ` 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=20210702102242.GD2610@twin.jikos.cz \
--to=dsterba@suse.cz \
--cc=dsterba@suse.com \
--cc=gustavo@embeddedor.com \
--cc=gustavoars@kernel.org \
--cc=linux-btrfs@vger.kernel.org \
--cc=quwenruo.btrfs@gmx.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.