Kernel document https://www.kernel.org/doc/gorman/html/understand/understand010.html says, that for vmalloc-ing
It searches through a linear linked list of vm_structs and returns a new struct describing the allocated region.
Does that mean vm_struct list is already created while booting up, just like kmem_cache_create and vmalloc() just adjusts the page entries? If that is the case, say if I have a 16GB RAM in x86_64 machine, the whole ZONE_NORMAL i.e
16GB - ZONE_DMA - ZONE_DMA32 - slab-memory(cache/kmalloc)
is used to create vm_struct list?
That document is fairly old. It's talking about Linux 2.5-2.6. Things have changed quite a bit with those functions from what I can tell. I'll start by talking about code from kernel 2.6.12 since that matches Gorman's explanation and is the oldest non-rc tag in the Linux kernel Github repo.
The
vm_structlist that the document is referring to is calledvmlist. It is created here as a struct pointer:Trying to figure out if it is initialized with any structs during bootup took some deduction. The easiest way to figure it out was by looking at the function
get_vmalloc_info()(edited for brevity):The logic says that if the
vmlistpointer is equal to NULL (!NULL), then there are novm_structs on the list and thelargest_chunkof free memory in thisVMALLOCarea is the entire space, henceVMALLOC_TOTAL. However, if there is something on thevmlist, then figure out the largest chunk based on the difference between the address of the currentvm_structand the end of the previousvm_struct(i.e.free_area_size = addr - prev_end).What this tells us is that when we
vmalloc, we look through thevmlistto find the absence of avm_structin a virtual memory area big enough to accomodate our request. Only then can it create this newvm_struct, which will now be part of thevmlist.vmallocwill eventually call__get_vm_area(), which is where the action happens:By this point in the function we have already created a new
vm_structnamedarea. This for loop just needs to find where to put the struct in the list. If thevmlistis empty, we skip the loop and immediately execute the "found" lines, making*p(thevmlist) point to our struct. Otherwise, we need to find the struct that will go after ours.So in summary, this means that even though the
vmlistpointer might be created at boot time, the list isn't necessarily populated at boot time. That is, unless there arevmalloccalls during boot or functions that explicitly addvm_structs to the list during boot as in future kernel versions (see below for kernel 6.0.9).One further clarification for you. You asked if
ZONE_NORMALis used for thevmlist, but those are two separate memory address spaces.ZONE_NORMALis describing physical memory whereasvmis virtual memory. There are lots of resources for explaining the difference between the two (e.g. this Stack Overflow question). The specific virtual memory address range forvmlistgoes fromVMALLOC_STARTtoVMALLOC_END. In x86, those were defined as:For kernel version 6.0.9:
The creation of the
vm_structlist is here:At this point, there is nothing on the list. But in this kernel version there are a few boot functions that may add structs to the list:
As for
vmallocin this version, thevmlistis now only a list used during initialization.get_vm_area()now callsget_vm_area_node(), which is a NUMA ready function. From there, the logic goes deeper and is much more complicated than the linear search described above.