Commit 58a57569 authored by Michal Hocko's avatar Michal Hocko Committed by Boris Ostrovsky

xen/gntdev: fix up blockable calls to mn_invl_range_start

Patch series "mmu_notifiers follow ups".

Tetsuo has noticed some fallouts from 93065ac7 ("mm, oom: distinguish
blockable mode for mmu notifiers").  One of them has been fixed and picked
up by AMD/DRM maintainer [1].  XEN issue is fixed by patch 1.  I have also
clarified expectations about blockable semantic of invalidate_range_end.
Finally the last patch removes MMU_INVALIDATE_DOES_NOT_BLOCK which is no
longer used nor needed.

[1] http://lkml.kernel.org/r/20180824135257.GU29735@dhcp22.suse.cz

This patch (of 3):

93065ac7 ("mm, oom: distinguish blockable mode for mmu notifiers") has
introduced blockable parameter to all mmu_notifiers and the notifier has
to back off when called in !blockable case and it could block down the
road.

The above commit implemented that for mn_invl_range_start but both
in_range checks are done unconditionally regardless of the blockable mode
and as such they would fail all the time for regular calls.  Fix this by
checking blockable parameter as well.

Once we are there we can remove the stale TODO.  The lock has to be
sleepable because we wait for completion down in gnttab_unmap_refs_sync.

Link: http://lkml.kernel.org/r/20180827112623.8992-2-mhocko@kernel.org
Fixes: 93065ac7 ("mm, oom: distinguish blockable mode for mmu notifiers")
Signed-off-by: default avatarMichal Hocko <mhocko@suse.com>
Cc: Boris Ostrovsky <boris.ostrovsky@oracle.com>
Cc: Juergen Gross <jgross@suse.com>
Cc: David Rientjes <rientjes@google.com>
Cc: Jerome Glisse <jglisse@redhat.com>
Cc: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Reviewed-by: default avatarJuergen Gross <jgross@suse.com>
Signed-off-by: default avatarBoris Ostrovsky <boris.ostrovsky@oracle.com>
parent 4dca864b
...@@ -492,12 +492,19 @@ static bool in_range(struct gntdev_grant_map *map, ...@@ -492,12 +492,19 @@ static bool in_range(struct gntdev_grant_map *map,
return true; return true;
} }
static void unmap_if_in_range(struct gntdev_grant_map *map, static int unmap_if_in_range(struct gntdev_grant_map *map,
unsigned long start, unsigned long end) unsigned long start, unsigned long end,
bool blockable)
{ {
unsigned long mstart, mend; unsigned long mstart, mend;
int err; int err;
if (!in_range(map, start, end))
return 0;
if (!blockable)
return -EAGAIN;
mstart = max(start, map->vma->vm_start); mstart = max(start, map->vma->vm_start);
mend = min(end, map->vma->vm_end); mend = min(end, map->vma->vm_end);
pr_debug("map %d+%d (%lx %lx), range %lx %lx, mrange %lx %lx\n", pr_debug("map %d+%d (%lx %lx), range %lx %lx, mrange %lx %lx\n",
...@@ -508,6 +515,8 @@ static void unmap_if_in_range(struct gntdev_grant_map *map, ...@@ -508,6 +515,8 @@ static void unmap_if_in_range(struct gntdev_grant_map *map,
(mstart - map->vma->vm_start) >> PAGE_SHIFT, (mstart - map->vma->vm_start) >> PAGE_SHIFT,
(mend - mstart) >> PAGE_SHIFT); (mend - mstart) >> PAGE_SHIFT);
WARN_ON(err); WARN_ON(err);
return 0;
} }
static int mn_invl_range_start(struct mmu_notifier *mn, static int mn_invl_range_start(struct mmu_notifier *mn,
...@@ -519,26 +528,21 @@ static int mn_invl_range_start(struct mmu_notifier *mn, ...@@ -519,26 +528,21 @@ static int mn_invl_range_start(struct mmu_notifier *mn,
struct gntdev_grant_map *map; struct gntdev_grant_map *map;
int ret = 0; int ret = 0;
/* TODO do we really need a mutex here? */
if (blockable) if (blockable)
mutex_lock(&priv->lock); mutex_lock(&priv->lock);
else if (!mutex_trylock(&priv->lock)) else if (!mutex_trylock(&priv->lock))
return -EAGAIN; return -EAGAIN;
list_for_each_entry(map, &priv->maps, next) { list_for_each_entry(map, &priv->maps, next) {
if (in_range(map, start, end)) { ret = unmap_if_in_range(map, start, end, blockable);
ret = -EAGAIN; if (ret)
goto out_unlock; goto out_unlock;
} }
unmap_if_in_range(map, start, end);
}
list_for_each_entry(map, &priv->freeable_maps, next) { list_for_each_entry(map, &priv->freeable_maps, next) {
if (in_range(map, start, end)) { ret = unmap_if_in_range(map, start, end, blockable);
ret = -EAGAIN; if (ret)
goto out_unlock; goto out_unlock;
} }
unmap_if_in_range(map, start, end);
}
out_unlock: out_unlock:
mutex_unlock(&priv->lock); mutex_unlock(&priv->lock);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment