diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index dc9301d31f12..a2efd770162c 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c @@ -47,6 +47,13 @@ enum { VHOST_MEMORY_F_LOG = 0x1, }; +void vhost_debug_mm(struct vhost_dev *dev, const char *prompt) +{ + printk("%s mm_count %d mm_users %d\n", + prompt, atomic_read(&dev->mm->mm_count), + atomic_read(&dev->mm->mm_users)); +} + #define vhost_used_event(vq) ((__virtio16 __user *)&vq->avail->ring[vq->num]) #define vhost_avail_event(vq) ((__virtio16 __user *)&vq->used->ring[vq->num]) @@ -709,6 +716,8 @@ long vhost_dev_set_owner(struct vhost_dev *dev) /* No owner, become one */ dev->mm = get_task_mm(current); + debug_mm = dev->mm; + vhost_debug_mm(dev, "set owner"); worker = kthread_create(vhost_worker, dev, "vhost-%d", current->pid); if (IS_ERR(worker)) { err = PTR_ERR(worker); @@ -730,6 +739,7 @@ long vhost_dev_set_owner(struct vhost_dev *dev) err = mmu_notifier_register(&dev->mmu_notifier, dev->mm); if (err) goto err_mmu_notifier; + vhost_debug_mm(dev, "after register in set_owner"); #endif return 0; @@ -742,8 +752,10 @@ long vhost_dev_set_owner(struct vhost_dev *dev) kthread_stop(worker); dev->worker = NULL; err_worker: - if (dev->mm) + if (dev->mm) { mmput(dev->mm); + vhost_debug_mm(dev, "err_worker"); + } dev->mm = NULL; err_mm: return err; @@ -963,12 +975,14 @@ void vhost_dev_cleanup(struct vhost_dev *dev) mmu_notifier_unregister(&dev->mmu_notifier, dev->mm); #endif mmput(dev->mm); + vhost_debug_mm(dev, "cleanup last"); } #if VHOST_ARCH_CAN_ACCEL_UACCESS for (i = 0; i < dev->nvqs; i++) vhost_uninit_vq_maps(dev->vqs[i]); #endif dev->mm = NULL; + debug_mm = NULL; } EXPORT_SYMBOL_GPL(vhost_dev_cleanup); @@ -2067,8 +2081,10 @@ static long vhost_vring_set_num_addr(struct vhost_dev *d, */ if (d->mm) mmu_notifier_unregister(&d->mmu_notifier, d->mm); + vhost_debug_mm(d, "unregister in set_num_addr"); vhost_uninit_vq_maps(vq); + vhost_debug_mm(d, "after uninit vq in set_vring_num"); #endif switch (ioctl) { @@ -2087,6 +2103,7 @@ static long vhost_vring_set_num_addr(struct vhost_dev *d, if (d->mm) mmu_notifier_register(&d->mmu_notifier, d->mm); + vhost_debug_mm(d, "after register in set_vring_num"); #endif mutex_unlock(&vq->mutex); diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h index 8ec38b11b361..3126d0c23763 100644 --- a/include/linux/mm_types.h +++ b/include/linux/mm_types.h @@ -515,6 +515,7 @@ struct mm_struct { }; extern struct mm_struct init_mm; +extern struct mm_struct *debug_mm; /* Pointer magic because the dynamic array size confuses some compilers. */ static inline void mm_init_cpumask(struct mm_struct *mm) diff --git a/include/linux/sched/mm.h b/include/linux/sched/mm.h index a3fda9f024c3..0530fc6fbe20 100644 --- a/include/linux/sched/mm.h +++ b/include/linux/sched/mm.h @@ -9,6 +9,7 @@ #include #include + /* * Routines for handling mm_structs */ @@ -33,6 +34,11 @@ extern struct mm_struct *mm_alloc(void); */ static inline void mmgrab(struct mm_struct *mm) { + if (debug_mm == mm) { + printk("%pF mmgrab to %d\n", + __builtin_return_address(0), + atomic_read(&mm->mm_count) + 1); + } atomic_inc(&mm->mm_count); } @@ -45,6 +51,11 @@ static inline void mmdrop(struct mm_struct *mm) * required by the membarrier system call before returning to * user-space, after storing to rq->curr. */ + if (debug_mm == mm) { + printk("%pF mmdrop to %d\n", + __builtin_return_address(0), + atomic_read(&mm->mm_count) - 1); + } if (unlikely(atomic_dec_and_test(&mm->mm_count))) __mmdrop(mm); } @@ -88,11 +99,21 @@ static inline bool mmget_still_valid(struct mm_struct *mm) */ static inline void mmget(struct mm_struct *mm) { + if (debug_mm == mm) { + printk("%pF mget %d\n", + __builtin_return_address(0), + atomic_read(&mm->mm_users) + 1); + } atomic_inc(&mm->mm_users); } static inline bool mmget_not_zero(struct mm_struct *mm) { + if (debug_mm == mm) { + printk("%pF mmget_not_zero %d\n", + __builtin_return_address(0), + atomic_read(&mm->mm_users) + 1); + } return atomic_inc_not_zero(&mm->mm_users); } diff --git a/kernel/fork.c b/kernel/fork.c index b2b87d450b80..d2d761af3512 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -1076,6 +1076,11 @@ void mmput(struct mm_struct *mm) { might_sleep(); + if (debug_mm == mm) { + printk("%pF mmput after %d\n", + __builtin_return_address(0), + atomic_read(&mm->mm_users) - 1); + } if (atomic_dec_and_test(&mm->mm_users)) __mmput(mm); } @@ -1092,6 +1097,11 @@ static void mmput_async_fn(struct work_struct *work) void mmput_async(struct mm_struct *mm) { + if (debug_mm == mm) { + printk("%pF mmput to %d\n", + __builtin_return_address(0), + atomic_read(&mm->mm_users) - 1); + } if (atomic_dec_and_test(&mm->mm_users)) { INIT_WORK(&mm->async_put_work, mmput_async_fn); schedule_work(&mm->async_put_work); diff --git a/mm/init-mm.c b/mm/init-mm.c index a787a319211e..f6253a53a891 100644 --- a/mm/init-mm.c +++ b/mm/init-mm.c @@ -38,3 +38,6 @@ struct mm_struct init_mm = { .cpu_bitmap = { [BITS_TO_LONGS(NR_CPUS)] = 0}, INIT_MM_CONTEXT(init_mm) }; + +struct mm_struct *debug_mm = NULL; +EXPORT_SYMBOL_GPL(debug_mm);