ia64/xen-unstable

changeset 4170:f04c449d7f82

bitkeeper revision 1.1236.32.7 (42378815CN21q6LzdBeA_XOojCOrwg)

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@cl.cam.ac.uk
author mafetter@fleming.research
date Wed Mar 16 01:12:53 2005 +0000 (2005-03-16)
parents 44b147d903bc
children e40b961673f2
files xen/arch/x86/shadow.c xen/include/asm-x86/shadow.h
line diff
     1.1 --- a/xen/arch/x86/shadow.c	Tue Mar 15 15:10:08 2005 +0000
     1.2 +++ b/xen/arch/x86/shadow.c	Wed Mar 16 01:12:53 2005 +0000
     1.3 @@ -70,7 +70,7 @@ shadow_promote(struct domain *d, unsigne
     1.4          min_type = PGT_l1_shadow;
     1.5          max_type = PGT_l1_shadow;
     1.6      }
     1.7 -    FSH_LOG("shadow_promote gpfn=%p gmfn=%p nt=%p min=%p max=%p\n",
     1.8 +    FSH_LOG("shadow_promote gpfn=%p gmfn=%p nt=%p min=%p max=%p",
     1.9              gmfn, gmfn, new_type, min_type, max_type);
    1.10  
    1.11      if ( min_type <= max_type )
    1.12 @@ -388,7 +388,12 @@ release_out_of_sync_entry(struct domain 
    1.13      // Only use entries that have low bits clear...
    1.14      //
    1.15      if ( !(entry->writable_pl1e & (sizeof(l1_pgentry_t)-1)) )
    1.16 +    {
    1.17          put_shadow_ref(entry->writable_pl1e >> PAGE_SHIFT);
    1.18 +        entry->writable_pl1e = -2;
    1.19 +    }
    1.20 +    else
    1.21 +        ASSERT( entry->writable_pl1e == -1 );
    1.22  
    1.23      // Free the snapshot
    1.24      //
    1.25 @@ -399,38 +404,63 @@ static void remove_out_of_sync_entries(s
    1.26  {
    1.27      struct out_of_sync_entry *entry = d->arch.out_of_sync;
    1.28      struct out_of_sync_entry **prev = &d->arch.out_of_sync;
    1.29 +    struct out_of_sync_entry *found = NULL;
    1.30  
    1.31 +    // NB: Be careful not to call something that manipulates this list
    1.32 +    //     while walking it.  Collect the results into a separate list
    1.33 +    //     first, then walk that list.
    1.34 +    //
    1.35      while ( entry )
    1.36      {
    1.37          if ( entry->gmfn == gmfn )
    1.38          {
    1.39 -            release_out_of_sync_entry(d, entry);
    1.40 -            *prev = entry = entry->next;
    1.41 +            // remove from out of sync list
    1.42 +            *prev = entry->next;
    1.43 +
    1.44 +            // add to found list
    1.45 +            entry->next = found;
    1.46 +            found = entry;
    1.47 +
    1.48 +            entry = *prev;
    1.49              continue;
    1.50          }
    1.51          prev = &entry->next;
    1.52          entry = entry->next;
    1.53      }
    1.54 +
    1.55 +    prev = NULL;
    1.56 +    entry = found;
    1.57 +    while ( entry )
    1.58 +    {
    1.59 +        release_out_of_sync_entry(d, entry);
    1.60 +
    1.61 +        prev = &entry->next;
    1.62 +        entry = entry->next;
    1.63 +    }
    1.64 +
    1.65 +    // Add found list to free list
    1.66 +    if ( prev )
    1.67 +    {
    1.68 +        *prev = d->arch.out_of_sync_free;
    1.69 +        d->arch.out_of_sync_free = found;
    1.70 +    }
    1.71  }
    1.72  
    1.73  static void free_out_of_sync_state(struct domain *d)
    1.74  {
    1.75      struct out_of_sync_entry *entry;
    1.76 -    struct out_of_sync_entry **tail = NULL;
    1.77  
    1.78 -    // Add the list of out-of-sync entries to the free list of entries.
    1.79 -    // Not the smartest code.  But it works.
    1.80 +    // NB: Be careful not to call something that manipulates this list
    1.81 +    //     while walking it.  Remove one item at a time, and always
    1.82 +    //     restart from start of list.
    1.83      //
    1.84 -    for ( entry = d->arch.out_of_sync; entry; entry = entry->next)
    1.85 +    while ( (entry = d->arch.out_of_sync) )
    1.86      {
    1.87 +        d->arch.out_of_sync = entry->next;
    1.88          release_out_of_sync_entry(d, entry);
    1.89 -        tail = &entry->next;
    1.90 -    }
    1.91 -    if ( tail )
    1.92 -    {
    1.93 -        *tail = d->arch.out_of_sync_free;
    1.94 -        d->arch.out_of_sync_free = d->arch.out_of_sync;
    1.95 -        d->arch.out_of_sync = NULL;
    1.96 +
    1.97 +        entry->next = d->arch.out_of_sync_free;
    1.98 +        d->arch.out_of_sync_free = entry;
    1.99      }
   1.100  }
   1.101  
   1.102 @@ -1515,7 +1545,7 @@ static u32 remove_all_write_access_in_pt
   1.103                  put_page_from_l1e(mk_l1_pgentry(old), d);
   1.104  
   1.105              FSH_LOG("removed write access to mfn=%p in smfn=%p entry %x "
   1.106 -                    "is_l1_shadow=%d\n",
   1.107 +                    "is_l1_shadow=%d",
   1.108                      readonly_mfn, pt_mfn, i, is_l1_shadow);
   1.109          }
   1.110      }
     2.1 --- a/xen/include/asm-x86/shadow.h	Tue Mar 15 15:10:08 2005 +0000
     2.2 +++ b/xen/include/asm-x86/shadow.h	Wed Mar 16 01:12:53 2005 +0000
     2.3 @@ -375,8 +375,9 @@ put_shadow_ref(unsigned long smfn)
     2.4  
     2.5      if ( unlikely(x == 0) )
     2.6      {
     2.7 -        printk("put_shadow_ref underflow, gmfn=%p smfn=%p\n",
     2.8 -               frame_table[smfn].u.inuse.type_info & PGT_mfn_mask, smfn);
     2.9 +        printk("put_shadow_ref underflow, oc=%p t=%p\n",
    2.10 +               frame_table[smfn].count_info,
    2.11 +               frame_table[smfn].u.inuse.type_info);
    2.12          BUG();
    2.13      }
    2.14  
    2.15 @@ -745,6 +746,9 @@ static void shadow_audit(struct domain *
    2.16          BUG();
    2.17      }
    2.18  #endif
    2.19 +
    2.20 +    // XXX ought to add some code to audit the out-of-sync entries, too.
    2.21 +    //
    2.22  }
    2.23  #else
    2.24  #define shadow_audit(p, print) ((void)0)
    2.25 @@ -1041,6 +1045,7 @@ static inline void set_shadow_status(
    2.26      {
    2.27          if ( x->gpfn_and_flags == key )
    2.28          {
    2.29 +            BUG();
    2.30              x->smfn = smfn;
    2.31              goto done;
    2.32          }