[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v2] gnttab: defer allocation of status frame tracking array



Hi Jan,

On 23/12/2020 15:13, Jan Beulich wrote:
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. */

I think gt->status cannot be accessed locklessly. If a entity read gt->nr_status_frames != 0, then there is no promise the array will be accessible when trying to access it as it may have been freed.

So I would drop the barrier here.

The rest of the code looks good to me.

Cheers,

--
Julien Grall



 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.