All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/4] convert read_kcore(), vread() to use iterators
@ 2023-03-19  0:20 Lorenzo Stoakes
  2023-03-19  0:20 ` [PATCH 1/4] fs/proc/kcore: Avoid bounce buffer for ktext data Lorenzo Stoakes
                   ` (3 more replies)
  0 siblings, 4 replies; 14+ messages in thread
From: Lorenzo Stoakes @ 2023-03-19  0:20 UTC (permalink / raw)
  To: linux-mm, linux-kernel, linux-fsdevel, Andrew Morton
  Cc: Baoquan He, Uladzislau Rezki, Matthew Wilcox, David Hildenbrand,
	Liu Shixin, Jiri Olsa, Lorenzo Stoakes

While reviewing Baoquan's recent changes to permit vread() access to
vm_map_ram regions of vmalloc allocations, Willy pointed out [1] that it
would be nice to refactor vread() as a whole, since its only user is
read_kcore() and the existing form of vread() necessitates the use of a
bounce buffer.

This patch series does exactly that, as well as adjusting how we read the
kernel text section to avoid the use of a bounce buffer in this case as
well.

This patch series necessarily changes the locking used in vmalloc, however
tests indicate that this has very little impact on allocation performance
(test results are shown in the relevant patch).

This has been tested against the test case which motivated Baoquan's
changes in the first place [2] which continues to function correctly, as
do the vmalloc self tests.

[1] https://lore.kernel.org/all/Y8WfDSRkc%2FOHP3oD@casper.infradead.org/
[2] https://lore.kernel.org/all/87ilk6gos2.fsf@oracle.com/T/#u

Lorenzo Stoakes (4):
  fs/proc/kcore: Avoid bounce buffer for ktext data
  mm: vmalloc: use rwsem, mutex for vmap_area_lock and vmap_block->lock
  fs/proc/kcore: convert read_kcore() to read_kcore_iter()
  mm: vmalloc: convert vread() to vread_iter()

 fs/proc/kcore.c         |  84 +++++++------------
 include/linux/vmalloc.h |   3 +-
 mm/vmalloc.c            | 178 +++++++++++++++++++++-------------------
 3 files changed, 125 insertions(+), 140 deletions(-)

--
2.39.2

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 1/4] fs/proc/kcore: Avoid bounce buffer for ktext data
  2023-03-19  0:20 [PATCH 0/4] convert read_kcore(), vread() to use iterators Lorenzo Stoakes
@ 2023-03-19  0:20 ` Lorenzo Stoakes
  2023-03-19  0:20 ` [PATCH 2/4] mm: vmalloc: use rwsem, mutex for vmap_area_lock and vmap_block->lock Lorenzo Stoakes
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 14+ messages in thread
From: Lorenzo Stoakes @ 2023-03-19  0:20 UTC (permalink / raw)
  To: linux-mm, linux-kernel, linux-fsdevel, Andrew Morton
  Cc: Baoquan He, Uladzislau Rezki, Matthew Wilcox, David Hildenbrand,
	Liu Shixin, Jiri Olsa, Lorenzo Stoakes

Commit df04abfd181a ("fs/proc/kcore.c: Add bounce buffer for ktext data")
introduced the use of a bounce buffer to retrieve kernel text data for
/proc/kcore in order to avoid failures arising from hardened user copies
enabled by CONFIG_HARDENED_USERCOPY in check_kernel_text_object().

We can avoid doing this if instead of copy_to_user() we use _copy_to_user()
which bypasses the hardening check. This is more efficient than using a
bounce buffer and simplifies the code.

We do so as part an overall effort to eliminate bounce buffer usage in the
function with an eye to converting it an iterator read.

Signed-off-by: Lorenzo Stoakes <lstoakes@gmail.com>
---
 fs/proc/kcore.c | 17 +++++------------
 1 file changed, 5 insertions(+), 12 deletions(-)

diff --git a/fs/proc/kcore.c b/fs/proc/kcore.c
index 71157ee35c1a..556f310d6aa4 100644
--- a/fs/proc/kcore.c
+++ b/fs/proc/kcore.c
@@ -541,19 +541,12 @@ read_kcore(struct file *file, char __user *buffer, size_t buflen, loff_t *fpos)
 		case KCORE_VMEMMAP:
 		case KCORE_TEXT:
 			/*
-			 * Using bounce buffer to bypass the
-			 * hardened user copy kernel text checks.
+			 * We use _copy_to_user() to bypass usermode hardening
+			 * which would otherwise prevent this operation.
 			 */
-			if (copy_from_kernel_nofault(buf, (void *)start, tsz)) {
-				if (clear_user(buffer, tsz)) {
-					ret = -EFAULT;
-					goto out;
-				}
-			} else {
-				if (copy_to_user(buffer, buf, tsz)) {
-					ret = -EFAULT;
-					goto out;
-				}
+			if (_copy_to_user(buffer, (char *)start, tsz)) {
+				ret = -EFAULT;
+				goto out;
 			}
 			break;
 		default:
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 2/4] mm: vmalloc: use rwsem, mutex for vmap_area_lock and vmap_block->lock
  2023-03-19  0:20 [PATCH 0/4] convert read_kcore(), vread() to use iterators Lorenzo Stoakes
  2023-03-19  0:20 ` [PATCH 1/4] fs/proc/kcore: Avoid bounce buffer for ktext data Lorenzo Stoakes
@ 2023-03-19  0:20 ` Lorenzo Stoakes
  2023-03-19  0:20 ` [PATCH 3/4] fs/proc/kcore: convert read_kcore() to read_kcore_iter() Lorenzo Stoakes
  2023-03-19  0:20 ` [PATCH 4/4] mm: vmalloc: convert vread() to vread_iter() Lorenzo Stoakes
  3 siblings, 0 replies; 14+ messages in thread
From: Lorenzo Stoakes @ 2023-03-19  0:20 UTC (permalink / raw)
  To: linux-mm, linux-kernel, linux-fsdevel, Andrew Morton
  Cc: Baoquan He, Uladzislau Rezki, Matthew Wilcox, David Hildenbrand,
	Liu Shixin, Jiri Olsa, Lorenzo Stoakes

vmalloc() is, by design, not permitted to be used in atomic context and
already contains components which may sleep, so avoiding spin locks is not
a problem from the perspective of atomic context.

The global vmap_area_lock is held when the red/black tree rooted in
vmap_are_root is accessed and thus is rather long-held and under
potentially high contention. It is likely to be under contention for reads
rather than write, so replace it with a rwsem.

Each individual vmap_block->lock is likely to be held for less time but
under low contention, so a mutex is not an outrageous choice here.

A subset of test_vmalloc.sh performance results:-

fix_size_alloc_test             0.40%
full_fit_alloc_test		2.08%
long_busy_list_alloc_test	0.34%
random_size_alloc_test		-0.25%
random_size_align_alloc_test	0.06%
...
all tests cycles                0.2%

This represents a tiny reduction in performance that sits barely above
noise.

The reason for making this change is to build a basis for vread() to be
usable asynchronously, this eliminating the need for a bounce buffer when
copying data to userland in read_kcore() and allowing that to be converted
to an iterator form.

Signed-off-by: Lorenzo Stoakes <lstoakes@gmail.com>
---
 mm/vmalloc.c | 77 +++++++++++++++++++++++++++-------------------------
 1 file changed, 40 insertions(+), 37 deletions(-)

diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index 978194dc2bb8..c24b27664a97 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -40,6 +40,7 @@
 #include <linux/uaccess.h>
 #include <linux/hugetlb.h>
 #include <linux/sched/mm.h>
+#include <linux/rwsem.h>
 #include <asm/tlbflush.h>
 #include <asm/shmparam.h>
 
@@ -725,7 +726,7 @@ EXPORT_SYMBOL(vmalloc_to_pfn);
 #define DEBUG_AUGMENT_LOWEST_MATCH_CHECK 0
 
 
-static DEFINE_SPINLOCK(vmap_area_lock);
+static DECLARE_RWSEM(vmap_area_lock);
 static DEFINE_SPINLOCK(free_vmap_area_lock);
 /* Export for kexec only */
 LIST_HEAD(vmap_area_list);
@@ -1537,9 +1538,9 @@ static void free_vmap_area(struct vmap_area *va)
 	/*
 	 * Remove from the busy tree/list.
 	 */
-	spin_lock(&vmap_area_lock);
+	down_write(&vmap_area_lock);
 	unlink_va(va, &vmap_area_root);
-	spin_unlock(&vmap_area_lock);
+	up_write(&vmap_area_lock);
 
 	/*
 	 * Insert/Merge it back to the free tree/list.
@@ -1627,9 +1628,9 @@ static struct vmap_area *alloc_vmap_area(unsigned long size,
 	va->vm = NULL;
 	va->flags = va_flags;
 
-	spin_lock(&vmap_area_lock);
+	down_write(&vmap_area_lock);
 	insert_vmap_area(va, &vmap_area_root, &vmap_area_list);
-	spin_unlock(&vmap_area_lock);
+	up_write(&vmap_area_lock);
 
 	BUG_ON(!IS_ALIGNED(va->va_start, align));
 	BUG_ON(va->va_start < vstart);
@@ -1854,9 +1855,9 @@ struct vmap_area *find_vmap_area(unsigned long addr)
 {
 	struct vmap_area *va;
 
-	spin_lock(&vmap_area_lock);
+	down_read(&vmap_area_lock);
 	va = __find_vmap_area(addr, &vmap_area_root);
-	spin_unlock(&vmap_area_lock);
+	up_read(&vmap_area_lock);
 
 	return va;
 }
@@ -1865,11 +1866,11 @@ static struct vmap_area *find_unlink_vmap_area(unsigned long addr)
 {
 	struct vmap_area *va;
 
-	spin_lock(&vmap_area_lock);
+	down_write(&vmap_area_lock);
 	va = __find_vmap_area(addr, &vmap_area_root);
 	if (va)
 		unlink_va(va, &vmap_area_root);
-	spin_unlock(&vmap_area_lock);
+	up_write(&vmap_area_lock);
 
 	return va;
 }
@@ -1914,7 +1915,7 @@ struct vmap_block_queue {
 };
 
 struct vmap_block {
-	spinlock_t lock;
+	struct mutex lock;
 	struct vmap_area *va;
 	unsigned long free, dirty;
 	DECLARE_BITMAP(used_map, VMAP_BBMAP_BITS);
@@ -1991,7 +1992,7 @@ static void *new_vmap_block(unsigned int order, gfp_t gfp_mask)
 	}
 
 	vaddr = vmap_block_vaddr(va->va_start, 0);
-	spin_lock_init(&vb->lock);
+	mutex_init(&vb->lock);
 	vb->va = va;
 	/* At least something should be left free */
 	BUG_ON(VMAP_BBMAP_BITS <= (1UL << order));
