This array can be large when many grant frames are permitted; avoid
allocating it when it's not going to be used anyway, by doing this only
in gnttab_populate_status_frames().
Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>
---
v2: Defer allocation to when a domain actually switches to the v2 grant
API.
--- a/xen/common/grant_table.c
+++ b/xen/common/grant_table.c
@@ -1725,6 +1728,17 @@ gnttab_populate_status_frames(struct dom
/* Make sure, prior version checks are architectural visible */
block_speculation();
+ if ( gt->status == ZERO_BLOCK_PTR )
+ {
+ gt->status = xzalloc_array(grant_status_t *,
+
grant_to_status_frames(gt->max_grant_frames));
+ if ( !gt->status )
+ {
+ gt->status = ZERO_BLOCK_PTR;
+ return -ENOMEM;
+ }
+ }
+
for ( i = nr_status_frames(gt); i < req_status_frames; i++ )
{
if ( (gt->status[i] = alloc_xenheap_page()) == NULL )
@@ -1745,18 +1759,23 @@ status_alloc_failed:
free_xenheap_page(gt->status[i]);
gt->status[i] = NULL;
}
+ if ( !nr_status_frames(gt) )
+ {
+ xfree(gt->status);
+ gt->status = ZERO_BLOCK_PTR;
+ }
return -ENOMEM;
}
static int
gnttab_unpopulate_status_frames(struct domain *d, struct grant_table *gt)
{
- unsigned int i;
+ unsigned int i, n = nr_status_frames(gt);
/* Make sure, prior version checks are architectural visible */
block_speculation();
- for ( i = 0; i < nr_status_frames(gt); i++ )
+ for ( i = 0; i < n; i++ )
{
struct page_info *pg = virt_to_page(gt->status[i]);
gfn_t gfn = gnttab_get_frame_gfn(gt, true, i);
@@ -1811,12 +1830,12 @@ gnttab_unpopulate_status_frames(struct d
page_set_owner(pg, NULL);
}
- for ( i = 0; i < nr_status_frames(gt); i++ )
- {
- free_xenheap_page(gt->status[i]);
- gt->status[i] = NULL;
- }
gt->nr_status_frames = 0;
+ smp_wmb(); /* Just in case - all accesses should be under lock. */