From: Christoph Hellwig <hch@lst.de>
Date: Wed, 10 Jun 2020 18:42:06 -0700
Subject: kernel: better document the use_mm/unuse_mm API contract
Git-commit: f5678e7f2ac31c270334b936352f0ef2fe7dd2b3
Patch-mainline: v5.8-rc1
References: MM Functionality, bsc#1178426
[vbabka@suse.cz SLE15-SP3 backport notes: fs/io_uring.c would not apply, had
to replace (un)use_mm() function calls manually
- drivers/gpu/drm/i915/gvt/kvmgt.c had to be patched, upstream has the calls
removed ]
[ms: on SP2 we don't have users in drivers/vfio/vfio_iommu_type1.c]
Switch the function documentation to kerneldoc comments, and add
WARN_ON_ONCE asserts that the calling thread is a kernel thread and does
not have ->mm set (or has ->mm set in the case of unuse_mm).
Also give the functions a kthread_ prefix to better document the use case.
[hch@lst.de: fix a comment typo, cover the newly merged use_mm/unuse_mm caller in vfio]
Link: http://lkml.kernel.org/r/20200416053158.586887-3-hch@lst.de
[sfr@canb.auug.org.au: powerpc/vas: fix up for {un}use_mm() rename]
Link: http://lkml.kernel.org/r/20200422163935.5aa93ba5@canb.auug.org.au
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Tested-by: Jens Axboe <axboe@kernel.dk>
Reviewed-by: Jens Axboe <axboe@kernel.dk>
Acked-by: Felix Kuehling <Felix.Kuehling@amd.com>
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> [usb]
Acked-by: Haren Myneni <haren@linux.ibm.com>
Cc: Alex Deucher <alexander.deucher@amd.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Felipe Balbi <balbi@kernel.org>
Cc: Jason Wang <jasowang@redhat.com>
Cc: "Michael S. Tsirkin" <mst@redhat.com>
Cc: Zhenyu Wang <zhenyuw@linux.intel.com>
Cc: Zhi Wang <zhi.a.wang@intel.com>
Link: http://lkml.kernel.org/r/20200404094101.672954-6-hch@lst.de
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Vlastimil Babka <vbabka@suse.cz>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h | 4 +--
drivers/gpu/drm/i915/gvt/kvmgt.c | 4 +--
drivers/usb/gadget/function/f_fs.c | 4 +--
drivers/usb/gadget/legacy/inode.c | 4 +--
drivers/vhost/vhost.c | 4 +--
fs/io_uring.c | 10 ++++----
include/linux/mmu_context.h | 4 +--
mm/mmu_context.c | 33 ++++++++++++++---------------
mm/oom_kill.c | 6 ++---
mm/vmacache.c | 4 +--
11 files changed, 40 insertions(+), 41 deletions(-)
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
@@ -185,9 +185,9 @@ uint8_t amdgpu_amdkfd_get_xgmi_hops_coun
if ((mmptr) == current->mm) { \
valid = !get_user((dst), (wptr)); \
} else if (current->mm == NULL) { \
- use_mm(mmptr); \
+ kthread_use_mm(mmptr); \
valid = !get_user((dst), (wptr)); \
- unuse_mm(mmptr); \
+ kthread_unuse_mm(mmptr); \
} \
} \
valid; \
--- a/drivers/gpu/drm/i915/gvt/kvmgt.c
+++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
@@ -1998,7 +1998,7 @@ static int kvmgt_rw_gpa(unsigned long ha
if (kthread) {
if (!mmget_not_zero(kvm->mm))
return -EFAULT;
- use_mm(kvm->mm);
+ kthread_use_mm(kvm->mm);
}
idx = srcu_read_lock(&kvm->srcu);
@@ -2007,7 +2007,7 @@ static int kvmgt_rw_gpa(unsigned long ha
srcu_read_unlock(&kvm->srcu, idx);
if (kthread) {
- unuse_mm(kvm->mm);
+ kthread_unuse_mm(kvm->mm);
mmput(kvm->mm);
}
--- a/drivers/usb/gadget/function/f_fs.c
+++ b/drivers/usb/gadget/function/f_fs.c
@@ -826,9 +826,9 @@ static void ffs_user_copy_worker(struct
mm_segment_t oldfs = get_fs();
set_fs(USER_DS);
- use_mm(io_data->mm);
+ kthread_use_mm(io_data->mm);
ret = ffs_copy_to_iter(io_data->buf, ret, &io_data->data);
- unuse_mm(io_data->mm);
+ kthread_unuse_mm(io_data->mm);
set_fs(oldfs);
}
--- a/drivers/usb/gadget/legacy/inode.c
+++ b/drivers/usb/gadget/legacy/inode.c
@@ -462,9 +462,9 @@ static void ep_user_copy_worker(struct w
struct kiocb *iocb = priv->iocb;
size_t ret;
- use_mm(mm);
+ kthread_use_mm(mm);
ret = copy_to_iter(priv->buf, priv->actual, &priv->to);
- unuse_mm(mm);
+ kthread_unuse_mm(mm);
if (!ret)
ret = -EFAULT;
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -336,7 +336,7 @@ static int vhost_worker(void *data)
mm_segment_t oldfs = get_fs();
set_fs(USER_DS);
- use_mm(dev->mm);
+ kthread_use_mm(dev->mm);
for (;;) {
/* mb paired w/ kthread_stop */
@@ -362,7 +362,7 @@ static int vhost_worker(void *data)
schedule();
}
}
- unuse_mm(dev->mm);
+ kthread_unuse_mm(dev->mm);
set_fs(oldfs);
return 0;
}
--- a/fs/io_uring.c
+++ b/fs/io_uring.c
@@ -1939,7 +1939,7 @@ restart:
ret = -EFAULT;
} else {
cur_mm = ctx->sqo_mm;
- use_mm(cur_mm);
+ kthread_use_mm(cur_mm);
old_fs = get_fs();
set_fs(USER_DS);
}
@@ -2027,7 +2027,7 @@ restart:
out:
if (cur_mm) {
set_fs(old_fs);
- unuse_mm(cur_mm);
+ kthread_unuse_mm(cur_mm);
mmput(cur_mm);
}
revert_creds(old_cred);
@@ -2338,7 +2338,7 @@ static int io_submit_sqes(struct io_ring
if (io_sqe_needs_user(s.sqe) && !*mm) {
mm_fault = mm_fault || !mmget_not_zero(ctx->sqo_mm);
if (!mm_fault) {
- use_mm(ctx->sqo_mm);
+ kthread_use_mm(ctx->sqo_mm);
*mm = ctx->sqo_mm;
}
}
@@ -2428,7 +2428,7 @@ static int io_sq_thread(void *data)
* may sleep.
*/
if (cur_mm) {
- unuse_mm(cur_mm);
+ kthread_unuse_mm(cur_mm);
mmput(cur_mm);
cur_mm = NULL;
}
@@ -2479,7 +2479,7 @@ static int io_sq_thread(void *data)
set_fs(old_fs);
if (cur_mm) {
- unuse_mm(cur_mm);
+ kthread_unuse_mm(cur_mm);
mmput(cur_mm);
}
revert_creds(old_cred);
--- a/include/linux/mmu_context.h
+++ b/include/linux/mmu_context.h
@@ -6,8 +6,8 @@
struct mm_struct;
-void use_mm(struct mm_struct *mm);
-void unuse_mm(struct mm_struct *mm);
+void kthread_use_mm(struct mm_struct *mm);
+void kthread_unuse_mm(struct mm_struct *mm);
/* Architectures that care about IRQ state in switch_mm can override this. */
#ifndef switch_mm_irqs_off
--- a/mm/mmu_context.c
+++ b/mm/mmu_context.c
@@ -12,18 +12,18 @@
#include <asm/mmu_context.h>
-/*
- * use_mm
- * Makes the calling kernel thread take on the specified
- * mm context.
- * (Note: this routine is intended to be called only
- * from a kernel thread context)
+/**
+ * kthread_use_mm - make the calling kthread operate on an address space
+ * @mm: address space to operate on
*/
-void use_mm(struct mm_struct *mm)
+void kthread_use_mm(struct mm_struct *mm)
{
struct mm_struct *active_mm;
struct task_struct *tsk = current;
+ WARN_ON_ONCE(!(tsk->flags & PF_KTHREAD));
+ WARN_ON_ONCE(tsk->mm);
+
task_lock(tsk);
active_mm = tsk->active_mm;
if (active_mm != mm) {
@@ -40,20 +40,19 @@ void use_mm(struct mm_struct *mm)
if (active_mm != mm)
mmdrop(active_mm);
}
-EXPORT_SYMBOL_GPL(use_mm);
+EXPORT_SYMBOL_GPL(kthread_use_mm);
-/*
- * unuse_mm
- * Reverses the effect of use_mm, i.e. releases the
- * specified mm context which was earlier taken on
- * by the calling kernel thread
- * (Note: this routine is intended to be called only
- * from a kernel thread context)
+/**
+ * kthread_unuse_mm - reverse the effect of kthread_use_mm()
+ * @mm: address space to operate on
*/
-void unuse_mm(struct mm_struct *mm)
+void kthread_unuse_mm(struct mm_struct *mm)
{
struct task_struct *tsk = current;
+ WARN_ON_ONCE(!(tsk->flags & PF_KTHREAD));
+ WARN_ON_ONCE(!tsk->mm);
+
task_lock(tsk);
sync_mm_rss(mm);
tsk->mm = NULL;
@@ -61,4 +60,4 @@ void unuse_mm(struct mm_struct *mm)
enter_lazy_tlb(mm, tsk);
task_unlock(tsk);
}
-EXPORT_SYMBOL_GPL(unuse_mm);
+EXPORT_SYMBOL_GPL(kthread_unuse_mm);
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -125,7 +125,7 @@ static bool oom_cpuset_eligible(struct t
/*
* The process p may have detached its own ->mm while exiting or through
- * use_mm(), but one or more of its subthreads may still have a valid
+ * kthread_use_mm(), but one or more of its subthreads may still have a valid
* pointer. Return p, or any of its subthreads with a valid ->mm, with
* task_lock() held.
*/
@@ -916,8 +916,8 @@ static void __oom_kill_process(struct ta
continue;
}
/*
- * No use_mm() user needs to read from the userspace so we are
- * ok to reap it.
+ * No kthead_use_mm() user needs to read from the userspace so
+ * we are ok to reap it.
*/
if (unlikely(p->flags & PF_KTHREAD))
continue;
--- a/mm/vmacache.c
+++ b/mm/vmacache.c
@@ -25,8 +25,8 @@
* task's vmacache pertains to a different mm (ie, its own). There is
* nothing we can do here.
*
- * Also handle the case where a kernel thread has adopted this mm via use_mm().
- * That kernel thread's vmacache is not applicable to this mm.
+ * Also handle the case where a kernel thread has adopted this mm via
+ * kthread_use_mm(). That kernel thread's vmacache is not applicable to this mm.
*/
static inline bool vmacache_valid_mm(struct mm_struct *mm)
{