1. 22 9月, 2009 4 次提交
    • D
      flex_array: introduce DEFINE_FLEX_ARRAY · 45b588d6
      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: NDavid Rientjes <rientjes@google.com>
      Acked-by: NDave Hansen <dave@linux.vnet.ibm.com>
      Signed-off-by: NAndrew Morton <akpm@linux-foundation.org>
      Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
      45b588d6
    • D
      flex_array: add flex_array_shrink function · 4af5a2f7
      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: NDavid Rientjes <rientjes@google.com>
      Cc: Dave Hansen <dave@linux.vnet.ibm.com>
      Signed-off-by: NAndrew Morton <akpm@linux-foundation.org>
      Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
      4af5a2f7
    • D
      flex_array: poison free elements · 19da3dd1
      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: NDavid Rientjes <rientjes@google.com>
      Cc: Dave Hansen <dave@linux.vnet.ibm.com>
      Signed-off-by: NAndrew Morton <akpm@linux-foundation.org>
      Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
      19da3dd1
    • D
      flex_array: add flex_array_clear function · e6de3988
      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: NDavid Rientjes <rientjes@google.com>
      Cc: Dave Hansen <dave@linux.vnet.ibm.com>
      Signed-off-by: NAndrew Morton <akpm@linux-foundation.org>
      Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
      e6de3988
  2. 27 8月, 2009 3 次提交
  3. 05 8月, 2009 1 次提交
  4. 30 7月, 2009 1 次提交
    • D
      lib: flexible array implementation · 534acc05
      Dave Hansen 提交于
      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: NDave Hansen <dave@linux.vnet.ibm.com>
      Reviewed-by: NKAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
      Signed-off-by: NAndrew Morton <akpm@linux-foundation.org>
      Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
      534acc05