diff mbox series

[7/7] fs: Fix a confusing error about overlapping regions

Message ID 20230823134209.1450567-8-sjg@chromium.org
State Changes Requested
Delegated to: Tom Rini
Headers show
Series Correct confusing lmb error message | expand

Commit Message

Simon Glass Aug. 23, 2023, 1:42 p.m. UTC
When lmb runs out of space in its internal tables, it gives errors on
every fs load operation. This is horribly confusing, as the poor user
tries different memory regions one at a time.

Use the updated API to check the error code and print a helpful message.
Also, allow the operation to proceed.

Update the tests accordingly.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 fs/fs.c        |  7 ++++++-
 include/lmb.h  | 19 ++++++++++++++++++-
 lib/lmb.c      | 20 +++++++++++---------
 test/lib/lmb.c | 42 ++++++++++++++++++++----------------------
 4 files changed, 55 insertions(+), 33 deletions(-)

Comments

Tom Rini Aug. 23, 2023, 3:14 p.m. UTC | #1
On Wed, Aug 23, 2023 at 07:42:03AM -0600, Simon Glass wrote:

> When lmb runs out of space in its internal tables, it gives errors on
> every fs load operation. This is horribly confusing, as the poor user
> tries different memory regions one at a time.
> 
> Use the updated API to check the error code and print a helpful message.
> Also, allow the operation to proceed.
> 
> Update the tests accordingly.
> 
> Signed-off-by: Simon Glass <sjg@chromium.org>
[snip]
> +	if (ret == -E2BIG) {
> +		log_warning("Reservation tables exhausted: see CONFIG_LMB_USE_MAX_REGIONS\n");
> +		return 0;
> +	}

This isn't the right option.  Everyone has CONFIG_LMB_USE_MAX_REGIONS
set.  You would want to increase CONFIG_LMB_MAX_REGIONS.

But it sounds like what you've found and fixed is an underlying problem
as to why 16 regions isn't enough in some common cases now?  So we could
possibly avoid the string size growth here and have a comment that also
matches up with the help under LMB_MAX_REGIONS?
Simon Glass Sept. 1, 2023, 12:15 a.m. UTC | #2
Hi Tom,

On Wed, 23 Aug 2023 at 09:14, Tom Rini <trini@konsulko.com> wrote:
>
> On Wed, Aug 23, 2023 at 07:42:03AM -0600, Simon Glass wrote:
>
> > When lmb runs out of space in its internal tables, it gives errors on
> > every fs load operation. This is horribly confusing, as the poor user
> > tries different memory regions one at a time.
> >
> > Use the updated API to check the error code and print a helpful message.
> > Also, allow the operation to proceed.
> >
> > Update the tests accordingly.
> >
> > Signed-off-by: Simon Glass <sjg@chromium.org>
> [snip]
> > +     if (ret == -E2BIG) {
> > +             log_warning("Reservation tables exhausted: see CONFIG_LMB_USE_MAX_REGIONS\n");
> > +             return 0;
> > +     }
>
> This isn't the right option.  Everyone has CONFIG_LMB_USE_MAX_REGIONS
> set.  You would want to increase CONFIG_LMB_MAX_REGIONS.
>
> But it sounds like what you've found and fixed is an underlying problem
> as to why 16 regions isn't enough in some common cases now?  So we could

I don't think I have fixed anything. But I'll send v2 and perhaps it
will be clearer what is going on here.

> possibly avoid the string size growth here and have a comment that also
> matches up with the help under LMB_MAX_REGIONS?

I don't know, sorry. The size of struct(lmb) on 64-bit sandbox is
about 400 bytes. There seems to be a lot of code to save not much
memory.

Regards,
Simom
Tom Rini Sept. 3, 2023, 4:42 p.m. UTC | #3
On Thu, Aug 31, 2023 at 06:15:19PM -0600, Simon Glass wrote:
> Hi Tom,
> 
> On Wed, 23 Aug 2023 at 09:14, Tom Rini <trini@konsulko.com> wrote:
> >
> > On Wed, Aug 23, 2023 at 07:42:03AM -0600, Simon Glass wrote:
> >
> > > When lmb runs out of space in its internal tables, it gives errors on
> > > every fs load operation. This is horribly confusing, as the poor user
> > > tries different memory regions one at a time.
> > >
> > > Use the updated API to check the error code and print a helpful message.
> > > Also, allow the operation to proceed.
> > >
> > > Update the tests accordingly.
> > >
> > > Signed-off-by: Simon Glass <sjg@chromium.org>
> > [snip]
> > > +     if (ret == -E2BIG) {
> > > +             log_warning("Reservation tables exhausted: see CONFIG_LMB_USE_MAX_REGIONS\n");
> > > +             return 0;
> > > +     }
> >
> > This isn't the right option.  Everyone has CONFIG_LMB_USE_MAX_REGIONS
> > set.  You would want to increase CONFIG_LMB_MAX_REGIONS.
> >
> > But it sounds like what you've found and fixed is an underlying problem
> > as to why 16 regions isn't enough in some common cases now?  So we could
> 
> I don't think I have fixed anything. But I'll send v2 and perhaps it
> will be clearer what is going on here.
> 
> > possibly avoid the string size growth here and have a comment that also
> > matches up with the help under LMB_MAX_REGIONS?
> 
> I don't know, sorry. The size of struct(lmb) on 64-bit sandbox is
> about 400 bytes. There seems to be a lot of code to save not much
> memory.

What do you mean here?  The alternative is not unlimited ranges but
instead to define the limit of memory regions and limit of reserved
ranges.
Simon Glass Sept. 3, 2023, 6:06 p.m. UTC | #4
Hi Tom,