@@ -2026,9 +2027,9 @@ static void free_vmap_block(struct vmap_block *vb)
 	tmp = xa_erase(&vmap_blocks, addr_to_vb_idx(vb->va->va_start));
 	BUG_ON(tmp != vb);
 
-	spin_lock(&vmap_area_lock);
+	down_write(&vmap_area_lock);
 	unlink_va(vb->va, &vmap_area_root);
-	spin_unlock(&vmap_area_lock);
+	up_write(&vmap_area_lock);
 
 	free_vmap_area_noflush(vb->va);
 	kfree_rcu(vb, rcu_head);
@@ -2047,7 +2048,7 @@ static void purge_fragmented_blocks(int cpu)
 		if (!(vb->free + vb->dirty == VMAP_BBMAP_BITS && vb->dirty != VMAP_BBMAP_BITS))
 			continue;
 
-		spin_lock(&vb->lock);
+		mutex_lock(&vb->lock);
 		if (vb->free + vb->dirty == VMAP_BBMAP_BITS && vb->dirty != VMAP_BBMAP_BITS) {
 			vb->free = 0; /* prevent further allocs after releasing lock */
 			vb->dirty = VMAP_BBMAP_BITS; /* prevent purging it again */
@@ -2056,10 +2057,10 @@ static void purge_fragmented_blocks(int cpu)
 			spin_lock(&vbq->lock);
 			list_del_rcu(&vb->free_list);
 			spin_unlock(&vbq->lock);
-			spin_unlock(&vb->lock);
+			mutex_unlock(&vb->lock);
 			list_add_tail(&vb->purge, &purge);
 		} else
-			spin_unlock(&vb->lock);
+			mutex_unlock(&vb->lock);
 	}
 	rcu_read_unlock();
 
@@ -2101,9 +2102,9 @@ static void *vb_alloc(unsigned long size, gfp_t gfp_mask)
 	list_for_each_entry_rcu(vb, &vbq->free, free_list) {
 		unsigned long pages_off;
 
-		spin_lock(&vb->lock);
+		mutex_lock(&vb->lock);
 		if (vb->free < (1UL << order)) {
-			spin_unlock(&vb->lock);
+			mutex_unlock(&vb->lock);
 			continue;
 		}
 
@@ -2117,7 +2118,7 @@ static void *vb_alloc(unsigned long size, gfp_t gfp_mask)
 			spin_unlock(&vbq->lock);
 		}
 
-		spin_unlock(&vb->lock);
+		mutex_unlock(&vb->lock);
 		break;
 	}
 
@@ -2144,16 +2145,16 @@ static void vb_free(unsigned long addr, unsigned long size)
 	order = get_order(size);
 	offset = (addr & (VMAP_BLOCK_SIZE - 1)) >> PAGE_SHIFT;
 	vb = xa_load(&vmap_blocks, addr_to_vb_idx(addr));
-	spin_lock(&vb->lock);
+	mutex_lock(&vb->lock);
 	bitmap_clear(vb->used_map, offset, (1UL << order));
-	spin_unlock(&vb->lock);
+	mutex_unlock(&vb->lock);
 
 	vunmap_range_noflush(addr, addr + size);
 
 	if (debug_pagealloc_enabled_static())
 		flush_tlb_kernel_range(addr, addr + size);
 
-	spin_lock(&vb->lock);
+	mutex_lock(&vb->lock);
 
 	/* Expand dirty range */
 	vb->dirty_min = min(vb->dirty_min, offset);
@@ -2162,10 +2163,10 @@ static void vb_free(unsigned long addr, unsigned long size)
 	vb->dirty += 1UL << order;
 	if (vb->dirty == VMAP_BBMAP_BITS) {
 		BUG_ON(vb->free);
-		spin_unlock(&vb->lock);
+		mutex_unlock(&vb->lock);
 		free_vmap_block(vb);
 	} else
-		spin_unlock(&vb->lock);
+		mutex_unlock(&vb->lock);
 }
 
 static void _vm_unmap_aliases(unsigned long start, unsigned long end, int flush)
@@ -2183,7 +2184,7 @@ static void _vm_unmap_aliases(unsigned long start, unsigned long end, int flush)
 
 		rcu_read_lock();
 		list_for_each_entry_rcu(vb, &vbq->free, free_list) {
-			spin_lock(&vb->lock);
+			mutex_lock(&vb->lock);
 			if (vb->dirty && vb->dirty != VMAP_BBMAP_BITS) {
 				unsigned long va_start = vb->va->va_start;
 				unsigned long s, e;
@@ -2196,7 +2197,7 @@ static void _vm_unmap_aliases(unsigned long start, unsigned long end, int flush)
 
 				flush = 1;
 			}
-			spin_unlock(&vb->lock);
+			mutex_unlock(&vb->lock);
 		}
 		rcu_read_unlock();
 	}
