direct-io.hg

changeset 603:7f7fc97be5fd

bitkeeper revision 1.336 (3f0d653cjDgXGC_7MbnpQ0f33BxQqQ)

Merge labyrinth.cl.cam.ac.uk:/auto/groups/xeno/users/rac61/xeno.bk
into labyrinth.cl.cam.ac.uk:/auto/groups/xeno/users/sos22/xeno.bk
author sos22@labyrinth.cl.cam.ac.uk
date Thu Jul 10 13:08:12 2003 +0000 (2003-07-10)
parents 4515f4d0701f 81fe7d3a9c46
children 4750dfc4d829
files xen/drivers/block/xen_segment.c
line diff
     1.1 --- a/xen/drivers/block/xen_segment.c	Thu Jul 10 12:53:46 2003 +0000
     1.2 +++ b/xen/drivers/block/xen_segment.c	Thu Jul 10 13:08:12 2003 +0000
     1.3 @@ -15,7 +15,21 @@
     1.4  #include <asm/domain_page.h>
     1.5  #include <hypervisor-ifs/block.h>
     1.6  
     1.7 +/* Global list of all possible segments.  This can be changed in
     1.8 +   the following way:
     1.9 +
    1.10 +   1) UNUSED segment -> RO or RW segment.  This requires the spinlock.
    1.11 +
    1.12 +   2) RO or RW -> UNUSED.  This requires the lock and can only happen
    1.13 +   during process teardown.
    1.14 +
    1.15 +   This means that processes can access entries in the list safely
    1.16 +   without having to hold any lock at all: they already have an entry
    1.17 +   allocated, and we know that entry can't become unused, as segments
    1.18 +   are only torn down when the domain is dieing, by which point it
    1.19 +   can't be accessing them anymore. */
    1.20  static segment_t xsegments[XEN_MAX_SEGMENTS];
    1.21 +static spinlock_t xsegment_lock = SPIN_LOCK_UNLOCKED;
    1.22  
    1.23  #if 0
    1.24  #define DPRINTK(_f, _a...) printk( _f , ## _a )
    1.25 @@ -23,9 +37,6 @@ static segment_t xsegments[XEN_MAX_SEGME
    1.26  #define DPRINTK(_f, _a...) ((void)0)
    1.27  #endif
    1.28  
    1.29 -/* XXX XXX XXX Why are there absolutely no calls to any locking
    1.30 -   primitives anywhere in this? */
    1.31 -
    1.32  /*
    1.33   * xen_segment_map_request
    1.34   *
    1.35 @@ -33,6 +44,12 @@ static segment_t xsegments[XEN_MAX_SEGME
    1.36   * 
    1.37   * NB. All offsets and sizes here are in sector units.
    1.38   * eg. 'size == 1' means an actual size of 512 bytes.
    1.39 + *
    1.40 + * Note that no locking is performed here whatsoever --
    1.41 + * we rely on the fact that once segment information is
    1.42 + * established, it is only modified by domain shutdown,
    1.43 + * and so if this is being called, noone is trying
    1.44 + * to modify the segment list.
    1.45   */
    1.46  int xen_segment_map_request(
    1.47      phys_seg_t *pseg, struct task_struct *p, int operation,
    1.48 @@ -162,6 +179,8 @@ void xen_segment_probe(struct task_struc
    1.49      xen_disk_info_t *xdi = map_domain_mem(virt_to_phys(raw_xdi));
    1.50      unsigned long capacity = 0, device;
    1.51  
    1.52 +    spin_lock(&xsegment_lock);
    1.53 +    xdi->count = 0;
    1.54      for ( loop = 0; loop < XEN_MAX_SEGMENTS; loop++ )
    1.55      {
    1.56          if ( (xsegments[loop].mode == XEN_SEGMENT_UNUSED) ||
    1.57 @@ -176,6 +195,7 @@ void xen_segment_probe(struct task_struc
    1.58          xdi->disks[xdi->count].capacity = capacity;
    1.59          xdi->count++;
    1.60      }
    1.61 +    spin_unlock(&xsegment_lock);
    1.62  
    1.63      unmap_domain_mem(xdi);
    1.64  }
    1.65 @@ -190,6 +210,7 @@ void xen_segment_probe_all(xen_segment_i
    1.66      int loop;
    1.67      xen_segment_info_t *xsi = map_domain_mem(virt_to_phys(raw_xsi));
    1.68  
    1.69 +    spin_lock(&xsegment_lock);
    1.70      xsi->count = 0;
    1.71      for ( loop = 0; loop < XEN_MAX_SEGMENTS; loop++ )
    1.72      {
    1.73 @@ -204,6 +225,7 @@ void xen_segment_probe_all(xen_segment_i
    1.74  	xsi->segments[xsi->count].seg_nr = xsegments[loop].segment_number;
    1.75          xsi->count++;	
    1.76      }
    1.77 +    spin_unlock(&xsegment_lock);
    1.78  
    1.79      unmap_domain_mem(xsi);
    1.80  }
    1.81 @@ -213,11 +235,13 @@ void xen_segment_probe_all(xen_segment_i
    1.82   *
    1.83   * find all segments associated with a domain and assign
    1.84   * them to the domain
    1.85 + *
    1.86   */
    1.87  void xen_refresh_segment_list (struct task_struct *p)
    1.88  {
    1.89      int loop;
    1.90  
    1.91 +    spin_lock(&xsegment_lock);
    1.92      for (loop = 0; loop < XEN_MAX_SEGMENTS; loop++)
    1.93      {
    1.94          if ( (xsegments[loop].mode == XEN_SEGMENT_UNUSED) ||
    1.95 @@ -226,6 +250,7 @@ void xen_refresh_segment_list (struct ta
    1.96  
    1.97          p->segment_list[xsegments[loop].segment_number] = &xsegments[loop];
    1.98      }
    1.99 +    spin_unlock(&xsegment_lock);
   1.100  }
   1.101  
   1.102  /*
   1.103 @@ -244,6 +269,7 @@ int xen_segment_create(xv_disk_t *xvd_in
   1.104      xv_disk_t *xvd = map_domain_mem(virt_to_phys(xvd_in));
   1.105      struct task_struct *p;
   1.106  
   1.107 +    spin_lock(&xsegment_lock);
   1.108      for (idx = 0; idx < XEN_MAX_SEGMENTS; idx++)
   1.109      {
   1.110          if (xsegments[idx].mode == XEN_SEGMENT_UNUSED ||
   1.111 @@ -262,8 +288,10 @@ int xen_segment_create(xv_disk_t *xvd_in
   1.112      xsegments[idx].segment_number = xvd->segment;
   1.113      memcpy(xsegments[idx].key, xvd->key, XEN_SEGMENT_KEYSIZE);
   1.114      xsegments[idx].num_extents = xvd->ext_count;
   1.115 +
   1.116 +
   1.117      if (xsegments[idx].extents)
   1.118 -	kfree(xsegments[idx].extents);
   1.119 +	kfree(xsegments[idx].extents);    
   1.120      xsegments[idx].extents = (extent_t *)kmalloc(
   1.121          sizeof(extent_t)*xvd->ext_count,
   1.122          GFP_KERNEL);
   1.123 @@ -290,6 +318,8 @@ int xen_segment_create(xv_disk_t *xvd_in
   1.124          put_task_struct(p);
   1.125      }
   1.126  
   1.127 +    spin_unlock(&xsegment_lock);
   1.128 +
   1.129      unmap_domain_mem(xvd);
   1.130      return 0;
   1.131  }
   1.132 @@ -299,6 +329,8 @@ int xen_segment_create(xv_disk_t *xvd_in
   1.133   *
   1.134   * return 0 on success, 1 on failure
   1.135   *
   1.136 + * This should *only* be called from domain shutdown, or else we
   1.137 + * race with access checking.
   1.138   */
   1.139  int xen_segment_delete(struct task_struct *p, int segnr)
   1.140  {
   1.141 @@ -330,12 +362,16 @@ int xen_segment_delete(struct task_struc
   1.142  	return 1;
   1.143      }
   1.144  
   1.145 +    spin_lock(&xsegment_lock);
   1.146 +
   1.147      p->segment_list[segnr] = NULL;
   1.148      seg->domain = -1;
   1.149      seg->segment_number = -1;
   1.150      kfree(seg->extents);
   1.151      seg->mode = XEN_SEGMENT_UNUSED;
   1.152  
   1.153 +    spin_unlock(&xsegment_lock);
   1.154 +
   1.155      return 0;
   1.156  }
   1.157