diff options
author | kaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk> | 2003-05-14 15:56:24 +0000 |
---|---|---|
committer | kaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk> | 2003-05-14 15:56:24 +0000 |
commit | 56bef42828c150ff1817e4ee536a2974ed8222b9 (patch) | |
tree | c8efa2ddbd16d22be71eab296fa6b1e13e3af18e | |
parent | b7a02a1c5547b49ef3bc467d335465391d57dab1 (diff) | |
download | xen-56bef42828c150ff1817e4ee536a2974ed8222b9.tar.gz xen-56bef42828c150ff1817e4ee536a2974ed8222b9.tar.bz2 xen-56bef42828c150ff1817e4ee536a2974ed8222b9.zip |
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 :-)
-rw-r--r-- | xen/common/dom0_ops.c | 16 | ||||
-rw-r--r-- | xen/include/xeno/skbuff.h | 10 | ||||
-rw-r--r-- | xen/include/xeno/vif.h | 3 | ||||
-rw-r--r-- | xen/net/dev.c | 32 |
4 files changed, 35 insertions, 26 deletions
diff --git a/xen/common/dom0_ops.c b/xen/common/dom0_ops.c index 89872251f7..c62b68b919 100644 --- a/xen/common/dom0_ops.c +++ b/xen/common/dom0_ops.c @@ -210,18 +210,20 @@ long do_dom0_op(dom0_op_t *u_dom0_op) case DOM0_GETDOMAININFO: { - struct task_struct *p; + struct task_struct *p = &idle0_task; u_long flags; - p = idle0_task.next_task; read_lock_irqsave (&tasklist_lock, flags); - do { - if ((!is_idle_task (p)) && (p -> domain >= op.u.getdominfo.domain)) + + while ( (p = p->next_task) != &idle0_task ) + if ( !is_idle_task(p) && (p->domain >= op.u.getdominfo.domain) ) break; - } while ((p = p -> next_task) != &idle0_task); - ret = -ESRCH; - if ( p != &idle0_task ) + if ( p == &idle0_task ) + { + ret = -ESRCH; + } + else { op.u.getdominfo.domain = p->domain; strcpy (op.u.getdominfo.name, p->name); diff --git a/xen/include/xeno/skbuff.h b/xen/include/xeno/skbuff.h index 367a7c114e..4e0afc0183 100644 --- a/xen/include/xeno/skbuff.h +++ b/xen/include/xeno/skbuff.h @@ -156,10 +156,12 @@ struct sk_buff { unsigned char *end; /* End pointer */ void (*destructor)(struct sk_buff *); /* Destruct function */ - struct pfn_info *pf; /* record of physical pf address for freeing */ - net_vif_t *src_vif; /* vif we came from */ - net_vif_t *dst_vif; /* vif we are bound for */ - struct skb_shared_info shinfo; /* shared info is no longer shared in Xen. */ + + unsigned short guest_id; /* guest-OS's id for this packet (tx only!) */ + struct pfn_info *pf; /* record of physical pf address for freeing */ + net_vif_t *src_vif; /* vif we came from */ + net_vif_t *dst_vif; /* vif we are bound for */ + struct skb_shared_info shinfo; /* shared info not shared in Xen. */ }; extern void __kfree_skb(struct sk_buff *skb); diff --git a/xen/include/xeno/vif.h b/xen/include/xeno/vif.h index 6cc339cbd9..8e4fcab444 100644 --- a/xen/include/xeno/vif.h +++ b/xen/include/xeno/vif.h @@ -58,8 +58,7 @@ typedef struct net_vif_st { unsigned int rx_cons; /* Next buffer to fill is here. */ tx_shadow_entry_t tx_shadow_ring[TX_RING_SIZE]; unsigned int tx_prod; /* More packets for sending go here. */ - unsigned int tx_idx; /* Next packet to send is here. */ - unsigned int tx_cons; /* Next packet to create response for is here. */ + unsigned int tx_cons; /* Next packet to send is here. */ /* Private indexes into shared ring. */ unsigned int rx_req_cons; diff --git a/xen/net/dev.c b/xen/net/dev.c index 0f36344e74..ce2795f3a0 100644 --- a/xen/net/dev.c +++ b/xen/net/dev.c @@ -504,16 +504,24 @@ void deliver_packet(struct sk_buff *skb, net_vif_t *vif) if ( ntohs(skb->mac.ethernet->h_proto) == ETH_P_ARP ) memcpy(skb->nh.raw + 18, vif->vmac, ETH_ALEN); + /* + * Slightly gross: we need the page_lock so that we can do PTE checking. + * However, we take it slightly early so that it can protect the update + * of rx_cons. This saves us from grabbing two locks. + */ + spin_lock(&vif->domain->page_lock); + if ( (i = vif->rx_cons) == vif->rx_prod ) + { + spin_unlock(&vif->domain->page_lock); return; - + } rx = vif->rx_shadow_ring + i; + vif->rx_cons = RX_RING_INC(i); size = (unsigned short)skb->len; offset = (unsigned char)((unsigned long)skb->data & ~PAGE_MASK); - spin_lock(&vif->domain->page_lock); - /* Release the page-table page. */ pte_page = frame_table + (rx->pte_ptr >> PAGE_SHIFT); put_page_type(pte_page); @@ -529,6 +537,8 @@ void deliver_packet(struct sk_buff *skb, net_vif_t *vif) /* Bail out if the PTE has been reused under our feet. */ list_add(&old_page->list, &vif->domain->pg_head); old_page->flags = vif->domain->domain; + unmap_domain_mem(ptep); + spin_unlock(&vif->domain->page_lock); status = RING_STATUS_BAD_PAGE; goto out; } @@ -558,13 +568,11 @@ void deliver_packet(struct sk_buff *skb, net_vif_t *vif) * NB. The remote flush here should be safe, as we hold no locks. The * network driver that called us should also have no nasty locks. */ - rx = vif->rx_shadow_ring + vif->rx_cons; if ( rx->flush_count == (unsigned short) atomic_read(&tlb_flush_count[vif->domain->processor]) ) flush_tlb_cpu(vif->domain->processor); out: - vif->rx_cons = RX_RING_INC(vif->rx_cons); make_rx_response(vif, rx->id, size, status, offset); } @@ -682,7 +690,6 @@ static void tx_skb_release(struct sk_buff *skb) { int i; net_vif_t *vif = skb->src_vif; - tx_shadow_entry_t *tx; unsigned long flags; spin_lock_irqsave(&vif->domain->page_lock, flags); @@ -695,9 +702,7 @@ static void tx_skb_release(struct sk_buff *skb) skb_shinfo(skb)->nr_frags = 0; - tx = vif->tx_shadow_ring + vif->tx_cons; - vif->tx_cons = TX_RING_INC(vif->tx_cons); - make_tx_response(vif, tx->id, RING_STATUS_OK); + make_tx_response(vif, skb->guest_id, RING_STATUS_OK); put_vif(vif); } @@ -720,7 +725,7 @@ static void net_tx_action(unsigned long unused) vif = list_entry(ent, net_vif_t, list); get_vif(vif); remove_from_net_schedule_list(vif); - if ( vif->tx_idx == vif->tx_prod ) + if ( vif->tx_cons == vif->tx_prod ) { put_vif(vif); continue; @@ -735,9 +740,9 @@ static void net_tx_action(unsigned long unused) } /* Pick an entry from the transmit queue. */ - tx = &vif->tx_shadow_ring[vif->tx_idx]; - vif->tx_idx = TX_RING_INC(vif->tx_idx); - if ( vif->tx_idx != vif->tx_prod ) + tx = &vif->tx_shadow_ring[vif->tx_cons]; + vif->tx_cons = TX_RING_INC(vif->tx_cons); + if ( vif->tx_cons != vif->tx_prod ) add_to_net_schedule_list_tail(vif); skb->destructor = tx_skb_release; @@ -749,6 +754,7 @@ static void net_tx_action(unsigned long unused) skb->src_vif = vif; skb->dst_vif = NULL; skb->mac.raw = skb->data; + skb->guest_id = tx->id; skb_shinfo(skb)->frags[0].page = frame_table + (tx->payload >> PAGE_SHIFT); |