10 Aug, 2010

1 commit

  • Getting and putting arrays of pointers with flex arrays is a PITA. You
    have to remember to pass &ptr to the _put and you have to do weird and
    wacky casting to get the ptr back from the _get. Add two functions
    flex_array_get_ptr() and flex_array_put_ptr() to handle all of the magic.

    [akpm@linux-foundation.org: simplification suggested by Joe]
    Signed-off-by: Eric Paris
    Cc: David Rientjes
    Cc: Dave Hansen
    Cc: Joe Perches
    Cc: James Morris
    Cc: Joe Perches
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Eric Paris
     

25 Apr, 2010

1 commit


22 Sep, 2009

5 commits

  • Add kerneldoc annotations for function formals of type struct flex_array
    and gfp_t which are currently lacking.

    Signed-off-by: David Rientjes
    Cc: Dave Hansen
    Cc: Randy Dunlap
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    David Rientjes
     
  • FLEX_ARRAY_INIT(element_size, total_nr_elements) cannot determine if
    either parameter is valid, so flex arrays which are statically allocated
    with this interface can easily become corrupted or reference beyond its
    allocated memory.

    This removes FLEX_ARRAY_INIT() as a struct flex_array initializer since no
    initializer may perform the required checking. Instead, the array is now
    defined with a new interface:

    DEFINE_FLEX_ARRAY(name, element_size, total_nr_elements)

    This may be prefixed with `static' for file scope.

    This interface includes compile-time checking of the parameters to ensure
    they are valid. Since the validity of both element_size and
    total_nr_elements depend on FLEX_ARRAY_BASE_SIZE and FLEX_ARRAY_PART_SIZE,
    the kernel build will fail if either of these predefined values changes
    such that the array parameters are no longer valid.

    Since BUILD_BUG_ON() requires compile time constants, several of the
    static inline functions that were once local to lib/flex_array.c had to be
    moved to include/linux/flex_array.h.

    Signed-off-by: David Rientjes
    Acked-by: Dave Hansen
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    David Rientjes
     
  • Add a new function to the flex_array API:

    int flex_array_shrink(struct flex_array *fa)

    This function will free all unused second-level pages. Since elements are
    now poisoned if they are not allocated with __GFP_ZERO, it's possible to
    identify parts that consist solely of unused elements.

    flex_array_shrink() returns the number of pages freed.

    Signed-off-by: David Rientjes
    Cc: Dave Hansen
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    David Rientjes
     
  • Newly initialized flex_array's and/or flex_array_part's are now poisoned
    with a new poison value, FLEX_ARRAY_FREE. It's value is similar to
    POISON_FREE used in the various slab allocators, but is different to
    distinguish between flex array's poisoned kmem and slab allocator poisoned
    kmem.

    This will allow us to identify flex_array_part's that only contain free
    elements (and free them with an addition to the flex_array API). This
    could also be extended in the future to identify `get' uses on elements
    that have not been `put'.

    If __GFP_ZERO is passed for a part's gfp mask, the poisoning is avoided.
    These elements are considered to be in-use since they have been
    initialized.

    Signed-off-by: David Rientjes
    Cc: Dave Hansen
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    David Rientjes
     
  • Add a new function to the flex_array API:

    int flex_array_clear(struct flex_array *fa,
    unsigned int element_nr)

    This function will zero the element at element_nr in the flex_array.

    Although this is equivalent to using flex_array_put() and passing a
    pointer to zero'd memory, flex_array_clear() does not require such a
    pointer to memory that would most likely need to be allocated on the
    caller's stack which could be significantly large depending on
    element_size.

    Signed-off-by: David Rientjes
    Cc: Dave Hansen
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    David Rientjes
     

27 Aug, 2009

3 commits

  • It's problematic to allow signed element_nr's or total's to be passed as
    part of the flex array API.

    flex_array_alloc() allows total_nr_elements to be set to a negative
    quantity, which is obviously erroneous.

    flex_array_get() and flex_array_put() allows negative array indices in
    dereferencing an array part, which could address memory mapped before
    struct flex_array.

    The fix is to convert all existing element_nr formals to be qualified as
    unsigned. Existing checks to compare it to total_nr_elements or the max
    array size based on element_size need not be changed.

    Signed-off-by: David Rientjes
    Cc: Dave Hansen
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    David Rientjes
     
  • flex_array_free_parts() does not take `src' or `element_nr' formals, so
    remove their respective comments.

    Signed-off-by: David Rientjes
    Acked-by: Dave Hansen
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    David Rientjes
     
  • If all array elements fit into the base structure and data is copied using
    flex_array_put() starting at a non-zero index, flex_array_get() will fail
    to return the data.

    This fixes the bug by only checking for NULL parts when all elements do
    not fit in the base structure when flex_array_get() is used. Otherwise,
    fa_element_to_part_nr() will always be 0 since there are no parts
    structures needed and such element may never have been put. Thus, it will
    remain NULL due to the kzalloc() of the base.

    Additionally, flex_array_put() now only checks for a NULL part when all
    elements do not fit in the base structure. This is otherwise unnecessary
    since the base structure is guaranteed to exist (or we would have already
    hit a NULL pointer).

    Signed-off-by: David Rientjes
    Acked-by: Dave Hansen
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    David Rientjes
     

05 Aug, 2009

1 commit


30 Jul, 2009

1 commit

  • Once a structure goes over PAGE_SIZE*2, we see occasional allocation
    failures. Some people have chosen to switch over to things like vmalloc()
    that will let them keep array-like access to such a large structures.
    But, vmalloc() has plenty of downsides.

    Here's an alternative. I think it's what Andrew was suggesting here:

    http://lkml.org/lkml/2009/7/2/518

    I call it a flexible array. It does all of its work in PAGE_SIZE bits, so
    never does an order>0 allocation. The base level has
    PAGE_SIZE-2*sizeof(int) bytes of storage for pointers to the second level.
    So, with a 32-bit arch, you get about 4MB (4183112 bytes) of total
    storage when the objects pack nicely into a page. It is half that on
    64-bit because the pointers are twice the size. There's a table detailing
    this in the code.

    There are kerneldocs for the functions, but here's an
    overview:

    flex_array_alloc() - dynamically allocate a base structure
    flex_array_free() - free the array and all of the
    second-level pages
    flex_array_free_parts() - free the second-level pages, but
    not the base (for static bases)
    flex_array_put() - copy into the array at the given index
    flex_array_get() - copy out of the array at the given index
    flex_array_prealloc() - preallocate the second-level pages
    between the given indexes to
    guarantee no allocs will occur at
    put() time.

    We could also potentially just pass the "element_size" into each of the
    API functions instead of storing it internally. That would get us one
    more base pointer on 32-bit.

    I've been testing this by running it in userspace. The header and patch
    that I've been using are here, as well as the little script I'm using to
    generate the size table which goes in the kerneldocs.

    http://sr71.net/~dave/linux/flexarray/

    [akpm@linux-foundation.org: coding-style fixes]
    Signed-off-by: Dave Hansen
    Reviewed-by: KAMEZAWA Hiroyuki
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Dave Hansen