diff options
Diffstat (limited to 'net/decnet')
-rw-r--r-- | net/decnet/af_decnet.c | 6 | ||||
-rw-r--r-- | net/decnet/dn_dev.c | 100 | ||||
-rw-r--r-- | net/decnet/dn_fib.c | 6 | ||||
-rw-r--r-- | net/decnet/dn_neigh.c | 2 | ||||
-rw-r--r-- | net/decnet/dn_route.c | 137 | ||||
-rw-r--r-- | net/decnet/dn_rules.c | 2 |
6 files changed, 147 insertions, 106 deletions
diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c index 6f97268ed85..2af15b15d1f 100644 --- a/net/decnet/af_decnet.c +++ b/net/decnet/af_decnet.c @@ -829,7 +829,7 @@ static int dn_confirm_accept(struct sock *sk, long *timeo, gfp_t allocation) return -EINVAL; scp->state = DN_CC; - scp->segsize_loc = dst_metric(__sk_dst_get(sk), RTAX_ADVMSS); + scp->segsize_loc = dst_metric_advmss(__sk_dst_get(sk)); dn_send_conn_conf(sk, allocation); prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); @@ -958,7 +958,7 @@ static int __dn_connect(struct sock *sk, struct sockaddr_dn *addr, int addrlen, sk->sk_route_caps = sk->sk_dst_cache->dev->features; sock->state = SS_CONNECTING; scp->state = DN_CI; - scp->segsize_loc = dst_metric(sk->sk_dst_cache, RTAX_ADVMSS); + scp->segsize_loc = dst_metric_advmss(sk->sk_dst_cache); dn_nsp_send_conninit(sk, NSP_CI); err = -EINPROGRESS; @@ -1850,7 +1850,7 @@ unsigned dn_mss_from_pmtu(struct net_device *dev, int mtu) { unsigned mss = 230 - DN_MAX_NSP_DATA_HEADER; if (dev) { - struct dn_dev *dn_db = dev->dn_ptr; + struct dn_dev *dn_db = rcu_dereference_raw(dev->dn_ptr); mtu -= LL_RESERVED_SPACE(dev); if (dn_db->use_long) mtu -= 21; diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c index 9b73e0b03e3..0dcaa903e00 100644 --- a/net/decnet/dn_dev.c +++ b/net/decnet/dn_dev.c @@ -267,7 +267,7 @@ static int dn_forwarding_proc(ctl_table *table, int write, if (table->extra1 == NULL) return -EINVAL; - dn_db = dev->dn_ptr; + dn_db = rcu_dereference_raw(dev->dn_ptr); old = dn_db->parms.forwarding; err = proc_dointvec(table, write, buffer, lenp, ppos); @@ -332,14 +332,19 @@ static struct dn_ifaddr *dn_dev_alloc_ifa(void) return ifa; } -static __inline__ void dn_dev_free_ifa(struct dn_ifaddr *ifa) +static void dn_dev_free_ifa_rcu(struct rcu_head *head) { - kfree(ifa); + kfree(container_of(head, struct dn_ifaddr, rcu)); } -static void dn_dev_del_ifa(struct dn_dev *dn_db, struct dn_ifaddr **ifap, int destroy) +static void dn_dev_free_ifa(struct dn_ifaddr *ifa) { - struct dn_ifaddr *ifa1 = *ifap; + call_rcu(&ifa->rcu, dn_dev_free_ifa_rcu); +} + +static void dn_dev_del_ifa(struct dn_dev *dn_db, struct dn_ifaddr __rcu **ifap, int destroy) +{ + struct dn_ifaddr *ifa1 = rtnl_dereference(*ifap); unsigned char mac_addr[6]; struct net_device *dev = dn_db->dev; @@ -373,7 +378,9 @@ static int dn_dev_insert_ifa(struct dn_dev *dn_db, struct dn_ifaddr *ifa) ASSERT_RTNL(); /* Check for duplicates */ - for(ifa1 = dn_db->ifa_list; ifa1; ifa1 = ifa1->ifa_next) { + for (ifa1 = rtnl_dereference(dn_db->ifa_list); + ifa1 != NULL; + ifa1 = rtnl_dereference(ifa1->ifa_next)) { if (ifa1->ifa_local == ifa->ifa_local) return -EEXIST; } @@ -386,7 +393,7 @@ static int dn_dev_insert_ifa(struct dn_dev *dn_db, struct dn_ifaddr *ifa) } ifa->ifa_next = dn_db->ifa_list; - dn_db->ifa_list = ifa; + rcu_assign_pointer(dn_db->ifa_list, ifa); dn_ifaddr_notify(RTM_NEWADDR, ifa); blocking_notifier_call_chain(&dnaddr_chain, NETDEV_UP, ifa); @@ -396,7 +403,7 @@ static int dn_dev_insert_ifa(struct dn_dev *dn_db, struct dn_ifaddr *ifa) static int dn_dev_set_ifa(struct net_device *dev, struct dn_ifaddr *ifa) { - struct dn_dev *dn_db = dev->dn_ptr; + struct dn_dev *dn_db = rtnl_dereference(dev->dn_ptr); int rv; if (dn_db == NULL) { @@ -425,7 +432,8 @@ int dn_dev_ioctl(unsigned int cmd, void __user *arg) struct sockaddr_dn *sdn = (struct sockaddr_dn *)&ifr->ifr_addr; struct dn_dev *dn_db; struct net_device *dev; - struct dn_ifaddr *ifa = NULL, **ifap = NULL; + struct dn_ifaddr *ifa = NULL; + struct dn_ifaddr __rcu **ifap = NULL; int ret = 0; if (copy_from_user(ifr, arg, DN_IFREQ_SIZE)) @@ -454,8 +462,10 @@ int dn_dev_ioctl(unsigned int cmd, void __user *arg) goto done; } - if ((dn_db = dev->dn_ptr) != NULL) { - for (ifap = &dn_db->ifa_list; (ifa=*ifap) != NULL; ifap = &ifa->ifa_next) + if ((dn_db = rtnl_dereference(dev->dn_ptr)) != NULL) { + for (ifap = &dn_db->ifa_list; + (ifa = rtnl_dereference(*ifap)) != NULL; + ifap = &ifa->ifa_next) if (strcmp(ifr->ifr_name, ifa->ifa_label) == 0) break; } @@ -558,7 +568,7 @@ static struct dn_dev *dn_dev_by_index(int ifindex) dev = __dev_get_by_index(&init_net, ifindex); if (dev) - dn_dev = dev->dn_ptr; + dn_dev = rtnl_dereference(dev->dn_ptr); return dn_dev; } @@ -576,7 +586,8 @@ static int dn_nl_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) struct nlattr *tb[IFA_MAX+1]; struct dn_dev *dn_db; struct ifaddrmsg *ifm; - struct dn_ifaddr *ifa, **ifap; + struct dn_ifaddr *ifa; + struct dn_ifaddr __rcu **ifap; int err = -EINVAL; if (!net_eq(net, &init_net)) @@ -592,7 +603,9 @@ static int dn_nl_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) goto errout; err = -EADDRNOTAVAIL; - for (ifap = &dn_db->ifa_list; (ifa = *ifap); ifap = &ifa->ifa_next) { + for (ifap = &dn_db->ifa_list; + (ifa = rtnl_dereference(*ifap)) != NULL; + ifap = &ifa->ifa_next) { if (tb[IFA_LOCAL] && nla_memcmp(tb[IFA_LOCAL], &ifa->ifa_local, 2)) continue; @@ -632,7 +645,7 @@ static int dn_nl_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) if ((dev = __dev_get_by_index(&init_net, ifm->ifa_index)) == NULL) return -ENODEV; - if ((dn_db = dev->dn_ptr) == NULL) { + if ((dn_db = rtnl_dereference(dev->dn_ptr)) == NULL) { dn_db = dn_dev_create(dev, &err); if (!dn_db) return err; @@ -748,11 +761,11 @@ static int dn_nl_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb) skip_naddr = 0; } - if ((dn_db = dev->dn_ptr) == NULL) + if ((dn_db = rtnl_dereference(dev->dn_ptr)) == NULL) goto cont; - for (ifa = dn_db->ifa_list, dn_idx = 0; ifa; - ifa = ifa->ifa_next, dn_idx++) { + for (ifa = rtnl_dereference(dn_db->ifa_list), dn_idx = 0; ifa; + ifa = rtnl_dereference(ifa->ifa_next), dn_idx++) { if (dn_idx < skip_naddr) continue; @@ -773,21 +786,22 @@ done: static int dn_dev_get_first(struct net_device *dev, __le16 *addr) { - struct dn_dev *dn_db = (struct dn_dev *)dev->dn_ptr; + struct dn_dev *dn_db; struct dn_ifaddr *ifa; int rv = -ENODEV; + rcu_read_lock(); + dn_db = rcu_dereference(dev->dn_ptr); if (dn_db == NULL) goto out; - rtnl_lock(); - ifa = dn_db->ifa_list; + ifa = rcu_dereference(dn_db->ifa_list); if (ifa != NULL) { *addr = ifa->ifa_local; rv = 0; } - rtnl_unlock(); out: + rcu_read_unlock(); return rv; } @@ -823,7 +837,7 @@ static void dn_send_endnode_hello(struct net_device *dev, struct dn_ifaddr *ifa) struct endnode_hello_message *msg; struct sk_buff *skb = NULL; __le16 *pktlen; - struct dn_dev *dn_db = (struct dn_dev *)dev->dn_ptr; + struct dn_dev *dn_db = rcu_dereference_raw(dev->dn_ptr); if ((skb = dn_alloc_skb(NULL, sizeof(*msg), GFP_ATOMIC)) == NULL) return; @@ -889,7 +903,7 @@ static int dn_am_i_a_router(struct dn_neigh *dn, struct dn_dev *dn_db, struct dn static void dn_send_router_hello(struct net_device *dev, struct dn_ifaddr *ifa) { int n; - struct dn_dev *dn_db = dev->dn_ptr; + struct dn_dev *dn_db = rcu_dereference_raw(dev->dn_ptr); struct dn_neigh *dn = (struct dn_neigh *)dn_db->router; struct sk_buff *skb; size_t size; @@ -960,7 +974,7 @@ static void dn_send_router_hello(struct net_device *dev, struct dn_ifaddr *ifa) static void dn_send_brd_hello(struct net_device *dev, struct dn_ifaddr *ifa) { - struct dn_dev *dn_db = (struct dn_dev *)dev->dn_ptr; + struct dn_dev *dn_db = rcu_dereference_raw(dev->dn_ptr); if (dn_db->parms.forwarding == 0) dn_send_endnode_hello(dev, ifa); @@ -998,7 +1012,7 @@ static void dn_send_ptp_hello(struct net_device *dev, struct dn_ifaddr *ifa) static int dn_eth_up(struct net_device *dev) { - struct dn_dev *dn_db = dev->dn_ptr; + struct dn_dev *dn_db = rcu_dereference_raw(dev->dn_ptr); if (dn_db->parms.forwarding == 0) dev_mc_add(dev, dn_rt_all_end_mcast); @@ -1012,7 +1026,7 @@ static int dn_eth_up(struct net_device *dev) static void dn_eth_down(struct net_device *dev) { - struct dn_dev *dn_db = dev->dn_ptr; + struct dn_dev *dn_db = rcu_dereference_raw(dev->dn_ptr); if (dn_db->parms.forwarding == 0) dev_mc_del(dev, dn_rt_all_end_mcast); @@ -1025,12 +1039,16 @@ static void dn_dev_set_timer(struct net_device *dev); static void dn_dev_timer_func(unsigned long arg) { struct net_device *dev = (struct net_device *)arg; - struct dn_dev *dn_db = dev->dn_ptr; + struct dn_dev *dn_db; struct dn_ifaddr *ifa; + rcu_read_lock(); + dn_db = rcu_dereference(dev->dn_ptr); if (dn_db->t3 <= dn_db->parms.t2) { if (dn_db->parms.timer3) { - for(ifa = dn_db->ifa_list; ifa; ifa = ifa->ifa_next) { + for (ifa = rcu_dereference(dn_db->ifa_list); + ifa; + ifa = rcu_dereference(ifa->ifa_next)) { if (!(ifa->ifa_flags & IFA_F_SECONDARY)) dn_db->parms.timer3(dev, ifa); } @@ -1039,13 +1057,13 @@ static void dn_dev_timer_func(unsigned long arg) } else { dn_db->t3 -= dn_db->parms.t2; } - + rcu_read_unlock(); dn_dev_set_timer(dev); } static void dn_dev_set_timer(struct net_device *dev) { - struct dn_dev *dn_db = dev->dn_ptr; + struct dn_dev *dn_db = rcu_dereference_raw(dev->dn_ptr); if (dn_db->parms.t2 > dn_db->parms.t3) dn_db->parms.t2 = dn_db->parms.t3; @@ -1077,8 +1095,8 @@ static struct dn_dev *dn_dev_create(struct net_device *dev, int *err) return NULL; memcpy(&dn_db->parms, p, sizeof(struct dn_dev_parms)); - smp_wmb(); - dev->dn_ptr = dn_db; + + rcu_assign_pointer(dev->dn_ptr, dn_db); dn_db->dev = dev; init_timer(&dn_db->timer); @@ -1086,7 +1104,7 @@ static struct dn_dev *dn_dev_create(struct net_device *dev, int *err) dn_db->neigh_parms = neigh_parms_alloc(dev, &dn_neigh_table); if (!dn_db->neigh_parms) { - dev->dn_ptr = NULL; + rcu_assign_pointer(dev->dn_ptr, NULL); kfree(dn_db); return NULL; } @@ -1125,7 +1143,7 @@ void dn_dev_up(struct net_device *dev) struct dn_ifaddr *ifa; __le16 addr = decnet_address; int maybe_default = 0; - struct dn_dev *dn_db = (struct dn_dev *)dev->dn_ptr; + struct dn_dev *dn_db = rtnl_dereference(dev->dn_ptr); if ((dev->type != ARPHRD_ETHER) && (dev->type != ARPHRD_LOOPBACK)) return; @@ -1176,7 +1194,7 @@ void dn_dev_up(struct net_device *dev) static void dn_dev_delete(struct net_device *dev) { - struct dn_dev *dn_db = dev->dn_ptr; + struct dn_dev *dn_db = rtnl_dereference(dev->dn_ptr); if (dn_db == NULL) return; @@ -1204,13 +1222,13 @@ static void dn_dev_delete(struct net_device *dev) void dn_dev_down(struct net_device *dev) { - struct dn_dev *dn_db = dev->dn_ptr; + struct dn_dev *dn_db = rtnl_dereference(dev->dn_ptr); struct dn_ifaddr *ifa; if (dn_db == NULL) return; - while((ifa = dn_db->ifa_list) != NULL) { + while ((ifa = rtnl_dereference(dn_db->ifa_list)) != NULL) { dn_dev_del_ifa(dn_db, &dn_db->ifa_list, 0); dn_dev_free_ifa(ifa); } @@ -1270,7 +1288,7 @@ static inline int is_dn_dev(struct net_device *dev) } static void *dn_dev_seq_start(struct seq_file *seq, loff_t *pos) - __acquires(rcu) + __acquires(RCU) { int i; struct net_device *dev; @@ -1313,7 +1331,7 @@ static void *dn_dev_seq_next(struct seq_file *seq, void *v, loff_t *pos) } static void dn_dev_seq_stop(struct seq_file *seq, void *v) - __releases(rcu) + __releases(RCU) { rcu_read_unlock(); } @@ -1340,7 +1358,7 @@ static int dn_dev_seq_show(struct seq_file *seq, void *v) struct net_device *dev = v; char peer_buf[DN_ASCBUF_LEN]; char router_buf[DN_ASCBUF_LEN]; - struct dn_dev *dn_db = dev->dn_ptr; + struct dn_dev *dn_db = rcu_dereference(dev->dn_ptr); seq_printf(seq, "%-8s %1s %04u %04u %04lu %04lu" " %04hu %03d %02x %-10s %-7s %-7s\n", diff --git a/net/decnet/dn_fib.c b/net/decnet/dn_fib.c index 4ab96c15166..0ef0a81bcd7 100644 --- a/net/decnet/dn_fib.c +++ b/net/decnet/dn_fib.c @@ -610,10 +610,12 @@ static void dn_fib_del_ifaddr(struct dn_ifaddr *ifa) /* Scan device list */ rcu_read_lock(); for_each_netdev_rcu(&init_net, dev) { - dn_db = dev->dn_ptr; + dn_db = rcu_dereference(dev->dn_ptr); if (dn_db == NULL) continue; - for(ifa2 = dn_db->ifa_list; ifa2; ifa2 = ifa2->ifa_next) { + for (ifa2 = rcu_dereference(dn_db->ifa_list); + ifa2 != NULL; + ifa2 = rcu_dereference(ifa2->ifa_next)) { if (ifa2->ifa_local == ifa->ifa_local) { found_it = 1; break; diff --git a/net/decnet/dn_neigh.c b/net/decnet/dn_neigh.c index a085dbcf5c7..602dade7e9a 100644 --- a/net/decnet/dn_neigh.c +++ b/net/decnet/dn_neigh.c @@ -391,7 +391,7 @@ int dn_neigh_router_hello(struct sk_buff *skb) write_lock(&neigh->lock); neigh->used = jiffies; - dn_db = (struct dn_dev *)neigh->dev->dn_ptr; + dn_db = rcu_dereference(neigh->dev->dn_ptr); if (!(neigh->nud_state & NUD_PERMANENT)) { neigh->updated = jiffies; diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c index df0f3e54ff8..5e636365d33 100644 --- a/net/decnet/dn_route.c +++ b/net/decnet/dn_route.c @@ -93,7 +93,7 @@ struct dn_rt_hash_bucket { - struct dn_route *chain; + struct dn_route __rcu *chain; spinlock_t lock; }; @@ -110,6 +110,8 @@ static unsigned long dn_rt_deadline; static int dn_dst_gc(struct dst_ops *ops); static struct dst_entry *dn_dst_check(struct dst_entry *, __u32); +static unsigned int dn_dst_default_advmss(const struct dst_entry *dst); +static unsigned int dn_dst_default_mtu(const struct dst_entry *dst); static struct dst_entry *dn_dst_negative_advice(struct dst_entry *); static void dn_dst_link_failure(struct sk_buff *); static void dn_dst_update_pmtu(struct dst_entry *dst, u32 mtu); @@ -129,6 +131,8 @@ static struct dst_ops dn_dst_ops = { .gc_thresh = 128, .gc = dn_dst_gc, .check = dn_dst_check, + .default_advmss = dn_dst_default_advmss, + .default_mtu = dn_dst_default_mtu, .negative_advice = dn_dst_negative_advice, .link_failure = dn_dst_link_failure, .update_pmtu = dn_dst_update_pmtu, @@ -157,15 +161,17 @@ static inline void dnrt_drop(struct dn_route *rt) static void dn_dst_check_expire(unsigned long dummy) { int i; - struct dn_route *rt, **rtp; + struct dn_route *rt; + struct dn_route __rcu **rtp; unsigned long now = jiffies; unsigned long expire = 120 * HZ; - for(i = 0; i <= dn_rt_hash_mask; i++) { + for (i = 0; i <= dn_rt_hash_mask; i++) { rtp = &dn_rt_hash_table[i].chain; spin_lock(&dn_rt_hash_table[i].lock); - while((rt=*rtp) != NULL) { + while ((rt = rcu_dereference_protected(*rtp, + lockdep_is_held(&dn_rt_hash_table[i].lock))) != NULL) { if (atomic_read(&rt->dst.__refcnt) || (now - rt->dst.lastuse) < expire) { rtp = &rt->dst.dn_next; @@ -186,17 +192,19 @@ static void dn_dst_check_expire(unsigned long dummy) static int dn_dst_gc(struct dst_ops *ops) { - struct dn_route *rt, **rtp; + struct dn_route *rt; + struct dn_route __rcu **rtp; int i; unsigned long now = jiffies; unsigned long expire = 10 * HZ; - for(i = 0; i <= dn_rt_hash_mask; i++) { + for (i = 0; i <= dn_rt_hash_mask; i++) { spin_lock_bh(&dn_rt_hash_table[i].lock); rtp = &dn_rt_hash_table[i].chain; - while((rt=*rtp) != NULL) { + while ((rt = rcu_dereference_protected(*rtp, + lockdep_is_held(&dn_rt_hash_table[i].lock))) != NULL) { if (atomic_read(&rt->dst.__refcnt) || (now - rt->dst.lastuse) < expire) { rtp = &rt->dst.dn_next; @@ -227,7 +235,7 @@ static void dn_dst_update_pmtu(struct dst_entry *dst, u32 mtu) { u32 min_mtu = 230; struct dn_dev *dn = dst->neighbour ? - (struct dn_dev *)dst->neighbour->dev->dn_ptr : NULL; + rcu_dereference_raw(dst->neighbour->dev->dn_ptr) : NULL; if (dn && dn->use_long == 0) min_mtu -= 6; @@ -236,13 +244,14 @@ static void dn_dst_update_pmtu(struct dst_entry *dst, u32 mtu) if (dst_metric(dst, RTAX_MTU) > mtu && mtu >= min_mtu) { if (!(dst_metric_locked(dst, RTAX_MTU))) { - dst->metrics[RTAX_MTU-1] = mtu; + dst_metric_set(dst, RTAX_MTU, mtu); dst_set_expires(dst, dn_rt_mtu_expires); } if (!(dst_metric_locked(dst, RTAX_ADVMSS))) { u32 mss = mtu - DN_MAX_NSP_DATA_HEADER; - if (dst_metric(dst, RTAX_ADVMSS) > mss) - dst->metrics[RTAX_ADVMSS-1] = mss; + u32 existing_mss = dst_metric_raw(dst, RTAX_ADVMSS); + if (!existing_mss || existing_mss > mss) + dst_metric_set(dst, RTAX_ADVMSS, mss); } } } @@ -267,23 +276,25 @@ static void dn_dst_link_failure(struct sk_buff *skb) static inline int compare_keys(struct flowi *fl1, struct flowi *fl2) { - return ((fl1->nl_u.dn_u.daddr ^ fl2->nl_u.dn_u.daddr) | - (fl1->nl_u.dn_u.saddr ^ fl2->nl_u.dn_u.saddr) | + return ((fl1->fld_dst ^ fl2->fld_dst) | + (fl1->fld_src ^ fl2->fld_src) | (fl1->mark ^ fl2->mark) | - (fl1->nl_u.dn_u.scope ^ fl2->nl_u.dn_u.scope) | + (fl1->fld_scope ^ fl2->fld_scope) | (fl1->oif ^ fl2->oif) | (fl1->iif ^ fl2->iif)) == 0; } static int dn_insert_route(struct dn_route *rt, unsigned hash, struct dn_route **rp) { - struct dn_route *rth, **rthp; + struct dn_route *rth; + struct dn_route __rcu **rthp; unsigned long now = jiffies; rthp = &dn_rt_hash_table[hash].chain; spin_lock_bh(&dn_rt_hash_table[hash].lock); - while((rth = *rthp) != NULL) { + while ((rth = rcu_dereference_protected(*rthp, + lockdep_is_held(&dn_rt_hash_table[hash].lock))) != NULL) { if (compare_keys(&rth->fl, &rt->fl)) { /* Put it first */ *rthp = rth->dst.dn_next; @@ -315,15 +326,15 @@ static void dn_run_flush(unsigned long dummy) int i; struct dn_route *rt, *next; - for(i = 0; i < dn_rt_hash_mask; i++) { + for (i = 0; i < dn_rt_hash_mask; i++) { spin_lock_bh(&dn_rt_hash_table[i].lock); - if ((rt = xchg(&dn_rt_hash_table[i].chain, NULL)) == NULL) + if ((rt = xchg((struct dn_route **)&dn_rt_hash_table[i].chain, NULL)) == NULL) goto nothing_to_declare; - for(; rt; rt=next) { - next = rt->dst.dn_next; - rt->dst.dn_next = NULL; + for(; rt; rt = next) { + next = rcu_dereference_raw(rt->dst.dn_next); + RCU_INIT_POINTER(rt->dst.dn_next, NULL); dst_free((struct dst_entry *)rt); } @@ -458,15 +469,16 @@ static int dn_return_long(struct sk_buff *skb) */ static int dn_route_rx_packet(struct sk_buff *skb) { - struct dn_skb_cb *cb = DN_SKB_CB(skb); + struct dn_skb_cb *cb; int err; if ((err = dn_route_input(skb)) == 0) return dst_input(skb); + cb = DN_SKB_CB(skb); if (decnet_debug_level & 4) { char *devname = skb->dev ? skb->dev->name : "???"; - struct dn_skb_cb *cb = DN_SKB_CB(skb); + printk(KERN_DEBUG "DECnet: dn_route_rx_packet: rt_flags=0x%02x dev=%s len=%d src=0x%04hx dst=0x%04hx err=%d type=%d\n", (int)cb->rt_flags, devname, skb->len, @@ -573,7 +585,7 @@ int dn_route_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type struct dn_skb_cb *cb; unsigned char flags = 0; __u16 len = le16_to_cpu(*(__le16 *)skb->data); - struct dn_dev *dn = (struct dn_dev *)dev->dn_ptr; + struct dn_dev *dn = rcu_dereference(dev->dn_ptr); unsigned char padlen = 0; if (!net_eq(dev_net(dev), &init_net)) @@ -728,7 +740,7 @@ static int dn_forward(struct sk_buff *skb) { struct dn_skb_cb *cb = DN_SKB_CB(skb); struct dst_entry *dst = skb_dst(skb); - struct dn_dev *dn_db = dst->dev->dn_ptr; + struct dn_dev *dn_db = rcu_dereference(dst->dev->dn_ptr); struct dn_route *rt; struct neighbour *neigh = dst->neighbour; int header_len; @@ -788,19 +800,28 @@ static int dn_rt_bug(struct sk_buff *skb) return NET_RX_DROP; } +static unsigned int dn_dst_default_advmss(const struct dst_entry *dst) +{ + return dn_mss_from_pmtu(dst->dev, dst_mtu(dst)); +} + +static unsigned int dn_dst_default_mtu(const struct dst_entry *dst) +{ + return dst->dev->mtu; +} + static int dn_rt_set_next_hop(struct dn_route *rt, struct dn_fib_res *res) { struct dn_fib_info *fi = res->fi; struct net_device *dev = rt->dst.dev; struct neighbour *n; - unsigned mss; + unsigned int metric; if (fi) { if (DN_FIB_RES_GW(*res) && DN_FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK) rt->rt_gateway = DN_FIB_RES_GW(*res); - memcpy(rt->dst.metrics, fi->fib_metrics, - sizeof(rt->dst.metrics)); + dst_import_metrics(&rt->dst, fi->fib_metrics); } rt->rt_type = res->type; @@ -811,13 +832,14 @@ static int dn_rt_set_next_hop(struct dn_route *rt, struct dn_fib_res *res) rt->dst.neighbour = n; } - if (dst_metric(&rt->dst, RTAX_MTU) == 0 || - dst_metric(&rt->dst, RTAX_MTU) > rt->dst.dev->mtu) - rt->dst.metrics[RTAX_MTU-1] = rt->dst.dev->mtu; - mss = dn_mss_from_pmtu(dev, dst_mtu(&rt->dst)); - if (dst_metric(&rt->dst, RTAX_ADVMSS) == 0 || - dst_metric(&rt->dst, RTAX_ADVMSS) > mss) - rt->dst.metrics[RTAX_ADVMSS-1] = mss; + if (dst_metric(&rt->dst, RTAX_MTU) > rt->dst.dev->mtu) + dst_metric_set(&rt->dst, RTAX_MTU, rt->dst.dev->mtu); + metric = dst_metric_raw(&rt->dst, RTAX_ADVMSS); + if (metric) { + unsigned int mss = dn_mss_from_pmtu(dev, dst_mtu(&rt->dst)); + if (metric > mss) + dst_metric_set(&rt->dst, RTAX_ADVMSS, mss); + } return 0; } @@ -835,13 +857,16 @@ static inline int dn_match_addr(__le16 addr1, __le16 addr2) static __le16 dnet_select_source(const struct net_device *dev, __le16 daddr, int scope) { __le16 saddr = 0; - struct dn_dev *dn_db = dev->dn_ptr; + struct dn_dev *dn_db; struct dn_ifaddr *ifa; int best_match = 0; int ret; - read_lock(&dev_base_lock); - for(ifa = dn_db->ifa_list; ifa; ifa = ifa->ifa_next) { + rcu_read_lock(); + dn_db = rcu_dereference(dev->dn_ptr); + for (ifa = rcu_dereference(dn_db->ifa_list); + ifa != NULL; + ifa = rcu_dereference(ifa->ifa_next)) { if (ifa->ifa_scope > scope) continue; if (!daddr) { @@ -854,7 +879,7 @@ static __le16 dnet_select_source(const struct net_device *dev, __le16 daddr, int if (best_match == 0) saddr = ifa->ifa_local; } - read_unlock(&dev_base_lock); + rcu_read_unlock(); return saddr; } @@ -872,11 +897,9 @@ static inline __le16 dn_fib_rules_map_destination(__le16 daddr, struct dn_fib_re static int dn_route_output_slow(struct dst_entry **pprt, const struct flowi *oldflp, int try_hard) { - struct flowi fl = { .nl_u = { .dn_u = - { .daddr = oldflp->fld_dst, - .saddr = oldflp->fld_src, - .scope = RT_SCOPE_UNIVERSE, - } }, + struct flowi fl = { .fld_dst = oldflp->fld_dst, + .fld_src = oldflp->fld_src, + .fld_scope = RT_SCOPE_UNIVERSE, .mark = oldflp->mark, .iif = init_net.loopback_dev->ifindex, .oif = oldflp->oif }; @@ -1020,7 +1043,7 @@ source_ok: err = -ENODEV; if (dev_out == NULL) goto out; - dn_db = dev_out->dn_ptr; + dn_db = rcu_dereference_raw(dev_out->dn_ptr); /* Possible improvement - check all devices for local addr */ if (dn_dev_islocal(dev_out, fl.fld_dst)) { dev_put(dev_out); @@ -1171,7 +1194,7 @@ static int __dn_route_output_key(struct dst_entry **pprt, const struct flowi *fl if ((flp->fld_dst == rt->fl.fld_dst) && (flp->fld_src == rt->fl.fld_src) && (flp->mark == rt->fl.mark) && - (rt->fl.iif == 0) && + dn_is_output_route(rt) && (rt->fl.oif == flp->oif)) { dst_use(&rt->dst, jiffies); rcu_read_unlock_bh(); @@ -1220,11 +1243,9 @@ static int dn_route_input_slow(struct sk_buff *skb) int flags = 0; __le16 gateway = 0; __le16 local_src = 0; - struct flowi fl = { .nl_u = { .dn_u = - { .daddr = cb->dst, - .saddr = cb->src, - .scope = RT_SCOPE_UNIVERSE, - } }, + struct flowi fl = { .fld_dst = cb->dst, + .fld_src = cb->src, + .fld_scope = RT_SCOPE_UNIVERSE, .mark = skb->mark, .iif = skb->dev->ifindex }; struct dn_fib_res res = { .fi = NULL, .type = RTN_UNREACHABLE }; @@ -1233,7 +1254,7 @@ static int dn_route_input_slow(struct sk_buff *skb) dev_hold(in_dev); - if ((dn_db = in_dev->dn_ptr) == NULL) + if ((dn_db = rcu_dereference(in_dev->dn_ptr)) == NULL) goto out; /* Zero source addresses are not allowed */ @@ -1496,13 +1517,13 @@ static int dn_rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, RTA_PUT(skb, RTA_PREFSRC, 2, &rt->rt_local_src); if (rt->rt_daddr != rt->rt_gateway) RTA_PUT(skb, RTA_GATEWAY, 2, &rt->rt_gateway); - if (rtnetlink_put_metrics(skb, rt->dst.metrics) < 0) + if (rtnetlink_put_metrics(skb, dst_metrics_ptr(&rt->dst)) < 0) goto rtattr_failure; expires = rt->dst.expires ? rt->dst.expires - jiffies : 0; if (rtnl_put_cacheinfo(skb, &rt->dst, 0, 0, 0, expires, rt->dst.error) < 0) goto rtattr_failure; - if (rt->fl.iif) + if (dn_is_input_route(rt)) RTA_PUT(skb, RTA_IIF, sizeof(int), &rt->fl.iif); nlh->nlmsg_len = skb_tail_pointer(skb) - b; @@ -1677,15 +1698,15 @@ static struct dn_route *dn_rt_cache_get_next(struct seq_file *seq, struct dn_rou { struct dn_rt_cache_iter_state *s = seq->private; - rt = rt->dst.dn_next; - while(!rt) { + rt = rcu_dereference_bh(rt->dst.dn_next); + while (!rt) { rcu_read_unlock_bh(); if (--s->bucket < 0) break; rcu_read_lock_bh(); - rt = dn_rt_hash_table[s->bucket].chain; + rt = rcu_dereference_bh(dn_rt_hash_table[s->bucket].chain); } - return rcu_dereference_bh(rt); + return rt; } static void *dn_rt_cache_seq_start(struct seq_file *seq, loff_t *pos) diff --git a/net/decnet/dn_rules.c b/net/decnet/dn_rules.c index 48fdf10be7a..6eb91df3c55 100644 --- a/net/decnet/dn_rules.c +++ b/net/decnet/dn_rules.c @@ -175,7 +175,7 @@ static int dn_fib_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh, unsigned dnet_addr_type(__le16 addr) { - struct flowi fl = { .nl_u = { .dn_u = { .daddr = addr } } }; + struct flowi fl = { .fld_dst = addr }; struct dn_fib_res res; unsigned ret = RTN_UNICAST; struct dn_fib_table *tb = dn_fib_get_table(RT_TABLE_LOCAL, 0); |