diff options
author | David S. Miller <davem@davemloft.net> | 2015-04-02 16:16:53 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-04-02 16:16:53 -0400 |
commit | 9f0d34bc344889c2e6c593bd949d7ab821f0f4a5 (patch) | |
tree | e5bfc776a09315afa4dbcae97ac04f2cca239c96 /net | |
parent | e4a924f5768c55002c02ceba9b9f86824c35f956 (diff) | |
parent | 0a4812798fae4f6bfcaab51e31b3898ff5ea3108 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Conflicts:
drivers/net/usb/asix_common.c
drivers/net/usb/sr9800.c
drivers/net/usb/usbnet.c
include/linux/usb/usbnet.h
net/ipv4/tcp_ipv4.c
net/ipv6/tcp_ipv6.c
The TCP conflicts were overlapping changes. In 'net' we added a
READ_ONCE() to the socket cached RX route read, whilst in 'net-next'
Eric Dumazet touched the surrounding code dealing with how mini
sockets are handled.
With USB, it's a case of the same bug fix first going into net-next
and then I cherry picked it back into net.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/core/net_namespace.c | 24 | ||||
-rw-r--r-- | net/core/rtnetlink.c | 4 | ||||
-rw-r--r-- | net/ipv4/ipmr.c | 2 | ||||
-rw-r--r-- | net/ipv4/tcp_ipv4.c | 2 | ||||
-rw-r--r-- | net/ipv6/ip6mr.c | 2 | ||||
-rw-r--r-- | net/ipv6/ndisc.c | 9 | ||||
-rw-r--r-- | net/ipv6/tcp_ipv6.c | 13 | ||||
-rw-r--r-- | net/iucv/af_iucv.c | 4 | ||||
-rw-r--r-- | net/mac80211/agg-rx.c | 8 | ||||
-rw-r--r-- | net/mac80211/rx.c | 7 | ||||
-rw-r--r-- | net/mac80211/sta_info.h | 2 | ||||
-rw-r--r-- | net/openvswitch/vport.c | 4 | ||||
-rw-r--r-- | net/sunrpc/clnt.c | 4 | ||||
-rw-r--r-- | net/sunrpc/debugfs.c | 52 | ||||
-rw-r--r-- | net/sunrpc/sunrpc_syms.c | 7 | ||||
-rw-r--r-- | net/sunrpc/xprt.c | 7 | ||||
-rw-r--r-- | net/tipc/core.c | 2 |
17 files changed, 87 insertions, 66 deletions
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index e5e96b0f6717..ce6396a75b8b 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c | |||
@@ -338,7 +338,7 @@ static LIST_HEAD(cleanup_list); /* Must hold cleanup_list_lock to touch */ | |||
338 | static void cleanup_net(struct work_struct *work) | 338 | static void cleanup_net(struct work_struct *work) |
339 | { | 339 | { |
340 | const struct pernet_operations *ops; | 340 | const struct pernet_operations *ops; |
341 | struct net *net, *tmp; | 341 | struct net *net, *tmp, *peer; |
342 | struct list_head net_kill_list; | 342 | struct list_head net_kill_list; |
343 | LIST_HEAD(net_exit_list); | 343 | LIST_HEAD(net_exit_list); |
344 | 344 | ||
@@ -354,14 +354,6 @@ static void cleanup_net(struct work_struct *work) | |||
354 | list_for_each_entry(net, &net_kill_list, cleanup_list) { | 354 | list_for_each_entry(net, &net_kill_list, cleanup_list) { |
355 | list_del_rcu(&net->list); | 355 | list_del_rcu(&net->list); |
356 | list_add_tail(&net->exit_list, &net_exit_list); | 356 | list_add_tail(&net->exit_list, &net_exit_list); |
357 | for_each_net(tmp) { | ||
358 | int id = __peernet2id(tmp, net, false); | ||
359 | |||
360 | if (id >= 0) | ||
361 | idr_remove(&tmp->netns_ids, id); | ||
362 | } | ||
363 | idr_destroy(&net->netns_ids); | ||
364 | |||
365 | } | 357 | } |
366 | rtnl_unlock(); | 358 | rtnl_unlock(); |
367 | 359 | ||
@@ -387,12 +379,26 @@ static void cleanup_net(struct work_struct *work) | |||
387 | */ | 379 | */ |
388 | rcu_barrier(); | 380 | rcu_barrier(); |
389 | 381 | ||
382 | rtnl_lock(); | ||
390 | /* Finally it is safe to free my network namespace structure */ | 383 | /* Finally it is safe to free my network namespace structure */ |
391 | list_for_each_entry_safe(net, tmp, &net_exit_list, exit_list) { | 384 | list_for_each_entry_safe(net, tmp, &net_exit_list, exit_list) { |
385 | /* Unreference net from all peers (no need to loop over | ||
386 | * net_exit_list because idr_destroy() will be called for each | ||
387 | * element of this list. | ||
388 | */ | ||
389 | for_each_net(peer) { | ||
390 | int id = __peernet2id(peer, net, false); | ||
391 | |||
392 | if (id >= 0) | ||
393 | idr_remove(&peer->netns_ids, id); | ||
394 | } | ||
395 | idr_destroy(&net->netns_ids); | ||
396 | |||
392 | list_del_init(&net->exit_list); | 397 | list_del_init(&net->exit_list); |
393 | put_user_ns(net->user_ns); | 398 | put_user_ns(net->user_ns); |
394 | net_drop_ns(net); | 399 | net_drop_ns(net); |
395 | } | 400 | } |
401 | rtnl_unlock(); | ||
396 | } | 402 | } |
397 | static DECLARE_WORK(net_cleanup_work, cleanup_net); | 403 | static DECLARE_WORK(net_cleanup_work, cleanup_net); |
398 | 404 | ||
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index ee0186cdd5cf..5e02260b087f 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
@@ -1991,10 +1991,10 @@ static int rtnl_group_changelink(const struct sk_buff *skb, | |||
1991 | struct ifinfomsg *ifm, | 1991 | struct ifinfomsg *ifm, |
1992 | struct nlattr **tb) | 1992 | struct nlattr **tb) |
1993 | { | 1993 | { |
1994 | struct net_device *dev; | 1994 | struct net_device *dev, *aux; |
1995 | int err; | 1995 | int err; |
1996 | 1996 | ||
1997 | for_each_netdev(net, dev) { | 1997 | for_each_netdev_safe(net, dev, aux) { |
1998 | if (dev->group == group) { | 1998 | if (dev->group == group) { |
1999 | err = do_setlink(skb, dev, ifm, tb, NULL, 0); | 1999 | err = do_setlink(skb, dev, ifm, tb, NULL, 0); |
2000 | if (err < 0) | 2000 | if (err < 0) |
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index d2e3b3ef039e..3ef30cf57f4a 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c | |||
@@ -266,7 +266,7 @@ static int __net_init ipmr_rules_init(struct net *net) | |||
266 | return 0; | 266 | return 0; |
267 | 267 | ||
268 | err2: | 268 | err2: |
269 | kfree(mrt); | 269 | ipmr_free_table(mrt); |
270 | err1: | 270 | err1: |
271 | fib_rules_unregister(ops); | 271 | fib_rules_unregister(ops); |
272 | return err; | 272 | return err; |
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 5aababa20a21..69f9cf684744 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -1469,7 +1469,7 @@ void tcp_v4_early_demux(struct sk_buff *skb) | |||
1469 | skb->sk = sk; | 1469 | skb->sk = sk; |
1470 | skb->destructor = sock_edemux; | 1470 | skb->destructor = sock_edemux; |
1471 | if (sk_fullsock(sk)) { | 1471 | if (sk_fullsock(sk)) { |
1472 | struct dst_entry *dst = sk->sk_rx_dst; | 1472 | struct dst_entry *dst = READ_ONCE(sk->sk_rx_dst); |
1473 | 1473 | ||
1474 | if (dst) | 1474 | if (dst) |
1475 | dst = dst_check(dst, 0); | 1475 | dst = dst_check(dst, 0); |
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index 003431f5b4b6..26456037bdfc 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c | |||
@@ -250,7 +250,7 @@ static int __net_init ip6mr_rules_init(struct net *net) | |||
250 | return 0; | 250 | return 0; |
251 | 251 | ||
252 | err2: | 252 | err2: |
253 | kfree(mrt); | 253 | ip6mr_free_table(mrt); |
254 | err1: | 254 | err1: |
255 | fib_rules_unregister(ops); | 255 | fib_rules_unregister(ops); |
256 | return err; | 256 | return err; |
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index c283827d60e2..71fde6cafb35 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c | |||
@@ -1225,7 +1225,14 @@ static void ndisc_router_discovery(struct sk_buff *skb) | |||
1225 | if (rt) | 1225 | if (rt) |
1226 | rt6_set_expires(rt, jiffies + (HZ * lifetime)); | 1226 | rt6_set_expires(rt, jiffies + (HZ * lifetime)); |
1227 | if (ra_msg->icmph.icmp6_hop_limit) { | 1227 | if (ra_msg->icmph.icmp6_hop_limit) { |
1228 | in6_dev->cnf.hop_limit = ra_msg->icmph.icmp6_hop_limit; | 1228 | /* Only set hop_limit on the interface if it is higher than |
1229 | * the current hop_limit. | ||
1230 | */ | ||
1231 | if (in6_dev->cnf.hop_limit < ra_msg->icmph.icmp6_hop_limit) { | ||
1232 | in6_dev->cnf.hop_limit = ra_msg->icmph.icmp6_hop_limit; | ||
1233 | } else { | ||
1234 | ND_PRINTK(2, warn, "RA: Got route advertisement with lower hop_limit than current\n"); | ||
1235 | } | ||
1229 | if (rt) | 1236 | if (rt) |
1230 | dst_metric_set(&rt->dst, RTAX_HOPLIMIT, | 1237 | dst_metric_set(&rt->dst, RTAX_HOPLIMIT, |
1231 | ra_msg->icmph.icmp6_hop_limit); | 1238 | ra_msg->icmph.icmp6_hop_limit); |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 7cdad8401434..f73a97f6e68e 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -1348,6 +1348,15 @@ static void tcp_v6_fill_cb(struct sk_buff *skb, const struct ipv6hdr *hdr, | |||
1348 | TCP_SKB_CB(skb)->sacked = 0; | 1348 | TCP_SKB_CB(skb)->sacked = 0; |
1349 | } | 1349 | } |
1350 | 1350 | ||
1351 | static void tcp_v6_restore_cb(struct sk_buff *skb) | ||
1352 | { | ||
1353 | /* We need to move header back to the beginning if xfrm6_policy_check() | ||
1354 | * and tcp_v6_fill_cb() are going to be called again. | ||
1355 | */ | ||
1356 | memmove(IP6CB(skb), &TCP_SKB_CB(skb)->header.h6, | ||
1357 | sizeof(struct inet6_skb_parm)); | ||
1358 | } | ||
1359 | |||
1351 | static int tcp_v6_rcv(struct sk_buff *skb) | 1360 | static int tcp_v6_rcv(struct sk_buff *skb) |
1352 | { | 1361 | { |
1353 | const struct tcphdr *th; | 1362 | const struct tcphdr *th; |
@@ -1480,6 +1489,7 @@ do_time_wait: | |||
1480 | inet_twsk_deschedule(tw, &tcp_death_row); | 1489 | inet_twsk_deschedule(tw, &tcp_death_row); |
1481 | inet_twsk_put(tw); | 1490 | inet_twsk_put(tw); |
1482 | sk = sk2; | 1491 | sk = sk2; |
1492 | tcp_v6_restore_cb(skb); | ||
1483 | goto process; | 1493 | goto process; |
1484 | } | 1494 | } |
1485 | /* Fall through to ACK */ | 1495 | /* Fall through to ACK */ |
@@ -1488,6 +1498,7 @@ do_time_wait: | |||
1488 | tcp_v6_timewait_ack(sk, skb); | 1498 | tcp_v6_timewait_ack(sk, skb); |
1489 | break; | 1499 | break; |
1490 | case TCP_TW_RST: | 1500 | case TCP_TW_RST: |
1501 | tcp_v6_restore_cb(skb); | ||
1491 | goto no_tcp_socket; | 1502 | goto no_tcp_socket; |
1492 | case TCP_TW_SUCCESS: | 1503 | case TCP_TW_SUCCESS: |
1493 | ; | 1504 | ; |
@@ -1522,7 +1533,7 @@ static void tcp_v6_early_demux(struct sk_buff *skb) | |||
1522 | skb->sk = sk; | 1533 | skb->sk = sk; |
1523 | skb->destructor = sock_edemux; | 1534 | skb->destructor = sock_edemux; |
1524 | if (sk_fullsock(sk)) { | 1535 | if (sk_fullsock(sk)) { |
1525 | struct dst_entry *dst = sk->sk_rx_dst; | 1536 | struct dst_entry *dst = READ_ONCE(sk->sk_rx_dst); |
1526 | 1537 | ||
1527 | if (dst) | 1538 | if (dst) |
1528 | dst = dst_check(dst, inet6_sk(sk)->rx_dst_cookie); | 1539 | dst = dst_check(dst, inet6_sk(sk)->rx_dst_cookie); |
diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c index 94b4c898a116..6daa52a18d40 100644 --- a/net/iucv/af_iucv.c +++ b/net/iucv/af_iucv.c | |||
@@ -1114,10 +1114,8 @@ static int iucv_sock_sendmsg(struct socket *sock, struct msghdr *msg, | |||
1114 | noblock, &err); | 1114 | noblock, &err); |
1115 | else | 1115 | else |
1116 | skb = sock_alloc_send_skb(sk, len, noblock, &err); | 1116 | skb = sock_alloc_send_skb(sk, len, noblock, &err); |
1117 | if (!skb) { | 1117 | if (!skb) |
1118 | err = -ENOMEM; | ||
1119 | goto out; | 1118 | goto out; |
1120 | } | ||
1121 | if (iucv->transport == AF_IUCV_TRANS_HIPER) | 1119 | if (iucv->transport == AF_IUCV_TRANS_HIPER) |
1122 | skb_reserve(skb, sizeof(struct af_iucv_trans_hdr) + ETH_HLEN); | 1120 | skb_reserve(skb, sizeof(struct af_iucv_trans_hdr) + ETH_HLEN); |
1123 | if (memcpy_from_msg(skb_put(skb, len), msg, len)) { | 1121 | if (memcpy_from_msg(skb_put(skb, len), msg, len)) { |
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c index 2c090c507391..5c564a68fb50 100644 --- a/net/mac80211/agg-rx.c +++ b/net/mac80211/agg-rx.c | |||
@@ -49,8 +49,6 @@ static void ieee80211_free_tid_rx(struct rcu_head *h) | |||
49 | container_of(h, struct tid_ampdu_rx, rcu_head); | 49 | container_of(h, struct tid_ampdu_rx, rcu_head); |
50 | int i; | 50 | int i; |
51 | 51 | ||
52 | del_timer_sync(&tid_rx->reorder_timer); | ||
53 | |||
54 | for (i = 0; i < tid_rx->buf_size; i++) | 52 | for (i = 0; i < tid_rx->buf_size; i++) |
55 | __skb_queue_purge(&tid_rx->reorder_buf[i]); | 53 | __skb_queue_purge(&tid_rx->reorder_buf[i]); |
56 | kfree(tid_rx->reorder_buf); | 54 | kfree(tid_rx->reorder_buf); |
@@ -93,6 +91,12 @@ void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, | |||
93 | 91 | ||
94 | del_timer_sync(&tid_rx->session_timer); | 92 | del_timer_sync(&tid_rx->session_timer); |
95 | 93 | ||
94 | /* make sure ieee80211_sta_reorder_release() doesn't re-arm the timer */ | ||
95 | spin_lock_bh(&tid_rx->reorder_lock); | ||
96 | tid_rx->removed = true; | ||
97 | spin_unlock_bh(&tid_rx->reorder_lock); | ||
98 | del_timer_sync(&tid_rx->reorder_timer); | ||
99 | |||
96 | call_rcu(&tid_rx->rcu_head, ieee80211_free_tid_rx); | 100 | call_rcu(&tid_rx->rcu_head, ieee80211_free_tid_rx); |
97 | } | 101 | } |
98 | 102 | ||
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 4f7b922cfda4..2cd02278d4d4 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -873,9 +873,10 @@ static void ieee80211_sta_reorder_release(struct ieee80211_sub_if_data *sdata, | |||
873 | 873 | ||
874 | set_release_timer: | 874 | set_release_timer: |
875 | 875 | ||
876 | mod_timer(&tid_agg_rx->reorder_timer, | 876 | if (!tid_agg_rx->removed) |
877 | tid_agg_rx->reorder_time[j] + 1 + | 877 | mod_timer(&tid_agg_rx->reorder_timer, |
878 | HT_RX_REORDER_BUF_TIMEOUT); | 878 | tid_agg_rx->reorder_time[j] + 1 + |
879 | HT_RX_REORDER_BUF_TIMEOUT); | ||
879 | } else { | 880 | } else { |
880 | del_timer(&tid_agg_rx->reorder_timer); | 881 | del_timer(&tid_agg_rx->reorder_timer); |
881 | } | 882 | } |
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 248f56e59ebc..7e2fa4018d41 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -175,6 +175,7 @@ struct tid_ampdu_tx { | |||
175 | * @reorder_lock: serializes access to reorder buffer, see below. | 175 | * @reorder_lock: serializes access to reorder buffer, see below. |
176 | * @auto_seq: used for offloaded BA sessions to automatically pick head_seq_and | 176 | * @auto_seq: used for offloaded BA sessions to automatically pick head_seq_and |
177 | * and ssn. | 177 | * and ssn. |
178 | * @removed: this session is removed (but might have been found due to RCU) | ||
178 | * | 179 | * |
179 | * This structure's lifetime is managed by RCU, assignments to | 180 | * This structure's lifetime is managed by RCU, assignments to |
180 | * the array holding it must hold the aggregation mutex. | 181 | * the array holding it must hold the aggregation mutex. |
@@ -199,6 +200,7 @@ struct tid_ampdu_rx { | |||
199 | u16 timeout; | 200 | u16 timeout; |
200 | u8 dialog_token; | 201 | u8 dialog_token; |
201 | bool auto_seq; | 202 | bool auto_seq; |
203 | bool removed; | ||
202 | }; | 204 | }; |
203 | 205 | ||
204 | /** | 206 | /** |
diff --git a/net/openvswitch/vport.c b/net/openvswitch/vport.c index ec2954ffc690..067a3fff1d2c 100644 --- a/net/openvswitch/vport.c +++ b/net/openvswitch/vport.c | |||
@@ -274,10 +274,8 @@ void ovs_vport_del(struct vport *vport) | |||
274 | ASSERT_OVSL(); | 274 | ASSERT_OVSL(); |
275 | 275 | ||
276 | hlist_del_rcu(&vport->hash_node); | 276 | hlist_del_rcu(&vport->hash_node); |
277 | |||
278 | vport->ops->destroy(vport); | ||
279 | |||
280 | module_put(vport->ops->owner); | 277 | module_put(vport->ops->owner); |
278 | vport->ops->destroy(vport); | ||
281 | } | 279 | } |
282 | 280 | ||
283 | /** | 281 | /** |
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 612aa73bbc60..e6ce1517367f 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
@@ -303,9 +303,7 @@ static int rpc_client_register(struct rpc_clnt *clnt, | |||
303 | struct super_block *pipefs_sb; | 303 | struct super_block *pipefs_sb; |
304 | int err; | 304 | int err; |
305 | 305 | ||
306 | err = rpc_clnt_debugfs_register(clnt); | 306 | rpc_clnt_debugfs_register(clnt); |
307 | if (err) | ||
308 | return err; | ||
309 | 307 | ||
310 | pipefs_sb = rpc_get_sb_net(net); | 308 | pipefs_sb = rpc_get_sb_net(net); |
311 | if (pipefs_sb) { | 309 | if (pipefs_sb) { |
diff --git a/net/sunrpc/debugfs.c b/net/sunrpc/debugfs.c index e811f390f9f6..82962f7e6e88 100644 --- a/net/sunrpc/debugfs.c +++ b/net/sunrpc/debugfs.c | |||
@@ -129,48 +129,52 @@ static const struct file_operations tasks_fops = { | |||
129 | .release = tasks_release, | 129 | .release = tasks_release, |
130 | }; | 130 | }; |
131 | 131 | ||
132 | int | 132 | void |
133 | rpc_clnt_debugfs_register(struct rpc_clnt *clnt) | 133 | rpc_clnt_debugfs_register(struct rpc_clnt *clnt) |
134 | { | 134 | { |
135 | int len, err; | 135 | int len; |
136 | char name[24]; /* enough for "../../rpc_xprt/ + 8 hex digits + NULL */ | 136 | char name[24]; /* enough for "../../rpc_xprt/ + 8 hex digits + NULL */ |
137 | struct rpc_xprt *xprt; | ||
137 | 138 | ||
138 | /* Already registered? */ | 139 | /* Already registered? */ |
139 | if (clnt->cl_debugfs) | 140 | if (clnt->cl_debugfs || !rpc_clnt_dir) |
140 | return 0; | 141 | return; |
141 | 142 | ||
142 | len = snprintf(name, sizeof(name), "%x", clnt->cl_clid); | 143 | len = snprintf(name, sizeof(name), "%x", clnt->cl_clid); |
143 | if (len >= sizeof(name)) | 144 | if (len >= sizeof(name)) |
144 | return -EINVAL; | 145 | return; |
145 | 146 | ||
146 | /* make the per-client dir */ | 147 | /* make the per-client dir */ |
147 | clnt->cl_debugfs = debugfs_create_dir(name, rpc_clnt_dir); | 148 | clnt->cl_debugfs = debugfs_create_dir(name, rpc_clnt_dir); |
148 | if (!clnt->cl_debugfs) | 149 | if (!clnt->cl_debugfs) |
149 | return -ENOMEM; | 150 | return; |
150 | 151 | ||
151 | /* make tasks file */ | 152 | /* make tasks file */ |
152 | err = -ENOMEM; | ||
153 | if (!debugfs_create_file("tasks", S_IFREG | S_IRUSR, clnt->cl_debugfs, | 153 | if (!debugfs_create_file("tasks", S_IFREG | S_IRUSR, clnt->cl_debugfs, |
154 | clnt, &tasks_fops)) | 154 | clnt, &tasks_fops)) |
155 | goto out_err; | 155 | goto out_err; |
156 | 156 | ||
157 | err = -EINVAL; | ||
158 | rcu_read_lock(); | 157 | rcu_read_lock(); |
158 | xprt = rcu_dereference(clnt->cl_xprt); | ||
159 | /* no "debugfs" dentry? Don't bother with the symlink. */ | ||
160 | if (!xprt->debugfs) { | ||
161 | rcu_read_unlock(); | ||
162 | return; | ||
163 | } | ||
159 | len = snprintf(name, sizeof(name), "../../rpc_xprt/%s", | 164 | len = snprintf(name, sizeof(name), "../../rpc_xprt/%s", |
160 | rcu_dereference(clnt->cl_xprt)->debugfs->d_name.name); | 165 | xprt->debugfs->d_name.name); |
161 | rcu_read_unlock(); | 166 | rcu_read_unlock(); |
167 | |||
162 | if (len >= sizeof(name)) | 168 | if (len >= sizeof(name)) |
163 | goto out_err; | 169 | goto out_err; |
164 | 170 | ||
165 | err = -ENOMEM; | ||
166 | if (!debugfs_create_symlink("xprt", clnt->cl_debugfs, name)) | 171 | if (!debugfs_create_symlink("xprt", clnt->cl_debugfs, name)) |
167 | goto out_err; | 172 | goto out_err; |
168 | 173 | ||
169 | return 0; | 174 | return; |
170 | out_err: | 175 | out_err: |
171 | debugfs_remove_recursive(clnt->cl_debugfs); | 176 | debugfs_remove_recursive(clnt->cl_debugfs); |
172 | clnt->cl_debugfs = NULL; | 177 | clnt->cl_debugfs = NULL; |
173 | return err; | ||
174 | } | 178 | } |
175 | 179 | ||
176 | void | 180 | void |
@@ -226,33 +230,33 @@ static const struct file_operations xprt_info_fops = { | |||
226 | .release = xprt_info_release, | 230 | .release = xprt_info_release, |
227 | }; | 231 | }; |
228 | 232 | ||
229 | int | 233 | void |
230 | rpc_xprt_debugfs_register(struct rpc_xprt *xprt) | 234 | rpc_xprt_debugfs_register(struct rpc_xprt *xprt) |
231 | { | 235 | { |
232 | int len, id; | 236 | int len, id; |
233 | static atomic_t cur_id; | 237 | static atomic_t cur_id; |
234 | char name[9]; /* 8 hex digits + NULL term */ | 238 | char name[9]; /* 8 hex digits + NULL term */ |
235 | 239 | ||
240 | if (!rpc_xprt_dir) | ||
241 | return; | ||
242 | |||
236 | id = (unsigned int)atomic_inc_return(&cur_id); | 243 | id = (unsigned int)atomic_inc_return(&cur_id); |
237 | 244 | ||
238 | len = snprintf(name, sizeof(name), "%x", id); | 245 | len = snprintf(name, sizeof(name), "%x", id); |
239 | if (len >= sizeof(name)) | 246 | if (len >= sizeof(name)) |
240 | return -EINVAL; | 247 | return; |
241 | 248 | ||
242 | /* make the per-client dir */ | 249 | /* make the per-client dir */ |
243 | xprt->debugfs = debugfs_create_dir(name, rpc_xprt_dir); | 250 | xprt->debugfs = debugfs_create_dir(name, rpc_xprt_dir); |
244 | if (!xprt->debugfs) | 251 | if (!xprt->debugfs) |
245 | return -ENOMEM; | 252 | return; |
246 | 253 | ||
247 | /* make tasks file */ | 254 | /* make tasks file */ |
248 | if (!debugfs_create_file("info", S_IFREG | S_IRUSR, xprt->debugfs, | 255 | if (!debugfs_create_file("info", S_IFREG | S_IRUSR, xprt->debugfs, |
249 | xprt, &xprt_info_fops)) { | 256 | xprt, &xprt_info_fops)) { |
250 | debugfs_remove_recursive(xprt->debugfs); | 257 | debugfs_remove_recursive(xprt->debugfs); |
251 | xprt->debugfs = NULL; | 258 | xprt->debugfs = NULL; |
252 | return -ENOMEM; | ||
253 | } | 259 | } |
254 | |||
255 | return 0; | ||
256 | } | 260 | } |
257 | 261 | ||
258 | void | 262 | void |
@@ -266,14 +270,17 @@ void __exit | |||
266 | sunrpc_debugfs_exit(void) | 270 | sunrpc_debugfs_exit(void) |
267 | { | 271 | { |
268 | debugfs_remove_recursive(topdir); | 272 | debugfs_remove_recursive(topdir); |
273 | topdir = NULL; | ||
274 | rpc_clnt_dir = NULL; | ||
275 | rpc_xprt_dir = NULL; | ||
269 | } | 276 | } |
270 | 277 | ||
271 | int __init | 278 | void __init |
272 | sunrpc_debugfs_init(void) | 279 | sunrpc_debugfs_init(void) |
273 | { | 280 | { |
274 | topdir = debugfs_create_dir("sunrpc", NULL); | 281 | topdir = debugfs_create_dir("sunrpc", NULL); |
275 | if (!topdir) | 282 | if (!topdir) |
276 | goto out; | 283 | return; |
277 | 284 | ||
278 | rpc_clnt_dir = debugfs_create_dir("rpc_clnt", topdir); | 285 | rpc_clnt_dir = debugfs_create_dir("rpc_clnt", topdir); |
279 | if (!rpc_clnt_dir) | 286 | if (!rpc_clnt_dir) |
@@ -283,10 +290,9 @@ sunrpc_debugfs_init(void) | |||
283 | if (!rpc_xprt_dir) | 290 | if (!rpc_xprt_dir) |
284 | goto out_remove; | 291 | goto out_remove; |
285 | 292 | ||
286 | return 0; | 293 | return; |
287 | out_remove: | 294 | out_remove: |
288 | debugfs_remove_recursive(topdir); | 295 | debugfs_remove_recursive(topdir); |
289 | topdir = NULL; | 296 | topdir = NULL; |
290 | out: | 297 | rpc_clnt_dir = NULL; |
291 | return -ENOMEM; | ||
292 | } | 298 | } |
diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c index e37fbed87956..ee5d3d253102 100644 --- a/net/sunrpc/sunrpc_syms.c +++ b/net/sunrpc/sunrpc_syms.c | |||
@@ -98,10 +98,7 @@ init_sunrpc(void) | |||
98 | if (err) | 98 | if (err) |
99 | goto out4; | 99 | goto out4; |
100 | 100 | ||
101 | err = sunrpc_debugfs_init(); | 101 | sunrpc_debugfs_init(); |
102 | if (err) | ||
103 | goto out5; | ||
104 | |||
105 | #if IS_ENABLED(CONFIG_SUNRPC_DEBUG) | 102 | #if IS_ENABLED(CONFIG_SUNRPC_DEBUG) |
106 | rpc_register_sysctl(); | 103 | rpc_register_sysctl(); |
107 | #endif | 104 | #endif |
@@ -109,8 +106,6 @@ init_sunrpc(void) | |||
109 | init_socket_xprt(); /* clnt sock transport */ | 106 | init_socket_xprt(); /* clnt sock transport */ |
110 | return 0; | 107 | return 0; |
111 | 108 | ||
112 | out5: | ||
113 | unregister_rpc_pipefs(); | ||
114 | out4: | 109 | out4: |
115 | unregister_pernet_subsys(&sunrpc_net_ops); | 110 | unregister_pernet_subsys(&sunrpc_net_ops); |
116 | out3: | 111 | out3: |
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index e3015aede0d9..9949722d99ce 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c | |||
@@ -1331,7 +1331,6 @@ static void xprt_init(struct rpc_xprt *xprt, struct net *net) | |||
1331 | */ | 1331 | */ |
1332 | struct rpc_xprt *xprt_create_transport(struct xprt_create *args) | 1332 | struct rpc_xprt *xprt_create_transport(struct xprt_create *args) |
1333 | { | 1333 | { |
1334 | int err; | ||
1335 | struct rpc_xprt *xprt; | 1334 | struct rpc_xprt *xprt; |
1336 | struct xprt_class *t; | 1335 | struct xprt_class *t; |
1337 | 1336 | ||
@@ -1372,11 +1371,7 @@ found: | |||
1372 | return ERR_PTR(-ENOMEM); | 1371 | return ERR_PTR(-ENOMEM); |
1373 | } | 1372 | } |
1374 | 1373 | ||
1375 | err = rpc_xprt_debugfs_register(xprt); | 1374 | rpc_xprt_debugfs_register(xprt); |
1376 | if (err) { | ||
1377 | xprt_destroy(xprt); | ||
1378 | return ERR_PTR(err); | ||
1379 | } | ||
1380 | 1375 | ||
1381 | dprintk("RPC: created transport %p with %u slots\n", xprt, | 1376 | dprintk("RPC: created transport %p with %u slots\n", xprt, |
1382 | xprt->max_reqs); | 1377 | xprt->max_reqs); |
diff --git a/net/tipc/core.c b/net/tipc/core.c index 935205e6bcfe..be1c9fa60b09 100644 --- a/net/tipc/core.c +++ b/net/tipc/core.c | |||
@@ -152,11 +152,11 @@ out_netlink: | |||
152 | static void __exit tipc_exit(void) | 152 | static void __exit tipc_exit(void) |
153 | { | 153 | { |
154 | tipc_bearer_cleanup(); | 154 | tipc_bearer_cleanup(); |
155 | unregister_pernet_subsys(&tipc_net_ops); | ||
155 | tipc_netlink_stop(); | 156 | tipc_netlink_stop(); |
156 | tipc_netlink_compat_stop(); | 157 | tipc_netlink_compat_stop(); |
157 | tipc_socket_stop(); | 158 | tipc_socket_stop(); |
158 | tipc_unregister_sysctl(); | 159 | tipc_unregister_sysctl(); |
159 | unregister_pernet_subsys(&tipc_net_ops); | ||
160 | 160 | ||
161 | pr_info("Deactivated\n"); | 161 | pr_info("Deactivated\n"); |
162 | } | 162 | } |