mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-30 08:04:13 +08:00
vhost: use mmgrab() instead of mmget() for non worker device
For the device that doesn't use vhost worker and use_mm(), mmget() is too heavy weight and it may brings troubles for implementing mmap() support for vDPA device. This is because, an reference to the address space was held via mm_get() in vhost_dev_set_owner() and an reference to the file was held in mmap(). This means when process exits, the mm can not be released thus we can not release the file. This patch tries to use mmgrab() instead of mmget(), which allows the address space to be destroy in process exit without releasing the mm structure itself. This is sufficient for vDPA device which pin user pages and does not depend on the address space to work. Signed-off-by: Jason Wang <jasowang@redhat.com> Link: https://lore.kernel.org/r/20200529080303.15449-3-jasowang@redhat.com Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
parent
01fcb1cbc8
commit
5ce995f313
@ -541,6 +541,36 @@ bool vhost_dev_has_owner(struct vhost_dev *dev)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(vhost_dev_has_owner);
|
||||
|
||||
static void vhost_attach_mm(struct vhost_dev *dev)
|
||||
{
|
||||
/* No owner, become one */
|
||||
if (dev->use_worker) {
|
||||
dev->mm = get_task_mm(current);
|
||||
} else {
|
||||
/* vDPA device does not use worker thead, so there's
|
||||
* no need to hold the address space for mm. This help
|
||||
* to avoid deadlock in the case of mmap() which may
|
||||
* held the refcnt of the file and depends on release
|
||||
* method to remove vma.
|
||||
*/
|
||||
dev->mm = current->mm;
|
||||
mmgrab(dev->mm);
|
||||
}
|
||||
}
|
||||
|
||||
static void vhost_detach_mm(struct vhost_dev *dev)
|
||||
{
|
||||
if (!dev->mm)
|
||||
return;
|
||||
|
||||
if (dev->use_worker)
|
||||
mmput(dev->mm);
|
||||
else
|
||||
mmdrop(dev->mm);
|
||||
|
||||
dev->mm = NULL;
|
||||
}
|
||||
|
||||
/* Caller should have device mutex */
|
||||
long vhost_dev_set_owner(struct vhost_dev *dev)
|
||||
{
|
||||
@ -553,8 +583,8 @@ long vhost_dev_set_owner(struct vhost_dev *dev)
|
||||
goto err_mm;
|
||||
}
|
||||
|
||||
/* No owner, become one */
|
||||
dev->mm = get_task_mm(current);
|
||||
vhost_attach_mm(dev);
|
||||
|
||||
dev->kcov_handle = kcov_common_handle();
|
||||
if (dev->use_worker) {
|
||||
worker = kthread_create(vhost_worker, dev,
|
||||
@ -583,9 +613,7 @@ err_cgroup:
|
||||
dev->worker = NULL;
|
||||
}
|
||||
err_worker:
|
||||
if (dev->mm)
|
||||
mmput(dev->mm);
|
||||
dev->mm = NULL;
|
||||
vhost_detach_mm(dev);
|
||||
dev->kcov_handle = 0;
|
||||
err_mm:
|
||||
return err;
|
||||
@ -682,9 +710,7 @@ void vhost_dev_cleanup(struct vhost_dev *dev)
|
||||
dev->worker = NULL;
|
||||
dev->kcov_handle = 0;
|
||||
}
|
||||
if (dev->mm)
|
||||
mmput(dev->mm);
|
||||
dev->mm = NULL;
|
||||
vhost_detach_mm(dev);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(vhost_dev_cleanup);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user