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. */