@@ -2451,9 +2452,9 @@ static inline void setup_vmalloc_vm_locked(struct vm_struct *vm,
 static void setup_vmalloc_vm(struct vm_struct *vm, struct vmap_area *va,
 			      unsigned long flags, const void *caller)
 {
-	spin_lock(&vmap_area_lock);
+	down_write(&vmap_area_lock);
 	setup_vmalloc_vm_locked(vm, va, flags, caller);
-	spin_unlock(&vmap_area_lock);
+	up_write(&vmap_area_lock);
 }
 
 static void clear_vm_uninitialized_flag(struct vm_struct *vm)
@@ -3507,9 +3508,9 @@ static void vmap_ram_vread(char *buf, char *addr, int count, unsigned long flags
 	if (!vb)
 		goto finished;
 
-	spin_lock(&vb->lock);
+	mutex_lock(&vb->lock);
 	if (bitmap_empty(vb->used_map, VMAP_BBMAP_BITS)) {
-		spin_unlock(&vb->lock);
+		mutex_unlock(&vb->lock);
 		goto finished;
 	}
 	for_each_set_bitrange(rs, re, vb->used_map, VMAP_BBMAP_BITS) {
@@ -3536,7 +3537,7 @@ static void vmap_ram_vread(char *buf, char *addr, int count, unsigned long flags
 		count -= n;
 	}
 unlock:
-	spin_unlock(&vb->lock);
+	mutex_unlock(&vb->lock);
 
 finished:
 	/* zero-fill the left dirty or free regions */
@@ -3576,13 +3577,15 @@ long vread(char *buf, char *addr, unsigned long count)
 	unsigned long buflen = count;
 	unsigned long n, size, flags;
 
+	might_sleep();
+
 	addr = kasan_reset_tag(addr);
 
 	/* Don't allow overflow */
 	if ((unsigned long) addr + count < count)
 		count = -(unsigned long) addr;
 
-	spin_lock(&vmap_area_lock);
+	down_read(&vmap_area_lock);
 	va = find_vmap_area_exceed_addr((unsigned long)addr);
 	if (!va)
 		goto finished;
@@ -3639,7 +3642,7 @@ long vread(char *buf, char *addr, unsigned long count)
 		count -= n;
 	}
 finished:
-	spin_unlock(&vmap_area_lock);
+	up_read(&vmap_area_lock);
 
 	if (buf == buf_start)
 		return 0;
@@ -3980,14 +3983,14 @@ struct vm_struct **pcpu_get_vm_areas(const unsigned long *offsets,
 	}
 
 	/* insert all vm's */
-	spin_lock(&vmap_area_lock);
+	down_write(&vmap_area_lock);
 	for (area = 0; area < nr_vms; area++) {
 		insert_vmap_area(vas[area], &vmap_area_root, &vmap_area_list);
 
 		setup_vmalloc_vm_locked(vms[area], vas[area], VM_ALLOC,
 				 pcpu_get_vm_areas);
 	}
-	spin_unlock(&vmap_area_lock);
+	up_write(&vmap_area_lock);
 
 	/*
 	 * Mark allocated areas as accessible. Do it now as a best-effort
@@ -4114,7 +4117,7 @@ static void *s_start(struct seq_file *m, loff_t *pos)
 	__acquires(&vmap_area_lock)
 {
 	mutex_lock(&vmap_purge_lock);
-	spin_lock(&vmap_area_lock);
+	down_read(&vmap_area_lock);
 
 	return seq_list_start(&vmap_area_list, *pos);
 }
@@ -4128,7 +4131,7 @@ static void s_stop(struct seq_file *m, void *p)
 	__releases(&vmap_area_lock)
 	__releases(&vmap_purge_lock)
 {
-	spin_unlock(&vmap_area_lock);
+	up_read(&vmap_area_lock);
 	mutex_unlock(&vmap_purge_lock);
 }
 
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 3/4] fs/proc/kcore: convert read_kcore() to read_kcore_iter()
  2023-03-19  0:20 [PATCH 0/4] convert read_kcore(), vread() to use iterators Lorenzo Stoakes
  2023-03-19  0:20 ` [PATCH 1/4] fs/proc/kcore: Avoid bounce buffer for ktext data Lorenzo Stoakes
  2023-03-19  0:20 ` [PATCH 2/4] mm: vmalloc: use rwsem, mutex for vmap_area_lock and vmap_block->lock Lorenzo Stoakes
@ 2023-03-19  0:20 ` Lorenzo Stoakes
  2023-03-19  0:20 ` [PATCH 4/4] mm: vmalloc: convert vread() to vread_iter() Lorenzo Stoakes
  3 siblings, 0 replies; 14+ messages in thread
From: Lorenzo Stoakes @ 2023-03-19  0:20 UTC (permalink / raw)
  To: linux-mm, linux-kernel, linux-fsdevel, Andrew Morton
  Cc: Baoquan He, Uladzislau Rezki, Matthew Wilcox, David Hildenbrand,
	Liu Shixin, Jiri Olsa, Lorenzo Stoakes

Now we have eliminated spinlocks from the vread() case, convert
read_kcore() to read_kcore_iter().

For the time being we still use a bounce buffer for vread(), however in the
next patch we will convert this to interact directly with the iterator and
eliminate the bounce buffer altogether.

Signed-off-by: Lorenzo Stoakes <lstoakes@gmail.com>
---
 fs/proc/kcore.c | 58 ++++++++++++++++++++++++-------------------------
 1 file changed, 29 insertions(+), 29 deletions(-)

diff --git a/fs/proc/kcore.c b/fs/proc/kcore.c
index 556f310d6aa4..25e0eeb8d498 100644
--- a/fs/proc/kcore.c
+++ b/fs/proc/kcore.c
@@ -24,7 +24,7 @@
 #include <linux/memblock.h>
 #include <linux/init.h>
 #include <linux/slab.h>
-#include <linux/uaccess.h>
+#include <linux/uio.h>
 #include <asm/io.h>
 #include <linux/list.h>
 #include <linux/ioport.h>
@@ -308,9 +308,12 @@ static void append_kcore_note(char *notes, size_t *i, const char *name,
 }
 
 static ssize_t
-read_kcore(struct file *file, char __user *buffer, size_t buflen, loff_t *fpos)
+read_kcore_iter(struct kiocb *iocb, struct iov_iter *iter)
 {
+	struct file *file = iocb->ki_filp;
 	char *buf = file->private_data;
+	loff_t *ppos = &iocb->ki_pos;
+
 	size_t phdrs_offset, notes_offset, data_offset;
 	size_t page_offline_frozen = 1;
 	size_t phdrs_len, notes_len;
@@ -318,6 +321,7 @@ read_kcore(struct file *file, char __user *buffer, size_t buflen, loff_t *fpos)
 	size_t tsz;
 	int nphdr;
 	unsigned long start;
+	size_t buflen = iov_iter_count(iter);
 	size_t orig_buflen = buflen;
 	int ret = 0;
 
@@ -333,7 +337,7 @@ read_kcore(struct file *file, char __user *buffer, size_t buflen, loff_t *fpos)
 	notes_offset = phdrs_offset + phdrs_len;
 
 	/* ELF file header. */
-	if (buflen && *fpos < sizeof(struct elfhdr)) {
+	if (buflen && *ppos < sizeof(struct elfhdr)) {
 		struct elfhdr ehdr = {
 			.e_ident = {
 				[EI_MAG0] = ELFMAG0,
@@ -355,19 +359,18 @@ read_kcore(struct file *file, char __user *buffer, size_t buflen, loff_t *fpos)
 			.e_phnum = nphdr,
 		};
 
-		tsz = min_t(size_t, buflen, sizeof(struct elfhdr) - *fpos);
-		if (copy_to_user(buffer, (char *)&ehdr + *fpos, tsz)) {
+		tsz = min_t(size_t, buflen, sizeof(struct elfhdr) - *ppos);
+		if (copy_to_iter((char *)&ehdr + *ppos, tsz, iter) != tsz) {
 			ret = -EFAULT;
 			goto out;
 		}
 
-		buffer += tsz;
 		buflen -= tsz;
-		*fpos += tsz;
+		*ppos += tsz;
 	}
 
 	/* ELF program headers. */
-	if (buflen && *fpos < phdrs_offset + phdrs_len) {
+	if (buflen && *ppos < phdrs_offset + phdrs_len) {
 		struct elf_phdr *phdrs, *phdr;
 
 		phdrs = kzalloc(phdrs_len, GFP_KERNEL);
@@ -397,22 +400,21 @@ read_kcore(struct file *file, char __user *buffer, size_t buflen, loff_t *fpos)
 			phdr++;
 		}
 
-		tsz = min_t(size_t, buflen, phdrs_offset + phdrs_len - *fpos);
-		if (copy_to_user(buffer, (char *)phdrs + *fpos - phdrs_offset,
-				 tsz)) {
+		tsz = min_t(size_t, buflen, phdrs_offset + phdrs_len - *ppos);
+		if (copy_to_iter((char *)phdrs + *ppos - phdrs_offset, tsz,
+				 iter) != tsz) {
 			kfree(phdrs);
 			ret = -EFAULT;
 			goto out;
 		}
 		kfree(phdrs);
 
-		buffer += tsz;
 		buflen -= tsz;
-		*fpos += tsz;
+		*ppos += tsz;
 	}
 
 	/* ELF note segment. */
-	if (buflen && *fpos < notes_offset + notes_len) {
+	if (buflen && *ppos < notes_offset + notes_len) {
 		struct elf_prstatus prstatus = {};
 		struct elf_prpsinfo prpsinfo = {
 			.pr_sname = 'R',
@@ -447,24 +449,23 @@ read_kcore(struct file *file, char __user *buffer, size_t buflen, loff_t *fpos)
 				  vmcoreinfo_data,
 				  min(vmcoreinfo_size, notes_len - i));
 
-		tsz = min_t(size_t, buflen, notes_offset + notes_len - *fpos);
-		if (copy_to_user(buffer, notes + *fpos - notes_offset, tsz)) {
+		tsz = min_t(size_t, buflen, notes_offset + notes_len - *ppos);
+		if (copy_to_iter(notes + *ppos - notes_offset, tsz, iter) != tsz) {
 			kfree(notes);
 			ret = -EFAULT;
 			goto out;
 		}
 		kfree(notes);
 
-		buffer += tsz;
 		buflen -= tsz;
-		*fpos += tsz;
+		*ppos += tsz;
 	}
 
 	/*
 	 * Check to see if our file offset matches with any of
 	 * the addresses in the elf_phdr on our list.
 	 */
-	start = kc_offset_to_vaddr(*fpos - data_offset);
+	start = kc_offset_to_vaddr(*ppos - data_offset);
 	if ((tsz = (PAGE_SIZE - (start & ~PAGE_MASK))) > buflen)
 		tsz = buflen;
 
@@ -497,7 +498,7 @@ read_kcore(struct file *file, char __user *buffer, size_t buflen, loff_t *fpos)
 		}
 
 		if (!m) {
-			if (clear_user(buffer, tsz)) {
+			if (iov_iter_zero(tsz, iter) != tsz) {
 				ret = -EFAULT;
 				goto out;
 			}
@@ -508,14 +509,14 @@ read_kcore(struct file *file, char __user *buffer, size_t buflen, loff_t *fpos)
 		case KCORE_VMALLOC:
 			vread(buf, (char *)start, tsz);
 			/* we have to zero-fill user buffer even if no read */
-			if (copy_to_user(buffer, buf, tsz)) {
+			if (copy_to_iter(buf, tsz, iter) != tsz) {
 				ret = -EFAULT;
 				goto out;
 			}
 			break;
 		case KCORE_USER:
 			/* User page is handled prior to normal kernel page: */
-			if (copy_to_user(buffer, (char *)start, tsz)) {
+			if (copy_to_iter((char *)start, tsz, iter) != tsz) {
 				ret = -EFAULT;
 				goto out;
 			}
@@ -531,7 +532,7 @@ read_kcore(struct file *file, char __user *buffer, size_t buflen, loff_t *fpos)
 			 */
 			if (!page || PageOffline(page) ||
 			    is_page_hwpoison(page) || !pfn_is_ram(pfn)) {
-				if (clear_user(buffer, tsz)) {
+				if (iov_iter_zero(tsz, iter) != tsz) {
 					ret = -EFAULT;
 					goto out;
 				}
@@ -541,25 +542,24 @@ read_kcore(struct file *file, char __user *buffer, size_t buflen, loff_t *fpos)
 		case KCORE_VMEMMAP:
 		case KCORE_TEXT:
 			/*
-			 * We use _copy_to_user() to bypass usermode hardening
+			 * We use _copy_to_iter() to bypass usermode hardening
 			 * which would otherwise prevent this operation.
 			 */
-			if (_copy_to_user(buffer, (char *)start, tsz)) {
+			if (_copy_to_iter((char *)start, tsz, iter) != tsz) {
 				ret = -EFAULT;
 				goto out;
 			}
 			break;
 		default:
 			pr_warn_once("Unhandled KCORE type: %d\n", m->type);
-			if (clear_user(buffer, tsz)) {
+			if (iov_iter_zero(tsz, iter) != tsz) {
 				ret = -EFAULT;
 				goto out;
 			}
 		}
 skip:
 		buflen -= tsz;
-		*fpos += tsz;
-		buffer += tsz;
+		*ppos += tsz;
 		start += tsz;
 		tsz = (buflen > PAGE_SIZE ? PAGE_SIZE : buflen);
 	}
@@ -603,7 +603,7 @@ static int release_kcore(struct inode *inode, struct file *file)
 }
 
 static const struct proc_ops kcore_proc_ops = {
-	.proc_read	= read_kcore,
+	.proc_read_iter	= read_kcore_iter,
 	.proc_open	= open_kcore,
 	.proc_release	= release_kcore,
 	.proc_lseek	= default_llseek,
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 4/4] mm: vmalloc: convert vread() to vread_iter()
  2023-03-19  0:20 [PATCH 0/4] convert read_kcore(), vread() to use iterators Lorenzo Stoakes
                   ` (2 preceding siblings ...)
  2023-03-19  0:20 ` [PATCH 3/4] fs/proc/kcore: convert read_kcore() to read_kcore_iter() Lorenzo Stoakes
@ 2023-03-19  0:20 ` Lorenzo Stoakes
  2023-03-19  1:46   ` kernel test robot
                     ` (2 more replies)
  3 siblings, 3 replies; 14+ messages in thread
From: Lorenzo Stoakes @ 2023-03-19  0:20 UTC (permalink / raw)
  To: linux-mm, linux-kernel, linux-fsdevel, Andrew Morton
  Cc: Baoquan He, Uladzislau Rezki, Matthew Wilcox, David Hildenbrand,
	Liu Shixin, Jiri Olsa, Lorenzo Stoakes

Having previously laid the foundation for converting vread() to an iterator
function, pull the trigger and do so.

This patch attempts to provide minimal refactoring and to reflect the
existing logic as best we can, with the exception of aligned_vread_iter()
which drops the use of the deprecated kmap_atomic() in favour of
kmap_local_page().

All existing logic to zero portions of memory not read remain and there
should be no functional difference other than a performance improvement in
/proc/kcore access to vmalloc regions.

Now we have discarded with the need for a bounce buffer at all in
read_kcore_iter(), we dispense with the one allocated there altogether.

Signed-off-by: Lorenzo Stoakes <lstoakes@gmail.com>
---
 fs/proc/kcore.c         |  21 +--------
 include/linux/vmalloc.h |   3 +-
 mm/vmalloc.c            | 101 +++++++++++++++++++++-------------------
 3 files changed, 57 insertions(+), 68 deletions(-)

diff --git a/fs/proc/kcore.c b/fs/proc/kcore.c
index 25e0eeb8d498..8a07f04c9203 100644
--- a/fs/proc/kcore.c
+++ b/fs/proc/kcore.c
@@ -307,13 +307,9 @@ static void append_kcore_note(char *notes, size_t *i, const char *name,
 	*i = ALIGN(*i + descsz, 4);
 }
 
-static ssize_t
-read_kcore_iter(struct kiocb *iocb, struct iov_iter *iter)
+static ssize_t read_kcore_iter(struct kiocb *iocb, struct iov_iter *iter)
 {
-	struct file *file = iocb->ki_filp;
-	char *buf = file->private_data;
 	loff_t *ppos = &iocb->ki_pos;
-
 	size_t phdrs_offset, notes_offset, data_offset;
 	size_t page_offline_frozen = 1;
 	size_t phdrs_len, notes_len;
@@ -507,9 +503,7 @@ read_kcore_iter(struct kiocb *iocb, struct iov_iter *iter)
 
 		switch (m->type) {
 		case KCORE_VMALLOC:
-			vread(buf, (char *)start, tsz);
-			/* we have to zero-fill user buffer even if no read */
-			if (copy_to_iter(buf, tsz, iter) != tsz) {
+			if (vread_iter((char *)start, tsz, iter) != tsz) {
 				ret = -EFAULT;
 				goto out;
 			}
@@ -582,10 +576,6 @@ static int open_kcore(struct inode *inode, struct file *filp)
 	if (ret)
 		return ret;
 
-	filp->private_data = kmalloc(PAGE_SIZE, GFP_KERNEL);
-	if (!filp->private_data)
-		return -ENOMEM;
-
 	if (kcore_need_update)
 		kcore_update_ram();
 	if (i_size_read(inode) != proc_root_kcore->size) {
@@ -596,16 +586,9 @@ static int open_kcore(struct inode *inode, struct file *filp)
 	return 0;
 }
 
-static int release_kcore(struct inode *inode, struct file *file)
-{
-	kfree(file->private_data);
-	return 0;
-}
-
 static const struct proc_ops kcore_proc_ops = {
 	.proc_read_iter	= read_kcore_iter,
 	.proc_open	= open_kcore,
-	.proc_release	= release_kcore,
 	.proc_lseek	= default_llseek,
 };
 
diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h
index 69250efa03d1..f70ebdf21f22 100644
--- a/include/linux/vmalloc.h
+++ b/include/linux/vmalloc.h
@@ -9,6 +9,7 @@
 #include <asm/page.h>		/* pgprot_t */
 #include <linux/rbtree.h>
 #include <linux/overflow.h>
+#include <linux/uio.h>
 
 #include <asm/vmalloc.h>
 
@@ -251,7 +252,7 @@ static inline void set_vm_flush_reset_perms(void *addr)
 #endif
 
 /* for /proc/kcore */
-extern long vread(char *buf, char *addr, unsigned long count);
+extern long vread_iter(char *addr, size_t count, struct iov_iter *iter);
 
 /*
  *	Internals.  Don't use..
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index c24b27664a97..3a32754266dc 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -37,7 +37,6 @@
 #include <linux/rbtree_augmented.h>
 #include <linux/overflow.h>
 #include <linux/pgtable.h>
-#include <linux/uaccess.h>
 #include <linux/hugetlb.h>
 #include <linux/sched/mm.h>
 #include <linux/rwsem.h>
@@ -3446,20 +3445,20 @@ EXPORT_SYMBOL(vmalloc_32_user);
  * small helper routine , copy contents to buf from addr.
  * If the page is not present, fill zero.
  */
-
-static int aligned_vread(char *buf, char *addr, unsigned long count)
+static void aligned_vread_iter(char *addr, size_t count,
+			       struct iov_iter *iter)
 {
-	struct page *p;
-	int copied = 0;
+	struct page *page;
 
-	while (count) {
+	while (count > 0) {
 		unsigned long offset, length;
+		size_t copied = 0;
 
 		offset = offset_in_page(addr);
 		length = PAGE_SIZE - offset;
 		if (length > count)
 			length = count;
-		p = vmalloc_to_page(addr);
+		page = vmalloc_to_page(addr);
 		/*
 		 * To do safe access to this _mapped_ area, we need
 		 * lock. But adding lock here means that we need to add
@@ -3467,23 +3466,24 @@ static int aligned_vread(char *buf, char *addr, unsigned long count)
 		 * interface, rarely used. Instead of that, we'll use
 		 * kmap() and get small overhead in this access function.
 		 */
-		if (p) {
+		if (page) {
 			/* We can expect USER0 is not used -- see vread() */
-			void *map = kmap_atomic(p);
-			memcpy(buf, map + offset, length);
-			kunmap_atomic(map);
-		} else
-			memset(buf, 0, length);
+			void *map = kmap_local_page(page);
+
+			copied = copy_to_iter(map + offset, length, iter);
+			kunmap_local(map);
+		}
+
+		if (copied < length)
+			iov_iter_zero(length - copied, iter);
 
 		addr += length;
-		buf += length;
-		copied += length;
 		count -= length;
 	}
-	return copied;
 }
 
-static void vmap_ram_vread(char *buf, char *addr, int count, unsigned long flags)
+static void vmap_ram_vread_iter(char *addr, int count, unsigned long flags,
+				struct iov_iter *iter)
 {
 	char *start;
 	struct vmap_block *vb;
@@ -3496,7 +3496,7 @@ static void vmap_ram_vread(char *buf, char *addr, int count, unsigned long flags
 	 * handle it here.
 	 */
 	if (!(flags & VMAP_BLOCK)) {
-		aligned_vread(buf, addr, count);
+		aligned_vread_iter(addr, count, iter);
 		return;
 	}
 
@@ -3517,22 +3517,24 @@ static void vmap_ram_vread(char *buf, char *addr, int count, unsigned long flags
 		if (!count)
 			break;
 		start = vmap_block_vaddr(vb->va->va_start, rs);
-		while (addr < start) {
+
+		if (addr < start) {
+			size_t to_zero = min_t(size_t, start - addr, count);
+
+			iov_iter_zero(to_zero, iter);
+			addr += to_zero;
+			count -= (int)to_zero;
 			if (count == 0)
 				goto unlock;
-			*buf = '\0';
-			buf++;
-			addr++;
-			count--;
 		}
+
 		/*it could start reading from the middle of used region*/
 		offset = offset_in_page(addr);
 		n = ((re - rs + 1) << PAGE_SHIFT) - offset;
 		if (n > count)
 			n = count;
-		aligned_vread(buf, start+offset, n);
+		aligned_vread_iter(start + offset, n, iter);
 
-		buf += n;
 		addr += n;
 		count -= n;
 	}
@@ -3541,15 +3543,15 @@ static void vmap_ram_vread(char *buf, char *addr, int count, unsigned long flags
 
 finished:
 	/* zero-fill the left dirty or free regions */
-	if (count)
-		memset(buf, 0, count);
+	if (count > 0)
+		iov_iter_zero(count, iter);
 }
 
 /**
- * vread() - read vmalloc area in a safe way.
- * @buf:     buffer for reading data
- * @addr:    vm address.
- * @count:   number of bytes to be read.
+ * vread_iter() - read vmalloc area in a safe way to an iterator.
+ * @addr:         vm address.
+ * @count:        number of bytes to be read.
+ * @iter:         the iterator to which data should be written.
  *
  * This function checks that addr is a valid vmalloc'ed area, and
  * copy data from that area to a given buffer. If the given memory range
@@ -3569,13 +3571,13 @@ static void vmap_ram_vread(char *buf, char *addr, int count, unsigned long flags
  * (same number as @count) or %0 if [addr...addr+count) doesn't
  * include any intersection with valid vmalloc area
  */
-long vread(char *buf, char *addr, unsigned long count)
+long vread_iter(char *addr, size_t count, struct iov_iter *iter)
 {
 	struct vmap_area *va;
 	struct vm_struct *vm;
-	char *vaddr, *buf_start = buf;
-	unsigned long buflen = count;
-	unsigned long n, size, flags;
+	char *vaddr;
+	size_t buflen = count;
+	size_t n, size, flags;
 
 	might_sleep();
 
@@ -3595,7 +3597,7 @@ long vread(char *buf, char *addr, unsigned long count)
 		goto finished;
 
 	list_for_each_entry_from(va, &vmap_area_list, list) {
-		if (!count)
+		if (count == 0)
 			break;
 
 		vm = va->vm;
@@ -3619,36 +3621,39 @@ long vread(char *buf, char *addr, unsigned long count)
 
 		if (addr >= vaddr + size)
 			continue;
-		while (addr < vaddr) {
+
+		if (addr < vaddr) {
+			size_t to_zero = min_t(size_t, vaddr - addr, count);
+
+			iov_iter_zero(to_zero, iter);
+			addr += to_zero;
+			count -= to_zero;
 			if (count == 0)
 				goto finished;
-			*buf = '\0';
-			buf++;
-			addr++;
-			count--;
 		}
+
 		n = vaddr + size - addr;
 		if (n > count)
 			n = count;
 
 		if (flags & VMAP_RAM)
-			vmap_ram_vread(buf, addr, n, flags);
+			vmap_ram_vread_iter(addr, n, flags, iter);
 		else if (!(vm->flags & VM_IOREMAP))
-			aligned_vread(buf, addr, n);
+			aligned_vread_iter(addr, n, iter);
 		else /* IOREMAP area is treated as memory hole */
-			memset(buf, 0, n);
-		buf += n;
+			iov_iter_zero(n, iter);
+
 		addr += n;
 		count -= n;
 	}
 finished:
 	up_read(&vmap_area_lock);
 
-	if (buf == buf_start)
+	if (count == buflen)
 		return 0;
 	/* zero-fill memory holes */
-	if (buf != buf_start + buflen)
-		memset(buf, 0, buflen - (buf - buf_start));
+	if (count > 0)
+		iov_iter_zero(count, iter);
 
 	return buflen;
 }
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH 4/4] mm: vmalloc: convert vread() to vread_iter()
  2023-03-19  0:20 ` [PATCH 4/4] mm: vmalloc: convert vread() to vread_iter() Lorenzo Stoakes
@ 2023-03-19  1:46   ` kernel test robot
  2023-03-19  6:08     ` Lorenzo Stoakes
  2023-03-19  2:16   ` kernel test robot
  2023-03-19  2:50   ` Matthew Wilcox
  2 siblings, 1 reply; 14+ messages in thread
From: kernel test robot @ 2023-03-19  1:46 UTC (permalink / raw)
  To: Lorenzo Stoakes, linux-mm, linux-kernel, linux-fsdevel, Andrew Morton
  Cc: oe-kbuild-all, Linux Memory Management List, Baoquan He,
	Uladzislau Rezki, Matthew Wilcox, David Hildenbrand, Liu Shixin,
	Jiri Olsa, Lorenzo Stoakes

Hi Lorenzo,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on akpm-mm/mm-everything]
[also build test WARNING on linus/master v6.3-rc2 next-20230317]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Lorenzo-Stoakes/fs-proc-kcore-Avoid-bounce-buffer-for-ktext-data/20230319-082147
base:   https://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm.git mm-everything
patch link:    https://lore.kernel.org/r/119871ea9507eac7be5d91db38acdb03981e049e.1679183626.git.lstoakes%40gmail.com
patch subject: [PATCH 4/4] mm: vmalloc: convert vread() to vread_iter()
config: sparc64-randconfig-r015-20230319 (https://download.01.org/0day-ci/archive/20230319/202303190922.Wk376onx-lkp@intel.com/config)
compiler: sparc64-linux-gcc (GCC) 12.1.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/intel-lab-lkp/linux/commit/a28f374d35bd294a529fcba0b69c8b0e2b66fa6c
        git remote add linux-review https://github.com/intel-lab-lkp/linux
        git fetch --no-tags linux-review Lorenzo-Stoakes/fs-proc-kcore-Avoid-bounce-buffer-for-ktext-data/20230319-082147
        git checkout a28f374d35bd294a529fcba0b69c8b0e2b66fa6c
        # save the config file
        mkdir build_dir && cp config build_dir/.config
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross W=1 O=build_dir ARCH=sparc64 olddefconfig
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross W=1 O=build_dir ARCH=sparc64 SHELL=/bin/bash arch/sparc/vdso/

If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <lkp@intel.com>
| Link: https://lore.kernel.org/oe-kbuild-all/202303190922.Wk376onx-lkp@intel.com/

All warnings (new ones prefixed by >>):

   In file included from include/linux/wait.h:11,
                    from include/linux/swait.h:8,
                    from include/linux/completion.h:12,
                    from include/linux/mm_types.h:14,
                    from include/linux/uio.h:10,
                    from include/linux/vmalloc.h:12,
                    from include/asm-generic/io.h:994,
                    from arch/sparc/include/asm/io.h:22,
                    from arch/sparc/vdso/vclock_gettime.c:18:
>> arch/sparc/include/asm/current.h:18:30: warning: call-clobbered register used for global register variable
      18 | register struct task_struct *current asm("g4");
         |                              ^~~~~~~
   arch/sparc/vdso/vclock_gettime.c:254:1: warning: no previous prototype for '__vdso_clock_gettime' [-Wmissing-prototypes]
     254 | __vdso_clock_gettime(clockid_t clock, struct __kernel_old_timespec *ts)
         | ^~~~~~~~~~~~~~~~~~~~
   arch/sparc/vdso/vclock_gettime.c:282:1: warning: no previous prototype for '__vdso_clock_gettime_stick' [-Wmissing-prototypes]
     282 | __vdso_clock_gettime_stick(clockid_t clock, struct __kernel_old_timespec *ts)
         | ^~~~~~~~~~~~~~~~~~~~~~~~~~
   arch/sparc/vdso/vclock_gettime.c:307:1: warning: no previous prototype for '__vdso_gettimeofday' [-Wmissing-prototypes]
     307 | __vdso_gettimeofday(struct __kernel_old_timeval *tv, struct timezone *tz)
         | ^~~~~~~~~~~~~~~~~~~
   arch/sparc/vdso/vclock_gettime.c:343:1: warning: no previous prototype for '__vdso_gettimeofday_stick' [-Wmissing-prototypes]
     343 | __vdso_gettimeofday_stick(struct __kernel_old_timeval *tv, struct timezone *tz)
         | ^~~~~~~~~~~~~~~~~~~~~~~~~


vim +18 arch/sparc/include/asm/current.h

^1da177e4c3f41 include/asm-sparc/current.h Linus Torvalds  2005-04-16  16  
ba89f59ab825d4 include/asm-sparc/current.h David S. Miller 2007-11-16  17  #ifdef CONFIG_SPARC64
ba89f59ab825d4 include/asm-sparc/current.h David S. Miller 2007-11-16 @18  register struct task_struct *current asm("g4");
ba89f59ab825d4 include/asm-sparc/current.h David S. Miller 2007-11-16  19  #endif
^1da177e4c3f41 include/asm-sparc/current.h Linus Torvalds  2005-04-16  20  

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 4/4] mm: vmalloc: convert vread() to vread_iter()
  2023-03-19  0:20 ` [PATCH 4/4] mm: vmalloc: convert vread() to vread_iter() Lorenzo Stoakes
  2023-03-19  1:46   ` kernel test robot
@ 2023-03-19  2:16   ` kernel test robot
  2023-03-19  6:03     ` Lorenzo Stoakes
  2023-03-19  2:50   ` Matthew Wilcox
  2 siblings, 1 reply; 14+ messages in thread
From: kernel test robot @ 2023-03-19  2:16 UTC (permalink / raw)
  To: Lorenzo Stoakes, linux-mm, linux-kernel, linux-fsdevel, Andrew Morton
  Cc: oe-kbuild-all, Linux Memory Management List, Baoquan He,
	Uladzislau Rezki, Matthew Wilcox, David Hildenbrand, Liu Shixin,
	Jiri Olsa, Lorenzo Stoakes

Hi Lorenzo,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on akpm-mm/mm-everything]
[also build test WARNING on linus/master v6.3-rc2 next-20230317]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Lorenzo-Stoakes/fs-proc-kcore-Avoid-bounce-buffer-for-ktext-data/20230319-082147
base:   https://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm.git mm-everything
patch link:    https://lore.kernel.org/r/119871ea9507eac7be5d91db38acdb03981e049e.1679183626.git.lstoakes%40gmail.com
patch subject: [PATCH 4/4] mm: vmalloc: convert vread() to vread_iter()
config: sh-randconfig-r013-20230319 (https://download.01.org/0day-ci/archive/20230319/202303191017.vsaaDpyw-lkp@intel.com/config)
compiler: sh4-linux-gcc (GCC) 12.1.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/intel-lab-lkp/linux/commit/a28f374d35bd294a529fcba0b69c8b0e2b66fa6c
        git remote add linux-review https://github.com/intel-lab-lkp/linux
        git fetch --no-tags linux-review Lorenzo-Stoakes/fs-proc-kcore-Avoid-bounce-buffer-for-ktext-data/20230319-082147
        git checkout a28f374d35bd294a529fcba0b69c8b0e2b66fa6c
        # save the config file
        mkdir build_dir && cp config build_dir/.config
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross W=1 O=build_dir ARCH=sh olddefconfig
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross W=1 O=build_dir ARCH=sh SHELL=/bin/bash

If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <lkp@intel.com>
| Link: https://lore.kernel.org/oe-kbuild-all/202303191017.vsaaDpyw-lkp@intel.com/

All warnings (new ones prefixed by >>):

>> mm/nommu.c:201:6: warning: no previous prototype for 'vread' [-Wmissing-prototypes]
     201 | long vread(char *buf, char *addr, unsigned long count)
         |      ^~~~~


vim +/vread +201 mm/nommu.c

^1da177e4c3f41 Linus Torvalds 2005-04-16  200  
^1da177e4c3f41 Linus Torvalds 2005-04-16 @201  long vread(char *buf, char *addr, unsigned long count)
^1da177e4c3f41 Linus Torvalds 2005-04-16  202  {
9bde916bc73255 Chen Gang      2013-07-03  203  	/* Don't allow overflow */
9bde916bc73255 Chen Gang      2013-07-03  204  	if ((unsigned long) buf + count < count)
9bde916bc73255 Chen Gang      2013-07-03  205  		count = -(unsigned long) buf;
9bde916bc73255 Chen Gang      2013-07-03  206  
^1da177e4c3f41 Linus Torvalds 2005-04-16  207  	memcpy(buf, addr, count);
^1da177e4c3f41 Linus Torvalds 2005-04-16  208  	return count;
^1da177e4c3f41 Linus Torvalds 2005-04-16  209  }
^1da177e4c3f41 Linus Torvalds 2005-04-16  210  

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 4/4] mm: vmalloc: convert vread() to vread_iter()
  2023-03-19  0:20 ` [PATCH 4/4] mm: vmalloc: convert vread() to vread_iter() Lorenzo Stoakes
  2023-03-19  1:46   ` kernel test robot
  2023-03-19  2:16   ` kernel test robot
@ 2023-03-19  2:50   ` Matthew Wilcox
  2023-03-19  6:16     ` Lorenzo Stoakes
  2023-03-19 22:28     ` David Laight
  2 siblings, 2 replies; 14+ messages in thread
From: Matthew Wilcox @ 2023-03-19  2:50 UTC (permalink / raw)
  To: Lorenzo Stoakes
  Cc: linux-mm, linux-kernel, linux-fsdevel, Andrew Morton, Baoquan He,
	Uladzislau Rezki, David Hildenbrand, Liu Shixin, Jiri Olsa

On Sun, Mar 19, 2023 at 12:20:12AM +0000, Lorenzo Stoakes wrote:
>  /* for /proc/kcore */
> -extern long vread(char *buf, char *addr, unsigned long count);
> +extern long vread_iter(char *addr, size_t count, struct iov_iter *iter);

I don't love the order of the arguments here.  Usually we follow
memcpy() and have (dst, src, len).  This sometimes gets a bit more
complex when either src or dst need two arguments, but that's not the
case here.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 4/4] mm: vmalloc: convert vread() to vread_iter()
  2023-03-19  2:16   ` kernel test robot
@ 2023-03-19  6:03     ` Lorenzo Stoakes
  0 siblings, 0 replies; 14+ messages in thread
From: Lorenzo Stoakes @ 2023-03-19  6:03 UTC (permalink / raw)
  To: kernel test robot
  Cc: linux-mm, linux-kernel, linux-fsdevel, Andrew Morton,
	oe-kbuild-all, Baoquan He, Uladzislau Rezki, Matthew Wilcox,
	David Hildenbrand, Liu Shixin, Jiri Olsa

On Sun, Mar 19, 2023 at 10:16:59AM +0800, kernel test robot wrote:
> Hi Lorenzo,
>
> Thank you for the patch! Perhaps something to improve:
>
> [auto build test WARNING on akpm-mm/mm-everything]
> [also build test WARNING on linus/master v6.3-rc2 next-20230317]
> [If your patch is applied to the wrong git tree, kindly drop us a note.
> And when submitting patch, we suggest to use '--base' as documented in
> https://git-scm.com/docs/git-format-patch#_base_tree_information]
>
> url:    https://github.com/intel-lab-lkp/linux/commits/Lorenzo-Stoakes/fs-proc-kcore-Avoid-bounce-buffer-for-ktext-data/20230319-082147
> base:   https://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm.git mm-everything
> patch link:    https://lore.kernel.org/r/119871ea9507eac7be5d91db38acdb03981e049e.1679183626.git.lstoakes%40gmail.com
> patch subject: [PATCH 4/4] mm: vmalloc: convert vread() to vread_iter()
> config: sh-randconfig-r013-20230319 (https://download.01.org/0day-ci/archive/20230319/202303191017.vsaaDpyw-lkp@intel.com/config)
> compiler: sh4-linux-gcc (GCC) 12.1.0
> reproduce (this is a W=1 build):
>         wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
>         chmod +x ~/bin/make.cross
>         # https://github.com/intel-lab-lkp/linux/commit/a28f374d35bd294a529fcba0b69c8b0e2b66fa6c
>         git remote add linux-review https://github.com/intel-lab-lkp/linux
>         git fetch --no-tags linux-review Lorenzo-Stoakes/fs-proc-kcore-Avoid-bounce-buffer-for-ktext-data/20230319-082147
>         git checkout a28f374d35bd294a529fcba0b69c8b0e2b66fa6c
>         # save the config file
>         mkdir build_dir && cp config build_dir/.config
>         COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross W=1 O=build_dir ARCH=sh olddefconfig
>         COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross W=1 O=build_dir ARCH=sh SHELL=/bin/bash
>
> If you fix the issue, kindly add following tag where applicable
> | Reported-by: kernel test robot <lkp@intel.com>
> | Link: https://lore.kernel.org/oe-kbuild-all/202303191017.vsaaDpyw-lkp@intel.com/
>
> All warnings (new ones prefixed by >>):
>
> >> mm/nommu.c:201:6: warning: no previous prototype for 'vread' [-Wmissing-prototypes]
>      201 | long vread(char *buf, char *addr, unsigned long count)
>          |      ^~~~~
>

Ah sorry, I forgot to update the nommu stub, will respin with a fix.
>
> vim +/vread +201 mm/nommu.c
>
> ^1da177e4c3f41 Linus Torvalds 2005-04-16  200
> ^1da177e4c3f41 Linus Torvalds 2005-04-16 @201  long vread(char *buf, char *addr, unsigned long count)
> ^1da177e4c3f41 Linus Torvalds 2005-04-16  202  {
> 9bde916bc73255 Chen Gang      2013-07-03  203  	/* Don't allow overflow */
> 9bde916bc73255 Chen Gang      2013-07-03  204  	if ((unsigned long) buf + count < count)
> 9bde916bc73255 Chen Gang      2013-07-03  205  		count = -(unsigned long) buf;
> 9bde916bc73255 Chen Gang      2013-07-03  206
> ^1da177e4c3f41 Linus Torvalds 2005-04-16  207  	memcpy(buf, addr, count);
> ^1da177e4c3f41 Linus Torvalds 2005-04-16  208  	return count;
> ^1da177e4c3f41 Linus Torvalds 2005-04-16  209  }
> ^1da177e4c3f41 Linus Torvalds 2005-04-16  210
>
> --
> 0-DAY CI Kernel Test Service
> https://github.com/intel/lkp-tests

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 4/4] mm: vmalloc: convert vread() to vread_iter()
  2023-03-19  1:46   ` kernel test robot
@ 2023-03-19  6:08     ` Lorenzo Stoakes
  0 siblings, 0 replies; 14+ messages in thread
From: Lorenzo Stoakes @ 2023-03-19  6:08 UTC (permalink / raw)
  To: kernel test robot
  Cc: linux-mm, linux-kernel, linux-fsdevel, Andrew Morton,
	oe-kbuild-all, Baoquan He, Uladzislau Rezki, Matthew Wilcox,
	David Hildenbrand, Liu Shixin, Jiri Olsa

On Sun, Mar 19, 2023 at 09:46:03AM +0800, kernel test robot wrote:
> Hi Lorenzo,
>
> Thank you for the patch! Perhaps something to improve:
>
> [auto build test WARNING on akpm-mm/mm-everything]
> [also build test WARNING on linus/master v6.3-rc2 next-20230317]
> [If your patch is applied to the wrong git tree, kindly drop us a note.
> And when submitting patch, we suggest to use '--base' as documented in
> https://git-scm.com/docs/git-format-patch#_base_tree_information]
>
> url:    https://github.com/intel-lab-lkp/linux/commits/Lorenzo-Stoakes/fs-proc-kcore-Avoid-bounce-buffer-for-ktext-data/20230319-082147
> base:   https://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm.git mm-everything
> patch link:    https://lore.kernel.org/r/119871ea9507eac7be5d91db38acdb03981e049e.1679183626.git.lstoakes%40gmail.com
> patch subject: [PATCH 4/4] mm: vmalloc: convert vread() to vread_iter()
> config: sparc64-randconfig-r015-20230319 (https://download.01.org/0day-ci/archive/20230319/202303190922.Wk376onx-lkp@intel.com/config)
> compiler: sparc64-linux-gcc (GCC) 12.1.0
> reproduce (this is a W=1 build):
>         wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
>         chmod +x ~/bin/make.cross
>         # https://github.com/intel-lab-lkp/linux/commit/a28f374d35bd294a529fcba0b69c8b0e2b66fa6c
>         git remote add linux-review https://github.com/intel-lab-lkp/linux
>         git fetch --no-tags linux-review Lorenzo-Stoakes/fs-proc-kcore-Avoid-bounce-buffer-for-ktext-data/20230319-082147
>         git checkout a28f374d35bd294a529fcba0b69c8b0e2b66fa6c
>         # save the config file
>         mkdir build_dir && cp config build_dir/.config
>         COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross W=1 O=build_dir ARCH=sparc64 olddefconfig
>         COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross W=1 O=build_dir ARCH=sparc64 SHELL=/bin/bash arch/sparc/vdso/
>
> If you fix the issue, kindly add following tag where applicable
> | Reported-by: kernel test robot <lkp@intel.com>
> | Link: https://lore.kernel.org/oe-kbuild-all/202303190922.Wk376onx-lkp@intel.com/
>
> All warnings (new ones prefixed by >>):
>
>    In file included from include/linux/wait.h:11,
>                     from include/linux/swait.h:8,
>                     from include/linux/completion.h:12,
>                     from include/linux/mm_types.h:14,
>                     from include/linux/uio.h:10,
>                     from include/linux/vmalloc.h:12,
>                     from include/asm-generic/io.h:994,
>                     from arch/sparc/include/asm/io.h:22,
>                     from arch/sparc/vdso/vclock_gettime.c:18:
> >> arch/sparc/include/asm/current.h:18:30: warning: call-clobbered register used for global register variable
>       18 | register struct task_struct *current asm("g4");
>          |                              ^~~~~~~
>    arch/sparc/vdso/vclock_gettime.c:254:1: warning: no previous prototype for '__vdso_clock_gettime' [-Wmissing-prototypes]
>      254 | __vdso_clock_gettime(clockid_t clock, struct __kernel_old_timespec *ts)
>          | ^~~~~~~~~~~~~~~~~~~~
>    arch/sparc/vdso/vclock_gettime.c:282:1: warning: no previous prototype for '__vdso_clock_gettime_stick' [-Wmissing-prototypes]
>      282 | __vdso_clock_gettime_stick(clockid_t clock, struct __kernel_old_timespec *ts)
>          | ^~~~~~~~~~~~~~~~~~~~~~~~~~
>    arch/sparc/vdso/vclock_gettime.c:307:1: warning: no previous prototype for '__vdso_gettimeofday' [-Wmissing-prototypes]
>      307 | __vdso_gettimeofday(struct __kernel_old_timeval *tv, struct timezone *tz)
>          | ^~~~~~~~~~~~~~~~~~~
>    arch/sparc/vdso/vclock_gettime.c:343:1: warning: no previous prototype for '__vdso_gettimeofday_stick' [-Wmissing-prototypes]
>      343 | __vdso_gettimeofday_stick(struct __kernel_old_timeval *tv, struct timezone *tz)
>          | ^~~~~~~~~~~~~~~~~~~~~~~~~
>
>
> vim +18 arch/sparc/include/asm/current.h
>
> ^1da177e4c3f41 include/asm-sparc/current.h Linus Torvalds  2005-04-16  16
> ba89f59ab825d4 include/asm-sparc/current.h David S. Miller 2007-11-16  17  #ifdef CONFIG_SPARC64
> ba89f59ab825d4 include/asm-sparc/current.h David S. Miller 2007-11-16 @18  register struct task_struct *current asm("g4");
> ba89f59ab825d4 include/asm-sparc/current.h David S. Miller 2007-11-16  19  #endif
> ^1da177e4c3f41 include/asm-sparc/current.h Linus Torvalds  2005-04-16  20
>
> --
> 0-DAY CI Kernel Test Service
> https://github.com/intel/lkp-tests

This doesn't seem even vaguely related to this patchset, possibly my not
specifying that I am basing on mm-unstable may be a factor here.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 4/4] mm: vmalloc: convert vread() to vread_iter()
  2023-03-19  2:50   ` Matthew Wilcox
@ 2023-03-19  6:16     ` Lorenzo Stoakes
  2023-03-19 22:28     ` David Laight
  1 sibling, 0 replies; 14+ messages in thread
From: Lorenzo Stoakes @ 2023-03-19  6:16 UTC (permalink / raw)
  To: Matthew Wilcox
  Cc: linux-mm, linux-kernel, linux-fsdevel, Andrew Morton, Baoquan He,
	Uladzislau Rezki, David Hildenbrand, Liu Shixin, Jiri Olsa

On Sun, Mar 19, 2023 at 02:50:56AM +0000, Matthew Wilcox wrote:
> On Sun, Mar 19, 2023 at 12:20:12AM +0000, Lorenzo Stoakes wrote:
> >  /* for /proc/kcore */
> > -extern long vread(char *buf, char *addr, unsigned long count);
> > +extern long vread_iter(char *addr, size_t count, struct iov_iter *iter);
>
> I don't love the order of the arguments here.  Usually we follow
> memcpy() and have (dst, src, len).  This sometimes gets a bit more
> complex when either src or dst need two arguments, but that's not the
> case here.

Indeed it's not delightful, I did this purely to mimic the order of
copy_to_iter() and friends which place iter last, however on second thoughts I
think placing iter first would be better here where we have the freedom to order
things more sensibly.

I'll respin with a fix.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* RE: [PATCH 4/4] mm: vmalloc: convert vread() to vread_iter()
  2023-03-19  2:50   ` Matthew Wilcox
  2023-03-19  6:16     ` Lorenzo Stoakes
@ 2023-03-19 22:28     ` David Laight
  2023-03-20  8:30       ` Lorenzo Stoakes
  1 sibling, 1 reply; 14+ messages in thread
From: David Laight @ 2023-03-19 22:28 UTC (permalink / raw)
  To: 'Matthew Wilcox', Lorenzo Stoakes
  Cc: linux-mm, linux-kernel, linux-fsdevel, Andrew Morton, Baoquan He,
	Uladzislau Rezki, David Hildenbrand, Liu Shixin, Jiri Olsa

From: Matthew Wilcox
> Sent: 19 March 2023 02:51
> 
> On Sun, Mar 19, 2023 at 12:20:12AM +0000, Lorenzo Stoakes wrote:
> >  /* for /proc/kcore */
> > -extern long vread(char *buf, char *addr, unsigned long count);
> > +extern long vread_iter(char *addr, size_t count, struct iov_iter *iter);
> 
> I don't love the order of the arguments here.  Usually we follow
> memcpy() and have (dst, src, len).  This sometimes gets a bit more
> complex when either src or dst need two arguments, but that's not the
> case here.

And, if 'addr' is the source (which Matthew's comment implies)
it ought to be 'const char *' (or probably even 'const void *').

	David

-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK
Registration No: 1397386 (Wales)


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 4/4] mm: vmalloc: convert vread() to vread_iter()
  2023-03-19 22:28     ` David Laight
@ 2023-03-20  8:30       ` Lorenzo Stoakes
  0 siblings, 0 replies; 14+ messages in thread
From: Lorenzo Stoakes @ 2023-03-20  8:30 UTC (permalink / raw)
  To: David Laight
  Cc: 'Matthew Wilcox',
	linux-mm, linux-kernel, linux-fsdevel, Andrew Morton, Baoquan He,
	Uladzislau Rezki, David Hildenbrand, Liu Shixin, Jiri Olsa

On Sun, Mar 19, 2023 at 10:28:12PM +0000, David Laight wrote:
> From: Matthew Wilcox
> > Sent: 19 March 2023 02:51
> >
> > On Sun, Mar 19, 2023 at 12:20:12AM +0000, Lorenzo Stoakes wrote:
> > >  /* for /proc/kcore */
> > > -extern long vread(char *buf, char *addr, unsigned long count);
> > > +extern long vread_iter(char *addr, size_t count, struct iov_iter *iter);
> >
> > I don't love the order of the arguments here.  Usually we follow
> > memcpy() and have (dst, src, len).  This sometimes gets a bit more
> > complex when either src or dst need two arguments, but that's not the
> > case here.
>
> And, if 'addr' is the source (which Matthew's comment implies)
> it ought to be 'const char *' (or probably even 'const void *').
>

Ack, I'll update on the next respin.

> 	David
>
> -
> Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK
> Registration No: 1397386 (Wales)
>

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 4/4] mm: vmalloc: convert vread() to vread_iter()
@ 2023-03-19  4:40 kernel test robot
  0 siblings, 0 replies; 14+ messages in thread
From: kernel test robot @ 2023-03-19  4:40 UTC (permalink / raw)
  To: oe-kbuild; +Cc: lkp, Dan Carpenter

BCC: lkp@intel.com
CC: oe-kbuild-all@lists.linux.dev
In-Reply-To: <119871ea9507eac7be5d91db38acdb03981e049e.1679183626.git.lstoakes@gmail.com>
References: <119871ea9507eac7be5d91db38acdb03981e049e.1679183626.git.lstoakes@gmail.com>
TO: Lorenzo Stoakes <lstoakes@gmail.com>
TO: linux-mm@kvack.org
TO: linux-kernel@vger.kernel.org
TO: linux-fsdevel@vger.kernel.org
TO: Andrew Morton <akpm@linux-foundation.org>
CC: Linux Memory Management List <linux-mm@kvack.org>
CC: Baoquan He <bhe@redhat.com>
CC: Uladzislau Rezki <urezki@gmail.com>
CC: Matthew Wilcox <willy@infradead.org>
CC: David Hildenbrand <david@redhat.com>
CC: Liu Shixin <liushixin2@huawei.com>
CC: Jiri Olsa <jolsa@kernel.org>
CC: Lorenzo Stoakes <lstoakes@gmail.com>

Hi Lorenzo,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on akpm-mm/mm-everything]
[also build test WARNING on linus/master v6.3-rc2 next-20230317]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Lorenzo-Stoakes/fs-proc-kcore-Avoid-bounce-buffer-for-ktext-data/20230319-082147
base:   https://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm.git mm-everything
patch link:    https://lore.kernel.org/r/119871ea9507eac7be5d91db38acdb03981e049e.1679183626.git.lstoakes%40gmail.com
patch subject: [PATCH 4/4] mm: vmalloc: convert vread() to vread_iter()
:::::: branch date: 4 hours ago
:::::: commit date: 4 hours ago
config: i386-randconfig-m021 (https://download.01.org/0day-ci/archive/20230319/202303191246.PQAdsQGK-lkp@intel.com/config)
compiler: gcc-11 (Debian 11.3.0-8) 11.3.0

If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <lkp@intel.com>
| Reported-by: Dan Carpenter <error27@gmail.com>
| Link: https://lore.kernel.org/r/202303191246.PQAdsQGK-lkp@intel.com/

smatch warnings:
mm/vmalloc.c:3641 vread_iter() error: we previously assumed 'vm' could be null (see line 3620)

vim +/vm +3641 mm/vmalloc.c

06c8994626d1b7 Baoquan He              2023-02-06  3549  
d0107eb07320b5 KAMEZAWA Hiroyuki       2009-09-21  3550  /**
a28f374d35bd29 Lorenzo Stoakes         2023-03-19  3551   * vread_iter() - read vmalloc area in a safe way to an iterator.
d0107eb07320b5 KAMEZAWA Hiroyuki       2009-09-21  3552   * @addr:         vm address.
d0107eb07320b5 KAMEZAWA Hiroyuki       2009-09-21  3553   * @count:        number of bytes to be read.
a28f374d35bd29 Lorenzo Stoakes         2023-03-19  3554   * @iter:         the iterator to which data should be written.
d0107eb07320b5 KAMEZAWA Hiroyuki       2009-09-21  3555   *
d0107eb07320b5 KAMEZAWA Hiroyuki       2009-09-21  3556   * This function checks that addr is a valid vmalloc'ed area, and
d0107eb07320b5 KAMEZAWA Hiroyuki       2009-09-21  3557   * copy data from that area to a given buffer. If the given memory range
d0107eb07320b5 KAMEZAWA Hiroyuki       2009-09-21  3558   * of [addr...addr+count) includes some valid address, data is copied to
d0107eb07320b5 KAMEZAWA Hiroyuki       2009-09-21  3559   * proper area of @buf. If there are memory holes, they'll be zero-filled.
d0107eb07320b5 KAMEZAWA Hiroyuki       2009-09-21  3560   * IOREMAP area is treated as memory hole and no copy is done.
d0107eb07320b5 KAMEZAWA Hiroyuki       2009-09-21  3561   *
d0107eb07320b5 KAMEZAWA Hiroyuki       2009-09-21  3562   * If [addr...addr+count) doesn't includes any intersects with alive
a8e5202d09c1ba Cong Wang               2012-06-23  3563   * vm_struct area, returns 0. @buf should be kernel's buffer.
d0107eb07320b5 KAMEZAWA Hiroyuki       2009-09-21  3564   *
d0107eb07320b5 KAMEZAWA Hiroyuki       2009-09-21  3565   * Note: In usual ops, vread() is never necessary because the caller
d0107eb07320b5 KAMEZAWA Hiroyuki       2009-09-21  3566   * should know vmalloc() area is valid and can use memcpy().
d0107eb07320b5 KAMEZAWA Hiroyuki       2009-09-21  3567   * This is for routines which have to access vmalloc area without
bbcd53c9607135 David Hildenbrand       2021-05-06  3568   * any information, as /proc/kcore.
a862f68a8b3600 Mike Rapoport           2019-03-05  3569   *
a862f68a8b3600 Mike Rapoport           2019-03-05  3570   * Return: number of bytes for which addr and buf should be increased
a862f68a8b3600 Mike Rapoport           2019-03-05  3571   * (same number as @count) or %0 if [addr...addr+count) doesn't
a862f68a8b3600 Mike Rapoport           2019-03-05  3572   * include any intersection with valid vmalloc area
d0107eb07320b5 KAMEZAWA Hiroyuki       2009-09-21  3573   */
a28f374d35bd29 Lorenzo Stoakes         2023-03-19  3574  long vread_iter(char *addr, size_t count, struct iov_iter *iter)
^1da177e4c3f41 Linus Torvalds          2005-04-16  3575  {
e81ce85f960c2e Joonsoo Kim             2013-04-29  3576  	struct vmap_area *va;
e81ce85f960c2e Joonsoo Kim             2013-04-29  3577  	struct vm_struct *vm;
a28f374d35bd29 Lorenzo Stoakes         2023-03-19  3578  	char *vaddr;
a28f374d35bd29 Lorenzo Stoakes         2023-03-19  3579  	size_t buflen = count;
a28f374d35bd29 Lorenzo Stoakes         2023-03-19  3580  	size_t n, size, flags;
^1da177e4c3f41 Linus Torvalds          2005-04-16  3581  
f11743b68de8fc Lorenzo Stoakes         2023-03-19  3582  	might_sleep();
f11743b68de8fc Lorenzo Stoakes         2023-03-19  3583  
4aff1dc4fb3a5a Andrey Konovalov        2022-03-24  3584  	addr = kasan_reset_tag(addr);
4aff1dc4fb3a5a Andrey Konovalov        2022-03-24  3585  
^1da177e4c3f41 Linus Torvalds          2005-04-16  3586  	/* Don't allow overflow */
^1da177e4c3f41 Linus Torvalds          2005-04-16  3587  	if ((unsigned long) addr + count < count)
^1da177e4c3f41 Linus Torvalds          2005-04-16  3588  		count = -(unsigned long) addr;
^1da177e4c3f41 Linus Torvalds          2005-04-16  3589  
f11743b68de8fc Lorenzo Stoakes         2023-03-19  3590  	down_read(&vmap_area_lock);
f181234a5a21fd Chen Wandun             2021-09-02  3591  	va = find_vmap_area_exceed_addr((unsigned long)addr);
f608788cd2d6ca Serapheim Dimitropoulos 2021-04-29  3592  	if (!va)
f608788cd2d6ca Serapheim Dimitropoulos 2021-04-29  3593  		goto finished;
f181234a5a21fd Chen Wandun             2021-09-02  3594  
f181234a5a21fd Chen Wandun             2021-09-02  3595  	/* no intersects with alive vmap_area */
f181234a5a21fd Chen Wandun             2021-09-02  3596  	if ((unsigned long)addr + count <= va->va_start)
f181234a5a21fd Chen Wandun             2021-09-02  3597  		goto finished;
f181234a5a21fd Chen Wandun             2021-09-02  3598  
f608788cd2d6ca Serapheim Dimitropoulos 2021-04-29  3599  	list_for_each_entry_from(va, &vmap_area_list, list) {
a28f374d35bd29 Lorenzo Stoakes         2023-03-19  3600  		if (count == 0)
e81ce85f960c2e Joonsoo Kim             2013-04-29  3601  			break;
e81ce85f960c2e Joonsoo Kim             2013-04-29  3602  
06c8994626d1b7 Baoquan He              2023-02-06  3603  		vm = va->vm;
06c8994626d1b7 Baoquan He              2023-02-06  3604  		flags = va->flags & VMAP_FLAGS_MASK;
06c8994626d1b7 Baoquan He              2023-02-06  3605  		/*
06c8994626d1b7 Baoquan He              2023-02-06  3606  		 * VMAP_BLOCK indicates a sub-type of vm_map_ram area, need
06c8994626d1b7 Baoquan He              2023-02-06  3607  		 * be set together with VMAP_RAM.
06c8994626d1b7 Baoquan He              2023-02-06  3608  		 */
06c8994626d1b7 Baoquan He              2023-02-06  3609  		WARN_ON(flags == VMAP_BLOCK);
06c8994626d1b7 Baoquan He              2023-02-06  3610  
06c8994626d1b7 Baoquan He              2023-02-06  3611  		if (!vm && !flags)
e81ce85f960c2e Joonsoo Kim             2013-04-29  3612  			continue;
e81ce85f960c2e Joonsoo Kim             2013-04-29  3613  
30a7a9b17c4b03 Baoquan He              2023-02-06  3614  		if (vm && (vm->flags & VM_UNINITIALIZED))
30a7a9b17c4b03 Baoquan He              2023-02-06  3615  			continue;
30a7a9b17c4b03 Baoquan He              2023-02-06  3616  		/* Pair with smp_wmb() in clear_vm_uninitialized_flag() */
30a7a9b17c4b03 Baoquan He              2023-02-06  3617  		smp_rmb();
30a7a9b17c4b03 Baoquan He              2023-02-06  3618  
06c8994626d1b7 Baoquan He              2023-02-06  3619  		vaddr = (char *) va->va_start;
06c8994626d1b7 Baoquan He              2023-02-06 @3620  		size = vm ? get_vm_area_size(vm) : va_size(va);
06c8994626d1b7 Baoquan He              2023-02-06  3621  
06c8994626d1b7 Baoquan He              2023-02-06  3622  		if (addr >= vaddr + size)
^1da177e4c3f41 Linus Torvalds          2005-04-16  3623  			continue;
a28f374d35bd29 Lorenzo Stoakes         2023-03-19  3624  
a28f374d35bd29 Lorenzo Stoakes         2023-03-19  3625  		if (addr < vaddr) {
a28f374d35bd29 Lorenzo Stoakes         2023-03-19  3626  			size_t to_zero = min_t(size_t, vaddr - addr, count);
a28f374d35bd29 Lorenzo Stoakes         2023-03-19  3627  
a28f374d35bd29 Lorenzo Stoakes         2023-03-19  3628  			iov_iter_zero(to_zero, iter);
a28f374d35bd29 Lorenzo Stoakes         2023-03-19  3629  			addr += to_zero;
a28f374d35bd29 Lorenzo Stoakes         2023-03-19  3630  			count -= to_zero;
^1da177e4c3f41 Linus Torvalds          2005-04-16  3631  			if (count == 0)
^1da177e4c3f41 Linus Torvalds          2005-04-16  3632  				goto finished;
^1da177e4c3f41 Linus Torvalds          2005-04-16  3633  		}
a28f374d35bd29 Lorenzo Stoakes         2023-03-19  3634  
06c8994626d1b7 Baoquan He              2023-02-06  3635  		n = vaddr + size - addr;
d0107eb07320b5 KAMEZAWA Hiroyuki       2009-09-21  3636  		if (n > count)
d0107eb07320b5 KAMEZAWA Hiroyuki       2009-09-21  3637  			n = count;
06c8994626d1b7 Baoquan He              2023-02-06  3638  
06c8994626d1b7 Baoquan He              2023-02-06  3639  		if (flags & VMAP_RAM)
a28f374d35bd29 Lorenzo Stoakes         2023-03-19  3640  			vmap_ram_vread_iter(addr, n, flags, iter);
06c8994626d1b7 Baoquan He              2023-02-06 @3641  		else if (!(vm->flags & VM_IOREMAP))
a28f374d35bd29 Lorenzo Stoakes         2023-03-19  3642  			aligned_vread_iter(addr, n, iter);
d0107eb07320b5 KAMEZAWA Hiroyuki       2009-09-21  3643  		else /* IOREMAP area is treated as memory hole */
a28f374d35bd29 Lorenzo Stoakes         2023-03-19  3644  			iov_iter_zero(n, iter);
a28f374d35bd29 Lorenzo Stoakes         2023-03-19  3645  
d0107eb07320b5 KAMEZAWA Hiroyuki       2009-09-21  3646  		addr += n;
d0107eb07320b5 KAMEZAWA Hiroyuki       2009-09-21  3647  		count -= n;
^1da177e4c3f41 Linus Torvalds          2005-04-16  3648  	}
^1da177e4c3f41 Linus Torvalds          2005-04-16  3649  finished:
f11743b68de8fc Lorenzo Stoakes         2023-03-19  3650  	up_read(&vmap_area_lock);
d0107eb07320b5 KAMEZAWA Hiroyuki       2009-09-21  3651  
a28f374d35bd29 Lorenzo Stoakes         2023-03-19  3652  	if (count == buflen)
d0107eb07320b5 KAMEZAWA Hiroyuki       2009-09-21  3653  		return 0;
d0107eb07320b5 KAMEZAWA Hiroyuki       2009-09-21  3654  	/* zero-fill memory holes */
a28f374d35bd29 Lorenzo Stoakes         2023-03-19  3655  	if (count > 0)
a28f374d35bd29 Lorenzo Stoakes         2023-03-19  3656  		iov_iter_zero(count, iter);
d0107eb07320b5 KAMEZAWA Hiroyuki       2009-09-21  3657  
d0107eb07320b5 KAMEZAWA Hiroyuki       2009-09-21  3658  	return buflen;
^1da177e4c3f41 Linus Torvalds          2005-04-16  3659  }
^1da177e4c3f41 Linus Torvalds          2005-04-16  3660  

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2023-03-20  8:30 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-03-19  0:20 [PATCH 0/4] convert read_kcore(), vread() to use iterators Lorenzo Stoakes
2023-03-19  0:20 ` [PATCH 1/4] fs/proc/kcore: Avoid bounce buffer for ktext data Lorenzo Stoakes
2023-03-19  0:20 ` [PATCH 2/4] mm: vmalloc: use rwsem, mutex for vmap_area_lock and vmap_block->lock Lorenzo Stoakes
2023-03-19  0:20 ` [PATCH 3/4] fs/proc/kcore: convert read_kcore() to read_kcore_iter() Lorenzo Stoakes
2023-03-19  0:20 ` [PATCH 4/4] mm: vmalloc: convert vread() to vread_iter() Lorenzo Stoakes
2023-03-19  1:46   ` kernel test robot
2023-03-19  6:08     ` Lorenzo Stoakes
2023-03-19  2:16   ` kernel test robot
2023-03-19  6:03     ` Lorenzo Stoakes
2023-03-19  2:50   ` Matthew Wilcox
2023-03-19  6:16     ` Lorenzo Stoakes
2023-03-19 22:28     ` David Laight
2023-03-20  8:30       ` Lorenzo Stoakes
2023-03-19  4:40 kernel test robot

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.