mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 18:50:05 +01:00
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:
1 parent
ba28eac093
commit
ed7765ae03
1 file changed
+17
-20
+17
-20
@@ -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);
|
||||
|
||||
|
||||