diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c index 2eeeb6fd631d..23f3411809f0 100644 --- a/drivers/xen/gntdev.c +++ b/drivers/xen/gntdev.c @@ -361,8 +361,7 @@ static int map_grant_pages(struct grant_map *map) for (i = 0; i < map->count; i++) { if (map->map_ops[i].status == GNTST_okay) { map->unmap_ops[i].handle = map->map_ops[i].handle; - if (!use_ptemod) - alloced++; + alloced++; } else if (!err) err = -EINVAL; @@ -371,8 +370,7 @@ static int map_grant_pages(struct grant_map *map) if (use_ptemod) { if (map->kmap_ops[i].status == GNTST_okay) { - if (map->map_ops[i].status == GNTST_okay) - alloced++; + alloced++; map->kunmap_ops[i].handle = map->kmap_ops[i].handle; } else if (!err) err = -EINVAL; @@ -388,8 +386,14 @@ static void __unmap_grant_pages_done(int result, unsigned int i; struct grant_map *map = data->data; unsigned int offset = data->unmap_ops - map->unmap_ops; + int successful_unmaps = 0; + int live_grants; for (i = 0; i < data->count; i++) { + if (map->unmap_ops[offset + i].status == GNTST_okay && + map->unmap_ops[offset + i].handle != -1) + successful_unmaps++; + WARN_ON(map->unmap_ops[offset+i].status && map->unmap_ops[offset+i].handle != -1); pr_debug("unmap handle=%d st=%d\n", @@ -397,6 +401,10 @@ static void __unmap_grant_pages_done(int result, map->unmap_ops[offset+i].status); map->unmap_ops[offset+i].handle = -1; if (use_ptemod) { + if (map->kunmap_ops[offset + i].status == GNTST_okay && + map->kunmap_ops[offset + i].handle != -1) + successful_unmaps++; + WARN_ON(map->kunmap_ops[offset+i].status && map->kunmap_ops[offset+i].handle != -1); pr_debug("kunmap handle=%u st=%d\n", @@ -405,11 +413,15 @@ static void __unmap_grant_pages_done(int result, map->kunmap_ops[offset+i].handle = -1; } } + /* * Decrease the live-grant counter. This must happen after the loop to * prevent premature reuse of the grants by gnttab_mmap(). */ - atomic_sub(data->count, &map->live_grants); + live_grants = atomic_sub_return(successful_unmaps, &map->live_grants); + if (WARN_ON(live_grants < 0)) + pr_err("%s: live_grants became negative (%d) after unmapping %d pages!\n", + __func__, live_grants, successful_unmaps); /* Release reference taken by unmap_grant_pages */ gntdev_put_map(NULL, map);