@@ -7,9 +7,10 @@
#include <asm/page.h>
#define FLEX_ARRAY_PART_SIZE PAGE_SIZE
-#define FLEX_ARRAY_BASE_SIZE PAGE_SIZE
+#define FLEX_ARRAY_BASE_SIZE FLEX_ARRAY_PART_SIZE
struct flex_array_part;
+struct flex_array_part_p;
/*
* This is meant to replace cases where an array-like
@@ -19,29 +20,17 @@ struct flex_array_part;
*/
struct flex_array {
- union {
- struct {
- int element_size;
- int total_nr_elements;
- int elems_per_part;
- struct reciprocal_value reciprocal_elems;
- struct flex_array_part *parts[];
- };
- /*
- * This little trick makes sure that
- * sizeof(flex_array) == PAGE_SIZE
- */
- char padding[FLEX_ARRAY_BASE_SIZE];
- };
+ int element_size;
+ int total_nr_elements;
+ int elems_per_part;
+ struct reciprocal_value reciprocal_elems;
+ struct flex_array_part_p *part_p;
+#define parts part_p->p_part
};
-/* Number of bytes left in base struct flex_array, excluding metadata */
-#define FLEX_ARRAY_BASE_BYTES_LEFT \
- (FLEX_ARRAY_BASE_SIZE - offsetof(struct flex_array, parts))
-
/* Number of pointers in base to struct flex_array_part pages */
#define FLEX_ARRAY_NR_BASE_PTRS \
- (FLEX_ARRAY_BASE_BYTES_LEFT / sizeof(struct flex_array_part *))
+ (FLEX_ARRAY_BASE_SIZE / sizeof(struct flex_array_part *))
/* Number of elements of size that fit in struct flex_array_part */
#define FLEX_ARRAY_ELEMENTS_PER_PART(size) \
@@ -30,6 +30,10 @@ struct flex_array_part {
char elements[FLEX_ARRAY_PART_SIZE];
};
+struct flex_array_part_p {
+ struct flex_array_part *p_part[FLEX_ARRAY_NR_BASE_PTRS];
+};
+
/*
* If a user requests an allocation which is small
* enough, we may simply use the space in the
@@ -39,7 +43,7 @@ struct flex_array_part {
static inline int elements_fit_in_base(struct flex_array *fa)
{
int data_size = fa->element_size * fa->total_nr_elements;
- if (data_size <= FLEX_ARRAY_BASE_BYTES_LEFT)
+ if (data_size <= FLEX_ARRAY_BASE_SIZE)
return 1;
return 0;
}
@@ -105,13 +109,17 @@ struct flex_array *flex_array_alloc(int element_size, unsigned int total,
ret = kzalloc(sizeof(struct flex_array), flags);
if (!ret)
return NULL;
+ ret->part_p = kzalloc(sizeof(struct flex_array_part_p), flags);
+ if (!ret->part_p) {
+ kfree(ret);
+ return NULL;
+ }
ret->element_size = element_size;
ret->total_nr_elements = total;
ret->elems_per_part = elems_per_part;
ret->reciprocal_elems = reciprocal_elems;
if (elements_fit_in_base(ret) && !(flags & __GFP_ZERO))
- memset(&ret->parts[0], FLEX_ARRAY_FREE,
- FLEX_ARRAY_BASE_BYTES_LEFT);
+ memset(&ret->parts[0], FLEX_ARRAY_FREE, FLEX_ARRAY_BASE_SIZE);
return ret;
}
EXPORT_SYMBOL(flex_array_alloc);
@@ -148,6 +156,7 @@ EXPORT_SYMBOL(flex_array_free_parts);
void flex_array_free(struct flex_array *fa)
{
flex_array_free_parts(fa);
+ kfree(fa->part_p);
kfree(fa);
}
EXPORT_SYMBOL(flex_array_free);