Skip to content

Commit 5d8de29

Browse files
Matthew Wilcox (Oracle)akpm00
authored andcommitted
vmcore: convert copy_oldmem_page() to take an iov_iter
Patch series "Convert vmcore to use an iov_iter", v5. For some reason several people have been sending bad patches to fix compiler warnings in vmcore recently. Here's how it should be done. Compile-tested only on x86. As noted in the first patch, s390 should take this conversion a bit further, but I'm not inclined to do that work myself. This patch (of 3): Instead of passing in a 'buf' and 'userbuf' argument, pass in an iov_iter. s390 needs more work to pass the iov_iter down further, or refactor, but I'd be more comfortable if someone who can test on s390 did that work. It's more convenient to convert the whole of read_from_oldmem() to take an iov_iter at the same time, so rename it to read_from_oldmem_iter() and add a temporary read_from_oldmem() wrapper that creates an iov_iter. Link: https://lkml.kernel.org/r/20220408090636.560886-1-bhe@redhat.com Link: https://lkml.kernel.org/r/20220408090636.560886-2-bhe@redhat.com Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org> Signed-off-by: Baoquan He <bhe@redhat.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Cc: Heiko Carstens <hca@linux.ibm.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
1 parent 04d168c commit 5d8de29

File tree

12 files changed

+91
-260
lines changed

12 files changed

+91
-260
lines changed

arch/arm/kernel/crash_dump.c

Lines changed: 4 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -14,22 +14,10 @@
1414
#include <linux/crash_dump.h>
1515
#include <linux/uaccess.h>
1616
#include <linux/io.h>
17+
#include <linux/uio.h>
1718

