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

[Xen-changelog] Bug fix to stop leaking out-of-sync entries, and to stop trashing



ChangeSet 1.1236.32.7, 2005/03/16 01:12:53+00:00, mafetter@xxxxxxxxxxxxxxxx

        Bug fix to stop leaking out-of-sync entries, and to stop trashing
        the list of out-of-sync entries by manipulating it in one routine
        while walking it in another.
        
        Signed-off-by: michael.fetterman@xxxxxxxxxxxx



 arch/x86/shadow.c        |   60 +++++++++++++++++++++++++++++++++++------------
 include/asm-x86/shadow.h |    9 +++++--
 2 files changed, 52 insertions(+), 17 deletions(-)


diff -Nru a/xen/arch/x86/shadow.c b/xen/arch/x86/shadow.c
--- a/xen/arch/x86/shadow.c     2005-04-05 12:09:34 -04:00
+++ b/xen/arch/x86/shadow.c     2005-04-05 12:09:34 -04:00
@@ -70,7 +70,7 @@
         min_type = PGT_l1_shadow;
         max_type = PGT_l1_shadow;
     }
-    FSH_LOG("shadow_promote gpfn=%p gmfn=%p nt=%p min=%p max=%p\n",
+    FSH_LOG("shadow_promote gpfn=%p gmfn=%p nt=%p min=%p max=%p",
             gmfn, gmfn, new_type, min_type, max_type);
 
     if ( min_type <= max_type )
@@ -388,7 +388,12 @@
     // Only use entries that have low bits clear...
     //
     if ( !(entry->writable_pl1e & (sizeof(l1_pgentry_t)-1)) )
+    {
         put_shadow_ref(entry->writable_pl1e >> PAGE_SHIFT);
+        entry->writable_pl1e = -2;
+    }
+    else
+        ASSERT( entry->writable_pl1e == -1 );
 
     // Free the snapshot
     //
@@ -399,38 +404,63 @@
 {
     struct out_of_sync_entry *entry = d->arch.out_of_sync;
     struct out_of_sync_entry **prev = &d->arch.out_of_sync;
+    struct out_of_sync_entry *found = NULL;
 
+    // NB: Be careful not to call something that manipulates this list
+    //     while walking it.  Collect the results into a separate list
+    //     first, then walk that list.
+    //
     while ( entry )
     {
         if ( entry->gmfn == gmfn )
         {
-            release_out_of_sync_entry(d, entry);
-            *prev = entry = entry->next;
+            // remove from out of sync list
+            *prev = entry->next;
+
+            // add to found list
+            entry->next = found;
+            found = entry;
+
+            entry = *prev;
             continue;
         }
         prev = &entry->next;
         entry = entry->next;
     }
+
+    prev = NULL;
+    entry = found;
+    while ( entry )
+    {
+        release_out_of_sync_entry(d, entry);
+
+        prev = &entry->next;
+        entry = entry->next;
+    }
+
+    // Add found list to free list
+    if ( prev )
+    {
+        *prev = d->arch.out_of_sync_free;
+        d->arch.out_of_sync_free = found;
+    }
 }
 
 static void free_out_of_sync_state(struct domain *d)
 {
     struct out_of_sync_entry *entry;
-    struct out_of_sync_entry **tail = NULL;
 
-    // Add the list of out-of-sync entries to the free list of entries.
-    // Not the smartest code.  But it works.
+    // NB: Be careful not to call something that manipulates this list
+    //     while walking it.  Remove one item at a time, and always
+    //     restart from start of list.
     //
-    for ( entry = d->arch.out_of_sync; entry; entry = entry->next)
+    while ( (entry = d->arch.out_of_sync) )
     {
+        d->arch.out_of_sync = entry->next;
         release_out_of_sync_entry(d, entry);
-        tail = &entry->next;
-    }
-    if ( tail )
-    {
-        *tail = d->arch.out_of_sync_free;
-        d->arch.out_of_sync_free = d->arch.out_of_sync;
-        d->arch.out_of_sync = NULL;
+
+        entry->next = d->arch.out_of_sync_free;
+        d->arch.out_of_sync_free = entry;
     }
 }
 
@@ -1515,7 +1545,7 @@
                 put_page_from_l1e(mk_l1_pgentry(old), d);
 
             FSH_LOG("removed write access to mfn=%p in smfn=%p entry %x "
-                    "is_l1_shadow=%d\n",
+                    "is_l1_shadow=%d",
                     readonly_mfn, pt_mfn, i, is_l1_shadow);
         }
     }
diff -Nru a/xen/include/asm-x86/shadow.h b/xen/include/asm-x86/shadow.h
--- a/xen/include/asm-x86/shadow.h      2005-04-05 12:09:34 -04:00
+++ b/xen/include/asm-x86/shadow.h      2005-04-05 12:09:34 -04:00
@@ -375,8 +375,9 @@
 
     if ( unlikely(x == 0) )
     {
-        printk("put_shadow_ref underflow, gmfn=%p smfn=%p\n",
-               frame_table[smfn].u.inuse.type_info & PGT_mfn_mask, smfn);
+        printk("put_shadow_ref underflow, oc=%p t=%p\n",
+               frame_table[smfn].count_info,
+               frame_table[smfn].u.inuse.type_info);
         BUG();
     }
 
@@ -745,6 +746,9 @@
         BUG();
     }
 #endif
+
+    // XXX ought to add some code to audit the out-of-sync entries, too.
+    //
 }
 #else
 #define shadow_audit(p, print) ((void)0)
@@ -1041,6 +1045,7 @@
     {
         if ( x->gpfn_and_flags == key )
         {
+            BUG();
             x->smfn = smfn;
             goto done;
         }

_______________________________________________
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®.