Commit 6935faf1 authored by ZhangPeng's avatar ZhangPeng Committed by Peng Zhang
Browse files

userswap: fix kmalloc ENOMEM failed for a large memory

hulk inclusion
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I6CAIM



--------------------------------

If the swapped-out memory is large, such as tens of gigabytes, we will
allocate a large management structure, which may be tens of megabytes or
hundreds of megabytes. So if we use kmalloc to allocate management
structures it may fail.
Fix this by changing kmalloc to kvzalloc and kfree to kvfree.

Signed-off-by: default avatarZhangPeng <zhangpeng362@huawei.com>
parent 9f98927f
Loading
Loading
Loading
Loading
+6 −7
Original line number Diff line number Diff line
@@ -86,7 +86,7 @@ static unsigned long pages_can_be_swapped(struct mm_struct *mm,
	*ppages = NULL;


	pages = kmalloc(sizeof(struct page *) * (len / PAGE_SIZE), GFP_KERNEL);
	pages = kvzalloc(sizeof(struct page *) * (len / PAGE_SIZE), GFP_KERNEL);
	if (!pages)
		return -ENOMEM;

@@ -153,7 +153,7 @@ static unsigned long pages_can_be_swapped(struct mm_struct *mm,
out_err:
	for (i = 0; i < page_num; i++)
		put_page(pages[i]);
	kfree(pages);
	kvfree(pages);
	return ret;
}

@@ -299,10 +299,9 @@ static unsigned long do_user_swap(struct mm_struct *mm,
	unsigned long i = 0, j;
	int ret;

	ptes = kmalloc(sizeof(pte_t) * (len / PAGE_SIZE), GFP_KERNEL);
	ptes = kvzalloc(sizeof(pte_t) * (len / PAGE_SIZE), GFP_KERNEL);
	if (!ptes)
		return -ENOMEM;
	memset(ptes, 0, sizeof(pte_t) * (len / PAGE_SIZE));
	lru_add_drain();
	for (j = 0; j < len; j += PAGE_SIZE) {
		page = pages[i];
@@ -350,12 +349,12 @@ static unsigned long do_user_swap(struct mm_struct *mm,

	if (pages_dirty)
		new_addr_start = new_addr_start | USWAP_PAGES_DIRTY;
	kfree(ptes);
	kvfree(ptes);
	return new_addr_start;

out_recover:
	uswapout_recover(mm, old_addr_start, i, pages, new_addr_start, ptes);
	kfree(ptes);
	kvfree(ptes);
	return ret;
}

@@ -401,7 +400,7 @@ unsigned long uswap_mremap(unsigned long old_addr, unsigned long old_len,
	for (i = 0; i < len / PAGE_SIZE; i++)
		if (pages[i])
			put_page(pages[i]);
	kfree(pages);
	kvfree(pages);
	return ret;
}