From: Christoph Hellwig <hch@xxxxxx> Subject: kernel: better document the use_mm/unuse_mm API contract 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@xxxxxx: 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@xxxxxx [sfr@xxxxxxxxxxxxxxxx: powerpc/vas: fix up for {un}use_mm() rename] Link: http://lkml.kernel.org/r/20200422163935.5aa93ba5@xxxxxxxxxxxxxxxx Link: http://lkml.kernel.org/r/20200404094101.672954-6-hch@xxxxxx Signed-off-by: Christoph Hellwig <hch@xxxxxx> Signed-off-by: Stephen Rothwell <sfr@xxxxxxxxxxxxxxxx> Acked-by: Felix Kuehling <Felix.Kuehling@xxxxxxx> Reviewed-by: Jens Axboe <axboe@xxxxxxxxx> Tested-by: Jens Axboe <axboe@xxxxxxxxx> Acked-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx> [usb] Acked-by: Felix Kuehling <Felix.Kuehling@xxxxxxx> Acked-by: Haren Myneni <haren@xxxxxxxxxxxxx> Cc: Alex Deucher <alexander.deucher@xxxxxxx> Cc: Al Viro <viro@xxxxxxxxxxxxxxxxxx> Cc: Felipe Balbi <balbi@xxxxxxxxxx> Cc: Jason Wang <jasowang@xxxxxxxxxx> Cc: "Michael S. Tsirkin" <mst@xxxxxxxxxx> Cc: Zhenyu Wang <zhenyuw@xxxxxxxxxxxxxxx> Cc: Zhi Wang <zhi.a.wang@xxxxxxxxx> Signed-off-by: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx> --- arch/powerpc/platforms/powernv/vas-fault.c | 4 +- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h | 4 +- drivers/usb/gadget/function/f_fs.c | 4 +- drivers/usb/gadget/legacy/inode.c | 4 +- drivers/vfio/vfio_iommu_type1.c | 4 +- drivers/vhost/vhost.c | 4 +- fs/io-wq.c | 6 +-- fs/io_uring.c | 4 +- include/linux/kthread.h | 4 +- kernel/kthread.c | 33 +++++++++---------- mm/oom_kill.c | 6 +-- mm/vmacache.c | 4 +- 12 files changed, 40 insertions(+), 41 deletions(-) --- a/arch/powerpc/platforms/powernv/vas-fault.c~kernel-better-document-the-use_mm-unuse_mm-api-contract +++ a/arch/powerpc/platforms/powernv/vas-fault.c @@ -127,7 +127,7 @@ static void update_csb(struct vas_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 @@ -139,7 +139,7 @@ static void update_csb(struct vas_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 */ --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h~kernel-better-document-the-use_mm-unuse_mm-api-contract +++ a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h @@ -197,9 +197,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); \ } \ pagefault_enable(); \ } \ --- a/drivers/usb/gadget/function/f_fs.c~kernel-better-document-the-use_mm-unuse_mm-api-contract +++ a/drivers/usb/gadget/function/f_fs.c @@ -827,9 +827,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~kernel-better-document-the-use_mm-unuse_mm-api-contract +++ a/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/vfio/vfio_iommu_type1.c~kernel-better-document-the-use_mm-unuse_mm-api-contract +++ a/drivers/vfio/vfio_iommu_type1.c @@ -2817,7 +2817,7 @@ static int vfio_iommu_type1_dma_rw_chunk return -EPERM; if (kthread) - use_mm(mm); + kthread_use_mm(mm); else if (current->mm != mm) goto out; @@ -2844,7 +2844,7 @@ static int vfio_iommu_type1_dma_rw_chunk *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; --- a/drivers/vhost/vhost.c~kernel-better-document-the-use_mm-unuse_mm-api-contract +++ a/drivers/vhost/vhost.c @@ -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 */ @@ -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; } --- a/fs/io_uring.c~kernel-better-document-the-use_mm-unuse_mm-api-contract +++ a/fs/io_uring.c @@ -5866,7 +5866,7 @@ static int io_init_req(struct io_ring_ct 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); @@ -5980,7 +5980,7 @@ static inline void io_sq_thread_drop_mm( struct mm_struct *mm = current->mm; if (mm) { - unuse_mm(mm); + kthread_unuse_mm(mm); mmput(mm); } } --- a/fs/io-wq.c~kernel-better-document-the-use_mm-unuse_mm-api-contract +++ a/fs/io-wq.c @@ -170,7 +170,7 @@ static bool __io_worker_unuse(struct io_ } __set_current_state(TASK_RUNNING); set_fs(KERNEL_DS); - unuse_mm(worker->mm); + kthread_unuse_mm(worker->mm); mmput(worker->mm); worker->mm = NULL; } @@ -417,7 +417,7 @@ static struct io_wq_work *io_get_next_wo 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; } @@ -426,7 +426,7 @@ static void io_wq_switch_mm(struct io_wo 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; --- a/include/linux/kthread.h~kernel-better-document-the-use_mm-unuse_mm-api-contract +++ a/include/linux/kthread.h @@ -200,8 +200,8 @@ bool kthread_cancel_delayed_work_sync(st 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; --- a/kernel/kthread.c~kernel-better-document-the-use_mm-unuse_mm-api-contract +++ a/kernel/kthread.c @@ -1208,18 +1208,18 @@ void kthread_destroy_worker(struct kthre } 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) { @@ -1236,20 +1236,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; @@ -1257,7 +1256,7 @@ 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); #ifdef CONFIG_BLK_CGROUP /** --- a/mm/oom_kill.c~kernel-better-document-the-use_mm-unuse_mm-api-contract +++ a/mm/oom_kill.c @@ -126,7 +126,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. */ @@ -919,8 +919,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~kernel-better-document-the-use_mm-unuse_mm-api-contract +++ a/mm/vmacache.c @@ -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) { _