ia64/xen-unstable

changeset 1560:16c2273aaf2c

bitkeeper revision 1.921.1.1 (40dab1f9AV7eQ2rrrWjdce8ozia3XQ)

add more stats collection to migration, prepare for NGIO fixup.
author iap10@labyrinth.cl.cam.ac.uk
date Thu Jun 24 10:50:33 2004 +0000 (2004-06-24)
parents 8ae534da09e8
children eec2392c11f7
files tools/xc/lib/xc.h tools/xc/lib/xc_domain.c tools/xc/lib/xc_linux_save.c tools/xc/py/Xc.c xen/common/shadow.c xen/drivers/block/xen_block.c xen/include/asm-i386/processor.h xen/include/hypervisor-ifs/dom0_ops.h xen/include/xen/shadow.h xen/net/dev.c
line diff
     1.1 --- a/tools/xc/lib/xc.h	Mon May 24 18:13:06 2004 +0000
     1.2 +++ b/tools/xc/lib/xc.h	Thu Jun 24 10:50:33 2004 +0000
     1.3 @@ -35,6 +35,14 @@ typedef struct {
     1.4      unsigned long max_memkb;
     1.5  } xc_dominfo_t;
     1.6  
     1.7 +typedef struct xc_shadow_control_stats_st
     1.8 +{
     1.9 +    unsigned long fault_count;
    1.10 +    unsigned long dirty_count;
    1.11 +    unsigned long dirty_net_count;     
    1.12 +    unsigned long dirty_block_count;     
    1.13 +} xc_shadow_control_stats_t;
    1.14 +
    1.15  int xc_domain_create(int xc_handle, 
    1.16                       unsigned int mem_kb, 
    1.17                       const char *name,
    1.18 @@ -60,8 +68,7 @@ int xc_shadow_control(int xc_handle,
    1.19                        unsigned int sop,
    1.20  		      unsigned long *dirty_bitmap,
    1.21  		      unsigned long pages,
    1.22 -		      unsigned long *fault_count,
    1.23 -		      unsigned long *dirty_count);
    1.24 +		      xc_shadow_control_stats_t *stats);
    1.25  
    1.26  
    1.27  #define XCFLAGS_VERBOSE 1
     2.1 --- a/tools/xc/lib/xc_domain.c	Mon May 24 18:13:06 2004 +0000
     2.2 +++ b/tools/xc/lib/xc_domain.c	Thu Jun 24 10:50:33 2004 +0000
     2.3 @@ -113,8 +113,7 @@ int xc_shadow_control(int xc_handle,
     2.4                        unsigned int sop,
     2.5  		      unsigned long *dirty_bitmap,
     2.6  		      unsigned long pages,
     2.7 -		      unsigned long *fault_count,
     2.8 -		      unsigned long *dirty_count)
     2.9 +		      xc_shadow_control_stats_t *stats )
    2.10  {
    2.11      int rc;
    2.12      dom0_op_t op;
    2.13 @@ -126,8 +125,8 @@ int xc_shadow_control(int xc_handle,
    2.14  
    2.15      rc = do_dom0_op(xc_handle, &op);
    2.16  
    2.17 -    if(fault_count) *fault_count = op.u.shadow_control.fault_count;
    2.18 -    if(dirty_count) *dirty_count = op.u.shadow_control.dirty_count;
    2.19 +    if(stats) memcpy(stats, &op.u.shadow_control.stats,
    2.20 +		     sizeof(xc_shadow_control_stats_t));
    2.21  
    2.22      if ( rc == 0 )
    2.23  	return op.u.shadow_control.pages;
     3.1 --- a/tools/xc/lib/xc_linux_save.c	Mon May 24 18:13:06 2004 +0000
     3.2 +++ b/tools/xc/lib/xc_linux_save.c	Thu Jun 24 10:50:33 2004 +0000
     3.3 @@ -144,14 +144,22 @@ static long long tv_to_us( struct timeva
     3.4      return (new->tv_sec * 1000000) + new->tv_usec;
     3.5  }
     3.6  
     3.7 -static long long tvdelta( struct timeval *new, struct timeval *old )
     3.8 +static long long llgettimeofday()
     3.9 +{
    3.10 +    struct timeval now;
    3.11 +    gettimeofday(&now, NULL);
    3.12 +    return tv_to_us(&now);
    3.13 +}
    3.14 +
    3.15 +static long long tv_delta( struct timeval *new, struct timeval *old )
    3.16  {
    3.17      return ((new->tv_sec - old->tv_sec)*1000000 ) + 
    3.18  	(new->tv_usec - old->tv_usec);
    3.19  }
    3.20  
    3.21 -static int track_cpu_usage( int xc_handle, u64 domid, int faults,
    3.22 -			    int pages_sent, int pages_dirtied, int print )
    3.23 +static int print_stats( int xc_handle, u64 domid, 
    3.24 +			int pages_sent, xc_shadow_control_stats_t *stats,
    3.25 +			int print )
    3.26  {
    3.27      static struct timeval wall_last;
    3.28      static long long      d0_cpu_last;
    3.29 @@ -162,7 +170,6 @@ static int track_cpu_usage( int xc_handl
    3.30      long long             d0_cpu_now, d0_cpu_delta;
    3.31      long long             d1_cpu_now, d1_cpu_delta;
    3.32  
    3.33 -
    3.34      gettimeofday(&wall_now, NULL);
    3.35  
    3.36      d0_cpu_now = xc_domain_get_cpu_usage( xc_handle, 0 )/1000;
    3.37 @@ -173,7 +180,7 @@ static int track_cpu_usage( int xc_handl
    3.38  	printf("ARRHHH!!\n");
    3.39      }
    3.40  
    3.41 -    wall_delta = tvdelta(&wall_now,&wall_last)/1000;
    3.42 +    wall_delta = tv_delta(&wall_now,&wall_last)/1000;
    3.43  
    3.44      if ( wall_delta == 0 ) wall_delta = 1;
    3.45  
    3.46 @@ -186,7 +193,7 @@ static int track_cpu_usage( int xc_handl
    3.47  	       (int)((d0_cpu_delta*100)/wall_delta),
    3.48  	       (int)((d1_cpu_delta*100)/wall_delta),
    3.49  	       (int)((pages_sent*PAGE_SIZE*8)/(wall_delta*1000)),
    3.50 -	       (int)((pages_dirtied*PAGE_SIZE*8)/(wall_delta*1000))
    3.51 +	       (int)((stats->dirty_count*PAGE_SIZE*8)/(wall_delta*1000))
    3.52  	    );
    3.53  
    3.54      d0_cpu_last  = d0_cpu_now;
    3.55 @@ -197,6 +204,44 @@ static int track_cpu_usage( int xc_handl
    3.56  }
    3.57  
    3.58  
    3.59 +static int analysis_phase( int xc_handle, u64 domid, 
    3.60 +			   int nr_pfns, unsigned long *arr )
    3.61 +{
    3.62 +    long long start, now;
    3.63 +    xc_shadow_control_stats_t stats;
    3.64 +
    3.65 +    start = llgettimeofday();
    3.66 +
    3.67 +    while(0)
    3.68 +    {
    3.69 +	int i;
    3.70 +
    3.71 +	xc_shadow_control( xc_handle, domid, 
    3.72 +			   DOM0_SHADOW_CONTROL_OP_CLEAN2,
    3.73 +			   arr, nr_pfns, NULL);
    3.74 +	printf("#Flush\n");
    3.75 +	for(i=0;i<100;i++)
    3.76 +	{	    
    3.77 +	    usleep(10000);	    
    3.78 +	    now = llgettimeofday();
    3.79 +	    xc_shadow_control( xc_handle, domid, 
    3.80 +			       DOM0_SHADOW_CONTROL_OP_PEEK,
    3.81 +			       NULL, 0, &stats);
    3.82 +
    3.83 +	    printf("now= %lld faults= %ld dirty= %ld dirty_net= %ld dirty_block= %ld\n", 
    3.84 +		   ((now-start)+500)/1000, 
    3.85 +		   stats.fault_count, stats.dirty_count,
    3.86 +		   stats.dirty_net_count, stats.dirty_block_count );
    3.87 +
    3.88 +	}
    3.89 +
    3.90 +
    3.91 +    }
    3.92 +    
    3.93 +
    3.94 +    return -1;
    3.95 +}
    3.96 +
    3.97  int xc_linux_save(int xc_handle,
    3.98                    u64 domid, 
    3.99  		  unsigned int flags,
   3.100 @@ -210,7 +255,6 @@ int xc_linux_save(int xc_handle,
   3.101      int live = flags & XCFLAGS_LIVE;
   3.102      int debug = flags & XCFLAGS_DEBUG;
   3.103      int sent_last_iter, sent_this_iter, skip_this_iter;
   3.104 -    unsigned long dirtied_this_iter, faults_this_iter;
   3.105  
   3.106      /* Important tuning parameters */
   3.107      int max_iters  = 29; // limit us to 30 times round loop
   3.108 @@ -261,6 +305,8 @@ int xc_linux_save(int xc_handle,
   3.109         - to skip this iteration because already dirty;
   3.110         - to fixup by sending at the end if not already resent; */
   3.111      unsigned long *to_send, *to_skip, *to_fix;
   3.112 +    
   3.113 +    xc_shadow_control_stats_t stats;
   3.114  
   3.115      int needed_to_fix = 0;
   3.116      int total_sent    = 0;
   3.117 @@ -374,7 +420,7 @@ int xc_linux_save(int xc_handle,
   3.118      { 
   3.119  	if ( xc_shadow_control( xc_handle, domid, 
   3.120  			   DOM0_SHADOW_CONTROL_OP_ENABLE_LOGDIRTY,
   3.121 -			   NULL, 0, NULL, NULL ) < 0 )
   3.122 +			   NULL, 0, NULL ) < 0 )
   3.123  	{
   3.124  	    ERROR("Couldn't enable shadow mode");
   3.125  	    goto out;
   3.126 @@ -392,6 +438,9 @@ int xc_linux_save(int xc_handle,
   3.127      else
   3.128  	last_iter = 1;
   3.129  
   3.130 +    /* calculate the power of 2 order of nr_pfns, e.g.
   3.131 +     15->4 16->4 17->5 */
   3.132 +    for( i=nr_pfns-1, order_nr=0; i ; i>>=1, order_nr++ );
   3.133  
   3.134      /* Setup to_send bitmap */
   3.135      {
   3.136 @@ -425,11 +474,7 @@ int xc_linux_save(int xc_handle,
   3.137  
   3.138      }
   3.139  
   3.140 -    /* calculate the power of 2 order of nr_pfns, e.g.
   3.141 -     15->4 16->4 17->5 */
   3.142 -    for( i=nr_pfns-1, order_nr=0; i ; i>>=1, order_nr++ );
   3.143 -
   3.144 -printf("nr_pfns=%d order_nr=%d\n",nr_pfns, order_nr);
   3.145 +    analysis_phase( xc_handle, domid, nr_pfns, to_skip );
   3.146  
   3.147      /* We want zeroed memory so use calloc rather than malloc. */
   3.148      pfn_type = calloc(BATCH_SIZE, sizeof(unsigned long));
   3.149 @@ -484,7 +529,7 @@ printf("nr_pfns=%d order_nr=%d\n",nr_pfn
   3.150          goto out;
   3.151      }
   3.152  
   3.153 -    track_cpu_usage( xc_handle, domid, 0, 0, 0, 0 );
   3.154 +    print_stats( xc_handle, domid, 0, &stats, 0 );
   3.155  
   3.156      /* Now write out each data page, canonicalising page tables as we go... */
   3.157      
   3.158 @@ -516,7 +561,7 @@ printf("nr_pfns=%d order_nr=%d\n",nr_pfn
   3.159  	    if ( !last_iter && 
   3.160  		 xc_shadow_control(xc_handle, domid, 
   3.161  				   DOM0_SHADOW_CONTROL_OP_PEEK,
   3.162 -				   to_skip, nr_pfns, NULL, NULL) != nr_pfns ) 
   3.163 +				   to_skip, nr_pfns, NULL) != nr_pfns ) 
   3.164  	    {
   3.165  		ERROR("Error peeking shadow bitmap");
   3.166  		goto out;
   3.167 @@ -722,7 +767,7 @@ printf("nr_pfns=%d order_nr=%d\n",nr_pfn
   3.168  
   3.169  	if ( last_iter )
   3.170  	{
   3.171 -	    track_cpu_usage( xc_handle, domid, 0, sent_this_iter, 0, 1);
   3.172 +	    print_stats( xc_handle, domid, sent_this_iter, &stats, 1);
   3.173  
   3.174  	    verbose_printf("Total pages sent= %d (%.2fx)\n", 
   3.175  			   total_sent, ((float)total_sent)/nr_pfns );
   3.176 @@ -732,7 +777,7 @@ printf("nr_pfns=%d order_nr=%d\n",nr_pfn
   3.177  	if ( debug && last_iter )
   3.178  	{
   3.179  	    int minusone = -1;
   3.180 -	    memset( to_send, 0xff, nr_pfns/8 );
   3.181 +	    memset( to_send, 0xff, (nr_pfns+8)/8 );
   3.182  	    debug = 0;
   3.183  	    printf("Entering debug resend-all mode\n");
   3.184      
   3.185 @@ -766,8 +811,7 @@ printf("nr_pfns=%d order_nr=%d\n",nr_pfn
   3.186  
   3.187  	    if ( xc_shadow_control( xc_handle, domid, 
   3.188  				    DOM0_SHADOW_CONTROL_OP_CLEAN2,
   3.189 -				    to_send, nr_pfns, &faults_this_iter,
   3.190 -				    &dirtied_this_iter) != nr_pfns ) 
   3.191 +				    to_send, nr_pfns, &stats ) != nr_pfns ) 
   3.192  	    {
   3.193  		ERROR("Error flushing shadow PT");
   3.194  		goto out;
   3.195 @@ -775,9 +819,7 @@ printf("nr_pfns=%d order_nr=%d\n",nr_pfn
   3.196  
   3.197  	    sent_last_iter = sent_this_iter;
   3.198  
   3.199 -	    //dirtied_this_iter = count_bits( nr_pfns, to_send ); 
   3.200 -	    track_cpu_usage( xc_handle, domid, faults_this_iter,
   3.201 -			     sent_this_iter, dirtied_this_iter, 1);
   3.202 +	    print_stats( xc_handle, domid, sent_this_iter, &stats, 1);
   3.203  	    
   3.204  	}
   3.205  
     4.1 --- a/tools/xc/py/Xc.c	Mon May 24 18:13:06 2004 +0000
     4.2 +++ b/tools/xc/py/Xc.c	Thu Jun 24 10:50:33 2004 +0000
     4.3 @@ -1296,7 +1296,7 @@ static PyObject *pyxc_shadow_control(PyO
     4.4                                        &dom, &op) )
     4.5          return NULL;
     4.6  
     4.7 -    if ( xc_shadow_control(xc->xc_handle, dom, op, NULL, 0, NULL, NULL) < 0 )
     4.8 +    if ( xc_shadow_control(xc->xc_handle, dom, op, NULL, 0, NULL) < 0 )
     4.9          return PyErr_SetFromErrno(xc_error);
    4.10      
    4.11      Py_INCREF(zero);
     5.1 --- a/xen/common/shadow.c	Mon May 24 18:13:06 2004 +0000
     5.2 +++ b/xen/common/shadow.c	Thu Jun 24 10:50:33 2004 +0000
     5.3 @@ -48,7 +48,7 @@ fault handler spinning waiting to grab t
     5.4  intterupts disabled, hence we can't use the normal flush_tlb_cpu
     5.5  mechanism.
     5.6  
     5.7 -For the moment, we have a grim hace whereby the spinlock in the shadow
     5.8 +For the moment, we have a grim race whereby the spinlock in the shadow
     5.9  fault handler is actually a try lock, in a loop with a helper for the
    5.10  tlb flush code.
    5.11  
    5.12 @@ -379,6 +379,17 @@ static int shadow_mode_table_op( struct 
    5.13  		__scan_shadow_table( m, TABLE_OP_FREE_L1 );
    5.14  		
    5.15  	send_bitmap:
    5.16 +		sc->stats.fault_count       = p->mm.shadow_fault_count;
    5.17 +		sc->stats.dirty_count       = p->mm.shadow_dirty_count;
    5.18 +		sc->stats.dirty_net_count   = p->mm.shadow_dirty_net_count;
    5.19 +		sc->stats.dirty_block_count = p->mm.shadow_dirty_block_count;
    5.20 +
    5.21 +		p->mm.shadow_fault_count       = 0;
    5.22 +		p->mm.shadow_dirty_count       = 0;
    5.23 +		p->mm.shadow_dirty_net_count   = 0;
    5.24 +		p->mm.shadow_dirty_block_count = 0;
    5.25 +	
    5.26 +		sc->pages = p->tot_pages;
    5.27  
    5.28  		if( p->tot_pages > sc->pages || 
    5.29  			!sc->dirty_bitmap || !p->mm.shadow_dirty_bitmap )
    5.30 @@ -387,12 +398,6 @@ static int shadow_mode_table_op( struct 
    5.31  			goto out;
    5.32  		}
    5.33  
    5.34 -		sc->fault_count = p->mm.shadow_fault_count;
    5.35 -		sc->dirty_count = p->mm.shadow_dirty_count;
    5.36 -		p->mm.shadow_fault_count = 0;
    5.37 -		p->mm.shadow_dirty_count = 0;
    5.38 -	
    5.39 -		sc->pages = p->tot_pages;
    5.40  	
    5.41  #define chunk (8*1024) // do this in 1KB chunks for L1 cache
    5.42  	
    5.43 @@ -428,6 +433,11 @@ static int shadow_mode_table_op( struct 
    5.44      case DOM0_SHADOW_CONTROL_OP_PEEK:
    5.45      {
    5.46  		int i;
    5.47 +
    5.48 +		sc->stats.fault_count       = p->mm.shadow_fault_count;
    5.49 +		sc->stats.dirty_count       = p->mm.shadow_dirty_count;
    5.50 +		sc->stats.dirty_net_count   = p->mm.shadow_dirty_net_count;
    5.51 +		sc->stats.dirty_block_count = p->mm.shadow_dirty_block_count;
    5.52  	
    5.53  		if( p->tot_pages > sc->pages || 
    5.54  			!sc->dirty_bitmap || !p->mm.shadow_dirty_bitmap )
    5.55 @@ -724,7 +734,7 @@ int shadow_fault( unsigned long va, long
    5.56              int i;
    5.57              sl1pfn_info = alloc_shadow_page( &current->mm ); 
    5.58              sl1pfn_info->type_and_flags = PGT_l1_page_table;
    5.59 -
    5.60 +			
    5.61              sl1pfn = sl1pfn_info - frame_table;
    5.62  
    5.63              SH_VVLOG("4a: l1 not shadowed ( %08lx )",sl1pfn);
     6.1 --- a/xen/drivers/block/xen_block.c	Mon May 24 18:13:06 2004 +0000
     6.2 +++ b/xen/drivers/block/xen_block.c	Thu Jun 24 10:50:33 2004 +0000
     6.3 @@ -364,7 +364,8 @@ static void unlock_buffer(unsigned long 
     6.4  	struct task_struct *p = frame_table[pfn].u.domain;
     6.5  
     6.6  	if( p->mm.shadow_mode == SHM_logdirty )
     6.7 -	    mark_dirty( &p->mm, pfn );	
     6.8 +	    if( mark_dirty( &p->mm, pfn ) )
     6.9 +		p->mm.shadow_dirty_block_count++;
    6.10  
    6.11  
    6.12          if ( writeable_buffer )
     7.1 --- a/xen/include/asm-i386/processor.h	Mon May 24 18:13:06 2004 +0000
     7.2 +++ b/xen/include/asm-i386/processor.h	Thu Jun 24 10:50:33 2004 +0000
     7.3 @@ -465,6 +465,8 @@ struct mm_struct {
     7.4      unsigned int shadow_page_count;     
     7.5      unsigned int shadow_fault_count;     
     7.6      unsigned int shadow_dirty_count;     
     7.7 +    unsigned int shadow_dirty_net_count;     
     7.8 +    unsigned int shadow_dirty_block_count;     
     7.9  
    7.10  
    7.11      /* Current LDT details. */
     8.1 --- a/xen/include/hypervisor-ifs/dom0_ops.h	Mon May 24 18:13:06 2004 +0000
     8.2 +++ b/xen/include/hypervisor-ifs/dom0_ops.h	Thu Jun 24 10:50:33 2004 +0000
     8.3 @@ -245,10 +245,20 @@ typedef struct dom0_sched_id_st
     8.4  #define DOM0_SHADOW_CONTROL_OP_OFF         0
     8.5  #define DOM0_SHADOW_CONTROL_OP_ENABLE_TEST 1
     8.6  #define DOM0_SHADOW_CONTROL_OP_ENABLE_LOGDIRTY 2
     8.7 +#define DOM0_SHADOW_CONTROL_OP_ENABLE_TRANSLATE 3
     8.8  #define DOM0_SHADOW_CONTROL_OP_FLUSH       10     /* table ops */
     8.9  #define DOM0_SHADOW_CONTROL_OP_CLEAN       11
    8.10  #define DOM0_SHADOW_CONTROL_OP_PEEK        12
    8.11  #define DOM0_SHADOW_CONTROL_OP_CLEAN2      13
    8.12 +
    8.13 +typedef struct dom0_shadow_control_stats_st
    8.14 +{
    8.15 +    unsigned long fault_count;
    8.16 +    unsigned long dirty_count;
    8.17 +    unsigned long dirty_net_count;     
    8.18 +    unsigned long dirty_block_count;     
    8.19 +} dom0_shadow_control_stats_t;
    8.20 +
    8.21  typedef struct dom0_shadow_control_st
    8.22  {
    8.23      /* IN variables. */
    8.24 @@ -258,8 +268,7 @@ typedef struct dom0_shadow_control_st
    8.25      /* IN/OUT variables */
    8.26      unsigned long  pages;  // size of buffer, updated with actual size
    8.27      /* OUT varaibles */
    8.28 -    unsigned long fault_count;
    8.29 -    unsigned long dirty_count;
    8.30 +    dom0_shadow_control_stats_t stats;
    8.31  } dom0_shadow_control_t;
    8.32  
    8.33  #define DOM0_SETDOMAINNAME     26
     9.1 --- a/xen/include/xen/shadow.h	Mon May 24 18:13:06 2004 +0000
     9.2 +++ b/xen/include/xen/shadow.h	Thu Jun 24 10:50:33 2004 +0000
     9.3 @@ -17,8 +17,9 @@
     9.4  /* Shadow PT operation mode : shadowmode variable in mm_struct */
     9.5  #define SHM_test        (1) /* just run domain on shadow PTs */
     9.6  #define SHM_logdirty    (2) /* log pages that are dirtied */
     9.7 -#define SHM_cow         (3) /* copy on write all dirtied pages */
     9.8 -#define SHM_translate   (4) /* lookup machine pages in translation table */
     9.9 +#define SHM_translate   (3) /* lookup machine pages in translation table */
    9.10 +//#define SHM_cow       (4) /* copy on write all dirtied pages */
    9.11 +
    9.12  
    9.13  #define shadow_linear_pg_table ((l1_pgentry_t *)SH_LINEAR_PT_VIRT_START)
    9.14  #define shadow_linear_l2_table ((l2_pgentry_t *)(SH_LINEAR_PT_VIRT_START+(SH_LINEAR_PT_VIRT_START>>(L2_PAGETABLE_SHIFT-L1_PAGETABLE_SHIFT))))
    9.15 @@ -76,9 +77,10 @@ printk("DOM%lld: (file=shadow.c, line=%d
    9.16  
    9.17  /************************************************************************/
    9.18  
    9.19 -    static inline void __mark_dirty( struct mm_struct *m, unsigned int mfn )
    9.20 +static inline int __mark_dirty( struct mm_struct *m, unsigned int mfn )
    9.21  {
    9.22      unsigned int pfn;
    9.23 +    int rc = 0;
    9.24  
    9.25      ASSERT(spin_is_locked(&m->shadow_lock));
    9.26  	
    9.27 @@ -90,17 +92,19 @@ printk("DOM%lld: (file=shadow.c, line=%d
    9.28         really part of the domain's psuedo-physical memory map e.g.
    9.29         the shared info frame. Nothing to do here...
    9.30         */
    9.31 -    if ( unlikely(pfn & 0x80000000U) ) return; 
    9.32 +    if ( unlikely(pfn & 0x80000000U) ) return rc; 
    9.33  
    9.34      ASSERT(m->shadow_dirty_bitmap);
    9.35      if( likely(pfn<m->shadow_dirty_bitmap_size) )
    9.36      {
    9.37 -		/* These updates occur with mm.shadow_lock held, so use 
    9.38 -		   (__) version of test_and_set */
    9.39 -		if( ! __test_and_set_bit( pfn, m->shadow_dirty_bitmap ) )
    9.40 -		{
    9.41 -			m->shadow_dirty_count++;
    9.42 -		}
    9.43 +	/* These updates occur with mm.shadow_lock held, so use 
    9.44 +	   (__) version of test_and_set */
    9.45 +	if( __test_and_set_bit( pfn, m->shadow_dirty_bitmap ) == 0 )
    9.46 +	{
    9.47 +	    // if we set it
    9.48 +	    m->shadow_dirty_count++;
    9.49 +	    rc = 1;
    9.50 +	}
    9.51      }
    9.52      else
    9.53      {
    9.54 @@ -113,17 +117,20 @@ printk("DOM%lld: (file=shadow.c, line=%d
    9.55  	       frame_table[mfn].type_and_flags );
    9.56  	//show_traceX();
    9.57      }
    9.58 -
    9.59 +	
    9.60 +    return rc;
    9.61  }
    9.62  
    9.63  
    9.64 -static inline void mark_dirty( struct mm_struct *m, unsigned int mfn )
    9.65 +static inline int mark_dirty( struct mm_struct *m, unsigned int mfn )
    9.66  {	
    9.67 +	int rc;
    9.68      ASSERT(local_irq_is_enabled());
    9.69      //if(spin_is_locked(&m->shadow_lock)) printk("+");
    9.70      spin_lock(&m->shadow_lock);
    9.71 -    __mark_dirty( m, mfn );
    9.72 +    rc = __mark_dirty( m, mfn );
    9.73      spin_unlock(&m->shadow_lock);
    9.74 +	return rc;
    9.75  }
    9.76  
    9.77  
    10.1 --- a/xen/net/dev.c	Mon May 24 18:13:06 2004 +0000
    10.2 +++ b/xen/net/dev.c	Thu Jun 24 10:50:33 2004 +0000
    10.3 @@ -567,7 +567,10 @@ void deliver_packet(struct sk_buff *skb,
    10.4  
    10.5      /* if in shadow mode, mark the buffer as dirty */
    10.6      if( p->mm.shadow_mode == SHM_logdirty )
    10.7 -	mark_dirty( &p->mm, (new_page-frame_table) );
    10.8 +    {
    10.9 +	if( mark_dirty( &p->mm, (new_page-frame_table) ) )
   10.10 +	    p->mm.shadow_dirty_net_count++;
   10.11 +    }
   10.12  
   10.13      /* Updates must happen before releasing the descriptor. */
   10.14      smp_wmb();
   10.15 @@ -2269,16 +2272,6 @@ long flush_bufs_for_vif(net_vif_t *vif)
   10.16  	if( p->mm.shadow_mode == SHM_logdirty )
   10.17  	{
   10.18  	    mark_dirty( &p->mm, rx->pte_ptr>>PAGE_SHIFT );
   10.19 -#if 0
   10.20 -	    mark_dirty( &p->mm, rx->buf_pfn ); // XXXXXXX debug
   10.21 -
   10.22 -	    {
   10.23 -		unsigned long * p = map_domain_mem( rx->buf_pfn<<PAGE_SHIFT );
   10.24 -		p[2] = 0xdeadc001;
   10.25 -		unmap_domain_mem(p);
   10.26 -	    }
   10.27 -#endif
   10.28 -
   10.29  	}
   10.30  	/* assume the shadow page table is about to be blown away,
   10.31  	   and that its not worth marking the buffer as dirty */