Skip to content

Commit 58a5756

Browse files
Michal HockoBoris Ostrovsky
authored andcommitted
xen/gntdev: fix up blockable calls to mn_invl_range_start
Patch series "mmu_notifiers follow ups". Tetsuo has noticed some fallouts from 93065ac ("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): 93065ac ("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: 93065ac ("mm, oom: distinguish blockable mode for mmu notifiers") Signed-off-by: Michal 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: Juergen Gross <jgross@suse.com> Signed-off-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
1 parent 4dca864 commit 58a5756

File tree

1 file changed

+15
-11
lines changed

1 file changed

+15
-11
lines changed

drivers/xen/gntdev.c

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -492,12 +492,19 @@ static bool in_range(struct gntdev_grant_map *map,
492492
return true;
493493
}
494494

495-
static void unmap_if_in_range(struct gntdev_grant_map *map,
496-
unsigned long start, unsigned long end)
495+
static int unmap_if_in_range(struct gntdev_grant_map *map,
496+
unsigned long start, unsigned long end,
497+
bool blockable)
497498
{
498499
unsigned long mstart, mend;
499500
int err;
500501

502+
if (!in_range(map, start, end))
503+
return 0;
504+
505+
if (!blockable)
506+
return -EAGAIN;
507+
501508
mstart = max(start, map->vma->vm_start);
502509
mend = min(end, map->vma->vm_end);
503510
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,
508515
(mstart - map->vma->vm_start) >> PAGE_SHIFT,
509516
(mend - mstart) >> PAGE_SHIFT);
510517
WARN_ON(err);
518+
519+
return 0;
511520
}
512521

513522
static int mn_invl_range_start(struct mmu_notifier *mn,
@@ -519,25 +528,20 @@ static int mn_invl_range_start(struct mmu_notifier *mn,
519528
struct gntdev_grant_map *map;
520529
int ret = 0;
521530

522-
/* TODO do we really need a mutex here? */
523531
if (blockable)
524532
mutex_lock(&priv->lock);
525533
else if (!mutex_trylock(&priv->lock))
526534
return -EAGAIN;
527535

528536
list_for_each_entry(map, &priv->maps, next) {
529-
if (in_range(map, start, end)) {
530-
ret = -EAGAIN;
537+
ret = unmap_if_in_range(map, start, end, blockable);
538+
if (ret)
531539
goto out_unlock;
532-
}
533-
unmap_if_in_range(map, start, end);
534540
}
535541
list_for_each_entry(map, &priv->freeable_maps, next) {
536-
if (in_range(map, start, end)) {
537-
ret = -EAGAIN;
542+
ret = unmap_if_in_range(map, start, end, blockable);
543+
if (ret)
538544
goto out_unlock;
539-
}
540-
unmap_if_in_range(map, start, end);
541545
}
542546

543547
out_unlock:

0 commit comments

Comments
 (0)