Skip to content

Commit

Permalink
kernel: better document the use_mm/unuse_mm API contract
Browse files Browse the repository at this point in the history
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.

[[email protected]: fix a comment typo, cover the newly merged use_mm/unuse_mm caller in vfio]
  Link: http://lkml.kernel.org/r/[email protected]
[[email protected]: powerpc/vas: fix up for {un}use_mm() rename]
  Link: http://lkml.kernel.org/r/[email protected]

Signed-off-by: Christoph Hellwig <[email protected]>
Signed-off-by: Stephen Rothwell <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Tested-by: Jens Axboe <[email protected]>
Reviewed-by: Jens Axboe <[email protected]>
Acked-by: Felix Kuehling <[email protected]>
Acked-by: Greg Kroah-Hartman <[email protected]> [usb]
Acked-by: Haren Myneni <[email protected]>
Cc: Alex Deucher <[email protected]>
Cc: Al Viro <[email protected]>
Cc: Felipe Balbi <[email protected]>
Cc: Jason Wang <[email protected]>
Cc: "Michael S. Tsirkin" <[email protected]>
Cc: Zhenyu Wang <[email protected]>
Cc: Zhi Wang <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
Christoph Hellwig authored and torvalds committed Jun 11, 2020
1 parent 4dbe59a commit f5678e7
Show file tree
Hide file tree
Showing 12 changed files with 40 additions and 41 deletions.
4 changes: 2 additions & 2 deletions arch/powerpc/platforms/powernv/vas-fault.c
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ static void update_csb(struct vas_window *window,
return;
}

use_mm(window->mm);
kthread_use_mm(window->mm);
rc = copy_to_user(csb_addr, &csb, sizeof(csb));
/*
* User space polls on csb.flags (first byte). So add barrier
Expand All @@ -139,7 +139,7 @@ static void update_csb(struct vas_window *window,
smp_mb();
rc = copy_to_user(csb_addr, &csb, sizeof(u8));
}
unuse_mm(window->mm);
kthread_unuse_mm(window->mm);
put_task_struct(tsk);

/* Success */
Expand Down
4 changes: 2 additions & 2 deletions drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
Original file line number Diff line number Diff line change
Expand Up @@ -197,9 +197,9 @@ uint8_t amdgpu_amdkfd_get_xgmi_hops_count(struct kgd_dev *dst, struct kgd_dev *s
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); \
} \
pagefault_enable(); \
} \
Expand Down
4 changes: 2 additions & 2 deletions drivers/usb/gadget/function/f_fs.c
Original file line number Diff line number Diff line change
Expand Up @@ -827,9 +827,9 @@ static void ffs_user_copy_worker(struct work_struct *work)
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);
}

Expand Down
4 changes: 2 additions & 2 deletions drivers/usb/gadget/legacy/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -462,9 +462,9 @@ static void ep_user_copy_worker(struct work_struct *work)
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;

