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

[Xen-changelog] [xen-unstable] [XEN] Clean up grant-table pinning logic.



# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxxxxxxxx
# Node ID 66dd34f2f439e49e5a19c77ac7e7085a8b18a226
# Parent  4fc1688d9a163644b4c3b15072432d1c2b203c50
[XEN] Clean up grant-table pinning logic.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
 xen/common/grant_table.c |  154 +++++++++++++++++++++--------------------------
 1 files changed, 70 insertions(+), 84 deletions(-)

diff -r 4fc1688d9a16 -r 66dd34f2f439 xen/common/grant_table.c
--- a/xen/common/grant_table.c  Tue Sep 05 17:26:20 2006 +0100
+++ b/xen/common/grant_table.c  Tue Sep 05 12:20:31 2006 -0700
@@ -90,11 +90,8 @@ __gnttab_map_grant_ref(
     unsigned long  frame = 0;
     int            rc = GNTST_okay;
     struct active_grant_entry *act;
-
-    /* Entry details from @rd's shared grant table. */
     grant_entry_t *sha;
-    domid_t        sdom;
-    u16            sflags;
+    union grant_combo scombo, prev_scombo, new_scombo;
 
     /*
      * We bound the number of times we retry CMPXCHG on memory locations that
@@ -175,13 +172,20 @@ __gnttab_map_grant_ref(
 
     spin_lock(&rd->grant_table->lock);
 
-    sdom = sha->domid;
+    /* If already pinned, check the active domid and avoid refcnt overflow. */
+    if ( act->pin &&
+         ((act->domid != ld->domain_id) ||
+          (act->pin & 0x80808080U) != 0) )
+        PIN_FAIL(unlock_out, GNTST_general_error,
+                 "Bad domain (%d != %d), or risk of counter overflow %08x\n",
+                 act->domid, ld->domain_id, act->pin);
 
     if ( !act->pin ||
          (!(op->flags & GNTMAP_readonly) &&
           !(act->pin & (GNTPIN_hstw_mask|GNTPIN_devw_mask))) )
     {
-        sflags = sha->flags;
+        scombo.shorts.flags = sha->flags;
+        scombo.shorts.domid = sha->domid;
 
         /*
          * This loop attempts to set the access (reading/writing) flags
@@ -191,33 +195,29 @@ __gnttab_map_grant_ref(
          */
         for ( ; ; )
         {
-            union grant_combo scombo, prev_scombo, new_scombo;
-
-            if ( unlikely((sflags & GTF_type_mask) != GTF_permit_access) ||
-                 unlikely(sdom != led->domain->domain_id) )
-                PIN_FAIL(unlock_out, GNTST_general_error,
-                         "Bad flags (%x) or dom (%d). (NB. expected dom %d)\n",
-                         sflags, sdom, led->domain->domain_id);
-
-            /* Merge two 16-bit values into a 32-bit combined update. */
-            scombo.shorts.flags = sflags;
-            scombo.shorts.domid = sdom;
-            
+            /* If not already pinned, check the grant domid and type. */
+            if ( !act->pin &&
+                 (((scombo.shorts.flags & GTF_type_mask) !=
+                   GTF_permit_access) ||
+                  (scombo.shorts.domid != ld->domain_id)) )
+                 PIN_FAIL(unlock_out, GNTST_general_error,
+                          "Bad flags (%x) or dom (%d). (expected dom %d)\n",
+                          scombo.shorts.flags, scombo.shorts.domid,
+                          ld->domain_id);
+
             new_scombo = scombo;
             new_scombo.shorts.flags |= GTF_reading;
 
             if ( !(op->flags & GNTMAP_readonly) )
             {
                 new_scombo.shorts.flags |= GTF_writing;
-                if ( unlikely(sflags & GTF_readonly) )
+                if ( unlikely(scombo.shorts.flags & GTF_readonly) )
                     PIN_FAIL(unlock_out, GNTST_general_error,
                              "Attempt to write-pin a r/o grant entry.\n");
             }
 
             prev_scombo.word = cmpxchg((u32 *)&sha->flags,
                                        scombo.word, new_scombo.word);
-
-            /* Did the combined update work (did we see what we expected?). */
             if ( likely(prev_scombo.word == scombo.word) )
                 break;
 
@@ -225,24 +225,15 @@ __gnttab_map_grant_ref(
                 PIN_FAIL(unlock_out, GNTST_general_error,
                          "Shared grant entry is unstable.\n");
 
-            /* Didn't see what we expected. Split out the seen flags & dom. */
-            sflags = prev_scombo.shorts.flags;
-            sdom   = prev_scombo.shorts.domid;
+            scombo = prev_scombo;
         }
 
         if ( !act->pin )
         {
-            act->domid = sdom;
+            act->domid = scombo.shorts.domid;
             act->frame = gmfn_to_mfn(rd, sha->frame);
         }
     }
-    else if ( unlikely(sdom != ld->domain_id) )
-        PIN_FAIL(unlock_out, GNTST_general_error,
-                 "Bad domain (%d). (NB. expected dom %d)\n",
-                 sdom, ld->domain_id);
-    else if ( (act->pin & 0x80808080U) != 0 )
-        PIN_FAIL(unlock_out, ENOSPC,
-                 "Risk of counter overflow %08x\n", act->pin);
 
     if ( op->flags & GNTMAP_device_map )
         act->pin += (op->flags & GNTMAP_readonly) ?
@@ -550,9 +541,7 @@ gnttab_prepare_for_transfer(
 {
     struct grant_table *rgt;
     struct grant_entry *sha;
-    domid_t             sdom;
-    u16                 sflags;
-    union grant_combo   scombo, prev_scombo, tmp_scombo;
+    union grant_combo   scombo, prev_scombo, new_scombo;
     int                 retries = 0;
 
     if ( unlikely((rgt = rd->grant_table) == NULL) ||
@@ -567,29 +556,25 @@ gnttab_prepare_for_transfer(
 
     sha = &rgt->shared[ref];
     
-    sflags = sha->flags;
-    sdom   = sha->domid;
+    scombo.shorts.flags = sha->flags;
+    scombo.shorts.domid = sha->domid;
 
     for ( ; ; )
     {
-        if ( unlikely(sflags != GTF_accept_transfer) ||
-             unlikely(sdom != ld->domain_id) )
+        if ( unlikely(scombo.shorts.flags != GTF_accept_transfer) ||
+             unlikely(scombo.shorts.domid != ld->domain_id) )
         {
             DPRINTK("Bad flags (%x) or dom (%d). (NB. expected dom %d)\n",
-                    sflags, sdom, ld->domain_id);
+                    scombo.shorts.flags, scombo.shorts.domid,
+                    ld->domain_id);
             goto fail;
         }
 
-        /* Merge two 16-bit values into a 32-bit combined update. */
-        scombo.shorts.flags = sflags;
-        scombo.shorts.domid = sdom;
-
-        tmp_scombo = scombo;
-        tmp_scombo.shorts.flags |= GTF_transfer_committed;
+        new_scombo = scombo;
+        new_scombo.shorts.flags |= GTF_transfer_committed;
+
         prev_scombo.word = cmpxchg((u32 *)&sha->flags,
-                                   scombo.word, tmp_scombo.word);
-
-        /* Did the combined update work (did we see what we expected?). */
+                                   scombo.word, new_scombo.word);
         if ( likely(prev_scombo.word == scombo.word) )
             break;
 
@@ -599,9 +584,7 @@ gnttab_prepare_for_transfer(
             goto fail;
         }
 
-        /* Didn't see what we expected. Split out the seen flags & dom. */
-        sflags = prev_scombo.shorts.flags;
-        sdom   = prev_scombo.shorts.domid;
+        scombo = prev_scombo;
     }
 
     spin_unlock(&rgt->lock);
@@ -739,16 +722,21 @@ __release_grant_for_copy(
         gnttab_mark_dirty(rd, r_frame);
 
     spin_lock(&rd->grant_table->lock);
+
     if ( readonly )
+    {
         act->pin -= GNTPIN_hstr_inc;
+    }
     else
+    {
         act->pin -= GNTPIN_hstw_inc;
-
-    if ( !(act->pin & GNTPIN_hstw_mask) && !readonly )
-        gnttab_clear_flag(_GTF_writing, &sha->flags);
+        if ( !(act->pin & (GNTPIN_devw_mask|GNTPIN_hstw_mask)) )
+            gnttab_clear_flag(_GTF_writing, &sha->flags);
+    }
 
     if ( !act->pin )
         gnttab_clear_flag(_GTF_reading, &sha->flags);
+
     spin_unlock(&rd->grant_table->lock);
 }
 
@@ -764,8 +752,7 @@ __acquire_grant_for_copy(
     struct active_grant_entry *act;
     s16 rc = GNTST_okay;
     int retries = 0;
-    u16 sflags;
-    domid_t sdom;
+    union grant_combo scombo, prev_scombo, new_scombo;
 
     if ( unlikely(gref >= NR_GRANT_ENTRIES) )
         PIN_FAIL(error_out, GNTST_bad_gntref,
@@ -776,37 +763,43 @@ __acquire_grant_for_copy(
 
     spin_lock(&rd->grant_table->lock);
     
-    sdom = sha->domid;
+    /* If already pinned, check the active domid and avoid refcnt overflow. */
+    if ( act->pin &&
+         ((act->domid != current->domain->domain_id) ||
+          (act->pin & 0x80808080U) != 0) )
+        PIN_FAIL(unlock_out, GNTST_general_error,
+                 "Bad domain (%d != %d), or risk of counter overflow %08x\n",
+                 act->domid, current->domain->domain_id, act->pin);
 
     if ( !act->pin ||
-         (!readonly && !(act->pin & GNTPIN_hstw_mask)) )
-    {
-        sflags = sha->flags;
+         (!readonly && !(act->pin & (GNTPIN_devw_mask|GNTPIN_hstw_mask))) )
+    {
+        scombo.shorts.flags = sha->flags;
+        scombo.shorts.domid = sha->domid;
 
         for ( ; ; )
         {
-            union grant_combo scombo, prev_scombo, new_scombo;
-
-            if ( unlikely((sflags & GTF_type_mask) != GTF_permit_access ||
-                          sdom != current->domain->domain_id ) )
-                PIN_FAIL(unlock_out, GNTST_general_error,
-                         "Bad flags (%x) or dom (%d). (NB. expected dom %d)\n",
-                         sflags, sdom, current->domain->domain_id);
-
-            /* Merge two 16-bit values into a 32-bit combined update. */
-            scombo.shorts.flags = sflags;
-            scombo.shorts.domid = sdom;
-            
+            /* If not already pinned, check the grant domid and type. */
+            if ( !act->pin &&
+                 (((scombo.shorts.flags & GTF_type_mask) !=
+                   GTF_permit_access) ||
+                  (scombo.shorts.domid != current->domain->domain_id)) )
+                 PIN_FAIL(unlock_out, GNTST_general_error,
+                          "Bad flags (%x) or dom (%d). (expected dom %d)\n",
+                          scombo.shorts.flags, scombo.shorts.domid,
+                          current->domain->domain_id);
+
             new_scombo = scombo;
             new_scombo.shorts.flags |= GTF_reading;
 
             if ( !readonly )
             {
                 new_scombo.shorts.flags |= GTF_writing;
-                if ( unlikely(sflags & GTF_readonly) )
+                if ( unlikely(scombo.shorts.flags & GTF_readonly) )
                     PIN_FAIL(unlock_out, GNTST_general_error,
                              "Attempt to write-pin a r/o grant entry.\n");
             }
+
             prev_scombo.word = cmpxchg((u32 *)&sha->flags,
                                        scombo.word, new_scombo.word);
             if ( likely(prev_scombo.word == scombo.word) )
@@ -815,23 +808,16 @@ __acquire_grant_for_copy(
             if ( retries++ == 4 )
                 PIN_FAIL(unlock_out, GNTST_general_error,
                          "Shared grant entry is unstable.\n");
-            sflags = prev_scombo.shorts.flags;
-            sdom = prev_scombo.shorts.flags;
+
+            scombo = prev_scombo;
         }
 
         if ( !act->pin )
         {
-            act->domid = sdom;
+            act->domid = scombo.shorts.domid;
             act->frame = gmfn_to_mfn(rd, sha->frame);
         }
     }
-    else if ( unlikely(sdom != current->domain->domain_id) )
-        PIN_FAIL(unlock_out, GNTST_general_error,
-                 "Bad domain (%d). (NB. expected dom %d)\n",
-                 sdom, current->domain->domain_id);
-    else if ( (act->pin & 0x80808080U) != 0 )
-        PIN_FAIL(unlock_out, ENOSPC,
-                 "Risk of counter overflow %08x\n", act->pin);
 
     act->pin += readonly ? GNTPIN_hstr_inc : GNTPIN_hstw_inc;
 

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

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