aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSong Liu <song@kernel.org>2022-08-18 14:46:53 -0700
committerSong Liu <song@kernel.org>2022-08-18 15:27:32 -0700
commit8d25ad2b7f84ddfb4a4fd9a79678aed4443d6403 (patch)
treea67006a446bdf9ba740da007ae780d0c4beff0da
parent28a773079c07c17ae304f0cc9f6d5f20e331e58b (diff)
downloadlinux-8d25ad2b7f84ddfb4a4fd9a79678aed4443d6403.tar.gz
vmalloc: vfree_exec: free unused vm_struct
This is clearly not done yet, but it won't be too hard. I would like to highlight that, we need both subtree_max_size and vm for vmap_area in free_text tree. Therefore, we cannot keep the union in vmam_area.
-rw-r--r--include/linux/vmalloc.h12
-rw-r--r--mm/vmalloc.c14
2 files changed, 14 insertions, 12 deletions
diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h
index 691c02ffe3dbea..de7731caadc036 100644
--- a/include/linux/vmalloc.h
+++ b/include/linux/vmalloc.h
@@ -68,16 +68,8 @@ struct vmap_area {
struct rb_node rb_node; /* address sorted rbtree */
struct list_head list; /* address sorted list */
- /*
- * The following two variables can be packed, because
- * a vmap_area object can be either:
- * 1) in "free" tree (root is free_vmap_area_root)
- * 2) or "busy" tree (root is vmap_area_root)
- */
- union {
- unsigned long subtree_max_size; /* in "free" tree */
- struct vm_struct *vm; /* in "busy" tree */
- };
+ unsigned long subtree_max_size;
+ struct vm_struct *vm;
};
/* archs that select HAVE_ARCH_HUGE_VMAP should override one or more of these */
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index 5f3b5df9313f33..57dd18882d3709 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -1428,6 +1428,7 @@ adjust_va_to_fit_type(struct rb_root *root, struct list_head *head,
*/
lva->va_start = va->va_start;
lva->va_end = nva_start_addr;
+ lva->vm = va->vm;
/*
* Shrink this VA to remaining size.
@@ -3394,10 +3395,19 @@ void vfree_exec(const void *addr)
spin_unlock(&vmap_area_lock);
spin_lock(&free_text_area_lock);
- merge_or_add_vmap_area_augment(va,
+ va = merge_or_add_vmap_area_augment(va,
&free_text_area_root, &free_text_area_list);
+ if (va) {
+ struct vm_struct *vm = va->vm;
+
+ if (vm != &text_tail_vm) {
+ va = __find_vmap_area((unsigned long)vm->addr,
+ free_text_area_root.rb_node);
+ if (va->va_start == (unsigned long)vm->addr)
+ pr_info("%s TODO: free vm->addr %px\n", __func__, vm->addr);
+ }
+ }
spin_unlock(&free_text_area_lock);
- /* TODO: when the whole vm_struct is not in use, free it */
}
/**