Messages in this thread Patch in this message | ![/](/images/icornerl.gif) | | Date | Wed, 03 Sep 2003 16:07:33 +0900 (JST) | Subject | Re: /proc/net/* read drops data | From | YOSHIFUJI Hideaki / 吉藤英明 <> |
| |
Hello.
In article <Pine.GSO.4.33.0308271935550.7750-100000@sweetums.bluetronic.net> (at Wed, 27 Aug 2003 19:58:17 -0400 (EDT)), Ricky Beam <jfbeam@bluetronic.net> says:
> On Wed, 27 Aug 2003, Ricky Beam wrote: > >This smells like a simple "off by one" bug, but I've been too busy to go > >look at the code. > > Ah hah! it's a block size problem... netstat reads 1024 at a time. > > Using dd... > > [root:pts/5{9}]gir:~/[7:55pm]:dd if=/proc/net/udp bs=1024 | wc > 2+1 records in > 2+1 records out > 18 216 2304 > [root:pts/5{9}]gir:~/[7:56pm]:dd if=/proc/net/udp bs=2048 | wc > 1+1 records in > 1+1 records out > 19 228 2432 :
Please try this patch.
D: Fixing a bug that reading /proc/net/{udp,udp6} may drop some data
Index: linux-2.6/net/ipv4/udp.c =================================================================== RCS file: /home/cvs/linux-2.5/net/ipv4/udp.c,v retrieving revision 1.38 diff -u -r1.38 udp.c --- linux-2.6/net/ipv4/udp.c 14 Aug 2003 06:00:04 -0000 1.38 +++ linux-2.6/net/ipv4/udp.c 3 Sep 2003 05:30:52 -0000 @@ -1349,64 +1349,65 @@ /* ------------------------------------------------------------------------ */ #ifdef CONFIG_PROC_FS -static __inline__ struct sock *udp_get_bucket(struct seq_file *seq, loff_t *pos) +static struct sock *udp_get_first(struct seq_file *seq) { - int i; struct sock *sk; - struct hlist_node *node; - loff_t l = *pos; struct udp_iter_state *state = seq->private; - for (; state->bucket < UDP_HTABLE_SIZE; ++state->bucket) { - i = 0; + for (state->bucket = 0; state->bucket < UDP_HTABLE_SIZE; ++state->bucket) { + struct hlist_node *node; sk_for_each(sk, node, &udp_hash[state->bucket]) { - if (sk->sk_family != state->family) { - ++i; - continue; - } - if (l--) { - ++i; - continue; - } - *pos = i; - goto out; + if (sk->sk_family == state->family) + goto found; } } sk = NULL; -out: +found: return sk; } +static struct sock *udp_get_next(struct seq_file *seq, struct sock *sk) +{ + struct udp_iter_state *state = seq->private; + + do { + sk = sk_next(sk); +try_again: + ; + } while (sk && sk->sk_family != state->family); + + if (!sk && ++state->bucket < UDP_HTABLE_SIZE) { + sk = sk_head(&udp_hash[state->bucket]); + goto try_again; + } + return sk; +} + +static struct sock *udp_get_idx(struct seq_file *seq, loff_t pos) +{ + struct sock *sk = udp_get_first(seq); + + if (sk) + while(pos && (sk = udp_get_next(seq, sk)) != NULL) + --pos; + return pos ? NULL : sk; +} + static void *udp_seq_start(struct seq_file *seq, loff_t *pos) { read_lock(&udp_hash_lock); - return *pos ? udp_get_bucket(seq, pos) : (void *)1; + return *pos ? udp_get_idx(seq, *pos-1) : (void *)1; } static void *udp_seq_next(struct seq_file *seq, void *v, loff_t *pos) { struct sock *sk; - struct hlist_node *node; - struct udp_iter_state *state; - - if (v == (void *)1) { - sk = udp_get_bucket(seq, pos); - goto out; - } - state = seq->private; + if (v == (void *)1) + sk = udp_get_idx(seq, 0); + else + sk = udp_get_next(seq, v); - sk = v; - sk_for_each_continue(sk, node) - if (sk->sk_family == state->family) - goto out; - - if (++state->bucket >= UDP_HTABLE_SIZE) - goto out; - - *pos = 0; - sk = udp_get_bucket(seq, pos); -out: ++*pos; return sk; } -- Hideaki YOSHIFUJI @ USAGI Project <yoshfuji@linux-ipv6.org> GPG FP: 9022 65EB 1ECF 3AD1 0BDF 80D8 4807 F894 E062 0EEA - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
| ![\](/images/icornerr.gif) |