From: Dave Hansen <dave@linux.vnet.ibm.com>
To: Mike Waychison <mikew@google.com>
Cc: akpm@linux-foundation.org, menage@google.com,
containers@lists.linux-foundation.org, bblum@google.com,
linux-kernel@vger.kernel.org
Subject: Re: [RFC][PATCH] flexible array implementation
Date: Tue, 21 Jul 2009 10:22:30 -0700 [thread overview]
Message-ID: <1248196950.13249.5515.camel@nimitz> (raw)
In-Reply-To: <4A65F13D.6060506@google.com>
On Tue, 2009-07-21 at 12:47 -0400, Mike Waychison wrote:
> > +/*
> > + * This is meant to replace cases where an array-like
> > + * structure has gotten to big to fit into kmalloc()
>
> s/to/too/g
Gah, thanks.
> > + * and the developer is getting tempted to use
> > + * vmalloc().
> > + */
> > +
> > +struct flex_array {
> > + union {
> > + struct {
> > + int nr_elements;
> > + int element_size;
> > + struct flex_array_part *parts[0];
> > + };
> > + /*
> > + * This little trick makes sure that
> > + * sizeof(flex_array) == PAGE_SIZE
> > + */
> > + char padding[FLEX_ARRAY_BASE_SIZE];
> > + };
> > +};
> > +
> > +struct flex_array *alloc_flex_array(int element_size, int total, gfp_t flags);
> > +void free_flex_array(struct flex_array *fa);
> > +int flex_array_put(struct flex_array *fa, void *src, gfp_t flags);
> > +void *flex_array_get(struct flex_array *fa, int element_nr);
>
> Would a single routine that acted like an lvalue be a bit clearer? Here
> it looks like the interface is a push to write, but random access to
> read. Something like:
>
> void **__flex_array_idx(struct flex_rray *fa, int element_nr);
> #define flex_array_idx(fa, element_nr) (*__flex_array_idx(fa, element_nr))
>
> may be a bit easier to read so users of the interface could just do:
>
> flex_array_idx(fa, n) = pointer;
> pointer = flex_array_idx(fa, n);
>
> I guess this would require that flex_array only store actual pointers
> though, instead of objects. Hmm.
Yeah, possibly.
I was hoping I'd get some suggestions for places in the kernel that
could use this. I'll see if another interface looks better once I get
some users. :)
> Is there any reason you defer allocation of parts to flex_array_put()
> given that alloc_flex_array() is told the total number of elements?
Yeah, I guess it's just in the hope that it won't all get filled. I
think I also started with it not being passed the total size. But, I
figured later on that it was better to fail as early as possible rather
than screwing the user later on when we fill up.
> > +struct flex_array_part {
> > + char elements[FLEX_ARRAY_PART_SIZE];
> > +};
> > +
> > +static inline int __elements_per_part(int element_size)
> > +{
> > + return FLEX_ARRAY_PART_SIZE / element_size;
>
> Micro-optimization, but perhaps the general case could use a bit shift
> stored inside the flex_array? That way we could avoid excessive divide
> operations.
Possibly, but that of course precludes having objects with
non-power-of-two sizes being packed very well. It's certainly worth
thinking about.
> > +void *flex_array_get(struct flex_array *fa, int element_nr)
> > +{
> > + int part_nr = fa_element_to_part_nr(fa, element_nr);
> > + struct flex_array_part *part;
> > + int offset;
> > +
> > + if (part_nr > __nr_part_ptrs())
>
> if (part_nr >= __nr_part_ptrs())
Yep. Good catch.
> > + return NULL;
>
> ERR_PTR(-EINVAL) ?
I guess this helps users differentiate bad arguments from memory
allocation failures. But, I'd rather not make users check ERR_PTR()
just because I want to keep it simple.
> Would it make sense to WARN here? A more precise test could be to
> compare element_nr vs fa->nr_elements?
My immediate goal here was just to avoid oopses and overflows. You're
right that fa->nr_elements would be more precise. But, I guess if you
overflow an array you get an oops, so why should this be any different?
A WARN() is potentially noisy, but way less noisy than an oops.
Thanks for the feedback!
-- Dave
next prev parent reply other threads:[~2009-07-21 17:22 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-07-21 16:03 [RFC][PATCH] flexible array implementation Dave Hansen
2009-07-21 16:47 ` Mike Waychison
2009-07-21 17:22 ` Dave Hansen [this message]
2009-07-21 16:57 ` Denys Vlasenko
2009-07-21 17:25 ` Dave Hansen
2009-07-21 20:18 ` Andrew Morton
2009-07-21 21:56 ` Dave Hansen
2009-07-21 22:33 ` Andrew Morton
2009-07-21 20:28 ` Paul Menage
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=1248196950.13249.5515.camel@nimitz \
--to=dave@linux.vnet.ibm.com \
--cc=akpm@linux-foundation.org \
--cc=bblum@google.com \
--cc=containers@lists.linux-foundation.org \
--cc=linux-kernel@vger.kernel.org \
--cc=menage@google.com \
--cc=mikew@google.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