summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2021-04-24 07:38:16 +0300
committerKent Overstreet <kent.overstreet@linux.dev>2023-10-23 00:09:02 +0300
commit65c0601a329580f6a016298f7148305288b7d719 (patch)
tree79d4f2942092b9ec89c9d56f838ee7c13e7ba442
parent537c32f5212396751bf39b10d71af60af32dc257 (diff)
downloadlinux-65c0601a329580f6a016298f7148305288b7d719.tar.xz
bcachefs: Use mmap() instead of vmalloc_exec() in userspace
Calling mmap() directly is much better than malloc() then mprotect(), we end up with much less address space fragmentation. Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com> Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
-rw-r--r--fs/bcachefs/btree_cache.c23
1 files changed, 15 insertions, 8 deletions
diff --git a/fs/bcachefs/btree_cache.c b/fs/bcachefs/btree_cache.c
index 5a5eb99baefa..a42e0922f5e9 100644
--- a/fs/bcachefs/btree_cache.c
+++ b/fs/bcachefs/btree_cache.c
@@ -33,21 +33,21 @@ static inline unsigned btree_cache_can_free(struct btree_cache *bc)
return max_t(int, 0, bc->used - bc->reserve);
}
-static void __btree_node_data_free(struct bch_fs *c, struct btree *b)
+static void btree_node_data_free(struct bch_fs *c, struct btree *b)
{
+ struct btree_cache *bc = &c->btree_cache;
+
EBUG_ON(btree_node_write_in_flight(b));
kvpfree(b->data, btree_bytes(c));
b->data = NULL;
+#ifdef __KERNEL__
kvfree(b->aux_data);
+#else
+ munmap(b->aux_data, btree_aux_data_bytes(b));
+#endif
b->aux_data = NULL;
-}
-static void btree_node_data_free(struct bch_fs *c, struct btree *b)
-{
- struct btree_cache *bc = &c->btree_cache;
-
- __btree_node_data_free(c, b);
bc->used--;
list_move(&b->list, &bc->freed);
}
@@ -75,8 +75,15 @@ static int btree_node_data_alloc(struct bch_fs *c, struct btree *b, gfp_t gfp)
b->data = kvpmalloc(btree_bytes(c), gfp);
if (!b->data)
return -ENOMEM;
-
+#ifdef __KERNEL__
b->aux_data = kvmalloc(btree_aux_data_bytes(b), gfp);
+#else
+ b->aux_data = mmap(NULL, btree_aux_data_bytes(b),
+ PROT_READ|PROT_WRITE|PROT_EXEC,
+ MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
+ if (b->aux_data == MAP_FAILED)
+ b->aux_data = NULL;
+#endif
if (!b->aux_data) {
kvpfree(b->data, btree_bytes(c));
b->data = NULL;