Arthur Kepner writes: Tanks. These races should be cured now I've tested a some runs and it works but I didn't see any problems before either. We'll hear from Jesse if this cured his problems.
Cheers. --ro Signed-off-by: Robert Olsson <[EMAIL PROTECTED]> > New patch differs from the previous one only in the ordering > of the two lines above. > > diff --git a/net/core/pktgen.c b/net/core/pktgen.c > --- a/net/core/pktgen.c > +++ b/net/core/pktgen.c > @@ -153,7 +153,7 @@ > #include <asm/timex.h> > > > -#define VERSION "pktgen v2.63: Packet Generator for packet performance > testing.\n" > +#define VERSION "pktgen v2.64: Packet Generator for packet performance > testing.\n" > > /* #define PG_DEBUG(a) a */ > #define PG_DEBUG(a) > @@ -176,7 +176,8 @@ > #define T_TERMINATE (1<<0) > #define T_STOP (1<<1) /* Stop run */ > #define T_RUN (1<<2) /* Start run */ > -#define T_REMDEV (1<<3) /* Remove all devs */ > +#define T_REMDEVALL (1<<3) /* Remove all devs */ > +#define T_REMDEV (1<<4) /* Remove one dev */ > > /* Locks */ > #define thread_lock() down(&pktgen_sem) > @@ -218,6 +219,8 @@ struct pktgen_dev { > * we will do a random selection from within the range. > */ > __u32 flags; > + int removal_mark; /* non-zero => the device is marked for > + * removal by worker thread */ > > int min_pkt_size; /* = ETH_ZLEN; */ > int max_pkt_size; /* = ETH_ZLEN; */ > @@ -481,7 +484,7 @@ static void pktgen_stop_all_threads_ifs( > static int pktgen_stop_device(struct pktgen_dev *pkt_dev); > static void pktgen_stop(struct pktgen_thread* t); > static void pktgen_clear_counters(struct pktgen_dev *pkt_dev); > -static struct pktgen_dev *pktgen_NN_threads(const char* dev_name, int > remove); > +static int pktgen_mark_device(const char* ifname); > static unsigned int scan_ip6(const char *s,char ip[16]); > static unsigned int fmt_ip6(char *s,const char ip[16]); > > @@ -1406,7 +1409,7 @@ static ssize_t pktgen_thread_write(struc > > if (!strcmp(name, "rem_device_all")) { > thread_lock(); > - t->control |= T_REMDEV; > + t->control |= T_REMDEVALL; > thread_unlock(); > schedule_timeout_interruptible(msecs_to_jiffies(125)); /* > Propagate thread->control */ > ret = count; > @@ -1457,7 +1460,8 @@ static struct pktgen_dev *__pktgen_NN_th > if (pkt_dev) { > if(remove) { > if_lock(t); > - pktgen_remove_device(t, pkt_dev); > + pkt_dev->removal_mark = 1; > + t->control |= T_REMDEV; > if_unlock(t); > } > break; > @@ -1467,13 +1471,44 @@ static struct pktgen_dev *__pktgen_NN_th > return pkt_dev; > } > > -static struct pktgen_dev *pktgen_NN_threads(const char* ifname, int remove) > +/* > + * mark a device for removal > + */ > +static int pktgen_mark_device(const char* ifname) > { > struct pktgen_dev *pkt_dev = NULL; > + const int max_tries = 10, msec_per_try = 125; > + int i = 0; > + int ret = 0; > + > thread_lock(); > - pkt_dev = __pktgen_NN_threads(ifname, remove); > - thread_unlock(); > - return pkt_dev; > + PG_DEBUG(printk("pktgen: pktgen_mark_device marking %s for > removal\n", > + ifname)); > + > + while(1) { > + > + pkt_dev = __pktgen_NN_threads(ifname, REMOVE); > + if (pkt_dev == NULL) break; /* success */ > + > + thread_unlock(); > + PG_DEBUG(printk("pktgen: pktgen_mark_device waiting for %s " > + "to disappear....\n", ifname)); > + schedule_timeout_interruptible(msecs_to_jiffies(msec_per_try)); > + thread_lock(); > + > + if (++i >= max_tries) { > + printk("pktgen_mark_device: timed out after waiting " > + "%d msec for device %s to be removed\n", > + msec_per_try*i, ifname); > + ret = 1; > + break; > + } > + > + } > + > + thread_unlock(); > + > + return ret; > } > > static int pktgen_device_event(struct notifier_block *unused, unsigned long > event, void *ptr) > @@ -1493,7 +1528,7 @@ static int pktgen_device_event(struct no > break; > > case NETDEV_UNREGISTER: > - pktgen_NN_threads(dev->name, REMOVE); > + pktgen_mark_device(dev->name); > break; > }; > > @@ -2303,11 +2338,11 @@ static void pktgen_stop_all_threads_ifs( > { > struct pktgen_thread *t = pktgen_threads; > > - PG_DEBUG(printk("pktgen: entering pktgen_stop_all_threads.\n")); > + PG_DEBUG(printk("pktgen: entering pktgen_stop_all_threads_ifs.\n")); > > thread_lock(); > while(t) { > - pktgen_stop(t); > + t->control |= T_STOP; > t = t->next; > } > thread_unlock(); > @@ -2431,7 +2466,9 @@ static void show_results(struct pktgen_d > > static int pktgen_stop_device(struct pktgen_dev *pkt_dev) > { > - > + int nr_frags = pkt_dev->skb ? > + skb_shinfo(pkt_dev->skb)->nr_frags: -1; > + > if (!pkt_dev->running) { > printk("pktgen: interface: %s is already stopped\n", > pkt_dev->ifname); > return -EINVAL; > @@ -2440,13 +2477,8 @@ static int pktgen_stop_device(struct pkt > pkt_dev->stopped_at = getCurUs(); > pkt_dev->running = 0; > > - show_results(pkt_dev, skb_shinfo(pkt_dev->skb)->nr_frags); > - > - if (pkt_dev->skb) > - kfree_skb(pkt_dev->skb); > + show_results(pkt_dev, nr_frags); > > - pkt_dev->skb = NULL; > - > return 0; > } > > @@ -2469,26 +2501,66 @@ static struct pktgen_dev *next_to_run(st > static void pktgen_stop(struct pktgen_thread *t) { > struct pktgen_dev *next = NULL; > > - PG_DEBUG(printk("pktgen: entering pktgen_stop.\n")); > + PG_DEBUG(printk("pktgen: entering pktgen_stop\n")); > > if_lock(t); > > - for(next=t->if_list; next; next=next->next) > + for(next=t->if_list; next; next=next->next) { > pktgen_stop_device(next); > + if (next->skb) > + kfree_skb(next->skb); > + > + next->skb = NULL; > + } > > if_unlock(t); > } > > +/* > + * one of our devices needs to be removed - find it > + * and remove it > + */ > +static void pktgen_rem_one_if(struct pktgen_thread *t) > +{ > + struct pktgen_dev *cur, *next = NULL; > + > + PG_DEBUG(printk("pktgen: entering pktgen_rem_one_if\n")); > + > + if_lock(t); > + > + for(cur=t->if_list; cur; cur=next) { > + next = cur->next; > + > + if (!cur->removal_mark) continue; > + > + if (cur->skb) > + kfree_skb(cur->skb); > + cur->skb = NULL; > + > + pktgen_remove_device(t, cur); > + > + break; > + } > + > + if_unlock(t); > +} > + > static void pktgen_rem_all_ifs(struct pktgen_thread *t) > { > struct pktgen_dev *cur, *next = NULL; > - > - /* Remove all devices, free mem */ > > + /* Remove all devices, free mem */ > + > + PG_DEBUG(printk("pktgen: entering pktgen_rem_all_ifs\n")); > if_lock(t); > > for(cur=t->if_list; cur; cur=next) { > next = cur->next; > + > + if (cur->skb) > + kfree_skb(cur->skb); > + cur->skb = NULL; > + > pktgen_remove_device(t, cur); > } > > @@ -2550,6 +2622,9 @@ static __inline__ void pktgen_xmit(struc > > if (!netif_running(odev)) { > pktgen_stop_device(pkt_dev); > + if (pkt_dev->skb) > + kfree_skb(pkt_dev->skb); > + pkt_dev->skb = NULL; > goto out; > } > if (need_resched()) > @@ -2581,7 +2656,7 @@ static __inline__ void pktgen_xmit(struc > pkt_dev->clone_count = 0; /* reset counter */ > } > } > - > + > spin_lock_bh(&odev->xmit_lock); > if (!netif_queue_stopped(odev)) { > > @@ -2644,6 +2719,9 @@ retry_now: > > /* Done with this */ > pktgen_stop_device(pkt_dev); > + if (pkt_dev->skb) > + kfree_skb(pkt_dev->skb); > + pkt_dev->skb = NULL; > } > out:; > } > @@ -2685,6 +2763,7 @@ static void pktgen_thread_worker(struct > t->control &= ~(T_TERMINATE); > t->control &= ~(T_RUN); > t->control &= ~(T_STOP); > + t->control &= ~(T_REMDEVALL); > t->control &= ~(T_REMDEV); > > t->pid = current->pid; > @@ -2748,8 +2827,13 @@ static void pktgen_thread_worker(struct > t->control &= ~(T_RUN); > } > > - if(t->control & T_REMDEV) { > + if(t->control & T_REMDEVALL) { > pktgen_rem_all_ifs(t); > + t->control &= ~(T_REMDEVALL); > + } > + > + if(t->control & T_REMDEV) { > + pktgen_rem_one_if(t); > t->control &= ~(T_REMDEV); > } > > @@ -2833,6 +2917,7 @@ static int pktgen_add_device(struct pktg > } > memset(pkt_dev->flows, 0, MAX_CFLOWS*sizeof(struct flow_state)); > > + pkt_dev->removal_mark = 0; > pkt_dev->min_pkt_size = ETH_ZLEN; > pkt_dev->max_pkt_size = ETH_ZLEN; > pkt_dev->nfrags = 0; - To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html