From: Danilo Krummrich <dakr@kernel.org>
To: Michal Hocko <mhocko@suse.com>
Cc: cl@linux.com, penberg@kernel.org, rientjes@google.com,
iamjoonsoo.kim@lge.com, akpm@linux-foundation.org,
vbabka@suse.cz, roman.gushchin@linux.dev, 42.hyeyoo@gmail.com,
urezki@gmail.com, hch@infradead.org, kees@kernel.org,
ojeda@kernel.org, wedsonaf@gmail.com, mpe@ellerman.id.au,
chandan.babu@oracle.com, christian.koenig@amd.com,
maz@kernel.org, oliver.upton@linux.dev,
linux-kernel@vger.kernel.org, linux-mm@kvack.org,
rust-for-linux@vger.kernel.org
Subject: Re: [PATCH v2 2/2] mm: kvmalloc: align kvrealloc() with krealloc()
Date: Tue, 23 Jul 2024 12:42:17 +0200 [thread overview]
Message-ID: <Zp-JCWCPbDLkzRVw@pollux> (raw)
In-Reply-To: <Zp9gtelmvzN5tfpS@tiehlicka>
On Tue, Jul 23, 2024 at 09:50:13AM +0200, Michal Hocko wrote:
> On Mon 22-07-24 18:29:24, Danilo Krummrich wrote:
> > Besides the obvious (and desired) difference between krealloc() and
> > kvrealloc(), there is some inconsistency in their function signatures
> > and behavior:
> >
> > - krealloc() frees the memory when the requested size is zero, whereas
> > kvrealloc() simply returns a pointer to the existing allocation.
> >
> > - krealloc() behaves like kmalloc() if a NULL pointer is passed, whereas
> > kvrealloc() does not accept a NULL pointer at all and, if passed,
> > would fault instead.
> >
> > - krealloc() is self-contained, whereas kvrealloc() relies on the caller
> > to provide the size of the previous allocation.
> >
> > Inconsistent behavior throughout allocation APIs is error prone, hence make
> > kvrealloc() behave like krealloc(), which seems superior in all mentioned
> > aspects.
>
> I completely agree with this. Fortunately the number of existing callers
> is small and none of them really seem to depend on the current behavior
> in that aspect.
>
> > Besides that, implementing kvrealloc() by making use of krealloc() and
> > vrealloc() provides oppertunities to grow (and shrink) allocations more
> > efficiently. For instance, vrealloc() can be optimized to allocate and
> > map additional pages to grow the allocation or unmap and free unused
> > pages to shrink the allocation.
>
> This seems like a change that is independent on the above and should be
> a patch on its own.
The optimizations you mean? Yes, I intend to do this in a separate series. For
now, I put TODOs in vrealloc.
>
> [...]
>
> > diff --git a/mm/util.c b/mm/util.c
> > index bc488f0121a7..0ff5898cc6de 100644
> > --- a/mm/util.c
> > +++ b/mm/util.c
> > @@ -608,6 +608,28 @@ unsigned long vm_mmap(struct file *file, unsigned long addr,
> > }
> > EXPORT_SYMBOL(vm_mmap);
> >
> > +static gfp_t kmalloc_gfp_adjust(gfp_t flags, size_t size)
>
> This seems like a generally useful helper which it is not. I would call
> it something like __kvmalloc_gfp_adjust or something similar so that it is
> clear that this is just a helper to adjust gfp flag for slab allocator
> path
Christoph proposed this name, I think he wanted to encode the target of the
flags, whereas you want to encode where the function is intended to be called
from.
When I originally named this thing, I had the same conflict - encoding both
turns out clumsy - and came up with to_kmalloc_flags().
Personally, I'd be fine with __kvmalloc_gfp_adjust() too.
>
> [...]
> > -void *kvrealloc_noprof(const void *p, size_t oldsize, size_t newsize, gfp_t flags)
> > +/**
> > + * kvrealloc - reallocate memory; contents remain unchanged
> > + * @p: object to reallocate memory for
> > + * @size: the size to reallocate
> > + * @flags: the flags for the page level allocator
> > + *
> > + * The contents of the object pointed to are preserved up to the lesser of the
> > + * new and old size (__GFP_ZERO flag is effectively ignored).
> > + *
> > + * If @p is %NULL, kvrealloc() behaves exactly like kvmalloc(). If @size is 0
> > + * and @p is not a %NULL pointer, the object pointed to is freed.
> > + *
> > + * Return: pointer to the allocated memory or %NULL in case of error
> > + */
> > +void *kvrealloc_noprof(const void *p, size_t size, gfp_t flags)
> > {
> > - void *newp;
> > + void *n;
> > +
>
> if (!size && p) {
> kvfree(p);
> return NULL;
> }
>
> would make this code flow slightly easier to read because the freeing
> path would be shared for all compbinations IMO.
Personally, I like it without. For me the simplicity comes from directing things
to either krealloc() or vrealloc(). But I'd be open to change it however.
>
> > + if (is_vmalloc_addr(p))
> > + return vrealloc_noprof(p, size, flags);
> > +
> > + n = krealloc_noprof(p, size, kmalloc_gfp_adjust(flags, size));
> > + if (!n) {
> > + /* We failed to krealloc(), fall back to kvmalloc(). */
> > + n = kvmalloc_noprof(size, flags);
>
> Why don't you simply use vrealloc_noprof here?
We could do that, but we'd also need to do the same checks kvmalloc() does, i.e.
/*
* It doesn't really make sense to fallback to vmalloc for sub page
* requests
*/
if (ret || size <= PAGE_SIZE)
return ret;
/* non-sleeping allocations are not supported by vmalloc */
if (!gfpflags_allow_blocking(flags))
return NULL;
/* Don't even allow crazy sizes */
if (unlikely(size > INT_MAX)) {
WARN_ON_ONCE(!(flags & __GFP_NOWARN));
return NULL;
}
Does the kmalloc() retry through kvmalloc() hurt us enough to do that? This
should only ever happen when we switch from a kmalloc buffer to a vmalloc
buffer, which we only do once, we never switch back.
>
> > + if (!n)
> > + return NULL;
> > +
> > + if (p) {
> > + /* We already know that `p` is not a vmalloc address. */
> > + memcpy(n, p, ksize(p));
> > + kfree(p);
> > + }
> > + }
> >
> > - if (oldsize >= newsize)
> > - return (void *)p;
> > - newp = kvmalloc_noprof(newsize, flags);
> > - if (!newp)
> > - return NULL;
> > - memcpy(newp, p, oldsize);
> > - kvfree(p);
> > - return newp;
> > + return n;
> > }
> > EXPORT_SYMBOL(kvrealloc_noprof);
> >
> > --
> > 2.45.2
>
> --
> Michal Hocko
> SUSE Labs
>
next prev parent reply other threads:[~2024-07-23 10:42 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-07-22 16:29 [PATCH v2 0/2] Align kvrealloc() with krealloc() Danilo Krummrich
2024-07-22 16:29 ` [PATCH v2 1/2] mm: vmalloc: implement vrealloc() Danilo Krummrich
2024-07-26 14:37 ` Vlastimil Babka
2024-07-26 20:05 ` Danilo Krummrich
2024-07-29 19:08 ` Danilo Krummrich
2024-07-30 1:35 ` Danilo Krummrich
2024-07-30 12:15 ` Vlastimil Babka
2024-07-30 13:14 ` Danilo Krummrich
2024-07-30 13:58 ` Vlastimil Babka
2024-07-30 14:32 ` Danilo Krummrich
2024-09-02 1:36 ` Feng Tang
2024-09-02 7:04 ` Feng Tang
2024-09-02 8:56 ` Vlastimil Babka
2024-09-03 3:18 ` Feng Tang
2024-09-06 7:35 ` Feng Tang
2024-07-22 16:29 ` [PATCH v2 2/2] mm: kvmalloc: align kvrealloc() with krealloc() Danilo Krummrich
2024-07-23 1:43 ` Andrew Morton
2024-07-23 14:05 ` Danilo Krummrich
2024-07-23 7:50 ` Michal Hocko
2024-07-23 10:42 ` Danilo Krummrich [this message]
2024-07-23 10:55 ` Michal Hocko
2024-07-23 11:55 ` Danilo Krummrich
2024-07-23 12:12 ` Michal Hocko
2024-07-23 13:33 ` Danilo Krummrich
2024-07-23 18:53 ` Michal Hocko
2024-07-26 14:38 ` Vlastimil Babka
2024-07-23 18:54 ` [PATCH v2 0/2] Align " Michal Hocko
2024-07-23 18:56 ` Danilo Krummrich
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=Zp-JCWCPbDLkzRVw@pollux \
--to=dakr@kernel.org \
--cc=42.hyeyoo@gmail.com \
--cc=akpm@linux-foundation.org \
--cc=chandan.babu@oracle.com \
--cc=christian.koenig@amd.com \
--cc=cl@linux.com \
--cc=hch@infradead.org \
--cc=iamjoonsoo.kim@lge.com \
--cc=kees@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=maz@kernel.org \
--cc=mhocko@suse.com \
--cc=mpe@ellerman.id.au \
--cc=ojeda@kernel.org \
--cc=oliver.upton@linux.dev \
--cc=penberg@kernel.org \
--cc=rientjes@google.com \
--cc=roman.gushchin@linux.dev \
--cc=rust-for-linux@vger.kernel.org \
--cc=urezki@gmail.com \
--cc=vbabka@suse.cz \
--cc=wedsonaf@gmail.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.