ia64/xen-unstable

changeset 448:59f3e52cfa46

bitkeeper revision 1.229 (3ec26728uXDBndxeN2-AxbIwi9afug)

dev.c, vif.h, skbuff.h, dom0_ops.c:
Fixed locking in network transmit and receive. Fixed bug I added to DOM0_GETDOMAININFO in previous checkin :-)
author kaf24@scramble.cl.cam.ac.uk
date Wed May 14 15:56:24 2003 +0000 (2003-05-14)
parents 7aea3ea7b542
children 2ea7a4a8604c
files xen/common/dom0_ops.c xen/include/xeno/skbuff.h xen/include/xeno/vif.h xen/net/dev.c
line diff
     1.1 --- a/xen/common/dom0_ops.c	Wed May 14 14:18:16 2003 +0000
     1.2 +++ b/xen/common/dom0_ops.c	Wed May 14 15:56:24 2003 +0000
     1.3 @@ -210,18 +210,20 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
     1.4  
     1.5      case DOM0_GETDOMAININFO:
     1.6      { 
     1.7 -        struct task_struct *p;
     1.8 +        struct task_struct *p = &idle0_task;
     1.9          u_long flags;
    1.10  
    1.11 -        p = idle0_task.next_task;
    1.12          read_lock_irqsave (&tasklist_lock, flags);
    1.13 -        do {
    1.14 -            if ((!is_idle_task (p)) && (p -> domain >= op.u.getdominfo.domain))
    1.15 +
    1.16 +        while ( (p = p->next_task) != &idle0_task )
    1.17 +            if ( !is_idle_task(p) && (p->domain >= op.u.getdominfo.domain) )
    1.18                  break;
    1.19 -        } while ((p = p -> next_task) != &idle0_task);
    1.20  
    1.21 -        ret = -ESRCH;
    1.22 -        if ( p != &idle0_task ) 
    1.23 +        if ( p == &idle0_task )
    1.24 +        {
    1.25 +            ret = -ESRCH;
    1.26 +        }
    1.27 +        else
    1.28          {
    1.29              op.u.getdominfo.domain      = p->domain;
    1.30              strcpy (op.u.getdominfo.name, p->name);
     2.1 --- a/xen/include/xeno/skbuff.h	Wed May 14 14:18:16 2003 +0000
     2.2 +++ b/xen/include/xeno/skbuff.h	Wed May 14 15:56:24 2003 +0000
     2.3 @@ -156,10 +156,12 @@ struct sk_buff {
     2.4      unsigned char 	*end;			/* End pointer					*/
     2.5  
     2.6      void 		(*destructor)(struct sk_buff *);	/* Destruct function		*/
     2.7 -    struct pfn_info *pf;                    /* record of physical pf address for freeing    */
     2.8 -    net_vif_t *src_vif;                     /* vif we came from                             */
     2.9 -    net_vif_t *dst_vif;                     /* vif we are bound for                         */
    2.10 -    struct skb_shared_info shinfo;          /* shared info is no longer shared in Xen.      */
    2.11 +
    2.12 +    unsigned short guest_id;  /* guest-OS's id for this packet (tx only!)   */
    2.13 +    struct pfn_info *pf;      /* record of physical pf address for freeing  */
    2.14 +    net_vif_t *src_vif;       /* vif we came from                           */
    2.15 +    net_vif_t *dst_vif;       /* vif we are bound for                       */
    2.16 +    struct skb_shared_info shinfo; /* shared info not shared in Xen.        */
    2.17  };
    2.18  
    2.19  extern void	       __kfree_skb(struct sk_buff *skb);
     3.1 --- a/xen/include/xeno/vif.h	Wed May 14 14:18:16 2003 +0000
     3.2 +++ b/xen/include/xeno/vif.h	Wed May 14 15:56:24 2003 +0000
     3.3 @@ -58,8 +58,7 @@ typedef struct net_vif_st {
     3.4      unsigned int rx_cons;  /* Next buffer to fill is here. */
     3.5      tx_shadow_entry_t tx_shadow_ring[TX_RING_SIZE];
     3.6      unsigned int tx_prod;  /* More packets for sending go here. */
     3.7 -    unsigned int tx_idx;   /* Next packet to send is here. */
     3.8 -    unsigned int tx_cons;  /* Next packet to create response for is here. */
     3.9 +    unsigned int tx_cons;  /* Next packet to send is here. */
    3.10  
    3.11      /* Private indexes into shared ring. */
    3.12      unsigned int rx_req_cons;
     4.1 --- a/xen/net/dev.c	Wed May 14 14:18:16 2003 +0000
     4.2 +++ b/xen/net/dev.c	Wed May 14 15:56:24 2003 +0000
     4.3 @@ -504,16 +504,24 @@ void deliver_packet(struct sk_buff *skb,
     4.4      if ( ntohs(skb->mac.ethernet->h_proto) == ETH_P_ARP )
     4.5          memcpy(skb->nh.raw + 18, vif->vmac, ETH_ALEN);
     4.6  
     4.7 +    /*
     4.8 +     * Slightly gross: we need the page_lock so that we can do PTE checking.
     4.9 +     * However, we take it slightly early so that it can protect the update
    4.10 +     * of rx_cons. This saves us from grabbing two locks.
    4.11 +     */
    4.12 +    spin_lock(&vif->domain->page_lock);
    4.13 +
    4.14      if ( (i = vif->rx_cons) == vif->rx_prod )
    4.15 +    {
    4.16 +        spin_unlock(&vif->domain->page_lock);
    4.17          return;
    4.18 -
    4.19 +    }
    4.20      rx = vif->rx_shadow_ring + i;
    4.21 +    vif->rx_cons = RX_RING_INC(i);
    4.22  
    4.23      size   = (unsigned short)skb->len;
    4.24      offset = (unsigned char)((unsigned long)skb->data & ~PAGE_MASK);
    4.25  
    4.26 -    spin_lock(&vif->domain->page_lock);
    4.27 -
    4.28      /* Release the page-table page. */
    4.29      pte_page = frame_table + (rx->pte_ptr >> PAGE_SHIFT);
    4.30      put_page_type(pte_page);
    4.31 @@ -529,6 +537,8 @@ void deliver_packet(struct sk_buff *skb,
    4.32          /* Bail out if the PTE has been reused under our feet. */
    4.33          list_add(&old_page->list, &vif->domain->pg_head);
    4.34          old_page->flags = vif->domain->domain;
    4.35 +        unmap_domain_mem(ptep);
    4.36 +        spin_unlock(&vif->domain->page_lock);
    4.37          status = RING_STATUS_BAD_PAGE;
    4.38          goto out;
    4.39      }
    4.40 @@ -558,13 +568,11 @@ void deliver_packet(struct sk_buff *skb,
    4.41       * NB. The remote flush here should be safe, as we hold no locks. The 
    4.42       * network driver that called us should also have no nasty locks.
    4.43       */
    4.44 -    rx = vif->rx_shadow_ring + vif->rx_cons;
    4.45      if ( rx->flush_count == (unsigned short)
    4.46           atomic_read(&tlb_flush_count[vif->domain->processor]) )
    4.47          flush_tlb_cpu(vif->domain->processor);
    4.48  
    4.49   out:
    4.50 -    vif->rx_cons = RX_RING_INC(vif->rx_cons);
    4.51      make_rx_response(vif, rx->id, size, status, offset);
    4.52  }
    4.53  
    4.54 @@ -682,7 +690,6 @@ static void tx_skb_release(struct sk_buf
    4.55  {
    4.56      int i;
    4.57      net_vif_t *vif = skb->src_vif;
    4.58 -    tx_shadow_entry_t *tx;
    4.59      unsigned long flags;
    4.60      
    4.61      spin_lock_irqsave(&vif->domain->page_lock, flags);
    4.62 @@ -695,9 +702,7 @@ static void tx_skb_release(struct sk_buf
    4.63  
    4.64      skb_shinfo(skb)->nr_frags = 0; 
    4.65  
    4.66 -    tx = vif->tx_shadow_ring + vif->tx_cons;
    4.67 -    vif->tx_cons = TX_RING_INC(vif->tx_cons);
    4.68 -    make_tx_response(vif, tx->id, RING_STATUS_OK);
    4.69 +    make_tx_response(vif, skb->guest_id, RING_STATUS_OK);
    4.70  
    4.71      put_vif(vif);
    4.72  }
    4.73 @@ -720,7 +725,7 @@ static void net_tx_action(unsigned long 
    4.74          vif = list_entry(ent, net_vif_t, list);
    4.75          get_vif(vif);
    4.76          remove_from_net_schedule_list(vif);
    4.77 -        if ( vif->tx_idx == vif->tx_prod )
    4.78 +        if ( vif->tx_cons == vif->tx_prod )
    4.79          {
    4.80              put_vif(vif);
    4.81              continue;
    4.82 @@ -735,9 +740,9 @@ static void net_tx_action(unsigned long 
    4.83          }
    4.84          
    4.85          /* Pick an entry from the transmit queue. */
    4.86 -        tx = &vif->tx_shadow_ring[vif->tx_idx];
    4.87 -        vif->tx_idx = TX_RING_INC(vif->tx_idx);
    4.88 -        if ( vif->tx_idx != vif->tx_prod )
    4.89 +        tx = &vif->tx_shadow_ring[vif->tx_cons];
    4.90 +        vif->tx_cons = TX_RING_INC(vif->tx_cons);
    4.91 +        if ( vif->tx_cons != vif->tx_prod )
    4.92              add_to_net_schedule_list_tail(vif);
    4.93  
    4.94          skb->destructor = tx_skb_release;
    4.95 @@ -749,6 +754,7 @@ static void net_tx_action(unsigned long 
    4.96          skb->src_vif  = vif;
    4.97          skb->dst_vif  = NULL;
    4.98          skb->mac.raw  = skb->data; 
    4.99 +        skb->guest_id = tx->id;
   4.100          
   4.101          skb_shinfo(skb)->frags[0].page        = frame_table +
   4.102              (tx->payload >> PAGE_SHIFT);