18-
/**
19-
* copy_oldmem_page() - copy one page from old kernel memory
20-
* @pfn: page frame number to be copied
21-
* @buf: buffer where the copied page is placed
22-
* @csize: number of bytes to copy
23-
* @offset: offset in bytes into the page
24-
* @userbuf: if set, @buf is int he user address space
25-
*
26-
* This function copies one page from old kernel memory into buffer pointed by
27-
* @buf. If @buf is in userspace, set @userbuf to %1. Returns number of bytes
28-
* copied or negative error in case of failure.
29-
*/
30-
ssize_t copy_oldmem_page(unsigned long pfn, char *buf,
31-
size_t csize, unsigned long offset,
32-
int userbuf)
19+
ssize_t copy_oldmem_page(struct iov_iter *iter, unsigned long pfn,
20+
size_t csize, unsigned long offset)
3321
{
3422
void *vaddr;
3523

@@ -40,14 +28,7 @@ ssize_t copy_oldmem_page(unsigned long pfn, char *buf,
4028
if (!vaddr)
4129
return -ENOMEM;
4230

43-
if (userbuf) {
44-
if (copy_to_user(buf, vaddr + offset, csize)) {
45-
iounmap(vaddr);
46-
return -EFAULT;
47-
}
48-
} else {
49-
memcpy(buf, vaddr + offset, csize);
50-
}
31+
csize = copy_to_iter(vaddr + offset, csize, iter);
5132

5233
iounmap(vaddr);
5334
return csize;

arch/arm64/kernel/crash_dump.c

Lines changed: 4 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -9,25 +9,11 @@
99
#include <linux/crash_dump.h>
1010
#include <linux/errno.h>
1111
#include <linux/io.h>
12-
#include <linux/memblock.h>
13-
#include <linux/uaccess.h>
12+
#include <linux/uio.h>
1413
#include <asm/memory.h>
1514

16-
/**
17-
* copy_oldmem_page() - copy one page from old kernel memory
18-
* @pfn: page frame number to be copied
19-
* @buf: buffer where the copied page is placed
20-
* @csize: number of bytes to copy
21-
* @offset: offset in bytes into the page
22-
* @userbuf: if set, @buf is in a user address space
23-
*
24-
* This function copies one page from old kernel memory into buffer pointed by
25-
* @buf. If @buf is in userspace, set @userbuf to %1. Returns number of bytes
26-
* copied or negative error in case of failure.
27-
*/
28-
ssize_t copy_oldmem_page(unsigned long pfn, char *buf,
29-
size_t csize, unsigned long offset,
30-
int userbuf)
15+
ssize_t copy_oldmem_page(struct iov_iter *iter, unsigned long pfn,
16+
size_t csize, unsigned long offset)
3117
{
3218
void *vaddr;
3319

@@ -38,14 +24,7 @@ ssize_t copy_oldmem_page(unsigned long pfn, char *buf,
3824
if (!vaddr)
3925
return -ENOMEM;
4026

41-
if (userbuf) {
42-
if (copy_to_user((char __user *)buf, vaddr + offset, csize)) {
43-
memunmap(vaddr);
44-
return -EFAULT;
45-
}
46-
} else {
47-
memcpy(buf, vaddr + offset, csize);
48-
}
27+
csize = copy_to_iter(vaddr + offset, csize, iter);
4928

5029
memunmap(vaddr);
5130

arch/ia64/kernel/crash_dump.c

Lines changed: 4 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -10,42 +10,18 @@
1010
#include <linux/errno.h>
1111
#include <linux/types.h>
1212
#include <linux/crash_dump.h>
13-
13+
#include <linux/uio.h>
1414
#include <asm/page.h>
15-
#include <linux/uaccess.h>
1615

17-
/**
18-
* copy_oldmem_page - copy one page from "oldmem"
19-
* @pfn: page frame number to be copied
20-
* @buf: target memory address for the copy; this can be in kernel address
21-
* space or user address space (see @userbuf)
22-
* @csize: number of bytes to copy
23-
* @offset: offset in bytes into the page (based on pfn) to begin the copy
24-
* @userbuf: if set, @buf is in user address space, use copy_to_user(),
25-
* otherwise @buf is in kernel address space, use memcpy().
26-
*
27-
* Copy a page from "oldmem". For this page, there is no pte mapped
28-
* in the current kernel. We stitch up a pte, similar to kmap_atomic.
29-
*
30-
* Calling copy_to_user() in atomic context is not desirable. Hence first
31-
* copying the data to a pre-allocated kernel page and then copying to user
32-
* space in non-atomic context.
33-
*/
34-
ssize_t
35-
copy_oldmem_page(unsigned long pfn, char *buf,
36-
size_t csize, unsigned long offset, int userbuf)
16+
ssize_t copy_oldmem_page(struct iov_iter *iter, unsigned long pfn,
17+
size_t csize, unsigned long offset)
3718
{
3819
void *vaddr;
3920

4021
if (!csize)
4122
return 0;
4223
vaddr = __va(pfn<<PAGE_SHIFT);
43-
if (userbuf) {
44-
if (copy_to_user(buf, (vaddr + offset), csize)) {
45-
return -EFAULT;
46-
}
47-
} else
48-
memcpy(buf, (vaddr + offset), csize);
24+
csize = copy_to_iter(vaddr + offset, csize, iter);
4925
return csize;
5026
}
5127

arch/mips/kernel/crash_dump.c

Lines changed: 4 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,18 @@
11
// SPDX-License-Identifier: GPL-2.0
22
#include <linux/highmem.h>
33
#include <linux/crash_dump.h>
4+
#include <linux/uio.h>
45

5-
/**
6-
* copy_oldmem_page - copy one page from "oldmem"
7-
* @pfn: page frame number to be copied
8-
* @buf: target memory address for the copy; this can be in kernel address
9-
* space or user address space (see @userbuf)
10-
* @csize: number of bytes to copy
11-
* @offset: offset in bytes into the page (based on pfn) to begin the copy
12-
* @userbuf: if set, @buf is in user address space, use copy_to_user(),
13-
* otherwise @buf is in kernel address space, use memcpy().
14-
*
15-
* Copy a page from "oldmem". For this page, there is no pte mapped
16-
* in the current kernel.
17-
*/
18-
ssize_t copy_oldmem_page(unsigned long pfn, char *buf,
19-
size_t csize, unsigned long offset, int userbuf)
6+
ssize_t copy_oldmem_page(struct iov_iter *iter, unsigned long pfn,
7+
size_t csize, unsigned long offset)
208
{
219
void *vaddr;
2210

2311
if (!csize)
2412
return 0;
2513

2614
vaddr = kmap_local_pfn(pfn);
27-
28-
if (!userbuf) {
29-
memcpy(buf, vaddr + offset, csize);
30-
} else {
31-
if (copy_to_user(buf, vaddr + offset, csize))
32-
csize = -EFAULT;
33-
}
34-
15+
csize = copy_to_iter(vaddr + offset, csize, iter);
3516
kunmap_local(vaddr);
3617

3718
return csize;

arch/powerpc/kernel/crash_dump.c

Lines changed: 5 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
#include <asm/kdump.h>
1717
#include <asm/prom.h>
1818
#include <asm/firmware.h>
19-
#include <linux/uaccess.h>
19+
#include <linux/uio.h>
2020
#include <asm/rtas.h>
2121
#include <asm/inst.h>
2222

@@ -68,33 +68,8 @@ void __init setup_kdump_trampoline(void)
6868
}
6969
#endif /* CONFIG_NONSTATIC_KERNEL */
7070

71-
static size_t copy_oldmem_vaddr(void *vaddr, char *buf, size_t csize,
72-
unsigned long offset, int userbuf)
73-
{
74-
if (userbuf) {
75-
if (copy_to_user((char __user *)buf, (vaddr + offset), csize))
76-
return -EFAULT;
77-
} else
78-
memcpy(buf, (vaddr + offset), csize);
79-
80-
return csize;
81-
}
82-
83-
/**
84-
* copy_oldmem_page - copy one page from "oldmem"
85-
* @pfn: page frame number to be copied
86-
* @buf: target memory address for the copy; this can be in kernel address
87-
* space or user address space (see @userbuf)
88-
* @csize: number of bytes to copy
89-
* @offset: offset in bytes into the page (based on pfn) to begin the copy
90-
* @userbuf: if set, @buf is in user address space, use copy_to_user(),
91-
* otherwise @buf is in kernel address space, use memcpy().
92-
*
93-
* Copy a page from "oldmem". For this page, there is no pte mapped
94-
* in the current kernel. We stitch up a pte, similar to kmap_atomic.
95-
*/
96-
ssize_t copy_oldmem_page(unsigned long pfn, char *buf,
97-
size_t csize, unsigned long offset, int userbuf)
71+
ssize_t copy_oldmem_page(struct iov_iter *iter, unsigned long pfn,
72+
size_t csize, unsigned long offset)
9873
{
9974
void *vaddr;
10075
phys_addr_t paddr;
@@ -107,10 +82,10 @@ ssize_t copy_oldmem_page(unsigned long pfn, char *buf,
10782

10883
if (memblock_is_region_memory(paddr, csize)) {
10984
vaddr = __va(paddr);
110-
csize = copy_oldmem_vaddr(vaddr, buf, csize, offset, userbuf);
85+
csize = copy_to_iter(vaddr + offset, csize, iter);
11186
} else {
11287
vaddr = ioremap_cache(paddr, PAGE_SIZE);
113-
csize = copy_oldmem_vaddr(vaddr, buf, csize, offset, userbuf);
88+
csize = copy_to_iter(vaddr + offset, csize, iter);
11489
iounmap(vaddr);
11590
}
11691

arch/riscv/kernel/crash_dump.c

Lines changed: 4 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,10 @@
77

88
#include <linux/crash_dump.h>
99
#include <linux/io.h>
10+
#include <linux/uio.h>
1011

11-
/**
12-
* copy_oldmem_page() - copy one page from old kernel memory
13-
* @pfn: page frame number to be copied
14-
* @buf: buffer where the copied page is placed
15-
* @csize: number of bytes to copy
16-
* @offset: offset in bytes into the page
17-
* @userbuf: if set, @buf is in a user address space
18-
*
19-
* This function copies one page from old kernel memory into buffer pointed by
20-
* @buf. If @buf is in userspace, set @userbuf to %1. Returns number of bytes
21-
* copied or negative error in case of failure.
22-
*/
23-
ssize_t copy_oldmem_page(unsigned long pfn, char *buf,
24-
size_t csize, unsigned long offset,
25-
int userbuf)
12+
ssize_t copy_oldmem_page(struct iov_iter *iter, unsigned long pfn,
13+
size_t csize, unsigned long offset)
2614
{
2715
void *vaddr;
2816

@@ -33,13 +21,7 @@ ssize_t copy_oldmem_page(unsigned long pfn, char *buf,
3321
if (!vaddr)
3422
return -ENOMEM;
3523

36-
if (userbuf) {
37-
if (copy_to_user((char __user *)buf, vaddr + offset, csize)) {
38-
memunmap(vaddr);
39-
return -EFAULT;
40-
}
41-
} else
42-
memcpy(buf, vaddr + offset, csize);
24+
csize = copy_to_iter(vaddr + offset, csize, iter);
4325

4426
memunmap(vaddr);
4527
return csize;

arch/s390/kernel/crash_dump.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <linux/slab.h>
1616
#include <linux/memblock.h>
1717
#include <linux/elf.h>
18+
#include <linux/uio.h>
1819
#include <asm/asm-offsets.h>
1920
#include <asm/os_info.h>
2021
#include <asm/elf.h>
@@ -212,19 +213,21 @@ static int copy_oldmem_user(void __user *dst, unsigned long src, size_t count)
212213
/*
213214
* Copy one page from "oldmem"
214215
*/
215-
ssize_t copy_oldmem_page(unsigned long pfn, char *buf, size_t csize,
216-
unsigned long offset, int userbuf)
216+
ssize_t copy_oldmem_page(struct iov_iter *iter, unsigned long pfn, size_t csize,
217+
unsigned long offset)
217218
{
218219
unsigned long src;
219220
int rc;
220221

221222
if (!csize)
222223
return 0;
223224
src = pfn_to_phys(pfn) + offset;
224-
if (userbuf)
225-
rc = copy_oldmem_user((void __force __user *) buf, src, csize);
225+
226+
/* XXX: pass the iov_iter down to a common function */
227+
if (iter_is_iovec(iter))
228+
rc = copy_oldmem_user(iter->iov->iov_base, src, csize);
226229
else
227-
rc = copy_oldmem_kernel((void *) buf, src, csize);
230+
rc = copy_oldmem_kernel(iter->kvec->iov_base, src, csize);
228231
return rc;
229232
}
230233

arch/sh/kernel/crash_dump.c

Lines changed: 5 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -8,39 +8,20 @@
88
#include <linux/errno.h>
99
#include <linux/crash_dump.h>
1010
#include <linux/io.h>
11+
#include <linux/uio.h>
1112
#include <linux/uaccess.h>
1213

13-
/**
14-
* copy_oldmem_page - copy one page from "oldmem"
15-
* @pfn: page frame number to be copied
16-
* @buf: target memory address for the copy; this can be in kernel address
17-
* space or user address space (see @userbuf)
18-
* @csize: number of bytes to copy
19-
* @offset: offset in bytes into the page (based on pfn) to begin the copy
20-
* @userbuf: if set, @buf is in user address space, use copy_to_user(),
21-
* otherwise @buf is in kernel address space, use memcpy().
22-
*
23-
* Copy a page from "oldmem". For this page, there is no pte mapped
24-
* in the current kernel. We stitch up a pte, similar to kmap_atomic.
25-
*/
26-
ssize_t copy_oldmem_page(unsigned long pfn, char *buf,
27-
size_t csize, unsigned long offset, int userbuf)
14+
ssize_t copy_oldmem_page(struct iov_iter *iter, unsigned long pfn,
15+
size_t csize, unsigned long offset)
2816
{
2917
void __iomem *vaddr;
3018

3119
if (!csize)
3220
return 0;
3321

3422
vaddr = ioremap(pfn << PAGE_SHIFT, PAGE_SIZE);
35-
36-
if (userbuf) {
37-
if (copy_to_user((void __user *)buf, (vaddr + offset), csize)) {
38-
iounmap(vaddr);
39-
return -EFAULT;
40-
}
41-
} else
42-
memcpy(buf, (vaddr + offset), csize);
43-
23+
csize = copy_to_iter(vaddr + offset, csize, iter);
4424
iounmap(vaddr);
25+
4526
return csize;
4627
}

0 commit comments

Comments
 (0)