From 1c92b4e50ef926d1e26fcc056a520e4a7d12478c Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 31 May 2007 13:24:26 -0700 Subject: [AF_UNIX]: Make socket locking much less confusing. The unix_state_*() locking macros imply that there is some rwlock kind of thing going on, but the implementation is actually a spinlock which makes the code more confusing than it needs to be. So use plain unix_state_lock and unix_state_unlock. Signed-off-by: David S. Miller --- include/net/af_unix.h | 8 ++--- net/unix/af_unix.c | 94 +++++++++++++++++++++++++-------------------------- 2 files changed, 50 insertions(+), 52 deletions(-) diff --git a/include/net/af_unix.h b/include/net/af_unix.h index c0398f5a8cb..65f49fd7def 100644 --- a/include/net/af_unix.h +++ b/include/net/af_unix.h @@ -62,13 +62,11 @@ struct unix_skb_parms { #define UNIXCREDS(skb) (&UNIXCB((skb)).creds) #define UNIXSID(skb) (&UNIXCB((skb)).secid) -#define unix_state_rlock(s) spin_lock(&unix_sk(s)->lock) -#define unix_state_runlock(s) spin_unlock(&unix_sk(s)->lock) -#define unix_state_wlock(s) spin_lock(&unix_sk(s)->lock) -#define unix_state_wlock_nested(s) \ +#define unix_state_lock(s) spin_lock(&unix_sk(s)->lock) +#define unix_state_unlock(s) spin_unlock(&unix_sk(s)->lock) +#define unix_state_lock_nested(s) \ spin_lock_nested(&unix_sk(s)->lock, \ SINGLE_DEPTH_NESTING) -#define unix_state_wunlock(s) spin_unlock(&unix_sk(s)->lock) #ifdef __KERNEL__ /* The AF_UNIX socket */ diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index fc12ba51c1f..453ede86a65 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -174,11 +174,11 @@ static struct sock *unix_peer_get(struct sock *s) { struct sock *peer; - unix_state_rlock(s); + unix_state_lock(s); peer = unix_peer(s); if (peer) sock_hold(peer); - unix_state_runlock(s); + unix_state_unlock(s); return peer; } @@ -369,7 +369,7 @@ static int unix_release_sock (struct sock *sk, int embrion) unix_remove_socket(sk); /* Clear state */ - unix_state_wlock(sk); + unix_state_lock(sk); sock_orphan(sk); sk->sk_shutdown = SHUTDOWN_MASK; dentry = u->dentry; @@ -378,7 +378,7 @@ static int unix_release_sock (struct sock *sk, int embrion) u->mnt = NULL; state = sk->sk_state; sk->sk_state = TCP_CLOSE; - unix_state_wunlock(sk); + unix_state_unlock(sk); wake_up_interruptible_all(&u->peer_wait); @@ -386,12 +386,12 @@ static int unix_release_sock (struct sock *sk, int embrion) if (skpair!=NULL) { if (sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_SEQPACKET) { - unix_state_wlock(skpair); + unix_state_lock(skpair); /* No more writes */ skpair->sk_shutdown = SHUTDOWN_MASK; if (!skb_queue_empty(&sk->sk_receive_queue) || embrion) skpair->sk_err = ECONNRESET; - unix_state_wunlock(skpair); + unix_state_unlock(skpair); skpair->sk_state_change(skpair); read_lock(&skpair->sk_callback_lock); sk_wake_async(skpair,1,POLL_HUP); @@ -448,7 +448,7 @@ static int unix_listen(struct socket *sock, int backlog) err = -EINVAL; if (!u->addr) goto out; /* No listens on an unbound socket */ - unix_state_wlock(sk); + unix_state_lock(sk); if (sk->sk_state != TCP_CLOSE && sk->sk_state != TCP_LISTEN) goto out_unlock; if (backlog > sk->sk_max_ack_backlog) @@ -462,7 +462,7 @@ static int unix_listen(struct socket *sock, int backlog) err = 0; out_unlock: - unix_state_wunlock(sk); + unix_state_unlock(sk); out: return err; } @@ -881,7 +881,7 @@ static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr, if (!other) goto out; - unix_state_wlock(sk); + unix_state_lock(sk); err = -EPERM; if (!unix_may_send(sk, other)) @@ -896,7 +896,7 @@ static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr, * 1003.1g breaking connected state with AF_UNSPEC */ other = NULL; - unix_state_wlock(sk); + unix_state_lock(sk); } /* @@ -905,19 +905,19 @@ static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr, if (unix_peer(sk)) { struct sock *old_peer = unix_peer(sk); unix_peer(sk)=other; - unix_state_wunlock(sk); + unix_state_unlock(sk); if (other != old_peer) unix_dgram_disconnected(sk, old_peer); sock_put(old_peer); } else { unix_peer(sk)=other; - unix_state_wunlock(sk); + unix_state_unlock(sk); } return 0; out_unlock: - unix_state_wunlock(sk); + unix_state_unlock(sk); sock_put(other); out: return err; @@ -936,7 +936,7 @@ static long unix_wait_for_peer(struct sock *other, long timeo) (skb_queue_len(&other->sk_receive_queue) > other->sk_max_ack_backlog); - unix_state_runlock(other); + unix_state_unlock(other); if (sched) timeo = schedule_timeout(timeo); @@ -994,11 +994,11 @@ restart: goto out; /* Latch state of peer */ - unix_state_rlock(other); + unix_state_lock(other); /* Apparently VFS overslept socket death. Retry. */ if (sock_flag(other, SOCK_DEAD)) { - unix_state_runlock(other); + unix_state_unlock(other); sock_put(other); goto restart; } @@ -1048,18 +1048,18 @@ restart: goto out_unlock; } - unix_state_wlock_nested(sk); + unix_state_lock_nested(sk); if (sk->sk_state != st) { - unix_state_wunlock(sk); - unix_state_runlock(other); + unix_state_unlock(sk); + unix_state_unlock(other); sock_put(other); goto restart; } err = security_unix_stream_connect(sock, other->sk_socket, newsk); if (err) { - unix_state_wunlock(sk); + unix_state_unlock(sk); goto out_unlock; } @@ -1096,7 +1096,7 @@ restart: smp_mb__after_atomic_inc(); /* sock_hold() does an atomic_inc() */ unix_peer(sk) = newsk; - unix_state_wunlock(sk); + unix_state_unlock(sk); /* take ten and and send info to listening sock */ spin_lock(&other->sk_receive_queue.lock); @@ -1105,14 +1105,14 @@ restart: * is installed to listening socket. */ atomic_inc(&newu->inflight); spin_unlock(&other->sk_receive_queue.lock); - unix_state_runlock(other); + unix_state_unlock(other); other->sk_data_ready(other, 0); sock_put(other); return 0; out_unlock: if (other) - unix_state_runlock(other); + unix_state_unlock(other); out: if (skb) @@ -1178,10 +1178,10 @@ static int unix_accept(struct socket *sock, struct socket *newsock, int flags) wake_up_interruptible(&unix_sk(sk)->peer_wait); /* attach accepted sock to socket */ - unix_state_wlock(tsk); + unix_state_lock(tsk); newsock->state = SS_CONNECTED; sock_graft(tsk, newsock); - unix_state_wunlock(tsk); + unix_state_unlock(tsk); return 0; out: @@ -1208,7 +1208,7 @@ static int unix_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_ } u = unix_sk(sk); - unix_state_rlock(sk); + unix_state_lock(sk); if (!u->addr) { sunaddr->sun_family = AF_UNIX; sunaddr->sun_path[0] = 0; @@ -1219,7 +1219,7 @@ static int unix_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_ *uaddr_len = addr->len; memcpy(sunaddr, addr->name, *uaddr_len); } - unix_state_runlock(sk); + unix_state_unlock(sk); sock_put(sk); out: return err; @@ -1337,7 +1337,7 @@ restart: goto out_free; } - unix_state_rlock(other); + unix_state_lock(other); err = -EPERM; if (!unix_may_send(sk, other)) goto out_unlock; @@ -1347,20 +1347,20 @@ restart: * Check with 1003.1g - what should * datagram error */ - unix_state_runlock(other); + unix_state_unlock(other); sock_put(other); err = 0; - unix_state_wlock(sk); + unix_state_lock(sk); if (unix_peer(sk) == other) { unix_peer(sk)=NULL; - unix_state_wunlock(sk); + unix_state_unlock(sk); unix_dgram_disconnected(sk, other); sock_put(other); err = -ECONNREFUSED; } else { - unix_state_wunlock(sk); + unix_state_unlock(sk); } other = NULL; @@ -1397,14 +1397,14 @@ restart: } skb_queue_tail(&other->sk_receive_queue, skb); - unix_state_runlock(other); + unix_state_unlock(other); other->sk_data_ready(other, len); sock_put(other); scm_destroy(siocb->scm); return len; out_unlock: - unix_state_runlock(other); + unix_state_unlock(other); out_free: kfree_skb(skb); out: @@ -1494,14 +1494,14 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock, goto out_err; } - unix_state_rlock(other); + unix_state_lock(other); if (sock_flag(other, SOCK_DEAD) || (other->sk_shutdown & RCV_SHUTDOWN)) goto pipe_err_free; skb_queue_tail(&other->sk_receive_queue, skb); - unix_state_runlock(other); + unix_state_unlock(other); other->sk_data_ready(other, size); sent+=size; } @@ -1512,7 +1512,7 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock, return sent; pipe_err_free: - unix_state_runlock(other); + unix_state_unlock(other); kfree_skb(skb); pipe_err: if (sent==0 && !(msg->msg_flags&MSG_NOSIGNAL)) @@ -1641,7 +1641,7 @@ static long unix_stream_data_wait(struct sock * sk, long timeo) { DEFINE_WAIT(wait); - unix_state_rlock(sk); + unix_state_lock(sk); for (;;) { prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); @@ -1654,14 +1654,14 @@ static long unix_stream_data_wait(struct sock * sk, long timeo) break; set_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); - unix_state_runlock(sk); + unix_state_unlock(sk); timeo = schedule_timeout(timeo); - unix_state_rlock(sk); + unix_state_lock(sk); clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); } finish_wait(sk->sk_sleep, &wait); - unix_state_runlock(sk); + unix_state_unlock(sk); return timeo; } @@ -1816,12 +1816,12 @@ static int unix_shutdown(struct socket *sock, int mode) mode = (mode+1)&(RCV_SHUTDOWN|SEND_SHUTDOWN); if (mode) { - unix_state_wlock(sk); + unix_state_lock(sk); sk->sk_shutdown |= mode; other=unix_peer(sk); if (other) sock_hold(other); - unix_state_wunlock(sk); + unix_state_unlock(sk); sk->sk_state_change(sk); if (other && @@ -1833,9 +1833,9 @@ static int unix_shutdown(struct socket *sock, int mode) peer_mode |= SEND_SHUTDOWN; if (mode&SEND_SHUTDOWN) peer_mode |= RCV_SHUTDOWN; - unix_state_wlock(other); + unix_state_lock(other); other->sk_shutdown |= peer_mode; - unix_state_wunlock(other); + unix_state_unlock(other); other->sk_state_change(other); read_lock(&other->sk_callback_lock); if (peer_mode == SHUTDOWN_MASK) @@ -1973,7 +1973,7 @@ static int unix_seq_show(struct seq_file *seq, void *v) else { struct sock *s = v; struct unix_sock *u = unix_sk(s); - unix_state_rlock(s); + unix_state_lock(s); seq_printf(seq, "%p: %08X %08X %08X %04X %02X %5lu", s, @@ -2001,7 +2001,7 @@ static int unix_seq_show(struct seq_file *seq, void *v) for ( ; i < len; i++) seq_putc(seq, u->addr->name->sun_path[i]); } - unix_state_runlock(s); + unix_state_unlock(s); seq_putc(seq, '\n'); } -- cgit v1.2.3 From 007a880d627aee0e854e793099bb33d0c1130678 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Thu, 31 May 2007 14:49:51 -0700 Subject: [TG3]: Fix link problem on Dell's onboard 5906. The bug is caused by code that always set (TG3_FLAG_USE_MI_INTERRUPT | TG3_FLAG_USE_LINKCHG_REG) on all Dell's onboard devices. With these 2 flags set, the link status is polled by tg3_timer() and will only work when the PHY is set up to interrupt the MAC on link changes. This breaks 5906 because the 5906 PHY does not support TG3_FLAG_USE_MI_INTERRUPT the same as other PHYs. For correctness, only Dell's onboard 5701 needs these 2 flags to be set. This change will fix the 5906 problem and will change other Dell devices except 5700 and 5701 to use the more efficient interrupt-driven link changes. Update version to 3.77. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 023779a581f..2f3184184ad 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -64,8 +64,8 @@ #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "3.76" -#define DRV_MODULE_RELDATE "May 5, 2007" +#define DRV_MODULE_VERSION "3.77" +#define DRV_MODULE_RELDATE "May 31, 2007" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 @@ -10961,6 +10961,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) * upon subsystem IDs. */ if (tp->pdev->subsystem_vendor == PCI_VENDOR_ID_DELL && + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701 && !(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) { tp->tg3_flags |= (TG3_FLAG_USE_MI_INTERRUPT | TG3_FLAG_USE_LINKCHG_REG); -- cgit v1.2.3 From 278a3de5abc7901805689a66340b5af9882b4f9a Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 31 May 2007 15:19:20 -0700 Subject: [AF_UNIX]: Fix datagram connect race causing an OOPS. Based upon an excellent bug report and initial patch by Frederik Deweerdt. The UNIX datagram connect code blindly dereferences other->sk_socket via the call down to the security_unix_may_send() function. Without locking 'other' that pointer can go NULL via unix_release_sock() which does sock_orphan() which also marks the socket SOCK_DEAD. So we have to lock both 'sk' and 'other' yet avoid all kinds of potential deadlocks (connect to self is OK for datagram sockets and it is possible for two datagram sockets to perform a simultaneous connect to each other). So what we do is have a "double lock" function similar to how we handle this situation in other areas of the kernel. We take the lock of the socket pointer with the smallest address first in order to avoid ABBA style deadlocks. Once we have them both locked, we check to see if SOCK_DEAD is set for 'other' and if so, drop everything and retry the lookup. Signed-off-by: David S. Miller --- net/unix/af_unix.c | 43 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 38 insertions(+), 5 deletions(-) diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 453ede86a65..87c794d8fa2 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -858,6 +858,31 @@ out_mknod_parent: goto out_up; } +static void unix_state_double_lock(struct sock *sk1, struct sock *sk2) +{ + if (unlikely(sk1 == sk2) || !sk2) { + unix_state_lock(sk1); + return; + } + if (sk1 < sk2) { + unix_state_lock(sk1); + unix_state_lock_nested(sk2); + } else { + unix_state_lock(sk2); + unix_state_lock_nested(sk1); + } +} + +static void unix_state_double_unlock(struct sock *sk1, struct sock *sk2) +{ + if (unlikely(sk1 == sk2) || !sk2) { + unix_state_unlock(sk1); + return; + } + unix_state_unlock(sk1); + unix_state_unlock(sk2); +} + static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr, int alen, int flags) { @@ -877,11 +902,19 @@ static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr, !unix_sk(sk)->addr && (err = unix_autobind(sock)) != 0) goto out; +restart: other=unix_find_other(sunaddr, alen, sock->type, hash, &err); if (!other) goto out; - unix_state_lock(sk); + unix_state_double_lock(sk, other); + + /* Apparently VFS overslept socket death. Retry. */ + if (sock_flag(other, SOCK_DEAD)) { + unix_state_double_unlock(sk, other); + sock_put(other); + goto restart; + } err = -EPERM; if (!unix_may_send(sk, other)) @@ -896,7 +929,7 @@ static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr, * 1003.1g breaking connected state with AF_UNSPEC */ other = NULL; - unix_state_lock(sk); + unix_state_double_lock(sk, other); } /* @@ -905,19 +938,19 @@ static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr, if (unix_peer(sk)) { struct sock *old_peer = unix_peer(sk); unix_peer(sk)=other; - unix_state_unlock(sk); + unix_state_double_unlock(sk, other); if (other != old_peer) unix_dgram_disconnected(sk, old_peer); sock_put(old_peer); } else { unix_peer(sk)=other; - unix_state_unlock(sk); + unix_state_double_unlock(sk, other); } return 0; out_unlock: - unix_state_unlock(sk); + unix_state_double_unlock(sk, other); sock_put(other); out: return err; -- cgit v1.2.3 From 3f196eb519a419bf83ecc22753943fd0a0de4f8f Mon Sep 17 00:00:00 2001 From: Mark Glines Date: Thu, 31 May 2007 15:44:48 -0700 Subject: [TCP]: Use default 32768-61000 outgoing port range in all cases. This diff changes the default port range used for outgoing connections, from "use 32768-61000 in most cases, but use N-4999 on small boxes (where N is a multiple of 1024, depending on just *how* small the box is)" to just "use 32768-61000 in all cases". I don't believe there are any drawbacks to this change, and it keeps outgoing connection ports farther away from the mess of IANA-registered ports. Signed-off-by: Mark Glines Signed-off-by: David S. Miller --- net/ipv4/inet_connection_sock.c | 4 +--- net/ipv4/tcp.c | 3 --- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index 43fb1600f1f..fbe7714f21d 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c @@ -31,10 +31,8 @@ EXPORT_SYMBOL(inet_csk_timer_bug_msg); /* * This array holds the first and last local port number. - * For high-usage systems, use sysctl to change this to - * 32768-61000 */ -int sysctl_local_port_range[2] = { 1024, 4999 }; +int sysctl_local_port_range[2] = { 32768, 61000 }; int inet_csk_bind_conflict(const struct sock *sk, const struct inet_bind_bucket *tb) diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 766314505c0..cd3c7e95de9 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -2464,13 +2464,10 @@ void __init tcp_init(void) order++) ; if (order >= 4) { - sysctl_local_port_range[0] = 32768; - sysctl_local_port_range[1] = 61000; tcp_death_row.sysctl_max_tw_buckets = 180000; sysctl_tcp_max_orphans = 4096 << (order - 4); sysctl_max_syn_backlog = 1024; } else if (order < 3) { - sysctl_local_port_range[0] = 1024 * (3 - order); tcp_death_row.sysctl_max_tw_buckets >>= (3 - order); sysctl_tcp_max_orphans >>= (3 - order); sysctl_max_syn_backlog = 128; -- cgit v1.2.3 From b206a65d671d359d0947f0b6da9d418c49a9b28a Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Thu, 31 May 2007 21:26:23 -0700 Subject: [ATM]: Fix warning. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The compiler warning drivers/atm/firestream.c: In function ‘top_off_fp’: drivers/atm/firestream.c:1505: warning: cast to pointer from integer of different size does indicate a bug, albeit a minor one. Fixed, by using a 32-bit temporary prior to the call to bus_to_virt(). The larger bug is still present: the entire driver assumes that machine pointers are 32-bit, as it stores pointers in 32-bit hardware registers. This is obvious to anyone who knows the driver well, but for the casual readers it is helpfully noted with FIXME. Signed-off-by: Jeff Garzik Signed-off-by: David S. Miller --- drivers/atm/firestream.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/atm/firestream.c b/drivers/atm/firestream.c index 9c67df5ccfa..7f6d02ce1b5 100644 --- a/drivers/atm/firestream.c +++ b/drivers/atm/firestream.c @@ -1475,6 +1475,7 @@ static void top_off_fp (struct fs_dev *dev, struct freepool *fp, struct FS_BPENTRY *qe, *ne; struct sk_buff *skb; int n = 0; + u32 qe_tmp; fs_dprintk (FS_DEBUG_QUEUE, "Topping off queue at %x (%d-%d/%d)\n", fp->offset, read_fs (dev, FP_CNT (fp->offset)), fp->n, @@ -1502,10 +1503,16 @@ static void top_off_fp (struct fs_dev *dev, struct freepool *fp, ne->skb = skb; ne->fp = fp; - qe = (struct FS_BPENTRY *) (read_fs (dev, FP_EA(fp->offset))); - fs_dprintk (FS_DEBUG_QUEUE, "link at %p\n", qe); - if (qe) { - qe = bus_to_virt ((long) qe); + /* + * FIXME: following code encodes and decodes + * machine pointers (could be 64-bit) into a + * 32-bit register. + */ + + qe_tmp = read_fs (dev, FP_EA(fp->offset)); + fs_dprintk (FS_DEBUG_QUEUE, "link at %x\n", qe_tmp); + if (qe_tmp) { + qe = bus_to_virt ((long) qe_tmp); qe->next = virt_to_bus(ne); qe->flags &= ~FP_FLAGS_EPI; } else -- cgit v1.2.3 From 60468d5b5b6931b4d4d704e26b5f17a6e476e6f8 Mon Sep 17 00:00:00 2001 From: Venkatesh Pallipadi Date: Thu, 31 May 2007 21:28:44 -0700 Subject: [NET]: Make net watchdog timers 1 sec jiffy aligned. round_jiffies for net dev watchdog timer. Signed-off-by: Venkatesh Pallipadi Signed-off-by: David S. Miller --- net/sched/sch_generic.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index cbefe225581..f4d34480a09 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c @@ -224,7 +224,8 @@ void __netdev_watchdog_up(struct net_device *dev) if (dev->tx_timeout) { if (dev->watchdog_timeo <= 0) dev->watchdog_timeo = 5*HZ; - if (!mod_timer(&dev->watchdog_timer, jiffies + dev->watchdog_timeo)) + if (!mod_timer(&dev->watchdog_timer, + round_jiffies(jiffies + dev->watchdog_timeo))) dev_hold(dev); } } -- cgit v1.2.3 From 75202e76893c11ce7f8bcc9a07f994d71e3d5113 Mon Sep 17 00:00:00 2001 From: Bill Nottingham Date: Thu, 31 May 2007 21:33:35 -0700 Subject: [NET]: Fix comparisons of unsigned < 0. Recent gcc versions emit warnings when unsigned variables are compared < 0 or >= 0. Signed-off-by: Bill Nottingham Signed-off-by: David S. Miller --- net/8021q/vlan.c | 3 +-- net/dccp/probe.c | 2 +- net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | 3 +-- net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c | 3 +-- net/sched/act_pedit.c | 3 +-- net/sctp/debug.c | 8 -------- net/sctp/sm_statetable.c | 2 +- net/wanrouter/wanmain.c | 2 +- 8 files changed, 7 insertions(+), 19 deletions(-) diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index ceef57c9ab3..de78c9dd713 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c @@ -736,8 +736,7 @@ static int vlan_ioctl_handler(void __user *arg) case SET_VLAN_NAME_TYPE_CMD: if (!capable(CAP_NET_ADMIN)) return -EPERM; - if ((args.u.name_type >= 0) && - (args.u.name_type < VLAN_NAME_TYPE_HIGHEST)) { + if (args.u.name_type < VLAN_NAME_TYPE_HIGHEST) { vlan_name_type = args.u.name_type; err = 0; } else { diff --git a/net/dccp/probe.c b/net/dccp/probe.c index 1f5e3ba6206..43a3adb027e 100644 --- a/net/dccp/probe.c +++ b/net/dccp/probe.c @@ -128,7 +128,7 @@ static ssize_t dccpprobe_read(struct file *file, char __user *buf, int error = 0, cnt = 0; unsigned char *tbuf; - if (!buf || len < 0) + if (!buf) return -EINVAL; if (len == 0) diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c index 6d2a0820511..dc442fb791b 100644 --- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c @@ -177,8 +177,7 @@ static unsigned int ipv6_confirm(unsigned int hooknum, protoff = nf_ct_ipv6_skip_exthdr(*pskb, extoff, &pnum, (*pskb)->len - extoff); - if (protoff < 0 || protoff > (*pskb)->len || - pnum == NEXTHDR_FRAGMENT) { + if (protoff > (*pskb)->len || pnum == NEXTHDR_FRAGMENT) { DEBUGP("proto header not found\n"); return NF_ACCEPT; } diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c index 0be790d250f..8814b95b232 100644 --- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c +++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c @@ -168,8 +168,7 @@ icmpv6_error_message(struct sk_buff *skb, skb->len - inip6off - sizeof(struct ipv6hdr)); - if ((inprotoff < 0) || (inprotoff > skb->len) || - (inprotonum == NEXTHDR_FRAGMENT)) { + if ((inprotoff > skb->len) || (inprotonum == NEXTHDR_FRAGMENT)) { DEBUGP("icmpv6_error: Can't get protocol header in ICMPv6 payload.\n"); return -NF_ACCEPT; } diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c index 45b3cda86a2..6f8684b5617 100644 --- a/net/sched/act_pedit.c +++ b/net/sched/act_pedit.c @@ -164,8 +164,7 @@ static int tcf_pedit(struct sk_buff *skb, struct tc_action *a, printk("offset must be on 32 bit boundaries\n"); goto bad; } - if (skb->len < 0 || - (offset > 0 && offset > skb->len)) { + if (offset > 0 && offset > skb->len) { printk("offset %d cant exceed pkt length %d\n", offset, skb->len); goto bad; diff --git a/net/sctp/debug.c b/net/sctp/debug.c index e8c0f7435d7..80f70aa5338 100644 --- a/net/sctp/debug.c +++ b/net/sctp/debug.c @@ -77,8 +77,6 @@ static const char *sctp_cid_tbl[SCTP_NUM_BASE_CHUNK_TYPES] = { /* Lookup "chunk type" debug name. */ const char *sctp_cname(const sctp_subtype_t cid) { - if (cid.chunk < 0) - return "illegal chunk id"; if (cid.chunk <= SCTP_CID_BASE_MAX) return sctp_cid_tbl[cid.chunk]; @@ -146,8 +144,6 @@ static const char *sctp_primitive_tbl[SCTP_NUM_PRIMITIVE_TYPES] = { /* Lookup primitive debug name. */ const char *sctp_pname(const sctp_subtype_t id) { - if (id.primitive < 0) - return "illegal primitive"; if (id.primitive <= SCTP_EVENT_PRIMITIVE_MAX) return sctp_primitive_tbl[id.primitive]; return "unknown_primitive"; @@ -161,8 +157,6 @@ static const char *sctp_other_tbl[] = { /* Lookup "other" debug name. */ const char *sctp_oname(const sctp_subtype_t id) { - if (id.other < 0) - return "illegal 'other' event"; if (id.other <= SCTP_EVENT_OTHER_MAX) return sctp_other_tbl[id.other]; return "unknown 'other' event"; @@ -184,8 +178,6 @@ static const char *sctp_timer_tbl[] = { /* Lookup timer debug name. */ const char *sctp_tname(const sctp_subtype_t id) { - if (id.timeout < 0) - return "illegal 'timer' event"; if (id.timeout <= SCTP_EVENT_TIMEOUT_MAX) return sctp_timer_tbl[id.timeout]; return "unknown_timer"; diff --git a/net/sctp/sm_statetable.c b/net/sctp/sm_statetable.c index 523071c7902..70a91ece3c4 100644 --- a/net/sctp/sm_statetable.c +++ b/net/sctp/sm_statetable.c @@ -960,7 +960,7 @@ static const sctp_sm_table_entry_t *sctp_chunk_event_lookup(sctp_cid_t cid, if (state > SCTP_STATE_MAX) return &bug; - if (cid >= 0 && cid <= SCTP_CID_BASE_MAX) + if (cid <= SCTP_CID_BASE_MAX) return &chunk_event_table[cid][state]; if (sctp_prsctp_enable) { diff --git a/net/wanrouter/wanmain.c b/net/wanrouter/wanmain.c index 7a19e0ede28..849cc06bd91 100644 --- a/net/wanrouter/wanmain.c +++ b/net/wanrouter/wanmain.c @@ -454,7 +454,7 @@ static int wanrouter_device_setup(struct wan_device *wandev, } if (conf->data_size && conf->data) { - if (conf->data_size > 128000 || conf->data_size < 0) { + if (conf->data_size > 128000) { printk(KERN_INFO "%s: ERROR, Invalid firmware data size %i !\n", wandev->name, conf->data_size); -- cgit v1.2.3 From 6418204f919c030ca0c943f6c77dc84aff2ec0d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= Date: Thu, 31 May 2007 21:37:55 -0700 Subject: [TCP]: Fix GSO ignorance of pkts_acked arg (cong.cntrl modules) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The code used to ignore GSO completely, passing either way too small or zero pkts_acked when GSO skb or part of it got ACKed. In addition, there is no need to calculate the value in the loop but simple arithmetics after the loop is sufficient. There is no need to handle SYN case specially because congestion control modules are not yet initialized when FLAG_SYN_ACKED is set. Signed-off-by: Ilpo Järvinen Signed-off-by: David S. Miller --- net/ipv4/tcp_input.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 38cb25b48bf..74683d81c3f 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -2407,8 +2407,8 @@ static int tcp_clean_rtx_queue(struct sock *sk, __s32 *seq_rtt_p) struct sk_buff *skb; __u32 now = tcp_time_stamp; int acked = 0; + int prior_packets = tp->packets_out; __s32 seq_rtt = -1; - u32 pkts_acked = 0; ktime_t last_ackt = ktime_set(0,0); while ((skb = tcp_write_queue_head(sk)) && @@ -2437,7 +2437,6 @@ static int tcp_clean_rtx_queue(struct sock *sk, __s32 *seq_rtt_p) */ if (!(scb->flags & TCPCB_FLAG_SYN)) { acked |= FLAG_DATA_ACKED; - ++pkts_acked; } else { acked |= FLAG_SYN_ACKED; tp->retrans_stamp = 0; @@ -2481,6 +2480,7 @@ static int tcp_clean_rtx_queue(struct sock *sk, __s32 *seq_rtt_p) } if (acked&FLAG_ACKED) { + u32 pkts_acked = prior_packets - tp->packets_out; const struct tcp_congestion_ops *ca_ops = inet_csk(sk)->icsk_ca_ops; -- cgit v1.2.3 From 4fcd6b991685493185c2bb8a76b21aadb658bd76 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Thu, 31 May 2007 22:15:50 -0700 Subject: [NET] gso: Fix GSO feature mask in sk_setup_caps This isn't a bug just yet as only TCP uses sk_setup_caps for GSO. However, if and when UDP or something else starts using it this is likely to cause a problem if we forget to add software emulation for it at the same time. The problem is that right now we translate GSO emulation to the bitmask NETIF_F_GSO_MASK, which includes every protocol, even ones that we cannot emulate. This patch makes it provide only the ones that we can emulate. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- net/core/sock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/core/sock.c b/net/core/sock.c index 7e51d3a5e4f..c14ce0198d2 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -998,7 +998,7 @@ void sk_setup_caps(struct sock *sk, struct dst_entry *dst) __sk_dst_set(sk, dst); sk->sk_route_caps = dst->dev->features; if (sk->sk_route_caps & NETIF_F_GSO) - sk->sk_route_caps |= NETIF_F_GSO_MASK; + sk->sk_route_caps |= NETIF_F_GSO_SOFTWARE; if (sk_can_gso(sk)) { if (dst->header_len) sk->sk_route_caps &= ~NETIF_F_GSO_MASK; -- cgit v1.2.3 From 584bdf8cbdf6f277c2a00e083257ee75687cf6f4 Mon Sep 17 00:00:00 2001 From: Wei Dong Date: Thu, 31 May 2007 22:49:28 -0700 Subject: [IPV4]: Fix "ipOutNoRoutes" counter error for TCP and UDP Signed-off-by: Wei Dong Signed-off-by: David S. Miller --- net/ipv4/datagram.c | 6 +++++- net/ipv4/tcp_ipv4.c | 5 ++++- net/ipv4/udp.c | 5 ++++- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/net/ipv4/datagram.c b/net/ipv4/datagram.c index dd02a45d0f6..0301dd468cf 100644 --- a/net/ipv4/datagram.c +++ b/net/ipv4/datagram.c @@ -50,8 +50,12 @@ int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) RT_CONN_FLAGS(sk), oif, sk->sk_protocol, inet->sport, usin->sin_port, sk, 1); - if (err) + if (err) { + if (err == -ENETUNREACH) + IP_INC_STATS_BH(IPSTATS_MIB_OUTNOROUTES); return err; + } + if ((rt->rt_flags & RTCF_BROADCAST) && !sock_flag(sk, SOCK_BROADCAST)) { ip_rt_put(rt); return -EACCES; diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 5a3e7f839fc..47c61055eb6 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -192,8 +192,11 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) RT_CONN_FLAGS(sk), sk->sk_bound_dev_if, IPPROTO_TCP, inet->sport, usin->sin_port, sk, 1); - if (tmp < 0) + if (tmp < 0) { + if (tmp == -ENETUNREACH) + IP_INC_STATS_BH(IPSTATS_MIB_OUTNOROUTES); return tmp; + } if (rt->rt_flags & (RTCF_MULTICAST | RTCF_BROADCAST)) { ip_rt_put(rt); diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 4c7e95fa090..5da703e699d 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -722,8 +722,11 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, .dport = dport } } }; security_sk_classify_flow(sk, &fl); err = ip_route_output_flow(&rt, &fl, sk, 1); - if (err) + if (err) { + if (err == -ENETUNREACH) + IP_INC_STATS_BH(IPSTATS_MIB_OUTNOROUTES); goto out; + } err = -EACCES; if ((rt->rt_flags & RTCF_BROADCAST) && -- cgit v1.2.3 From 6e1d91039becc9d5bcd046d8c709dbaf471220e3 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Fri, 1 Jun 2007 11:45:04 -0700 Subject: [ICMP]: Fix icmp_errors_use_inbound_ifaddr sysctl Currently when icmp_errors_use_inbound_ifaddr is set and an ICMP error is sent after the packet passed through ip_output(), an address from the outgoing interface is chosen as ICMP source address since skb->dev doesn't point to the incoming interface anymore. Fix this by doing an interface lookup on rt->dst.iif and using that device. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/ipv4/icmp.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index e238b17f554..02a899bec19 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c @@ -514,12 +514,15 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info) saddr = iph->daddr; if (!(rt->rt_flags & RTCF_LOCAL)) { - /* This is broken, skb_in->dev points to the outgoing device - * after the packet passes through ip_output(). - */ - if (skb_in->dev && sysctl_icmp_errors_use_inbound_ifaddr) - saddr = inet_select_addr(skb_in->dev, 0, RT_SCOPE_LINK); - else + struct net_device *dev = NULL; + + if (rt->fl.iif && sysctl_icmp_errors_use_inbound_ifaddr) + dev = dev_get_by_index(rt->fl.iif); + + if (dev) { + saddr = inet_select_addr(dev, 0, RT_SCOPE_LINK); + dev_put(dev); + } else saddr = 0; } -- cgit v1.2.3