Expand Down
4 changes: 2 additions & 2 deletions drivers/vfio/vfio_iommu_type1.c
Original file line number Diff line number Diff line change
Expand Up @@ -2817,7 +2817,7 @@ static int vfio_iommu_type1_dma_rw_chunk(struct vfio_iommu *iommu,
return -EPERM;

if (kthread)
use_mm(mm);
kthread_use_mm(mm);
else if (current->mm != mm)
goto out;

Expand All @@ -2844,7 +2844,7 @@ static int vfio_iommu_type1_dma_rw_chunk(struct vfio_iommu *iommu,
*copied = copy_from_user(data, (void __user *)vaddr,
count) ? 0 : count;
if (kthread)
unuse_mm(mm);
kthread_unuse_mm(mm);
out:
mmput(mm);
return *copied ? 0 : -EFAULT;
Expand Down
4 changes: 2 additions & 2 deletions drivers/vhost/vhost.c
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,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 */
Expand Down Expand Up @@ -360,7 +360,7 @@ static int vhost_worker(void *data)
schedule();
}
}
unuse_mm(dev->mm);
kthread_unuse_mm(dev->mm);
set_fs(oldfs);
return 0;
}
Expand Down
6 changes: 3 additions & 3 deletions fs/io-wq.c
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ static bool __io_worker_unuse(struct io_wqe *wqe, struct io_worker *worker)
}
__set_current_state(TASK_RUNNING);
set_fs(KERNEL_DS);
unuse_mm(worker->mm);
kthread_unuse_mm(worker->mm);
mmput(worker->mm);
worker->mm = NULL;
}
Expand Down Expand Up @@ -417,7 +417,7 @@ static struct io_wq_work *io_get_next_work(struct io_wqe *wqe)
static void io_wq_switch_mm(struct io_worker *worker, struct io_wq_work *work)
{
if (worker->mm) {
unuse_mm(worker->mm);
kthread_unuse_mm(worker->mm);
mmput(worker->mm);
worker->mm = NULL;
}
Expand All @@ -426,7 +426,7 @@ static void io_wq_switch_mm(struct io_worker *worker, struct io_wq_work *work)
return;
}
if (mmget_not_zero(work->mm)) {
use_mm(work->mm);
kthread_use_mm(work->mm);
if (!worker->mm)
set_fs(USER_DS);
worker->mm = work->mm;
Expand Down
4 changes: 2 additions & 2 deletions fs/io_uring.c
Original file line number Diff line number Diff line change
Expand Up @@ -5866,7 +5866,7 @@ static int io_init_req(struct io_ring_ctx *ctx, struct io_kiocb *req,
if (io_op_defs[req->opcode].needs_mm && !current->mm) {
if (unlikely(!mmget_not_zero(ctx->sqo_mm)))
return -EFAULT;
use_mm(ctx->sqo_mm);
kthread_use_mm(ctx->sqo_mm);
}

sqe_flags = READ_ONCE(sqe->flags);
Expand Down Expand Up @@ -5980,7 +5980,7 @@ static inline void io_sq_thread_drop_mm(struct io_ring_ctx *ctx)
struct mm_struct *mm = current->mm;

if (mm) {
unuse_mm(mm);
kthread_unuse_mm(mm);
mmput(mm);
}
}
Expand Down
4 changes: 2 additions & 2 deletions include/linux/kthread.h
Original file line number Diff line number Diff line change
Expand Up @@ -200,8 +200,8 @@ bool kthread_cancel_delayed_work_sync(struct kthread_delayed_work *work);

void kthread_destroy_worker(struct kthread_worker *worker);

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);

struct cgroup_subsys_state;

Expand Down
33 changes: 16 additions & 17 deletions kernel/kthread.c
Original file line number Diff line number Diff line change
Expand Up @@ -1208,18 +1208,18 @@ void kthread_destroy_worker(struct kthread_worker *worker)
}
EXPORT_SYMBOL(kthread_destroy_worker);

/*
* 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) {
Expand All @@ -1236,28 +1236,27 @@ 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;
/* active_mm is still 'mm' */
enter_lazy_tlb(mm, tsk);
task_unlock(tsk);
}
EXPORT_SYMBOL_GPL(unuse_mm);
EXPORT_SYMBOL_GPL(kthread_unuse_mm);

#ifdef CONFIG_BLK_CGROUP
/**
Expand Down
6 changes: 3 additions & 3 deletions mm/oom_kill.c
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ static bool oom_cpuset_eligible(struct task_struct *tsk, struct oom_control *oc)

/*
* 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.
*/
Expand Down Expand Up @@ -919,8 +919,8 @@ static void __oom_kill_process(struct task_struct *victim, const char *message)
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;
Expand Down
4 changes: 2 additions & 2 deletions mm/vmacache.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,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)
{
Expand Down

0 comments on commit f5678e7

Please sign in to comment.