diff options
author | David Rientjes <rientjes@google.com> | 2009-09-21 20:04:31 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-22 10:17:47 -0400 |
commit | 19da3dd157f8db6fe727ff268dab4791d55a6371 (patch) | |
tree | 4259074638b384e765c73542d74dd8f44750068b /lib/flex_array.c | |
parent | e6de3988aa52debb25a427d085061f3bf1181d54 (diff) |
flex_array: poison free elements
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 <rientjes@google.com>
Cc: Dave Hansen <dave@linux.vnet.ibm.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'lib/flex_array.c')
-rw-r--r-- | lib/flex_array.c | 15 |
1 files changed, 7 insertions, 8 deletions
diff --git a/lib/flex_array.c b/lib/flex_array.c index b68f99be408..e22d0e9776a 100644 --- a/lib/flex_array.c +++ b/lib/flex_array.c | |||
@@ -113,6 +113,8 @@ struct flex_array *flex_array_alloc(int element_size, unsigned int total, | |||
113 | return NULL; | 113 | return NULL; |
114 | ret->element_size = element_size; | 114 | ret->element_size = element_size; |
115 | ret->total_nr_elements = total; | 115 | ret->total_nr_elements = total; |
116 | if (elements_fit_in_base(ret) && !(flags & __GFP_ZERO)) | ||
117 | memset(ret->parts[0], FLEX_ARRAY_FREE, bytes_left_in_base()); | ||
116 | return ret; | 118 | return ret; |
117 | } | 119 | } |
118 | 120 | ||
@@ -159,15 +161,12 @@ __fa_get_part(struct flex_array *fa, int part_nr, gfp_t flags) | |||
159 | { | 161 | { |
160 | struct flex_array_part *part = fa->parts[part_nr]; | 162 | struct flex_array_part *part = fa->parts[part_nr]; |
161 | if (!part) { | 163 | if (!part) { |
162 | /* | 164 | part = kmalloc(sizeof(struct flex_array_part), flags); |
163 | * This leaves the part pages uninitialized | ||
164 | * and with potentially random data, just | ||
165 | * as if the user had kmalloc()'d the whole. | ||
166 | * __GFP_ZERO can be used to zero it. | ||
167 | */ | ||
168 | part = kmalloc(FLEX_ARRAY_PART_SIZE, flags); | ||
169 | if (!part) | 165 | if (!part) |
170 | return NULL; | 166 | return NULL; |
167 | if (!(flags & __GFP_ZERO)) | ||
168 | memset(part, FLEX_ARRAY_FREE, | ||
169 | sizeof(struct flex_array_part)); | ||
171 | fa->parts[part_nr] = part; | 170 | fa->parts[part_nr] = part; |
172 | } | 171 | } |
173 | return part; | 172 | return part; |
@@ -228,7 +227,7 @@ int flex_array_clear(struct flex_array *fa, unsigned int element_nr) | |||
228 | return -EINVAL; | 227 | return -EINVAL; |
229 | } | 228 | } |
230 | dst = &part->elements[index_inside_part(fa, element_nr)]; | 229 | dst = &part->elements[index_inside_part(fa, element_nr)]; |
231 | memset(dst, 0, fa->element_size); | 230 | memset(dst, FLEX_ARRAY_FREE, fa->element_size); |
232 | return 0; | 231 | return 0; |
233 | } | 232 | } |
234 | 233 | ||