gnttab: improve GNTTABOP_cache_flush locking

Dropping the lock before returning from grant_map_exists() means handing
possibly stale information back to the caller. Return back the pointer
to the active entry instead, for the caller to release the lock once
done.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Andre Przywara <andre.przywara@linaro.org>
Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>
master commit: 553ac37137
master date: 2017-12-04 11:04:18 +0100
This commit is contained in:
Jan Beulich committed 2017-12-20 16:10:37 +01:00
1 parent ba28eac093
commit ed7765ae03
1 file changed
+17 -20
+17 -20
View File
@@ -680,10 +680,10 @@ static int _set_status(unsigned gt_version,
return _set_status_v2(domid, readonly, mapflag, shah, act, status);
}
static int grant_map_exists(const struct domain *ld,
struct grant_table *rgt,
unsigned long mfn,
unsigned int *ref_count)
static struct active_grant_entry *grant_map_exists(const struct domain *ld,
struct grant_table *rgt,
unsigned long mfn,
unsigned int *ref_count)
{
unsigned int ref, max_iter;
@@ -699,28 +699,20 @@ static int grant_map_exists(const struct domain *ld,
nr_grant_entries(rgt));
for ( ref = *ref_count; ref < max_iter; ref++ )
{
struct active_grant_entry *act;
bool_t exists;
act = active_entry_acquire(rgt, ref);
exists = act->pin
&& act->domid == ld->domain_id
&& act->frame == mfn;
struct active_grant_entry *act = active_entry_acquire(rgt, ref);
if ( act->pin && act->domid == ld->domain_id && act->frame == mfn )
return act;
active_entry_release(act);
if ( exists )
return 0;
}
if ( ref < nr_grant_entries(rgt) )
{
*ref_count = ref;
return 1;
return NULL;
}
return -EINVAL;
return ERR_PTR(-EINVAL);
}
#define MAPKIND_READ 1
@@ -3013,6 +3005,7 @@ static int __gnttab_cache_flush(const gnttab_cache_flush_t *cflush,
struct domain *d, *owner;
struct page_info *page;
unsigned long mfn;
struct active_grant_entry *act = NULL;
void *v;
int ret;
@@ -3050,13 +3043,13 @@ static int __gnttab_cache_flush(const gnttab_cache_flush_t *cflush,
{
grant_read_lock(owner->grant_table);
ret = grant_map_exists(d, owner->grant_table, mfn, ref_count);
if ( ret != 0 )
act = grant_map_exists(d, owner->grant_table, mfn, ref_count);
if ( IS_ERR_OR_NULL(act) )
{
grant_read_unlock(owner->grant_table);
rcu_unlock_domain(d);
put_page(page);
return ret;
return act ? PTR_ERR(act) : 1;
}
}
@@ -3073,7 +3066,11 @@ static int __gnttab_cache_flush(const gnttab_cache_flush_t *cflush,
ret = 0;
if ( d != owner )
{
active_entry_release(act);
grant_read_unlock(owner->grant_table);
}
unmap_domain_page(v);
put_page(page);
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.