diff options
author | Kent Overstreet <kent.overstreet@linux.dev> | 2023-12-30 14:38:29 -0500 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@linux.dev> | 2024-01-01 11:46:52 -0500 |
commit | 099dc5c29dff52c0c37abcaa6cc747a1ac8df5fe (patch) | |
tree | 2ee31e5b1f483349dd0b35eb4921dbfd954a184b /fs/bcachefs | |
parent | a58a6a58f5ad55aa1f5c54598c44f1d9938c1793 (diff) | |
download | lwn-099dc5c29dff52c0c37abcaa6cc747a1ac8df5fe.tar.gz lwn-099dc5c29dff52c0c37abcaa6cc747a1ac8df5fe.zip |
bcachefs: DARRAY_PREALLOCATED()
Add support to darray for preallocating some number of elements.
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
Diffstat (limited to 'fs/bcachefs')
-rw-r--r-- | fs/bcachefs/darray.c | 5 | ||||
-rw-r--r-- | fs/bcachefs/darray.h | 28 |
2 files changed, 20 insertions, 13 deletions
diff --git a/fs/bcachefs/darray.c b/fs/bcachefs/darray.c index 4c900c853268..ac35b8b705ae 100644 --- a/fs/bcachefs/darray.c +++ b/fs/bcachefs/darray.c @@ -4,7 +4,7 @@ #include <linux/slab.h> #include "darray.h" -int __bch2_darray_resize(darray_void *d, size_t element_size, size_t new_size, gfp_t gfp) +int __bch2_darray_resize(darray_char *d, size_t element_size, size_t new_size, gfp_t gfp) { if (new_size > d->size) { new_size = roundup_pow_of_two(new_size); @@ -14,7 +14,8 @@ int __bch2_darray_resize(darray_void *d, size_t element_size, size_t new_size, g return -ENOMEM; memcpy(data, d->data, d->size * element_size); - kvfree(d->data); + if (d->data != d->preallocated) + kvfree(d->data); d->data = data; d->size = new_size; } diff --git a/fs/bcachefs/darray.h b/fs/bcachefs/darray.h index 6157c53d5bf0..e367c625f057 100644 --- a/fs/bcachefs/darray.h +++ b/fs/bcachefs/darray.h @@ -10,17 +10,20 @@ #include <linux/slab.h> -#define DARRAY(type) \ +#define DARRAY_PREALLOCATED(_type, _nr) \ struct { \ size_t nr, size; \ - type *data; \ + _type *data; \ + _type preallocated[_nr]; \ } -typedef DARRAY(void) darray_void; +#define DARRAY(_type) DARRAY_PREALLOCATED(_type, 0) -int __bch2_darray_resize(darray_void *, size_t, size_t, gfp_t); +typedef DARRAY(char) darray_char; -static inline int __darray_resize(darray_void *d, size_t element_size, +int __bch2_darray_resize(darray_char *, size_t, size_t, gfp_t); + +static inline int __darray_resize(darray_char *d, size_t element_size, size_t new_size, gfp_t gfp) { return unlikely(new_size > d->size) @@ -29,18 +32,18 @@ static inline int __darray_resize(darray_void *d, size_t element_size, } #define darray_resize_gfp(_d, _new_size, _gfp) \ - __darray_resize((darray_void *) (_d), sizeof((_d)->data[0]), (_new_size), _gfp) + unlikely(__darray_resize((darray_char *) (_d), sizeof((_d)->data[0]), (_new_size), _gfp)) #define darray_resize(_d, _new_size) \ darray_resize_gfp(_d, _new_size, GFP_KERNEL) -static inline int __darray_make_room(darray_void *d, size_t t_size, size_t more, gfp_t gfp) +static inline int __darray_make_room(darray_char *d, size_t t_size, size_t more, gfp_t gfp) { return __darray_resize(d, t_size, d->nr + more, gfp); } #define darray_make_room_gfp(_d, _more, _gfp) \ - __darray_make_room((darray_void *) (_d), sizeof((_d)->data[0]), (_more), _gfp) + __darray_make_room((darray_char *) (_d), sizeof((_d)->data[0]), (_more), _gfp) #define darray_make_room(_d, _more) \ darray_make_room_gfp(_d, _more, GFP_KERNEL) @@ -86,13 +89,16 @@ static inline int __darray_make_room(darray_void *d, size_t t_size, size_t more, #define darray_init(_d) \ do { \ - (_d)->data = NULL; \ - (_d)->nr = (_d)->size = 0; \ + (_d)->nr = 0; \ + (_d)->size = ARRAY_SIZE((_d)->preallocated); \ + (_d)->data = (_d)->size ? (_d)->preallocated : NULL; \ } while (0) #define darray_exit(_d) \ do { \ - kvfree((_d)->data); \ + if (!ARRAY_SIZE((_d)->preallocated) || \ + (_d)->data != (_d)->preallocated) \ + kvfree((_d)->data); \ darray_init(_d); \ } while (0) |