Objective --------- The current implementation of struct vmap_area wasted space. After applying this commit, sizeof(struct vmap_area) has been reduced from 11 words to 8 words. Description ----------- 1) Pack "subtree_max_size", "vm" and "purge_list". This is no problem because A) "subtree_max_size" is only used when vmap_area is in "free" tree B) "vm" is only used when vmap_area is in "busy" tree C) "purge_list" is only used when vmap_area is in vmap_purge_list 2) Eliminate "flags". ;Since only one flag VM_VM_AREA is being used, and the same thing can be done by judging whether "vm" is NULL, then the "flags" can be eliminated.
Unified · Split
| @@ -53,15 +53,21 @@ struct vmap_area { · 52 unmodified lines | ||
| 53 | 53 | unsigned long va_start; |
| 54 | 54 | unsigned long va_end; |
| 55 | 55 | |
| 56 | − /* | |
| 57 | − * Largest available free size in subtree. | |
| 58 | − */ | |
| 59 | − unsigned long subtree_max_size; | |
| 60 | − unsigned long flags; | |
| 61 | 56 | struct rb_node rb_node; /* address sorted rbtree */ |
| 62 | 57 | struct list_head list; /* address sorted list */ |
| 63 | − struct llist_node purge_list; /* "lazy purge" list */ | |
| 64 | − struct vm_struct *vm; | |
| 58 | + | |
| 59 | + /* | |
| 60 | + * The following three variables can be packed, because | |
| 61 | + * a vmap_area object is always one of the three states: | |
| 62 | + * 1) in "free" tree (root is vmap_area_root) | |
| 63 | + * 2) in "busy" tree (root is free_vmap_area_root) | |
| 64 | + * 3) in purge list (head is vmap_purge_list) | |
| 65 | + */ | |
| 66 | + union { | |
| 67 | + unsigned long subtree_max_size; /* in "free" tree */ | |
| 68 | + struct vm_struct *vm; /* in "busy" tree */ | |
| 69 | + struct llist_node purge_list; /* in purge list */ | |
| 70 | + }; | |
| 65 | 71 | }; |
| 66 | 72 | |
| 67 | 73 | /* |
| @@ -329,7 +329,6 @@ EXPORT_SYMBOL(vmalloc_to_pfn); · 328 unmodified lines | ||
| 329 | 329 | #define DEBUG_AUGMENT_PROPAGATE_CHECK 0 |
| 330 | 330 | #define DEBUG_AUGMENT_LOWEST_MATCH_CHECK 0 |
| 331 | 331 | |
| 332 | −#define VM_VM_AREA 0x04 | |
| 333 | 332 | |
| 334 | 333 | static DEFINE_SPINLOCK(vmap_area_lock); |
| 335 | 334 | /* Export for kexec only */ |
| @@ -1115,7 +1114,7 @@ retry: · 779 unmodified lines | ||
| 1115 | 1114 | |
| 1116 | 1115 | va->va_start = addr; |
| 1117 | 1116 | va->va_end = addr + size; |
| 1118 | − va->flags = 0; | |
| 1117 | + va->vm = NULL; | |
| 1119 | 1118 | insert_vmap_area(va, &vmap_area_root, &vmap_area_list); |
| 1120 | 1119 | |
| 1121 | 1120 | spin_unlock(&vmap_area_lock); |
| @@ -1928,7 +1927,6 @@ void __init vmalloc_init(void) · 806 unmodified lines | ||
| 1928 | 1927 | if (WARN_ON_ONCE(!va)) |
| 1929 | 1928 | continue; |
| 1930 | 1929 | |
| 1931 | − va->flags = VM_VM_AREA; | |
| 1932 | 1930 | va->va_start = (unsigned long)tmp->addr; |
| 1933 | 1931 | va->va_end = va->va_start + tmp->size; |
| 1934 | 1932 | va->vm = tmp; |
| @@ -2026,7 +2024,6 @@ static void setup_vmalloc_vm(struct vm_struct *vm, struct vmap_area *va, · 91 unmodified lines | ||
| 2026 | 2024 | vm->size = va->va_end - va->va_start; |
| 2027 | 2025 | vm->caller = caller; |
| 2028 | 2026 | va->vm = vm; |
| 2029 | − va->flags |= VM_VM_AREA; | |
| 2030 | 2027 | spin_unlock(&vmap_area_lock); |
| 2031 | 2028 | } |
| 2032 | 2029 | |
| @@ -2131,10 +2128,10 @@ struct vm_struct *find_vm_area(const void *addr) · 98 unmodified lines | ||
| 2131 | 2128 | struct vmap_area *va; |
| 2132 | 2129 | |
| 2133 | 2130 | va = find_vmap_area((unsigned long)addr); |
| 2134 | − if (va && va->flags & VM_VM_AREA) | |
| 2135 | − return va->vm; | |
| 2131 | + if (!va) | |
| 2132 | + return NULL; | |
| 2136 | 2133 | |
| 2137 | − return NULL; | |
| 2134 | + return va->vm; | |
| 2138 | 2135 | } |
| 2139 | 2136 | |
| 2140 | 2137 | /** |
| @@ -2155,11 +2152,10 @@ struct vm_struct *remove_vm_area(const void *addr) · 14 unmodified lines | ||
| 2155 | 2152 | |
| 2156 | 2153 | spin_lock(&vmap_area_lock); |
| 2157 | 2154 | va = __find_vmap_area((unsigned long)addr); |
| 2158 | − if (va && va->flags & VM_VM_AREA) { | |
| 2155 | + if (va && va->vm) { | |
| 2159 | 2156 | struct vm_struct *vm = va->vm; |
| 2160 | 2157 | |
| 2161 | 2158 | va->vm = NULL; |
| 2162 | − va->flags &= ~VM_VM_AREA; | |
| 2163 | 2159 | spin_unlock(&vmap_area_lock); |
| 2164 | 2160 | |
| 2165 | 2161 | kasan_free_shadow(vm); |
| @@ -2862,7 +2858,7 @@ long vread(char *buf, char *addr, unsigned long count) · 696 unmodified lines | ||
| 2862 | 2858 | if (!count) |
| 2863 | 2859 | break; |
| 2864 | 2860 | |
| 2865 | − if (!(va->flags & VM_VM_AREA)) | |
| 2861 | + if (!va->vm) | |
| 2866 | 2862 | continue; |
| 2867 | 2863 | |
| 2868 | 2864 | vm = va->vm; |
| @@ -2942,7 +2938,7 @@ long vwrite(char *buf, char *addr, unsigned long count) · 73 unmodified lines | ||
| 2942 | 2938 | if (!count) |
| 2943 | 2939 | break; |
| 2944 | 2940 | |
| 2945 | − if (!(va->flags & VM_VM_AREA)) | |
| 2941 | + if (!va->vm) | |
| 2946 | 2942 | continue; |
| 2947 | 2943 | |
| 2948 | 2944 | vm = va->vm; |
| @@ -3485,10 +3481,10 @@ static int s_show(struct seq_file *m, void *p) · 536 unmodified lines | ||
| 3485 | 3481 | va = list_entry(p, struct vmap_area, list); |
| 3486 | 3482 | |
| 3487 | 3483 | /* |
| 3488 | − * s_show can encounter race with remove_vm_area, !VM_VM_AREA on | |
| 3489 | − * behalf of vmap area is being tear down or vm_map_ram allocation. | |
| 3484 | + * s_show can encounter race with remove_vm_area, !vm on behalf | |
| 3485 | + * of vmap area is being tear down or vm_map_ram allocation. | |
| 3490 | 3486 | */ |
| 3491 | − if (!(va->flags & VM_VM_AREA)) { | |
| 3487 | + if (!va->vm) { | |
| 3492 | 3488 | seq_printf(m, "0x%pK-0x%pK %7ld vm_map_ram\n", |
| 3493 | 3489 | (void *)va->va_start, (void *)va->va_end, |
| 3494 | 3490 | va->va_end - va->va_start); |