On Sun, 3 Sept 2023 at 10:42, Tom Rini <trini@konsulko.com> wrote:
>
> On Thu, Aug 31, 2023 at 06:15:19PM -0600, Simon Glass wrote:
> > Hi Tom,
> >
> > On Wed, 23 Aug 2023 at 09:14, Tom Rini <trini@konsulko.com> wrote:
> > >
> > > On Wed, Aug 23, 2023 at 07:42:03AM -0600, Simon Glass wrote:
> > >
> > > > When lmb runs out of space in its internal tables, it gives errors on
> > > > every fs load operation. This is horribly confusing, as the poor user
> > > > tries different memory regions one at a time.
> > > >
> > > > Use the updated API to check the error code and print a helpful message.
> > > > Also, allow the operation to proceed.
> > > >
> > > > Update the tests accordingly.
> > > >
> > > > Signed-off-by: Simon Glass <sjg@chromium.org>
> > > [snip]
> > > > +     if (ret == -E2BIG) {
> > > > +             log_warning("Reservation tables exhausted: see CONFIG_LMB_USE_MAX_REGIONS\n");
> > > > +             return 0;
> > > > +     }
> > >
> > > This isn't the right option.  Everyone has CONFIG_LMB_USE_MAX_REGIONS
> > > set.  You would want to increase CONFIG_LMB_MAX_REGIONS.
> > >
> > > But it sounds like what you've found and fixed is an underlying problem
> > > as to why 16 regions isn't enough in some common cases now?  So we could
> >
> > I don't think I have fixed anything. But I'll send v2 and perhaps it
> > will be clearer what is going on here.
> >
> > > possibly avoid the string size growth here and have a comment that also
> > > matches up with the help under LMB_MAX_REGIONS?
> >
> > I don't know, sorry. The size of struct(lmb) on 64-bit sandbox is
> > about 400 bytes. There seems to be a lot of code to save not much
> > memory.
>
> What do you mean here?  The alternative is not unlimited ranges but
> instead to define the limit of memory regions and limit of reserved
> ranges.

A better alternative would be not to limit the number of regions, IMO,
i.e. have an array of regions that can grow as needed.

Regards,
Simon
Tom Rini Sept. 3, 2023, 7:25 p.m. UTC | #5
On Sun, Sep 03, 2023 at 12:06:13PM -0600, Simon Glass wrote:
> Hi Tom,
> 
> On Sun, 3 Sept 2023 at 10:42, Tom Rini <trini@konsulko.com> wrote:
> >
> > On Thu, Aug 31, 2023 at 06:15:19PM -0600, Simon Glass wrote:
> > > Hi Tom,
> > >
> > > On Wed, 23 Aug 2023 at 09:14, Tom Rini <trini@konsulko.com> wrote:
> > > >
> > > > On Wed, Aug 23, 2023 at 07:42:03AM -0600, Simon Glass wrote:
> > > >
> > > > > When lmb runs out of space in its internal tables, it gives errors on
> > > > > every fs load operation. This is horribly confusing, as the poor user
> > > > > tries different memory regions one at a time.
> > > > >
> > > > > Use the updated API to check the error code and print a helpful message.
> > > > > Also, allow the operation to proceed.
> > > > >
> > > > > Update the tests accordingly.
> > > > >
> > > > > Signed-off-by: Simon Glass <sjg@chromium.org>
> > > > [snip]
> > > > > +     if (ret == -E2BIG) {
> > > > > +             log_warning("Reservation tables exhausted: see CONFIG_LMB_USE_MAX_REGIONS\n");
> > > > > +             return 0;
> > > > > +     }
> > > >
> > > > This isn't the right option.  Everyone has CONFIG_LMB_USE_MAX_REGIONS
> > > > set.  You would want to increase CONFIG_LMB_MAX_REGIONS.
> > > >
> > > > But it sounds like what you've found and fixed is an underlying problem
> > > > as to why 16 regions isn't enough in some common cases now?  So we could
> > >
> > > I don't think I have fixed anything. But I'll send v2 and perhaps it
> > > will be clearer what is going on here.
> > >
> > > > possibly avoid the string size growth here and have a comment that also
> > > > matches up with the help under LMB_MAX_REGIONS?
> > >
> > > I don't know, sorry. The size of struct(lmb) on 64-bit sandbox is
> > > about 400 bytes. There seems to be a lot of code to save not much
> > > memory.
> >
> > What do you mean here?  The alternative is not unlimited ranges but
> > instead to define the limit of memory regions and limit of reserved
> > ranges.
> 
> A better alternative would be not to limit the number of regions, IMO,
> i.e. have an array of regions that can grow as needed.

That's not something that we have in the code today, however.
Simon Glass Sept. 5, 2023, 6:16 p.m. UTC | #6
Hi Tom,

