| Dave Hansen | 534acc0 | 2009-07-29 15:04:18 -0700 | [diff] [blame] | 1 | #ifndef _FLEX_ARRAY_H | 
 | 2 | #define _FLEX_ARRAY_H | 
 | 3 |  | 
 | 4 | #include <linux/types.h> | 
 | 5 | #include <asm/page.h> | 
 | 6 |  | 
 | 7 | #define FLEX_ARRAY_PART_SIZE PAGE_SIZE | 
 | 8 | #define FLEX_ARRAY_BASE_SIZE PAGE_SIZE | 
 | 9 |  | 
 | 10 | struct flex_array_part; | 
 | 11 |  | 
 | 12 | /* | 
 | 13 |  * This is meant to replace cases where an array-like | 
 | 14 |  * structure has gotten too big to fit into kmalloc() | 
 | 15 |  * and the developer is getting tempted to use | 
 | 16 |  * vmalloc(). | 
 | 17 |  */ | 
 | 18 |  | 
 | 19 | struct flex_array { | 
 | 20 | 	union { | 
 | 21 | 		struct { | 
 | 22 | 			int element_size; | 
 | 23 | 			int total_nr_elements; | 
| David Rientjes | 8e7ee270 | 2009-08-26 14:29:21 -0700 | [diff] [blame] | 24 | 			struct flex_array_part *parts[]; | 
| Dave Hansen | 534acc0 | 2009-07-29 15:04:18 -0700 | [diff] [blame] | 25 | 		}; | 
 | 26 | 		/* | 
 | 27 | 		 * This little trick makes sure that | 
 | 28 | 		 * sizeof(flex_array) == PAGE_SIZE | 
 | 29 | 		 */ | 
 | 30 | 		char padding[FLEX_ARRAY_BASE_SIZE]; | 
 | 31 | 	}; | 
 | 32 | }; | 
 | 33 |  | 
| David Rientjes | 45b588d | 2009-09-21 17:04:33 -0700 | [diff] [blame] | 34 | /* Number of bytes left in base struct flex_array, excluding metadata */ | 
 | 35 | #define FLEX_ARRAY_BASE_BYTES_LEFT					\ | 
 | 36 | 	(FLEX_ARRAY_BASE_SIZE - offsetof(struct flex_array, parts)) | 
 | 37 |  | 
 | 38 | /* Number of pointers in base to struct flex_array_part pages */ | 
 | 39 | #define FLEX_ARRAY_NR_BASE_PTRS						\ | 
 | 40 | 	(FLEX_ARRAY_BASE_BYTES_LEFT / sizeof(struct flex_array_part *)) | 
 | 41 |  | 
 | 42 | /* Number of elements of size that fit in struct flex_array_part */ | 
 | 43 | #define FLEX_ARRAY_ELEMENTS_PER_PART(size)				\ | 
 | 44 | 	(FLEX_ARRAY_PART_SIZE / size) | 
 | 45 |  | 
 | 46 | /* | 
 | 47 |  * Defines a statically allocated flex array and ensures its parameters are | 
 | 48 |  * valid. | 
 | 49 |  */ | 
 | 50 | #define DEFINE_FLEX_ARRAY(__arrayname, __element_size, __total)		\ | 
 | 51 | 	struct flex_array __arrayname = { { {				\ | 
 | 52 | 		.element_size = (__element_size),			\ | 
 | 53 | 		.total_nr_elements = (__total),				\ | 
 | 54 | 	} } };								\ | 
 | 55 | 	static inline void __arrayname##_invalid_parameter(void)	\ | 
 | 56 | 	{								\ | 
 | 57 | 		BUILD_BUG_ON((__total) > FLEX_ARRAY_NR_BASE_PTRS *	\ | 
 | 58 | 			FLEX_ARRAY_ELEMENTS_PER_PART(__element_size));	\ | 
 | 59 | 	} | 
| Dave Hansen | 534acc0 | 2009-07-29 15:04:18 -0700 | [diff] [blame] | 60 |  | 
| David Rientjes | b62e408 | 2009-08-26 14:29:22 -0700 | [diff] [blame] | 61 | struct flex_array *flex_array_alloc(int element_size, unsigned int total, | 
 | 62 | 		gfp_t flags); | 
 | 63 | int flex_array_prealloc(struct flex_array *fa, unsigned int start, | 
 | 64 | 		unsigned int end, gfp_t flags); | 
| Dave Hansen | 534acc0 | 2009-07-29 15:04:18 -0700 | [diff] [blame] | 65 | void flex_array_free(struct flex_array *fa); | 
 | 66 | void flex_array_free_parts(struct flex_array *fa); | 
| David Rientjes | b62e408 | 2009-08-26 14:29:22 -0700 | [diff] [blame] | 67 | int flex_array_put(struct flex_array *fa, unsigned int element_nr, void *src, | 
| Dave Hansen | 534acc0 | 2009-07-29 15:04:18 -0700 | [diff] [blame] | 68 | 		gfp_t flags); | 
| David Rientjes | e6de398 | 2009-09-21 17:04:30 -0700 | [diff] [blame] | 69 | int flex_array_clear(struct flex_array *fa, unsigned int element_nr); | 
| David Rientjes | b62e408 | 2009-08-26 14:29:22 -0700 | [diff] [blame] | 70 | void *flex_array_get(struct flex_array *fa, unsigned int element_nr); | 
| David Rientjes | 4af5a2f | 2009-09-21 17:04:31 -0700 | [diff] [blame] | 71 | int flex_array_shrink(struct flex_array *fa); | 
| Dave Hansen | 534acc0 | 2009-07-29 15:04:18 -0700 | [diff] [blame] | 72 |  | 
 | 73 | #endif /* _FLEX_ARRAY_H */ |