|
8 | 8 | * Inspired by CCAN's darray |
9 | 9 | */ |
10 | 10 |
|
11 | | -#include "util.h" |
12 | 11 | #include <linux/slab.h> |
13 | 12 |
|
14 | | -#define DARRAY(type) \ |
| 13 | +#define DARRAY_PREALLOCATED(_type, _nr) \ |
15 | 14 | struct { \ |
16 | 15 | size_t nr, size; \ |
17 | | - type *data; \ |
| 16 | + _type *data; \ |
| 17 | + _type preallocated[_nr]; \ |
18 | 18 | } |
19 | 19 |
|
20 | | -typedef DARRAY(void) darray_void; |
| 20 | +#define DARRAY(_type) DARRAY_PREALLOCATED(_type, 0) |
21 | 21 |
|
22 | | -static inline int __darray_make_room(darray_void *d, size_t t_size, size_t more, gfp_t gfp) |
| 22 | +typedef DARRAY(char) darray_char; |
| 23 | + |
| 24 | +int __bch2_darray_resize(darray_char *, size_t, size_t, gfp_t); |
| 25 | + |
| 26 | +static inline int __darray_resize(darray_char *d, size_t element_size, |
| 27 | + size_t new_size, gfp_t gfp) |
23 | 28 | { |
24 | | - if (d->nr + more > d->size) { |
25 | | - size_t new_size = roundup_pow_of_two(d->nr + more); |
26 | | - void *data = krealloc_array(d->data, new_size, t_size, gfp); |
| 29 | + return unlikely(new_size > d->size) |
| 30 | + ? __bch2_darray_resize(d, element_size, new_size, gfp) |
| 31 | + : 0; |
| 32 | +} |
27 | 33 |
|
28 | | - if (!data) |
29 | | - return -ENOMEM; |
| 34 | +#define darray_resize_gfp(_d, _new_size, _gfp) \ |
| 35 | + unlikely(__darray_resize((darray_char *) (_d), sizeof((_d)->data[0]), (_new_size), _gfp)) |
30 | 36 |
|
31 | | - d->data = data; |
32 | | - d->size = new_size; |
33 | | - } |
| 37 | +#define darray_resize(_d, _new_size) \ |
| 38 | + darray_resize_gfp(_d, _new_size, GFP_KERNEL) |
34 | 39 |
|
35 | | - return 0; |
| 40 | +static inline int __darray_make_room(darray_char *d, size_t t_size, size_t more, gfp_t gfp) |
| 41 | +{ |
| 42 | + return __darray_resize(d, t_size, d->nr + more, gfp); |
36 | 43 | } |
37 | 44 |
|
38 | 45 | #define darray_make_room_gfp(_d, _more, _gfp) \ |
39 | | - __darray_make_room((darray_void *) (_d), sizeof((_d)->data[0]), (_more), _gfp) |
| 46 | + __darray_make_room((darray_char *) (_d), sizeof((_d)->data[0]), (_more), _gfp) |
40 | 47 |
|
41 | 48 | #define darray_make_room(_d, _more) \ |
42 | 49 | darray_make_room_gfp(_d, _more, GFP_KERNEL) |
43 | 50 |
|
| 51 | +#define darray_room(_d) ((_d).size - (_d).nr) |
| 52 | + |
44 | 53 | #define darray_top(_d) ((_d).data[(_d).nr]) |
45 | 54 |
|
46 | 55 | #define darray_push_gfp(_d, _item, _gfp) \ |
@@ -80,13 +89,16 @@ static inline int __darray_make_room(darray_void *d, size_t t_size, size_t more, |
80 | 89 |
|
81 | 90 | #define darray_init(_d) \ |
82 | 91 | do { \ |
83 | | - (_d)->data = NULL; \ |
84 | | - (_d)->nr = (_d)->size = 0; \ |
| 92 | + (_d)->nr = 0; \ |
| 93 | + (_d)->size = ARRAY_SIZE((_d)->preallocated); \ |
| 94 | + (_d)->data = (_d)->size ? (_d)->preallocated : NULL; \ |
85 | 95 | } while (0) |
86 | 96 |
|
87 | 97 | #define darray_exit(_d) \ |
88 | 98 | do { \ |
89 | | - kfree((_d)->data); \ |
| 99 | + if (!ARRAY_SIZE((_d)->preallocated) || \ |
| 100 | + (_d)->data != (_d)->preallocated) \ |
| 101 | + kvfree((_d)->data); \ |
90 | 102 | darray_init(_d); \ |
91 | 103 | } while (0) |
92 | 104 |
|
|
0 commit comments