On Sun, 3 Sept 2023 at 13:25, Tom Rini <trini@konsulko.com> wrote:
>
> On Sun, Sep 03, 2023 at 12:06:13PM -0600, Simon Glass wrote:
> > Hi Tom,
> >
> > On Sun, 3 Sept 2023 at 10:42, Tom Rini <trini@konsulko.com> wrote:
> > >
> > > On Thu, Aug 31, 2023 at 06:15:19PM -0600, Simon Glass wrote:
> > > > Hi Tom,
> > > >
> > > > On Wed, 23 Aug 2023 at 09:14, Tom Rini <trini@konsulko.com> wrote:
> > > > >
> > > > > On Wed, Aug 23, 2023 at 07:42:03AM -0600, Simon Glass wrote:
> > > > >
> > > > > > When lmb runs out of space in its internal tables, it gives
errors on
> > > > > > every fs load operation. This is horribly confusing, as the
poor user
> > > > > > tries different memory regions one at a time.
> > > > > >
> > > > > > Use the updated API to check the error code and print a helpful
message.
> > > > > > Also, allow the operation to proceed.
> > > > > >
> > > > > > Update the tests accordingly.
> > > > > >
> > > > > > Signed-off-by: Simon Glass <sjg@chromium.org>
> > > > > [snip]
> > > > > > +     if (ret == -E2BIG) {
> > > > > > +             log_warning("Reservation tables exhausted: see
CONFIG_LMB_USE_MAX_REGIONS\n");
> > > > > > +             return 0;
> > > > > > +     }
> > > > >
> > > > > This isn't the right option.  Everyone has
CONFIG_LMB_USE_MAX_REGIONS
> > > > > set.  You would want to increase CONFIG_LMB_MAX_REGIONS.
> > > > >
> > > > > But it sounds like what you've found and fixed is an underlying
problem
> > > > > as to why 16 regions isn't enough in some common cases now?  So
we could
> > > >
> > > > I don't think I have fixed anything. But I'll send v2 and perhaps it
> > > > will be clearer what is going on here.
> > > >
> > > > > possibly avoid the string size growth here and have a comment
that also
> > > > > matches up with the help under LMB_MAX_REGIONS?
> > > >
> > > > I don't know, sorry. The size of struct(lmb) on 64-bit sandbox is
> > > > about 400 bytes. There seems to be a lot of code to save not much
> > > > memory.
> > >
> > > What do you mean here?  The alternative is not unlimited ranges but
> > > instead to define the limit of memory regions and limit of reserved
> > > ranges.
> >
> > A better alternative would be not to limit the number of regions, IMO,
> > i.e. have an array of regions that can grow as needed.
>
> That's not something that we have in the code today, however.

No, I do have an arraylist thing that I plan to upstream, which could
handle that.

But for this series, what do you think of the memregion idea? I am still
unsure of the saming we should use - see Heinrich's comments too.

Regards,
Simon
Tom Rini Sept. 6, 2023, 5:57 p.m. UTC | #7
On Tue, Sep 05, 2023 at 12:16:56PM -0600, Simon Glass wrote:
> Hi Tom,
> 
> On Sun, 3 Sept 2023 at 13:25, Tom Rini <trini@konsulko.com> wrote:
> >
> > On Sun, Sep 03, 2023 at 12:06:13PM -0600, Simon Glass wrote:
> > > Hi Tom,
> > >
> > > On Sun, 3 Sept 2023 at 10:42, Tom Rini <trini@konsulko.com> wrote:
> > > >
> > > > On Thu, Aug 31, 2023 at 06:15:19PM -0600, Simon Glass wrote:
> > > > > Hi Tom,
> > > > >
> > > > > On Wed, 23 Aug 2023 at 09:14, Tom Rini <trini@konsulko.com> wrote:
> > > > > >
> > > > > > On Wed, Aug 23, 2023 at 07:42:03AM -0600, Simon Glass wrote:
> > > > > >
> > > > > > > When lmb runs out of space in its internal tables, it gives
> errors on
> > > > > > > every fs load operation. This is horribly confusing, as the
> poor user
> > > > > > > tries different memory regions one at a time.
> > > > > > >
> > > > > > > Use the updated API to check the error code and print a helpful
> message.
> > > > > > > Also, allow the operation to proceed.
> > > > > > >
> > > > > > > Update the tests accordingly.
> > > > > > >
> > > > > > > Signed-off-by: Simon Glass <sjg@chromium.org>
> > > > > > [snip]
> > > > > > > +     if (ret == -E2BIG) {
> > > > > > > +             log_warning("Reservation tables exhausted: see
> CONFIG_LMB_USE_MAX_REGIONS\n");
> > > > > > > +             return 0;
> > > > > > > +     }
> > > > > >
> > > > > > This isn't the right option.  Everyone has
> CONFIG_LMB_USE_MAX_REGIONS
> > > > > > set.  You would want to increase CONFIG_LMB_MAX_REGIONS.
> > > > > >
> > > > > > But it sounds like what you've found and fixed is an underlying
> problem
> > > > > > as to why 16 regions isn't enough in some common cases now?  So
> we could
> > > > >
> > > > > I don't think I have fixed anything. But I'll send v2 and perhaps it
> > > > > will be clearer what is going on here.
> > > > >
> > > > > > possibly avoid the string size growth here and have a comment
> that also
> > > > > > matches up with the help under LMB_MAX_REGIONS?
> > > > >
> > > > > I don't know, sorry. The size of struct(lmb) on 64-bit sandbox is
> > > > > about 400 bytes. There seems to be a lot of code to save not much
> > > > > memory.
> > > >
> > > > What do you mean here?  The alternative is not unlimited ranges but
> > > > instead to define the limit of memory regions and limit of reserved
> > > > ranges.
> > >
> > > A better alternative would be not to limit the number of regions, IMO,
> > > i.e. have an array of regions that can grow as needed.
> >
> > That's not something that we have in the code today, however.
> 
> No, I do have an arraylist thing that I plan to upstream, which could
> handle that.
> 
> But for this series, what do you think of the memregion idea? I am still
> unsure of the saming we should use - see Heinrich's comments too.

My biggest worry here is that we're papering over a real issue, and
should either dig at that and see what's going on (should something be
coalescing adjacent allocations? Were many platforms just right at the
previous limit?) or just bump the default from 16 to "64 if EFI_LOADER"
and then see if anything else really needs tweaking / cleaning up in the
code itself.  I know Heinrich has previously said the LMB system could
be better (or something to that effect, I'm going from memory, sorry if
I'm mis-stating things) and I don't object to replacing what we have
with something more robust/smarter/etc.
Simon Glass Sept. 7, 2023, 12:23 p.m. UTC | #8
Hi Tom,

On Wed, 6 Sept 2023 at 11:58, Tom Rini <trini@konsulko.com> wrote:
>
> On Tue, Sep 05, 2023 at 12:16:56PM -0600, Simon Glass wrote:
> > Hi Tom,
> >
> > On Sun, 3 Sept 2023 at 13:25, Tom Rini <trini@konsulko.com> wrote:
> > >
> > > On Sun, Sep 03, 2023 at 12:06:13PM -0600, Simon Glass wrote:
> > > > Hi Tom,
> > > >
> > > > On Sun, 3 Sept 2023 at 10:42, Tom Rini <trini@konsulko.com> wrote:
> > > > >
> > > > > On Thu, Aug 31, 2023 at 06:15:19PM -0600, Simon Glass wrote:
> > > > > > Hi Tom,
> > > > > >
> > > > > > On Wed, 23 Aug 2023 at 09:14, Tom Rini <trini@konsulko.com> wrote:
> > > > > > >
> > > > > > > On Wed, Aug 23, 2023 at 07:42:03AM -0600, Simon Glass wrote:
> > > > > > >
> > > > > > > > When lmb runs out of space in its internal tables, it gives
> > errors on
> > > > > > > > every fs load operation. This is horribly confusing, as the
> > poor user
> > > > > > > > tries different memory regions one at a time.
> > > > > > > >
> > > > > > > > Use the updated API to check the error code and print a helpful
> > message.
> > > > > > > > Also, allow the operation to proceed.
> > > > > > > >
> > > > > > > > Update the tests accordingly.
> > > > > > > >
> > > > > > > > Signed-off-by: Simon Glass <sjg@chromium.org>
> > > > > > > [snip]
> > > > > > > > +     if (ret == -E2BIG) {
> > > > > > > > +             log_warning("Reservation tables exhausted: see
> > CONFIG_LMB_USE_MAX_REGIONS\n");
> > > > > > > > +             return 0;
> > > > > > > > +     }
> > > > > > >
> > > > > > > This isn't the right option.  Everyone has
> > CONFIG_LMB_USE_MAX_REGIONS
> > > > > > > set.  You would want to increase CONFIG_LMB_MAX_REGIONS.
> > > > > > >
> > > > > > > But it sounds like what you've found and fixed is an underlying
> > problem
> > > > > > > as to why 16 regions isn't enough in some common cases now?  So
> > we could
> > > > > >
> > > > > > I don't think I have fixed anything. But I'll send v2 and perhaps it
> > > > > > will be clearer what is going on here.
> > > > > >
> > > > > > > possibly avoid the string size growth here and have a comment
> > that also
> > > > > > > matches up with the help under LMB_MAX_REGIONS?
> > > > > >
> > > > > > I don't know, sorry. The size of struct(lmb) on 64-bit sandbox is
> > > > > > about 400 bytes. There seems to be a lot of code to save not much
> > > > > > memory.
> > > > >
> > > > > What do you mean here?  The alternative is not unlimited ranges but
> > > > > instead to define the limit of memory regions and limit of reserved
> > > > > ranges.
> > > >
> > > > A better alternative would be not to limit the number of regions, IMO,
> > > > i.e. have an array of regions that can grow as needed.
> > >
> > > That's not something that we have in the code today, however.
> >
> > No, I do have an arraylist thing that I plan to upstream, which could
> > handle that.
> >
> > But for this series, what do you think of the memregion idea? I am still
> > unsure of the saming we should use - see Heinrich's comments too.
>
> My biggest worry here is that we're papering over a real issue, and
> should either dig at that and see what's going on (should something be
> coalescing adjacent allocations? Were many platforms just right at the
> previous limit?) or just bump the default from 16 to "64 if EFI_LOADER"
> and then see if anything else really needs tweaking / cleaning up in the
> code itself.  I know Heinrich has previously said the LMB system could
> be better (or something to that effect, I'm going from memory, sorry if
> I'm mis-stating things) and I don't object to replacing what we have
> with something more robust/smarter/etc.

I am not sure...my series was designed to rename the code to reduce
confusion, and print a useful message when we run out of regions. It
does not paper over the problem, but actually makes it more visible.

Regards,
Simon
Tom Rini Sept. 7, 2023, 7:40 p.m. UTC | #9
On Thu, Sep 07, 2023 at 06:23:06AM -0600, Simon Glass wrote:
> Hi Tom,
> 
> On Wed, 6 Sept 2023 at 11:58, Tom Rini <trini@konsulko.com> wrote:
> >
> > On Tue, Sep 05, 2023 at 12:16:56PM -0600, Simon Glass wrote:
> > > Hi Tom,
> > >
> > > On Sun, 3 Sept 2023 at 13:25, Tom Rini <trini@konsulko.com> wrote:
> > > >
> > > > On Sun, Sep 03, 2023 at 12:06:13PM -0600, Simon Glass wrote:
> > > > > Hi Tom,
> > > > >
> > > > > On Sun, 3 Sept 2023 at 10:42, Tom Rini <trini@konsulko.com> wrote:
> > > > > >
> > > > > > On Thu, Aug 31, 2023 at 06:15:19PM -0600, Simon Glass wrote:
> > > > > > > Hi Tom,
> > > > > > >
> > > > > > > On Wed, 23 Aug 2023 at 09:14, Tom Rini <trini@konsulko.com> wrote:
> > > > > > > >
> > > > > > > > On Wed, Aug 23, 2023 at 07:42:03AM -0600, Simon Glass wrote:
> > > > > > > >
> > > > > > > > > When lmb runs out of space in its internal tables, it gives
> > > errors on
> > > > > > > > > every fs load operation. This is horribly confusing, as the
> > > poor user
> > > > > > > > > tries different memory regions one at a time.
> > > > > > > > >
> > > > > > > > > Use the updated API to check the error code and print a helpful
> > > message.
> > > > > > > > > Also, allow the operation to proceed.
> > > > > > > > >
> > > > > > > > > Update the tests accordingly.
> > > > > > > > >
> > > > > > > > > Signed-off-by: Simon Glass <sjg@chromium.org>
> > > > > > > > [snip]
> > > > > > > > > +     if (ret == -E2BIG) {
> > > > > > > > > +             log_warning("Reservation tables exhausted: see
> > > CONFIG_LMB_USE_MAX_REGIONS\n");
> > > > > > > > > +             return 0;
> > > > > > > > > +     }
> > > > > > > >
> > > > > > > > This isn't the right option.  Everyone has
> > > CONFIG_LMB_USE_MAX_REGIONS
> > > > > > > > set.  You would want to increase CONFIG_LMB_MAX_REGIONS.
> > > > > > > >
> > > > > > > > But it sounds like what you've found and fixed is an underlying
> > > problem
> > > > > > > > as to why 16 regions isn't enough in some common cases now?  So
> > > we could
> > > > > > >
> > > > > > > I don't think I have fixed anything. But I'll send v2 and perhaps it
> > > > > > > will be clearer what is going on here.
> > > > > > >
> > > > > > > > possibly avoid the string size growth here and have a comment
> > > that also
> > > > > > > > matches up with the help under LMB_MAX_REGIONS?
> > > > > > >
> > > > > > > I don't know, sorry. The size of struct(lmb) on 64-bit sandbox is
> > > > > > > about 400 bytes. There seems to be a lot of code to save not much
> > > > > > > memory.
> > > > > >
> > > > > > What do you mean here?  The alternative is not unlimited ranges but
> > > > > > instead to define the limit of memory regions and limit of reserved
> > > > > > ranges.
> > > > >
> > > > > A better alternative would be not to limit the number of regions, IMO,
> > > > > i.e. have an array of regions that can grow as needed.
> > > >
> > > > That's not something that we have in the code today, however.
> > >
> > > No, I do have an arraylist thing that I plan to upstream, which could
> > > handle that.
> > >
> > > But for this series, what do you think of the memregion idea? I am still
> > > unsure of the saming we should use - see Heinrich's comments too.
> >
> > My biggest worry here is that we're papering over a real issue, and
> > should either dig at that and see what's going on (should something be
> > coalescing adjacent allocations? Were many platforms just right at the
> > previous limit?) or just bump the default from 16 to "64 if EFI_LOADER"
> > and then see if anything else really needs tweaking / cleaning up in the
> > code itself.  I know Heinrich has previously said the LMB system could
> > be better (or something to that effect, I'm going from memory, sorry if
> > I'm mis-stating things) and I don't object to replacing what we have
> > with something more robust/smarter/etc.
> 
> I am not sure...my series was designed to rename the code to reduce
> confusion, and print a useful message when we run out of regions. It
> does not paper over the problem, but actually makes it more visible.

Well, "papering over" maybe wasn't the best choice of words on my part.
But since the series of events was something like:
- We nee to use LMB to cover my U-Boot regions to address a handful of
  CVEs over arbitrarily overwriting U-Boot at run-time.
  - AFAICT no platforms suddenly ran out of LMB reservation space, but
    maybe I'm wrong?
- Someone noted that the EFI subsystem was exposing the same kind of
  issue.
- Heinrich adds logic for EFI_LOADER (iirc) to also add allocations
  there to LMB
- Assorted platforms start changing the max allocation to 64 to fix the
  problems that get reported sometimes by booting.
- Heinrich notes that our memory reservation system (LMB) could be
  better designed than it is today.
  - And, iirc, EFI_LOADER or similar has something maybe we can
    leverage?

Which brings me to what I was trying to say.  I'm not sure it's worth
cleaning up the code a little, or refactoring/renaming things within it
without both:
- Understanding why EFI_LOADER being enabled causes us to run out of
  allocations and so if the answer is "increase the default" OR "fix
  some underlying issue such as coalescing being too strict or broken".
- Understanding if there's a better memory reservation system we can use
  instead.
Simon Glass Sept. 7, 2023, 9:01 p.m. UTC | #10
Hi Tom,

On Thu, 7 Sept 2023 at 13:40, Tom Rini <trini@konsulko.com> wrote:
>
> On Thu, Sep 07, 2023 at 06:23:06AM -0600, Simon Glass wrote:
> > Hi Tom,
> >
> > On Wed, 6 Sept 2023 at 11:58, Tom Rini <trini@konsulko.com> wrote:
> > >
> > > On Tue, Sep 05, 2023 at 12:16:56PM -0600, Simon Glass wrote:
> > > > Hi Tom,
> > > >
> > > > On Sun, 3 Sept 2023 at 13:25, Tom Rini <trini@konsulko.com> wrote:
> > > > >
> > > > > On Sun, Sep 03, 2023 at 12:06:13PM -0600, Simon Glass wrote:
> > > > > > Hi Tom,
> > > > > >
> > > > > > On Sun, 3 Sept 2023 at 10:42, Tom Rini <trini@konsulko.com> wrote:
> > > > > > >
> > > > > > > On Thu, Aug 31, 2023 at 06:15:19PM -0600, Simon Glass wrote:
> > > > > > > > Hi Tom,
> > > > > > > >
> > > > > > > > On Wed, 23 Aug 2023 at 09:14, Tom Rini <trini@konsulko.com> wrote:
> > > > > > > > >
> > > > > > > > > On Wed, Aug 23, 2023 at 07:42:03AM -0600, Simon Glass wrote:
> > > > > > > > >
> > > > > > > > > > When lmb runs out of space in its internal tables, it gives
> > > > errors on
> > > > > > > > > > every fs load operation. This is horribly confusing, as the
> > > > poor user
> > > > > > > > > > tries different memory regions one at a time.
> > > > > > > > > >
> > > > > > > > > > Use the updated API to check the error code and print a helpful
> > > > message.
> > > > > > > > > > Also, allow the operation to proceed.
> > > > > > > > > >
> > > > > > > > > > Update the tests accordingly.
> > > > > > > > > >
> > > > > > > > > > Signed-off-by: Simon Glass <sjg@chromium.org>
> > > > > > > > > [snip]
> > > > > > > > > > +     if (ret == -E2BIG) {
> > > > > > > > > > +             log_warning("Reservation tables exhausted: see
> > > > CONFIG_LMB_USE_MAX_REGIONS\n");
> > > > > > > > > > +             return 0;
> > > > > > > > > > +     }
> > > > > > > > >
> > > > > > > > > This isn't the right option.  Everyone has
> > > > CONFIG_LMB_USE_MAX_REGIONS
> > > > > > > > > set.  You would want to increase CONFIG_LMB_MAX_REGIONS.
> > > > > > > > >
> > > > > > > > > But it sounds like what you've found and fixed is an underlying
> > > > problem
> > > > > > > > > as to why 16 regions isn't enough in some common cases now?  So
> > > > we could
> > > > > > > >
> > > > > > > > I don't think I have fixed anything. But I'll send v2 and perhaps it
> > > > > > > > will be clearer what is going on here.
> > > > > > > >
> > > > > > > > > possibly avoid the string size growth here and have a comment
> > > > that also
> > > > > > > > > matches up with the help under LMB_MAX_REGIONS?
> > > > > > > >
> > > > > > > > I don't know, sorry. The size of struct(lmb) on 64-bit sandbox is
> > > > > > > > about 400 bytes. There seems to be a lot of code to save not much
> > > > > > > > memory.
> > > > > > >
> > > > > > > What do you mean here?  The alternative is not unlimited ranges but
> > > > > > > instead to define the limit of memory regions and limit of reserved
> > > > > > > ranges.
> > > > > >
> > > > > > A better alternative would be not to limit the number of regions, IMO,
> > > > > > i.e. have an array of regions that can grow as needed.
> > > > >
> > > > > That's not something that we have in the code today, however.
> > > >
> > > > No, I do have an arraylist thing that I plan to upstream, which could
> > > > handle that.
> > > >
> > > > But for this series, what do you think of the memregion idea? I am still
> > > > unsure of the saming we should use - see Heinrich's comments too.
> > >
> > > My biggest worry here is that we're papering over a real issue, and
> > > should either dig at that and see what's going on (should something be
> > > coalescing adjacent allocations? Were many platforms just right at the
> > > previous limit?) or just bump the default from 16 to "64 if EFI_LOADER"
> > > and then see if anything else really needs tweaking / cleaning up in the
> > > code itself.  I know Heinrich has previously said the LMB system could
> > > be better (or something to that effect, I'm going from memory, sorry if
> > > I'm mis-stating things) and I don't object to replacing what we have
> > > with something more robust/smarter/etc.
> >
> > I am not sure...my series was designed to rename the code to reduce
> > confusion, and print a useful message when we run out of regions. It
> > does not paper over the problem, but actually makes it more visible.
>
> Well, "papering over" maybe wasn't the best choice of words on my part.
> But since the series of events was something like:
> - We nee to use LMB to cover my U-Boot regions to address a handful of
>   CVEs over arbitrarily overwriting U-Boot at run-time.
>   - AFAICT no platforms suddenly ran out of LMB reservation space, but
>     maybe I'm wrong?
> - Someone noted that the EFI subsystem was exposing the same kind of
>   issue.
> - Heinrich adds logic for EFI_LOADER (iirc) to also add allocations
>   there to LMB
> - Assorted platforms start changing the max allocation to 64 to fix the
>   problems that get reported sometimes by booting.
> - Heinrich notes that our memory reservation system (LMB) could be
>   better designed than it is today.
>   - And, iirc, EFI_LOADER or similar has something maybe we can
>     leverage?
>
> Which brings me to what I was trying to say.  I'm not sure it's worth
> cleaning up the code a little, or refactoring/renaming things within it
> without both:
> - Understanding why EFI_LOADER being enabled causes us to run out of
>   allocations and so if the answer is "increase the default" OR "fix
>   some underlying issue such as coalescing being too strict or broken".
> - Understanding if there's a better memory reservation system we can use
>   instead.

Perhaps Heinrich has some thoughts on that and/or the memregion
question. EFI loves memory regions so perhaps it needs more?

But it should report a useful error, not the silly one it shows today.

Regards,
Simon
diff mbox series

Patch

diff --git a/fs/fs.c b/fs/fs.c
index 2b815b1db0fe..1a84cb410bf9 100644
--- a/fs/fs.c
+++ b/fs/fs.c
@@ -569,8 +569,13 @@  static int fs_read_lmb_check(const char *filename, ulong addr, loff_t offset,
 	lmb_init_and_reserve(&lmb, gd->bd, (void *)gd->fdt_blob);
 	lmb_dump_all(&lmb);
 
-	if (lmb_alloc_addr(&lmb, addr, read_len) == addr)
+	ret = lmb_alloc_addr(&lmb, addr, read_len, NULL);
+	if (!ret)
 		return 0;
+	if (ret == -E2BIG) {
+		log_warning("Reservation tables exhausted: see CONFIG_LMB_USE_MAX_REGIONS\n");
+		return 0;
+	}
 
 	log_err("** Reading file would overwrite reserved memory **\n");
 	return -ENOSPC;
diff --git a/include/lmb.h b/include/lmb.h
index 79a3a12155b4..2060280aff54 100644
--- a/include/lmb.h
+++ b/include/lmb.h
@@ -114,7 +114,24 @@  phys_addr_t lmb_alloc_base(struct lmb *lmb, phys_size_t size, ulong align,
 			   phys_addr_t max_addr);
 phys_addr_t __lmb_alloc_base(struct lmb *lmb, phys_size_t size, ulong align,
 			     phys_addr_t max_addr);
-phys_addr_t lmb_alloc_addr(struct lmb *lmb, phys_addr_t base, phys_size_t size);
+
+/**
+ * lmb_alloc_addr() - Allocate memory within a region
+ *
+ * Try to allocate a specific address range: must be in defined memory but not
+ * reserved
+ *
+ * @lmb:	the logical memory block struct
+ * @base:	base address of the memory region
+ * @size:	size of the memory region
+ * @addrp:	if non-NULL, returns the allocated address, on success
+ * Return:	0 if OK, -EPERM if the memory is already allocated, -E2BIG if
+ * there is not enough room in the reservation tables, so
+ * CONFIG_LMB_USE_MAX_REGIONS should be increased
+ */
+int lmb_alloc_addr(struct lmb *lmb, phys_addr_t base, phys_size_t size,
+		   phys_addr_t *addrp);
+
 phys_size_t lmb_get_free_size(struct lmb *lmb, phys_addr_t addr);
 
 /**
diff --git a/lib/lmb.c b/lib/lmb.c
index 340681961826..6bb8fa3829d3 100644
--- a/lib/lmb.c
+++ b/lib/lmb.c
@@ -253,7 +253,7 @@  void lmb_init_and_reserve_range(struct lmb *lmb, phys_addr_t base,
  * @size:	size of the memory region to add
  * @flags:	flags for this new memory region
  * Returns: 0 if OK, -EBUSY if an existing enveloping region has different
- * flags, -EPERM if there is an existing non-adjacent region, -ENOSPC if there
+ * flags, -EPERM if there is an existing non-adjacent region, -E2BIG if there
  * is no more room in the list of regions, ekse region number that was coalesced
  * with this one
  **/
@@ -319,7 +319,7 @@  static int lmb_add_region_flags(struct lmb_region *rgn, phys_addr_t base,
 	if (coalesced)
 		return coalesced;
 	if (rgn->cnt >= rgn->max)
-		return -ENOSPC;
+		return -E2BIG;
 
 	/* Couldn't coalesce the LMB, so add it to the sorted table. */
 	for (i = rgn->cnt-1; i >= 0; i--) {
@@ -511,11 +511,8 @@  phys_addr_t __lmb_alloc_base(struct lmb *lmb, phys_size_t size, ulong align,
 	return 0;
 }
 
-/*
- * Try to allocate a specific address range: must be in defined memory but not
- * reserved
- */
-phys_addr_t lmb_alloc_addr(struct lmb *lmb, phys_addr_t base, phys_size_t size)
+int lmb_alloc_addr(struct lmb *lmb, phys_addr_t base, phys_size_t size,
+		   phys_addr_t *addrp)
 {
 	long rgn;
 
@@ -529,9 +526,14 @@  phys_addr_t lmb_alloc_addr(struct lmb *lmb, phys_addr_t base, phys_size_t size)
 		if (lmb_addrs_overlap(lmb->memory.region[rgn].base,
 				      lmb->memory.region[rgn].size,
 				      base + size - 1, 1)) {
+			int ret;
+
 			/* ok, reserve the memory */
-			if (lmb_reserve(lmb, base, size) >= 0)
-				return base;
+			ret = lmb_reserve(lmb, base, size);
+			if (ret < 0)
+				return ret;
+			if (addrp)
+				*addrp = base;
 		}
 	}
 
diff --git a/test/lib/lmb.c b/test/lib/lmb.c
index 162887503588..9ab5fe593ebd 100644
--- a/test/lib/lmb.c
+++ b/test/lib/lmb.c
@@ -497,22 +497,22 @@  static int test_alloc_addr(struct unit_test_state *uts, const phys_addr_t ram)
 		   alloc_addr_b, 0x10000, alloc_addr_c, 0x10000);
 
 	/* allocate blocks */
-	a = lmb_alloc_addr(&lmb, ram, alloc_addr_a - ram);
+	ut_assertok(lmb_alloc_addr(&lmb, ram, alloc_addr_a - ram, &a));
 	ut_asserteq(a, ram);
 	ASSERT_LMB(&lmb, ram, ram_size, 3, ram, 0x8010000,
 		   alloc_addr_b, 0x10000, alloc_addr_c, 0x10000);
-	b = lmb_alloc_addr(&lmb, alloc_addr_a + 0x10000,
-			   alloc_addr_b - alloc_addr_a - 0x10000);
+	ut_assertok(lmb_alloc_addr(&lmb, alloc_addr_a + 0x10000,
+				   alloc_addr_b - alloc_addr_a - 0x10000, &b));
 	ut_asserteq(b, alloc_addr_a + 0x10000);
 	ASSERT_LMB(&lmb, ram, ram_size, 2, ram, 0x10010000,
 		   alloc_addr_c, 0x10000, 0, 0);
-	c = lmb_alloc_addr(&lmb, alloc_addr_b + 0x10000,
-			   alloc_addr_c - alloc_addr_b - 0x10000);
+	ut_assertok(lmb_alloc_addr(&lmb, alloc_addr_b + 0x10000,
+				   alloc_addr_c - alloc_addr_b - 0x10000, &c));
 	ut_asserteq(c, alloc_addr_b + 0x10000);
 	ASSERT_LMB(&lmb, ram, ram_size, 1, ram, 0x18010000,
 		   0, 0, 0, 0);
-	d = lmb_alloc_addr(&lmb, alloc_addr_c + 0x10000,
-			   ram_end - alloc_addr_c - 0x10000);
+	ut_assertok(lmb_alloc_addr(&lmb, alloc_addr_c + 0x10000,
+				   ram_end - alloc_addr_c - 0x10000, &d));
 	ut_asserteq(d, alloc_addr_c + 0x10000);
 	ASSERT_LMB(&lmb, ram, ram_size, 1, ram, ram_size,
 		   0, 0, 0, 0);
@@ -528,7 +528,7 @@  static int test_alloc_addr(struct unit_test_state *uts, const phys_addr_t ram)
 
 	/* allocate at 3 points in free range */
 
-	d = lmb_alloc_addr(&lmb, ram_end - 4, 4);
+	ut_assertok(lmb_alloc_addr(&lmb, ram_end - 4, 4, &d));
 	ut_asserteq(d, ram_end - 4);
 	ASSERT_LMB(&lmb, ram, ram_size, 2, ram, 0x18010000,
 		   d, 4, 0, 0);
@@ -537,7 +537,7 @@  static int test_alloc_addr(struct unit_test_state *uts, const phys_addr_t ram)
 	ASSERT_LMB(&lmb, ram, ram_size, 1, ram, 0x18010000,
 		   0, 0, 0, 0);
 
-	d = lmb_alloc_addr(&lmb, ram_end - 128, 4);
+	ut_assertok(lmb_alloc_addr(&lmb, ram_end - 128, 4, &d));
 	ut_asserteq(d, ram_end - 128);
 	ASSERT_LMB(&lmb, ram, ram_size, 2, ram, 0x18010000,
 		   d, 4, 0, 0);
@@ -546,7 +546,7 @@  static int test_alloc_addr(struct unit_test_state *uts, const phys_addr_t ram)
 	ASSERT_LMB(&lmb, ram, ram_size, 1, ram, 0x18010000,
 		   0, 0, 0, 0);
 
-	d = lmb_alloc_addr(&lmb, alloc_addr_c + 0x10000, 4);
+	ut_assertok(lmb_alloc_addr(&lmb, alloc_addr_c + 0x10000, 4, &d));
 	ut_asserteq(d, alloc_addr_c + 0x10000);
 	ASSERT_LMB(&lmb, ram, ram_size, 1, ram, 0x18010004,
 		   0, 0, 0, 0);
@@ -560,19 +560,19 @@  static int test_alloc_addr(struct unit_test_state *uts, const phys_addr_t ram)
 	ut_asserteq(ret, 0);
 	ASSERT_LMB(&lmb, ram, ram_size, 1, ram + 0x8000000, 0x10010000,
 		   0, 0, 0, 0);
-	d = lmb_alloc_addr(&lmb, ram, 4);
+	ut_assertok(lmb_alloc_addr(&lmb, ram, 4, &d));
 	ut_asserteq(d, ram);
 	ASSERT_LMB(&lmb, ram, ram_size, 2, d, 4,
 		   ram + 0x8000000, 0x10010000, 0, 0);
 
 	/* check that allocating outside memory fails */
 	if (ram_end != 0) {
-		ret = lmb_alloc_addr(&lmb, ram_end, 1);
-		ut_asserteq(ret, 0);
+		ut_assertok(lmb_alloc_addr(&lmb, ram_end, 1, &a));
+		ut_asserteq(0x40000000, a);
 	}
 	if (ram != 0) {
-		ret = lmb_alloc_addr(&lmb, ram - 1, 1);
-		ut_asserteq(ret, 0);
+		ut_assertok(lmb_alloc_addr(&lmb, ram - 1, 1, &a));
+		ut_asserteq(ram, a);
 	}
 
 	return 0;
@@ -588,7 +588,7 @@  static int lib_test_lmb_alloc_addr(struct unit_test_state *uts)
 		return ret;
 
 	/* simulate 512 MiB RAM beginning at 1.5GiB */
-	return test_alloc_addr(uts, 0xE0000000);
+	return test_alloc_addr(uts, 0xe0000000);
 }
 
 DM_TEST(lib_test_lmb_alloc_addr, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
@@ -699,8 +699,7 @@  static int lib_test_lmb_max_regions(struct unit_test_state *uts)
 
 	/*  error for the (CONFIG_LMB_MAX_REGIONS + 1) memory regions */
 	offset = ram + 2 * (CONFIG_LMB_MAX_REGIONS + 1) * ram_size;
-	ret = lmb_add(&lmb, offset, ram_size);
-	ut_asserteq(ret, -1);
+	ut_asserteq(-E2BIG, lmb_add(&lmb, offset, ram_size));
 
 	ut_asserteq(lmb.memory.cnt, CONFIG_LMB_MAX_REGIONS);
 	ut_asserteq(lmb.reserved.cnt, 0);
@@ -717,8 +716,7 @@  static int lib_test_lmb_max_regions(struct unit_test_state *uts)
 
 	/*  error for the 9th reserved blocks */
 	offset = ram + 2 * (CONFIG_LMB_MAX_REGIONS + 1) * blk_size;
-	ret = lmb_reserve(&lmb, offset, blk_size);
-	ut_asserteq(ret, -1);
+	ut_asserteq(-E2BIG, lmb_reserve(&lmb, offset, blk_size));
 
 	ut_asserteq(lmb.memory.cnt, CONFIG_LMB_MAX_REGIONS);
 	ut_asserteq(lmb.reserved.cnt, CONFIG_LMB_MAX_REGIONS);
@@ -762,8 +760,8 @@  static int lib_test_lmb_flags(struct unit_test_state *uts)
 		   0, 0, 0, 0);
 
 	/* reserve again, new flag */
-	ret = lmb_reserve_flags(&lmb, 0x40010000, 0x10000, LMB_NONE);
-	ut_asserteq(ret, -1);
+	ut_asserteq(-EBUSY,
+		    lmb_reserve_flags(&lmb, 0x40010000, 0x10000, LMB_NONE));
 	ASSERT_LMB(&lmb, ram, ram_size, 1, 0x40010000, 0x10000,
 		   0, 0, 0, 0);