From: Al Viro <viro@zeniv.linux.org.uk>
To: "Fabio M. De Francesco" <fmdefrancesco@gmail.com>
Cc: Evgeniy Dushistov <dushistov@mail.ru>,
Ira Weiny <ira.weiny@intel.com>,
linux-kernel@vger.kernel.org, Jeff Moyer <jmoyer@redhat.com>
Subject: Re: [PATCH v2 2/3] fs/ufs: Change the signature of ufs_get_page()
Date: Tue, 13 Dec 2022 21:02:40 +0000 [thread overview]
Message-ID: <Y5jocC08THah/nHz@ZenIV> (raw)
In-Reply-To: <3174926.0WQXIW03uk@suse>
On Tue, Dec 13, 2022 at 08:08:22PM +0100, Fabio M. De Francesco wrote:
> But I can't yet understand why that pointer was returned unconditionally in
> the code which I'm changing with this patch (i.e., regardless of any potential
> errors from read_mapping_page()) :-/
Because on error from read_mapping_page() you get page or ERR_PTR(-E...),
which is what you want the sucker to return on error.
Here you want to return page_address(page) on success or ERR_PTR(-E...) on
error.
For original calling conventions return page; worked both on success and
on error. With the new ones it's no longer true - giving page_address() an
error value (address in range (unsigned long)(-4095) to (unsigned long)(-1))
is *not* going to return the same error value.
It's even more obvious with your third patch - on read_mapping_page() failure
you want to return the same bit pattern it gave you, on its success you want
to pass the pointer it gave you to kmap_local_page() and return the address
you get from kmap_local_page(), right? Check what your patch ends up doing -
you store result of kmap_local_page() in kaddr, then return it. Including
the case when you have *not* called kmap_local_page() at all...
Again, warnings are occasionally useful...
Brain dump on ERR_PTR() and related things: kernel makes sure that the top 4K
of possible addresses are never used for objects of any type (that's
0xfffff000--0xffffffff on 32bit, 0xfffffffffffff000--0xffffffffffffffff
on 64bit). That gives us 4095 values that are never going to clash with
any valid pointer values. One way of thinking about those is "split NULL" -
instead of one value that is guaranteed to be distinct from address of
any object we have a small bunch of those and we can use the _choice_ of
such value to carry information. Similar to how NaN are used for real
numbers, actually.
If function returns a pointer on success and errno value on failure,
it can be declared to return a pointer type, using ERR_PTR(-22) to represent
"error #22", etc. These values can be easily recognized; IS_ERR(p) is
true for those and only for those. PTR_ERR() converts those to numbers -
PTR_ERR(ERR_PTR(-22)) is -22, etc.
On non-error values PTR_ERR() yields garbage; it won't break (or do any
calculations, actually - just cast to signed long), but the value is
going to be useless for anything.
IS_ERR() is annotated so that compiler knows that it's unlikely to be
true; i.e. if (IS_ERR(...)) {do something} won't have the body cluttering
the hot path.
You can compare them for (in)equality just fine -
if (p == ERR_PTR(-ENOMEM))
is fine; no need to bother with the things like
if (PTR_ERR(p) == -ENOMEM)
You obviously can't dereference them and (slightly less obviously) can't do
ordered comparisons. You definitely can't do pointer arithmetics on those.
These values are used with all pointer types; something like
struct foo *f()
{
struct foo *p;
char *s;
p = kmalloc(sizeof(struct foo), GFP_KERNEL);
if (!p)
return ERR_PTR(-ENOMEM);
s = bar();
// if bar() has failed, return the error it gave you
if (IS_ERR(s)) {
kfree(p);
return (void *)s; // UNIDIOMATIC
}
....
return p;
}
is valid, but it's better spelled as ERR_CAST(s) instead of (void *)s.
Note that these values can also be used as arguments - it's less common
that use as return values, but there are situations when it makes sense.
Not the case here, though...
See include/linux/err.h; one warning - use of IS_ERR_OR_NULL() is very
often a mistake. Mixing NULL and ERR_PTR() in calling conventions is
a good way to end up with massive confusion down the road; sometimes
it's warranted, but such cases are rare and generally you want to ask
yourself "do I really want to go there?"
> P.S.: While at this patch I'd like to gently ping you about another conversion
> that I sent (and resent) months ago:
>
> [RESEND PATCH] fs/aio: Replace kmap{,_atomic}() with kmap_local_page() at:
> https://lore.kernel.org/lkml/20221016150656.5803-1-fmdefrancesco@gmail.com/
>
> This patch to fs/aio.c has already received two "Reviewed-by" tags: the first
> from Ira Weiny and the second from Jeff Moyer (you won't see the second there,
> because I forgot to forward it when I sent again :-( ).
>
> The tag from Jeff is in the following message (from another [RESEND PATCH]
> thread):
> https://lore.kernel.org/lkml/x49h6zzvn1a.fsf@segfault.boston.devel.redhat.com/
>
> In that same thread, I explained better I meant in the last sentence of the
> commit message, because Jeff commented that it is ambiguous (I'm adding him in
> the Cc list of recipients).
>
> The original patch, submitted on Thu, 7 Jul 2022 01:33:28 +0200 is at:
> https://lore.kernel.org/lkml/20220706233328.18582-1-fmdefrancesco@gmail.com/
>
> I'd appreciate very much if you can spend some time on that patch too :)
Will check...
next prev parent reply other threads:[~2022-12-13 21:02 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <bpf@vger.kernel.org,linux-fsdevel@vger.kernel.org>
2022-12-12 23:19 ` [PATCH v2 0/3] fs/ufs: replace kmap() with kmap_local_page Fabio M. De Francesco
2022-12-12 23:19 ` [PATCH v2 1/3] fs/ufs: Use the offset_in_page() helper Fabio M. De Francesco
2022-12-12 23:19 ` [PATCH v2 2/3] fs/ufs: Change the signature of ufs_get_page() Fabio M. De Francesco
2022-12-13 7:10 ` Al Viro
2022-12-13 19:08 ` Fabio M. De Francesco
2022-12-13 21:02 ` Al Viro [this message]
2022-12-12 23:19 ` [PATCH v2 3/3] fs/ufs: Replace kmap() with kmap_local_page() Fabio M. De Francesco
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=Y5jocC08THah/nHz@ZenIV \
--to=viro@zeniv.linux.org.uk \
--cc=dushistov@mail.ru \
--cc=fmdefrancesco@gmail.com \
--cc=ira.weiny@intel.com \
--cc=jmoyer@redhat.com \
--cc=linux-kernel@vger.kernel.org \
/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.