summaryrefslogtreecommitdiff
path: root/fs/bcachefs/darray.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/bcachefs/darray.c')
-rw-r--r--fs/bcachefs/darray.c22
1 files changed, 15 insertions, 7 deletions
diff --git a/fs/bcachefs/darray.c b/fs/bcachefs/darray.c
index e86d36d23e9e..c06c81e842e4 100644
--- a/fs/bcachefs/darray.c
+++ b/fs/bcachefs/darray.c
@@ -5,7 +5,8 @@
#include <linux/vmalloc.h>
#include "darray.h"
-int __bch2_darray_resize_noprof(darray_char *d, size_t element_size, size_t new_size, gfp_t gfp)
+int __bch2_darray_resize_noprof(darray_char *d, size_t element_size, size_t new_size, gfp_t gfp,
+ bool rcu)
{
if (new_size > d->size) {
new_size = roundup_pow_of_two(new_size);
@@ -20,18 +21,25 @@ int __bch2_darray_resize_noprof(darray_char *d, size_t element_size, size_t new_
if (unlikely(check_mul_overflow(new_size, element_size, &bytes)))
return -ENOMEM;
- void *data = likely(bytes < INT_MAX)
+ void *old = d->data;
+ void *new = likely(bytes < INT_MAX)
? kvmalloc_noprof(bytes, gfp)
: vmalloc_noprof(bytes);
- if (!data)
+ if (!new)
return -ENOMEM;
if (d->size)
- memcpy(data, d->data, d->size * element_size);
- if (d->data != d->preallocated)
- kvfree(d->data);
- d->data = data;
+ memcpy(new, old, d->size * element_size);
+
+ rcu_assign_pointer(d->data, new);
d->size = new_size;
+
+ if (old != d->preallocated) {
+ if (!rcu)
+ kvfree(old);
+ else
+ kvfree_rcu_mightsleep(old);
+ }
}
return 0;