* [PATCH v6 2/3] mm: memory: Add access_remote_vm_locked variant
2020-09-01 9:18 [PATCH v6 0/3] Anonymous VMA naming patches Sumit Semwal
@ 2020-09-01 9:19 ` Sumit Semwal
0 siblings, 0 replies; 2+ messages in thread
From: Sumit Semwal @ 2020-09-01 9:19 UTC (permalink / raw)
To: Andrew Morton, linux-mm, linux-kernel, Alexey Dobriyan,
Jonathan Corbet
Cc: Mauro Carvalho Chehab, Kees Cook, Michal Hocko, Colin Cross,
Alexey Gladkov, Matthew Wilcox, Jason Gunthorpe,
Kirill A . Shutemov, Michel Lespinasse, Michal Koutný,
Song Liu, Huang Ying, Vlastimil Babka, Yang Shi, chenqiwu,
Mathieu Desnoyers, John Hubbard, Mike Christie, Bart Van Assche,
Amit Pundir, Thomas Gleixner, Christian Brauner, Daniel Jordan,
Adrian Reber, Nicolas Viennot, Al Viro, Thomas Cedeno,
linux-fsdevel, John Stultz, Sumit Semwal
This allows accessing a remote vm while the mmap_lock is already
held by the caller.
While adding support for anonymous vma naming, show_map_vma()
needs to access the remote vm to get the name of the anonymous vma.
Since show_map_vma() already holds the mmap_lock, so this _locked
variant was required.
Signed-off-by: Sumit Semwal <sumit.semwal@linaro.org>
---
include/linux/mm.h | 2 ++
mm/memory.c | 49 ++++++++++++++++++++++++++++++++++++++++------
2 files changed, 45 insertions(+), 6 deletions(-)
diff --git a/include/linux/mm.h b/include/linux/mm.h
index ca6e6a81576b..e9212c0bb5ac 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -1708,6 +1708,8 @@ extern int access_remote_vm(struct mm_struct *mm, unsigned long addr,
void *buf, int len, unsigned int gup_flags);
extern int __access_remote_vm(struct task_struct *tsk, struct mm_struct *mm,
unsigned long addr, void *buf, int len, unsigned int gup_flags);
+extern int access_remote_vm_locked(struct mm_struct *mm, unsigned long addr,
+ void *buf, int len, unsigned int gup_flags);
long get_user_pages_remote(struct mm_struct *mm,
unsigned long start, unsigned long nr_pages,
diff --git a/mm/memory.c b/mm/memory.c
index 602f4283122f..207be99390e9 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -4726,17 +4726,17 @@ EXPORT_SYMBOL_GPL(generic_access_phys);
/*
* Access another process' address space as given in mm. If non-NULL, use the
* given task for page fault accounting.
+ * This variant assumes that the mmap_lock is already held by the caller, so
+ * doesn't take the mmap_lock.
*/
-int __access_remote_vm(struct task_struct *tsk, struct mm_struct *mm,
- unsigned long addr, void *buf, int len, unsigned int gup_flags)
+int __access_remote_vm_locked(struct task_struct *tsk, struct mm_struct *mm,
+ unsigned long addr, void *buf, int len,
+ unsigned int gup_flags)
{
struct vm_area_struct *vma;
void *old_buf = buf;
int write = gup_flags & FOLL_WRITE;
- if (mmap_read_lock_killable(mm))
- return 0;
-
/* ignore errors, just check how much was successfully transferred */
while (len) {
int bytes, ret, offset;
@@ -4785,9 +4785,46 @@ int __access_remote_vm(struct task_struct *tsk, struct mm_struct *mm,
buf += bytes;
addr += bytes;
}
+ return buf - old_buf;
+}
+
+/*
+ * Access another process' address space as given in mm. If non-NULL, use the
+ * given task for page fault accounting.
+ */
+int __access_remote_vm(struct task_struct *tsk, struct mm_struct *mm,
+ unsigned long addr, void *buf, int len, unsigned int gup_flags)
+{
+ int ret;
+
+ if (mmap_read_lock_killable(mm))
+ return 0;
+
+ ret = __access_remote_vm_locked(tsk, mm, addr, buf, len, gup_flags);
mmap_read_unlock(mm);
- return buf - old_buf;
+ return ret;
+}
+
+/**
+ * access_remote_vm_locked - access another process' address space, without
+ * taking the mmap_lock. This allows nested calls from callers that already have
+ * taken the lock.
+ *
+ * @mm: the mm_struct of the target address space
+ * @addr: start address to access
+ * @buf: source or destination buffer
+ * @len: number of bytes to transfer
+ * @gup_flags: flags modifying lookup behaviour
+ *
+ * The caller must hold a reference on @mm, as well as hold the mmap_lock
+ *
+ * Return: number of bytes copied from source to destination.
+ */
+int access_remote_vm_locked(struct mm_struct *mm, unsigned long addr, void *buf,
+ int len, unsigned int gup_flags)
+{
+ return __access_remote_vm_locked(NULL, mm, addr, buf, len, gup_flags);
}
/**
--
2.28.0
^ permalink raw reply related [flat|nested] 2+ messages in thread