On 10/28/19 4:10 PM, Jason Gunthorpe wrote:
> From: Jason Gunthorpe
>
> gntdev simply wants to monitor a specific VMA for any notifier events,
> this can be done straightforwardly using mmu_range_notifier_insert() over
> the VMA's VA range.
>
> The notifier should be attached until the original VMA is destroyed.
>
> It is unclear if any of this is even sane, but at least a lot of duplicate
> code is removed.
I didn't have a chance to look at the patch itself yet but as a heads-up
--- it crashes dom0.
-boris
>
> Cc: Oleksandr Andrushchenko
> Cc: Boris Ostrovsky
> Cc: xen-de...@lists.xenproject.org
> Cc: Juergen Gross
> Cc: Stefano Stabellini
> Signed-off-by: Jason Gunthorpe
> ---
> drivers/xen/gntdev-common.h | 8 +-
> drivers/xen/gntdev.c| 180 ++--
> 2 files changed, 49 insertions(+), 139 deletions(-)
>
> diff --git a/drivers/xen/gntdev-common.h b/drivers/xen/gntdev-common.h
> index 2f8b949c3eeb14..b201fdd20b667b 100644
> --- a/drivers/xen/gntdev-common.h
> +++ b/drivers/xen/gntdev-common.h
> @@ -21,15 +21,8 @@ struct gntdev_dmabuf_priv;
> struct gntdev_priv {
> /* Maps with visible offsets in the file descriptor. */
> struct list_head maps;
> - /*
> - * Maps that are not visible; will be freed on munmap.
> - * Only populated if populate_freeable_maps == 1
> - */
> - struct list_head freeable_maps;
> /* lock protects maps and freeable_maps. */
> struct mutex lock;
> - struct mm_struct *mm;
> - struct mmu_notifier mn;
>
> #ifdef CONFIG_XEN_GRANT_DMA_ALLOC
> /* Device for which DMA memory is allocated. */
> @@ -49,6 +42,7 @@ struct gntdev_unmap_notify {
> };
>
> struct gntdev_grant_map {
> + struct mmu_range_notifier notifier;
> struct list_head next;
> struct vm_area_struct *vma;
> int index;
> diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c
> index a446a7221e13e9..12d626670bebbc 100644
> --- a/drivers/xen/gntdev.c
> +++ b/drivers/xen/gntdev.c
> @@ -65,7 +65,6 @@ MODULE_PARM_DESC(limit, "Maximum number of grants that may
> be mapped by "
> static atomic_t pages_mapped = ATOMIC_INIT(0);
>
> static int use_ptemod;
> -#define populate_freeable_maps use_ptemod
>
> static int unmap_grant_pages(struct gntdev_grant_map *map,
>int offset, int pages);
> @@ -251,12 +250,6 @@ void gntdev_put_map(struct gntdev_priv *priv, struct
> gntdev_grant_map *map)
> evtchn_put(map->notify.event);
> }
>
> - if (populate_freeable_maps && priv) {
> - mutex_lock(>lock);
> - list_del(>next);
> - mutex_unlock(>lock);
> - }
> -
> if (map->pages && !use_ptemod)
> unmap_grant_pages(map, 0, map->count);
> gntdev_free_map(map);
> @@ -445,17 +438,9 @@ static void gntdev_vma_close(struct vm_area_struct *vma)
> struct gntdev_priv *priv = file->private_data;
>
> pr_debug("gntdev_vma_close %p\n", vma);
> - if (use_ptemod) {
> - /* It is possible that an mmu notifier could be running
> - * concurrently, so take priv->lock to ensure that the vma won't
> - * vanishing during the unmap_grant_pages call, since we will
> - * spin here until that completes. Such a concurrent call will
> - * not do any unmapping, since that has been done prior to
> - * closing the vma, but it may still iterate the unmap_ops list.
> - */
> - mutex_lock(>lock);
> + if (use_ptemod && map->vma == vma) {
> + mmu_range_notifier_remove(>notifier);
> map->vma = NULL;
> - mutex_unlock(>lock);
> }
> vma->vm_private_data = NULL;
> gntdev_put_map(priv, map);
> @@ -477,109 +462,44 @@ static const struct vm_operations_struct gntdev_vmops
> = {
>
> /* -- */
>
> -static bool in_range(struct gntdev_grant_map *map,
> - unsigned long start, unsigned long end)
> -{
> - if (!map->vma)
> - return false;
> - if (map->vma->vm_start >= end)
> - return false;
> - if (map->vma->vm_end <= start)
> - return false;
> -
> - return true;
> -}
> -
> -static int unmap_if_in_range(struct gntdev_grant_map *map,
> - unsigned long start, unsigned long end,
> - bool blockable)
> +static bool gntdev_invalidate(struct mmu_range_notifier *mn,
> + const struct mmu_notifier_range *range,
> + unsigned long cur_seq)
> {
> + struct gntdev_grant_map *map =
> + container_of(mn, struct gntdev_grant_map, notifier);
> unsigned long mstart, mend;
> int err;
>
> - if (!in_range(map, start, end))
> - return 0;
> + if (!mmu_notifier_range_blockable(range))
> +