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