s390/crash: use static swap buffer for copy_to_user_real()
Currently a temporary page-size buffer is allocated for copying oldmem to user space. That limits copy_to_user_real() operation only to stages when virtual memory is available and still makes it possible to fail while the system is being dumped. Instead of reallocating single page on each copy_oldmem_page() iteration use a statically allocated buffer. This also paves the way for a further memcpy_real() rework where no swap buffer is needed altogether. Acked-by: Heiko Carstens <hca@linux.ibm.com> Tested-by: Alexander Egorenkov <egorenar@linux.ibm.com> Link: https://lore.kernel.org/r/334ed359680c4d45dd32feb104909f610312ef0f.1658206891.git.agordeev@linux.ibm.com Signed-off-by: Alexander Gordeev <agordeev@linux.ibm.com>
This commit is contained in:
@@ -53,6 +53,8 @@ struct save_area {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static LIST_HEAD(dump_save_areas);
|
static LIST_HEAD(dump_save_areas);
|
||||||
|
static DEFINE_MUTEX(memcpy_real_mutex);
|
||||||
|
static char memcpy_real_buf[PAGE_SIZE];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Allocate a save area
|
* Allocate a save area
|
||||||
@@ -178,25 +180,21 @@ int copy_oldmem_kernel(void *dst, unsigned long src, size_t count)
|
|||||||
*/
|
*/
|
||||||
static int copy_to_user_real(void __user *dest, unsigned long src, unsigned long count)
|
static int copy_to_user_real(void __user *dest, unsigned long src, unsigned long count)
|
||||||
{
|
{
|
||||||
int offs = 0, size, rc;
|
unsigned long offs = 0, size;
|
||||||
char *buf;
|
|
||||||
|
|
||||||
buf = (char *)__get_free_page(GFP_KERNEL);
|
mutex_lock(&memcpy_real_mutex);
|
||||||
if (!buf)
|
|
||||||
return -ENOMEM;
|
|
||||||
rc = -EFAULT;
|
|
||||||
while (offs < count) {
|
while (offs < count) {
|
||||||
size = min(PAGE_SIZE, count - offs);
|
size = min(PAGE_SIZE, count - offs);
|
||||||
if (memcpy_real(buf, src + offs, size))
|
if (memcpy_real(memcpy_real_buf, src + offs, size))
|
||||||
goto out;
|
break;
|
||||||
if (copy_to_user(dest + offs, buf, size))
|
if (copy_to_user(dest + offs, memcpy_real_buf, size))
|
||||||
goto out;
|
break;
|
||||||
offs += size;
|
offs += size;
|
||||||
}
|
}
|
||||||
rc = 0;
|
mutex_unlock(&memcpy_real_mutex);
|
||||||
out:
|
if (offs < count)
|
||||||
free_page((unsigned long)buf);
|
return -EFAULT;
|
||||||
return rc;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
Reference in New Issue
Block a user