Messages in this thread |  | | From | Nick Piggin <> | | Subject | Re: [PATCH 07/10] vmalloc: implement vm_area_register_early() | | Date | Thu, 19 Feb 2009 23:09:28 +1100 |
| |
On Wednesday 18 February 2009 23:04:33 Tejun Heo wrote: > Impact: allow multiple early vm areas > > There are places where kernel VM area needs to be allocated before > vmalloc is initialized. This is done by allocating static vm_struct, > initializing several fields and linking it to vmlist and later vmalloc > initialization picking up these from vmlist. This is currently done > manually and if there's more than one such areas, there's no defined > way to arbitrate who gets which address. > > This patch implements vm_area_register_early(), which takes vm_area > struct with flags and size initialized, assigns address to it and puts > it on the vmlist. This way, multiple early vm areas can determine > which addresses they should use. The only current user - alpha mm > init - is converted to use it.
Yes, this is much cleaner. Arguably could go upstream earlier, but if there are no other callers, probably doesn't matter so much.
Acked-by: Nick Piggin <npiggin@suse.de>
> > Signed-off-by: Tejun Heo <tj@kernel.org> > --- > arch/alpha/mm/init.c | 20 +++++++++++++------- > include/linux/vmalloc.h | 1 + > mm/vmalloc.c | 24 ++++++++++++++++++++++++ > 3 files changed, 38 insertions(+), 7 deletions(-) > > diff --git a/arch/alpha/mm/init.c b/arch/alpha/mm/init.c > index 5d7a16e..df6df02 100644 > --- a/arch/alpha/mm/init.c > +++ b/arch/alpha/mm/init.c > @@ -189,9 +189,21 @@ callback_init(void * kernel_end) > > if (alpha_using_srm) { > static struct vm_struct console_remap_vm; > - unsigned long vaddr = VMALLOC_START; > + unsigned long nr_pages = 0; > + unsigned long vaddr; > unsigned long i, j; > > + /* calculate needed size */ > + for (i = 0; i < crb->map_entries; ++i) > + nr_pages += crb->map[i].count; > + > + /* register the vm area */ > + console_remap_vm.flags = VM_ALLOC; > + console_remap_vm.size = nr_pages << PAGE_SHIFT; > + vm_area_register_early(&console_remap_vm); > + > + vaddr = (unsigned long)consle_remap_vm.addr; > + > /* Set up the third level PTEs and update the virtual > addresses of the CRB entries. */ > for (i = 0; i < crb->map_entries; ++i) { > @@ -213,12 +225,6 @@ callback_init(void * kernel_end) > vaddr += PAGE_SIZE; > } > } > - > - /* Let vmalloc know that we've allocated some space. */ > - console_remap_vm.flags = VM_ALLOC; > - console_remap_vm.addr = (void *) VMALLOC_START; > - console_remap_vm.size = vaddr - VMALLOC_START; > - vmlist = &console_remap_vm; > } > > callback_init_done = 1; > diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h > index 506e762..bbc0513 100644 > --- a/include/linux/vmalloc.h > +++ b/include/linux/vmalloc.h > @@ -106,5 +106,6 @@ extern long vwrite(char *buf, char *addr, unsigned long > count); */ > extern rwlock_t vmlist_lock; > extern struct vm_struct *vmlist; > +extern __init void vm_area_register_early(struct vm_struct *vm); > > #endif /* _LINUX_VMALLOC_H */ > diff --git a/mm/vmalloc.c b/mm/vmalloc.c > index c37924a..d206261 100644 > --- a/mm/vmalloc.c > +++ b/mm/vmalloc.c > @@ -24,6 +24,7 @@ > #include <linux/radix-tree.h> > #include <linux/rcupdate.h> > #include <linux/bootmem.h> > +#include <linux/pfn.h> > > #include <asm/atomic.h> > #include <asm/uaccess.h> > @@ -982,6 +983,29 @@ void *vm_map_ram(struct page **pages, unsigned int > count, int node, pgprot_t pro } > EXPORT_SYMBOL(vm_map_ram); > > +/** > + * vm_area_register_early - register vmap area early during boot > + * @vm: vm_struct to register > + * @size: size of area to register > + * > + * This function is used to register kernel vm area before > + * vmalloc_init() is called. @vm->size and @vm->flags should contain > + * proper values on entry and other fields should be zero. On return, > + * vm->addr contains the allocated address. > + * > + * DO NOT USE THIS FUNCTION UNLESS YOU KNOW WHAT YOU'RE DOING. > + */ > +void __init vm_area_register_early(struct vm_struct *vm) > +{ > + static size_t vm_init_off __initdata; > + > + vm->addr = (void *)VMALLOC_START + vm_init_off; > + vm_init_off = PFN_ALIGN(vm_init_off + vm->size); > + > + vm->next = vmlist; > + vmlist = vm; > +} > + > void __init vmalloc_init(void) > { > struct vmap_area *va;
|  |