Issue
In snapshot management, NOVA uses kmalloc to allocate the page-sized memory, and then checks the alignment, as the below code shows.
|
new_page = (unsigned long)kmalloc(PAGE_SIZE, |
|
GFP_KERNEL); |
|
/* Aligned to PAGE_SIZE */ |
|
if (!new_page || ENTRY_LOC(new_page)) { |
|
nova_dbg("%s: failed\n", __func__); |
|
kfree((void *)new_page); |
|
return -ENOMEM; |
|
} |
However, the allocated memory space might not be aligned to the page size. I have encountered this situation where the allocation is successful but the alignment is not satisfied, but I am not sure whether it was caused by VMs or small DRAM size that was used in the VM.
The documentation of kernel-5.1 does not say the alignment is guaranteed (https://www.kernel.org/doc/html/v5.1/core-api/memory-allocation.html). There also have discussions regarding the alignment of kmalloc (https://lwn.net/Articles/787740/).
From kernel-5.4, the documentation confirms the alignment guarantee of kmalloc. However, it also suggests to use the page allocator for large allocations. The blow code is the APIs of the page allocator.
|
#define alloc_page(gfp_mask) alloc_pages(gfp_mask, 0) |
|
#define alloc_page_vma(gfp_mask, vma, addr) \ |
|
alloc_pages_vma(gfp_mask, 0, vma, addr, numa_node_id(), false) |
|
#define alloc_page_vma_node(gfp_mask, vma, addr, node) \ |
|
alloc_pages_vma(gfp_mask, 0, vma, addr, node, false) |
|
|
|
extern unsigned long __get_free_pages(gfp_t gfp_mask, unsigned int order); |
|
extern unsigned long get_zeroed_page(gfp_t gfp_mask); |
|
|
|
void *alloc_pages_exact(size_t size, gfp_t gfp_mask); |
|
void free_pages_exact(void *virt, size_t size); |
|
void * __meminit alloc_pages_exact_nid(int nid, size_t size, gfp_t gfp_mask); |
|
|
|
#define __get_free_page(gfp_mask) \ |
|
__get_free_pages((gfp_mask), 0) |
|
|
|
#define __get_dma_pages(gfp_mask, order) \ |
|
__get_free_pages((gfp_mask) | GFP_DMA, (order)) |
|
|
|
extern void __free_pages(struct page *page, unsigned int order); |
|
extern void free_pages(unsigned long addr, unsigned int order); |
|
extern void free_unref_page(struct page *page); |
|
extern void free_unref_page_list(struct list_head *list); |
|
|
|
struct page_frag_cache; |
|
extern void __page_frag_cache_drain(struct page *page, unsigned int count); |
|
extern void *page_frag_alloc(struct page_frag_cache *nc, |
|
unsigned int fragsz, gfp_t gfp_mask); |
|
extern void page_frag_free(void *addr); |
|
|
|
#define __free_page(page) __free_pages((page), 0) |
|
#define free_page(addr) free_pages((addr), 0) |
Fix
Replacing kmalloc as __get_free_page and kfree as free_page, as below code shows
// new_page = (unsigned long)kmalloc(PAGE_SIZE, GFP_KERNEL);
new_page = __get_free_page(GFP_KERNEL);
if (!new_page || ENTRY_LOC(new_page)) {
// kfree((void *)new_page);
free_page((unsigned long)new_page);
nova_err(sb, "%s: allocation failed\n", __func__);
return -ENOMEM;
}
// and other places to fix
Issue
In snapshot management, NOVA uses
kmallocto allocate the page-sized memory, and then checks the alignment, as the below code shows.linux-nova/fs/nova/snapshot.c
Lines 313 to 320 in 976a4d1
However, the allocated memory space might not be aligned to the page size. I have encountered this situation where the allocation is successful but the alignment is not satisfied, but I am not sure whether it was caused by VMs or small DRAM size that was used in the VM.
The documentation of kernel-5.1 does not say the alignment is guaranteed (https://www.kernel.org/doc/html/v5.1/core-api/memory-allocation.html). There also have discussions regarding the alignment of
kmalloc(https://lwn.net/Articles/787740/).From kernel-5.4, the documentation confirms the alignment guarantee of
kmalloc. However, it also suggests to use the page allocator for large allocations. The blow code is the APIs of the page allocator.linux-nova/include/linux/gfp.h
Lines 524 to 555 in 976a4d1
Fix
Replacing
kmallocas__get_free_pageandkfreeasfree_page, as below code shows