diff options
Diffstat (limited to 'net')
131 files changed, 2288 insertions, 1274 deletions
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index 453512266ea1..c39a5f41169c 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c | |||
@@ -530,6 +530,10 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event, | |||
530 | } | 530 | } |
531 | unregister_netdevice_many(&list); | 531 | unregister_netdevice_many(&list); |
532 | break; | 532 | break; |
533 | |||
534 | case NETDEV_PRE_TYPE_CHANGE: | ||
535 | /* Forbid underlaying device to change its type. */ | ||
536 | return NOTIFY_BAD; | ||
533 | } | 537 | } |
534 | 538 | ||
535 | out: | 539 | out: |
diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c index c0316e0ca6e8..c584a0af77d3 100644 --- a/net/8021q/vlan_core.c +++ b/net/8021q/vlan_core.c | |||
@@ -11,7 +11,7 @@ int __vlan_hwaccel_rx(struct sk_buff *skb, struct vlan_group *grp, | |||
11 | if (netpoll_rx(skb)) | 11 | if (netpoll_rx(skb)) |
12 | return NET_RX_DROP; | 12 | return NET_RX_DROP; |
13 | 13 | ||
14 | if (skb_bond_should_drop(skb)) | 14 | if (skb_bond_should_drop(skb, ACCESS_ONCE(skb->dev->master))) |
15 | goto drop; | 15 | goto drop; |
16 | 16 | ||
17 | skb->skb_iif = skb->dev->ifindex; | 17 | skb->skb_iif = skb->dev->ifindex; |
@@ -83,7 +83,7 @@ vlan_gro_common(struct napi_struct *napi, struct vlan_group *grp, | |||
83 | { | 83 | { |
84 | struct sk_buff *p; | 84 | struct sk_buff *p; |
85 | 85 | ||
86 | if (skb_bond_should_drop(skb)) | 86 | if (skb_bond_should_drop(skb, ACCESS_ONCE(skb->dev->master))) |
87 | goto drop; | 87 | goto drop; |
88 | 88 | ||
89 | skb->skb_iif = skb->dev->ifindex; | 89 | skb->skb_iif = skb->dev->ifindex; |
diff --git a/net/9p/client.c b/net/9p/client.c index 09d4f1e2e4a8..e3e5bf4469ce 100644 --- a/net/9p/client.c +++ b/net/9p/client.c | |||
@@ -46,6 +46,7 @@ enum { | |||
46 | Opt_msize, | 46 | Opt_msize, |
47 | Opt_trans, | 47 | Opt_trans, |
48 | Opt_legacy, | 48 | Opt_legacy, |
49 | Opt_version, | ||
49 | Opt_err, | 50 | Opt_err, |
50 | }; | 51 | }; |
51 | 52 | ||
@@ -53,9 +54,42 @@ static const match_table_t tokens = { | |||
53 | {Opt_msize, "msize=%u"}, | 54 | {Opt_msize, "msize=%u"}, |
54 | {Opt_legacy, "noextend"}, | 55 | {Opt_legacy, "noextend"}, |
55 | {Opt_trans, "trans=%s"}, | 56 | {Opt_trans, "trans=%s"}, |
57 | {Opt_version, "version=%s"}, | ||
56 | {Opt_err, NULL}, | 58 | {Opt_err, NULL}, |
57 | }; | 59 | }; |
58 | 60 | ||
61 | inline int p9_is_proto_dotl(struct p9_client *clnt) | ||
62 | { | ||
63 | return (clnt->proto_version == p9_proto_2000L); | ||
64 | } | ||
65 | EXPORT_SYMBOL(p9_is_proto_dotl); | ||
66 | |||
67 | inline int p9_is_proto_dotu(struct p9_client *clnt) | ||
68 | { | ||
69 | return (clnt->proto_version == p9_proto_2000u); | ||
70 | } | ||
71 | EXPORT_SYMBOL(p9_is_proto_dotu); | ||
72 | |||
73 | /* Interpret mount option for protocol version */ | ||
74 | static unsigned char get_protocol_version(const substring_t *name) | ||
75 | { | ||
76 | unsigned char version = -EINVAL; | ||
77 | if (!strncmp("9p2000", name->from, name->to-name->from)) { | ||
78 | version = p9_proto_legacy; | ||
79 | P9_DPRINTK(P9_DEBUG_9P, "Protocol version: Legacy\n"); | ||
80 | } else if (!strncmp("9p2000.u", name->from, name->to-name->from)) { | ||
81 | version = p9_proto_2000u; | ||
82 | P9_DPRINTK(P9_DEBUG_9P, "Protocol version: 9P2000.u\n"); | ||
83 | } else if (!strncmp("9p2000.L", name->from, name->to-name->from)) { | ||
84 | version = p9_proto_2000L; | ||
85 | P9_DPRINTK(P9_DEBUG_9P, "Protocol version: 9P2000.L\n"); | ||
86 | } else { | ||
87 | P9_DPRINTK(P9_DEBUG_ERROR, "Unknown protocol version %s. ", | ||
88 | name->from); | ||
89 | } | ||
90 | return version; | ||
91 | } | ||
92 | |||
59 | static struct p9_req_t * | 93 | static struct p9_req_t * |
60 | p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...); | 94 | p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...); |
61 | 95 | ||
@@ -75,7 +109,7 @@ static int parse_opts(char *opts, struct p9_client *clnt) | |||
75 | int option; | 109 | int option; |
76 | int ret = 0; | 110 | int ret = 0; |
77 | 111 | ||
78 | clnt->dotu = 1; | 112 | clnt->proto_version = p9_proto_2000u; |
79 | clnt->msize = 8192; | 113 | clnt->msize = 8192; |
80 | 114 | ||
81 | if (!opts) | 115 | if (!opts) |
@@ -118,7 +152,13 @@ static int parse_opts(char *opts, struct p9_client *clnt) | |||
118 | } | 152 | } |
119 | break; | 153 | break; |
120 | case Opt_legacy: | 154 | case Opt_legacy: |
121 | clnt->dotu = 0; | 155 | clnt->proto_version = p9_proto_legacy; |
156 | break; | ||
157 | case Opt_version: | ||
158 | ret = get_protocol_version(&args[0]); | ||
159 | if (ret == -EINVAL) | ||
160 | goto free_and_return; | ||
161 | clnt->proto_version = ret; | ||
122 | break; | 162 | break; |
123 | default: | 163 | default: |
124 | continue; | 164 | continue; |
@@ -410,14 +450,15 @@ static int p9_check_errors(struct p9_client *c, struct p9_req_t *req) | |||
410 | int ecode; | 450 | int ecode; |
411 | char *ename; | 451 | char *ename; |
412 | 452 | ||
413 | err = p9pdu_readf(req->rc, c->dotu, "s?d", &ename, &ecode); | 453 | err = p9pdu_readf(req->rc, c->proto_version, "s?d", |
454 | &ename, &ecode); | ||
414 | if (err) { | 455 | if (err) { |
415 | P9_DPRINTK(P9_DEBUG_ERROR, "couldn't parse error%d\n", | 456 | P9_DPRINTK(P9_DEBUG_ERROR, "couldn't parse error%d\n", |
416 | err); | 457 | err); |
417 | return err; | 458 | return err; |
418 | } | 459 | } |
419 | 460 | ||
420 | if (c->dotu) | 461 | if (p9_is_proto_dotu(c)) |
421 | err = -ecode; | 462 | err = -ecode; |
422 | 463 | ||
423 | if (!err || !IS_ERR_VALUE(err)) | 464 | if (!err || !IS_ERR_VALUE(err)) |
@@ -515,7 +556,7 @@ p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...) | |||
515 | /* marshall the data */ | 556 | /* marshall the data */ |
516 | p9pdu_prepare(req->tc, tag, type); | 557 | p9pdu_prepare(req->tc, tag, type); |
517 | va_start(ap, fmt); | 558 | va_start(ap, fmt); |
518 | err = p9pdu_vwritef(req->tc, c->dotu, fmt, ap); | 559 | err = p9pdu_vwritef(req->tc, c->proto_version, fmt, ap); |
519 | va_end(ap); | 560 | va_end(ap); |
520 | p9pdu_finalize(req->tc); | 561 | p9pdu_finalize(req->tc); |
521 | 562 | ||
@@ -627,14 +668,31 @@ int p9_client_version(struct p9_client *c) | |||
627 | char *version; | 668 | char *version; |
628 | int msize; | 669 | int msize; |
629 | 670 | ||
630 | P9_DPRINTK(P9_DEBUG_9P, ">>> TVERSION msize %d extended %d\n", | 671 | P9_DPRINTK(P9_DEBUG_9P, ">>> TVERSION msize %d protocol %d\n", |
631 | c->msize, c->dotu); | 672 | c->msize, c->proto_version); |
632 | req = p9_client_rpc(c, P9_TVERSION, "ds", c->msize, | 673 | |
633 | c->dotu ? "9P2000.u" : "9P2000"); | 674 | switch (c->proto_version) { |
675 | case p9_proto_2000L: | ||
676 | req = p9_client_rpc(c, P9_TVERSION, "ds", | ||
677 | c->msize, "9P2000.L"); | ||
678 | break; | ||
679 | case p9_proto_2000u: | ||
680 | req = p9_client_rpc(c, P9_TVERSION, "ds", | ||
681 | c->msize, "9P2000.u"); | ||
682 | break; | ||
683 | case p9_proto_legacy: | ||
684 | req = p9_client_rpc(c, P9_TVERSION, "ds", | ||
685 | c->msize, "9P2000"); | ||
686 | break; | ||
687 | default: | ||
688 | return -EINVAL; | ||
689 | break; | ||
690 | } | ||
691 | |||
634 | if (IS_ERR(req)) | 692 | if (IS_ERR(req)) |
635 | return PTR_ERR(req); | 693 | return PTR_ERR(req); |
636 | 694 | ||
637 | err = p9pdu_readf(req->rc, c->dotu, "ds", &msize, &version); | 695 | err = p9pdu_readf(req->rc, c->proto_version, "ds", &msize, &version); |
638 | if (err) { | 696 | if (err) { |
639 | P9_DPRINTK(P9_DEBUG_9P, "version error %d\n", err); | 697 | P9_DPRINTK(P9_DEBUG_9P, "version error %d\n", err); |
640 | p9pdu_dump(1, req->rc); | 698 | p9pdu_dump(1, req->rc); |
@@ -642,10 +700,12 @@ int p9_client_version(struct p9_client *c) | |||
642 | } | 700 | } |
643 | 701 | ||
644 | P9_DPRINTK(P9_DEBUG_9P, "<<< RVERSION msize %d %s\n", msize, version); | 702 | P9_DPRINTK(P9_DEBUG_9P, "<<< RVERSION msize %d %s\n", msize, version); |
645 | if (!memcmp(version, "9P2000.u", 8)) | 703 | if (!strncmp(version, "9P2000.L", 8)) |
646 | c->dotu = 1; | 704 | c->proto_version = p9_proto_2000L; |
647 | else if (!memcmp(version, "9P2000", 6)) | 705 | else if (!strncmp(version, "9P2000.u", 8)) |
648 | c->dotu = 0; | 706 | c->proto_version = p9_proto_2000u; |
707 | else if (!strncmp(version, "9P2000", 6)) | ||
708 | c->proto_version = p9_proto_legacy; | ||
649 | else { | 709 | else { |
650 | err = -EREMOTEIO; | 710 | err = -EREMOTEIO; |
651 | goto error; | 711 | goto error; |
@@ -700,8 +760,8 @@ struct p9_client *p9_client_create(const char *dev_name, char *options) | |||
700 | goto put_trans; | 760 | goto put_trans; |
701 | } | 761 | } |
702 | 762 | ||
703 | P9_DPRINTK(P9_DEBUG_MUX, "clnt %p trans %p msize %d dotu %d\n", | 763 | P9_DPRINTK(P9_DEBUG_MUX, "clnt %p trans %p msize %d protocol %d\n", |
704 | clnt, clnt->trans_mod, clnt->msize, clnt->dotu); | 764 | clnt, clnt->trans_mod, clnt->msize, clnt->proto_version); |
705 | 765 | ||
706 | err = clnt->trans_mod->create(clnt, dev_name, options); | 766 | err = clnt->trans_mod->create(clnt, dev_name, options); |
707 | if (err) | 767 | if (err) |
@@ -784,7 +844,7 @@ struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid, | |||
784 | goto error; | 844 | goto error; |
785 | } | 845 | } |
786 | 846 | ||
787 | err = p9pdu_readf(req->rc, clnt->dotu, "Q", &qid); | 847 | err = p9pdu_readf(req->rc, clnt->proto_version, "Q", &qid); |
788 | if (err) { | 848 | if (err) { |
789 | p9pdu_dump(1, req->rc); | 849 | p9pdu_dump(1, req->rc); |
790 | p9_free_req(clnt, req); | 850 | p9_free_req(clnt, req); |
@@ -833,7 +893,7 @@ p9_client_auth(struct p9_client *clnt, char *uname, u32 n_uname, char *aname) | |||
833 | goto error; | 893 | goto error; |
834 | } | 894 | } |
835 | 895 | ||
836 | err = p9pdu_readf(req->rc, clnt->dotu, "Q", &qid); | 896 | err = p9pdu_readf(req->rc, clnt->proto_version, "Q", &qid); |
837 | if (err) { | 897 | if (err) { |
838 | p9pdu_dump(1, req->rc); | 898 | p9pdu_dump(1, req->rc); |
839 | p9_free_req(clnt, req); | 899 | p9_free_req(clnt, req); |
@@ -891,7 +951,7 @@ struct p9_fid *p9_client_walk(struct p9_fid *oldfid, int nwname, char **wnames, | |||
891 | goto error; | 951 | goto error; |
892 | } | 952 | } |
893 | 953 | ||
894 | err = p9pdu_readf(req->rc, clnt->dotu, "R", &nwqids, &wqids); | 954 | err = p9pdu_readf(req->rc, clnt->proto_version, "R", &nwqids, &wqids); |
895 | if (err) { | 955 | if (err) { |
896 | p9pdu_dump(1, req->rc); | 956 | p9pdu_dump(1, req->rc); |
897 | p9_free_req(clnt, req); | 957 | p9_free_req(clnt, req); |
@@ -952,7 +1012,7 @@ int p9_client_open(struct p9_fid *fid, int mode) | |||
952 | goto error; | 1012 | goto error; |
953 | } | 1013 | } |
954 | 1014 | ||
955 | err = p9pdu_readf(req->rc, clnt->dotu, "Qd", &qid, &iounit); | 1015 | err = p9pdu_readf(req->rc, clnt->proto_version, "Qd", &qid, &iounit); |
956 | if (err) { | 1016 | if (err) { |
957 | p9pdu_dump(1, req->rc); | 1017 | p9pdu_dump(1, req->rc); |
958 | goto free_and_error; | 1018 | goto free_and_error; |
@@ -997,7 +1057,7 @@ int p9_client_fcreate(struct p9_fid *fid, char *name, u32 perm, int mode, | |||
997 | goto error; | 1057 | goto error; |
998 | } | 1058 | } |
999 | 1059 | ||
1000 | err = p9pdu_readf(req->rc, clnt->dotu, "Qd", &qid, &iounit); | 1060 | err = p9pdu_readf(req->rc, clnt->proto_version, "Qd", &qid, &iounit); |
1001 | if (err) { | 1061 | if (err) { |
1002 | p9pdu_dump(1, req->rc); | 1062 | p9pdu_dump(1, req->rc); |
1003 | goto free_and_error; | 1063 | goto free_and_error; |
@@ -1098,7 +1158,7 @@ p9_client_read(struct p9_fid *fid, char *data, char __user *udata, u64 offset, | |||
1098 | goto error; | 1158 | goto error; |
1099 | } | 1159 | } |
1100 | 1160 | ||
1101 | err = p9pdu_readf(req->rc, clnt->dotu, "D", &count, &dataptr); | 1161 | err = p9pdu_readf(req->rc, clnt->proto_version, "D", &count, &dataptr); |
1102 | if (err) { | 1162 | if (err) { |
1103 | p9pdu_dump(1, req->rc); | 1163 | p9pdu_dump(1, req->rc); |
1104 | goto free_and_error; | 1164 | goto free_and_error; |
@@ -1159,7 +1219,7 @@ p9_client_write(struct p9_fid *fid, char *data, const char __user *udata, | |||
1159 | goto error; | 1219 | goto error; |
1160 | } | 1220 | } |
1161 | 1221 | ||
1162 | err = p9pdu_readf(req->rc, clnt->dotu, "d", &count); | 1222 | err = p9pdu_readf(req->rc, clnt->proto_version, "d", &count); |
1163 | if (err) { | 1223 | if (err) { |
1164 | p9pdu_dump(1, req->rc); | 1224 | p9pdu_dump(1, req->rc); |
1165 | goto free_and_error; | 1225 | goto free_and_error; |
@@ -1199,7 +1259,7 @@ struct p9_wstat *p9_client_stat(struct p9_fid *fid) | |||
1199 | goto error; | 1259 | goto error; |
1200 | } | 1260 | } |
1201 | 1261 | ||
1202 | err = p9pdu_readf(req->rc, clnt->dotu, "wS", &ignored, ret); | 1262 | err = p9pdu_readf(req->rc, clnt->proto_version, "wS", &ignored, ret); |
1203 | if (err) { | 1263 | if (err) { |
1204 | p9pdu_dump(1, req->rc); | 1264 | p9pdu_dump(1, req->rc); |
1205 | p9_free_req(clnt, req); | 1265 | p9_free_req(clnt, req); |
@@ -1226,7 +1286,7 @@ error: | |||
1226 | } | 1286 | } |
1227 | EXPORT_SYMBOL(p9_client_stat); | 1287 | EXPORT_SYMBOL(p9_client_stat); |
1228 | 1288 | ||
1229 | static int p9_client_statsize(struct p9_wstat *wst, int optional) | 1289 | static int p9_client_statsize(struct p9_wstat *wst, int proto_version) |
1230 | { | 1290 | { |
1231 | int ret; | 1291 | int ret; |
1232 | 1292 | ||
@@ -1245,7 +1305,7 @@ static int p9_client_statsize(struct p9_wstat *wst, int optional) | |||
1245 | if (wst->muid) | 1305 | if (wst->muid) |
1246 | ret += strlen(wst->muid); | 1306 | ret += strlen(wst->muid); |
1247 | 1307 | ||
1248 | if (optional) { | 1308 | if (proto_version == p9_proto_2000u) { |
1249 | ret += 2+4+4+4; /* extension[s] n_uid[4] n_gid[4] n_muid[4] */ | 1309 | ret += 2+4+4+4; /* extension[s] n_uid[4] n_gid[4] n_muid[4] */ |
1250 | if (wst->extension) | 1310 | if (wst->extension) |
1251 | ret += strlen(wst->extension); | 1311 | ret += strlen(wst->extension); |
@@ -1262,7 +1322,7 @@ int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst) | |||
1262 | 1322 | ||
1263 | err = 0; | 1323 | err = 0; |
1264 | clnt = fid->clnt; | 1324 | clnt = fid->clnt; |
1265 | wst->size = p9_client_statsize(wst, clnt->dotu); | 1325 | wst->size = p9_client_statsize(wst, clnt->proto_version); |
1266 | P9_DPRINTK(P9_DEBUG_9P, ">>> TWSTAT fid %d\n", fid->fid); | 1326 | P9_DPRINTK(P9_DEBUG_9P, ">>> TWSTAT fid %d\n", fid->fid); |
1267 | P9_DPRINTK(P9_DEBUG_9P, | 1327 | P9_DPRINTK(P9_DEBUG_9P, |
1268 | " sz=%x type=%x dev=%x qid=%x.%llx.%x\n" | 1328 | " sz=%x type=%x dev=%x qid=%x.%llx.%x\n" |
diff --git a/net/9p/protocol.c b/net/9p/protocol.c index fc70147c771e..94f5a8f65e9c 100644 --- a/net/9p/protocol.c +++ b/net/9p/protocol.c | |||
@@ -52,7 +52,7 @@ | |||
52 | #endif | 52 | #endif |
53 | 53 | ||
54 | static int | 54 | static int |
55 | p9pdu_writef(struct p9_fcall *pdu, int optional, const char *fmt, ...); | 55 | p9pdu_writef(struct p9_fcall *pdu, int proto_version, const char *fmt, ...); |
56 | 56 | ||
57 | #ifdef CONFIG_NET_9P_DEBUG | 57 | #ifdef CONFIG_NET_9P_DEBUG |
58 | void | 58 | void |
@@ -144,7 +144,8 @@ pdu_write_u(struct p9_fcall *pdu, const char __user *udata, size_t size) | |||
144 | */ | 144 | */ |
145 | 145 | ||
146 | static int | 146 | static int |
147 | p9pdu_vreadf(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap) | 147 | p9pdu_vreadf(struct p9_fcall *pdu, int proto_version, const char *fmt, |
148 | va_list ap) | ||
148 | { | 149 | { |
149 | const char *ptr; | 150 | const char *ptr; |
150 | int errcode = 0; | 151 | int errcode = 0; |
@@ -194,7 +195,8 @@ p9pdu_vreadf(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap) | |||
194 | int16_t len; | 195 | int16_t len; |
195 | int size; | 196 | int size; |
196 | 197 | ||
197 | errcode = p9pdu_readf(pdu, optional, "w", &len); | 198 | errcode = p9pdu_readf(pdu, proto_version, |
199 | "w", &len); | ||
198 | if (errcode) | 200 | if (errcode) |
199 | break; | 201 | break; |
200 | 202 | ||
@@ -217,7 +219,7 @@ p9pdu_vreadf(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap) | |||
217 | struct p9_qid *qid = | 219 | struct p9_qid *qid = |
218 | va_arg(ap, struct p9_qid *); | 220 | va_arg(ap, struct p9_qid *); |
219 | 221 | ||
220 | errcode = p9pdu_readf(pdu, optional, "bdq", | 222 | errcode = p9pdu_readf(pdu, proto_version, "bdq", |
221 | &qid->type, &qid->version, | 223 | &qid->type, &qid->version, |
222 | &qid->path); | 224 | &qid->path); |
223 | } | 225 | } |
@@ -230,7 +232,7 @@ p9pdu_vreadf(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap) | |||
230 | stbuf->n_uid = stbuf->n_gid = stbuf->n_muid = | 232 | stbuf->n_uid = stbuf->n_gid = stbuf->n_muid = |
231 | -1; | 233 | -1; |
232 | errcode = | 234 | errcode = |
233 | p9pdu_readf(pdu, optional, | 235 | p9pdu_readf(pdu, proto_version, |
234 | "wwdQdddqssss?sddd", | 236 | "wwdQdddqssss?sddd", |
235 | &stbuf->size, &stbuf->type, | 237 | &stbuf->size, &stbuf->type, |
236 | &stbuf->dev, &stbuf->qid, | 238 | &stbuf->dev, &stbuf->qid, |
@@ -250,7 +252,7 @@ p9pdu_vreadf(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap) | |||
250 | void **data = va_arg(ap, void **); | 252 | void **data = va_arg(ap, void **); |
251 | 253 | ||
252 | errcode = | 254 | errcode = |
253 | p9pdu_readf(pdu, optional, "d", count); | 255 | p9pdu_readf(pdu, proto_version, "d", count); |
254 | if (!errcode) { | 256 | if (!errcode) { |
255 | *count = | 257 | *count = |
256 | MIN(*count, | 258 | MIN(*count, |
@@ -263,8 +265,8 @@ p9pdu_vreadf(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap) | |||
263 | int16_t *nwname = va_arg(ap, int16_t *); | 265 | int16_t *nwname = va_arg(ap, int16_t *); |
264 | char ***wnames = va_arg(ap, char ***); | 266 | char ***wnames = va_arg(ap, char ***); |
265 | 267 | ||
266 | errcode = | 268 | errcode = p9pdu_readf(pdu, proto_version, |
267 | p9pdu_readf(pdu, optional, "w", nwname); | 269 | "w", nwname); |
268 | if (!errcode) { | 270 | if (!errcode) { |
269 | *wnames = | 271 | *wnames = |
270 | kmalloc(sizeof(char *) * *nwname, | 272 | kmalloc(sizeof(char *) * *nwname, |
@@ -278,7 +280,8 @@ p9pdu_vreadf(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap) | |||
278 | 280 | ||
279 | for (i = 0; i < *nwname; i++) { | 281 | for (i = 0; i < *nwname; i++) { |
280 | errcode = | 282 | errcode = |
281 | p9pdu_readf(pdu, optional, | 283 | p9pdu_readf(pdu, |
284 | proto_version, | ||
282 | "s", | 285 | "s", |
283 | &(*wnames)[i]); | 286 | &(*wnames)[i]); |
284 | if (errcode) | 287 | if (errcode) |
@@ -306,7 +309,7 @@ p9pdu_vreadf(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap) | |||
306 | *wqids = NULL; | 309 | *wqids = NULL; |
307 | 310 | ||
308 | errcode = | 311 | errcode = |
309 | p9pdu_readf(pdu, optional, "w", nwqid); | 312 | p9pdu_readf(pdu, proto_version, "w", nwqid); |
310 | if (!errcode) { | 313 | if (!errcode) { |
311 | *wqids = | 314 | *wqids = |
312 | kmalloc(*nwqid * | 315 | kmalloc(*nwqid * |
@@ -321,7 +324,8 @@ p9pdu_vreadf(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap) | |||
321 | 324 | ||
322 | for (i = 0; i < *nwqid; i++) { | 325 | for (i = 0; i < *nwqid; i++) { |
323 | errcode = | 326 | errcode = |
324 | p9pdu_readf(pdu, optional, | 327 | p9pdu_readf(pdu, |
328 | proto_version, | ||
325 | "Q", | 329 | "Q", |
326 | &(*wqids)[i]); | 330 | &(*wqids)[i]); |
327 | if (errcode) | 331 | if (errcode) |
@@ -336,7 +340,7 @@ p9pdu_vreadf(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap) | |||
336 | } | 340 | } |
337 | break; | 341 | break; |
338 | case '?': | 342 | case '?': |
339 | if (!optional) | 343 | if (proto_version != p9_proto_2000u) |
340 | return 0; | 344 | return 0; |
341 | break; | 345 | break; |
342 | default: | 346 | default: |
@@ -352,7 +356,8 @@ p9pdu_vreadf(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap) | |||
352 | } | 356 | } |
353 | 357 | ||
354 | int | 358 | int |
355 | p9pdu_vwritef(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap) | 359 | p9pdu_vwritef(struct p9_fcall *pdu, int proto_version, const char *fmt, |
360 | va_list ap) | ||
356 | { | 361 | { |
357 | const char *ptr; | 362 | const char *ptr; |
358 | int errcode = 0; | 363 | int errcode = 0; |
@@ -389,7 +394,8 @@ p9pdu_vwritef(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap) | |||
389 | if (sptr) | 394 | if (sptr) |
390 | len = MIN(strlen(sptr), USHORT_MAX); | 395 | len = MIN(strlen(sptr), USHORT_MAX); |
391 | 396 | ||
392 | errcode = p9pdu_writef(pdu, optional, "w", len); | 397 | errcode = p9pdu_writef(pdu, proto_version, |
398 | "w", len); | ||
393 | if (!errcode && pdu_write(pdu, sptr, len)) | 399 | if (!errcode && pdu_write(pdu, sptr, len)) |
394 | errcode = -EFAULT; | 400 | errcode = -EFAULT; |
395 | } | 401 | } |
@@ -398,7 +404,7 @@ p9pdu_vwritef(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap) | |||
398 | const struct p9_qid *qid = | 404 | const struct p9_qid *qid = |
399 | va_arg(ap, const struct p9_qid *); | 405 | va_arg(ap, const struct p9_qid *); |
400 | errcode = | 406 | errcode = |
401 | p9pdu_writef(pdu, optional, "bdq", | 407 | p9pdu_writef(pdu, proto_version, "bdq", |
402 | qid->type, qid->version, | 408 | qid->type, qid->version, |
403 | qid->path); | 409 | qid->path); |
404 | } break; | 410 | } break; |
@@ -406,7 +412,7 @@ p9pdu_vwritef(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap) | |||
406 | const struct p9_wstat *stbuf = | 412 | const struct p9_wstat *stbuf = |
407 | va_arg(ap, const struct p9_wstat *); | 413 | va_arg(ap, const struct p9_wstat *); |
408 | errcode = | 414 | errcode = |
409 | p9pdu_writef(pdu, optional, | 415 | p9pdu_writef(pdu, proto_version, |
410 | "wwdQdddqssss?sddd", | 416 | "wwdQdddqssss?sddd", |
411 | stbuf->size, stbuf->type, | 417 | stbuf->size, stbuf->type, |
412 | stbuf->dev, &stbuf->qid, | 418 | stbuf->dev, &stbuf->qid, |
@@ -421,8 +427,8 @@ p9pdu_vwritef(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap) | |||
421 | int32_t count = va_arg(ap, int32_t); | 427 | int32_t count = va_arg(ap, int32_t); |
422 | const void *data = va_arg(ap, const void *); | 428 | const void *data = va_arg(ap, const void *); |
423 | 429 | ||
424 | errcode = | 430 | errcode = p9pdu_writef(pdu, proto_version, "d", |
425 | p9pdu_writef(pdu, optional, "d", count); | 431 | count); |
426 | if (!errcode && pdu_write(pdu, data, count)) | 432 | if (!errcode && pdu_write(pdu, data, count)) |
427 | errcode = -EFAULT; | 433 | errcode = -EFAULT; |
428 | } | 434 | } |
@@ -431,8 +437,8 @@ p9pdu_vwritef(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap) | |||
431 | int32_t count = va_arg(ap, int32_t); | 437 | int32_t count = va_arg(ap, int32_t); |
432 | const char __user *udata = | 438 | const char __user *udata = |
433 | va_arg(ap, const void __user *); | 439 | va_arg(ap, const void __user *); |
434 | errcode = | 440 | errcode = p9pdu_writef(pdu, proto_version, "d", |
435 | p9pdu_writef(pdu, optional, "d", count); | 441 | count); |
436 | if (!errcode && pdu_write_u(pdu, udata, count)) | 442 | if (!errcode && pdu_write_u(pdu, udata, count)) |
437 | errcode = -EFAULT; | 443 | errcode = -EFAULT; |
438 | } | 444 | } |
@@ -441,14 +447,15 @@ p9pdu_vwritef(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap) | |||
441 | int16_t nwname = va_arg(ap, int); | 447 | int16_t nwname = va_arg(ap, int); |
442 | const char **wnames = va_arg(ap, const char **); | 448 | const char **wnames = va_arg(ap, const char **); |
443 | 449 | ||
444 | errcode = | 450 | errcode = p9pdu_writef(pdu, proto_version, "w", |
445 | p9pdu_writef(pdu, optional, "w", nwname); | 451 | nwname); |
446 | if (!errcode) { | 452 | if (!errcode) { |
447 | int i; | 453 | int i; |
448 | 454 | ||
449 | for (i = 0; i < nwname; i++) { | 455 | for (i = 0; i < nwname; i++) { |
450 | errcode = | 456 | errcode = |
451 | p9pdu_writef(pdu, optional, | 457 | p9pdu_writef(pdu, |
458 | proto_version, | ||
452 | "s", | 459 | "s", |
453 | wnames[i]); | 460 | wnames[i]); |
454 | if (errcode) | 461 | if (errcode) |
@@ -462,14 +469,15 @@ p9pdu_vwritef(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap) | |||
462 | struct p9_qid *wqids = | 469 | struct p9_qid *wqids = |
463 | va_arg(ap, struct p9_qid *); | 470 | va_arg(ap, struct p9_qid *); |
464 | 471 | ||
465 | errcode = | 472 | errcode = p9pdu_writef(pdu, proto_version, "w", |
466 | p9pdu_writef(pdu, optional, "w", nwqid); | 473 | nwqid); |
467 | if (!errcode) { | 474 | if (!errcode) { |
468 | int i; | 475 | int i; |
469 | 476 | ||
470 | for (i = 0; i < nwqid; i++) { | 477 | for (i = 0; i < nwqid; i++) { |
471 | errcode = | 478 | errcode = |
472 | p9pdu_writef(pdu, optional, | 479 | p9pdu_writef(pdu, |
480 | proto_version, | ||
473 | "Q", | 481 | "Q", |
474 | &wqids[i]); | 482 | &wqids[i]); |
475 | if (errcode) | 483 | if (errcode) |
@@ -479,7 +487,7 @@ p9pdu_vwritef(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap) | |||
479 | } | 487 | } |
480 | break; | 488 | break; |
481 | case '?': | 489 | case '?': |
482 | if (!optional) | 490 | if (proto_version != p9_proto_2000u) |
483 | return 0; | 491 | return 0; |
484 | break; | 492 | break; |
485 | default: | 493 | default: |
@@ -494,32 +502,32 @@ p9pdu_vwritef(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap) | |||
494 | return errcode; | 502 | return errcode; |
495 | } | 503 | } |
496 | 504 | ||
497 | int p9pdu_readf(struct p9_fcall *pdu, int optional, const char *fmt, ...) | 505 | int p9pdu_readf(struct p9_fcall *pdu, int proto_version, const char *fmt, ...) |
498 | { | 506 | { |
499 | va_list ap; | 507 | va_list ap; |
500 | int ret; | 508 | int ret; |
501 | 509 | ||
502 | va_start(ap, fmt); | 510 | va_start(ap, fmt); |
503 | ret = p9pdu_vreadf(pdu, optional, fmt, ap); | 511 | ret = p9pdu_vreadf(pdu, proto_version, fmt, ap); |
504 | va_end(ap); | 512 | va_end(ap); |
505 | 513 | ||
506 | return ret; | 514 | return ret; |
507 | } | 515 | } |
508 | 516 | ||
509 | static int | 517 | static int |
510 | p9pdu_writef(struct p9_fcall *pdu, int optional, const char *fmt, ...) | 518 | p9pdu_writef(struct p9_fcall *pdu, int proto_version, const char *fmt, ...) |
511 | { | 519 | { |
512 | va_list ap; | 520 | va_list ap; |
513 | int ret; | 521 | int ret; |
514 | 522 | ||
515 | va_start(ap, fmt); | 523 | va_start(ap, fmt); |
516 | ret = p9pdu_vwritef(pdu, optional, fmt, ap); | 524 | ret = p9pdu_vwritef(pdu, proto_version, fmt, ap); |
517 | va_end(ap); | 525 | va_end(ap); |
518 | 526 | ||
519 | return ret; | 527 | return ret; |
520 | } | 528 | } |
521 | 529 | ||
522 | int p9stat_read(char *buf, int len, struct p9_wstat *st, int dotu) | 530 | int p9stat_read(char *buf, int len, struct p9_wstat *st, int proto_version) |
523 | { | 531 | { |
524 | struct p9_fcall fake_pdu; | 532 | struct p9_fcall fake_pdu; |
525 | int ret; | 533 | int ret; |
@@ -529,7 +537,7 @@ int p9stat_read(char *buf, int len, struct p9_wstat *st, int dotu) | |||
529 | fake_pdu.sdata = buf; | 537 | fake_pdu.sdata = buf; |
530 | fake_pdu.offset = 0; | 538 | fake_pdu.offset = 0; |
531 | 539 | ||
532 | ret = p9pdu_readf(&fake_pdu, dotu, "S", st); | 540 | ret = p9pdu_readf(&fake_pdu, proto_version, "S", st); |
533 | if (ret) { | 541 | if (ret) { |
534 | P9_DPRINTK(P9_DEBUG_9P, "<<< p9stat_read failed: %d\n", ret); | 542 | P9_DPRINTK(P9_DEBUG_9P, "<<< p9stat_read failed: %d\n", ret); |
535 | p9pdu_dump(1, &fake_pdu); | 543 | p9pdu_dump(1, &fake_pdu); |
diff --git a/net/9p/protocol.h b/net/9p/protocol.h index ccde462e7ac5..2431c0f38d56 100644 --- a/net/9p/protocol.h +++ b/net/9p/protocol.h | |||
@@ -25,9 +25,9 @@ | |||
25 | * | 25 | * |
26 | */ | 26 | */ |
27 | 27 | ||
28 | int | 28 | int p9pdu_vwritef(struct p9_fcall *pdu, int proto_version, const char *fmt, |
29 | p9pdu_vwritef(struct p9_fcall *pdu, int optional, const char *fmt, va_list ap); | 29 | va_list ap); |
30 | int p9pdu_readf(struct p9_fcall *pdu, int optional, const char *fmt, ...); | 30 | int p9pdu_readf(struct p9_fcall *pdu, int proto_version, const char *fmt, ...); |
31 | int p9pdu_prepare(struct p9_fcall *pdu, int16_t tag, int8_t type); | 31 | int p9pdu_prepare(struct p9_fcall *pdu, int16_t tag, int8_t type); |
32 | int p9pdu_finalize(struct p9_fcall *pdu); | 32 | int p9pdu_finalize(struct p9_fcall *pdu); |
33 | void p9pdu_dump(int, struct p9_fcall *); | 33 | void p9pdu_dump(int, struct p9_fcall *); |
diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c index cb50f4ae5eef..afde1a89fbb3 100644 --- a/net/9p/trans_virtio.c +++ b/net/9p/trans_virtio.c | |||
@@ -49,8 +49,6 @@ | |||
49 | 49 | ||
50 | /* a single mutex to manage channel initialization and attachment */ | 50 | /* a single mutex to manage channel initialization and attachment */ |
51 | static DEFINE_MUTEX(virtio_9p_lock); | 51 | static DEFINE_MUTEX(virtio_9p_lock); |
52 | /* global which tracks highest initialized channel */ | ||
53 | static int chan_index; | ||
54 | 52 | ||
55 | /** | 53 | /** |
56 | * struct virtio_chan - per-instance transport information | 54 | * struct virtio_chan - per-instance transport information |
@@ -68,8 +66,7 @@ static int chan_index; | |||
68 | * | 66 | * |
69 | */ | 67 | */ |
70 | 68 | ||
71 | static struct virtio_chan { | 69 | struct virtio_chan { |
72 | bool initialized; | ||
73 | bool inuse; | 70 | bool inuse; |
74 | 71 | ||
75 | spinlock_t lock; | 72 | spinlock_t lock; |
@@ -80,7 +77,17 @@ static struct virtio_chan { | |||
80 | 77 | ||
81 | /* Scatterlist: can be too big for stack. */ | 78 | /* Scatterlist: can be too big for stack. */ |
82 | struct scatterlist sg[VIRTQUEUE_NUM]; | 79 | struct scatterlist sg[VIRTQUEUE_NUM]; |
83 | } channels[MAX_9P_CHAN]; | 80 | |
81 | int tag_len; | ||
82 | /* | ||
83 | * tag name to identify a mount Non-null terminated | ||
84 | */ | ||
85 | char *tag; | ||
86 | |||
87 | struct list_head chan_list; | ||
88 | }; | ||
89 | |||
90 | static struct list_head virtio_chan_list; | ||
84 | 91 | ||
85 | /* How many bytes left in this page. */ | 92 | /* How many bytes left in this page. */ |
86 | static unsigned int rest_of_page(void *data) | 93 | static unsigned int rest_of_page(void *data) |
@@ -213,30 +220,38 @@ p9_virtio_request(struct p9_client *client, struct p9_req_t *req) | |||
213 | return 0; | 220 | return 0; |
214 | } | 221 | } |
215 | 222 | ||
223 | static ssize_t p9_mount_tag_show(struct device *dev, | ||
224 | struct device_attribute *attr, char *buf) | ||
225 | { | ||
226 | struct virtio_chan *chan; | ||
227 | struct virtio_device *vdev; | ||
228 | |||
229 | vdev = dev_to_virtio(dev); | ||
230 | chan = vdev->priv; | ||
231 | |||
232 | return snprintf(buf, chan->tag_len + 1, "%s", chan->tag); | ||
233 | } | ||
234 | |||
235 | static DEVICE_ATTR(mount_tag, 0444, p9_mount_tag_show, NULL); | ||
236 | |||
216 | /** | 237 | /** |
217 | * p9_virtio_probe - probe for existence of 9P virtio channels | 238 | * p9_virtio_probe - probe for existence of 9P virtio channels |
218 | * @vdev: virtio device to probe | 239 | * @vdev: virtio device to probe |
219 | * | 240 | * |
220 | * This probes for existing virtio channels. At present only | 241 | * This probes for existing virtio channels. |
221 | * a single channel is in use, so in the future more work may need | ||
222 | * to be done here. | ||
223 | * | 242 | * |
224 | */ | 243 | */ |
225 | 244 | ||
226 | static int p9_virtio_probe(struct virtio_device *vdev) | 245 | static int p9_virtio_probe(struct virtio_device *vdev) |
227 | { | 246 | { |
247 | __u16 tag_len; | ||
248 | char *tag; | ||
228 | int err; | 249 | int err; |
229 | struct virtio_chan *chan; | 250 | struct virtio_chan *chan; |
230 | int index; | ||
231 | 251 | ||
232 | mutex_lock(&virtio_9p_lock); | 252 | chan = kmalloc(sizeof(struct virtio_chan), GFP_KERNEL); |
233 | index = chan_index++; | 253 | if (!chan) { |
234 | chan = &channels[index]; | 254 | printk(KERN_ERR "9p: Failed to allocate virtio 9P channel\n"); |
235 | mutex_unlock(&virtio_9p_lock); | ||
236 | |||
237 | if (chan_index > MAX_9P_CHAN) { | ||
238 | printk(KERN_ERR "9p: virtio: Maximum channels exceeded\n"); | ||
239 | BUG(); | ||
240 | err = -ENOMEM; | 255 | err = -ENOMEM; |
241 | goto fail; | 256 | goto fail; |
242 | } | 257 | } |
@@ -255,15 +270,37 @@ static int p9_virtio_probe(struct virtio_device *vdev) | |||
255 | sg_init_table(chan->sg, VIRTQUEUE_NUM); | 270 | sg_init_table(chan->sg, VIRTQUEUE_NUM); |
256 | 271 | ||
257 | chan->inuse = false; | 272 | chan->inuse = false; |
258 | chan->initialized = true; | 273 | if (virtio_has_feature(vdev, VIRTIO_9P_MOUNT_TAG)) { |
274 | vdev->config->get(vdev, | ||
275 | offsetof(struct virtio_9p_config, tag_len), | ||
276 | &tag_len, sizeof(tag_len)); | ||
277 | } else { | ||
278 | err = -EINVAL; | ||
279 | goto out_free_vq; | ||
280 | } | ||
281 | tag = kmalloc(tag_len, GFP_KERNEL); | ||
282 | if (!tag) { | ||
283 | err = -ENOMEM; | ||
284 | goto out_free_vq; | ||
285 | } | ||
286 | vdev->config->get(vdev, offsetof(struct virtio_9p_config, tag), | ||
287 | tag, tag_len); | ||
288 | chan->tag = tag; | ||
289 | chan->tag_len = tag_len; | ||
290 | err = sysfs_create_file(&(vdev->dev.kobj), &dev_attr_mount_tag.attr); | ||
291 | if (err) { | ||
292 | kfree(tag); | ||
293 | goto out_free_vq; | ||
294 | } | ||
295 | mutex_lock(&virtio_9p_lock); | ||
296 | list_add_tail(&chan->chan_list, &virtio_chan_list); | ||
297 | mutex_unlock(&virtio_9p_lock); | ||
259 | return 0; | 298 | return 0; |
260 | 299 | ||
261 | out_free_vq: | 300 | out_free_vq: |
262 | vdev->config->del_vqs(vdev); | 301 | vdev->config->del_vqs(vdev); |
302 | kfree(chan); | ||
263 | fail: | 303 | fail: |
264 | mutex_lock(&virtio_9p_lock); | ||
265 | chan_index--; | ||
266 | mutex_unlock(&virtio_9p_lock); | ||
267 | return err; | 304 | return err; |
268 | } | 305 | } |
269 | 306 | ||
@@ -280,35 +317,31 @@ fail: | |||
280 | * We use a simple reference count mechanism to ensure that only a single | 317 | * We use a simple reference count mechanism to ensure that only a single |
281 | * mount has a channel open at a time. | 318 | * mount has a channel open at a time. |
282 | * | 319 | * |
283 | * Bugs: doesn't allow identification of a specific channel | ||
284 | * to allocate, channels are allocated sequentially. This was | ||
285 | * a pragmatic decision to get things rolling, but ideally some | ||
286 | * way of identifying the channel to attach to would be nice | ||
287 | * if we are going to support multiple channels. | ||
288 | * | ||
289 | */ | 320 | */ |
290 | 321 | ||
291 | static int | 322 | static int |
292 | p9_virtio_create(struct p9_client *client, const char *devname, char *args) | 323 | p9_virtio_create(struct p9_client *client, const char *devname, char *args) |
293 | { | 324 | { |
294 | struct virtio_chan *chan = channels; | 325 | struct virtio_chan *chan; |
295 | int index = 0; | 326 | int ret = -ENOENT; |
327 | int found = 0; | ||
296 | 328 | ||
297 | mutex_lock(&virtio_9p_lock); | 329 | mutex_lock(&virtio_9p_lock); |
298 | while (index < MAX_9P_CHAN) { | 330 | list_for_each_entry(chan, &virtio_chan_list, chan_list) { |
299 | if (chan->initialized && !chan->inuse) { | 331 | if (!strncmp(devname, chan->tag, chan->tag_len)) { |
300 | chan->inuse = true; | 332 | if (!chan->inuse) { |
301 | break; | 333 | chan->inuse = true; |
302 | } else { | 334 | found = 1; |
303 | index++; | 335 | break; |
304 | chan = &channels[index]; | 336 | } |
337 | ret = -EBUSY; | ||
305 | } | 338 | } |
306 | } | 339 | } |
307 | mutex_unlock(&virtio_9p_lock); | 340 | mutex_unlock(&virtio_9p_lock); |
308 | 341 | ||
309 | if (index >= MAX_9P_CHAN) { | 342 | if (!found) { |
310 | printk(KERN_ERR "9p: no channels available\n"); | 343 | printk(KERN_ERR "9p: no channels available\n"); |
311 | return -ENODEV; | 344 | return ret; |
312 | } | 345 | } |
313 | 346 | ||
314 | client->trans = (void *)chan; | 347 | client->trans = (void *)chan; |
@@ -329,11 +362,15 @@ static void p9_virtio_remove(struct virtio_device *vdev) | |||
329 | struct virtio_chan *chan = vdev->priv; | 362 | struct virtio_chan *chan = vdev->priv; |
330 | 363 | ||
331 | BUG_ON(chan->inuse); | 364 | BUG_ON(chan->inuse); |
365 | vdev->config->del_vqs(vdev); | ||
366 | |||
367 | mutex_lock(&virtio_9p_lock); | ||
368 | list_del(&chan->chan_list); | ||
369 | mutex_unlock(&virtio_9p_lock); | ||
370 | sysfs_remove_file(&(vdev->dev.kobj), &dev_attr_mount_tag.attr); | ||
371 | kfree(chan->tag); | ||
372 | kfree(chan); | ||
332 | 373 | ||
333 | if (chan->initialized) { | ||
334 | vdev->config->del_vqs(vdev); | ||
335 | chan->initialized = false; | ||
336 | } | ||
337 | } | 374 | } |
338 | 375 | ||
339 | static struct virtio_device_id id_table[] = { | 376 | static struct virtio_device_id id_table[] = { |
@@ -341,13 +378,19 @@ static struct virtio_device_id id_table[] = { | |||
341 | { 0 }, | 378 | { 0 }, |
342 | }; | 379 | }; |
343 | 380 | ||
381 | static unsigned int features[] = { | ||
382 | VIRTIO_9P_MOUNT_TAG, | ||
383 | }; | ||
384 | |||
344 | /* The standard "struct lguest_driver": */ | 385 | /* The standard "struct lguest_driver": */ |
345 | static struct virtio_driver p9_virtio_drv = { | 386 | static struct virtio_driver p9_virtio_drv = { |
346 | .driver.name = KBUILD_MODNAME, | 387 | .feature_table = features, |
347 | .driver.owner = THIS_MODULE, | 388 | .feature_table_size = ARRAY_SIZE(features), |
348 | .id_table = id_table, | 389 | .driver.name = KBUILD_MODNAME, |
349 | .probe = p9_virtio_probe, | 390 | .driver.owner = THIS_MODULE, |
350 | .remove = p9_virtio_remove, | 391 | .id_table = id_table, |
392 | .probe = p9_virtio_probe, | ||
393 | .remove = p9_virtio_remove, | ||
351 | }; | 394 | }; |
352 | 395 | ||
353 | static struct p9_trans_module p9_virtio_trans = { | 396 | static struct p9_trans_module p9_virtio_trans = { |
@@ -364,10 +407,7 @@ static struct p9_trans_module p9_virtio_trans = { | |||
364 | /* The standard init function */ | 407 | /* The standard init function */ |
365 | static int __init p9_virtio_init(void) | 408 | static int __init p9_virtio_init(void) |
366 | { | 409 | { |
367 | int count; | 410 | INIT_LIST_HEAD(&virtio_chan_list); |
368 | |||
369 | for (count = 0; count < MAX_9P_CHAN; count++) | ||
370 | channels[count].initialized = false; | ||
371 | 411 | ||
372 | v9fs_register_trans(&p9_virtio_trans); | 412 | v9fs_register_trans(&p9_virtio_trans); |
373 | return register_virtio_driver(&p9_virtio_drv); | 413 | return register_virtio_driver(&p9_virtio_drv); |
diff --git a/net/Kconfig b/net/Kconfig index 041c35edb763..68514644ce91 100644 --- a/net/Kconfig +++ b/net/Kconfig | |||
@@ -203,6 +203,11 @@ source "net/ieee802154/Kconfig" | |||
203 | source "net/sched/Kconfig" | 203 | source "net/sched/Kconfig" |
204 | source "net/dcb/Kconfig" | 204 | source "net/dcb/Kconfig" |
205 | 205 | ||
206 | config RPS | ||
207 | boolean | ||
208 | depends on SMP && SYSFS | ||
209 | default y | ||
210 | |||
206 | menu "Network testing" | 211 | menu "Network testing" |
207 | 212 | ||
208 | config NET_PKTGEN | 213 | config NET_PKTGEN |
diff --git a/net/atm/proc.c b/net/atm/proc.c index 7a96b2376bd7..f188a399c679 100644 --- a/net/atm/proc.c +++ b/net/atm/proc.c | |||
@@ -406,7 +406,6 @@ EXPORT_SYMBOL(atm_proc_root); | |||
406 | 406 | ||
407 | int atm_proc_dev_register(struct atm_dev *dev) | 407 | int atm_proc_dev_register(struct atm_dev *dev) |
408 | { | 408 | { |
409 | int digits, num; | ||
410 | int error; | 409 | int error; |
411 | 410 | ||
412 | /* No proc info */ | 411 | /* No proc info */ |
@@ -414,16 +413,9 @@ int atm_proc_dev_register(struct atm_dev *dev) | |||
414 | return 0; | 413 | return 0; |
415 | 414 | ||
416 | error = -ENOMEM; | 415 | error = -ENOMEM; |
417 | digits = 0; | 416 | dev->proc_name = kasprintf(GFP_KERNEL, "%s:%d", dev->type, dev->number); |
418 | for (num = dev->number; num; num /= 10) | ||
419 | digits++; | ||
420 | if (!digits) | ||
421 | digits++; | ||
422 | |||
423 | dev->proc_name = kmalloc(strlen(dev->type) + digits + 2, GFP_KERNEL); | ||
424 | if (!dev->proc_name) | 417 | if (!dev->proc_name) |
425 | goto err_out; | 418 | goto err_out; |
426 | sprintf(dev->proc_name, "%s:%d", dev->type, dev->number); | ||
427 | 419 | ||
428 | dev->proc_entry = proc_create_data(dev->proc_name, 0, atm_proc_root, | 420 | dev->proc_entry = proc_create_data(dev->proc_name, 0, atm_proc_root, |
429 | &proc_atm_dev_ops, dev); | 421 | &proc_atm_dev_ops, dev); |
diff --git a/net/bluetooth/bnep/netdev.c b/net/bluetooth/bnep/netdev.c index b6234b73c4cf..326ab453edb7 100644 --- a/net/bluetooth/bnep/netdev.c +++ b/net/bluetooth/bnep/netdev.c | |||
@@ -87,7 +87,7 @@ static void bnep_net_set_mc_list(struct net_device *dev) | |||
87 | memcpy(__skb_put(skb, ETH_ALEN), dev->broadcast, ETH_ALEN); | 87 | memcpy(__skb_put(skb, ETH_ALEN), dev->broadcast, ETH_ALEN); |
88 | r->len = htons(ETH_ALEN * 2); | 88 | r->len = htons(ETH_ALEN * 2); |
89 | } else { | 89 | } else { |
90 | struct dev_mc_list *dmi = dev->mc_list; | 90 | struct dev_mc_list *dmi; |
91 | int i, len = skb->len; | 91 | int i, len = skb->len; |
92 | 92 | ||
93 | if (dev->flags & IFF_BROADCAST) { | 93 | if (dev->flags & IFF_BROADCAST) { |
@@ -97,12 +97,12 @@ static void bnep_net_set_mc_list(struct net_device *dev) | |||
97 | 97 | ||
98 | /* FIXME: We should group addresses here. */ | 98 | /* FIXME: We should group addresses here. */ |
99 | 99 | ||
100 | for (i = 0; | 100 | i = 0; |
101 | i < netdev_mc_count(dev) && i < BNEP_MAX_MULTICAST_FILTERS; | 101 | netdev_for_each_mc_addr(dmi, dev) { |
102 | i++) { | 102 | if (i == BNEP_MAX_MULTICAST_FILTERS) |
103 | break; | ||
103 | memcpy(__skb_put(skb, ETH_ALEN), dmi->dmi_addr, ETH_ALEN); | 104 | memcpy(__skb_put(skb, ETH_ALEN), dmi->dmi_addr, ETH_ALEN); |
104 | memcpy(__skb_put(skb, ETH_ALEN), dmi->dmi_addr, ETH_ALEN); | 105 | memcpy(__skb_put(skb, ETH_ALEN), dmi->dmi_addr, ETH_ALEN); |
105 | dmi = dmi->next; | ||
106 | } | 106 | } |
107 | r->len = htons(skb->len - len); | 107 | r->len = htons(skb->len - len); |
108 | } | 108 | } |
diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c index 1a79a6c7e30e..cafb55b0cea5 100644 --- a/net/bluetooth/hci_sysfs.c +++ b/net/bluetooth/hci_sysfs.c | |||
@@ -3,6 +3,7 @@ | |||
3 | #include <linux/kernel.h> | 3 | #include <linux/kernel.h> |
4 | #include <linux/init.h> | 4 | #include <linux/init.h> |
5 | #include <linux/debugfs.h> | 5 | #include <linux/debugfs.h> |
6 | #include <linux/seq_file.h> | ||
6 | 7 | ||
7 | #include <net/bluetooth/bluetooth.h> | 8 | #include <net/bluetooth/bluetooth.h> |
8 | #include <net/bluetooth/hci_core.h> | 9 | #include <net/bluetooth/hci_core.h> |
@@ -405,20 +406,11 @@ static struct device_type bt_host = { | |||
405 | .release = bt_host_release, | 406 | .release = bt_host_release, |
406 | }; | 407 | }; |
407 | 408 | ||
408 | static int inquiry_cache_open(struct inode *inode, struct file *file) | 409 | static int inquiry_cache_show(struct seq_file *f, void *p) |
409 | { | ||
410 | file->private_data = inode->i_private; | ||
411 | return 0; | ||
412 | } | ||
413 | |||
414 | static ssize_t inquiry_cache_read(struct file *file, char __user *userbuf, | ||
415 | size_t count, loff_t *ppos) | ||
416 | { | 410 | { |
417 | struct hci_dev *hdev = file->private_data; | 411 | struct hci_dev *hdev = f->private; |
418 | struct inquiry_cache *cache = &hdev->inq_cache; | 412 | struct inquiry_cache *cache = &hdev->inq_cache; |
419 | struct inquiry_entry *e; | 413 | struct inquiry_entry *e; |
420 | char buf[4096]; | ||
421 | int n = 0; | ||
422 | 414 | ||
423 | hci_dev_lock_bh(hdev); | 415 | hci_dev_lock_bh(hdev); |
424 | 416 | ||
@@ -426,23 +418,30 @@ static ssize_t inquiry_cache_read(struct file *file, char __user *userbuf, | |||
426 | struct inquiry_data *data = &e->data; | 418 | struct inquiry_data *data = &e->data; |
427 | bdaddr_t bdaddr; | 419 | bdaddr_t bdaddr; |
428 | baswap(&bdaddr, &data->bdaddr); | 420 | baswap(&bdaddr, &data->bdaddr); |
429 | n += sprintf(buf + n, "%s %d %d %d 0x%.2x%.2x%.2x 0x%.4x %d %d %u\n", | 421 | seq_printf(f, "%s %d %d %d 0x%.2x%.2x%.2x 0x%.4x %d %d %u\n", |
430 | batostr(&bdaddr), | 422 | batostr(&bdaddr), |
431 | data->pscan_rep_mode, data->pscan_period_mode, | 423 | data->pscan_rep_mode, data->pscan_period_mode, |
432 | data->pscan_mode, data->dev_class[2], | 424 | data->pscan_mode, data->dev_class[2], |
433 | data->dev_class[1], data->dev_class[0], | 425 | data->dev_class[1], data->dev_class[0], |
434 | __le16_to_cpu(data->clock_offset), | 426 | __le16_to_cpu(data->clock_offset), |
435 | data->rssi, data->ssp_mode, e->timestamp); | 427 | data->rssi, data->ssp_mode, e->timestamp); |
436 | } | 428 | } |
437 | 429 | ||
438 | hci_dev_unlock_bh(hdev); | 430 | hci_dev_unlock_bh(hdev); |
439 | 431 | ||
440 | return simple_read_from_buffer(userbuf, count, ppos, buf, n); | 432 | return 0; |
433 | } | ||
434 | |||
435 | static int inquiry_cache_open(struct inode *inode, struct file *file) | ||
436 | { | ||
437 | return single_open(file, inquiry_cache_show, inode->i_private); | ||
441 | } | 438 | } |
442 | 439 | ||
443 | static const struct file_operations inquiry_cache_fops = { | 440 | static const struct file_operations inquiry_cache_fops = { |
444 | .open = inquiry_cache_open, | 441 | .open = inquiry_cache_open, |
445 | .read = inquiry_cache_read, | 442 | .read = seq_read, |
443 | .llseek = seq_lseek, | ||
444 | .release = single_release, | ||
446 | }; | 445 | }; |
447 | 446 | ||
448 | int hci_register_sysfs(struct hci_dev *hdev) | 447 | int hci_register_sysfs(struct hci_dev *hdev) |
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 400efa26ddba..4db7ae2fe07d 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c | |||
@@ -3937,7 +3937,9 @@ drop: | |||
3937 | return 0; | 3937 | return 0; |
3938 | } | 3938 | } |
3939 | 3939 | ||
3940 | static ssize_t l2cap_sysfs_show(struct class *dev, char *buf) | 3940 | static ssize_t l2cap_sysfs_show(struct class *dev, |
3941 | struct class_attribute *attr, | ||
3942 | char *buf) | ||
3941 | { | 3943 | { |
3942 | struct sock *sk; | 3944 | struct sock *sk; |
3943 | struct hlist_node *node; | 3945 | struct hlist_node *node; |
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index 89f4a59eb82b..db8a68e1a5ba 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c | |||
@@ -2098,7 +2098,9 @@ static struct hci_cb rfcomm_cb = { | |||
2098 | .security_cfm = rfcomm_security_cfm | 2098 | .security_cfm = rfcomm_security_cfm |
2099 | }; | 2099 | }; |
2100 | 2100 | ||
2101 | static ssize_t rfcomm_dlc_sysfs_show(struct class *dev, char *buf) | 2101 | static ssize_t rfcomm_dlc_sysfs_show(struct class *dev, |
2102 | struct class_attribute *attr, | ||
2103 | char *buf) | ||
2102 | { | 2104 | { |
2103 | struct rfcomm_session *s; | 2105 | struct rfcomm_session *s; |
2104 | struct list_head *pp, *p; | 2106 | struct list_head *pp, *p; |
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index 4b5968dda673..ca87d6ac6a20 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c | |||
@@ -1061,7 +1061,9 @@ done: | |||
1061 | return result; | 1061 | return result; |
1062 | } | 1062 | } |
1063 | 1063 | ||
1064 | static ssize_t rfcomm_sock_sysfs_show(struct class *dev, char *buf) | 1064 | static ssize_t rfcomm_sock_sysfs_show(struct class *dev, |
1065 | struct class_attribute *attr, | ||
1066 | char *buf) | ||
1065 | { | 1067 | { |
1066 | struct sock *sk; | 1068 | struct sock *sk; |
1067 | struct hlist_node *node; | 1069 | struct hlist_node *node; |
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index dd8f6ec57dce..f93b939539bc 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c | |||
@@ -953,7 +953,9 @@ drop: | |||
953 | return 0; | 953 | return 0; |
954 | } | 954 | } |
955 | 955 | ||
956 | static ssize_t sco_sysfs_show(struct class *dev, char *buf) | 956 | static ssize_t sco_sysfs_show(struct class *dev, |
957 | struct class_attribute *attr, | ||
958 | char *buf) | ||
957 | { | 959 | { |
958 | struct sock *sk; | 960 | struct sock *sk; |
959 | struct hlist_node *node; | 961 | struct hlist_node *node; |
diff --git a/net/bridge/Kconfig b/net/bridge/Kconfig index 19a6b9629c51..d115d5cea5b6 100644 --- a/net/bridge/Kconfig +++ b/net/bridge/Kconfig | |||
@@ -35,6 +35,7 @@ config BRIDGE | |||
35 | config BRIDGE_IGMP_SNOOPING | 35 | config BRIDGE_IGMP_SNOOPING |
36 | bool "IGMP snooping" | 36 | bool "IGMP snooping" |
37 | depends on BRIDGE | 37 | depends on BRIDGE |
38 | depends on INET | ||
38 | default y | 39 | default y |
39 | ---help--- | 40 | ---help--- |
40 | If you say Y here, then the Ethernet bridge will be able selectively | 41 | If you say Y here, then the Ethernet bridge will be able selectively |
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index eb7062d2e9e5..5b8a6e73b02f 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c | |||
@@ -26,11 +26,12 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev) | |||
26 | const unsigned char *dest = skb->data; | 26 | const unsigned char *dest = skb->data; |
27 | struct net_bridge_fdb_entry *dst; | 27 | struct net_bridge_fdb_entry *dst; |
28 | struct net_bridge_mdb_entry *mdst; | 28 | struct net_bridge_mdb_entry *mdst; |
29 | struct br_cpu_netstats *brstats = this_cpu_ptr(br->stats); | ||
29 | 30 | ||
30 | BR_INPUT_SKB_CB(skb)->brdev = dev; | 31 | brstats->tx_packets++; |
32 | brstats->tx_bytes += skb->len; | ||
31 | 33 | ||
32 | dev->stats.tx_packets++; | 34 | BR_INPUT_SKB_CB(skb)->brdev = dev; |
33 | dev->stats.tx_bytes += skb->len; | ||
34 | 35 | ||
35 | skb_reset_mac_header(skb); | 36 | skb_reset_mac_header(skb); |
36 | skb_pull(skb, ETH_HLEN); | 37 | skb_pull(skb, ETH_HLEN); |
@@ -40,7 +41,7 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev) | |||
40 | goto out; | 41 | goto out; |
41 | 42 | ||
42 | mdst = br_mdb_get(br, skb); | 43 | mdst = br_mdb_get(br, skb); |
43 | if (mdst || BR_INPUT_SKB_CB(skb)->mrouters_only) | 44 | if (mdst || BR_INPUT_SKB_CB_MROUTERS_ONLY(skb)) |
44 | br_multicast_deliver(mdst, skb); | 45 | br_multicast_deliver(mdst, skb); |
45 | else | 46 | else |
46 | br_flood_deliver(br, skb); | 47 | br_flood_deliver(br, skb); |
@@ -81,6 +82,31 @@ static int br_dev_stop(struct net_device *dev) | |||
81 | return 0; | 82 | return 0; |
82 | } | 83 | } |
83 | 84 | ||
85 | static struct net_device_stats *br_get_stats(struct net_device *dev) | ||
86 | { | ||
87 | struct net_bridge *br = netdev_priv(dev); | ||
88 | struct net_device_stats *stats = &dev->stats; | ||
89 | struct br_cpu_netstats sum = { 0 }; | ||
90 | unsigned int cpu; | ||
91 | |||
92 | for_each_possible_cpu(cpu) { | ||
93 | const struct br_cpu_netstats *bstats | ||
94 | = per_cpu_ptr(br->stats, cpu); | ||
95 | |||
96 | sum.tx_bytes += bstats->tx_bytes; | ||
97 | sum.tx_packets += bstats->tx_packets; | ||
98 | sum.rx_bytes += bstats->rx_bytes; | ||
99 | sum.rx_packets += bstats->rx_packets; | ||
100 | } | ||
101 | |||
102 | stats->tx_bytes = sum.tx_bytes; | ||
103 | stats->tx_packets = sum.tx_packets; | ||
104 | stats->rx_bytes = sum.rx_bytes; | ||
105 | stats->rx_packets = sum.rx_packets; | ||
106 | |||
107 | return stats; | ||
108 | } | ||
109 | |||
84 | static int br_change_mtu(struct net_device *dev, int new_mtu) | 110 | static int br_change_mtu(struct net_device *dev, int new_mtu) |
85 | { | 111 | { |
86 | struct net_bridge *br = netdev_priv(dev); | 112 | struct net_bridge *br = netdev_priv(dev); |
@@ -180,19 +206,28 @@ static const struct net_device_ops br_netdev_ops = { | |||
180 | .ndo_open = br_dev_open, | 206 | .ndo_open = br_dev_open, |
181 | .ndo_stop = br_dev_stop, | 207 | .ndo_stop = br_dev_stop, |
182 | .ndo_start_xmit = br_dev_xmit, | 208 | .ndo_start_xmit = br_dev_xmit, |
209 | .ndo_get_stats = br_get_stats, | ||
183 | .ndo_set_mac_address = br_set_mac_address, | 210 | .ndo_set_mac_address = br_set_mac_address, |
184 | .ndo_set_multicast_list = br_dev_set_multicast_list, | 211 | .ndo_set_multicast_list = br_dev_set_multicast_list, |
185 | .ndo_change_mtu = br_change_mtu, | 212 | .ndo_change_mtu = br_change_mtu, |
186 | .ndo_do_ioctl = br_dev_ioctl, | 213 | .ndo_do_ioctl = br_dev_ioctl, |
187 | }; | 214 | }; |
188 | 215 | ||
216 | static void br_dev_free(struct net_device *dev) | ||
217 | { | ||
218 | struct net_bridge *br = netdev_priv(dev); | ||
219 | |||
220 | free_percpu(br->stats); | ||
221 | free_netdev(dev); | ||
222 | } | ||
223 | |||
189 | void br_dev_setup(struct net_device *dev) | 224 | void br_dev_setup(struct net_device *dev) |
190 | { | 225 | { |
191 | random_ether_addr(dev->dev_addr); | 226 | random_ether_addr(dev->dev_addr); |
192 | ether_setup(dev); | 227 | ether_setup(dev); |
193 | 228 | ||
194 | dev->netdev_ops = &br_netdev_ops; | 229 | dev->netdev_ops = &br_netdev_ops; |
195 | dev->destructor = free_netdev; | 230 | dev->destructor = br_dev_free; |
196 | SET_ETHTOOL_OPS(dev, &br_ethtool_ops); | 231 | SET_ETHTOOL_OPS(dev, &br_ethtool_ops); |
197 | dev->tx_queue_len = 0; | 232 | dev->tx_queue_len = 0; |
198 | dev->priv_flags = IFF_EBRIDGE; | 233 | dev->priv_flags = IFF_EBRIDGE; |
diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c index d61e6f741125..8dbec83e50ca 100644 --- a/net/bridge/br_forward.c +++ b/net/bridge/br_forward.c | |||
@@ -19,6 +19,11 @@ | |||
19 | #include <linux/netfilter_bridge.h> | 19 | #include <linux/netfilter_bridge.h> |
20 | #include "br_private.h" | 20 | #include "br_private.h" |
21 | 21 | ||
22 | static int deliver_clone(const struct net_bridge_port *prev, | ||
23 | struct sk_buff *skb, | ||
24 | void (*__packet_hook)(const struct net_bridge_port *p, | ||
25 | struct sk_buff *skb)); | ||
26 | |||
22 | /* Don't forward packets to originating port or forwarding diasabled */ | 27 | /* Don't forward packets to originating port or forwarding diasabled */ |
23 | static inline int should_deliver(const struct net_bridge_port *p, | 28 | static inline int should_deliver(const struct net_bridge_port *p, |
24 | const struct sk_buff *skb) | 29 | const struct sk_buff *skb) |
@@ -94,17 +99,22 @@ void br_deliver(const struct net_bridge_port *to, struct sk_buff *skb) | |||
94 | } | 99 | } |
95 | 100 | ||
96 | /* called with rcu_read_lock */ | 101 | /* called with rcu_read_lock */ |
97 | void br_forward(const struct net_bridge_port *to, struct sk_buff *skb) | 102 | void br_forward(const struct net_bridge_port *to, struct sk_buff *skb, struct sk_buff *skb0) |
98 | { | 103 | { |
99 | if (should_deliver(to, skb)) { | 104 | if (should_deliver(to, skb)) { |
100 | __br_forward(to, skb); | 105 | if (skb0) |
106 | deliver_clone(to, skb, __br_forward); | ||
107 | else | ||
108 | __br_forward(to, skb); | ||
101 | return; | 109 | return; |
102 | } | 110 | } |
103 | 111 | ||
104 | kfree_skb(skb); | 112 | if (!skb0) |
113 | kfree_skb(skb); | ||
105 | } | 114 | } |
106 | 115 | ||
107 | static int deliver_clone(struct net_bridge_port *prev, struct sk_buff *skb, | 116 | static int deliver_clone(const struct net_bridge_port *prev, |
117 | struct sk_buff *skb, | ||
108 | void (*__packet_hook)(const struct net_bridge_port *p, | 118 | void (*__packet_hook)(const struct net_bridge_port *p, |
109 | struct sk_buff *skb)) | 119 | struct sk_buff *skb)) |
110 | { | 120 | { |
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index b6a3872f5681..b7cdd2e98050 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c | |||
@@ -185,6 +185,12 @@ static struct net_device *new_bridge_dev(struct net *net, const char *name) | |||
185 | br = netdev_priv(dev); | 185 | br = netdev_priv(dev); |
186 | br->dev = dev; | 186 | br->dev = dev; |
187 | 187 | ||
188 | br->stats = alloc_percpu(struct br_cpu_netstats); | ||
189 | if (!br->stats) { | ||
190 | free_netdev(dev); | ||
191 | return NULL; | ||
192 | } | ||
193 | |||
188 | spin_lock_init(&br->lock); | 194 | spin_lock_init(&br->lock); |
189 | INIT_LIST_HEAD(&br->port_list); | 195 | INIT_LIST_HEAD(&br->port_list); |
190 | spin_lock_init(&br->hash_lock); | 196 | spin_lock_init(&br->hash_lock); |
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c index 53b39851d87d..333dfb7c5886 100644 --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c | |||
@@ -23,9 +23,11 @@ const u8 br_group_address[ETH_ALEN] = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 }; | |||
23 | static int br_pass_frame_up(struct sk_buff *skb) | 23 | static int br_pass_frame_up(struct sk_buff *skb) |
24 | { | 24 | { |
25 | struct net_device *indev, *brdev = BR_INPUT_SKB_CB(skb)->brdev; | 25 | struct net_device *indev, *brdev = BR_INPUT_SKB_CB(skb)->brdev; |
26 | struct net_bridge *br = netdev_priv(brdev); | ||
27 | struct br_cpu_netstats *brstats = this_cpu_ptr(br->stats); | ||
26 | 28 | ||
27 | brdev->stats.rx_packets++; | 29 | brstats->rx_packets++; |
28 | brdev->stats.rx_bytes += skb->len; | 30 | brstats->rx_bytes += skb->len; |
29 | 31 | ||
30 | indev = skb->dev; | 32 | indev = skb->dev; |
31 | skb->dev = brdev; | 33 | skb->dev = brdev; |
@@ -70,7 +72,7 @@ int br_handle_frame_finish(struct sk_buff *skb) | |||
70 | 72 | ||
71 | if (is_multicast_ether_addr(dest)) { | 73 | if (is_multicast_ether_addr(dest)) { |
72 | mdst = br_mdb_get(br, skb); | 74 | mdst = br_mdb_get(br, skb); |
73 | if (mdst || BR_INPUT_SKB_CB(skb)->mrouters_only) { | 75 | if (mdst || BR_INPUT_SKB_CB_MROUTERS_ONLY(skb)) { |
74 | if ((mdst && !hlist_unhashed(&mdst->mglist)) || | 76 | if ((mdst && !hlist_unhashed(&mdst->mglist)) || |
75 | br_multicast_is_router(br)) | 77 | br_multicast_is_router(br)) |
76 | skb2 = skb; | 78 | skb2 = skb; |
@@ -90,7 +92,7 @@ int br_handle_frame_finish(struct sk_buff *skb) | |||
90 | 92 | ||
91 | if (skb) { | 93 | if (skb) { |
92 | if (dst) | 94 | if (dst) |
93 | br_forward(dst->dst, skb); | 95 | br_forward(dst->dst, skb, skb2); |
94 | else | 96 | else |
95 | br_flood_forward(br, skb, skb2); | 97 | br_flood_forward(br, skb, skb2); |
96 | } | 98 | } |
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 2559fb539836..9f0c4f065604 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c | |||
@@ -38,7 +38,7 @@ static struct net_bridge_mdb_entry *__br_mdb_ip_get( | |||
38 | struct net_bridge_mdb_entry *mp; | 38 | struct net_bridge_mdb_entry *mp; |
39 | struct hlist_node *p; | 39 | struct hlist_node *p; |
40 | 40 | ||
41 | hlist_for_each_entry(mp, p, &mdb->mhash[hash], hlist[mdb->ver]) { | 41 | hlist_for_each_entry_rcu(mp, p, &mdb->mhash[hash], hlist[mdb->ver]) { |
42 | if (dst == mp->addr) | 42 | if (dst == mp->addr) |
43 | return mp; | 43 | return mp; |
44 | } | 44 | } |
@@ -49,22 +49,23 @@ static struct net_bridge_mdb_entry *__br_mdb_ip_get( | |||
49 | static struct net_bridge_mdb_entry *br_mdb_ip_get( | 49 | static struct net_bridge_mdb_entry *br_mdb_ip_get( |
50 | struct net_bridge_mdb_htable *mdb, __be32 dst) | 50 | struct net_bridge_mdb_htable *mdb, __be32 dst) |
51 | { | 51 | { |
52 | if (!mdb) | ||
53 | return NULL; | ||
54 | |||
52 | return __br_mdb_ip_get(mdb, dst, br_ip_hash(mdb, dst)); | 55 | return __br_mdb_ip_get(mdb, dst, br_ip_hash(mdb, dst)); |
53 | } | 56 | } |
54 | 57 | ||
55 | struct net_bridge_mdb_entry *br_mdb_get(struct net_bridge *br, | 58 | struct net_bridge_mdb_entry *br_mdb_get(struct net_bridge *br, |
56 | struct sk_buff *skb) | 59 | struct sk_buff *skb) |
57 | { | 60 | { |
58 | struct net_bridge_mdb_htable *mdb = br->mdb; | 61 | if (br->multicast_disabled) |
59 | |||
60 | if (!mdb || br->multicast_disabled) | ||
61 | return NULL; | 62 | return NULL; |
62 | 63 | ||
63 | switch (skb->protocol) { | 64 | switch (skb->protocol) { |
64 | case htons(ETH_P_IP): | 65 | case htons(ETH_P_IP): |
65 | if (BR_INPUT_SKB_CB(skb)->igmp) | 66 | if (BR_INPUT_SKB_CB(skb)->igmp) |
66 | break; | 67 | break; |
67 | return br_mdb_ip_get(mdb, ip_hdr(skb)->daddr); | 68 | return br_mdb_ip_get(br->mdb, ip_hdr(skb)->daddr); |
68 | } | 69 | } |
69 | 70 | ||
70 | return NULL; | 71 | return NULL; |
@@ -627,8 +628,8 @@ static void br_multicast_port_query_expired(unsigned long data) | |||
627 | struct net_bridge *br = port->br; | 628 | struct net_bridge *br = port->br; |
628 | 629 | ||
629 | spin_lock(&br->multicast_lock); | 630 | spin_lock(&br->multicast_lock); |
630 | if (port && (port->state == BR_STATE_DISABLED || | 631 | if (port->state == BR_STATE_DISABLED || |
631 | port->state == BR_STATE_BLOCKING)) | 632 | port->state == BR_STATE_BLOCKING) |
632 | goto out; | 633 | goto out; |
633 | 634 | ||
634 | if (port->multicast_startup_queries_sent < | 635 | if (port->multicast_startup_queries_sent < |
@@ -823,6 +824,7 @@ static int br_multicast_query(struct net_bridge *br, | |||
823 | unsigned long max_delay; | 824 | unsigned long max_delay; |
824 | unsigned long now = jiffies; | 825 | unsigned long now = jiffies; |
825 | __be32 group; | 826 | __be32 group; |
827 | int err = 0; | ||
826 | 828 | ||
827 | spin_lock(&br->multicast_lock); | 829 | spin_lock(&br->multicast_lock); |
828 | if (!netif_running(br->dev) || | 830 | if (!netif_running(br->dev) || |
@@ -841,15 +843,17 @@ static int br_multicast_query(struct net_bridge *br, | |||
841 | group = 0; | 843 | group = 0; |
842 | } | 844 | } |
843 | } else { | 845 | } else { |
844 | if (!pskb_may_pull(skb, sizeof(struct igmpv3_query))) | 846 | if (!pskb_may_pull(skb, sizeof(struct igmpv3_query))) { |
845 | return -EINVAL; | 847 | err = -EINVAL; |
848 | goto out; | ||
849 | } | ||
846 | 850 | ||
847 | ih3 = igmpv3_query_hdr(skb); | 851 | ih3 = igmpv3_query_hdr(skb); |
848 | if (ih3->nsrcs) | 852 | if (ih3->nsrcs) |
849 | return 0; | 853 | goto out; |
850 | 854 | ||
851 | max_delay = ih3->code ? 1 : | 855 | max_delay = ih3->code ? |
852 | IGMPV3_MRC(ih3->code) * (HZ / IGMP_TIMER_SCALE); | 856 | IGMPV3_MRC(ih3->code) * (HZ / IGMP_TIMER_SCALE) : 1; |
853 | } | 857 | } |
854 | 858 | ||
855 | if (!group) | 859 | if (!group) |
@@ -876,7 +880,7 @@ static int br_multicast_query(struct net_bridge *br, | |||
876 | 880 | ||
877 | out: | 881 | out: |
878 | spin_unlock(&br->multicast_lock); | 882 | spin_unlock(&br->multicast_lock); |
879 | return 0; | 883 | return err; |
880 | } | 884 | } |
881 | 885 | ||
882 | static void br_multicast_leave_group(struct net_bridge *br, | 886 | static void br_multicast_leave_group(struct net_bridge *br, |
@@ -987,7 +991,7 @@ static int br_multicast_ipv4_rcv(struct net_bridge *br, | |||
987 | 991 | ||
988 | err = pskb_trim_rcsum(skb2, len); | 992 | err = pskb_trim_rcsum(skb2, len); |
989 | if (err) | 993 | if (err) |
990 | return err; | 994 | goto err_out; |
991 | } | 995 | } |
992 | 996 | ||
993 | len -= ip_hdrlen(skb2); | 997 | len -= ip_hdrlen(skb2); |
@@ -999,8 +1003,6 @@ static int br_multicast_ipv4_rcv(struct net_bridge *br, | |||
999 | if (!pskb_may_pull(skb2, sizeof(*ih))) | 1003 | if (!pskb_may_pull(skb2, sizeof(*ih))) |
1000 | goto out; | 1004 | goto out; |
1001 | 1005 | ||
1002 | iph = ip_hdr(skb2); | ||
1003 | |||
1004 | switch (skb2->ip_summed) { | 1006 | switch (skb2->ip_summed) { |
1005 | case CHECKSUM_COMPLETE: | 1007 | case CHECKSUM_COMPLETE: |
1006 | if (!csum_fold(skb2->csum)) | 1008 | if (!csum_fold(skb2->csum)) |
@@ -1009,7 +1011,7 @@ static int br_multicast_ipv4_rcv(struct net_bridge *br, | |||
1009 | case CHECKSUM_NONE: | 1011 | case CHECKSUM_NONE: |
1010 | skb2->csum = 0; | 1012 | skb2->csum = 0; |
1011 | if (skb_checksum_complete(skb2)) | 1013 | if (skb_checksum_complete(skb2)) |
1012 | return -EINVAL; | 1014 | goto out; |
1013 | } | 1015 | } |
1014 | 1016 | ||
1015 | err = 0; | 1017 | err = 0; |
@@ -1036,6 +1038,7 @@ static int br_multicast_ipv4_rcv(struct net_bridge *br, | |||
1036 | 1038 | ||
1037 | out: | 1039 | out: |
1038 | __skb_push(skb2, offset); | 1040 | __skb_push(skb2, offset); |
1041 | err_out: | ||
1039 | if (skb2 != skb) | 1042 | if (skb2 != skb) |
1040 | kfree_skb(skb2); | 1043 | kfree_skb(skb2); |
1041 | return err; | 1044 | return err; |
@@ -1135,7 +1138,7 @@ void br_multicast_stop(struct net_bridge *br) | |||
1135 | 1138 | ||
1136 | if (mdb->old) { | 1139 | if (mdb->old) { |
1137 | spin_unlock_bh(&br->multicast_lock); | 1140 | spin_unlock_bh(&br->multicast_lock); |
1138 | synchronize_rcu_bh(); | 1141 | rcu_barrier_bh(); |
1139 | spin_lock_bh(&br->multicast_lock); | 1142 | spin_lock_bh(&br->multicast_lock); |
1140 | WARN_ON(mdb->old); | 1143 | WARN_ON(mdb->old); |
1141 | } | 1144 | } |
diff --git a/net/bridge/br_notify.c b/net/bridge/br_notify.c index 763a3ec292e5..1413b72acc7f 100644 --- a/net/bridge/br_notify.c +++ b/net/bridge/br_notify.c | |||
@@ -82,6 +82,10 @@ static int br_device_event(struct notifier_block *unused, unsigned long event, v | |||
82 | case NETDEV_UNREGISTER: | 82 | case NETDEV_UNREGISTER: |
83 | br_del_if(br, dev); | 83 | br_del_if(br, dev); |
84 | break; | 84 | break; |
85 | |||
86 | case NETDEV_PRE_TYPE_CHANGE: | ||
87 | /* Forbid underlaying device to change its type. */ | ||
88 | return NOTIFY_BAD; | ||
85 | } | 89 | } |
86 | 90 | ||
87 | /* Events that may cause spanning tree to refresh */ | 91 | /* Events that may cause spanning tree to refresh */ |
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 1cf2cef78584..791d4ab0fd4d 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h | |||
@@ -135,6 +135,14 @@ struct net_bridge | |||
135 | spinlock_t lock; | 135 | spinlock_t lock; |
136 | struct list_head port_list; | 136 | struct list_head port_list; |
137 | struct net_device *dev; | 137 | struct net_device *dev; |
138 | |||
139 | struct br_cpu_netstats __percpu { | ||
140 | unsigned long rx_packets; | ||
141 | unsigned long rx_bytes; | ||
142 | unsigned long tx_packets; | ||
143 | unsigned long tx_bytes; | ||
144 | } *stats; | ||
145 | |||
138 | spinlock_t hash_lock; | 146 | spinlock_t hash_lock; |
139 | struct hlist_head hash[BR_HASH_SIZE]; | 147 | struct hlist_head hash[BR_HASH_SIZE]; |
140 | unsigned long feature_mask; | 148 | unsigned long feature_mask; |
@@ -206,12 +214,20 @@ struct net_bridge | |||
206 | 214 | ||
207 | struct br_input_skb_cb { | 215 | struct br_input_skb_cb { |
208 | struct net_device *brdev; | 216 | struct net_device *brdev; |
217 | #ifdef CONFIG_BRIDGE_IGMP_SNOOPING | ||
209 | int igmp; | 218 | int igmp; |
210 | int mrouters_only; | 219 | int mrouters_only; |
220 | #endif | ||
211 | }; | 221 | }; |
212 | 222 | ||
213 | #define BR_INPUT_SKB_CB(__skb) ((struct br_input_skb_cb *)(__skb)->cb) | 223 | #define BR_INPUT_SKB_CB(__skb) ((struct br_input_skb_cb *)(__skb)->cb) |
214 | 224 | ||
225 | #ifdef CONFIG_BRIDGE_IGMP_SNOOPING | ||
226 | # define BR_INPUT_SKB_CB_MROUTERS_ONLY(__skb) (BR_INPUT_SKB_CB(__skb)->mrouters_only) | ||
227 | #else | ||
228 | # define BR_INPUT_SKB_CB_MROUTERS_ONLY(__skb) (0) | ||
229 | #endif | ||
230 | |||
215 | extern struct notifier_block br_device_notifier; | 231 | extern struct notifier_block br_device_notifier; |
216 | extern const u8 br_group_address[ETH_ALEN]; | 232 | extern const u8 br_group_address[ETH_ALEN]; |
217 | 233 | ||
@@ -252,7 +268,7 @@ extern void br_deliver(const struct net_bridge_port *to, | |||
252 | struct sk_buff *skb); | 268 | struct sk_buff *skb); |
253 | extern int br_dev_queue_push_xmit(struct sk_buff *skb); | 269 | extern int br_dev_queue_push_xmit(struct sk_buff *skb); |
254 | extern void br_forward(const struct net_bridge_port *to, | 270 | extern void br_forward(const struct net_bridge_port *to, |
255 | struct sk_buff *skb); | 271 | struct sk_buff *skb, struct sk_buff *skb0); |
256 | extern int br_forward_finish(struct sk_buff *skb); | 272 | extern int br_forward_finish(struct sk_buff *skb); |
257 | extern void br_flood_deliver(struct net_bridge *br, struct sk_buff *skb); | 273 | extern void br_flood_deliver(struct net_bridge *br, struct sk_buff *skb); |
258 | extern void br_flood_forward(struct net_bridge *br, struct sk_buff *skb, | 274 | extern void br_flood_forward(struct net_bridge *br, struct sk_buff *skb, |
@@ -423,7 +439,7 @@ extern void br_ifinfo_notify(int event, struct net_bridge_port *port); | |||
423 | 439 | ||
424 | #ifdef CONFIG_SYSFS | 440 | #ifdef CONFIG_SYSFS |
425 | /* br_sysfs_if.c */ | 441 | /* br_sysfs_if.c */ |
426 | extern struct sysfs_ops brport_sysfs_ops; | 442 | extern const struct sysfs_ops brport_sysfs_ops; |
427 | extern int br_sysfs_addif(struct net_bridge_port *p); | 443 | extern int br_sysfs_addif(struct net_bridge_port *p); |
428 | 444 | ||
429 | /* br_sysfs_br.c */ | 445 | /* br_sysfs_br.c */ |
diff --git a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c index 696596cd3384..0b9916489d6b 100644 --- a/net/bridge/br_sysfs_if.c +++ b/net/bridge/br_sysfs_if.c | |||
@@ -238,7 +238,7 @@ static ssize_t brport_store(struct kobject * kobj, | |||
238 | return ret; | 238 | return ret; |
239 | } | 239 | } |
240 | 240 | ||
241 | struct sysfs_ops brport_sysfs_ops = { | 241 | const struct sysfs_ops brport_sysfs_ops = { |
242 | .show = brport_show, | 242 | .show = brport_show, |
243 | .store = brport_store, | 243 | .store = brport_store, |
244 | }; | 244 | }; |
diff --git a/net/core/dev.c b/net/core/dev.c index bcc490cc9452..887aa84fcd46 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -772,14 +772,17 @@ EXPORT_SYMBOL(__dev_getfirstbyhwtype); | |||
772 | 772 | ||
773 | struct net_device *dev_getfirstbyhwtype(struct net *net, unsigned short type) | 773 | struct net_device *dev_getfirstbyhwtype(struct net *net, unsigned short type) |
774 | { | 774 | { |
775 | struct net_device *dev; | 775 | struct net_device *dev, *ret = NULL; |
776 | 776 | ||
777 | rtnl_lock(); | 777 | rcu_read_lock(); |
778 | dev = __dev_getfirstbyhwtype(net, type); | 778 | for_each_netdev_rcu(net, dev) |
779 | if (dev) | 779 | if (dev->type == type) { |
780 | dev_hold(dev); | 780 | dev_hold(dev); |
781 | rtnl_unlock(); | 781 | ret = dev; |
782 | return dev; | 782 | break; |
783 | } | ||
784 | rcu_read_unlock(); | ||
785 | return ret; | ||
783 | } | 786 | } |
784 | EXPORT_SYMBOL(dev_getfirstbyhwtype); | 787 | EXPORT_SYMBOL(dev_getfirstbyhwtype); |
785 | 788 | ||
@@ -1084,9 +1087,9 @@ void netdev_state_change(struct net_device *dev) | |||
1084 | } | 1087 | } |
1085 | EXPORT_SYMBOL(netdev_state_change); | 1088 | EXPORT_SYMBOL(netdev_state_change); |
1086 | 1089 | ||
1087 | void netdev_bonding_change(struct net_device *dev, unsigned long event) | 1090 | int netdev_bonding_change(struct net_device *dev, unsigned long event) |
1088 | { | 1091 | { |
1089 | call_netdevice_notifiers(event, dev); | 1092 | return call_netdevice_notifiers(event, dev); |
1090 | } | 1093 | } |
1091 | EXPORT_SYMBOL(netdev_bonding_change); | 1094 | EXPORT_SYMBOL(netdev_bonding_change); |
1092 | 1095 | ||
@@ -1931,7 +1934,7 @@ out_kfree_skb: | |||
1931 | return rc; | 1934 | return rc; |
1932 | } | 1935 | } |
1933 | 1936 | ||
1934 | static u32 skb_tx_hashrnd; | 1937 | static u32 hashrnd __read_mostly; |
1935 | 1938 | ||
1936 | u16 skb_tx_hash(const struct net_device *dev, const struct sk_buff *skb) | 1939 | u16 skb_tx_hash(const struct net_device *dev, const struct sk_buff *skb) |
1937 | { | 1940 | { |
@@ -1949,7 +1952,7 @@ u16 skb_tx_hash(const struct net_device *dev, const struct sk_buff *skb) | |||
1949 | else | 1952 | else |
1950 | hash = skb->protocol; | 1953 | hash = skb->protocol; |
1951 | 1954 | ||
1952 | hash = jhash_1word(hash, skb_tx_hashrnd); | 1955 | hash = jhash_1word(hash, hashrnd); |
1953 | 1956 | ||
1954 | return (u16) (((u64) hash * dev->real_num_tx_queues) >> 32); | 1957 | return (u16) (((u64) hash * dev->real_num_tx_queues) >> 32); |
1955 | } | 1958 | } |
@@ -1959,10 +1962,9 @@ static inline u16 dev_cap_txqueue(struct net_device *dev, u16 queue_index) | |||
1959 | { | 1962 | { |
1960 | if (unlikely(queue_index >= dev->real_num_tx_queues)) { | 1963 | if (unlikely(queue_index >= dev->real_num_tx_queues)) { |
1961 | if (net_ratelimit()) { | 1964 | if (net_ratelimit()) { |
1962 | WARN(1, "%s selects TX queue %d, but " | 1965 | netdev_warn(dev, "selects TX queue %d, but " |
1963 | "real number of TX queues is %d\n", | 1966 | "real number of TX queues is %d\n", |
1964 | dev->name, queue_index, | 1967 | queue_index, dev->real_num_tx_queues); |
1965 | dev->real_num_tx_queues); | ||
1966 | } | 1968 | } |
1967 | return 0; | 1969 | return 0; |
1968 | } | 1970 | } |
@@ -2175,6 +2177,178 @@ int weight_p __read_mostly = 64; /* old backlog weight */ | |||
2175 | 2177 | ||
2176 | DEFINE_PER_CPU(struct netif_rx_stats, netdev_rx_stat) = { 0, }; | 2178 | DEFINE_PER_CPU(struct netif_rx_stats, netdev_rx_stat) = { 0, }; |
2177 | 2179 | ||
2180 | #ifdef CONFIG_RPS | ||
2181 | /* | ||
2182 | * get_rps_cpu is called from netif_receive_skb and returns the target | ||
2183 | * CPU from the RPS map of the receiving queue for a given skb. | ||
2184 | */ | ||
2185 | static int get_rps_cpu(struct net_device *dev, struct sk_buff *skb) | ||
2186 | { | ||
2187 | struct ipv6hdr *ip6; | ||
2188 | struct iphdr *ip; | ||
2189 | struct netdev_rx_queue *rxqueue; | ||
2190 | struct rps_map *map; | ||
2191 | int cpu = -1; | ||
2192 | u8 ip_proto; | ||
2193 | u32 addr1, addr2, ports, ihl; | ||
2194 | |||
2195 | rcu_read_lock(); | ||
2196 | |||
2197 | if (skb_rx_queue_recorded(skb)) { | ||
2198 | u16 index = skb_get_rx_queue(skb); | ||
2199 | if (unlikely(index >= dev->num_rx_queues)) { | ||
2200 | if (net_ratelimit()) { | ||
2201 | netdev_warn(dev, "received packet on queue " | ||
2202 | "%u, but number of RX queues is %u\n", | ||
2203 | index, dev->num_rx_queues); | ||
2204 | } | ||
2205 | goto done; | ||
2206 | } | ||
2207 | rxqueue = dev->_rx + index; | ||
2208 | } else | ||
2209 | rxqueue = dev->_rx; | ||
2210 | |||
2211 | if (!rxqueue->rps_map) | ||
2212 | goto done; | ||
2213 | |||
2214 | if (skb->rxhash) | ||
2215 | goto got_hash; /* Skip hash computation on packet header */ | ||
2216 | |||
2217 | switch (skb->protocol) { | ||
2218 | case __constant_htons(ETH_P_IP): | ||
2219 | if (!pskb_may_pull(skb, sizeof(*ip))) | ||
2220 | goto done; | ||
2221 | |||
2222 | ip = (struct iphdr *) skb->data; | ||
2223 | ip_proto = ip->protocol; | ||
2224 | addr1 = ip->saddr; | ||
2225 | addr2 = ip->daddr; | ||
2226 | ihl = ip->ihl; | ||
2227 | break; | ||
2228 | case __constant_htons(ETH_P_IPV6): | ||
2229 | if (!pskb_may_pull(skb, sizeof(*ip6))) | ||
2230 | goto done; | ||
2231 | |||
2232 | ip6 = (struct ipv6hdr *) skb->data; | ||
2233 | ip_proto = ip6->nexthdr; | ||
2234 | addr1 = ip6->saddr.s6_addr32[3]; | ||
2235 | addr2 = ip6->daddr.s6_addr32[3]; | ||
2236 | ihl = (40 >> 2); | ||
2237 | break; | ||
2238 | default: | ||
2239 | goto done; | ||
2240 | } | ||
2241 | ports = 0; | ||
2242 | switch (ip_proto) { | ||
2243 | case IPPROTO_TCP: | ||
2244 | case IPPROTO_UDP: | ||
2245 | case IPPROTO_DCCP: | ||
2246 | case IPPROTO_ESP: | ||
2247 | case IPPROTO_AH: | ||
2248 | case IPPROTO_SCTP: | ||
2249 | case IPPROTO_UDPLITE: | ||
2250 | if (pskb_may_pull(skb, (ihl * 4) + 4)) | ||
2251 | ports = *((u32 *) (skb->data + (ihl * 4))); | ||
2252 | break; | ||
2253 | |||
2254 | default: | ||
2255 | break; | ||
2256 | } | ||
2257 | |||
2258 | skb->rxhash = jhash_3words(addr1, addr2, ports, hashrnd); | ||
2259 | if (!skb->rxhash) | ||
2260 | skb->rxhash = 1; | ||
2261 | |||
2262 | got_hash: | ||
2263 | map = rcu_dereference(rxqueue->rps_map); | ||
2264 | if (map) { | ||
2265 | u16 tcpu = map->cpus[((u64) skb->rxhash * map->len) >> 32]; | ||
2266 | |||
2267 | if (cpu_online(tcpu)) { | ||
2268 | cpu = tcpu; | ||
2269 | goto done; | ||
2270 | } | ||
2271 | } | ||
2272 | |||
2273 | done: | ||
2274 | rcu_read_unlock(); | ||
2275 | return cpu; | ||
2276 | } | ||
2277 | |||
2278 | /* | ||
2279 | * This structure holds the per-CPU mask of CPUs for which IPIs are scheduled | ||
2280 | * to be sent to kick remote softirq processing. There are two masks since | ||
2281 | * the sending of IPIs must be done with interrupts enabled. The select field | ||
2282 | * indicates the current mask that enqueue_backlog uses to schedule IPIs. | ||
2283 | * select is flipped before net_rps_action is called while still under lock, | ||
2284 | * net_rps_action then uses the non-selected mask to send the IPIs and clears | ||
2285 | * it without conflicting with enqueue_backlog operation. | ||
2286 | */ | ||
2287 | struct rps_remote_softirq_cpus { | ||
2288 | cpumask_t mask[2]; | ||
2289 | int select; | ||
2290 | }; | ||
2291 | static DEFINE_PER_CPU(struct rps_remote_softirq_cpus, rps_remote_softirq_cpus); | ||
2292 | |||
2293 | /* Called from hardirq (IPI) context */ | ||
2294 | static void trigger_softirq(void *data) | ||
2295 | { | ||
2296 | struct softnet_data *queue = data; | ||
2297 | __napi_schedule(&queue->backlog); | ||
2298 | __get_cpu_var(netdev_rx_stat).received_rps++; | ||
2299 | } | ||
2300 | #endif /* CONFIG_SMP */ | ||
2301 | |||
2302 | /* | ||
2303 | * enqueue_to_backlog is called to queue an skb to a per CPU backlog | ||
2304 | * queue (may be a remote CPU queue). | ||
2305 | */ | ||
2306 | static int enqueue_to_backlog(struct sk_buff *skb, int cpu) | ||
2307 | { | ||
2308 | struct softnet_data *queue; | ||
2309 | unsigned long flags; | ||
2310 | |||
2311 | queue = &per_cpu(softnet_data, cpu); | ||
2312 | |||
2313 | local_irq_save(flags); | ||
2314 | __get_cpu_var(netdev_rx_stat).total++; | ||
2315 | |||
2316 | spin_lock(&queue->input_pkt_queue.lock); | ||
2317 | if (queue->input_pkt_queue.qlen <= netdev_max_backlog) { | ||
2318 | if (queue->input_pkt_queue.qlen) { | ||
2319 | enqueue: | ||
2320 | __skb_queue_tail(&queue->input_pkt_queue, skb); | ||
2321 | spin_unlock_irqrestore(&queue->input_pkt_queue.lock, | ||
2322 | flags); | ||
2323 | return NET_RX_SUCCESS; | ||
2324 | } | ||
2325 | |||
2326 | /* Schedule NAPI for backlog device */ | ||
2327 | if (napi_schedule_prep(&queue->backlog)) { | ||
2328 | #ifdef CONFIG_RPS | ||
2329 | if (cpu != smp_processor_id()) { | ||
2330 | struct rps_remote_softirq_cpus *rcpus = | ||
2331 | &__get_cpu_var(rps_remote_softirq_cpus); | ||
2332 | |||
2333 | cpu_set(cpu, rcpus->mask[rcpus->select]); | ||
2334 | __raise_softirq_irqoff(NET_RX_SOFTIRQ); | ||
2335 | } else | ||
2336 | __napi_schedule(&queue->backlog); | ||
2337 | #else | ||
2338 | __napi_schedule(&queue->backlog); | ||
2339 | #endif | ||
2340 | } | ||
2341 | goto enqueue; | ||
2342 | } | ||
2343 | |||
2344 | spin_unlock(&queue->input_pkt_queue.lock); | ||
2345 | |||
2346 | __get_cpu_var(netdev_rx_stat).dropped++; | ||
2347 | local_irq_restore(flags); | ||
2348 | |||
2349 | kfree_skb(skb); | ||
2350 | return NET_RX_DROP; | ||
2351 | } | ||
2178 | 2352 | ||
2179 | /** | 2353 | /** |
2180 | * netif_rx - post buffer to the network code | 2354 | * netif_rx - post buffer to the network code |
@@ -2193,8 +2367,7 @@ DEFINE_PER_CPU(struct netif_rx_stats, netdev_rx_stat) = { 0, }; | |||
2193 | 2367 | ||
2194 | int netif_rx(struct sk_buff *skb) | 2368 | int netif_rx(struct sk_buff *skb) |
2195 | { | 2369 | { |
2196 | struct softnet_data *queue; | 2370 | int cpu; |
2197 | unsigned long flags; | ||
2198 | 2371 | ||
2199 | /* if netpoll wants it, pretend we never saw it */ | 2372 | /* if netpoll wants it, pretend we never saw it */ |
2200 | if (netpoll_rx(skb)) | 2373 | if (netpoll_rx(skb)) |
@@ -2203,31 +2376,15 @@ int netif_rx(struct sk_buff *skb) | |||
2203 | if (!skb->tstamp.tv64) | 2376 | if (!skb->tstamp.tv64) |
2204 | net_timestamp(skb); | 2377 | net_timestamp(skb); |
2205 | 2378 | ||
2206 | /* | 2379 | #ifdef CONFIG_RPS |
2207 | * The code is rearranged so that the path is the most | 2380 | cpu = get_rps_cpu(skb->dev, skb); |
2208 | * short when CPU is congested, but is still operating. | 2381 | if (cpu < 0) |
2209 | */ | 2382 | cpu = smp_processor_id(); |
2210 | local_irq_save(flags); | 2383 | #else |
2211 | queue = &__get_cpu_var(softnet_data); | 2384 | cpu = smp_processor_id(); |
2212 | 2385 | #endif | |
2213 | __get_cpu_var(netdev_rx_stat).total++; | ||
2214 | if (queue->input_pkt_queue.qlen <= netdev_max_backlog) { | ||
2215 | if (queue->input_pkt_queue.qlen) { | ||
2216 | enqueue: | ||
2217 | __skb_queue_tail(&queue->input_pkt_queue, skb); | ||
2218 | local_irq_restore(flags); | ||
2219 | return NET_RX_SUCCESS; | ||
2220 | } | ||
2221 | |||
2222 | napi_schedule(&queue->backlog); | ||
2223 | goto enqueue; | ||
2224 | } | ||
2225 | |||
2226 | __get_cpu_var(netdev_rx_stat).dropped++; | ||
2227 | local_irq_restore(flags); | ||
2228 | 2386 | ||
2229 | kfree_skb(skb); | 2387 | return enqueue_to_backlog(skb, cpu); |
2230 | return NET_RX_DROP; | ||
2231 | } | 2388 | } |
2232 | EXPORT_SYMBOL(netif_rx); | 2389 | EXPORT_SYMBOL(netif_rx); |
2233 | 2390 | ||
@@ -2464,25 +2621,11 @@ void netif_nit_deliver(struct sk_buff *skb) | |||
2464 | rcu_read_unlock(); | 2621 | rcu_read_unlock(); |
2465 | } | 2622 | } |
2466 | 2623 | ||
2467 | /** | 2624 | static int __netif_receive_skb(struct sk_buff *skb) |
2468 | * netif_receive_skb - process receive buffer from network | ||
2469 | * @skb: buffer to process | ||
2470 | * | ||
2471 | * netif_receive_skb() is the main receive data processing function. | ||
2472 | * It always succeeds. The buffer may be dropped during processing | ||
2473 | * for congestion control or by the protocol layers. | ||
2474 | * | ||
2475 | * This function may only be called from softirq context and interrupts | ||
2476 | * should be enabled. | ||
2477 | * | ||
2478 | * Return values (usually ignored): | ||
2479 | * NET_RX_SUCCESS: no congestion | ||
2480 | * NET_RX_DROP: packet was dropped | ||
2481 | */ | ||
2482 | int netif_receive_skb(struct sk_buff *skb) | ||
2483 | { | 2625 | { |
2484 | struct packet_type *ptype, *pt_prev; | 2626 | struct packet_type *ptype, *pt_prev; |
2485 | struct net_device *orig_dev; | 2627 | struct net_device *orig_dev; |
2628 | struct net_device *master; | ||
2486 | struct net_device *null_or_orig; | 2629 | struct net_device *null_or_orig; |
2487 | struct net_device *null_or_bond; | 2630 | struct net_device *null_or_bond; |
2488 | int ret = NET_RX_DROP; | 2631 | int ret = NET_RX_DROP; |
@@ -2503,11 +2646,12 @@ int netif_receive_skb(struct sk_buff *skb) | |||
2503 | 2646 | ||
2504 | null_or_orig = NULL; | 2647 | null_or_orig = NULL; |
2505 | orig_dev = skb->dev; | 2648 | orig_dev = skb->dev; |
2506 | if (orig_dev->master) { | 2649 | master = ACCESS_ONCE(orig_dev->master); |
2507 | if (skb_bond_should_drop(skb)) | 2650 | if (master) { |
2651 | if (skb_bond_should_drop(skb, master)) | ||
2508 | null_or_orig = orig_dev; /* deliver only exact match */ | 2652 | null_or_orig = orig_dev; /* deliver only exact match */ |
2509 | else | 2653 | else |
2510 | skb->dev = orig_dev->master; | 2654 | skb->dev = master; |
2511 | } | 2655 | } |
2512 | 2656 | ||
2513 | __get_cpu_var(netdev_rx_stat).total++; | 2657 | __get_cpu_var(netdev_rx_stat).total++; |
@@ -2588,20 +2732,53 @@ out: | |||
2588 | rcu_read_unlock(); | 2732 | rcu_read_unlock(); |
2589 | return ret; | 2733 | return ret; |
2590 | } | 2734 | } |
2735 | |||
2736 | /** | ||
2737 | * netif_receive_skb - process receive buffer from network | ||
2738 | * @skb: buffer to process | ||
2739 | * | ||
2740 | * netif_receive_skb() is the main receive data processing function. | ||
2741 | * It always succeeds. The buffer may be dropped during processing | ||
2742 | * for congestion control or by the protocol layers. | ||
2743 | * | ||
2744 | * This function may only be called from softirq context and interrupts | ||
2745 | * should be enabled. | ||
2746 | * | ||
2747 | * Return values (usually ignored): | ||
2748 | * NET_RX_SUCCESS: no congestion | ||
2749 | * NET_RX_DROP: packet was dropped | ||
2750 | */ | ||
2751 | int netif_receive_skb(struct sk_buff *skb) | ||
2752 | { | ||
2753 | #ifdef CONFIG_RPS | ||
2754 | int cpu; | ||
2755 | |||
2756 | cpu = get_rps_cpu(skb->dev, skb); | ||
2757 | |||
2758 | if (cpu < 0) | ||
2759 | return __netif_receive_skb(skb); | ||
2760 | else | ||
2761 | return enqueue_to_backlog(skb, cpu); | ||
2762 | #else | ||
2763 | return __netif_receive_skb(skb); | ||
2764 | #endif | ||
2765 | } | ||
2591 | EXPORT_SYMBOL(netif_receive_skb); | 2766 | EXPORT_SYMBOL(netif_receive_skb); |
2592 | 2767 | ||
2593 | /* Network device is going away, flush any packets still pending */ | 2768 | /* Network device is going away, flush any packets still pending */ |
2594 | static void flush_backlog(void *arg) | 2769 | static void flush_backlog(struct net_device *dev, int cpu) |
2595 | { | 2770 | { |
2596 | struct net_device *dev = arg; | 2771 | struct softnet_data *queue = &per_cpu(softnet_data, cpu); |
2597 | struct softnet_data *queue = &__get_cpu_var(softnet_data); | ||
2598 | struct sk_buff *skb, *tmp; | 2772 | struct sk_buff *skb, *tmp; |
2773 | unsigned long flags; | ||
2599 | 2774 | ||
2775 | spin_lock_irqsave(&queue->input_pkt_queue.lock, flags); | ||
2600 | skb_queue_walk_safe(&queue->input_pkt_queue, skb, tmp) | 2776 | skb_queue_walk_safe(&queue->input_pkt_queue, skb, tmp) |
2601 | if (skb->dev == dev) { | 2777 | if (skb->dev == dev) { |
2602 | __skb_unlink(skb, &queue->input_pkt_queue); | 2778 | __skb_unlink(skb, &queue->input_pkt_queue); |
2603 | kfree_skb(skb); | 2779 | kfree_skb(skb); |
2604 | } | 2780 | } |
2781 | spin_unlock_irqrestore(&queue->input_pkt_queue.lock, flags); | ||
2605 | } | 2782 | } |
2606 | 2783 | ||
2607 | static int napi_gro_complete(struct sk_buff *skb) | 2784 | static int napi_gro_complete(struct sk_buff *skb) |
@@ -2914,16 +3091,16 @@ static int process_backlog(struct napi_struct *napi, int quota) | |||
2914 | do { | 3091 | do { |
2915 | struct sk_buff *skb; | 3092 | struct sk_buff *skb; |
2916 | 3093 | ||
2917 | local_irq_disable(); | 3094 | spin_lock_irq(&queue->input_pkt_queue.lock); |
2918 | skb = __skb_dequeue(&queue->input_pkt_queue); | 3095 | skb = __skb_dequeue(&queue->input_pkt_queue); |
2919 | if (!skb) { | 3096 | if (!skb) { |
2920 | __napi_complete(napi); | 3097 | __napi_complete(napi); |
2921 | local_irq_enable(); | 3098 | spin_unlock_irq(&queue->input_pkt_queue.lock); |
2922 | break; | 3099 | break; |
2923 | } | 3100 | } |
2924 | local_irq_enable(); | 3101 | spin_unlock_irq(&queue->input_pkt_queue.lock); |
2925 | 3102 | ||
2926 | netif_receive_skb(skb); | 3103 | __netif_receive_skb(skb); |
2927 | } while (++work < quota && jiffies == start_time); | 3104 | } while (++work < quota && jiffies == start_time); |
2928 | 3105 | ||
2929 | return work; | 3106 | return work; |
@@ -3012,6 +3189,24 @@ void netif_napi_del(struct napi_struct *napi) | |||
3012 | } | 3189 | } |
3013 | EXPORT_SYMBOL(netif_napi_del); | 3190 | EXPORT_SYMBOL(netif_napi_del); |
3014 | 3191 | ||
3192 | #ifdef CONFIG_RPS | ||
3193 | /* | ||
3194 | * net_rps_action sends any pending IPI's for rps. This is only called from | ||
3195 | * softirq and interrupts must be enabled. | ||
3196 | */ | ||
3197 | static void net_rps_action(cpumask_t *mask) | ||
3198 | { | ||
3199 | int cpu; | ||
3200 | |||
3201 | /* Send pending IPI's to kick RPS processing on remote cpus. */ | ||
3202 | for_each_cpu_mask_nr(cpu, *mask) { | ||
3203 | struct softnet_data *queue = &per_cpu(softnet_data, cpu); | ||
3204 | if (cpu_online(cpu)) | ||
3205 | __smp_call_function_single(cpu, &queue->csd, 0); | ||
3206 | } | ||
3207 | cpus_clear(*mask); | ||
3208 | } | ||
3209 | #endif | ||
3015 | 3210 | ||
3016 | static void net_rx_action(struct softirq_action *h) | 3211 | static void net_rx_action(struct softirq_action *h) |
3017 | { | 3212 | { |
@@ -3019,6 +3214,10 @@ static void net_rx_action(struct softirq_action *h) | |||
3019 | unsigned long time_limit = jiffies + 2; | 3214 | unsigned long time_limit = jiffies + 2; |
3020 | int budget = netdev_budget; | 3215 | int budget = netdev_budget; |
3021 | void *have; | 3216 | void *have; |
3217 | #ifdef CONFIG_RPS | ||
3218 | int select; | ||
3219 | struct rps_remote_softirq_cpus *rcpus; | ||
3220 | #endif | ||
3022 | 3221 | ||
3023 | local_irq_disable(); | 3222 | local_irq_disable(); |
3024 | 3223 | ||
@@ -3081,7 +3280,17 @@ static void net_rx_action(struct softirq_action *h) | |||
3081 | netpoll_poll_unlock(have); | 3280 | netpoll_poll_unlock(have); |
3082 | } | 3281 | } |
3083 | out: | 3282 | out: |
3283 | #ifdef CONFIG_RPS | ||
3284 | rcpus = &__get_cpu_var(rps_remote_softirq_cpus); | ||
3285 | select = rcpus->select; | ||
3286 | rcpus->select ^= 1; | ||
3287 | |||
3288 | local_irq_enable(); | ||
3289 | |||
3290 | net_rps_action(&rcpus->mask[select]); | ||
3291 | #else | ||
3084 | local_irq_enable(); | 3292 | local_irq_enable(); |
3293 | #endif | ||
3085 | 3294 | ||
3086 | #ifdef CONFIG_NET_DMA | 3295 | #ifdef CONFIG_NET_DMA |
3087 | /* | 3296 | /* |
@@ -3327,10 +3536,10 @@ static int softnet_seq_show(struct seq_file *seq, void *v) | |||
3327 | { | 3536 | { |
3328 | struct netif_rx_stats *s = v; | 3537 | struct netif_rx_stats *s = v; |
3329 | 3538 | ||
3330 | seq_printf(seq, "%08x %08x %08x %08x %08x %08x %08x %08x %08x\n", | 3539 | seq_printf(seq, "%08x %08x %08x %08x %08x %08x %08x %08x %08x %08x\n", |
3331 | s->total, s->dropped, s->time_squeeze, 0, | 3540 | s->total, s->dropped, s->time_squeeze, 0, |
3332 | 0, 0, 0, 0, /* was fastroute */ | 3541 | 0, 0, 0, 0, /* was fastroute */ |
3333 | s->cpu_collision); | 3542 | s->cpu_collision, s->received_rps); |
3334 | return 0; | 3543 | return 0; |
3335 | } | 3544 | } |
3336 | 3545 | ||
@@ -3553,11 +3762,10 @@ int netdev_set_master(struct net_device *slave, struct net_device *master) | |||
3553 | 3762 | ||
3554 | slave->master = master; | 3763 | slave->master = master; |
3555 | 3764 | ||
3556 | synchronize_net(); | 3765 | if (old) { |
3557 | 3766 | synchronize_net(); | |
3558 | if (old) | ||
3559 | dev_put(old); | 3767 | dev_put(old); |
3560 | 3768 | } | |
3561 | if (master) | 3769 | if (master) |
3562 | slave->flags |= IFF_SLAVE; | 3770 | slave->flags |= IFF_SLAVE; |
3563 | else | 3771 | else |
@@ -4253,12 +4461,13 @@ void dev_unicast_unsync(struct net_device *to, struct net_device *from) | |||
4253 | } | 4461 | } |
4254 | EXPORT_SYMBOL(dev_unicast_unsync); | 4462 | EXPORT_SYMBOL(dev_unicast_unsync); |
4255 | 4463 | ||
4256 | static void dev_unicast_flush(struct net_device *dev) | 4464 | void dev_unicast_flush(struct net_device *dev) |
4257 | { | 4465 | { |
4258 | netif_addr_lock_bh(dev); | 4466 | netif_addr_lock_bh(dev); |
4259 | __hw_addr_flush(&dev->uc); | 4467 | __hw_addr_flush(&dev->uc); |
4260 | netif_addr_unlock_bh(dev); | 4468 | netif_addr_unlock_bh(dev); |
4261 | } | 4469 | } |
4470 | EXPORT_SYMBOL(dev_unicast_flush); | ||
4262 | 4471 | ||
4263 | static void dev_unicast_init(struct net_device *dev) | 4472 | static void dev_unicast_init(struct net_device *dev) |
4264 | { | 4473 | { |
@@ -4280,7 +4489,7 @@ static void __dev_addr_discard(struct dev_addr_list **list) | |||
4280 | } | 4489 | } |
4281 | } | 4490 | } |
4282 | 4491 | ||
4283 | static void dev_addr_discard(struct net_device *dev) | 4492 | void dev_addr_discard(struct net_device *dev) |
4284 | { | 4493 | { |
4285 | netif_addr_lock_bh(dev); | 4494 | netif_addr_lock_bh(dev); |
4286 | 4495 | ||
@@ -4289,6 +4498,7 @@ static void dev_addr_discard(struct net_device *dev) | |||
4289 | 4498 | ||
4290 | netif_addr_unlock_bh(dev); | 4499 | netif_addr_unlock_bh(dev); |
4291 | } | 4500 | } |
4501 | EXPORT_SYMBOL(dev_addr_discard); | ||
4292 | 4502 | ||
4293 | /** | 4503 | /** |
4294 | * dev_get_flags - get flags reported to userspace | 4504 | * dev_get_flags - get flags reported to userspace |
@@ -5067,6 +5277,24 @@ int register_netdevice(struct net_device *dev) | |||
5067 | 5277 | ||
5068 | dev->iflink = -1; | 5278 | dev->iflink = -1; |
5069 | 5279 | ||
5280 | #ifdef CONFIG_RPS | ||
5281 | if (!dev->num_rx_queues) { | ||
5282 | /* | ||
5283 | * Allocate a single RX queue if driver never called | ||
5284 | * alloc_netdev_mq | ||
5285 | */ | ||
5286 | |||
5287 | dev->_rx = kzalloc(sizeof(struct netdev_rx_queue), GFP_KERNEL); | ||
5288 | if (!dev->_rx) { | ||
5289 | ret = -ENOMEM; | ||
5290 | goto out; | ||
5291 | } | ||
5292 | |||
5293 | dev->_rx->first = dev->_rx; | ||
5294 | atomic_set(&dev->_rx->count, 1); | ||
5295 | dev->num_rx_queues = 1; | ||
5296 | } | ||
5297 | #endif | ||
5070 | /* Init, if this function is available */ | 5298 | /* Init, if this function is available */ |
5071 | if (dev->netdev_ops->ndo_init) { | 5299 | if (dev->netdev_ops->ndo_init) { |
5072 | ret = dev->netdev_ops->ndo_init(dev); | 5300 | ret = dev->netdev_ops->ndo_init(dev); |
@@ -5320,6 +5548,7 @@ void netdev_run_todo(void) | |||
5320 | while (!list_empty(&list)) { | 5548 | while (!list_empty(&list)) { |
5321 | struct net_device *dev | 5549 | struct net_device *dev |
5322 | = list_first_entry(&list, struct net_device, todo_list); | 5550 | = list_first_entry(&list, struct net_device, todo_list); |
5551 | int i; | ||
5323 | list_del(&dev->todo_list); | 5552 | list_del(&dev->todo_list); |
5324 | 5553 | ||
5325 | if (unlikely(dev->reg_state != NETREG_UNREGISTERING)) { | 5554 | if (unlikely(dev->reg_state != NETREG_UNREGISTERING)) { |
@@ -5331,7 +5560,8 @@ void netdev_run_todo(void) | |||
5331 | 5560 | ||
5332 | dev->reg_state = NETREG_UNREGISTERED; | 5561 | dev->reg_state = NETREG_UNREGISTERED; |
5333 | 5562 | ||
5334 | on_each_cpu(flush_backlog, dev, 1); | 5563 | for_each_online_cpu(i) |
5564 | flush_backlog(dev, i); | ||
5335 | 5565 | ||
5336 | netdev_wait_allrefs(dev); | 5566 | netdev_wait_allrefs(dev); |
5337 | 5567 | ||
@@ -5427,6 +5657,10 @@ struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name, | |||
5427 | struct net_device *dev; | 5657 | struct net_device *dev; |
5428 | size_t alloc_size; | 5658 | size_t alloc_size; |
5429 | struct net_device *p; | 5659 | struct net_device *p; |
5660 | #ifdef CONFIG_RPS | ||
5661 | struct netdev_rx_queue *rx; | ||
5662 | int i; | ||
5663 | #endif | ||
5430 | 5664 | ||
5431 | BUG_ON(strlen(name) >= sizeof(dev->name)); | 5665 | BUG_ON(strlen(name) >= sizeof(dev->name)); |
5432 | 5666 | ||
@@ -5452,11 +5686,29 @@ struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name, | |||
5452 | goto free_p; | 5686 | goto free_p; |
5453 | } | 5687 | } |
5454 | 5688 | ||
5689 | #ifdef CONFIG_RPS | ||
5690 | rx = kcalloc(queue_count, sizeof(struct netdev_rx_queue), GFP_KERNEL); | ||
5691 | if (!rx) { | ||
5692 | printk(KERN_ERR "alloc_netdev: Unable to allocate " | ||
5693 | "rx queues.\n"); | ||
5694 | goto free_tx; | ||
5695 | } | ||
5696 | |||
5697 | atomic_set(&rx->count, queue_count); | ||
5698 | |||
5699 | /* | ||
5700 | * Set a pointer to first element in the array which holds the | ||
5701 | * reference count. | ||
5702 | */ | ||
5703 | for (i = 0; i < queue_count; i++) | ||
5704 | rx[i].first = rx; | ||
5705 | #endif | ||
5706 | |||
5455 | dev = PTR_ALIGN(p, NETDEV_ALIGN); | 5707 | dev = PTR_ALIGN(p, NETDEV_ALIGN); |
5456 | dev->padded = (char *)dev - (char *)p; | 5708 | dev->padded = (char *)dev - (char *)p; |
5457 | 5709 | ||
5458 | if (dev_addr_init(dev)) | 5710 | if (dev_addr_init(dev)) |
5459 | goto free_tx; | 5711 | goto free_rx; |
5460 | 5712 | ||
5461 | dev_unicast_init(dev); | 5713 | dev_unicast_init(dev); |
5462 | 5714 | ||
@@ -5466,6 +5718,11 @@ struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name, | |||
5466 | dev->num_tx_queues = queue_count; | 5718 | dev->num_tx_queues = queue_count; |
5467 | dev->real_num_tx_queues = queue_count; | 5719 | dev->real_num_tx_queues = queue_count; |
5468 | 5720 | ||
5721 | #ifdef CONFIG_RPS | ||
5722 | dev->_rx = rx; | ||
5723 | dev->num_rx_queues = queue_count; | ||
5724 | #endif | ||
5725 | |||
5469 | dev->gso_max_size = GSO_MAX_SIZE; | 5726 | dev->gso_max_size = GSO_MAX_SIZE; |
5470 | 5727 | ||
5471 | netdev_init_queues(dev); | 5728 | netdev_init_queues(dev); |
@@ -5480,9 +5737,12 @@ struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name, | |||
5480 | strcpy(dev->name, name); | 5737 | strcpy(dev->name, name); |
5481 | return dev; | 5738 | return dev; |
5482 | 5739 | ||
5740 | free_rx: | ||
5741 | #ifdef CONFIG_RPS | ||
5742 | kfree(rx); | ||
5483 | free_tx: | 5743 | free_tx: |
5744 | #endif | ||
5484 | kfree(tx); | 5745 | kfree(tx); |
5485 | |||
5486 | free_p: | 5746 | free_p: |
5487 | kfree(p); | 5747 | kfree(p); |
5488 | return NULL; | 5748 | return NULL; |
@@ -5985,6 +6245,12 @@ static int __init net_dev_init(void) | |||
5985 | queue->completion_queue = NULL; | 6245 | queue->completion_queue = NULL; |
5986 | INIT_LIST_HEAD(&queue->poll_list); | 6246 | INIT_LIST_HEAD(&queue->poll_list); |
5987 | 6247 | ||
6248 | #ifdef CONFIG_RPS | ||
6249 | queue->csd.func = trigger_softirq; | ||
6250 | queue->csd.info = queue; | ||
6251 | queue->csd.flags = 0; | ||
6252 | #endif | ||
6253 | |||
5988 | queue->backlog.poll = process_backlog; | 6254 | queue->backlog.poll = process_backlog; |
5989 | queue->backlog.weight = weight_p; | 6255 | queue->backlog.weight = weight_p; |
5990 | queue->backlog.gro_list = NULL; | 6256 | queue->backlog.gro_list = NULL; |
@@ -6023,7 +6289,7 @@ subsys_initcall(net_dev_init); | |||
6023 | 6289 | ||
6024 | static int __init initialize_hashrnd(void) | 6290 | static int __init initialize_hashrnd(void) |
6025 | { | 6291 | { |
6026 | get_random_bytes(&skb_tx_hashrnd, sizeof(skb_tx_hashrnd)); | 6292 | get_random_bytes(&hashrnd, sizeof(hashrnd)); |
6027 | return 0; | 6293 | return 0; |
6028 | } | 6294 | } |
6029 | 6295 | ||
diff --git a/net/core/dev_mcast.c b/net/core/dev_mcast.c index fd91569e2394..3dc295beb483 100644 --- a/net/core/dev_mcast.c +++ b/net/core/dev_mcast.c | |||
@@ -97,8 +97,9 @@ int dev_mc_add(struct net_device *dev, void *addr, int alen, int glbl) | |||
97 | 97 | ||
98 | netif_addr_lock_bh(dev); | 98 | netif_addr_lock_bh(dev); |
99 | if (alen != dev->addr_len) | 99 | if (alen != dev->addr_len) |
100 | return -EINVAL; | 100 | err = -EINVAL; |
101 | err = __dev_addr_add(&dev->mc_list, &dev->mc_count, addr, alen, glbl); | 101 | else |
102 | err = __dev_addr_add(&dev->mc_list, &dev->mc_count, addr, alen, glbl); | ||
102 | if (!err) | 103 | if (!err) |
103 | __dev_set_rx_mode(dev); | 104 | __dev_set_rx_mode(dev); |
104 | netif_addr_unlock_bh(dev); | 105 | netif_addr_unlock_bh(dev); |
diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 0f2f82185ec4..f4cb6b6299d9 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/errno.h> | 17 | #include <linux/errno.h> |
18 | #include <linux/ethtool.h> | 18 | #include <linux/ethtool.h> |
19 | #include <linux/netdevice.h> | 19 | #include <linux/netdevice.h> |
20 | #include <linux/bitops.h> | ||
20 | #include <asm/uaccess.h> | 21 | #include <asm/uaccess.h> |
21 | 22 | ||
22 | /* | 23 | /* |
@@ -199,10 +200,7 @@ static int ethtool_set_settings(struct net_device *dev, void __user *useraddr) | |||
199 | return dev->ethtool_ops->set_settings(dev, &cmd); | 200 | return dev->ethtool_ops->set_settings(dev, &cmd); |
200 | } | 201 | } |
201 | 202 | ||
202 | /* | 203 | static noinline_for_stack int ethtool_get_drvinfo(struct net_device *dev, void __user *useraddr) |
203 | * noinline attribute so that gcc doesnt use too much stack in dev_ethtool() | ||
204 | */ | ||
205 | static noinline int ethtool_get_drvinfo(struct net_device *dev, void __user *useraddr) | ||
206 | { | 204 | { |
207 | struct ethtool_drvinfo info; | 205 | struct ethtool_drvinfo info; |
208 | const struct ethtool_ops *ops = dev->ethtool_ops; | 206 | const struct ethtool_ops *ops = dev->ethtool_ops; |
@@ -214,6 +212,10 @@ static noinline int ethtool_get_drvinfo(struct net_device *dev, void __user *use | |||
214 | info.cmd = ETHTOOL_GDRVINFO; | 212 | info.cmd = ETHTOOL_GDRVINFO; |
215 | ops->get_drvinfo(dev, &info); | 213 | ops->get_drvinfo(dev, &info); |
216 | 214 | ||
215 | /* | ||
216 | * this method of obtaining string set info is deprecated; | ||
217 | * Use ETHTOOL_GSSET_INFO instead. | ||
218 | */ | ||
217 | if (ops->get_sset_count) { | 219 | if (ops->get_sset_count) { |
218 | int rc; | 220 | int rc; |
219 | 221 | ||
@@ -237,10 +239,67 @@ static noinline int ethtool_get_drvinfo(struct net_device *dev, void __user *use | |||
237 | return 0; | 239 | return 0; |
238 | } | 240 | } |
239 | 241 | ||
240 | /* | 242 | static noinline_for_stack int ethtool_get_sset_info(struct net_device *dev, |
241 | * noinline attribute so that gcc doesnt use too much stack in dev_ethtool() | 243 | void __user *useraddr) |
242 | */ | 244 | { |
243 | static noinline int ethtool_set_rxnfc(struct net_device *dev, void __user *useraddr) | 245 | struct ethtool_sset_info info; |
246 | const struct ethtool_ops *ops = dev->ethtool_ops; | ||
247 | u64 sset_mask; | ||
248 | int i, idx = 0, n_bits = 0, ret, rc; | ||
249 | u32 *info_buf = NULL; | ||
250 | |||
251 | if (!ops->get_sset_count) | ||
252 | return -EOPNOTSUPP; | ||
253 | |||
254 | if (copy_from_user(&info, useraddr, sizeof(info))) | ||
255 | return -EFAULT; | ||
256 | |||
257 | /* store copy of mask, because we zero struct later on */ | ||
258 | sset_mask = info.sset_mask; | ||
259 | if (!sset_mask) | ||
260 | return 0; | ||
261 | |||
262 | /* calculate size of return buffer */ | ||
263 | n_bits = hweight64(sset_mask); | ||
264 | |||
265 | memset(&info, 0, sizeof(info)); | ||
266 | info.cmd = ETHTOOL_GSSET_INFO; | ||
267 | |||
268 | info_buf = kzalloc(n_bits * sizeof(u32), GFP_USER); | ||
269 | if (!info_buf) | ||
270 | return -ENOMEM; | ||
271 | |||
272 | /* | ||
273 | * fill return buffer based on input bitmask and successful | ||
274 | * get_sset_count return | ||
275 | */ | ||
276 | for (i = 0; i < 64; i++) { | ||
277 | if (!(sset_mask & (1ULL << i))) | ||
278 | continue; | ||
279 | |||
280 | rc = ops->get_sset_count(dev, i); | ||
281 | if (rc >= 0) { | ||
282 | info.sset_mask |= (1ULL << i); | ||
283 | info_buf[idx++] = rc; | ||
284 | } | ||
285 | } | ||
286 | |||
287 | ret = -EFAULT; | ||
288 | if (copy_to_user(useraddr, &info, sizeof(info))) | ||
289 | goto out; | ||
290 | |||
291 | useraddr += offsetof(struct ethtool_sset_info, data); | ||
292 | if (copy_to_user(useraddr, info_buf, idx * sizeof(u32))) | ||
293 | goto out; | ||
294 | |||
295 | ret = 0; | ||
296 | |||
297 | out: | ||
298 | kfree(info_buf); | ||
299 | return ret; | ||
300 | } | ||
301 | |||
302 | static noinline_for_stack int ethtool_set_rxnfc(struct net_device *dev, void __user *useraddr) | ||
244 | { | 303 | { |
245 | struct ethtool_rxnfc cmd; | 304 | struct ethtool_rxnfc cmd; |
246 | 305 | ||
@@ -253,10 +312,7 @@ static noinline int ethtool_set_rxnfc(struct net_device *dev, void __user *usera | |||
253 | return dev->ethtool_ops->set_rxnfc(dev, &cmd); | 312 | return dev->ethtool_ops->set_rxnfc(dev, &cmd); |
254 | } | 313 | } |
255 | 314 | ||
256 | /* | 315 | static noinline_for_stack int ethtool_get_rxnfc(struct net_device *dev, void __user *useraddr) |
257 | * noinline attribute so that gcc doesnt use too much stack in dev_ethtool() | ||
258 | */ | ||
259 | static noinline int ethtool_get_rxnfc(struct net_device *dev, void __user *useraddr) | ||
260 | { | 316 | { |
261 | struct ethtool_rxnfc info; | 317 | struct ethtool_rxnfc info; |
262 | const struct ethtool_ops *ops = dev->ethtool_ops; | 318 | const struct ethtool_ops *ops = dev->ethtool_ops; |
@@ -328,10 +384,7 @@ static void __rx_ntuple_filter_add(struct ethtool_rx_ntuple_list *list, | |||
328 | list->count++; | 384 | list->count++; |
329 | } | 385 | } |
330 | 386 | ||
331 | /* | 387 | static noinline_for_stack int ethtool_set_rx_ntuple(struct net_device *dev, void __user *useraddr) |
332 | * noinline attribute so that gcc doesnt use too much stack in dev_ethtool() | ||
333 | */ | ||
334 | static noinline int ethtool_set_rx_ntuple(struct net_device *dev, void __user *useraddr) | ||
335 | { | 388 | { |
336 | struct ethtool_rx_ntuple cmd; | 389 | struct ethtool_rx_ntuple cmd; |
337 | const struct ethtool_ops *ops = dev->ethtool_ops; | 390 | const struct ethtool_ops *ops = dev->ethtool_ops; |
@@ -799,10 +852,7 @@ static int ethtool_set_eeprom(struct net_device *dev, void __user *useraddr) | |||
799 | return ret; | 852 | return ret; |
800 | } | 853 | } |
801 | 854 | ||
802 | /* | 855 | static noinline_for_stack int ethtool_get_coalesce(struct net_device *dev, void __user *useraddr) |
803 | * noinline attribute so that gcc doesnt use too much stack in dev_ethtool() | ||
804 | */ | ||
805 | static noinline int ethtool_get_coalesce(struct net_device *dev, void __user *useraddr) | ||
806 | { | 856 | { |
807 | struct ethtool_coalesce coalesce = { .cmd = ETHTOOL_GCOALESCE }; | 857 | struct ethtool_coalesce coalesce = { .cmd = ETHTOOL_GCOALESCE }; |
808 | 858 | ||
@@ -816,10 +866,7 @@ static noinline int ethtool_get_coalesce(struct net_device *dev, void __user *us | |||
816 | return 0; | 866 | return 0; |
817 | } | 867 | } |
818 | 868 | ||
819 | /* | 869 | static noinline_for_stack int ethtool_set_coalesce(struct net_device *dev, void __user *useraddr) |
820 | * noinline attribute so that gcc doesnt use too much stack in dev_ethtool() | ||
821 | */ | ||
822 | static noinline int ethtool_set_coalesce(struct net_device *dev, void __user *useraddr) | ||
823 | { | 870 | { |
824 | struct ethtool_coalesce coalesce; | 871 | struct ethtool_coalesce coalesce; |
825 | 872 | ||
@@ -1229,10 +1276,7 @@ static int ethtool_set_value(struct net_device *dev, char __user *useraddr, | |||
1229 | return actor(dev, edata.data); | 1276 | return actor(dev, edata.data); |
1230 | } | 1277 | } |
1231 | 1278 | ||
1232 | /* | 1279 | static noinline_for_stack int ethtool_flash_device(struct net_device *dev, char __user *useraddr) |
1233 | * noinline attribute so that gcc doesnt use too much stack in dev_ethtool() | ||
1234 | */ | ||
1235 | static noinline int ethtool_flash_device(struct net_device *dev, char __user *useraddr) | ||
1236 | { | 1280 | { |
1237 | struct ethtool_flash efl; | 1281 | struct ethtool_flash efl; |
1238 | 1282 | ||
@@ -1471,6 +1515,9 @@ int dev_ethtool(struct net *net, struct ifreq *ifr) | |||
1471 | case ETHTOOL_GRXNTUPLE: | 1515 | case ETHTOOL_GRXNTUPLE: |
1472 | rc = ethtool_get_rx_ntuple(dev, useraddr); | 1516 | rc = ethtool_get_rx_ntuple(dev, useraddr); |
1473 | break; | 1517 | break; |
1518 | case ETHTOOL_GSSET_INFO: | ||
1519 | rc = ethtool_get_sset_info(dev, useraddr); | ||
1520 | break; | ||
1474 | default: | 1521 | default: |
1475 | rc = -EOPNOTSUPP; | 1522 | rc = -EOPNOTSUPP; |
1476 | } | 1523 | } |
diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c index 9a24377146bf..2ff34894357a 100644 --- a/net/core/fib_rules.c +++ b/net/core/fib_rules.c | |||
@@ -108,7 +108,7 @@ fib_rules_register(struct fib_rules_ops *tmpl, struct net *net) | |||
108 | struct fib_rules_ops *ops; | 108 | struct fib_rules_ops *ops; |
109 | int err; | 109 | int err; |
110 | 110 | ||
111 | ops = kmemdup(tmpl, sizeof (*ops), GFP_KERNEL); | 111 | ops = kmemdup(tmpl, sizeof(*ops), GFP_KERNEL); |
112 | if (ops == NULL) | 112 | if (ops == NULL) |
113 | return ERR_PTR(-ENOMEM); | 113 | return ERR_PTR(-ENOMEM); |
114 | 114 | ||
@@ -123,7 +123,6 @@ fib_rules_register(struct fib_rules_ops *tmpl, struct net *net) | |||
123 | 123 | ||
124 | return ops; | 124 | return ops; |
125 | } | 125 | } |
126 | |||
127 | EXPORT_SYMBOL_GPL(fib_rules_register); | 126 | EXPORT_SYMBOL_GPL(fib_rules_register); |
128 | 127 | ||
129 | void fib_rules_cleanup_ops(struct fib_rules_ops *ops) | 128 | void fib_rules_cleanup_ops(struct fib_rules_ops *ops) |
@@ -157,7 +156,6 @@ void fib_rules_unregister(struct fib_rules_ops *ops) | |||
157 | 156 | ||
158 | call_rcu(&ops->rcu, fib_rules_put_rcu); | 157 | call_rcu(&ops->rcu, fib_rules_put_rcu); |
159 | } | 158 | } |
160 | |||
161 | EXPORT_SYMBOL_GPL(fib_rules_unregister); | 159 | EXPORT_SYMBOL_GPL(fib_rules_unregister); |
162 | 160 | ||
163 | static int fib_rule_match(struct fib_rule *rule, struct fib_rules_ops *ops, | 161 | static int fib_rule_match(struct fib_rule *rule, struct fib_rules_ops *ops, |
@@ -220,7 +218,6 @@ out: | |||
220 | 218 | ||
221 | return err; | 219 | return err; |
222 | } | 220 | } |
223 | |||
224 | EXPORT_SYMBOL_GPL(fib_rules_lookup); | 221 | EXPORT_SYMBOL_GPL(fib_rules_lookup); |
225 | 222 | ||
226 | static int validate_rulemsg(struct fib_rule_hdr *frh, struct nlattr **tb, | 223 | static int validate_rulemsg(struct fib_rule_hdr *frh, struct nlattr **tb, |
@@ -613,7 +610,7 @@ static int fib_nl_dumprule(struct sk_buff *skb, struct netlink_callback *cb) | |||
613 | break; | 610 | break; |
614 | 611 | ||
615 | cb->args[1] = 0; | 612 | cb->args[1] = 0; |
616 | skip: | 613 | skip: |
617 | idx++; | 614 | idx++; |
618 | } | 615 | } |
619 | rcu_read_unlock(); | 616 | rcu_read_unlock(); |
@@ -685,7 +682,6 @@ static int fib_rules_event(struct notifier_block *this, unsigned long event, | |||
685 | struct fib_rules_ops *ops; | 682 | struct fib_rules_ops *ops; |
686 | 683 | ||
687 | ASSERT_RTNL(); | 684 | ASSERT_RTNL(); |
688 | rcu_read_lock(); | ||
689 | 685 | ||
690 | switch (event) { | 686 | switch (event) { |
691 | case NETDEV_REGISTER: | 687 | case NETDEV_REGISTER: |
@@ -699,8 +695,6 @@ static int fib_rules_event(struct notifier_block *this, unsigned long event, | |||
699 | break; | 695 | break; |
700 | } | 696 | } |
701 | 697 | ||
702 | rcu_read_unlock(); | ||
703 | |||
704 | return NOTIFY_DONE; | 698 | return NOTIFY_DONE; |
705 | } | 699 | } |
706 | 700 | ||
diff --git a/net/core/neighbour.c b/net/core/neighbour.c index d102f6d9abdc..6cee6434da67 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c | |||
@@ -771,6 +771,8 @@ static __inline__ int neigh_max_probes(struct neighbour *n) | |||
771 | } | 771 | } |
772 | 772 | ||
773 | static void neigh_invalidate(struct neighbour *neigh) | 773 | static void neigh_invalidate(struct neighbour *neigh) |
774 | __releases(neigh->lock) | ||
775 | __acquires(neigh->lock) | ||
774 | { | 776 | { |
775 | struct sk_buff *skb; | 777 | struct sk_buff *skb; |
776 | 778 | ||
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index 099c753c4213..1e7fdd6029a2 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c | |||
@@ -466,6 +466,217 @@ static struct attribute_group wireless_group = { | |||
466 | }; | 466 | }; |
467 | #endif | 467 | #endif |
468 | 468 | ||
469 | #ifdef CONFIG_RPS | ||
470 | /* | ||
471 | * RX queue sysfs structures and functions. | ||
472 | */ | ||
473 | struct rx_queue_attribute { | ||
474 | struct attribute attr; | ||
475 | ssize_t (*show)(struct netdev_rx_queue *queue, | ||
476 | struct rx_queue_attribute *attr, char *buf); | ||
477 | ssize_t (*store)(struct netdev_rx_queue *queue, | ||
478 | struct rx_queue_attribute *attr, const char *buf, size_t len); | ||
479 | }; | ||
480 | #define to_rx_queue_attr(_attr) container_of(_attr, \ | ||
481 | struct rx_queue_attribute, attr) | ||
482 | |||
483 | #define to_rx_queue(obj) container_of(obj, struct netdev_rx_queue, kobj) | ||
484 | |||
485 | static ssize_t rx_queue_attr_show(struct kobject *kobj, struct attribute *attr, | ||
486 | char *buf) | ||
487 | { | ||
488 | struct rx_queue_attribute *attribute = to_rx_queue_attr(attr); | ||
489 | struct netdev_rx_queue *queue = to_rx_queue(kobj); | ||
490 | |||
491 | if (!attribute->show) | ||
492 | return -EIO; | ||
493 | |||
494 | return attribute->show(queue, attribute, buf); | ||
495 | } | ||
496 | |||
497 | static ssize_t rx_queue_attr_store(struct kobject *kobj, struct attribute *attr, | ||
498 | const char *buf, size_t count) | ||
499 | { | ||
500 | struct rx_queue_attribute *attribute = to_rx_queue_attr(attr); | ||
501 | struct netdev_rx_queue *queue = to_rx_queue(kobj); | ||
502 | |||
503 | if (!attribute->store) | ||
504 | return -EIO; | ||
505 | |||
506 | return attribute->store(queue, attribute, buf, count); | ||
507 | } | ||
508 | |||
509 | static struct sysfs_ops rx_queue_sysfs_ops = { | ||
510 | .show = rx_queue_attr_show, | ||
511 | .store = rx_queue_attr_store, | ||
512 | }; | ||
513 | |||
514 | static ssize_t show_rps_map(struct netdev_rx_queue *queue, | ||
515 | struct rx_queue_attribute *attribute, char *buf) | ||
516 | { | ||
517 | struct rps_map *map; | ||
518 | cpumask_var_t mask; | ||
519 | size_t len = 0; | ||
520 | int i; | ||
521 | |||
522 | if (!zalloc_cpumask_var(&mask, GFP_KERNEL)) | ||
523 | return -ENOMEM; | ||
524 | |||
525 | rcu_read_lock(); | ||
526 | map = rcu_dereference(queue->rps_map); | ||
527 | if (map) | ||
528 | for (i = 0; i < map->len; i++) | ||
529 | cpumask_set_cpu(map->cpus[i], mask); | ||
530 | |||
531 | len += cpumask_scnprintf(buf + len, PAGE_SIZE, mask); | ||
532 | if (PAGE_SIZE - len < 3) { | ||
533 | rcu_read_unlock(); | ||
534 | free_cpumask_var(mask); | ||
535 | return -EINVAL; | ||
536 | } | ||
537 | rcu_read_unlock(); | ||
538 | |||
539 | free_cpumask_var(mask); | ||
540 | len += sprintf(buf + len, "\n"); | ||
541 | return len; | ||
542 | } | ||
543 | |||
544 | static void rps_map_release(struct rcu_head *rcu) | ||
545 | { | ||
546 | struct rps_map *map = container_of(rcu, struct rps_map, rcu); | ||
547 | |||
548 | kfree(map); | ||
549 | } | ||
550 | |||
551 | ssize_t store_rps_map(struct netdev_rx_queue *queue, | ||
552 | struct rx_queue_attribute *attribute, | ||
553 | const char *buf, size_t len) | ||
554 | { | ||
555 | struct rps_map *old_map, *map; | ||
556 | cpumask_var_t mask; | ||
557 | int err, cpu, i; | ||
558 | static DEFINE_SPINLOCK(rps_map_lock); | ||
559 | |||
560 | if (!capable(CAP_NET_ADMIN)) | ||
561 | return -EPERM; | ||
562 | |||
563 | if (!alloc_cpumask_var(&mask, GFP_KERNEL)) | ||
564 | return -ENOMEM; | ||
565 | |||
566 | err = bitmap_parse(buf, len, cpumask_bits(mask), nr_cpumask_bits); | ||
567 | if (err) { | ||
568 | free_cpumask_var(mask); | ||
569 | return err; | ||
570 | } | ||
571 | |||
572 | map = kzalloc(max_t(unsigned, | ||
573 | RPS_MAP_SIZE(cpumask_weight(mask)), L1_CACHE_BYTES), | ||
574 | GFP_KERNEL); | ||
575 | if (!map) { | ||
576 | free_cpumask_var(mask); | ||
577 | return -ENOMEM; | ||
578 | } | ||
579 | |||
580 | i = 0; | ||
581 | for_each_cpu_and(cpu, mask, cpu_online_mask) | ||
582 | map->cpus[i++] = cpu; | ||
583 | |||
584 | if (i) | ||
585 | map->len = i; | ||
586 | else { | ||
587 | kfree(map); | ||
588 | map = NULL; | ||
589 | } | ||
590 | |||
591 | spin_lock(&rps_map_lock); | ||
592 | old_map = queue->rps_map; | ||
593 | rcu_assign_pointer(queue->rps_map, map); | ||
594 | spin_unlock(&rps_map_lock); | ||
595 | |||
596 | if (old_map) | ||
597 | call_rcu(&old_map->rcu, rps_map_release); | ||
598 | |||
599 | free_cpumask_var(mask); | ||
600 | return len; | ||
601 | } | ||
602 | |||
603 | static struct rx_queue_attribute rps_cpus_attribute = | ||
604 | __ATTR(rps_cpus, S_IRUGO | S_IWUSR, show_rps_map, store_rps_map); | ||
605 | |||
606 | static struct attribute *rx_queue_default_attrs[] = { | ||
607 | &rps_cpus_attribute.attr, | ||
608 | NULL | ||
609 | }; | ||
610 | |||
611 | static void rx_queue_release(struct kobject *kobj) | ||
612 | { | ||
613 | struct netdev_rx_queue *queue = to_rx_queue(kobj); | ||
614 | struct rps_map *map = queue->rps_map; | ||
615 | struct netdev_rx_queue *first = queue->first; | ||
616 | |||
617 | if (map) | ||
618 | call_rcu(&map->rcu, rps_map_release); | ||
619 | |||
620 | if (atomic_dec_and_test(&first->count)) | ||
621 | kfree(first); | ||
622 | } | ||
623 | |||
624 | static struct kobj_type rx_queue_ktype = { | ||
625 | .sysfs_ops = &rx_queue_sysfs_ops, | ||
626 | .release = rx_queue_release, | ||
627 | .default_attrs = rx_queue_default_attrs, | ||
628 | }; | ||
629 | |||
630 | static int rx_queue_add_kobject(struct net_device *net, int index) | ||
631 | { | ||
632 | struct netdev_rx_queue *queue = net->_rx + index; | ||
633 | struct kobject *kobj = &queue->kobj; | ||
634 | int error = 0; | ||
635 | |||
636 | kobj->kset = net->queues_kset; | ||
637 | error = kobject_init_and_add(kobj, &rx_queue_ktype, NULL, | ||
638 | "rx-%u", index); | ||
639 | if (error) { | ||
640 | kobject_put(kobj); | ||
641 | return error; | ||
642 | } | ||
643 | |||
644 | kobject_uevent(kobj, KOBJ_ADD); | ||
645 | |||
646 | return error; | ||
647 | } | ||
648 | |||
649 | static int rx_queue_register_kobjects(struct net_device *net) | ||
650 | { | ||
651 | int i; | ||
652 | int error = 0; | ||
653 | |||
654 | net->queues_kset = kset_create_and_add("queues", | ||
655 | NULL, &net->dev.kobj); | ||
656 | if (!net->queues_kset) | ||
657 | return -ENOMEM; | ||
658 | for (i = 0; i < net->num_rx_queues; i++) { | ||
659 | error = rx_queue_add_kobject(net, i); | ||
660 | if (error) | ||
661 | break; | ||
662 | } | ||
663 | |||
664 | if (error) | ||
665 | while (--i >= 0) | ||
666 | kobject_put(&net->_rx[i].kobj); | ||
667 | |||
668 | return error; | ||
669 | } | ||
670 | |||
671 | static void rx_queue_remove_kobjects(struct net_device *net) | ||
672 | { | ||
673 | int i; | ||
674 | |||
675 | for (i = 0; i < net->num_rx_queues; i++) | ||
676 | kobject_put(&net->_rx[i].kobj); | ||
677 | kset_unregister(net->queues_kset); | ||
678 | } | ||
679 | #endif /* CONFIG_RPS */ | ||
469 | #endif /* CONFIG_SYSFS */ | 680 | #endif /* CONFIG_SYSFS */ |
470 | 681 | ||
471 | #ifdef CONFIG_HOTPLUG | 682 | #ifdef CONFIG_HOTPLUG |
@@ -529,6 +740,10 @@ void netdev_unregister_kobject(struct net_device * net) | |||
529 | if (!net_eq(dev_net(net), &init_net)) | 740 | if (!net_eq(dev_net(net), &init_net)) |
530 | return; | 741 | return; |
531 | 742 | ||
743 | #ifdef CONFIG_RPS | ||
744 | rx_queue_remove_kobjects(net); | ||
745 | #endif | ||
746 | |||
532 | device_del(dev); | 747 | device_del(dev); |
533 | } | 748 | } |
534 | 749 | ||
@@ -537,6 +752,7 @@ int netdev_register_kobject(struct net_device *net) | |||
537 | { | 752 | { |
538 | struct device *dev = &(net->dev); | 753 | struct device *dev = &(net->dev); |
539 | const struct attribute_group **groups = net->sysfs_groups; | 754 | const struct attribute_group **groups = net->sysfs_groups; |
755 | int error = 0; | ||
540 | 756 | ||
541 | dev->class = &net_class; | 757 | dev->class = &net_class; |
542 | dev->platform_data = net; | 758 | dev->platform_data = net; |
@@ -563,7 +779,19 @@ int netdev_register_kobject(struct net_device *net) | |||
563 | if (!net_eq(dev_net(net), &init_net)) | 779 | if (!net_eq(dev_net(net), &init_net)) |
564 | return 0; | 780 | return 0; |
565 | 781 | ||
566 | return device_add(dev); | 782 | error = device_add(dev); |
783 | if (error) | ||
784 | return error; | ||
785 | |||
786 | #ifdef CONFIG_RPS | ||
787 | error = rx_queue_register_kobjects(net); | ||
788 | if (error) { | ||
789 | device_del(dev); | ||
790 | return error; | ||
791 | } | ||
792 | #endif | ||
793 | |||
794 | return error; | ||
567 | } | 795 | } |
568 | 796 | ||
569 | int netdev_class_create_file(struct class_attribute *class_attr) | 797 | int netdev_class_create_file(struct class_attribute *class_attr) |
diff --git a/net/core/netpoll.c b/net/core/netpoll.c index 7aa697253765..d4ec38fa64e6 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c | |||
@@ -735,7 +735,7 @@ int netpoll_setup(struct netpoll *np) | |||
735 | npinfo = kmalloc(sizeof(*npinfo), GFP_KERNEL); | 735 | npinfo = kmalloc(sizeof(*npinfo), GFP_KERNEL); |
736 | if (!npinfo) { | 736 | if (!npinfo) { |
737 | err = -ENOMEM; | 737 | err = -ENOMEM; |
738 | goto release; | 738 | goto put; |
739 | } | 739 | } |
740 | 740 | ||
741 | npinfo->rx_flags = 0; | 741 | npinfo->rx_flags = 0; |
@@ -845,7 +845,7 @@ int netpoll_setup(struct netpoll *np) | |||
845 | 845 | ||
846 | kfree(npinfo); | 846 | kfree(npinfo); |
847 | } | 847 | } |
848 | 848 | put: | |
849 | dev_put(ndev); | 849 | dev_put(ndev); |
850 | return err; | 850 | return err; |
851 | } | 851 | } |
diff --git a/net/core/pktgen.c b/net/core/pktgen.c index 43923811bd6a..2ad68da418df 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c | |||
@@ -169,7 +169,7 @@ | |||
169 | #include <asm/dma.h> | 169 | #include <asm/dma.h> |
170 | #include <asm/div64.h> /* do_div */ | 170 | #include <asm/div64.h> /* do_div */ |
171 | 171 | ||
172 | #define VERSION "2.72" | 172 | #define VERSION "2.73" |
173 | #define IP_NAME_SZ 32 | 173 | #define IP_NAME_SZ 32 |
174 | #define MAX_MPLS_LABELS 16 /* This is the max label stack depth */ | 174 | #define MAX_MPLS_LABELS 16 /* This is the max label stack depth */ |
175 | #define MPLS_STACK_BOTTOM htonl(0x00000100) | 175 | #define MPLS_STACK_BOTTOM htonl(0x00000100) |
@@ -190,6 +190,7 @@ | |||
190 | #define F_IPSEC_ON (1<<12) /* ipsec on for flows */ | 190 | #define F_IPSEC_ON (1<<12) /* ipsec on for flows */ |
191 | #define F_QUEUE_MAP_RND (1<<13) /* queue map Random */ | 191 | #define F_QUEUE_MAP_RND (1<<13) /* queue map Random */ |
192 | #define F_QUEUE_MAP_CPU (1<<14) /* queue map mirrors smp_processor_id() */ | 192 | #define F_QUEUE_MAP_CPU (1<<14) /* queue map mirrors smp_processor_id() */ |
193 | #define F_NODE (1<<15) /* Node memory alloc*/ | ||
193 | 194 | ||
194 | /* Thread control flag bits */ | 195 | /* Thread control flag bits */ |
195 | #define T_STOP (1<<0) /* Stop run */ | 196 | #define T_STOP (1<<0) /* Stop run */ |
@@ -372,6 +373,7 @@ struct pktgen_dev { | |||
372 | 373 | ||
373 | u16 queue_map_min; | 374 | u16 queue_map_min; |
374 | u16 queue_map_max; | 375 | u16 queue_map_max; |
376 | int node; /* Memory node */ | ||
375 | 377 | ||
376 | #ifdef CONFIG_XFRM | 378 | #ifdef CONFIG_XFRM |
377 | __u8 ipsmode; /* IPSEC mode (config) */ | 379 | __u8 ipsmode; /* IPSEC mode (config) */ |
@@ -607,6 +609,9 @@ static int pktgen_if_show(struct seq_file *seq, void *v) | |||
607 | if (pkt_dev->traffic_class) | 609 | if (pkt_dev->traffic_class) |
608 | seq_printf(seq, " traffic_class: 0x%02x\n", pkt_dev->traffic_class); | 610 | seq_printf(seq, " traffic_class: 0x%02x\n", pkt_dev->traffic_class); |
609 | 611 | ||
612 | if (pkt_dev->node >= 0) | ||
613 | seq_printf(seq, " node: %d\n", pkt_dev->node); | ||
614 | |||
610 | seq_printf(seq, " Flags: "); | 615 | seq_printf(seq, " Flags: "); |
611 | 616 | ||
612 | if (pkt_dev->flags & F_IPV6) | 617 | if (pkt_dev->flags & F_IPV6) |
@@ -660,6 +665,9 @@ static int pktgen_if_show(struct seq_file *seq, void *v) | |||
660 | if (pkt_dev->flags & F_SVID_RND) | 665 | if (pkt_dev->flags & F_SVID_RND) |
661 | seq_printf(seq, "SVID_RND "); | 666 | seq_printf(seq, "SVID_RND "); |
662 | 667 | ||
668 | if (pkt_dev->flags & F_NODE) | ||
669 | seq_printf(seq, "NODE_ALLOC "); | ||
670 | |||
663 | seq_puts(seq, "\n"); | 671 | seq_puts(seq, "\n"); |
664 | 672 | ||
665 | /* not really stopped, more like last-running-at */ | 673 | /* not really stopped, more like last-running-at */ |
@@ -1074,6 +1082,21 @@ static ssize_t pktgen_if_write(struct file *file, | |||
1074 | pkt_dev->dst_mac_count); | 1082 | pkt_dev->dst_mac_count); |
1075 | return count; | 1083 | return count; |
1076 | } | 1084 | } |
1085 | if (!strcmp(name, "node")) { | ||
1086 | len = num_arg(&user_buffer[i], 10, &value); | ||
1087 | if (len < 0) | ||
1088 | return len; | ||
1089 | |||
1090 | i += len; | ||
1091 | |||
1092 | if (node_possible(value)) { | ||
1093 | pkt_dev->node = value; | ||
1094 | sprintf(pg_result, "OK: node=%d", pkt_dev->node); | ||
1095 | } | ||
1096 | else | ||
1097 | sprintf(pg_result, "ERROR: node not possible"); | ||
1098 | return count; | ||
1099 | } | ||
1077 | if (!strcmp(name, "flag")) { | 1100 | if (!strcmp(name, "flag")) { |
1078 | char f[32]; | 1101 | char f[32]; |
1079 | memset(f, 0, 32); | 1102 | memset(f, 0, 32); |
@@ -1166,12 +1189,18 @@ static ssize_t pktgen_if_write(struct file *file, | |||
1166 | else if (strcmp(f, "!IPV6") == 0) | 1189 | else if (strcmp(f, "!IPV6") == 0) |
1167 | pkt_dev->flags &= ~F_IPV6; | 1190 | pkt_dev->flags &= ~F_IPV6; |
1168 | 1191 | ||
1192 | else if (strcmp(f, "NODE_ALLOC") == 0) | ||
1193 | pkt_dev->flags |= F_NODE; | ||
1194 | |||
1195 | else if (strcmp(f, "!NODE_ALLOC") == 0) | ||
1196 | pkt_dev->flags &= ~F_NODE; | ||
1197 | |||
1169 | else { | 1198 | else { |
1170 | sprintf(pg_result, | 1199 | sprintf(pg_result, |
1171 | "Flag -:%s:- unknown\nAvailable flags, (prepend ! to un-set flag):\n%s", | 1200 | "Flag -:%s:- unknown\nAvailable flags, (prepend ! to un-set flag):\n%s", |
1172 | f, | 1201 | f, |
1173 | "IPSRC_RND, IPDST_RND, UDPSRC_RND, UDPDST_RND, " | 1202 | "IPSRC_RND, IPDST_RND, UDPSRC_RND, UDPDST_RND, " |
1174 | "MACSRC_RND, MACDST_RND, TXSIZE_RND, IPV6, MPLS_RND, VID_RND, SVID_RND, FLOW_SEQ, IPSEC\n"); | 1203 | "MACSRC_RND, MACDST_RND, TXSIZE_RND, IPV6, MPLS_RND, VID_RND, SVID_RND, FLOW_SEQ, IPSEC, NODE_ALLOC\n"); |
1175 | return count; | 1204 | return count; |
1176 | } | 1205 | } |
1177 | sprintf(pg_result, "OK: flags=0x%x", pkt_dev->flags); | 1206 | sprintf(pg_result, "OK: flags=0x%x", pkt_dev->flags); |
@@ -2572,9 +2601,27 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev, | |||
2572 | mod_cur_headers(pkt_dev); | 2601 | mod_cur_headers(pkt_dev); |
2573 | 2602 | ||
2574 | datalen = (odev->hard_header_len + 16) & ~0xf; | 2603 | datalen = (odev->hard_header_len + 16) & ~0xf; |
2575 | skb = __netdev_alloc_skb(odev, | 2604 | |
2576 | pkt_dev->cur_pkt_size + 64 | 2605 | if (pkt_dev->flags & F_NODE) { |
2577 | + datalen + pkt_dev->pkt_overhead, GFP_NOWAIT); | 2606 | int node; |
2607 | |||
2608 | if (pkt_dev->node >= 0) | ||
2609 | node = pkt_dev->node; | ||
2610 | else | ||
2611 | node = numa_node_id(); | ||
2612 | |||
2613 | skb = __alloc_skb(NET_SKB_PAD + pkt_dev->cur_pkt_size + 64 | ||
2614 | + datalen + pkt_dev->pkt_overhead, GFP_NOWAIT, 0, node); | ||
2615 | if (likely(skb)) { | ||
2616 | skb_reserve(skb, NET_SKB_PAD); | ||
2617 | skb->dev = odev; | ||
2618 | } | ||
2619 | } | ||
2620 | else | ||
2621 | skb = __netdev_alloc_skb(odev, | ||
2622 | pkt_dev->cur_pkt_size + 64 | ||
2623 | + datalen + pkt_dev->pkt_overhead, GFP_NOWAIT); | ||
2624 | |||
2578 | if (!skb) { | 2625 | if (!skb) { |
2579 | sprintf(pkt_dev->result, "No memory"); | 2626 | sprintf(pkt_dev->result, "No memory"); |
2580 | return NULL; | 2627 | return NULL; |
@@ -3674,6 +3721,7 @@ static int pktgen_add_device(struct pktgen_thread *t, const char *ifname) | |||
3674 | pkt_dev->svlan_p = 0; | 3721 | pkt_dev->svlan_p = 0; |
3675 | pkt_dev->svlan_cfi = 0; | 3722 | pkt_dev->svlan_cfi = 0; |
3676 | pkt_dev->svlan_id = 0xffff; | 3723 | pkt_dev->svlan_id = 0xffff; |
3724 | pkt_dev->node = -1; | ||
3677 | 3725 | ||
3678 | err = pktgen_setup_dev(pkt_dev, ifname); | 3726 | err = pktgen_setup_dev(pkt_dev, ifname); |
3679 | if (err) | 3727 | if (err) |
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 4568120d8533..bf919b6acea2 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
@@ -600,7 +600,41 @@ static void copy_rtnl_link_stats(struct rtnl_link_stats *a, | |||
600 | 600 | ||
601 | a->rx_compressed = b->rx_compressed; | 601 | a->rx_compressed = b->rx_compressed; |
602 | a->tx_compressed = b->tx_compressed; | 602 | a->tx_compressed = b->tx_compressed; |
603 | }; | 603 | } |
604 | |||
605 | static void copy_rtnl_link_stats64(void *v, const struct net_device_stats *b) | ||
606 | { | ||
607 | struct rtnl_link_stats64 a; | ||
608 | |||
609 | a.rx_packets = b->rx_packets; | ||
610 | a.tx_packets = b->tx_packets; | ||
611 | a.rx_bytes = b->rx_bytes; | ||
612 | a.tx_bytes = b->tx_bytes; | ||
613 | a.rx_errors = b->rx_errors; | ||
614 | a.tx_errors = b->tx_errors; | ||
615 | a.rx_dropped = b->rx_dropped; | ||
616 | a.tx_dropped = b->tx_dropped; | ||
617 | |||
618 | a.multicast = b->multicast; | ||
619 | a.collisions = b->collisions; | ||
620 | |||
621 | a.rx_length_errors = b->rx_length_errors; | ||
622 | a.rx_over_errors = b->rx_over_errors; | ||
623 | a.rx_crc_errors = b->rx_crc_errors; | ||
624 | a.rx_frame_errors = b->rx_frame_errors; | ||
625 | a.rx_fifo_errors = b->rx_fifo_errors; | ||
626 | a.rx_missed_errors = b->rx_missed_errors; | ||
627 | |||
628 | a.tx_aborted_errors = b->tx_aborted_errors; | ||
629 | a.tx_carrier_errors = b->tx_carrier_errors; | ||
630 | a.tx_fifo_errors = b->tx_fifo_errors; | ||
631 | a.tx_heartbeat_errors = b->tx_heartbeat_errors; | ||
632 | a.tx_window_errors = b->tx_window_errors; | ||
633 | |||
634 | a.rx_compressed = b->rx_compressed; | ||
635 | a.tx_compressed = b->tx_compressed; | ||
636 | memcpy(v, &a, sizeof(a)); | ||
637 | } | ||
604 | 638 | ||
605 | static inline int rtnl_vfinfo_size(const struct net_device *dev) | 639 | static inline int rtnl_vfinfo_size(const struct net_device *dev) |
606 | { | 640 | { |
@@ -619,6 +653,7 @@ static inline size_t if_nlmsg_size(const struct net_device *dev) | |||
619 | + nla_total_size(IFNAMSIZ) /* IFLA_QDISC */ | 653 | + nla_total_size(IFNAMSIZ) /* IFLA_QDISC */ |
620 | + nla_total_size(sizeof(struct rtnl_link_ifmap)) | 654 | + nla_total_size(sizeof(struct rtnl_link_ifmap)) |
621 | + nla_total_size(sizeof(struct rtnl_link_stats)) | 655 | + nla_total_size(sizeof(struct rtnl_link_stats)) |
656 | + nla_total_size(sizeof(struct rtnl_link_stats64)) | ||
622 | + nla_total_size(MAX_ADDR_LEN) /* IFLA_ADDRESS */ | 657 | + nla_total_size(MAX_ADDR_LEN) /* IFLA_ADDRESS */ |
623 | + nla_total_size(MAX_ADDR_LEN) /* IFLA_BROADCAST */ | 658 | + nla_total_size(MAX_ADDR_LEN) /* IFLA_BROADCAST */ |
624 | + nla_total_size(4) /* IFLA_TXQLEN */ | 659 | + nla_total_size(4) /* IFLA_TXQLEN */ |
@@ -698,6 +733,12 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, | |||
698 | stats = dev_get_stats(dev); | 733 | stats = dev_get_stats(dev); |
699 | copy_rtnl_link_stats(nla_data(attr), stats); | 734 | copy_rtnl_link_stats(nla_data(attr), stats); |
700 | 735 | ||
736 | attr = nla_reserve(skb, IFLA_STATS64, | ||
737 | sizeof(struct rtnl_link_stats64)); | ||
738 | if (attr == NULL) | ||
739 | goto nla_put_failure; | ||
740 | copy_rtnl_link_stats64(nla_data(attr), stats); | ||
741 | |||
701 | if (dev->netdev_ops->ndo_get_vf_config && dev->dev.parent) { | 742 | if (dev->netdev_ops->ndo_get_vf_config && dev->dev.parent) { |
702 | int i; | 743 | int i; |
703 | struct ifla_vf_info ivi; | 744 | struct ifla_vf_info ivi; |
@@ -1473,6 +1514,7 @@ static int rtnetlink_event(struct notifier_block *this, unsigned long event, voi | |||
1473 | case NETDEV_POST_INIT: | 1514 | case NETDEV_POST_INIT: |
1474 | case NETDEV_REGISTER: | 1515 | case NETDEV_REGISTER: |
1475 | case NETDEV_CHANGE: | 1516 | case NETDEV_CHANGE: |
1517 | case NETDEV_PRE_TYPE_CHANGE: | ||
1476 | case NETDEV_GOING_DOWN: | 1518 | case NETDEV_GOING_DOWN: |
1477 | case NETDEV_UNREGISTER: | 1519 | case NETDEV_UNREGISTER: |
1478 | case NETDEV_UNREGISTER_BATCH: | 1520 | case NETDEV_UNREGISTER_BATCH: |
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 93c4e060c91e..bdea0efdf8cb 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
@@ -534,6 +534,7 @@ static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old) | |||
534 | new->network_header = old->network_header; | 534 | new->network_header = old->network_header; |
535 | new->mac_header = old->mac_header; | 535 | new->mac_header = old->mac_header; |
536 | skb_dst_set(new, dst_clone(skb_dst(old))); | 536 | skb_dst_set(new, dst_clone(skb_dst(old))); |
537 | new->rxhash = old->rxhash; | ||
537 | #ifdef CONFIG_XFRM | 538 | #ifdef CONFIG_XFRM |
538 | new->sp = secpath_get(old->sp); | 539 | new->sp = secpath_get(old->sp); |
539 | #endif | 540 | #endif |
@@ -581,6 +582,7 @@ static struct sk_buff *__skb_clone(struct sk_buff *n, struct sk_buff *skb) | |||
581 | C(len); | 582 | C(len); |
582 | C(data_len); | 583 | C(data_len); |
583 | C(mac_len); | 584 | C(mac_len); |
585 | C(rxhash); | ||
584 | n->hdr_len = skb->nohdr ? skb_headroom(skb) : skb->hdr_len; | 586 | n->hdr_len = skb->nohdr ? skb_headroom(skb) : skb->hdr_len; |
585 | n->cloned = 1; | 587 | n->cloned = 1; |
586 | n->nohdr = 0; | 588 | n->nohdr = 0; |
diff --git a/net/core/sock.c b/net/core/sock.c index fcd397a762ff..c5812bbc2cc9 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
@@ -340,8 +340,12 @@ int sk_receive_skb(struct sock *sk, struct sk_buff *skb, const int nested) | |||
340 | rc = sk_backlog_rcv(sk, skb); | 340 | rc = sk_backlog_rcv(sk, skb); |
341 | 341 | ||
342 | mutex_release(&sk->sk_lock.dep_map, 1, _RET_IP_); | 342 | mutex_release(&sk->sk_lock.dep_map, 1, _RET_IP_); |
343 | } else | 343 | } else if (sk_add_backlog(sk, skb)) { |
344 | sk_add_backlog(sk, skb); | 344 | bh_unlock_sock(sk); |
345 | atomic_inc(&sk->sk_drops); | ||
346 | goto discard_and_relse; | ||
347 | } | ||
348 | |||
345 | bh_unlock_sock(sk); | 349 | bh_unlock_sock(sk); |
346 | out: | 350 | out: |
347 | sock_put(sk); | 351 | sock_put(sk); |
@@ -1139,6 +1143,7 @@ struct sock *sk_clone(const struct sock *sk, const gfp_t priority) | |||
1139 | sock_lock_init(newsk); | 1143 | sock_lock_init(newsk); |
1140 | bh_lock_sock(newsk); | 1144 | bh_lock_sock(newsk); |
1141 | newsk->sk_backlog.head = newsk->sk_backlog.tail = NULL; | 1145 | newsk->sk_backlog.head = newsk->sk_backlog.tail = NULL; |
1146 | newsk->sk_backlog.len = 0; | ||
1142 | 1147 | ||
1143 | atomic_set(&newsk->sk_rmem_alloc, 0); | 1148 | atomic_set(&newsk->sk_rmem_alloc, 0); |
1144 | /* | 1149 | /* |
@@ -1542,6 +1547,12 @@ static void __release_sock(struct sock *sk) | |||
1542 | 1547 | ||
1543 | bh_lock_sock(sk); | 1548 | bh_lock_sock(sk); |
1544 | } while ((skb = sk->sk_backlog.head) != NULL); | 1549 | } while ((skb = sk->sk_backlog.head) != NULL); |
1550 | |||
1551 | /* | ||
1552 | * Doing the zeroing here guarantee we can not loop forever | ||
1553 | * while a wild producer attempts to flood us. | ||
1554 | */ | ||
1555 | sk->sk_backlog.len = 0; | ||
1545 | } | 1556 | } |
1546 | 1557 | ||
1547 | /** | 1558 | /** |
@@ -1874,6 +1885,7 @@ void sock_init_data(struct socket *sock, struct sock *sk) | |||
1874 | sk->sk_allocation = GFP_KERNEL; | 1885 | sk->sk_allocation = GFP_KERNEL; |
1875 | sk->sk_rcvbuf = sysctl_rmem_default; | 1886 | sk->sk_rcvbuf = sysctl_rmem_default; |
1876 | sk->sk_sndbuf = sysctl_wmem_default; | 1887 | sk->sk_sndbuf = sysctl_wmem_default; |
1888 | sk->sk_backlog.limit = sk->sk_rcvbuf << 1; | ||
1877 | sk->sk_state = TCP_CLOSE; | 1889 | sk->sk_state = TCP_CLOSE; |
1878 | sk_set_socket(sk, sock); | 1890 | sk_set_socket(sk, sock); |
1879 | 1891 | ||
@@ -2276,7 +2288,8 @@ out_free_request_sock_slab: | |||
2276 | prot->rsk_prot->slab = NULL; | 2288 | prot->rsk_prot->slab = NULL; |
2277 | } | 2289 | } |
2278 | out_free_request_sock_slab_name: | 2290 | out_free_request_sock_slab_name: |
2279 | kfree(prot->rsk_prot->slab_name); | 2291 | if (prot->rsk_prot) |
2292 | kfree(prot->rsk_prot->slab_name); | ||
2280 | out_free_sock_slab: | 2293 | out_free_sock_slab: |
2281 | kmem_cache_destroy(prot->slab); | 2294 | kmem_cache_destroy(prot->slab); |
2282 | prot->slab = NULL; | 2295 | prot->slab = NULL; |
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index bcd7632299f5..d3235899c7e3 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c | |||
@@ -208,7 +208,7 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data) | |||
208 | goto restart_timer; | 208 | goto restart_timer; |
209 | } | 209 | } |
210 | 210 | ||
211 | ccid3_pr_debug("%s(%p, state=%s) - entry \n", dccp_role(sk), sk, | 211 | ccid3_pr_debug("%s(%p, state=%s) - entry\n", dccp_role(sk), sk, |
212 | ccid3_tx_state_name(hc->tx_state)); | 212 | ccid3_tx_state_name(hc->tx_state)); |
213 | 213 | ||
214 | if (hc->tx_state == TFRC_SSTATE_FBACK) | 214 | if (hc->tx_state == TFRC_SSTATE_FBACK) |
diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h index 5ef32c2f0d6a..53f8e12d0c10 100644 --- a/net/dccp/dccp.h +++ b/net/dccp/dccp.h | |||
@@ -189,7 +189,7 @@ enum { | |||
189 | #define DCCP_MIB_MAX __DCCP_MIB_MAX | 189 | #define DCCP_MIB_MAX __DCCP_MIB_MAX |
190 | struct dccp_mib { | 190 | struct dccp_mib { |
191 | unsigned long mibs[DCCP_MIB_MAX]; | 191 | unsigned long mibs[DCCP_MIB_MAX]; |
192 | } __SNMP_MIB_ALIGN__; | 192 | }; |
193 | 193 | ||
194 | DECLARE_SNMP_STAT(struct dccp_mib, dccp_statistics); | 194 | DECLARE_SNMP_STAT(struct dccp_mib, dccp_statistics); |
195 | #define DCCP_INC_STATS(field) SNMP_INC_STATS(dccp_statistics, field) | 195 | #define DCCP_INC_STATS(field) SNMP_INC_STATS(dccp_statistics, field) |
diff --git a/net/dccp/input.c b/net/dccp/input.c index 7648f316310f..5daa4bdfdb10 100644 --- a/net/dccp/input.c +++ b/net/dccp/input.c | |||
@@ -414,7 +414,7 @@ static int dccp_rcv_request_sent_state_process(struct sock *sk, | |||
414 | if (!between48(DCCP_SKB_CB(skb)->dccpd_ack_seq, | 414 | if (!between48(DCCP_SKB_CB(skb)->dccpd_ack_seq, |
415 | dp->dccps_awl, dp->dccps_awh)) { | 415 | dp->dccps_awl, dp->dccps_awh)) { |
416 | dccp_pr_debug("invalid ackno: S.AWL=%llu, " | 416 | dccp_pr_debug("invalid ackno: S.AWL=%llu, " |
417 | "P.ackno=%llu, S.AWH=%llu \n", | 417 | "P.ackno=%llu, S.AWH=%llu\n", |
418 | (unsigned long long)dp->dccps_awl, | 418 | (unsigned long long)dp->dccps_awl, |
419 | (unsigned long long)DCCP_SKB_CB(skb)->dccpd_ack_seq, | 419 | (unsigned long long)DCCP_SKB_CB(skb)->dccpd_ack_seq, |
420 | (unsigned long long)dp->dccps_awh); | 420 | (unsigned long long)dp->dccps_awh); |
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index b195c4feaa0a..4071eaf2b361 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c | |||
@@ -998,11 +998,11 @@ static struct inet_protosw dccp_v4_protosw = { | |||
998 | 998 | ||
999 | static int __net_init dccp_v4_init_net(struct net *net) | 999 | static int __net_init dccp_v4_init_net(struct net *net) |
1000 | { | 1000 | { |
1001 | int err; | 1001 | if (dccp_hashinfo.bhash == NULL) |
1002 | return -ESOCKTNOSUPPORT; | ||
1002 | 1003 | ||
1003 | err = inet_ctl_sock_create(&net->dccp.v4_ctl_sk, PF_INET, | 1004 | return inet_ctl_sock_create(&net->dccp.v4_ctl_sk, PF_INET, |
1004 | SOCK_DCCP, IPPROTO_DCCP, net); | 1005 | SOCK_DCCP, IPPROTO_DCCP, net); |
1005 | return err; | ||
1006 | } | 1006 | } |
1007 | 1007 | ||
1008 | static void __net_exit dccp_v4_exit_net(struct net *net) | 1008 | static void __net_exit dccp_v4_exit_net(struct net *net) |
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index 1aec6349e858..af3394df63b7 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c | |||
@@ -1191,11 +1191,11 @@ static struct inet_protosw dccp_v6_protosw = { | |||
1191 | 1191 | ||
1192 | static int __net_init dccp_v6_init_net(struct net *net) | 1192 | static int __net_init dccp_v6_init_net(struct net *net) |
1193 | { | 1193 | { |
1194 | int err; | 1194 | if (dccp_hashinfo.bhash == NULL) |
1195 | return -ESOCKTNOSUPPORT; | ||
1195 | 1196 | ||
1196 | err = inet_ctl_sock_create(&net->dccp.v6_ctl_sk, PF_INET6, | 1197 | return inet_ctl_sock_create(&net->dccp.v6_ctl_sk, PF_INET6, |
1197 | SOCK_DCCP, IPPROTO_DCCP, net); | 1198 | SOCK_DCCP, IPPROTO_DCCP, net); |
1198 | return err; | ||
1199 | } | 1199 | } |
1200 | 1200 | ||
1201 | static void __net_exit dccp_v6_exit_net(struct net *net) | 1201 | static void __net_exit dccp_v6_exit_net(struct net *net) |
diff --git a/net/dccp/minisocks.c b/net/dccp/minisocks.c index af226a063141..0d508c359fa9 100644 --- a/net/dccp/minisocks.c +++ b/net/dccp/minisocks.c | |||
@@ -254,7 +254,7 @@ int dccp_child_process(struct sock *parent, struct sock *child, | |||
254 | * in main socket hash table and lock on listening | 254 | * in main socket hash table and lock on listening |
255 | * socket does not protect us more. | 255 | * socket does not protect us more. |
256 | */ | 256 | */ |
257 | sk_add_backlog(child, skb); | 257 | __sk_add_backlog(child, skb); |
258 | } | 258 | } |
259 | 259 | ||
260 | bh_unlock_sock(child); | 260 | bh_unlock_sock(child); |
diff --git a/net/dccp/proto.c b/net/dccp/proto.c index 0ef7061920c0..aa4cef374fd0 100644 --- a/net/dccp/proto.c +++ b/net/dccp/proto.c | |||
@@ -1036,7 +1036,7 @@ static int __init dccp_init(void) | |||
1036 | FIELD_SIZEOF(struct sk_buff, cb)); | 1036 | FIELD_SIZEOF(struct sk_buff, cb)); |
1037 | rc = percpu_counter_init(&dccp_orphan_count, 0); | 1037 | rc = percpu_counter_init(&dccp_orphan_count, 0); |
1038 | if (rc) | 1038 | if (rc) |
1039 | goto out; | 1039 | goto out_fail; |
1040 | rc = -ENOBUFS; | 1040 | rc = -ENOBUFS; |
1041 | inet_hashinfo_init(&dccp_hashinfo); | 1041 | inet_hashinfo_init(&dccp_hashinfo); |
1042 | dccp_hashinfo.bind_bucket_cachep = | 1042 | dccp_hashinfo.bind_bucket_cachep = |
@@ -1125,8 +1125,9 @@ static int __init dccp_init(void) | |||
1125 | goto out_sysctl_exit; | 1125 | goto out_sysctl_exit; |
1126 | 1126 | ||
1127 | dccp_timestamping_init(); | 1127 | dccp_timestamping_init(); |
1128 | out: | 1128 | |
1129 | return rc; | 1129 | return 0; |
1130 | |||
1130 | out_sysctl_exit: | 1131 | out_sysctl_exit: |
1131 | dccp_sysctl_exit(); | 1132 | dccp_sysctl_exit(); |
1132 | out_ackvec_exit: | 1133 | out_ackvec_exit: |
@@ -1135,18 +1136,19 @@ out_free_dccp_mib: | |||
1135 | dccp_mib_exit(); | 1136 | dccp_mib_exit(); |
1136 | out_free_dccp_bhash: | 1137 | out_free_dccp_bhash: |
1137 | free_pages((unsigned long)dccp_hashinfo.bhash, bhash_order); | 1138 | free_pages((unsigned long)dccp_hashinfo.bhash, bhash_order); |
1138 | dccp_hashinfo.bhash = NULL; | ||
1139 | out_free_dccp_locks: | 1139 | out_free_dccp_locks: |
1140 | inet_ehash_locks_free(&dccp_hashinfo); | 1140 | inet_ehash_locks_free(&dccp_hashinfo); |
1141 | out_free_dccp_ehash: | 1141 | out_free_dccp_ehash: |
1142 | free_pages((unsigned long)dccp_hashinfo.ehash, ehash_order); | 1142 | free_pages((unsigned long)dccp_hashinfo.ehash, ehash_order); |
1143 | dccp_hashinfo.ehash = NULL; | ||
1144 | out_free_bind_bucket_cachep: | 1143 | out_free_bind_bucket_cachep: |
1145 | kmem_cache_destroy(dccp_hashinfo.bind_bucket_cachep); | 1144 | kmem_cache_destroy(dccp_hashinfo.bind_bucket_cachep); |
1146 | dccp_hashinfo.bind_bucket_cachep = NULL; | ||
1147 | out_free_percpu: | 1145 | out_free_percpu: |
1148 | percpu_counter_destroy(&dccp_orphan_count); | 1146 | percpu_counter_destroy(&dccp_orphan_count); |
1149 | goto out; | 1147 | out_fail: |
1148 | dccp_hashinfo.bhash = NULL; | ||
1149 | dccp_hashinfo.ehash = NULL; | ||
1150 | dccp_hashinfo.bind_bucket_cachep = NULL; | ||
1151 | return rc; | ||
1150 | } | 1152 | } |
1151 | 1153 | ||
1152 | static void __exit dccp_fini(void) | 1154 | static void __exit dccp_fini(void) |
diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig index 0c94a1ac2946..c9a1c68767ff 100644 --- a/net/ipv4/Kconfig +++ b/net/ipv4/Kconfig | |||
@@ -587,9 +587,15 @@ choice | |||
587 | config DEFAULT_HTCP | 587 | config DEFAULT_HTCP |
588 | bool "Htcp" if TCP_CONG_HTCP=y | 588 | bool "Htcp" if TCP_CONG_HTCP=y |
589 | 589 | ||
590 | config DEFAULT_HYBLA | ||
591 | bool "Hybla" if TCP_CONG_HYBLA=y | ||
592 | |||
590 | config DEFAULT_VEGAS | 593 | config DEFAULT_VEGAS |
591 | bool "Vegas" if TCP_CONG_VEGAS=y | 594 | bool "Vegas" if TCP_CONG_VEGAS=y |
592 | 595 | ||
596 | config DEFAULT_VENO | ||
597 | bool "Veno" if TCP_CONG_VENO=y | ||
598 | |||
593 | config DEFAULT_WESTWOOD | 599 | config DEFAULT_WESTWOOD |
594 | bool "Westwood" if TCP_CONG_WESTWOOD=y | 600 | bool "Westwood" if TCP_CONG_WESTWOOD=y |
595 | 601 | ||
@@ -610,8 +616,10 @@ config DEFAULT_TCP_CONG | |||
610 | default "bic" if DEFAULT_BIC | 616 | default "bic" if DEFAULT_BIC |
611 | default "cubic" if DEFAULT_CUBIC | 617 | default "cubic" if DEFAULT_CUBIC |
612 | default "htcp" if DEFAULT_HTCP | 618 | default "htcp" if DEFAULT_HTCP |
619 | default "hybla" if DEFAULT_HYBLA | ||
613 | default "vegas" if DEFAULT_VEGAS | 620 | default "vegas" if DEFAULT_VEGAS |
614 | default "westwood" if DEFAULT_WESTWOOD | 621 | default "westwood" if DEFAULT_WESTWOOD |
622 | default "veno" if DEFAULT_VENO | ||
615 | default "reno" if DEFAULT_RENO | 623 | default "reno" if DEFAULT_RENO |
616 | default "cubic" | 624 | default "cubic" |
617 | 625 | ||
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 33b7dffa7732..55e11906a73a 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c | |||
@@ -1401,10 +1401,10 @@ EXPORT_SYMBOL_GPL(snmp_fold_field); | |||
1401 | int snmp_mib_init(void __percpu *ptr[2], size_t mibsize) | 1401 | int snmp_mib_init(void __percpu *ptr[2], size_t mibsize) |
1402 | { | 1402 | { |
1403 | BUG_ON(ptr == NULL); | 1403 | BUG_ON(ptr == NULL); |
1404 | ptr[0] = __alloc_percpu(mibsize, __alignof__(unsigned long long)); | 1404 | ptr[0] = __alloc_percpu(mibsize, __alignof__(unsigned long)); |
1405 | if (!ptr[0]) | 1405 | if (!ptr[0]) |
1406 | goto err0; | 1406 | goto err0; |
1407 | ptr[1] = __alloc_percpu(mibsize, __alignof__(unsigned long long)); | 1407 | ptr[1] = __alloc_percpu(mibsize, __alignof__(unsigned long)); |
1408 | if (!ptr[1]) | 1408 | if (!ptr[1]) |
1409 | goto err1; | 1409 | goto err1; |
1410 | return 0; | 1410 | return 0; |
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index 51ca946e3392..c75320ef95c2 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c | |||
@@ -1095,10 +1095,10 @@ static int inetdev_event(struct notifier_block *this, unsigned long event, | |||
1095 | case NETDEV_DOWN: | 1095 | case NETDEV_DOWN: |
1096 | ip_mc_down(in_dev); | 1096 | ip_mc_down(in_dev); |
1097 | break; | 1097 | break; |
1098 | case NETDEV_BONDING_OLDTYPE: | 1098 | case NETDEV_PRE_TYPE_CHANGE: |
1099 | ip_mc_unmap(in_dev); | 1099 | ip_mc_unmap(in_dev); |
1100 | break; | 1100 | break; |
1101 | case NETDEV_BONDING_NEWTYPE: | 1101 | case NETDEV_POST_TYPE_CHANGE: |
1102 | ip_mc_remap(in_dev); | 1102 | ip_mc_remap(in_dev); |
1103 | break; | 1103 | break; |
1104 | case NETDEV_CHANGEMTU: | 1104 | case NETDEV_CHANGEMTU: |
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index c0c5274d0271..f47c9f76754b 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c | |||
@@ -1144,12 +1144,9 @@ static int ipgre_header(struct sk_buff *skb, struct net_device *dev, | |||
1144 | 1144 | ||
1145 | if (saddr) | 1145 | if (saddr) |
1146 | memcpy(&iph->saddr, saddr, 4); | 1146 | memcpy(&iph->saddr, saddr, 4); |
1147 | 1147 | if (daddr) | |
1148 | if (daddr) { | ||
1149 | memcpy(&iph->daddr, daddr, 4); | 1148 | memcpy(&iph->daddr, daddr, 4); |
1150 | return t->hlen; | 1149 | if (iph->daddr) |
1151 | } | ||
1152 | if (iph->daddr && !ipv4_is_multicast(iph->daddr)) | ||
1153 | return t->hlen; | 1150 | return t->hlen; |
1154 | 1151 | ||
1155 | return -t->hlen; | 1152 | return -t->hlen; |
diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c index 10a6a604bf32..bf12d2a7a0c7 100644 --- a/net/ipv4/ipconfig.c +++ b/net/ipv4/ipconfig.c | |||
@@ -187,6 +187,16 @@ struct ic_device { | |||
187 | static struct ic_device *ic_first_dev __initdata = NULL;/* List of open device */ | 187 | static struct ic_device *ic_first_dev __initdata = NULL;/* List of open device */ |
188 | static struct net_device *ic_dev __initdata = NULL; /* Selected device */ | 188 | static struct net_device *ic_dev __initdata = NULL; /* Selected device */ |
189 | 189 | ||
190 | static bool __init ic_device_match(struct net_device *dev) | ||
191 | { | ||
192 | if (user_dev_name[0] ? !strcmp(dev->name, user_dev_name) : | ||
193 | (!(dev->flags & IFF_LOOPBACK) && | ||
194 | (dev->flags & (IFF_POINTOPOINT|IFF_BROADCAST)) && | ||
195 | strncmp(dev->name, "dummy", 5))) | ||
196 | return true; | ||
197 | return false; | ||
198 | } | ||
199 | |||
190 | static int __init ic_open_devs(void) | 200 | static int __init ic_open_devs(void) |
191 | { | 201 | { |
192 | struct ic_device *d, **last; | 202 | struct ic_device *d, **last; |
@@ -207,10 +217,7 @@ static int __init ic_open_devs(void) | |||
207 | for_each_netdev(&init_net, dev) { | 217 | for_each_netdev(&init_net, dev) { |
208 | if (dev->flags & IFF_LOOPBACK) | 218 | if (dev->flags & IFF_LOOPBACK) |
209 | continue; | 219 | continue; |
210 | if (user_dev_name[0] ? !strcmp(dev->name, user_dev_name) : | 220 | if (ic_device_match(dev)) { |
211 | (!(dev->flags & IFF_LOOPBACK) && | ||
212 | (dev->flags & (IFF_POINTOPOINT|IFF_BROADCAST)) && | ||
213 | strncmp(dev->name, "dummy", 5))) { | ||
214 | int able = 0; | 221 | int able = 0; |
215 | if (dev->mtu >= 364) | 222 | if (dev->mtu >= 364) |
216 | able |= IC_BOOTP; | 223 | able |= IC_BOOTP; |
@@ -228,7 +235,7 @@ static int __init ic_open_devs(void) | |||
228 | } | 235 | } |
229 | if (!(d = kmalloc(sizeof(struct ic_device), GFP_KERNEL))) { | 236 | if (!(d = kmalloc(sizeof(struct ic_device), GFP_KERNEL))) { |
230 | rtnl_unlock(); | 237 | rtnl_unlock(); |
231 | return -1; | 238 | return -ENOMEM; |
232 | } | 239 | } |
233 | d->dev = dev; | 240 | d->dev = dev; |
234 | *last = d; | 241 | *last = d; |
@@ -253,7 +260,7 @@ static int __init ic_open_devs(void) | |||
253 | printk(KERN_ERR "IP-Config: Device `%s' not found.\n", user_dev_name); | 260 | printk(KERN_ERR "IP-Config: Device `%s' not found.\n", user_dev_name); |
254 | else | 261 | else |
255 | printk(KERN_ERR "IP-Config: No network devices available.\n"); | 262 | printk(KERN_ERR "IP-Config: No network devices available.\n"); |
256 | return -1; | 263 | return -ENODEV; |
257 | } | 264 | } |
258 | return 0; | 265 | return 0; |
259 | } | 266 | } |
@@ -968,7 +975,7 @@ static int __init ic_bootp_recv(struct sk_buff *skb, struct net_device *dev, str | |||
968 | /* Is it a reply for the device we are configuring? */ | 975 | /* Is it a reply for the device we are configuring? */ |
969 | if (b->xid != ic_dev_xid) { | 976 | if (b->xid != ic_dev_xid) { |
970 | if (net_ratelimit()) | 977 | if (net_ratelimit()) |
971 | printk(KERN_ERR "DHCP/BOOTP: Ignoring delayed packet \n"); | 978 | printk(KERN_ERR "DHCP/BOOTP: Ignoring delayed packet\n"); |
972 | goto drop_unlock; | 979 | goto drop_unlock; |
973 | } | 980 | } |
974 | 981 | ||
@@ -1303,6 +1310,32 @@ __be32 __init root_nfs_parse_addr(char *name) | |||
1303 | return addr; | 1310 | return addr; |
1304 | } | 1311 | } |
1305 | 1312 | ||
1313 | #define DEVICE_WAIT_MAX 12 /* 12 seconds */ | ||
1314 | |||
1315 | static int __init wait_for_devices(void) | ||
1316 | { | ||
1317 | int i; | ||
1318 | |||
1319 | msleep(CONF_PRE_OPEN); | ||
1320 | for (i = 0; i < DEVICE_WAIT_MAX; i++) { | ||
1321 | struct net_device *dev; | ||
1322 | int found = 0; | ||
1323 | |||
1324 | rtnl_lock(); | ||
1325 | for_each_netdev(&init_net, dev) { | ||
1326 | if (ic_device_match(dev)) { | ||
1327 | found = 1; | ||
1328 | break; | ||
1329 | } | ||
1330 | } | ||
1331 | rtnl_unlock(); | ||
1332 | if (found) | ||
1333 | return 0; | ||
1334 | ssleep(1); | ||
1335 | } | ||
1336 | return -ENODEV; | ||
1337 | } | ||
1338 | |||
1306 | /* | 1339 | /* |
1307 | * IP Autoconfig dispatcher. | 1340 | * IP Autoconfig dispatcher. |
1308 | */ | 1341 | */ |
@@ -1313,6 +1346,7 @@ static int __init ip_auto_config(void) | |||
1313 | #ifdef IPCONFIG_DYNAMIC | 1346 | #ifdef IPCONFIG_DYNAMIC |
1314 | int retries = CONF_OPEN_RETRIES; | 1347 | int retries = CONF_OPEN_RETRIES; |
1315 | #endif | 1348 | #endif |
1349 | int err; | ||
1316 | 1350 | ||
1317 | #ifdef CONFIG_PROC_FS | 1351 | #ifdef CONFIG_PROC_FS |
1318 | proc_net_fops_create(&init_net, "pnp", S_IRUGO, &pnp_seq_fops); | 1352 | proc_net_fops_create(&init_net, "pnp", S_IRUGO, &pnp_seq_fops); |
@@ -1325,12 +1359,15 @@ static int __init ip_auto_config(void) | |||
1325 | #ifdef IPCONFIG_DYNAMIC | 1359 | #ifdef IPCONFIG_DYNAMIC |
1326 | try_try_again: | 1360 | try_try_again: |
1327 | #endif | 1361 | #endif |
1328 | /* Give hardware a chance to settle */ | 1362 | /* Wait for devices to appear */ |
1329 | msleep(CONF_PRE_OPEN); | 1363 | err = wait_for_devices(); |
1364 | if (err) | ||
1365 | return err; | ||
1330 | 1366 | ||
1331 | /* Setup all network devices */ | 1367 | /* Setup all network devices */ |
1332 | if (ic_open_devs() < 0) | 1368 | err = ic_open_devs(); |
1333 | return -1; | 1369 | if (err) |
1370 | return err; | ||
1334 | 1371 | ||
1335 | /* Give drivers a chance to settle */ | 1372 | /* Give drivers a chance to settle */ |
1336 | ssleep(CONF_POST_OPEN); | 1373 | ssleep(CONF_POST_OPEN); |
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 8582e12e4a62..0b9d03c54dc3 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c | |||
@@ -802,6 +802,9 @@ static int ipmr_mfc_add(struct net *net, struct mfcctl *mfc, int mrtsock) | |||
802 | int line; | 802 | int line; |
803 | struct mfc_cache *uc, *c, **cp; | 803 | struct mfc_cache *uc, *c, **cp; |
804 | 804 | ||
805 | if (mfc->mfcc_parent >= MAXVIFS) | ||
806 | return -ENFILE; | ||
807 | |||
805 | line = MFC_HASH(mfc->mfcc_mcastgrp.s_addr, mfc->mfcc_origin.s_addr); | 808 | line = MFC_HASH(mfc->mfcc_mcastgrp.s_addr, mfc->mfcc_origin.s_addr); |
806 | 809 | ||
807 | for (cp = &net->ipv4.mfc_cache_array[line]; | 810 | for (cp = &net->ipv4.mfc_cache_array[line]; |
diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c index 242ed2307370..3dc9914c1dce 100644 --- a/net/ipv4/proc.c +++ b/net/ipv4/proc.c | |||
@@ -249,6 +249,9 @@ static const struct snmp_mib snmp4_net_list[] = { | |||
249 | SNMP_MIB_ITEM("TCPSackShifted", LINUX_MIB_SACKSHIFTED), | 249 | SNMP_MIB_ITEM("TCPSackShifted", LINUX_MIB_SACKSHIFTED), |
250 | SNMP_MIB_ITEM("TCPSackMerged", LINUX_MIB_SACKMERGED), | 250 | SNMP_MIB_ITEM("TCPSackMerged", LINUX_MIB_SACKMERGED), |
251 | SNMP_MIB_ITEM("TCPSackShiftFallback", LINUX_MIB_SACKSHIFTFALLBACK), | 251 | SNMP_MIB_ITEM("TCPSackShiftFallback", LINUX_MIB_SACKSHIFTFALLBACK), |
252 | SNMP_MIB_ITEM("TCPBacklogDrop", LINUX_MIB_TCPBACKLOGDROP), | ||
253 | SNMP_MIB_ITEM("TCPMinTTLDrop", LINUX_MIB_TCPMINTTLDROP), | ||
254 | SNMP_MIB_ITEM("TCPDeferAcceptDrop", LINUX_MIB_TCPDEFERACCEPTDROP), | ||
252 | SNMP_MIB_SENTINEL | 255 | SNMP_MIB_SENTINEL |
253 | }; | 256 | }; |
254 | 257 | ||
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index b2ba5581d2ae..32d396196df8 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
@@ -146,7 +146,6 @@ static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst); | |||
146 | static void ipv4_link_failure(struct sk_buff *skb); | 146 | static void ipv4_link_failure(struct sk_buff *skb); |
147 | static void ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu); | 147 | static void ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu); |
148 | static int rt_garbage_collect(struct dst_ops *ops); | 148 | static int rt_garbage_collect(struct dst_ops *ops); |
149 | static void rt_emergency_hash_rebuild(struct net *net); | ||
150 | 149 | ||
151 | 150 | ||
152 | static struct dst_ops ipv4_dst_ops = { | 151 | static struct dst_ops ipv4_dst_ops = { |
@@ -780,11 +779,30 @@ static void rt_do_flush(int process_context) | |||
780 | #define FRACT_BITS 3 | 779 | #define FRACT_BITS 3 |
781 | #define ONE (1UL << FRACT_BITS) | 780 | #define ONE (1UL << FRACT_BITS) |
782 | 781 | ||
782 | /* | ||
783 | * Given a hash chain and an item in this hash chain, | ||
784 | * find if a previous entry has the same hash_inputs | ||
785 | * (but differs on tos, mark or oif) | ||
786 | * Returns 0 if an alias is found. | ||
787 | * Returns ONE if rth has no alias before itself. | ||
788 | */ | ||
789 | static int has_noalias(const struct rtable *head, const struct rtable *rth) | ||
790 | { | ||
791 | const struct rtable *aux = head; | ||
792 | |||
793 | while (aux != rth) { | ||
794 | if (compare_hash_inputs(&aux->fl, &rth->fl)) | ||
795 | return 0; | ||
796 | aux = aux->u.dst.rt_next; | ||
797 | } | ||
798 | return ONE; | ||
799 | } | ||
800 | |||
783 | static void rt_check_expire(void) | 801 | static void rt_check_expire(void) |
784 | { | 802 | { |
785 | static unsigned int rover; | 803 | static unsigned int rover; |
786 | unsigned int i = rover, goal; | 804 | unsigned int i = rover, goal; |
787 | struct rtable *rth, *aux, **rthp; | 805 | struct rtable *rth, **rthp; |
788 | unsigned long samples = 0; | 806 | unsigned long samples = 0; |
789 | unsigned long sum = 0, sum2 = 0; | 807 | unsigned long sum = 0, sum2 = 0; |
790 | unsigned long delta; | 808 | unsigned long delta; |
@@ -835,15 +853,7 @@ nofree: | |||
835 | * attributes don't unfairly skew | 853 | * attributes don't unfairly skew |
836 | * the length computation | 854 | * the length computation |
837 | */ | 855 | */ |
838 | for (aux = rt_hash_table[i].chain;;) { | 856 | length += has_noalias(rt_hash_table[i].chain, rth); |
839 | if (aux == rth) { | ||
840 | length += ONE; | ||
841 | break; | ||
842 | } | ||
843 | if (compare_hash_inputs(&aux->fl, &rth->fl)) | ||
844 | break; | ||
845 | aux = aux->u.dst.rt_next; | ||
846 | } | ||
847 | continue; | 857 | continue; |
848 | } | 858 | } |
849 | } else if (!rt_may_expire(rth, tmo, ip_rt_gc_timeout)) | 859 | } else if (!rt_may_expire(rth, tmo, ip_rt_gc_timeout)) |
@@ -922,10 +932,8 @@ static void rt_secret_rebuild_oneshot(struct net *net) | |||
922 | { | 932 | { |
923 | del_timer_sync(&net->ipv4.rt_secret_timer); | 933 | del_timer_sync(&net->ipv4.rt_secret_timer); |
924 | rt_cache_invalidate(net); | 934 | rt_cache_invalidate(net); |
925 | if (ip_rt_secret_interval) { | 935 | if (ip_rt_secret_interval) |
926 | net->ipv4.rt_secret_timer.expires += ip_rt_secret_interval; | 936 | mod_timer(&net->ipv4.rt_secret_timer, jiffies + ip_rt_secret_interval); |
927 | add_timer(&net->ipv4.rt_secret_timer); | ||
928 | } | ||
929 | } | 937 | } |
930 | 938 | ||
931 | static void rt_emergency_hash_rebuild(struct net *net) | 939 | static void rt_emergency_hash_rebuild(struct net *net) |
@@ -1073,6 +1081,21 @@ work_done: | |||
1073 | out: return 0; | 1081 | out: return 0; |
1074 | } | 1082 | } |
1075 | 1083 | ||
1084 | /* | ||
1085 | * Returns number of entries in a hash chain that have different hash_inputs | ||
1086 | */ | ||
1087 | static int slow_chain_length(const struct rtable *head) | ||
1088 | { | ||
1089 | int length = 0; | ||
1090 | const struct rtable *rth = head; | ||
1091 | |||
1092 | while (rth) { | ||
1093 | length += has_noalias(head, rth); | ||
1094 | rth = rth->u.dst.rt_next; | ||
1095 | } | ||
1096 | return length >> FRACT_BITS; | ||
1097 | } | ||
1098 | |||
1076 | static int rt_intern_hash(unsigned hash, struct rtable *rt, | 1099 | static int rt_intern_hash(unsigned hash, struct rtable *rt, |
1077 | struct rtable **rp, struct sk_buff *skb) | 1100 | struct rtable **rp, struct sk_buff *skb) |
1078 | { | 1101 | { |
@@ -1185,7 +1208,8 @@ restart: | |||
1185 | rt_free(cand); | 1208 | rt_free(cand); |
1186 | } | 1209 | } |
1187 | } else { | 1210 | } else { |
1188 | if (chain_length > rt_chain_length_max) { | 1211 | if (chain_length > rt_chain_length_max && |
1212 | slow_chain_length(rt_hash_table[hash].chain) > rt_chain_length_max) { | ||
1189 | struct net *net = dev_net(rt->u.dst.dev); | 1213 | struct net *net = dev_net(rt->u.dst.dev); |
1190 | int num = ++net->ipv4.current_rt_cache_rebuild_count; | 1214 | int num = ++net->ipv4.current_rt_cache_rebuild_count; |
1191 | if (!rt_caching(dev_net(rt->u.dst.dev))) { | 1215 | if (!rt_caching(dev_net(rt->u.dst.dev))) { |
@@ -1417,7 +1441,7 @@ void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw, | |||
1417 | dev_hold(rt->u.dst.dev); | 1441 | dev_hold(rt->u.dst.dev); |
1418 | if (rt->idev) | 1442 | if (rt->idev) |
1419 | in_dev_hold(rt->idev); | 1443 | in_dev_hold(rt->idev); |
1420 | rt->u.dst.obsolete = 0; | 1444 | rt->u.dst.obsolete = -1; |
1421 | rt->u.dst.lastuse = jiffies; | 1445 | rt->u.dst.lastuse = jiffies; |
1422 | rt->u.dst.path = &rt->u.dst; | 1446 | rt->u.dst.path = &rt->u.dst; |
1423 | rt->u.dst.neighbour = NULL; | 1447 | rt->u.dst.neighbour = NULL; |
@@ -1482,7 +1506,7 @@ static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst) | |||
1482 | struct dst_entry *ret = dst; | 1506 | struct dst_entry *ret = dst; |
1483 | 1507 | ||
1484 | if (rt) { | 1508 | if (rt) { |
1485 | if (dst->obsolete) { | 1509 | if (dst->obsolete > 0) { |
1486 | ip_rt_put(rt); | 1510 | ip_rt_put(rt); |
1487 | ret = NULL; | 1511 | ret = NULL; |
1488 | } else if ((rt->rt_flags & RTCF_REDIRECTED) || | 1512 | } else if ((rt->rt_flags & RTCF_REDIRECTED) || |
@@ -1702,7 +1726,9 @@ static void ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu) | |||
1702 | 1726 | ||
1703 | static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie) | 1727 | static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie) |
1704 | { | 1728 | { |
1705 | return NULL; | 1729 | if (rt_is_expired((struct rtable *)dst)) |
1730 | return NULL; | ||
1731 | return dst; | ||
1706 | } | 1732 | } |
1707 | 1733 | ||
1708 | static void ipv4_dst_destroy(struct dst_entry *dst) | 1734 | static void ipv4_dst_destroy(struct dst_entry *dst) |
@@ -1864,7 +1890,8 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr, | |||
1864 | if (!rth) | 1890 | if (!rth) |
1865 | goto e_nobufs; | 1891 | goto e_nobufs; |
1866 | 1892 | ||
1867 | rth->u.dst.output= ip_rt_bug; | 1893 | rth->u.dst.output = ip_rt_bug; |
1894 | rth->u.dst.obsolete = -1; | ||
1868 | 1895 | ||
1869 | atomic_set(&rth->u.dst.__refcnt, 1); | 1896 | atomic_set(&rth->u.dst.__refcnt, 1); |
1870 | rth->u.dst.flags= DST_HOST; | 1897 | rth->u.dst.flags= DST_HOST; |
@@ -2030,6 +2057,7 @@ static int __mkroute_input(struct sk_buff *skb, | |||
2030 | rth->fl.oif = 0; | 2057 | rth->fl.oif = 0; |
2031 | rth->rt_spec_dst= spec_dst; | 2058 | rth->rt_spec_dst= spec_dst; |
2032 | 2059 | ||
2060 | rth->u.dst.obsolete = -1; | ||
2033 | rth->u.dst.input = ip_forward; | 2061 | rth->u.dst.input = ip_forward; |
2034 | rth->u.dst.output = ip_output; | 2062 | rth->u.dst.output = ip_output; |
2035 | rth->rt_genid = rt_genid(dev_net(rth->u.dst.dev)); | 2063 | rth->rt_genid = rt_genid(dev_net(rth->u.dst.dev)); |
@@ -2194,6 +2222,7 @@ local_input: | |||
2194 | goto e_nobufs; | 2222 | goto e_nobufs; |
2195 | 2223 | ||
2196 | rth->u.dst.output= ip_rt_bug; | 2224 | rth->u.dst.output= ip_rt_bug; |
2225 | rth->u.dst.obsolete = -1; | ||
2197 | rth->rt_genid = rt_genid(net); | 2226 | rth->rt_genid = rt_genid(net); |
2198 | 2227 | ||
2199 | atomic_set(&rth->u.dst.__refcnt, 1); | 2228 | atomic_set(&rth->u.dst.__refcnt, 1); |
@@ -2420,6 +2449,7 @@ static int __mkroute_output(struct rtable **result, | |||
2420 | rth->rt_spec_dst= fl->fl4_src; | 2449 | rth->rt_spec_dst= fl->fl4_src; |
2421 | 2450 | ||
2422 | rth->u.dst.output=ip_output; | 2451 | rth->u.dst.output=ip_output; |
2452 | rth->u.dst.obsolete = -1; | ||
2423 | rth->rt_genid = rt_genid(dev_net(dev_out)); | 2453 | rth->rt_genid = rt_genid(dev_net(dev_out)); |
2424 | 2454 | ||
2425 | RT_CACHE_STAT_INC(out_slow_tot); | 2455 | RT_CACHE_STAT_INC(out_slow_tot); |
@@ -3077,22 +3107,20 @@ static void rt_secret_reschedule(int old) | |||
3077 | rtnl_lock(); | 3107 | rtnl_lock(); |
3078 | for_each_net(net) { | 3108 | for_each_net(net) { |
3079 | int deleted = del_timer_sync(&net->ipv4.rt_secret_timer); | 3109 | int deleted = del_timer_sync(&net->ipv4.rt_secret_timer); |
3110 | long time; | ||
3080 | 3111 | ||
3081 | if (!new) | 3112 | if (!new) |
3082 | continue; | 3113 | continue; |
3083 | 3114 | ||
3084 | if (deleted) { | 3115 | if (deleted) { |
3085 | long time = net->ipv4.rt_secret_timer.expires - jiffies; | 3116 | time = net->ipv4.rt_secret_timer.expires - jiffies; |
3086 | 3117 | ||
3087 | if (time <= 0 || (time += diff) <= 0) | 3118 | if (time <= 0 || (time += diff) <= 0) |
3088 | time = 0; | 3119 | time = 0; |
3089 | |||
3090 | net->ipv4.rt_secret_timer.expires = time; | ||
3091 | } else | 3120 | } else |
3092 | net->ipv4.rt_secret_timer.expires = new; | 3121 | time = new; |
3093 | 3122 | ||
3094 | net->ipv4.rt_secret_timer.expires += jiffies; | 3123 | mod_timer(&net->ipv4.rt_secret_timer, jiffies + time); |
3095 | add_timer(&net->ipv4.rt_secret_timer); | ||
3096 | } | 3124 | } |
3097 | rtnl_unlock(); | 3125 | rtnl_unlock(); |
3098 | } | 3126 | } |
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 5901010fad55..6afb6d8662b2 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
@@ -429,7 +429,7 @@ unsigned int tcp_poll(struct file *file, struct socket *sock, poll_table *wait) | |||
429 | if (tp->urg_seq == tp->copied_seq && | 429 | if (tp->urg_seq == tp->copied_seq && |
430 | !sock_flag(sk, SOCK_URGINLINE) && | 430 | !sock_flag(sk, SOCK_URGINLINE) && |
431 | tp->urg_data) | 431 | tp->urg_data) |
432 | target--; | 432 | target++; |
433 | 433 | ||
434 | /* Potential race condition. If read of tp below will | 434 | /* Potential race condition. If read of tp below will |
435 | * escape above sk->sk_state, we can be illegally awaken | 435 | * escape above sk->sk_state, we can be illegally awaken |
@@ -1254,6 +1254,39 @@ static void tcp_prequeue_process(struct sock *sk) | |||
1254 | tp->ucopy.memory = 0; | 1254 | tp->ucopy.memory = 0; |
1255 | } | 1255 | } |
1256 | 1256 | ||
1257 | #ifdef CONFIG_NET_DMA | ||
1258 | static void tcp_service_net_dma(struct sock *sk, bool wait) | ||
1259 | { | ||
1260 | dma_cookie_t done, used; | ||
1261 | dma_cookie_t last_issued; | ||
1262 | struct tcp_sock *tp = tcp_sk(sk); | ||
1263 | |||
1264 | if (!tp->ucopy.dma_chan) | ||
1265 | return; | ||
1266 | |||
1267 | last_issued = tp->ucopy.dma_cookie; | ||
1268 | dma_async_memcpy_issue_pending(tp->ucopy.dma_chan); | ||
1269 | |||
1270 | do { | ||
1271 | if (dma_async_memcpy_complete(tp->ucopy.dma_chan, | ||
1272 | last_issued, &done, | ||
1273 | &used) == DMA_SUCCESS) { | ||
1274 | /* Safe to free early-copied skbs now */ | ||
1275 | __skb_queue_purge(&sk->sk_async_wait_queue); | ||
1276 | break; | ||
1277 | } else { | ||
1278 | struct sk_buff *skb; | ||
1279 | while ((skb = skb_peek(&sk->sk_async_wait_queue)) && | ||
1280 | (dma_async_is_complete(skb->dma_cookie, done, | ||
1281 | used) == DMA_SUCCESS)) { | ||
1282 | __skb_dequeue(&sk->sk_async_wait_queue); | ||
1283 | kfree_skb(skb); | ||
1284 | } | ||
1285 | } | ||
1286 | } while (wait); | ||
1287 | } | ||
1288 | #endif | ||
1289 | |||
1257 | static inline struct sk_buff *tcp_recv_skb(struct sock *sk, u32 seq, u32 *off) | 1290 | static inline struct sk_buff *tcp_recv_skb(struct sock *sk, u32 seq, u32 *off) |
1258 | { | 1291 | { |
1259 | struct sk_buff *skb; | 1292 | struct sk_buff *skb; |
@@ -1546,6 +1579,10 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | |||
1546 | /* __ Set realtime policy in scheduler __ */ | 1579 | /* __ Set realtime policy in scheduler __ */ |
1547 | } | 1580 | } |
1548 | 1581 | ||
1582 | #ifdef CONFIG_NET_DMA | ||
1583 | if (tp->ucopy.dma_chan) | ||
1584 | dma_async_memcpy_issue_pending(tp->ucopy.dma_chan); | ||
1585 | #endif | ||
1549 | if (copied >= target) { | 1586 | if (copied >= target) { |
1550 | /* Do not sleep, just process backlog. */ | 1587 | /* Do not sleep, just process backlog. */ |
1551 | release_sock(sk); | 1588 | release_sock(sk); |
@@ -1554,6 +1591,7 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | |||
1554 | sk_wait_data(sk, &timeo); | 1591 | sk_wait_data(sk, &timeo); |
1555 | 1592 | ||
1556 | #ifdef CONFIG_NET_DMA | 1593 | #ifdef CONFIG_NET_DMA |
1594 | tcp_service_net_dma(sk, false); /* Don't block */ | ||
1557 | tp->ucopy.wakeup = 0; | 1595 | tp->ucopy.wakeup = 0; |
1558 | #endif | 1596 | #endif |
1559 | 1597 | ||
@@ -1633,6 +1671,9 @@ do_prequeue: | |||
1633 | copied = -EFAULT; | 1671 | copied = -EFAULT; |
1634 | break; | 1672 | break; |
1635 | } | 1673 | } |
1674 | |||
1675 | dma_async_memcpy_issue_pending(tp->ucopy.dma_chan); | ||
1676 | |||
1636 | if ((offset + used) == skb->len) | 1677 | if ((offset + used) == skb->len) |
1637 | copied_early = 1; | 1678 | copied_early = 1; |
1638 | 1679 | ||
@@ -1702,27 +1743,9 @@ skip_copy: | |||
1702 | } | 1743 | } |
1703 | 1744 | ||
1704 | #ifdef CONFIG_NET_DMA | 1745 | #ifdef CONFIG_NET_DMA |
1705 | if (tp->ucopy.dma_chan) { | 1746 | tcp_service_net_dma(sk, true); /* Wait for queue to drain */ |
1706 | dma_cookie_t done, used; | 1747 | tp->ucopy.dma_chan = NULL; |
1707 | |||
1708 | dma_async_memcpy_issue_pending(tp->ucopy.dma_chan); | ||
1709 | |||
1710 | while (dma_async_memcpy_complete(tp->ucopy.dma_chan, | ||
1711 | tp->ucopy.dma_cookie, &done, | ||
1712 | &used) == DMA_IN_PROGRESS) { | ||
1713 | /* do partial cleanup of sk_async_wait_queue */ | ||
1714 | while ((skb = skb_peek(&sk->sk_async_wait_queue)) && | ||
1715 | (dma_async_is_complete(skb->dma_cookie, done, | ||
1716 | used) == DMA_SUCCESS)) { | ||
1717 | __skb_dequeue(&sk->sk_async_wait_queue); | ||
1718 | kfree_skb(skb); | ||
1719 | } | ||
1720 | } | ||
1721 | 1748 | ||
1722 | /* Safe to free early-copied skbs now */ | ||
1723 | __skb_queue_purge(&sk->sk_async_wait_queue); | ||
1724 | tp->ucopy.dma_chan = NULL; | ||
1725 | } | ||
1726 | if (tp->ucopy.pinned_list) { | 1749 | if (tp->ucopy.pinned_list) { |
1727 | dma_unpin_iovec_pages(tp->ucopy.pinned_list); | 1750 | dma_unpin_iovec_pages(tp->ucopy.pinned_list); |
1728 | tp->ucopy.pinned_list = NULL; | 1751 | tp->ucopy.pinned_list = NULL; |
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 788851ca8c5d..7b31476a4063 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -2511,6 +2511,9 @@ static void tcp_mark_head_lost(struct sock *sk, int packets) | |||
2511 | int err; | 2511 | int err; |
2512 | unsigned int mss; | 2512 | unsigned int mss; |
2513 | 2513 | ||
2514 | if (packets == 0) | ||
2515 | return; | ||
2516 | |||
2514 | WARN_ON(packets > tp->packets_out); | 2517 | WARN_ON(packets > tp->packets_out); |
2515 | if (tp->lost_skb_hint) { | 2518 | if (tp->lost_skb_hint) { |
2516 | skb = tp->lost_skb_hint; | 2519 | skb = tp->lost_skb_hint; |
@@ -4315,7 +4318,7 @@ static void tcp_ofo_queue(struct sock *sk) | |||
4315 | } | 4318 | } |
4316 | 4319 | ||
4317 | if (!after(TCP_SKB_CB(skb)->end_seq, tp->rcv_nxt)) { | 4320 | if (!after(TCP_SKB_CB(skb)->end_seq, tp->rcv_nxt)) { |
4318 | SOCK_DEBUG(sk, "ofo packet was already received \n"); | 4321 | SOCK_DEBUG(sk, "ofo packet was already received\n"); |
4319 | __skb_unlink(skb, &tp->out_of_order_queue); | 4322 | __skb_unlink(skb, &tp->out_of_order_queue); |
4320 | __kfree_skb(skb); | 4323 | __kfree_skb(skb); |
4321 | continue; | 4324 | continue; |
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index c3588b4fd979..f4df5f931f36 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -370,6 +370,11 @@ void tcp_v4_err(struct sk_buff *icmp_skb, u32 info) | |||
370 | if (sk->sk_state == TCP_CLOSE) | 370 | if (sk->sk_state == TCP_CLOSE) |
371 | goto out; | 371 | goto out; |
372 | 372 | ||
373 | if (unlikely(iph->ttl < inet_sk(sk)->min_ttl)) { | ||
374 | NET_INC_STATS_BH(net, LINUX_MIB_TCPMINTTLDROP); | ||
375 | goto out; | ||
376 | } | ||
377 | |||
373 | icsk = inet_csk(sk); | 378 | icsk = inet_csk(sk); |
374 | tp = tcp_sk(sk); | 379 | tp = tcp_sk(sk); |
375 | seq = ntohl(th->seq); | 380 | seq = ntohl(th->seq); |
@@ -1651,13 +1656,15 @@ int tcp_v4_rcv(struct sk_buff *skb) | |||
1651 | if (!sk) | 1656 | if (!sk) |
1652 | goto no_tcp_socket; | 1657 | goto no_tcp_socket; |
1653 | 1658 | ||
1654 | if (iph->ttl < inet_sk(sk)->min_ttl) | ||
1655 | goto discard_and_relse; | ||
1656 | |||
1657 | process: | 1659 | process: |
1658 | if (sk->sk_state == TCP_TIME_WAIT) | 1660 | if (sk->sk_state == TCP_TIME_WAIT) |
1659 | goto do_time_wait; | 1661 | goto do_time_wait; |
1660 | 1662 | ||
1663 | if (unlikely(iph->ttl < inet_sk(sk)->min_ttl)) { | ||
1664 | NET_INC_STATS_BH(net, LINUX_MIB_TCPMINTTLDROP); | ||
1665 | goto discard_and_relse; | ||
1666 | } | ||
1667 | |||
1661 | if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb)) | 1668 | if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb)) |
1662 | goto discard_and_relse; | 1669 | goto discard_and_relse; |
1663 | nf_reset(skb); | 1670 | nf_reset(skb); |
@@ -1682,8 +1689,11 @@ process: | |||
1682 | if (!tcp_prequeue(sk, skb)) | 1689 | if (!tcp_prequeue(sk, skb)) |
1683 | ret = tcp_v4_do_rcv(sk, skb); | 1690 | ret = tcp_v4_do_rcv(sk, skb); |
1684 | } | 1691 | } |
1685 | } else | 1692 | } else if (unlikely(sk_add_backlog(sk, skb))) { |
1686 | sk_add_backlog(sk, skb); | 1693 | bh_unlock_sock(sk); |
1694 | NET_INC_STATS_BH(net, LINUX_MIB_TCPBACKLOGDROP); | ||
1695 | goto discard_and_relse; | ||
1696 | } | ||
1687 | bh_unlock_sock(sk); | 1697 | bh_unlock_sock(sk); |
1688 | 1698 | ||
1689 | sock_put(sk); | 1699 | sock_put(sk); |
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index f206ee5dda80..32f96278a24a 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c | |||
@@ -671,6 +671,7 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb, | |||
671 | if (req->retrans < inet_csk(sk)->icsk_accept_queue.rskq_defer_accept && | 671 | if (req->retrans < inet_csk(sk)->icsk_accept_queue.rskq_defer_accept && |
672 | TCP_SKB_CB(skb)->end_seq == tcp_rsk(req)->rcv_isn + 1) { | 672 | TCP_SKB_CB(skb)->end_seq == tcp_rsk(req)->rcv_isn + 1) { |
673 | inet_rsk(req)->acked = 1; | 673 | inet_rsk(req)->acked = 1; |
674 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPDEFERACCEPTDROP); | ||
674 | return NULL; | 675 | return NULL; |
675 | } | 676 | } |
676 | 677 | ||
@@ -728,7 +729,7 @@ int tcp_child_process(struct sock *parent, struct sock *child, | |||
728 | * in main socket hash table and lock on listening | 729 | * in main socket hash table and lock on listening |
729 | * socket does not protect us more. | 730 | * socket does not protect us more. |
730 | */ | 731 | */ |
731 | sk_add_backlog(child, skb); | 732 | __sk_add_backlog(child, skb); |
732 | } | 733 | } |
733 | 734 | ||
734 | bh_unlock_sock(child); | 735 | bh_unlock_sock(child); |
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 4a1605d3f909..f181b78f2385 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c | |||
@@ -2395,13 +2395,17 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst, | |||
2395 | struct tcp_extend_values *xvp = tcp_xv(rvp); | 2395 | struct tcp_extend_values *xvp = tcp_xv(rvp); |
2396 | struct inet_request_sock *ireq = inet_rsk(req); | 2396 | struct inet_request_sock *ireq = inet_rsk(req); |
2397 | struct tcp_sock *tp = tcp_sk(sk); | 2397 | struct tcp_sock *tp = tcp_sk(sk); |
2398 | const struct tcp_cookie_values *cvp = tp->cookie_values; | ||
2398 | struct tcphdr *th; | 2399 | struct tcphdr *th; |
2399 | struct sk_buff *skb; | 2400 | struct sk_buff *skb; |
2400 | struct tcp_md5sig_key *md5; | 2401 | struct tcp_md5sig_key *md5; |
2401 | int tcp_header_size; | 2402 | int tcp_header_size; |
2402 | int mss; | 2403 | int mss; |
2404 | int s_data_desired = 0; | ||
2403 | 2405 | ||
2404 | skb = sock_wmalloc(sk, MAX_TCP_HEADER + 15, 1, GFP_ATOMIC); | 2406 | if (cvp != NULL && cvp->s_data_constant && cvp->s_data_desired) |
2407 | s_data_desired = cvp->s_data_desired; | ||
2408 | skb = sock_wmalloc(sk, MAX_TCP_HEADER + 15 + s_data_desired, 1, GFP_ATOMIC); | ||
2405 | if (skb == NULL) | 2409 | if (skb == NULL) |
2406 | return NULL; | 2410 | return NULL; |
2407 | 2411 | ||
@@ -2457,16 +2461,12 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst, | |||
2457 | TCPCB_FLAG_SYN | TCPCB_FLAG_ACK); | 2461 | TCPCB_FLAG_SYN | TCPCB_FLAG_ACK); |
2458 | 2462 | ||
2459 | if (OPTION_COOKIE_EXTENSION & opts.options) { | 2463 | if (OPTION_COOKIE_EXTENSION & opts.options) { |
2460 | const struct tcp_cookie_values *cvp = tp->cookie_values; | 2464 | if (s_data_desired) { |
2461 | 2465 | u8 *buf = skb_put(skb, s_data_desired); | |
2462 | if (cvp != NULL && | ||
2463 | cvp->s_data_constant && | ||
2464 | cvp->s_data_desired > 0) { | ||
2465 | u8 *buf = skb_put(skb, cvp->s_data_desired); | ||
2466 | 2466 | ||
2467 | /* copy data directly from the listening socket. */ | 2467 | /* copy data directly from the listening socket. */ |
2468 | memcpy(buf, cvp->s_data_payload, cvp->s_data_desired); | 2468 | memcpy(buf, cvp->s_data_payload, s_data_desired); |
2469 | TCP_SKB_CB(skb)->end_seq += cvp->s_data_desired; | 2469 | TCP_SKB_CB(skb)->end_seq += s_data_desired; |
2470 | } | 2470 | } |
2471 | 2471 | ||
2472 | if (opts.hash_size > 0) { | 2472 | if (opts.hash_size > 0) { |
diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c index a17629b8912e..b2e6bbccaee1 100644 --- a/net/ipv4/tcp_timer.c +++ b/net/ipv4/tcp_timer.c | |||
@@ -134,7 +134,7 @@ static void tcp_mtu_probing(struct inet_connection_sock *icsk, struct sock *sk) | |||
134 | } | 134 | } |
135 | 135 | ||
136 | /* This function calculates a "timeout" which is equivalent to the timeout of a | 136 | /* This function calculates a "timeout" which is equivalent to the timeout of a |
137 | * TCP connection after "boundary" unsucessful, exponentially backed-off | 137 | * TCP connection after "boundary" unsuccessful, exponentially backed-off |
138 | * retransmissions with an initial RTO of TCP_RTO_MIN. | 138 | * retransmissions with an initial RTO of TCP_RTO_MIN. |
139 | */ | 139 | */ |
140 | static bool retransmits_timed_out(struct sock *sk, | 140 | static bool retransmits_timed_out(struct sock *sk, |
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 608a5446d05b..7af756d0f931 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
@@ -1371,8 +1371,10 @@ int udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
1371 | bh_lock_sock(sk); | 1371 | bh_lock_sock(sk); |
1372 | if (!sock_owned_by_user(sk)) | 1372 | if (!sock_owned_by_user(sk)) |
1373 | rc = __udp_queue_rcv_skb(sk, skb); | 1373 | rc = __udp_queue_rcv_skb(sk, skb); |
1374 | else | 1374 | else if (sk_add_backlog(sk, skb)) { |
1375 | sk_add_backlog(sk, skb); | 1375 | bh_unlock_sock(sk); |
1376 | goto drop; | ||
1377 | } | ||
1376 | bh_unlock_sock(sk); | 1378 | bh_unlock_sock(sk); |
1377 | 1379 | ||
1378 | return rc; | 1380 | return rc; |
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c index 67107d63c1cd..e4a1483fba77 100644 --- a/net/ipv4/xfrm4_policy.c +++ b/net/ipv4/xfrm4_policy.c | |||
@@ -91,11 +91,12 @@ static int xfrm4_init_path(struct xfrm_dst *path, struct dst_entry *dst, | |||
91 | return 0; | 91 | return 0; |
92 | } | 92 | } |
93 | 93 | ||
94 | static int xfrm4_fill_dst(struct xfrm_dst *xdst, struct net_device *dev) | 94 | static int xfrm4_fill_dst(struct xfrm_dst *xdst, struct net_device *dev, |
95 | struct flowi *fl) | ||
95 | { | 96 | { |
96 | struct rtable *rt = (struct rtable *)xdst->route; | 97 | struct rtable *rt = (struct rtable *)xdst->route; |
97 | 98 | ||
98 | xdst->u.rt.fl = rt->fl; | 99 | xdst->u.rt.fl = *fl; |
99 | 100 | ||
100 | xdst->u.dst.dev = dev; | 101 | xdst->u.dst.dev = dev; |
101 | dev_hold(dev); | 102 | dev_hold(dev); |
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 88fd8c5877ee..21b4c9e1a682 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -81,7 +81,7 @@ | |||
81 | #include <linux/random.h> | 81 | #include <linux/random.h> |
82 | #endif | 82 | #endif |
83 | 83 | ||
84 | #include <asm/uaccess.h> | 84 | #include <linux/uaccess.h> |
85 | #include <asm/unaligned.h> | 85 | #include <asm/unaligned.h> |
86 | 86 | ||
87 | #include <linux/proc_fs.h> | 87 | #include <linux/proc_fs.h> |
@@ -97,7 +97,11 @@ | |||
97 | #endif | 97 | #endif |
98 | 98 | ||
99 | #define INFINITY_LIFE_TIME 0xFFFFFFFF | 99 | #define INFINITY_LIFE_TIME 0xFFFFFFFF |
100 | #define TIME_DELTA(a,b) ((unsigned long)((long)(a) - (long)(b))) | 100 | #define TIME_DELTA(a, b) ((unsigned long)((long)(a) - (long)(b))) |
101 | |||
102 | #define ADDRCONF_TIMER_FUZZ_MINUS (HZ > 50 ? HZ/50 : 1) | ||
103 | #define ADDRCONF_TIMER_FUZZ (HZ / 4) | ||
104 | #define ADDRCONF_TIMER_FUZZ_MAX (HZ) | ||
101 | 105 | ||
102 | #ifdef CONFIG_SYSCTL | 106 | #ifdef CONFIG_SYSCTL |
103 | static void addrconf_sysctl_register(struct inet6_dev *idev); | 107 | static void addrconf_sysctl_register(struct inet6_dev *idev); |
@@ -126,8 +130,8 @@ static int ipv6_count_addresses(struct inet6_dev *idev); | |||
126 | /* | 130 | /* |
127 | * Configured unicast address hash table | 131 | * Configured unicast address hash table |
128 | */ | 132 | */ |
129 | static struct inet6_ifaddr *inet6_addr_lst[IN6_ADDR_HSIZE]; | 133 | static struct hlist_head inet6_addr_lst[IN6_ADDR_HSIZE]; |
130 | static DEFINE_RWLOCK(addrconf_hash_lock); | 134 | static DEFINE_SPINLOCK(addrconf_hash_lock); |
131 | 135 | ||
132 | static void addrconf_verify(unsigned long); | 136 | static void addrconf_verify(unsigned long); |
133 | 137 | ||
@@ -137,8 +141,8 @@ static DEFINE_SPINLOCK(addrconf_verify_lock); | |||
137 | static void addrconf_join_anycast(struct inet6_ifaddr *ifp); | 141 | static void addrconf_join_anycast(struct inet6_ifaddr *ifp); |
138 | static void addrconf_leave_anycast(struct inet6_ifaddr *ifp); | 142 | static void addrconf_leave_anycast(struct inet6_ifaddr *ifp); |
139 | 143 | ||
140 | static void addrconf_bonding_change(struct net_device *dev, | 144 | static void addrconf_type_change(struct net_device *dev, |
141 | unsigned long event); | 145 | unsigned long event); |
142 | static int addrconf_ifdown(struct net_device *dev, int how); | 146 | static int addrconf_ifdown(struct net_device *dev, int how); |
143 | 147 | ||
144 | static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags); | 148 | static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags); |
@@ -151,8 +155,8 @@ static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifa); | |||
151 | 155 | ||
152 | static void inet6_prefix_notify(int event, struct inet6_dev *idev, | 156 | static void inet6_prefix_notify(int event, struct inet6_dev *idev, |
153 | struct prefix_info *pinfo); | 157 | struct prefix_info *pinfo); |
154 | static int ipv6_chk_same_addr(struct net *net, const struct in6_addr *addr, | 158 | static bool ipv6_chk_same_addr(struct net *net, const struct in6_addr *addr, |
155 | struct net_device *dev); | 159 | struct net_device *dev); |
156 | 160 | ||
157 | static ATOMIC_NOTIFIER_HEAD(inet6addr_chain); | 161 | static ATOMIC_NOTIFIER_HEAD(inet6addr_chain); |
158 | 162 | ||
@@ -249,8 +253,7 @@ static void addrconf_del_timer(struct inet6_ifaddr *ifp) | |||
249 | __in6_ifa_put(ifp); | 253 | __in6_ifa_put(ifp); |
250 | } | 254 | } |
251 | 255 | ||
252 | enum addrconf_timer_t | 256 | enum addrconf_timer_t { |
253 | { | ||
254 | AC_NONE, | 257 | AC_NONE, |
255 | AC_DAD, | 258 | AC_DAD, |
256 | AC_RS, | 259 | AC_RS, |
@@ -270,7 +273,8 @@ static void addrconf_mod_timer(struct inet6_ifaddr *ifp, | |||
270 | case AC_RS: | 273 | case AC_RS: |
271 | ifp->timer.function = addrconf_rs_timer; | 274 | ifp->timer.function = addrconf_rs_timer; |
272 | break; | 275 | break; |
273 | default:; | 276 | default: |
277 | break; | ||
274 | } | 278 | } |
275 | ifp->timer.expires = jiffies + when; | 279 | ifp->timer.expires = jiffies + when; |
276 | add_timer(&ifp->timer); | 280 | add_timer(&ifp->timer); |
@@ -317,7 +321,7 @@ void in6_dev_finish_destroy(struct inet6_dev *idev) | |||
317 | { | 321 | { |
318 | struct net_device *dev = idev->dev; | 322 | struct net_device *dev = idev->dev; |
319 | 323 | ||
320 | WARN_ON(idev->addr_list != NULL); | 324 | WARN_ON(!list_empty(&idev->addr_list)); |
321 | WARN_ON(idev->mc_list != NULL); | 325 | WARN_ON(idev->mc_list != NULL); |
322 | 326 | ||
323 | #ifdef NET_REFCNT_DEBUG | 327 | #ifdef NET_REFCNT_DEBUG |
@@ -325,7 +329,7 @@ void in6_dev_finish_destroy(struct inet6_dev *idev) | |||
325 | #endif | 329 | #endif |
326 | dev_put(dev); | 330 | dev_put(dev); |
327 | if (!idev->dead) { | 331 | if (!idev->dead) { |
328 | printk("Freeing alive inet6 device %p\n", idev); | 332 | pr_warning("Freeing alive inet6 device %p\n", idev); |
329 | return; | 333 | return; |
330 | } | 334 | } |
331 | snmp6_free_dev(idev); | 335 | snmp6_free_dev(idev); |
@@ -350,6 +354,8 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev) | |||
350 | 354 | ||
351 | rwlock_init(&ndev->lock); | 355 | rwlock_init(&ndev->lock); |
352 | ndev->dev = dev; | 356 | ndev->dev = dev; |
357 | INIT_LIST_HEAD(&ndev->addr_list); | ||
358 | |||
353 | memcpy(&ndev->cnf, dev_net(dev)->ipv6.devconf_dflt, sizeof(ndev->cnf)); | 359 | memcpy(&ndev->cnf, dev_net(dev)->ipv6.devconf_dflt, sizeof(ndev->cnf)); |
354 | ndev->cnf.mtu6 = dev->mtu; | 360 | ndev->cnf.mtu6 = dev->mtu; |
355 | ndev->cnf.sysctl = NULL; | 361 | ndev->cnf.sysctl = NULL; |
@@ -401,6 +407,7 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev) | |||
401 | #endif | 407 | #endif |
402 | 408 | ||
403 | #ifdef CONFIG_IPV6_PRIVACY | 409 | #ifdef CONFIG_IPV6_PRIVACY |
410 | INIT_LIST_HEAD(&ndev->tempaddr_list); | ||
404 | setup_timer(&ndev->regen_timer, ipv6_regen_rndid, (unsigned long)ndev); | 411 | setup_timer(&ndev->regen_timer, ipv6_regen_rndid, (unsigned long)ndev); |
405 | if ((dev->flags&IFF_LOOPBACK) || | 412 | if ((dev->flags&IFF_LOOPBACK) || |
406 | dev->type == ARPHRD_TUNNEL || | 413 | dev->type == ARPHRD_TUNNEL || |
@@ -438,8 +445,10 @@ static struct inet6_dev * ipv6_find_idev(struct net_device *dev) | |||
438 | 445 | ||
439 | ASSERT_RTNL(); | 446 | ASSERT_RTNL(); |
440 | 447 | ||
441 | if ((idev = __in6_dev_get(dev)) == NULL) { | 448 | idev = __in6_dev_get(dev); |
442 | if ((idev = ipv6_add_dev(dev)) == NULL) | 449 | if (!idev) { |
450 | idev = ipv6_add_dev(dev); | ||
451 | if (!idev) | ||
443 | return NULL; | 452 | return NULL; |
444 | } | 453 | } |
445 | 454 | ||
@@ -465,7 +474,8 @@ static void dev_forward_change(struct inet6_dev *idev) | |||
465 | else | 474 | else |
466 | ipv6_dev_mc_dec(dev, &in6addr_linklocal_allrouters); | 475 | ipv6_dev_mc_dec(dev, &in6addr_linklocal_allrouters); |
467 | } | 476 | } |
468 | for (ifa=idev->addr_list; ifa; ifa=ifa->if_next) { | 477 | |
478 | list_for_each_entry(ifa, &idev->addr_list, if_list) { | ||
469 | if (ifa->flags&IFA_F_TENTATIVE) | 479 | if (ifa->flags&IFA_F_TENTATIVE) |
470 | continue; | 480 | continue; |
471 | if (idev->cnf.forwarding) | 481 | if (idev->cnf.forwarding) |
@@ -522,12 +532,16 @@ static int addrconf_fixup_forwarding(struct ctl_table *table, int *p, int old) | |||
522 | } | 532 | } |
523 | #endif | 533 | #endif |
524 | 534 | ||
525 | /* Nobody refers to this ifaddr, destroy it */ | 535 | static void inet6_ifa_finish_destroy_rcu(struct rcu_head *head) |
536 | { | ||
537 | struct inet6_ifaddr *ifp = container_of(head, struct inet6_ifaddr, rcu); | ||
538 | kfree(ifp); | ||
539 | } | ||
526 | 540 | ||
541 | /* Nobody refers to this ifaddr, destroy it */ | ||
527 | void inet6_ifa_finish_destroy(struct inet6_ifaddr *ifp) | 542 | void inet6_ifa_finish_destroy(struct inet6_ifaddr *ifp) |
528 | { | 543 | { |
529 | WARN_ON(ifp->if_next != NULL); | 544 | WARN_ON(!hlist_unhashed(&ifp->addr_lst)); |
530 | WARN_ON(ifp->lst_next != NULL); | ||
531 | 545 | ||
532 | #ifdef NET_REFCNT_DEBUG | 546 | #ifdef NET_REFCNT_DEBUG |
533 | printk(KERN_DEBUG "inet6_ifa_finish_destroy\n"); | 547 | printk(KERN_DEBUG "inet6_ifa_finish_destroy\n"); |
@@ -536,54 +550,45 @@ void inet6_ifa_finish_destroy(struct inet6_ifaddr *ifp) | |||
536 | in6_dev_put(ifp->idev); | 550 | in6_dev_put(ifp->idev); |
537 | 551 | ||
538 | if (del_timer(&ifp->timer)) | 552 | if (del_timer(&ifp->timer)) |
539 | printk("Timer is still running, when freeing ifa=%p\n", ifp); | 553 | pr_notice("Timer is still running, when freeing ifa=%p\n", ifp); |
540 | 554 | ||
541 | if (!ifp->dead) { | 555 | if (!ifp->dead) { |
542 | printk("Freeing alive inet6 address %p\n", ifp); | 556 | pr_warning("Freeing alive inet6 address %p\n", ifp); |
543 | return; | 557 | return; |
544 | } | 558 | } |
545 | dst_release(&ifp->rt->u.dst); | 559 | dst_release(&ifp->rt->u.dst); |
546 | 560 | ||
547 | kfree(ifp); | 561 | call_rcu(&ifp->rcu, inet6_ifa_finish_destroy_rcu); |
548 | } | 562 | } |
549 | 563 | ||
550 | static void | 564 | static void |
551 | ipv6_link_dev_addr(struct inet6_dev *idev, struct inet6_ifaddr *ifp) | 565 | ipv6_link_dev_addr(struct inet6_dev *idev, struct inet6_ifaddr *ifp) |
552 | { | 566 | { |
553 | struct inet6_ifaddr *ifa, **ifap; | 567 | struct list_head *p; |
554 | int ifp_scope = ipv6_addr_src_scope(&ifp->addr); | 568 | int ifp_scope = ipv6_addr_src_scope(&ifp->addr); |
555 | 569 | ||
556 | /* | 570 | /* |
557 | * Each device address list is sorted in order of scope - | 571 | * Each device address list is sorted in order of scope - |
558 | * global before linklocal. | 572 | * global before linklocal. |
559 | */ | 573 | */ |
560 | for (ifap = &idev->addr_list; (ifa = *ifap) != NULL; | 574 | list_for_each(p, &idev->addr_list) { |
561 | ifap = &ifa->if_next) { | 575 | struct inet6_ifaddr *ifa |
576 | = list_entry(p, struct inet6_ifaddr, if_list); | ||
562 | if (ifp_scope >= ipv6_addr_src_scope(&ifa->addr)) | 577 | if (ifp_scope >= ipv6_addr_src_scope(&ifa->addr)) |
563 | break; | 578 | break; |
564 | } | 579 | } |
565 | 580 | ||
566 | ifp->if_next = *ifap; | 581 | list_add_tail(&ifp->if_list, p); |
567 | *ifap = ifp; | ||
568 | } | 582 | } |
569 | 583 | ||
570 | /* | 584 | static u32 ipv6_addr_hash(const struct in6_addr *addr) |
571 | * Hash function taken from net_alias.c | ||
572 | */ | ||
573 | static u8 ipv6_addr_hash(const struct in6_addr *addr) | ||
574 | { | 585 | { |
575 | __u32 word; | ||
576 | |||
577 | /* | 586 | /* |
578 | * We perform the hash function over the last 64 bits of the address | 587 | * We perform the hash function over the last 64 bits of the address |
579 | * This will include the IEEE address token on links that support it. | 588 | * This will include the IEEE address token on links that support it. |
580 | */ | 589 | */ |
581 | 590 | return jhash_2words(addr->s6_addr32[2], addr->s6_addr32[3], 0) | |
582 | word = (__force u32)(addr->s6_addr32[2] ^ addr->s6_addr32[3]); | 591 | & (IN6_ADDR_HSIZE - 1); |
583 | word ^= (word >> 16); | ||
584 | word ^= (word >> 8); | ||
585 | |||
586 | return ((word ^ (word >> 4)) & 0x0f); | ||
587 | } | 592 | } |
588 | 593 | ||
589 | /* On success it returns ifp with increased reference count */ | 594 | /* On success it returns ifp with increased reference count */ |
@@ -594,7 +599,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen, | |||
594 | { | 599 | { |
595 | struct inet6_ifaddr *ifa = NULL; | 600 | struct inet6_ifaddr *ifa = NULL; |
596 | struct rt6_info *rt; | 601 | struct rt6_info *rt; |
597 | int hash; | 602 | unsigned int hash; |
598 | int err = 0; | 603 | int err = 0; |
599 | int addr_type = ipv6_addr_type(addr); | 604 | int addr_type = ipv6_addr_type(addr); |
600 | 605 | ||
@@ -615,7 +620,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen, | |||
615 | goto out2; | 620 | goto out2; |
616 | } | 621 | } |
617 | 622 | ||
618 | write_lock(&addrconf_hash_lock); | 623 | spin_lock(&addrconf_hash_lock); |
619 | 624 | ||
620 | /* Ignore adding duplicate addresses on an interface */ | 625 | /* Ignore adding duplicate addresses on an interface */ |
621 | if (ipv6_chk_same_addr(dev_net(idev->dev), addr, idev->dev)) { | 626 | if (ipv6_chk_same_addr(dev_net(idev->dev), addr, idev->dev)) { |
@@ -642,6 +647,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen, | |||
642 | 647 | ||
643 | spin_lock_init(&ifa->lock); | 648 | spin_lock_init(&ifa->lock); |
644 | init_timer(&ifa->timer); | 649 | init_timer(&ifa->timer); |
650 | INIT_HLIST_NODE(&ifa->addr_lst); | ||
645 | ifa->timer.data = (unsigned long) ifa; | 651 | ifa->timer.data = (unsigned long) ifa; |
646 | ifa->scope = scope; | 652 | ifa->scope = scope; |
647 | ifa->prefix_len = pfxlen; | 653 | ifa->prefix_len = pfxlen; |
@@ -668,10 +674,9 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen, | |||
668 | /* Add to big hash table */ | 674 | /* Add to big hash table */ |
669 | hash = ipv6_addr_hash(addr); | 675 | hash = ipv6_addr_hash(addr); |
670 | 676 | ||
671 | ifa->lst_next = inet6_addr_lst[hash]; | 677 | hlist_add_head_rcu(&ifa->addr_lst, &inet6_addr_lst[hash]); |
672 | inet6_addr_lst[hash] = ifa; | ||
673 | in6_ifa_hold(ifa); | 678 | in6_ifa_hold(ifa); |
674 | write_unlock(&addrconf_hash_lock); | 679 | spin_unlock(&addrconf_hash_lock); |
675 | 680 | ||
676 | write_lock(&idev->lock); | 681 | write_lock(&idev->lock); |
677 | /* Add to inet6_dev unicast addr list. */ | 682 | /* Add to inet6_dev unicast addr list. */ |
@@ -679,8 +684,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen, | |||
679 | 684 | ||
680 | #ifdef CONFIG_IPV6_PRIVACY | 685 | #ifdef CONFIG_IPV6_PRIVACY |
681 | if (ifa->flags&IFA_F_TEMPORARY) { | 686 | if (ifa->flags&IFA_F_TEMPORARY) { |
682 | ifa->tmp_next = idev->tempaddr_list; | 687 | list_add(&ifa->tmp_list, &idev->tempaddr_list); |
683 | idev->tempaddr_list = ifa; | ||
684 | in6_ifa_hold(ifa); | 688 | in6_ifa_hold(ifa); |
685 | } | 689 | } |
686 | #endif | 690 | #endif |
@@ -699,7 +703,7 @@ out2: | |||
699 | 703 | ||
700 | return ifa; | 704 | return ifa; |
701 | out: | 705 | out: |
702 | write_unlock(&addrconf_hash_lock); | 706 | spin_unlock(&addrconf_hash_lock); |
703 | goto out2; | 707 | goto out2; |
704 | } | 708 | } |
705 | 709 | ||
@@ -707,7 +711,7 @@ out: | |||
707 | 711 | ||
708 | static void ipv6_del_addr(struct inet6_ifaddr *ifp) | 712 | static void ipv6_del_addr(struct inet6_ifaddr *ifp) |
709 | { | 713 | { |
710 | struct inet6_ifaddr *ifa, **ifap; | 714 | struct inet6_ifaddr *ifa, *ifn; |
711 | struct inet6_dev *idev = ifp->idev; | 715 | struct inet6_dev *idev = ifp->idev; |
712 | int hash; | 716 | int hash; |
713 | int deleted = 0, onlink = 0; | 717 | int deleted = 0, onlink = 0; |
@@ -717,42 +721,28 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp) | |||
717 | 721 | ||
718 | ifp->dead = 1; | 722 | ifp->dead = 1; |
719 | 723 | ||
720 | write_lock_bh(&addrconf_hash_lock); | 724 | spin_lock_bh(&addrconf_hash_lock); |
721 | for (ifap = &inet6_addr_lst[hash]; (ifa=*ifap) != NULL; | 725 | hlist_del_init_rcu(&ifp->addr_lst); |
722 | ifap = &ifa->lst_next) { | 726 | __in6_ifa_put(ifp); |
723 | if (ifa == ifp) { | 727 | spin_unlock_bh(&addrconf_hash_lock); |
724 | *ifap = ifa->lst_next; | ||
725 | __in6_ifa_put(ifp); | ||
726 | ifa->lst_next = NULL; | ||
727 | break; | ||
728 | } | ||
729 | } | ||
730 | write_unlock_bh(&addrconf_hash_lock); | ||
731 | 728 | ||
732 | write_lock_bh(&idev->lock); | 729 | write_lock_bh(&idev->lock); |
733 | #ifdef CONFIG_IPV6_PRIVACY | 730 | #ifdef CONFIG_IPV6_PRIVACY |
734 | if (ifp->flags&IFA_F_TEMPORARY) { | 731 | if (ifp->flags&IFA_F_TEMPORARY) { |
735 | for (ifap = &idev->tempaddr_list; (ifa=*ifap) != NULL; | 732 | list_del(&ifp->tmp_list); |
736 | ifap = &ifa->tmp_next) { | 733 | if (ifp->ifpub) { |
737 | if (ifa == ifp) { | 734 | in6_ifa_put(ifp->ifpub); |
738 | *ifap = ifa->tmp_next; | 735 | ifp->ifpub = NULL; |
739 | if (ifp->ifpub) { | ||
740 | in6_ifa_put(ifp->ifpub); | ||
741 | ifp->ifpub = NULL; | ||
742 | } | ||
743 | __in6_ifa_put(ifp); | ||
744 | ifa->tmp_next = NULL; | ||
745 | break; | ||
746 | } | ||
747 | } | 736 | } |
737 | __in6_ifa_put(ifp); | ||
748 | } | 738 | } |
749 | #endif | 739 | #endif |
750 | 740 | ||
751 | for (ifap = &idev->addr_list; (ifa=*ifap) != NULL;) { | 741 | list_for_each_entry_safe(ifa, ifn, &idev->addr_list, if_list) { |
752 | if (ifa == ifp) { | 742 | if (ifa == ifp) { |
753 | *ifap = ifa->if_next; | 743 | list_del_init(&ifp->if_list); |
754 | __in6_ifa_put(ifp); | 744 | __in6_ifa_put(ifp); |
755 | ifa->if_next = NULL; | 745 | |
756 | if (!(ifp->flags & IFA_F_PERMANENT) || onlink > 0) | 746 | if (!(ifp->flags & IFA_F_PERMANENT) || onlink > 0) |
757 | break; | 747 | break; |
758 | deleted = 1; | 748 | deleted = 1; |
@@ -785,7 +775,6 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp) | |||
785 | } | 775 | } |
786 | } | 776 | } |
787 | } | 777 | } |
788 | ifap = &ifa->if_next; | ||
789 | } | 778 | } |
790 | write_unlock_bh(&idev->lock); | 779 | write_unlock_bh(&idev->lock); |
791 | 780 | ||
@@ -1164,7 +1153,7 @@ int ipv6_dev_get_saddr(struct net *net, struct net_device *dst_dev, | |||
1164 | continue; | 1153 | continue; |
1165 | 1154 | ||
1166 | read_lock_bh(&idev->lock); | 1155 | read_lock_bh(&idev->lock); |
1167 | for (score->ifa = idev->addr_list; score->ifa; score->ifa = score->ifa->if_next) { | 1156 | list_for_each_entry(score->ifa, &idev->addr_list, if_list) { |
1168 | int i; | 1157 | int i; |
1169 | 1158 | ||
1170 | /* | 1159 | /* |
@@ -1242,7 +1231,6 @@ try_nextdev: | |||
1242 | in6_ifa_put(hiscore->ifa); | 1231 | in6_ifa_put(hiscore->ifa); |
1243 | return 0; | 1232 | return 0; |
1244 | } | 1233 | } |
1245 | |||
1246 | EXPORT_SYMBOL(ipv6_dev_get_saddr); | 1234 | EXPORT_SYMBOL(ipv6_dev_get_saddr); |
1247 | 1235 | ||
1248 | int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr, | 1236 | int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr, |
@@ -1252,12 +1240,14 @@ int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr, | |||
1252 | int err = -EADDRNOTAVAIL; | 1240 | int err = -EADDRNOTAVAIL; |
1253 | 1241 | ||
1254 | rcu_read_lock(); | 1242 | rcu_read_lock(); |
1255 | if ((idev = __in6_dev_get(dev)) != NULL) { | 1243 | idev = __in6_dev_get(dev); |
1244 | if (idev) { | ||
1256 | struct inet6_ifaddr *ifp; | 1245 | struct inet6_ifaddr *ifp; |
1257 | 1246 | ||
1258 | read_lock_bh(&idev->lock); | 1247 | read_lock_bh(&idev->lock); |
1259 | for (ifp=idev->addr_list; ifp; ifp=ifp->if_next) { | 1248 | list_for_each_entry(ifp, &idev->addr_list, if_list) { |
1260 | if (ifp->scope == IFA_LINK && !(ifp->flags & banned_flags)) { | 1249 | if (ifp->scope == IFA_LINK && |
1250 | !(ifp->flags & banned_flags)) { | ||
1261 | ipv6_addr_copy(addr, &ifp->addr); | 1251 | ipv6_addr_copy(addr, &ifp->addr); |
1262 | err = 0; | 1252 | err = 0; |
1263 | break; | 1253 | break; |
@@ -1275,7 +1265,7 @@ static int ipv6_count_addresses(struct inet6_dev *idev) | |||
1275 | struct inet6_ifaddr *ifp; | 1265 | struct inet6_ifaddr *ifp; |
1276 | 1266 | ||
1277 | read_lock_bh(&idev->lock); | 1267 | read_lock_bh(&idev->lock); |
1278 | for (ifp=idev->addr_list; ifp; ifp=ifp->if_next) | 1268 | list_for_each_entry(ifp, &idev->addr_list, if_list) |
1279 | cnt++; | 1269 | cnt++; |
1280 | read_unlock_bh(&idev->lock); | 1270 | read_unlock_bh(&idev->lock); |
1281 | return cnt; | 1271 | return cnt; |
@@ -1284,11 +1274,12 @@ static int ipv6_count_addresses(struct inet6_dev *idev) | |||
1284 | int ipv6_chk_addr(struct net *net, struct in6_addr *addr, | 1274 | int ipv6_chk_addr(struct net *net, struct in6_addr *addr, |
1285 | struct net_device *dev, int strict) | 1275 | struct net_device *dev, int strict) |
1286 | { | 1276 | { |
1287 | struct inet6_ifaddr * ifp; | 1277 | struct inet6_ifaddr *ifp = NULL; |
1288 | u8 hash = ipv6_addr_hash(addr); | 1278 | struct hlist_node *node; |
1279 | unsigned int hash = ipv6_addr_hash(addr); | ||
1289 | 1280 | ||
1290 | read_lock_bh(&addrconf_hash_lock); | 1281 | rcu_read_lock_bh(); |
1291 | for(ifp = inet6_addr_lst[hash]; ifp; ifp=ifp->lst_next) { | 1282 | hlist_for_each_entry_rcu(ifp, node, &inet6_addr_lst[hash], addr_lst) { |
1292 | if (!net_eq(dev_net(ifp->idev->dev), net)) | 1283 | if (!net_eq(dev_net(ifp->idev->dev), net)) |
1293 | continue; | 1284 | continue; |
1294 | if (ipv6_addr_equal(&ifp->addr, addr) && | 1285 | if (ipv6_addr_equal(&ifp->addr, addr) && |
@@ -1298,27 +1289,28 @@ int ipv6_chk_addr(struct net *net, struct in6_addr *addr, | |||
1298 | break; | 1289 | break; |
1299 | } | 1290 | } |
1300 | } | 1291 | } |
1301 | read_unlock_bh(&addrconf_hash_lock); | 1292 | rcu_read_unlock_bh(); |
1293 | |||
1302 | return ifp != NULL; | 1294 | return ifp != NULL; |
1303 | } | 1295 | } |
1304 | EXPORT_SYMBOL(ipv6_chk_addr); | 1296 | EXPORT_SYMBOL(ipv6_chk_addr); |
1305 | 1297 | ||
1306 | static | 1298 | static bool ipv6_chk_same_addr(struct net *net, const struct in6_addr *addr, |
1307 | int ipv6_chk_same_addr(struct net *net, const struct in6_addr *addr, | 1299 | struct net_device *dev) |
1308 | struct net_device *dev) | ||
1309 | { | 1300 | { |
1310 | struct inet6_ifaddr * ifp; | 1301 | unsigned int hash = ipv6_addr_hash(addr); |
1311 | u8 hash = ipv6_addr_hash(addr); | 1302 | struct inet6_ifaddr *ifp; |
1303 | struct hlist_node *node; | ||
1312 | 1304 | ||
1313 | for(ifp = inet6_addr_lst[hash]; ifp; ifp=ifp->lst_next) { | 1305 | hlist_for_each_entry(ifp, node, &inet6_addr_lst[hash], addr_lst) { |
1314 | if (!net_eq(dev_net(ifp->idev->dev), net)) | 1306 | if (!net_eq(dev_net(ifp->idev->dev), net)) |
1315 | continue; | 1307 | continue; |
1316 | if (ipv6_addr_equal(&ifp->addr, addr)) { | 1308 | if (ipv6_addr_equal(&ifp->addr, addr)) { |
1317 | if (dev == NULL || ifp->idev->dev == dev) | 1309 | if (dev == NULL || ifp->idev->dev == dev) |
1318 | break; | 1310 | return true; |
1319 | } | 1311 | } |
1320 | } | 1312 | } |
1321 | return ifp != NULL; | 1313 | return false; |
1322 | } | 1314 | } |
1323 | 1315 | ||
1324 | int ipv6_chk_prefix(struct in6_addr *addr, struct net_device *dev) | 1316 | int ipv6_chk_prefix(struct in6_addr *addr, struct net_device *dev) |
@@ -1332,7 +1324,7 @@ int ipv6_chk_prefix(struct in6_addr *addr, struct net_device *dev) | |||
1332 | idev = __in6_dev_get(dev); | 1324 | idev = __in6_dev_get(dev); |
1333 | if (idev) { | 1325 | if (idev) { |
1334 | read_lock_bh(&idev->lock); | 1326 | read_lock_bh(&idev->lock); |
1335 | for (ifa = idev->addr_list; ifa; ifa = ifa->if_next) { | 1327 | list_for_each_entry(ifa, &idev->addr_list, if_list) { |
1336 | onlink = ipv6_prefix_equal(addr, &ifa->addr, | 1328 | onlink = ipv6_prefix_equal(addr, &ifa->addr, |
1337 | ifa->prefix_len); | 1329 | ifa->prefix_len); |
1338 | if (onlink) | 1330 | if (onlink) |
@@ -1349,24 +1341,26 @@ EXPORT_SYMBOL(ipv6_chk_prefix); | |||
1349 | struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net, const struct in6_addr *addr, | 1341 | struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net, const struct in6_addr *addr, |
1350 | struct net_device *dev, int strict) | 1342 | struct net_device *dev, int strict) |
1351 | { | 1343 | { |
1352 | struct inet6_ifaddr * ifp; | 1344 | struct inet6_ifaddr *ifp, *result = NULL; |
1353 | u8 hash = ipv6_addr_hash(addr); | 1345 | unsigned int hash = ipv6_addr_hash(addr); |
1346 | struct hlist_node *node; | ||
1354 | 1347 | ||
1355 | read_lock_bh(&addrconf_hash_lock); | 1348 | rcu_read_lock_bh(); |
1356 | for(ifp = inet6_addr_lst[hash]; ifp; ifp=ifp->lst_next) { | 1349 | hlist_for_each_entry_rcu(ifp, node, &inet6_addr_lst[hash], addr_lst) { |
1357 | if (!net_eq(dev_net(ifp->idev->dev), net)) | 1350 | if (!net_eq(dev_net(ifp->idev->dev), net)) |
1358 | continue; | 1351 | continue; |
1359 | if (ipv6_addr_equal(&ifp->addr, addr)) { | 1352 | if (ipv6_addr_equal(&ifp->addr, addr)) { |
1360 | if (dev == NULL || ifp->idev->dev == dev || | 1353 | if (dev == NULL || ifp->idev->dev == dev || |
1361 | !(ifp->scope&(IFA_LINK|IFA_HOST) || strict)) { | 1354 | !(ifp->scope&(IFA_LINK|IFA_HOST) || strict)) { |
1355 | result = ifp; | ||
1362 | in6_ifa_hold(ifp); | 1356 | in6_ifa_hold(ifp); |
1363 | break; | 1357 | break; |
1364 | } | 1358 | } |
1365 | } | 1359 | } |
1366 | } | 1360 | } |
1367 | read_unlock_bh(&addrconf_hash_lock); | 1361 | rcu_read_unlock_bh(); |
1368 | 1362 | ||
1369 | return ifp; | 1363 | return result; |
1370 | } | 1364 | } |
1371 | 1365 | ||
1372 | /* Gets referenced address, destroys ifaddr */ | 1366 | /* Gets referenced address, destroys ifaddr */ |
@@ -1380,6 +1374,8 @@ static void addrconf_dad_stop(struct inet6_ifaddr *ifp, int dad_failed) | |||
1380 | if (dad_failed) | 1374 | if (dad_failed) |
1381 | ifp->flags |= IFA_F_DADFAILED; | 1375 | ifp->flags |= IFA_F_DADFAILED; |
1382 | spin_unlock_bh(&ifp->lock); | 1376 | spin_unlock_bh(&ifp->lock); |
1377 | if (dad_failed) | ||
1378 | ipv6_ifa_notify(0, ifp); | ||
1383 | in6_ifa_put(ifp); | 1379 | in6_ifa_put(ifp); |
1384 | #ifdef CONFIG_IPV6_PRIVACY | 1380 | #ifdef CONFIG_IPV6_PRIVACY |
1385 | } else if (ifp->flags&IFA_F_TEMPORARY) { | 1381 | } else if (ifp->flags&IFA_F_TEMPORARY) { |
@@ -1567,7 +1563,7 @@ static int ipv6_inherit_eui64(u8 *eui, struct inet6_dev *idev) | |||
1567 | struct inet6_ifaddr *ifp; | 1563 | struct inet6_ifaddr *ifp; |
1568 | 1564 | ||
1569 | read_lock_bh(&idev->lock); | 1565 | read_lock_bh(&idev->lock); |
1570 | for (ifp=idev->addr_list; ifp; ifp=ifp->if_next) { | 1566 | list_for_each_entry(ifp, &idev->addr_list, if_list) { |
1571 | if (ifp->scope == IFA_LINK && !(ifp->flags&IFA_F_TENTATIVE)) { | 1567 | if (ifp->scope == IFA_LINK && !(ifp->flags&IFA_F_TENTATIVE)) { |
1572 | memcpy(eui, ifp->addr.s6_addr+8, 8); | 1568 | memcpy(eui, ifp->addr.s6_addr+8, 8); |
1573 | err = 0; | 1569 | err = 0; |
@@ -1735,7 +1731,8 @@ static struct inet6_dev *addrconf_add_dev(struct net_device *dev) | |||
1735 | 1731 | ||
1736 | ASSERT_RTNL(); | 1732 | ASSERT_RTNL(); |
1737 | 1733 | ||
1738 | if ((idev = ipv6_find_idev(dev)) == NULL) | 1734 | idev = ipv6_find_idev(dev); |
1735 | if (!idev) | ||
1739 | return NULL; | 1736 | return NULL; |
1740 | 1737 | ||
1741 | /* Add default multicast route */ | 1738 | /* Add default multicast route */ |
@@ -1968,7 +1965,7 @@ ok: | |||
1968 | #ifdef CONFIG_IPV6_PRIVACY | 1965 | #ifdef CONFIG_IPV6_PRIVACY |
1969 | read_lock_bh(&in6_dev->lock); | 1966 | read_lock_bh(&in6_dev->lock); |
1970 | /* update all temporary addresses in the list */ | 1967 | /* update all temporary addresses in the list */ |
1971 | for (ift=in6_dev->tempaddr_list; ift; ift=ift->tmp_next) { | 1968 | list_for_each_entry(ift, &in6_dev->tempaddr_list, tmp_list) { |
1972 | /* | 1969 | /* |
1973 | * When adjusting the lifetimes of an existing | 1970 | * When adjusting the lifetimes of an existing |
1974 | * temporary address, only lower the lifetimes. | 1971 | * temporary address, only lower the lifetimes. |
@@ -2171,7 +2168,7 @@ static int inet6_addr_del(struct net *net, int ifindex, struct in6_addr *pfx, | |||
2171 | return -ENXIO; | 2168 | return -ENXIO; |
2172 | 2169 | ||
2173 | read_lock_bh(&idev->lock); | 2170 | read_lock_bh(&idev->lock); |
2174 | for (ifp = idev->addr_list; ifp; ifp=ifp->if_next) { | 2171 | list_for_each_entry(ifp, &idev->addr_list, if_list) { |
2175 | if (ifp->prefix_len == plen && | 2172 | if (ifp->prefix_len == plen && |
2176 | ipv6_addr_equal(pfx, &ifp->addr)) { | 2173 | ipv6_addr_equal(pfx, &ifp->addr)) { |
2177 | in6_ifa_hold(ifp); | 2174 | in6_ifa_hold(ifp); |
@@ -2182,7 +2179,7 @@ static int inet6_addr_del(struct net *net, int ifindex, struct in6_addr *pfx, | |||
2182 | /* If the last address is deleted administratively, | 2179 | /* If the last address is deleted administratively, |
2183 | disable IPv6 on this interface. | 2180 | disable IPv6 on this interface. |
2184 | */ | 2181 | */ |
2185 | if (idev->addr_list == NULL) | 2182 | if (list_empty(&idev->addr_list)) |
2186 | addrconf_ifdown(idev->dev, 1); | 2183 | addrconf_ifdown(idev->dev, 1); |
2187 | return 0; | 2184 | return 0; |
2188 | } | 2185 | } |
@@ -2443,7 +2440,8 @@ static void addrconf_ip6_tnl_config(struct net_device *dev) | |||
2443 | 2440 | ||
2444 | ASSERT_RTNL(); | 2441 | ASSERT_RTNL(); |
2445 | 2442 | ||
2446 | if ((idev = addrconf_add_dev(dev)) == NULL) { | 2443 | idev = addrconf_add_dev(dev); |
2444 | if (!idev) { | ||
2447 | printk(KERN_DEBUG "init ip6-ip6: add_dev failed\n"); | 2445 | printk(KERN_DEBUG "init ip6-ip6: add_dev failed\n"); |
2448 | return; | 2446 | return; |
2449 | } | 2447 | } |
@@ -2458,7 +2456,7 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, | |||
2458 | int run_pending = 0; | 2456 | int run_pending = 0; |
2459 | int err; | 2457 | int err; |
2460 | 2458 | ||
2461 | switch(event) { | 2459 | switch (event) { |
2462 | case NETDEV_REGISTER: | 2460 | case NETDEV_REGISTER: |
2463 | if (!idev && dev->mtu >= IPV6_MIN_MTU) { | 2461 | if (!idev && dev->mtu >= IPV6_MIN_MTU) { |
2464 | idev = ipv6_add_dev(dev); | 2462 | idev = ipv6_add_dev(dev); |
@@ -2466,6 +2464,7 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, | |||
2466 | return notifier_from_errno(-ENOMEM); | 2464 | return notifier_from_errno(-ENOMEM); |
2467 | } | 2465 | } |
2468 | break; | 2466 | break; |
2467 | |||
2469 | case NETDEV_UP: | 2468 | case NETDEV_UP: |
2470 | case NETDEV_CHANGE: | 2469 | case NETDEV_CHANGE: |
2471 | if (dev->flags & IFF_SLAVE) | 2470 | if (dev->flags & IFF_SLAVE) |
@@ -2495,10 +2494,9 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, | |||
2495 | } | 2494 | } |
2496 | 2495 | ||
2497 | if (idev) { | 2496 | if (idev) { |
2498 | if (idev->if_flags & IF_READY) { | 2497 | if (idev->if_flags & IF_READY) |
2499 | /* device is already configured. */ | 2498 | /* device is already configured. */ |
2500 | break; | 2499 | break; |
2501 | } | ||
2502 | idev->if_flags |= IF_READY; | 2500 | idev->if_flags |= IF_READY; |
2503 | } | 2501 | } |
2504 | 2502 | ||
@@ -2510,7 +2508,7 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, | |||
2510 | run_pending = 1; | 2508 | run_pending = 1; |
2511 | } | 2509 | } |
2512 | 2510 | ||
2513 | switch(dev->type) { | 2511 | switch (dev->type) { |
2514 | #if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE) | 2512 | #if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE) |
2515 | case ARPHRD_SIT: | 2513 | case ARPHRD_SIT: |
2516 | addrconf_sit_config(dev); | 2514 | addrconf_sit_config(dev); |
@@ -2527,25 +2525,30 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, | |||
2527 | addrconf_dev_config(dev); | 2525 | addrconf_dev_config(dev); |
2528 | break; | 2526 | break; |
2529 | } | 2527 | } |
2528 | |||
2530 | if (idev) { | 2529 | if (idev) { |
2531 | if (run_pending) | 2530 | if (run_pending) |
2532 | addrconf_dad_run(idev); | 2531 | addrconf_dad_run(idev); |
2533 | 2532 | ||
2534 | /* If the MTU changed during the interface down, when the | 2533 | /* |
2535 | interface up, the changed MTU must be reflected in the | 2534 | * If the MTU changed during the interface down, |
2536 | idev as well as routers. | 2535 | * when the interface up, the changed MTU must be |
2536 | * reflected in the idev as well as routers. | ||
2537 | */ | 2537 | */ |
2538 | if (idev->cnf.mtu6 != dev->mtu && dev->mtu >= IPV6_MIN_MTU) { | 2538 | if (idev->cnf.mtu6 != dev->mtu && |
2539 | dev->mtu >= IPV6_MIN_MTU) { | ||
2539 | rt6_mtu_change(dev, dev->mtu); | 2540 | rt6_mtu_change(dev, dev->mtu); |
2540 | idev->cnf.mtu6 = dev->mtu; | 2541 | idev->cnf.mtu6 = dev->mtu; |
2541 | } | 2542 | } |
2542 | idev->tstamp = jiffies; | 2543 | idev->tstamp = jiffies; |
2543 | inet6_ifinfo_notify(RTM_NEWLINK, idev); | 2544 | inet6_ifinfo_notify(RTM_NEWLINK, idev); |
2544 | /* If the changed mtu during down is lower than IPV6_MIN_MTU | 2545 | |
2545 | stop IPv6 on this interface. | 2546 | /* |
2547 | * If the changed mtu during down is lower than | ||
2548 | * IPV6_MIN_MTU stop IPv6 on this interface. | ||
2546 | */ | 2549 | */ |
2547 | if (dev->mtu < IPV6_MIN_MTU) | 2550 | if (dev->mtu < IPV6_MIN_MTU) |
2548 | addrconf_ifdown(dev, event != NETDEV_DOWN); | 2551 | addrconf_ifdown(dev, 1); |
2549 | } | 2552 | } |
2550 | break; | 2553 | break; |
2551 | 2554 | ||
@@ -2562,7 +2565,10 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, | |||
2562 | break; | 2565 | break; |
2563 | } | 2566 | } |
2564 | 2567 | ||
2565 | /* MTU falled under IPV6_MIN_MTU. Stop IPv6 on this interface. */ | 2568 | /* |
2569 | * MTU falled under IPV6_MIN_MTU. | ||
2570 | * Stop IPv6 on this interface. | ||
2571 | */ | ||
2566 | 2572 | ||
2567 | case NETDEV_DOWN: | 2573 | case NETDEV_DOWN: |
2568 | case NETDEV_UNREGISTER: | 2574 | case NETDEV_UNREGISTER: |
@@ -2582,9 +2588,10 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, | |||
2582 | return notifier_from_errno(err); | 2588 | return notifier_from_errno(err); |
2583 | } | 2589 | } |
2584 | break; | 2590 | break; |
2585 | case NETDEV_BONDING_OLDTYPE: | 2591 | |
2586 | case NETDEV_BONDING_NEWTYPE: | 2592 | case NETDEV_PRE_TYPE_CHANGE: |
2587 | addrconf_bonding_change(dev, event); | 2593 | case NETDEV_POST_TYPE_CHANGE: |
2594 | addrconf_type_change(dev, event); | ||
2588 | break; | 2595 | break; |
2589 | } | 2596 | } |
2590 | 2597 | ||
@@ -2596,28 +2603,27 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, | |||
2596 | */ | 2603 | */ |
2597 | static struct notifier_block ipv6_dev_notf = { | 2604 | static struct notifier_block ipv6_dev_notf = { |
2598 | .notifier_call = addrconf_notify, | 2605 | .notifier_call = addrconf_notify, |
2599 | .priority = 0 | ||
2600 | }; | 2606 | }; |
2601 | 2607 | ||
2602 | static void addrconf_bonding_change(struct net_device *dev, unsigned long event) | 2608 | static void addrconf_type_change(struct net_device *dev, unsigned long event) |
2603 | { | 2609 | { |
2604 | struct inet6_dev *idev; | 2610 | struct inet6_dev *idev; |
2605 | ASSERT_RTNL(); | 2611 | ASSERT_RTNL(); |
2606 | 2612 | ||
2607 | idev = __in6_dev_get(dev); | 2613 | idev = __in6_dev_get(dev); |
2608 | 2614 | ||
2609 | if (event == NETDEV_BONDING_NEWTYPE) | 2615 | if (event == NETDEV_POST_TYPE_CHANGE) |
2610 | ipv6_mc_remap(idev); | 2616 | ipv6_mc_remap(idev); |
2611 | else if (event == NETDEV_BONDING_OLDTYPE) | 2617 | else if (event == NETDEV_PRE_TYPE_CHANGE) |
2612 | ipv6_mc_unmap(idev); | 2618 | ipv6_mc_unmap(idev); |
2613 | } | 2619 | } |
2614 | 2620 | ||
2615 | static int addrconf_ifdown(struct net_device *dev, int how) | 2621 | static int addrconf_ifdown(struct net_device *dev, int how) |
2616 | { | 2622 | { |
2617 | struct inet6_dev *idev; | ||
2618 | struct inet6_ifaddr *ifa, **bifa; | ||
2619 | struct net *net = dev_net(dev); | 2623 | struct net *net = dev_net(dev); |
2620 | int i; | 2624 | struct inet6_dev *idev; |
2625 | struct inet6_ifaddr *ifa; | ||
2626 | LIST_HEAD(keep_list); | ||
2621 | 2627 | ||
2622 | ASSERT_RTNL(); | 2628 | ASSERT_RTNL(); |
2623 | 2629 | ||
@@ -2628,8 +2634,9 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
2628 | if (idev == NULL) | 2634 | if (idev == NULL) |
2629 | return -ENODEV; | 2635 | return -ENODEV; |
2630 | 2636 | ||
2631 | /* Step 1: remove reference to ipv6 device from parent device. | 2637 | /* |
2632 | Do not dev_put! | 2638 | * Step 1: remove reference to ipv6 device from parent device. |
2639 | * Do not dev_put! | ||
2633 | */ | 2640 | */ |
2634 | if (how) { | 2641 | if (how) { |
2635 | idev->dead = 1; | 2642 | idev->dead = 1; |
@@ -2642,40 +2649,21 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
2642 | 2649 | ||
2643 | } | 2650 | } |
2644 | 2651 | ||
2645 | /* Step 2: clear hash table */ | ||
2646 | for (i=0; i<IN6_ADDR_HSIZE; i++) { | ||
2647 | bifa = &inet6_addr_lst[i]; | ||
2648 | |||
2649 | write_lock_bh(&addrconf_hash_lock); | ||
2650 | while ((ifa = *bifa) != NULL) { | ||
2651 | if (ifa->idev == idev && | ||
2652 | (how || !(ifa->flags&IFA_F_PERMANENT))) { | ||
2653 | *bifa = ifa->lst_next; | ||
2654 | ifa->lst_next = NULL; | ||
2655 | addrconf_del_timer(ifa); | ||
2656 | in6_ifa_put(ifa); | ||
2657 | continue; | ||
2658 | } | ||
2659 | bifa = &ifa->lst_next; | ||
2660 | } | ||
2661 | write_unlock_bh(&addrconf_hash_lock); | ||
2662 | } | ||
2663 | |||
2664 | write_lock_bh(&idev->lock); | 2652 | write_lock_bh(&idev->lock); |
2665 | 2653 | ||
2666 | /* Step 3: clear flags for stateless addrconf */ | 2654 | /* Step 2: clear flags for stateless addrconf */ |
2667 | if (!how) | 2655 | if (!how) |
2668 | idev->if_flags &= ~(IF_RS_SENT|IF_RA_RCVD|IF_READY); | 2656 | idev->if_flags &= ~(IF_RS_SENT|IF_RA_RCVD|IF_READY); |
2669 | 2657 | ||
2670 | /* Step 4: clear address list */ | ||
2671 | #ifdef CONFIG_IPV6_PRIVACY | 2658 | #ifdef CONFIG_IPV6_PRIVACY |
2672 | if (how && del_timer(&idev->regen_timer)) | 2659 | if (how && del_timer(&idev->regen_timer)) |
2673 | in6_dev_put(idev); | 2660 | in6_dev_put(idev); |
2674 | 2661 | ||
2675 | /* clear tempaddr list */ | 2662 | /* Step 3: clear tempaddr list */ |
2676 | while ((ifa = idev->tempaddr_list) != NULL) { | 2663 | while (!list_empty(&idev->tempaddr_list)) { |
2677 | idev->tempaddr_list = ifa->tmp_next; | 2664 | ifa = list_first_entry(&idev->tempaddr_list, |
2678 | ifa->tmp_next = NULL; | 2665 | struct inet6_ifaddr, tmp_list); |
2666 | list_del(&ifa->tmp_list); | ||
2679 | ifa->dead = 1; | 2667 | ifa->dead = 1; |
2680 | write_unlock_bh(&idev->lock); | 2668 | write_unlock_bh(&idev->lock); |
2681 | spin_lock_bh(&ifa->lock); | 2669 | spin_lock_bh(&ifa->lock); |
@@ -2689,35 +2677,56 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
2689 | write_lock_bh(&idev->lock); | 2677 | write_lock_bh(&idev->lock); |
2690 | } | 2678 | } |
2691 | #endif | 2679 | #endif |
2692 | bifa = &idev->addr_list; | ||
2693 | while ((ifa = *bifa) != NULL) { | ||
2694 | if (how == 0 && (ifa->flags&IFA_F_PERMANENT)) { | ||
2695 | /* Retain permanent address on admin down */ | ||
2696 | bifa = &ifa->if_next; | ||
2697 | |||
2698 | /* Restart DAD if needed when link comes back up */ | ||
2699 | if ( !((dev->flags&(IFF_NOARP|IFF_LOOPBACK)) || | ||
2700 | idev->cnf.accept_dad <= 0 || | ||
2701 | (ifa->flags & IFA_F_NODAD))) | ||
2702 | ifa->flags |= IFA_F_TENTATIVE; | ||
2703 | } else { | ||
2704 | *bifa = ifa->if_next; | ||
2705 | ifa->if_next = NULL; | ||
2706 | 2680 | ||
2707 | ifa->dead = 1; | 2681 | while (!list_empty(&idev->addr_list)) { |
2708 | write_unlock_bh(&idev->lock); | 2682 | ifa = list_first_entry(&idev->addr_list, |
2683 | struct inet6_ifaddr, if_list); | ||
2684 | addrconf_del_timer(ifa); | ||
2685 | |||
2686 | /* If just doing link down, and address is permanent | ||
2687 | and not link-local, then retain it. */ | ||
2688 | if (!how && | ||
2689 | (ifa->flags&IFA_F_PERMANENT) && | ||
2690 | !(ipv6_addr_type(&ifa->addr) & IPV6_ADDR_LINKLOCAL)) { | ||
2691 | list_move_tail(&ifa->if_list, &keep_list); | ||
2692 | |||
2693 | /* If not doing DAD on this address, just keep it. */ | ||
2694 | if ((dev->flags&(IFF_NOARP|IFF_LOOPBACK)) || | ||
2695 | idev->cnf.accept_dad <= 0 || | ||
2696 | (ifa->flags & IFA_F_NODAD)) | ||
2697 | continue; | ||
2709 | 2698 | ||
2710 | __ipv6_ifa_notify(RTM_DELADDR, ifa); | 2699 | /* If it was tentative already, no need to notify */ |
2711 | atomic_notifier_call_chain(&inet6addr_chain, NETDEV_DOWN, ifa); | 2700 | if (ifa->flags & IFA_F_TENTATIVE) |
2712 | in6_ifa_put(ifa); | 2701 | continue; |
2713 | 2702 | ||
2714 | write_lock_bh(&idev->lock); | 2703 | /* Flag it for later restoration when link comes up */ |
2704 | ifa->flags |= IFA_F_TENTATIVE; | ||
2705 | in6_ifa_hold(ifa); | ||
2706 | } else { | ||
2707 | list_del(&ifa->if_list); | ||
2708 | ifa->dead = 1; | ||
2715 | } | 2709 | } |
2710 | write_unlock_bh(&idev->lock); | ||
2711 | |||
2712 | /* clear hash table */ | ||
2713 | spin_lock_bh(&addrconf_hash_lock); | ||
2714 | hlist_del_init_rcu(&ifa->addr_lst); | ||
2715 | __in6_ifa_put(ifa); | ||
2716 | spin_unlock_bh(&addrconf_hash_lock); | ||
2717 | |||
2718 | __ipv6_ifa_notify(RTM_DELADDR, ifa); | ||
2719 | atomic_notifier_call_chain(&inet6addr_chain, NETDEV_DOWN, ifa); | ||
2720 | in6_ifa_put(ifa); | ||
2721 | |||
2722 | write_lock_bh(&idev->lock); | ||
2716 | } | 2723 | } |
2724 | |||
2725 | list_splice(&keep_list, &idev->addr_list); | ||
2726 | |||
2717 | write_unlock_bh(&idev->lock); | 2727 | write_unlock_bh(&idev->lock); |
2718 | 2728 | ||
2719 | /* Step 5: Discard multicast list */ | 2729 | /* Step 5: Discard multicast list */ |
2720 | |||
2721 | if (how) | 2730 | if (how) |
2722 | ipv6_mc_destroy_dev(idev); | 2731 | ipv6_mc_destroy_dev(idev); |
2723 | else | 2732 | else |
@@ -2725,8 +2734,7 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
2725 | 2734 | ||
2726 | idev->tstamp = jiffies; | 2735 | idev->tstamp = jiffies; |
2727 | 2736 | ||
2728 | /* Shot the device (if unregistered) */ | 2737 | /* Last: Shot the device (if unregistered) */ |
2729 | |||
2730 | if (how) { | 2738 | if (how) { |
2731 | addrconf_sysctl_unregister(idev); | 2739 | addrconf_sysctl_unregister(idev); |
2732 | neigh_parms_release(&nd_tbl, idev->nd_parms); | 2740 | neigh_parms_release(&nd_tbl, idev->nd_parms); |
@@ -2739,28 +2747,29 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
2739 | static void addrconf_rs_timer(unsigned long data) | 2747 | static void addrconf_rs_timer(unsigned long data) |
2740 | { | 2748 | { |
2741 | struct inet6_ifaddr *ifp = (struct inet6_ifaddr *) data; | 2749 | struct inet6_ifaddr *ifp = (struct inet6_ifaddr *) data; |
2750 | struct inet6_dev *idev = ifp->idev; | ||
2742 | 2751 | ||
2743 | if (ifp->idev->cnf.forwarding) | 2752 | read_lock(&idev->lock); |
2753 | if (idev->dead || !(idev->if_flags & IF_READY)) | ||
2744 | goto out; | 2754 | goto out; |
2745 | 2755 | ||
2746 | if (ifp->idev->if_flags & IF_RA_RCVD) { | 2756 | if (idev->cnf.forwarding) |
2747 | /* | 2757 | goto out; |
2748 | * Announcement received after solicitation | 2758 | |
2749 | * was sent | 2759 | /* Announcement received after solicitation was sent */ |
2750 | */ | 2760 | if (idev->if_flags & IF_RA_RCVD) |
2751 | goto out; | 2761 | goto out; |
2752 | } | ||
2753 | 2762 | ||
2754 | spin_lock(&ifp->lock); | 2763 | spin_lock(&ifp->lock); |
2755 | if (ifp->probes++ < ifp->idev->cnf.rtr_solicits) { | 2764 | if (ifp->probes++ < idev->cnf.rtr_solicits) { |
2756 | /* The wait after the last probe can be shorter */ | 2765 | /* The wait after the last probe can be shorter */ |
2757 | addrconf_mod_timer(ifp, AC_RS, | 2766 | addrconf_mod_timer(ifp, AC_RS, |
2758 | (ifp->probes == ifp->idev->cnf.rtr_solicits) ? | 2767 | (ifp->probes == idev->cnf.rtr_solicits) ? |
2759 | ifp->idev->cnf.rtr_solicit_delay : | 2768 | idev->cnf.rtr_solicit_delay : |
2760 | ifp->idev->cnf.rtr_solicit_interval); | 2769 | idev->cnf.rtr_solicit_interval); |
2761 | spin_unlock(&ifp->lock); | 2770 | spin_unlock(&ifp->lock); |
2762 | 2771 | ||
2763 | ndisc_send_rs(ifp->idev->dev, &ifp->addr, &in6addr_linklocal_allrouters); | 2772 | ndisc_send_rs(idev->dev, &ifp->addr, &in6addr_linklocal_allrouters); |
2764 | } else { | 2773 | } else { |
2765 | spin_unlock(&ifp->lock); | 2774 | spin_unlock(&ifp->lock); |
2766 | /* | 2775 | /* |
@@ -2768,10 +2777,11 @@ static void addrconf_rs_timer(unsigned long data) | |||
2768 | * assumption any longer. | 2777 | * assumption any longer. |
2769 | */ | 2778 | */ |
2770 | printk(KERN_DEBUG "%s: no IPv6 routers present\n", | 2779 | printk(KERN_DEBUG "%s: no IPv6 routers present\n", |
2771 | ifp->idev->dev->name); | 2780 | idev->dev->name); |
2772 | } | 2781 | } |
2773 | 2782 | ||
2774 | out: | 2783 | out: |
2784 | read_unlock(&idev->lock); | ||
2775 | in6_ifa_put(ifp); | 2785 | in6_ifa_put(ifp); |
2776 | } | 2786 | } |
2777 | 2787 | ||
@@ -2835,7 +2845,7 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags) | |||
2835 | * Optimistic nodes can start receiving | 2845 | * Optimistic nodes can start receiving |
2836 | * Frames right away | 2846 | * Frames right away |
2837 | */ | 2847 | */ |
2838 | if(ifp->flags & IFA_F_OPTIMISTIC) | 2848 | if (ifp->flags & IFA_F_OPTIMISTIC) |
2839 | ip6_ins_rt(ifp->rt); | 2849 | ip6_ins_rt(ifp->rt); |
2840 | 2850 | ||
2841 | addrconf_dad_kick(ifp); | 2851 | addrconf_dad_kick(ifp); |
@@ -2850,9 +2860,9 @@ static void addrconf_dad_timer(unsigned long data) | |||
2850 | struct inet6_dev *idev = ifp->idev; | 2860 | struct inet6_dev *idev = ifp->idev; |
2851 | struct in6_addr mcaddr; | 2861 | struct in6_addr mcaddr; |
2852 | 2862 | ||
2853 | read_lock_bh(&idev->lock); | 2863 | read_lock(&idev->lock); |
2854 | if (idev->dead) { | 2864 | if (idev->dead || !(idev->if_flags & IF_READY)) { |
2855 | read_unlock_bh(&idev->lock); | 2865 | read_unlock(&idev->lock); |
2856 | goto out; | 2866 | goto out; |
2857 | } | 2867 | } |
2858 | 2868 | ||
@@ -2864,7 +2874,7 @@ static void addrconf_dad_timer(unsigned long data) | |||
2864 | 2874 | ||
2865 | ifp->flags &= ~(IFA_F_TENTATIVE|IFA_F_OPTIMISTIC|IFA_F_DADFAILED); | 2875 | ifp->flags &= ~(IFA_F_TENTATIVE|IFA_F_OPTIMISTIC|IFA_F_DADFAILED); |
2866 | spin_unlock(&ifp->lock); | 2876 | spin_unlock(&ifp->lock); |
2867 | read_unlock_bh(&idev->lock); | 2877 | read_unlock(&idev->lock); |
2868 | 2878 | ||
2869 | addrconf_dad_completed(ifp); | 2879 | addrconf_dad_completed(ifp); |
2870 | 2880 | ||
@@ -2874,7 +2884,7 @@ static void addrconf_dad_timer(unsigned long data) | |||
2874 | ifp->probes--; | 2884 | ifp->probes--; |
2875 | addrconf_mod_timer(ifp, AC_DAD, ifp->idev->nd_parms->retrans_time); | 2885 | addrconf_mod_timer(ifp, AC_DAD, ifp->idev->nd_parms->retrans_time); |
2876 | spin_unlock(&ifp->lock); | 2886 | spin_unlock(&ifp->lock); |
2877 | read_unlock_bh(&idev->lock); | 2887 | read_unlock(&idev->lock); |
2878 | 2888 | ||
2879 | /* send a neighbour solicitation for our addr */ | 2889 | /* send a neighbour solicitation for our addr */ |
2880 | addrconf_addr_solict_mult(&ifp->addr, &mcaddr); | 2890 | addrconf_addr_solict_mult(&ifp->addr, &mcaddr); |
@@ -2885,7 +2895,7 @@ out: | |||
2885 | 2895 | ||
2886 | static void addrconf_dad_completed(struct inet6_ifaddr *ifp) | 2896 | static void addrconf_dad_completed(struct inet6_ifaddr *ifp) |
2887 | { | 2897 | { |
2888 | struct net_device * dev = ifp->idev->dev; | 2898 | struct net_device *dev = ifp->idev->dev; |
2889 | 2899 | ||
2890 | /* | 2900 | /* |
2891 | * Configure the address for reception. Now it is valid. | 2901 | * Configure the address for reception. Now it is valid. |
@@ -2916,11 +2926,12 @@ static void addrconf_dad_completed(struct inet6_ifaddr *ifp) | |||
2916 | } | 2926 | } |
2917 | } | 2927 | } |
2918 | 2928 | ||
2919 | static void addrconf_dad_run(struct inet6_dev *idev) { | 2929 | static void addrconf_dad_run(struct inet6_dev *idev) |
2930 | { | ||
2920 | struct inet6_ifaddr *ifp; | 2931 | struct inet6_ifaddr *ifp; |
2921 | 2932 | ||
2922 | read_lock_bh(&idev->lock); | 2933 | read_lock_bh(&idev->lock); |
2923 | for (ifp = idev->addr_list; ifp; ifp = ifp->if_next) { | 2934 | list_for_each_entry(ifp, &idev->addr_list, if_list) { |
2924 | spin_lock(&ifp->lock); | 2935 | spin_lock(&ifp->lock); |
2925 | if (!(ifp->flags & IFA_F_TENTATIVE)) { | 2936 | if (!(ifp->flags & IFA_F_TENTATIVE)) { |
2926 | spin_unlock(&ifp->lock); | 2937 | spin_unlock(&ifp->lock); |
@@ -2945,36 +2956,35 @@ static struct inet6_ifaddr *if6_get_first(struct seq_file *seq) | |||
2945 | struct net *net = seq_file_net(seq); | 2956 | struct net *net = seq_file_net(seq); |
2946 | 2957 | ||
2947 | for (state->bucket = 0; state->bucket < IN6_ADDR_HSIZE; ++state->bucket) { | 2958 | for (state->bucket = 0; state->bucket < IN6_ADDR_HSIZE; ++state->bucket) { |
2948 | ifa = inet6_addr_lst[state->bucket]; | 2959 | struct hlist_node *n; |
2949 | 2960 | hlist_for_each_entry_rcu(ifa, n, &inet6_addr_lst[state->bucket], | |
2950 | while (ifa && !net_eq(dev_net(ifa->idev->dev), net)) | 2961 | addr_lst) |
2951 | ifa = ifa->lst_next; | 2962 | if (net_eq(dev_net(ifa->idev->dev), net)) |
2952 | if (ifa) | 2963 | return ifa; |
2953 | break; | ||
2954 | } | 2964 | } |
2955 | return ifa; | 2965 | return NULL; |
2956 | } | 2966 | } |
2957 | 2967 | ||
2958 | static struct inet6_ifaddr *if6_get_next(struct seq_file *seq, struct inet6_ifaddr *ifa) | 2968 | static struct inet6_ifaddr *if6_get_next(struct seq_file *seq, |
2969 | struct inet6_ifaddr *ifa) | ||
2959 | { | 2970 | { |
2960 | struct if6_iter_state *state = seq->private; | 2971 | struct if6_iter_state *state = seq->private; |
2961 | struct net *net = seq_file_net(seq); | 2972 | struct net *net = seq_file_net(seq); |
2973 | struct hlist_node *n = &ifa->addr_lst; | ||
2962 | 2974 | ||
2963 | ifa = ifa->lst_next; | 2975 | hlist_for_each_entry_continue_rcu(ifa, n, addr_lst) |
2964 | try_again: | 2976 | if (net_eq(dev_net(ifa->idev->dev), net)) |
2965 | if (ifa) { | 2977 | return ifa; |
2966 | if (!net_eq(dev_net(ifa->idev->dev), net)) { | ||
2967 | ifa = ifa->lst_next; | ||
2968 | goto try_again; | ||
2969 | } | ||
2970 | } | ||
2971 | 2978 | ||
2972 | if (!ifa && ++state->bucket < IN6_ADDR_HSIZE) { | 2979 | while (++state->bucket < IN6_ADDR_HSIZE) { |
2973 | ifa = inet6_addr_lst[state->bucket]; | 2980 | hlist_for_each_entry(ifa, n, |
2974 | goto try_again; | 2981 | &inet6_addr_lst[state->bucket], addr_lst) { |
2982 | if (net_eq(dev_net(ifa->idev->dev), net)) | ||
2983 | return ifa; | ||
2984 | } | ||
2975 | } | 2985 | } |
2976 | 2986 | ||
2977 | return ifa; | 2987 | return NULL; |
2978 | } | 2988 | } |
2979 | 2989 | ||
2980 | static struct inet6_ifaddr *if6_get_idx(struct seq_file *seq, loff_t pos) | 2990 | static struct inet6_ifaddr *if6_get_idx(struct seq_file *seq, loff_t pos) |
@@ -2982,15 +2992,15 @@ static struct inet6_ifaddr *if6_get_idx(struct seq_file *seq, loff_t pos) | |||
2982 | struct inet6_ifaddr *ifa = if6_get_first(seq); | 2992 | struct inet6_ifaddr *ifa = if6_get_first(seq); |
2983 | 2993 | ||
2984 | if (ifa) | 2994 | if (ifa) |
2985 | while(pos && (ifa = if6_get_next(seq, ifa)) != NULL) | 2995 | while (pos && (ifa = if6_get_next(seq, ifa)) != NULL) |
2986 | --pos; | 2996 | --pos; |
2987 | return pos ? NULL : ifa; | 2997 | return pos ? NULL : ifa; |
2988 | } | 2998 | } |
2989 | 2999 | ||
2990 | static void *if6_seq_start(struct seq_file *seq, loff_t *pos) | 3000 | static void *if6_seq_start(struct seq_file *seq, loff_t *pos) |
2991 | __acquires(addrconf_hash_lock) | 3001 | __acquires(rcu) |
2992 | { | 3002 | { |
2993 | read_lock_bh(&addrconf_hash_lock); | 3003 | rcu_read_lock_bh(); |
2994 | return if6_get_idx(seq, *pos); | 3004 | return if6_get_idx(seq, *pos); |
2995 | } | 3005 | } |
2996 | 3006 | ||
@@ -3004,9 +3014,9 @@ static void *if6_seq_next(struct seq_file *seq, void *v, loff_t *pos) | |||
3004 | } | 3014 | } |
3005 | 3015 | ||
3006 | static void if6_seq_stop(struct seq_file *seq, void *v) | 3016 | static void if6_seq_stop(struct seq_file *seq, void *v) |
3007 | __releases(addrconf_hash_lock) | 3017 | __releases(rcu) |
3008 | { | 3018 | { |
3009 | read_unlock_bh(&addrconf_hash_lock); | 3019 | rcu_read_unlock_bh(); |
3010 | } | 3020 | } |
3011 | 3021 | ||
3012 | static int if6_seq_show(struct seq_file *seq, void *v) | 3022 | static int if6_seq_show(struct seq_file *seq, void *v) |
@@ -3076,10 +3086,12 @@ void if6_proc_exit(void) | |||
3076 | int ipv6_chk_home_addr(struct net *net, struct in6_addr *addr) | 3086 | int ipv6_chk_home_addr(struct net *net, struct in6_addr *addr) |
3077 | { | 3087 | { |
3078 | int ret = 0; | 3088 | int ret = 0; |
3079 | struct inet6_ifaddr * ifp; | 3089 | struct inet6_ifaddr *ifp = NULL; |
3080 | u8 hash = ipv6_addr_hash(addr); | 3090 | struct hlist_node *n; |
3081 | read_lock_bh(&addrconf_hash_lock); | 3091 | unsigned int hash = ipv6_addr_hash(addr); |
3082 | for (ifp = inet6_addr_lst[hash]; ifp; ifp = ifp->lst_next) { | 3092 | |
3093 | rcu_read_lock_bh(); | ||
3094 | hlist_for_each_entry_rcu(ifp, n, &inet6_addr_lst[hash], addr_lst) { | ||
3083 | if (!net_eq(dev_net(ifp->idev->dev), net)) | 3095 | if (!net_eq(dev_net(ifp->idev->dev), net)) |
3084 | continue; | 3096 | continue; |
3085 | if (ipv6_addr_equal(&ifp->addr, addr) && | 3097 | if (ipv6_addr_equal(&ifp->addr, addr) && |
@@ -3088,7 +3100,7 @@ int ipv6_chk_home_addr(struct net *net, struct in6_addr *addr) | |||
3088 | break; | 3100 | break; |
3089 | } | 3101 | } |
3090 | } | 3102 | } |
3091 | read_unlock_bh(&addrconf_hash_lock); | 3103 | rcu_read_unlock_bh(); |
3092 | return ret; | 3104 | return ret; |
3093 | } | 3105 | } |
3094 | #endif | 3106 | #endif |
@@ -3099,43 +3111,35 @@ int ipv6_chk_home_addr(struct net *net, struct in6_addr *addr) | |||
3099 | 3111 | ||
3100 | static void addrconf_verify(unsigned long foo) | 3112 | static void addrconf_verify(unsigned long foo) |
3101 | { | 3113 | { |
3114 | unsigned long now, next, next_sec, next_sched; | ||
3102 | struct inet6_ifaddr *ifp; | 3115 | struct inet6_ifaddr *ifp; |
3103 | unsigned long now, next; | 3116 | struct hlist_node *node; |
3104 | int i; | 3117 | int i; |
3105 | 3118 | ||
3106 | spin_lock_bh(&addrconf_verify_lock); | 3119 | rcu_read_lock_bh(); |
3120 | spin_lock(&addrconf_verify_lock); | ||
3107 | now = jiffies; | 3121 | now = jiffies; |
3108 | next = now + ADDR_CHECK_FREQUENCY; | 3122 | next = round_jiffies_up(now + ADDR_CHECK_FREQUENCY); |
3109 | 3123 | ||
3110 | del_timer(&addr_chk_timer); | 3124 | del_timer(&addr_chk_timer); |
3111 | 3125 | ||
3112 | for (i=0; i < IN6_ADDR_HSIZE; i++) { | 3126 | for (i = 0; i < IN6_ADDR_HSIZE; i++) { |
3113 | |||
3114 | restart: | 3127 | restart: |
3115 | read_lock(&addrconf_hash_lock); | 3128 | hlist_for_each_entry_rcu(ifp, node, |
3116 | for (ifp=inet6_addr_lst[i]; ifp; ifp=ifp->lst_next) { | 3129 | &inet6_addr_lst[i], addr_lst) { |
3117 | unsigned long age; | 3130 | unsigned long age; |
3118 | #ifdef CONFIG_IPV6_PRIVACY | ||
3119 | unsigned long regen_advance; | ||
3120 | #endif | ||
3121 | 3131 | ||
3122 | if (ifp->flags & IFA_F_PERMANENT) | 3132 | if (ifp->flags & IFA_F_PERMANENT) |
3123 | continue; | 3133 | continue; |
3124 | 3134 | ||
3125 | spin_lock(&ifp->lock); | 3135 | spin_lock(&ifp->lock); |
3126 | age = (now - ifp->tstamp) / HZ; | 3136 | /* We try to batch several events at once. */ |
3127 | 3137 | age = (now - ifp->tstamp + ADDRCONF_TIMER_FUZZ_MINUS) / HZ; | |
3128 | #ifdef CONFIG_IPV6_PRIVACY | ||
3129 | regen_advance = ifp->idev->cnf.regen_max_retry * | ||
3130 | ifp->idev->cnf.dad_transmits * | ||
3131 | ifp->idev->nd_parms->retrans_time / HZ; | ||
3132 | #endif | ||
3133 | 3138 | ||
3134 | if (ifp->valid_lft != INFINITY_LIFE_TIME && | 3139 | if (ifp->valid_lft != INFINITY_LIFE_TIME && |
3135 | age >= ifp->valid_lft) { | 3140 | age >= ifp->valid_lft) { |
3136 | spin_unlock(&ifp->lock); | 3141 | spin_unlock(&ifp->lock); |
3137 | in6_ifa_hold(ifp); | 3142 | in6_ifa_hold(ifp); |
3138 | read_unlock(&addrconf_hash_lock); | ||
3139 | ipv6_del_addr(ifp); | 3143 | ipv6_del_addr(ifp); |
3140 | goto restart; | 3144 | goto restart; |
3141 | } else if (ifp->prefered_lft == INFINITY_LIFE_TIME) { | 3145 | } else if (ifp->prefered_lft == INFINITY_LIFE_TIME) { |
@@ -3157,7 +3161,6 @@ restart: | |||
3157 | 3161 | ||
3158 | if (deprecate) { | 3162 | if (deprecate) { |
3159 | in6_ifa_hold(ifp); | 3163 | in6_ifa_hold(ifp); |
3160 | read_unlock(&addrconf_hash_lock); | ||
3161 | 3164 | ||
3162 | ipv6_ifa_notify(0, ifp); | 3165 | ipv6_ifa_notify(0, ifp); |
3163 | in6_ifa_put(ifp); | 3166 | in6_ifa_put(ifp); |
@@ -3166,6 +3169,10 @@ restart: | |||
3166 | #ifdef CONFIG_IPV6_PRIVACY | 3169 | #ifdef CONFIG_IPV6_PRIVACY |
3167 | } else if ((ifp->flags&IFA_F_TEMPORARY) && | 3170 | } else if ((ifp->flags&IFA_F_TEMPORARY) && |
3168 | !(ifp->flags&IFA_F_TENTATIVE)) { | 3171 | !(ifp->flags&IFA_F_TENTATIVE)) { |
3172 | unsigned long regen_advance = ifp->idev->cnf.regen_max_retry * | ||
3173 | ifp->idev->cnf.dad_transmits * | ||
3174 | ifp->idev->nd_parms->retrans_time / HZ; | ||
3175 | |||
3169 | if (age >= ifp->prefered_lft - regen_advance) { | 3176 | if (age >= ifp->prefered_lft - regen_advance) { |
3170 | struct inet6_ifaddr *ifpub = ifp->ifpub; | 3177 | struct inet6_ifaddr *ifpub = ifp->ifpub; |
3171 | if (time_before(ifp->tstamp + ifp->prefered_lft * HZ, next)) | 3178 | if (time_before(ifp->tstamp + ifp->prefered_lft * HZ, next)) |
@@ -3175,7 +3182,7 @@ restart: | |||
3175 | in6_ifa_hold(ifp); | 3182 | in6_ifa_hold(ifp); |
3176 | in6_ifa_hold(ifpub); | 3183 | in6_ifa_hold(ifpub); |
3177 | spin_unlock(&ifp->lock); | 3184 | spin_unlock(&ifp->lock); |
3178 | read_unlock(&addrconf_hash_lock); | 3185 | |
3179 | spin_lock(&ifpub->lock); | 3186 | spin_lock(&ifpub->lock); |
3180 | ifpub->regen_count = 0; | 3187 | ifpub->regen_count = 0; |
3181 | spin_unlock(&ifpub->lock); | 3188 | spin_unlock(&ifpub->lock); |
@@ -3195,12 +3202,26 @@ restart: | |||
3195 | spin_unlock(&ifp->lock); | 3202 | spin_unlock(&ifp->lock); |
3196 | } | 3203 | } |
3197 | } | 3204 | } |
3198 | read_unlock(&addrconf_hash_lock); | ||
3199 | } | 3205 | } |
3200 | 3206 | ||
3201 | addr_chk_timer.expires = time_before(next, jiffies + HZ) ? jiffies + HZ : next; | 3207 | next_sec = round_jiffies_up(next); |
3208 | next_sched = next; | ||
3209 | |||
3210 | /* If rounded timeout is accurate enough, accept it. */ | ||
3211 | if (time_before(next_sec, next + ADDRCONF_TIMER_FUZZ)) | ||
3212 | next_sched = next_sec; | ||
3213 | |||
3214 | /* And minimum interval is ADDRCONF_TIMER_FUZZ_MAX. */ | ||
3215 | if (time_before(next_sched, jiffies + ADDRCONF_TIMER_FUZZ_MAX)) | ||
3216 | next_sched = jiffies + ADDRCONF_TIMER_FUZZ_MAX; | ||
3217 | |||
3218 | ADBG((KERN_DEBUG "now = %lu, schedule = %lu, rounded schedule = %lu => %lu\n", | ||
3219 | now, next, next_sec, next_sched)); | ||
3220 | |||
3221 | addr_chk_timer.expires = next_sched; | ||
3202 | add_timer(&addr_chk_timer); | 3222 | add_timer(&addr_chk_timer); |
3203 | spin_unlock_bh(&addrconf_verify_lock); | 3223 | spin_unlock(&addrconf_verify_lock); |
3224 | rcu_read_unlock_bh(); | ||
3204 | } | 3225 | } |
3205 | 3226 | ||
3206 | static struct in6_addr *extract_addr(struct nlattr *addr, struct nlattr *local) | 3227 | static struct in6_addr *extract_addr(struct nlattr *addr, struct nlattr *local) |
@@ -3490,8 +3511,7 @@ static int inet6_fill_ifacaddr(struct sk_buff *skb, struct ifacaddr6 *ifaca, | |||
3490 | return nlmsg_end(skb, nlh); | 3511 | return nlmsg_end(skb, nlh); |
3491 | } | 3512 | } |
3492 | 3513 | ||
3493 | enum addr_type_t | 3514 | enum addr_type_t { |
3494 | { | ||
3495 | UNICAST_ADDR, | 3515 | UNICAST_ADDR, |
3496 | MULTICAST_ADDR, | 3516 | MULTICAST_ADDR, |
3497 | ANYCAST_ADDR, | 3517 | ANYCAST_ADDR, |
@@ -3502,7 +3522,6 @@ static int in6_dump_addrs(struct inet6_dev *idev, struct sk_buff *skb, | |||
3502 | struct netlink_callback *cb, enum addr_type_t type, | 3522 | struct netlink_callback *cb, enum addr_type_t type, |
3503 | int s_ip_idx, int *p_ip_idx) | 3523 | int s_ip_idx, int *p_ip_idx) |
3504 | { | 3524 | { |
3505 | struct inet6_ifaddr *ifa; | ||
3506 | struct ifmcaddr6 *ifmca; | 3525 | struct ifmcaddr6 *ifmca; |
3507 | struct ifacaddr6 *ifaca; | 3526 | struct ifacaddr6 *ifaca; |
3508 | int err = 1; | 3527 | int err = 1; |
@@ -3510,11 +3529,12 @@ static int in6_dump_addrs(struct inet6_dev *idev, struct sk_buff *skb, | |||
3510 | 3529 | ||
3511 | read_lock_bh(&idev->lock); | 3530 | read_lock_bh(&idev->lock); |
3512 | switch (type) { | 3531 | switch (type) { |
3513 | case UNICAST_ADDR: | 3532 | case UNICAST_ADDR: { |
3533 | struct inet6_ifaddr *ifa; | ||
3534 | |||
3514 | /* unicast address incl. temp addr */ | 3535 | /* unicast address incl. temp addr */ |
3515 | for (ifa = idev->addr_list; ifa; | 3536 | list_for_each_entry(ifa, &idev->addr_list, if_list) { |
3516 | ifa = ifa->if_next, ip_idx++) { | 3537 | if (++ip_idx < s_ip_idx) |
3517 | if (ip_idx < s_ip_idx) | ||
3518 | continue; | 3538 | continue; |
3519 | err = inet6_fill_ifaddr(skb, ifa, | 3539 | err = inet6_fill_ifaddr(skb, ifa, |
3520 | NETLINK_CB(cb->skb).pid, | 3540 | NETLINK_CB(cb->skb).pid, |
@@ -3525,6 +3545,7 @@ static int in6_dump_addrs(struct inet6_dev *idev, struct sk_buff *skb, | |||
3525 | break; | 3545 | break; |
3526 | } | 3546 | } |
3527 | break; | 3547 | break; |
3548 | } | ||
3528 | case MULTICAST_ADDR: | 3549 | case MULTICAST_ADDR: |
3529 | /* multicast address */ | 3550 | /* multicast address */ |
3530 | for (ifmca = idev->mc_list; ifmca; | 3551 | for (ifmca = idev->mc_list; ifmca; |
@@ -3589,7 +3610,8 @@ static int inet6_dump_addr(struct sk_buff *skb, struct netlink_callback *cb, | |||
3589 | if (idx > s_idx) | 3610 | if (idx > s_idx) |
3590 | s_ip_idx = 0; | 3611 | s_ip_idx = 0; |
3591 | ip_idx = 0; | 3612 | ip_idx = 0; |
3592 | if ((idev = __in6_dev_get(dev)) == NULL) | 3613 | idev = __in6_dev_get(dev); |
3614 | if (!idev) | ||
3593 | goto cont; | 3615 | goto cont; |
3594 | 3616 | ||
3595 | if (in6_dump_addrs(idev, skb, cb, type, | 3617 | if (in6_dump_addrs(idev, skb, cb, type, |
@@ -3656,12 +3678,14 @@ static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr* nlh, | |||
3656 | if (ifm->ifa_index) | 3678 | if (ifm->ifa_index) |
3657 | dev = __dev_get_by_index(net, ifm->ifa_index); | 3679 | dev = __dev_get_by_index(net, ifm->ifa_index); |
3658 | 3680 | ||
3659 | if ((ifa = ipv6_get_ifaddr(net, addr, dev, 1)) == NULL) { | 3681 | ifa = ipv6_get_ifaddr(net, addr, dev, 1); |
3682 | if (!ifa) { | ||
3660 | err = -EADDRNOTAVAIL; | 3683 | err = -EADDRNOTAVAIL; |
3661 | goto errout; | 3684 | goto errout; |
3662 | } | 3685 | } |
3663 | 3686 | ||
3664 | if ((skb = nlmsg_new(inet6_ifaddr_msgsize(), GFP_KERNEL)) == NULL) { | 3687 | skb = nlmsg_new(inet6_ifaddr_msgsize(), GFP_KERNEL); |
3688 | if (!skb) { | ||
3665 | err = -ENOBUFS; | 3689 | err = -ENOBUFS; |
3666 | goto errout_ifa; | 3690 | goto errout_ifa; |
3667 | } | 3691 | } |
@@ -3786,7 +3810,7 @@ static inline void __snmp6_fill_stats(u64 *stats, void __percpu **mib, | |||
3786 | static void snmp6_fill_stats(u64 *stats, struct inet6_dev *idev, int attrtype, | 3810 | static void snmp6_fill_stats(u64 *stats, struct inet6_dev *idev, int attrtype, |
3787 | int bytes) | 3811 | int bytes) |
3788 | { | 3812 | { |
3789 | switch(attrtype) { | 3813 | switch (attrtype) { |
3790 | case IFLA_INET6_STATS: | 3814 | case IFLA_INET6_STATS: |
3791 | __snmp6_fill_stats(stats, (void __percpu **)idev->stats.ipv6, IPSTATS_MIB_MAX, bytes); | 3815 | __snmp6_fill_stats(stats, (void __percpu **)idev->stats.ipv6, IPSTATS_MIB_MAX, bytes); |
3792 | break; | 3816 | break; |
@@ -4138,211 +4162,211 @@ static struct addrconf_sysctl_table | |||
4138 | .sysctl_header = NULL, | 4162 | .sysctl_header = NULL, |
4139 | .addrconf_vars = { | 4163 | .addrconf_vars = { |
4140 | { | 4164 | { |
4141 | .procname = "forwarding", | 4165 | .procname = "forwarding", |
4142 | .data = &ipv6_devconf.forwarding, | 4166 | .data = &ipv6_devconf.forwarding, |
4143 | .maxlen = sizeof(int), | 4167 | .maxlen = sizeof(int), |
4144 | .mode = 0644, | 4168 | .mode = 0644, |
4145 | .proc_handler = addrconf_sysctl_forward, | 4169 | .proc_handler = addrconf_sysctl_forward, |
4146 | }, | 4170 | }, |
4147 | { | 4171 | { |
4148 | .procname = "hop_limit", | 4172 | .procname = "hop_limit", |
4149 | .data = &ipv6_devconf.hop_limit, | 4173 | .data = &ipv6_devconf.hop_limit, |
4150 | .maxlen = sizeof(int), | 4174 | .maxlen = sizeof(int), |
4151 | .mode = 0644, | 4175 | .mode = 0644, |
4152 | .proc_handler = proc_dointvec, | 4176 | .proc_handler = proc_dointvec, |
4153 | }, | 4177 | }, |
4154 | { | 4178 | { |
4155 | .procname = "mtu", | 4179 | .procname = "mtu", |
4156 | .data = &ipv6_devconf.mtu6, | 4180 | .data = &ipv6_devconf.mtu6, |
4157 | .maxlen = sizeof(int), | 4181 | .maxlen = sizeof(int), |
4158 | .mode = 0644, | 4182 | .mode = 0644, |
4159 | .proc_handler = proc_dointvec, | 4183 | .proc_handler = proc_dointvec, |
4160 | }, | 4184 | }, |
4161 | { | 4185 | { |
4162 | .procname = "accept_ra", | 4186 | .procname = "accept_ra", |
4163 | .data = &ipv6_devconf.accept_ra, | 4187 | .data = &ipv6_devconf.accept_ra, |
4164 | .maxlen = sizeof(int), | 4188 | .maxlen = sizeof(int), |
4165 | .mode = 0644, | 4189 | .mode = 0644, |
4166 | .proc_handler = proc_dointvec, | 4190 | .proc_handler = proc_dointvec, |
4167 | }, | 4191 | }, |
4168 | { | 4192 | { |
4169 | .procname = "accept_redirects", | 4193 | .procname = "accept_redirects", |
4170 | .data = &ipv6_devconf.accept_redirects, | 4194 | .data = &ipv6_devconf.accept_redirects, |
4171 | .maxlen = sizeof(int), | 4195 | .maxlen = sizeof(int), |
4172 | .mode = 0644, | 4196 | .mode = 0644, |
4173 | .proc_handler = proc_dointvec, | 4197 | .proc_handler = proc_dointvec, |
4174 | }, | 4198 | }, |
4175 | { | 4199 | { |
4176 | .procname = "autoconf", | 4200 | .procname = "autoconf", |
4177 | .data = &ipv6_devconf.autoconf, | 4201 | .data = &ipv6_devconf.autoconf, |
4178 | .maxlen = sizeof(int), | 4202 | .maxlen = sizeof(int), |
4179 | .mode = 0644, | 4203 | .mode = 0644, |
4180 | .proc_handler = proc_dointvec, | 4204 | .proc_handler = proc_dointvec, |
4181 | }, | 4205 | }, |
4182 | { | 4206 | { |
4183 | .procname = "dad_transmits", | 4207 | .procname = "dad_transmits", |
4184 | .data = &ipv6_devconf.dad_transmits, | 4208 | .data = &ipv6_devconf.dad_transmits, |
4185 | .maxlen = sizeof(int), | 4209 | .maxlen = sizeof(int), |
4186 | .mode = 0644, | 4210 | .mode = 0644, |
4187 | .proc_handler = proc_dointvec, | 4211 | .proc_handler = proc_dointvec, |
4188 | }, | 4212 | }, |
4189 | { | 4213 | { |
4190 | .procname = "router_solicitations", | 4214 | .procname = "router_solicitations", |
4191 | .data = &ipv6_devconf.rtr_solicits, | 4215 | .data = &ipv6_devconf.rtr_solicits, |
4192 | .maxlen = sizeof(int), | 4216 | .maxlen = sizeof(int), |
4193 | .mode = 0644, | 4217 | .mode = 0644, |
4194 | .proc_handler = proc_dointvec, | 4218 | .proc_handler = proc_dointvec, |
4195 | }, | 4219 | }, |
4196 | { | 4220 | { |
4197 | .procname = "router_solicitation_interval", | 4221 | .procname = "router_solicitation_interval", |
4198 | .data = &ipv6_devconf.rtr_solicit_interval, | 4222 | .data = &ipv6_devconf.rtr_solicit_interval, |
4199 | .maxlen = sizeof(int), | 4223 | .maxlen = sizeof(int), |
4200 | .mode = 0644, | 4224 | .mode = 0644, |
4201 | .proc_handler = proc_dointvec_jiffies, | 4225 | .proc_handler = proc_dointvec_jiffies, |
4202 | }, | 4226 | }, |
4203 | { | 4227 | { |
4204 | .procname = "router_solicitation_delay", | 4228 | .procname = "router_solicitation_delay", |
4205 | .data = &ipv6_devconf.rtr_solicit_delay, | 4229 | .data = &ipv6_devconf.rtr_solicit_delay, |
4206 | .maxlen = sizeof(int), | 4230 | .maxlen = sizeof(int), |
4207 | .mode = 0644, | 4231 | .mode = 0644, |
4208 | .proc_handler = proc_dointvec_jiffies, | 4232 | .proc_handler = proc_dointvec_jiffies, |
4209 | }, | 4233 | }, |
4210 | { | 4234 | { |
4211 | .procname = "force_mld_version", | 4235 | .procname = "force_mld_version", |
4212 | .data = &ipv6_devconf.force_mld_version, | 4236 | .data = &ipv6_devconf.force_mld_version, |
4213 | .maxlen = sizeof(int), | 4237 | .maxlen = sizeof(int), |
4214 | .mode = 0644, | 4238 | .mode = 0644, |
4215 | .proc_handler = proc_dointvec, | 4239 | .proc_handler = proc_dointvec, |
4216 | }, | 4240 | }, |
4217 | #ifdef CONFIG_IPV6_PRIVACY | 4241 | #ifdef CONFIG_IPV6_PRIVACY |
4218 | { | 4242 | { |
4219 | .procname = "use_tempaddr", | 4243 | .procname = "use_tempaddr", |
4220 | .data = &ipv6_devconf.use_tempaddr, | 4244 | .data = &ipv6_devconf.use_tempaddr, |
4221 | .maxlen = sizeof(int), | 4245 | .maxlen = sizeof(int), |
4222 | .mode = 0644, | 4246 | .mode = 0644, |
4223 | .proc_handler = proc_dointvec, | 4247 | .proc_handler = proc_dointvec, |
4224 | }, | 4248 | }, |
4225 | { | 4249 | { |
4226 | .procname = "temp_valid_lft", | 4250 | .procname = "temp_valid_lft", |
4227 | .data = &ipv6_devconf.temp_valid_lft, | 4251 | .data = &ipv6_devconf.temp_valid_lft, |
4228 | .maxlen = sizeof(int), | 4252 | .maxlen = sizeof(int), |
4229 | .mode = 0644, | 4253 | .mode = 0644, |
4230 | .proc_handler = proc_dointvec, | 4254 | .proc_handler = proc_dointvec, |
4231 | }, | 4255 | }, |
4232 | { | 4256 | { |
4233 | .procname = "temp_prefered_lft", | 4257 | .procname = "temp_prefered_lft", |
4234 | .data = &ipv6_devconf.temp_prefered_lft, | 4258 | .data = &ipv6_devconf.temp_prefered_lft, |
4235 | .maxlen = sizeof(int), | 4259 | .maxlen = sizeof(int), |
4236 | .mode = 0644, | 4260 | .mode = 0644, |
4237 | .proc_handler = proc_dointvec, | 4261 | .proc_handler = proc_dointvec, |
4238 | }, | 4262 | }, |
4239 | { | 4263 | { |
4240 | .procname = "regen_max_retry", | 4264 | .procname = "regen_max_retry", |
4241 | .data = &ipv6_devconf.regen_max_retry, | 4265 | .data = &ipv6_devconf.regen_max_retry, |
4242 | .maxlen = sizeof(int), | 4266 | .maxlen = sizeof(int), |
4243 | .mode = 0644, | 4267 | .mode = 0644, |
4244 | .proc_handler = proc_dointvec, | 4268 | .proc_handler = proc_dointvec, |
4245 | }, | 4269 | }, |
4246 | { | 4270 | { |
4247 | .procname = "max_desync_factor", | 4271 | .procname = "max_desync_factor", |
4248 | .data = &ipv6_devconf.max_desync_factor, | 4272 | .data = &ipv6_devconf.max_desync_factor, |
4249 | .maxlen = sizeof(int), | 4273 | .maxlen = sizeof(int), |
4250 | .mode = 0644, | 4274 | .mode = 0644, |
4251 | .proc_handler = proc_dointvec, | 4275 | .proc_handler = proc_dointvec, |
4252 | }, | 4276 | }, |
4253 | #endif | 4277 | #endif |
4254 | { | 4278 | { |
4255 | .procname = "max_addresses", | 4279 | .procname = "max_addresses", |
4256 | .data = &ipv6_devconf.max_addresses, | 4280 | .data = &ipv6_devconf.max_addresses, |
4257 | .maxlen = sizeof(int), | 4281 | .maxlen = sizeof(int), |
4258 | .mode = 0644, | 4282 | .mode = 0644, |
4259 | .proc_handler = proc_dointvec, | 4283 | .proc_handler = proc_dointvec, |
4260 | }, | 4284 | }, |
4261 | { | 4285 | { |
4262 | .procname = "accept_ra_defrtr", | 4286 | .procname = "accept_ra_defrtr", |
4263 | .data = &ipv6_devconf.accept_ra_defrtr, | 4287 | .data = &ipv6_devconf.accept_ra_defrtr, |
4264 | .maxlen = sizeof(int), | 4288 | .maxlen = sizeof(int), |
4265 | .mode = 0644, | 4289 | .mode = 0644, |
4266 | .proc_handler = proc_dointvec, | 4290 | .proc_handler = proc_dointvec, |
4267 | }, | 4291 | }, |
4268 | { | 4292 | { |
4269 | .procname = "accept_ra_pinfo", | 4293 | .procname = "accept_ra_pinfo", |
4270 | .data = &ipv6_devconf.accept_ra_pinfo, | 4294 | .data = &ipv6_devconf.accept_ra_pinfo, |
4271 | .maxlen = sizeof(int), | 4295 | .maxlen = sizeof(int), |
4272 | .mode = 0644, | 4296 | .mode = 0644, |
4273 | .proc_handler = proc_dointvec, | 4297 | .proc_handler = proc_dointvec, |
4274 | }, | 4298 | }, |
4275 | #ifdef CONFIG_IPV6_ROUTER_PREF | 4299 | #ifdef CONFIG_IPV6_ROUTER_PREF |
4276 | { | 4300 | { |
4277 | .procname = "accept_ra_rtr_pref", | 4301 | .procname = "accept_ra_rtr_pref", |
4278 | .data = &ipv6_devconf.accept_ra_rtr_pref, | 4302 | .data = &ipv6_devconf.accept_ra_rtr_pref, |
4279 | .maxlen = sizeof(int), | 4303 | .maxlen = sizeof(int), |
4280 | .mode = 0644, | 4304 | .mode = 0644, |
4281 | .proc_handler = proc_dointvec, | 4305 | .proc_handler = proc_dointvec, |
4282 | }, | 4306 | }, |
4283 | { | 4307 | { |
4284 | .procname = "router_probe_interval", | 4308 | .procname = "router_probe_interval", |
4285 | .data = &ipv6_devconf.rtr_probe_interval, | 4309 | .data = &ipv6_devconf.rtr_probe_interval, |
4286 | .maxlen = sizeof(int), | 4310 | .maxlen = sizeof(int), |
4287 | .mode = 0644, | 4311 | .mode = 0644, |
4288 | .proc_handler = proc_dointvec_jiffies, | 4312 | .proc_handler = proc_dointvec_jiffies, |
4289 | }, | 4313 | }, |
4290 | #ifdef CONFIG_IPV6_ROUTE_INFO | 4314 | #ifdef CONFIG_IPV6_ROUTE_INFO |
4291 | { | 4315 | { |
4292 | .procname = "accept_ra_rt_info_max_plen", | 4316 | .procname = "accept_ra_rt_info_max_plen", |
4293 | .data = &ipv6_devconf.accept_ra_rt_info_max_plen, | 4317 | .data = &ipv6_devconf.accept_ra_rt_info_max_plen, |
4294 | .maxlen = sizeof(int), | 4318 | .maxlen = sizeof(int), |
4295 | .mode = 0644, | 4319 | .mode = 0644, |
4296 | .proc_handler = proc_dointvec, | 4320 | .proc_handler = proc_dointvec, |
4297 | }, | 4321 | }, |
4298 | #endif | 4322 | #endif |
4299 | #endif | 4323 | #endif |
4300 | { | 4324 | { |
4301 | .procname = "proxy_ndp", | 4325 | .procname = "proxy_ndp", |
4302 | .data = &ipv6_devconf.proxy_ndp, | 4326 | .data = &ipv6_devconf.proxy_ndp, |
4303 | .maxlen = sizeof(int), | 4327 | .maxlen = sizeof(int), |
4304 | .mode = 0644, | 4328 | .mode = 0644, |
4305 | .proc_handler = proc_dointvec, | 4329 | .proc_handler = proc_dointvec, |
4306 | }, | 4330 | }, |
4307 | { | 4331 | { |
4308 | .procname = "accept_source_route", | 4332 | .procname = "accept_source_route", |
4309 | .data = &ipv6_devconf.accept_source_route, | 4333 | .data = &ipv6_devconf.accept_source_route, |
4310 | .maxlen = sizeof(int), | 4334 | .maxlen = sizeof(int), |
4311 | .mode = 0644, | 4335 | .mode = 0644, |
4312 | .proc_handler = proc_dointvec, | 4336 | .proc_handler = proc_dointvec, |
4313 | }, | 4337 | }, |
4314 | #ifdef CONFIG_IPV6_OPTIMISTIC_DAD | 4338 | #ifdef CONFIG_IPV6_OPTIMISTIC_DAD |
4315 | { | 4339 | { |
4316 | .procname = "optimistic_dad", | 4340 | .procname = "optimistic_dad", |
4317 | .data = &ipv6_devconf.optimistic_dad, | 4341 | .data = &ipv6_devconf.optimistic_dad, |
4318 | .maxlen = sizeof(int), | 4342 | .maxlen = sizeof(int), |
4319 | .mode = 0644, | 4343 | .mode = 0644, |
4320 | .proc_handler = proc_dointvec, | 4344 | .proc_handler = proc_dointvec, |
4321 | 4345 | ||
4322 | }, | 4346 | }, |
4323 | #endif | 4347 | #endif |
4324 | #ifdef CONFIG_IPV6_MROUTE | 4348 | #ifdef CONFIG_IPV6_MROUTE |
4325 | { | 4349 | { |
4326 | .procname = "mc_forwarding", | 4350 | .procname = "mc_forwarding", |
4327 | .data = &ipv6_devconf.mc_forwarding, | 4351 | .data = &ipv6_devconf.mc_forwarding, |
4328 | .maxlen = sizeof(int), | 4352 | .maxlen = sizeof(int), |
4329 | .mode = 0444, | 4353 | .mode = 0444, |
4330 | .proc_handler = proc_dointvec, | 4354 | .proc_handler = proc_dointvec, |
4331 | }, | 4355 | }, |
4332 | #endif | 4356 | #endif |
4333 | { | 4357 | { |
4334 | .procname = "disable_ipv6", | 4358 | .procname = "disable_ipv6", |
4335 | .data = &ipv6_devconf.disable_ipv6, | 4359 | .data = &ipv6_devconf.disable_ipv6, |
4336 | .maxlen = sizeof(int), | 4360 | .maxlen = sizeof(int), |
4337 | .mode = 0644, | 4361 | .mode = 0644, |
4338 | .proc_handler = addrconf_sysctl_disable, | 4362 | .proc_handler = addrconf_sysctl_disable, |
4339 | }, | 4363 | }, |
4340 | { | 4364 | { |
4341 | .procname = "accept_dad", | 4365 | .procname = "accept_dad", |
4342 | .data = &ipv6_devconf.accept_dad, | 4366 | .data = &ipv6_devconf.accept_dad, |
4343 | .maxlen = sizeof(int), | 4367 | .maxlen = sizeof(int), |
4344 | .mode = 0644, | 4368 | .mode = 0644, |
4345 | .proc_handler = proc_dointvec, | 4369 | .proc_handler = proc_dointvec, |
4346 | }, | 4370 | }, |
4347 | { | 4371 | { |
4348 | .procname = "force_tllao", | 4372 | .procname = "force_tllao", |
@@ -4378,8 +4402,8 @@ static int __addrconf_sysctl_register(struct net *net, char *dev_name, | |||
4378 | if (t == NULL) | 4402 | if (t == NULL) |
4379 | goto out; | 4403 | goto out; |
4380 | 4404 | ||
4381 | for (i=0; t->addrconf_vars[i].data; i++) { | 4405 | for (i = 0; t->addrconf_vars[i].data; i++) { |
4382 | t->addrconf_vars[i].data += (char*)p - (char*)&ipv6_devconf; | 4406 | t->addrconf_vars[i].data += (char *)p - (char *)&ipv6_devconf; |
4383 | t->addrconf_vars[i].extra1 = idev; /* embedded; no ref */ | 4407 | t->addrconf_vars[i].extra1 = idev; /* embedded; no ref */ |
4384 | t->addrconf_vars[i].extra2 = net; | 4408 | t->addrconf_vars[i].extra2 = net; |
4385 | } | 4409 | } |
@@ -4516,14 +4540,12 @@ int register_inet6addr_notifier(struct notifier_block *nb) | |||
4516 | { | 4540 | { |
4517 | return atomic_notifier_chain_register(&inet6addr_chain, nb); | 4541 | return atomic_notifier_chain_register(&inet6addr_chain, nb); |
4518 | } | 4542 | } |
4519 | |||
4520 | EXPORT_SYMBOL(register_inet6addr_notifier); | 4543 | EXPORT_SYMBOL(register_inet6addr_notifier); |
4521 | 4544 | ||
4522 | int unregister_inet6addr_notifier(struct notifier_block *nb) | 4545 | int unregister_inet6addr_notifier(struct notifier_block *nb) |
4523 | { | 4546 | { |
4524 | return atomic_notifier_chain_unregister(&inet6addr_chain,nb); | 4547 | return atomic_notifier_chain_unregister(&inet6addr_chain, nb); |
4525 | } | 4548 | } |
4526 | |||
4527 | EXPORT_SYMBOL(unregister_inet6addr_notifier); | 4549 | EXPORT_SYMBOL(unregister_inet6addr_notifier); |
4528 | 4550 | ||
4529 | /* | 4551 | /* |
@@ -4532,11 +4554,12 @@ EXPORT_SYMBOL(unregister_inet6addr_notifier); | |||
4532 | 4554 | ||
4533 | int __init addrconf_init(void) | 4555 | int __init addrconf_init(void) |
4534 | { | 4556 | { |
4535 | int err; | 4557 | int i, err; |
4536 | 4558 | ||
4537 | if ((err = ipv6_addr_label_init()) < 0) { | 4559 | err = ipv6_addr_label_init(); |
4538 | printk(KERN_CRIT "IPv6 Addrconf: cannot initialize default policy table: %d.\n", | 4560 | if (err < 0) { |
4539 | err); | 4561 | printk(KERN_CRIT "IPv6 Addrconf:" |
4562 | " cannot initialize default policy table: %d.\n", err); | ||
4540 | return err; | 4563 | return err; |
4541 | } | 4564 | } |
4542 | 4565 | ||
@@ -4567,6 +4590,9 @@ int __init addrconf_init(void) | |||
4567 | if (err) | 4590 | if (err) |
4568 | goto errlo; | 4591 | goto errlo; |
4569 | 4592 | ||
4593 | for (i = 0; i < IN6_ADDR_HSIZE; i++) | ||
4594 | INIT_HLIST_HEAD(&inet6_addr_lst[i]); | ||
4595 | |||
4570 | register_netdevice_notifier(&ipv6_dev_notf); | 4596 | register_netdevice_notifier(&ipv6_dev_notf); |
4571 | 4597 | ||
4572 | addrconf_verify(0); | 4598 | addrconf_verify(0); |
@@ -4595,7 +4621,6 @@ errlo: | |||
4595 | 4621 | ||
4596 | void addrconf_cleanup(void) | 4622 | void addrconf_cleanup(void) |
4597 | { | 4623 | { |
4598 | struct inet6_ifaddr *ifa; | ||
4599 | struct net_device *dev; | 4624 | struct net_device *dev; |
4600 | int i; | 4625 | int i; |
4601 | 4626 | ||
@@ -4615,20 +4640,10 @@ void addrconf_cleanup(void) | |||
4615 | /* | 4640 | /* |
4616 | * Check hash table. | 4641 | * Check hash table. |
4617 | */ | 4642 | */ |
4618 | write_lock_bh(&addrconf_hash_lock); | 4643 | spin_lock_bh(&addrconf_hash_lock); |
4619 | for (i=0; i < IN6_ADDR_HSIZE; i++) { | 4644 | for (i = 0; i < IN6_ADDR_HSIZE; i++) |
4620 | for (ifa=inet6_addr_lst[i]; ifa; ) { | 4645 | WARN_ON(!hlist_empty(&inet6_addr_lst[i])); |
4621 | struct inet6_ifaddr *bifa; | 4646 | spin_unlock_bh(&addrconf_hash_lock); |
4622 | |||
4623 | bifa = ifa; | ||
4624 | ifa = ifa->lst_next; | ||
4625 | printk(KERN_DEBUG "bug: IPv6 address leakage detected: ifa=%p\n", bifa); | ||
4626 | /* Do not free it; something is wrong. | ||
4627 | Now we can investigate it with debugger. | ||
4628 | */ | ||
4629 | } | ||
4630 | } | ||
4631 | write_unlock_bh(&addrconf_hash_lock); | ||
4632 | 4647 | ||
4633 | del_timer(&addr_chk_timer); | 4648 | del_timer(&addr_chk_timer); |
4634 | rtnl_unlock(); | 4649 | rtnl_unlock(); |
diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c index 551882b9dfd6..5e463c43fcc2 100644 --- a/net/ipv6/fib6_rules.c +++ b/net/ipv6/fib6_rules.c | |||
@@ -84,18 +84,11 @@ static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp, | |||
84 | if ((rule->flags & FIB_RULE_FIND_SADDR) && | 84 | if ((rule->flags & FIB_RULE_FIND_SADDR) && |
85 | r->src.plen && !(flags & RT6_LOOKUP_F_HAS_SADDR)) { | 85 | r->src.plen && !(flags & RT6_LOOKUP_F_HAS_SADDR)) { |
86 | struct in6_addr saddr; | 86 | struct in6_addr saddr; |
87 | unsigned int srcprefs = 0; | ||
88 | |||
89 | if (flags & RT6_LOOKUP_F_SRCPREF_TMP) | ||
90 | srcprefs |= IPV6_PREFER_SRC_TMP; | ||
91 | if (flags & RT6_LOOKUP_F_SRCPREF_PUBLIC) | ||
92 | srcprefs |= IPV6_PREFER_SRC_PUBLIC; | ||
93 | if (flags & RT6_LOOKUP_F_SRCPREF_COA) | ||
94 | srcprefs |= IPV6_PREFER_SRC_COA; | ||
95 | 87 | ||
96 | if (ipv6_dev_get_saddr(net, | 88 | if (ipv6_dev_get_saddr(net, |
97 | ip6_dst_idev(&rt->u.dst)->dev, | 89 | ip6_dst_idev(&rt->u.dst)->dev, |
98 | &flp->fl6_dst, srcprefs, | 90 | &flp->fl6_dst, |
91 | rt6_flags2srcprefs(flags), | ||
99 | &saddr)) | 92 | &saddr)) |
100 | goto again; | 93 | goto again; |
101 | if (!ipv6_prefix_equal(&saddr, &r->src.addr, | 94 | if (!ipv6_prefix_equal(&saddr, &r->src.addr, |
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index 52e0f74fdfe0..23e4ac0cc30e 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c | |||
@@ -1113,6 +1113,9 @@ static int ip6mr_mfc_add(struct net *net, struct mf6cctl *mfc, int mrtsock) | |||
1113 | unsigned char ttls[MAXMIFS]; | 1113 | unsigned char ttls[MAXMIFS]; |
1114 | int i; | 1114 | int i; |
1115 | 1115 | ||
1116 | if (mfc->mf6cc_parent >= MAXMIFS) | ||
1117 | return -ENFILE; | ||
1118 | |||
1116 | memset(ttls, 255, MAXMIFS); | 1119 | memset(ttls, 255, MAXMIFS); |
1117 | for (i = 0; i < MAXMIFS; i++) { | 1120 | for (i = 0; i < MAXMIFS; i++) { |
1118 | if (IF_ISSET(i, &mfc->mf6cc_ifset)) | 1121 | if (IF_ISSET(i, &mfc->mf6cc_ifset)) |
diff --git a/net/ipv6/netfilter/ip6t_hbh.c b/net/ipv6/netfilter/ip6t_hbh.c index cbe8dec9744b..e60677519e40 100644 --- a/net/ipv6/netfilter/ip6t_hbh.c +++ b/net/ipv6/netfilter/ip6t_hbh.c | |||
@@ -141,11 +141,11 @@ hbh_mt6(const struct sk_buff *skb, const struct xt_match_param *par) | |||
141 | } | 141 | } |
142 | 142 | ||
143 | /* Step to the next */ | 143 | /* Step to the next */ |
144 | pr_debug("len%04X \n", optlen); | 144 | pr_debug("len%04X\n", optlen); |
145 | 145 | ||
146 | if ((ptr > skb->len - optlen || hdrlen < optlen) && | 146 | if ((ptr > skb->len - optlen || hdrlen < optlen) && |
147 | temp < optinfo->optsnr - 1) { | 147 | temp < optinfo->optsnr - 1) { |
148 | pr_debug("new pointer is too large! \n"); | 148 | pr_debug("new pointer is too large!\n"); |
149 | break; | 149 | break; |
150 | } | 150 | } |
151 | ptr += optlen; | 151 | ptr += optlen; |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index b08879e97f22..7fcb0e5d1213 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -819,15 +819,8 @@ struct dst_entry * ip6_route_output(struct net *net, struct sock *sk, | |||
819 | 819 | ||
820 | if (!ipv6_addr_any(&fl->fl6_src)) | 820 | if (!ipv6_addr_any(&fl->fl6_src)) |
821 | flags |= RT6_LOOKUP_F_HAS_SADDR; | 821 | flags |= RT6_LOOKUP_F_HAS_SADDR; |
822 | else if (sk) { | 822 | else if (sk) |
823 | unsigned int prefs = inet6_sk(sk)->srcprefs; | 823 | flags |= rt6_srcprefs2flags(inet6_sk(sk)->srcprefs); |
824 | if (prefs & IPV6_PREFER_SRC_TMP) | ||
825 | flags |= RT6_LOOKUP_F_SRCPREF_TMP; | ||
826 | if (prefs & IPV6_PREFER_SRC_PUBLIC) | ||
827 | flags |= RT6_LOOKUP_F_SRCPREF_PUBLIC; | ||
828 | if (prefs & IPV6_PREFER_SRC_COA) | ||
829 | flags |= RT6_LOOKUP_F_SRCPREF_COA; | ||
830 | } | ||
831 | 824 | ||
832 | return fib6_rule_lookup(net, fl, flags, ip6_pol_route_output); | 825 | return fib6_rule_lookup(net, fl, flags, ip6_pol_route_output); |
833 | } | 826 | } |
@@ -886,7 +879,7 @@ static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie) | |||
886 | 879 | ||
887 | rt = (struct rt6_info *) dst; | 880 | rt = (struct rt6_info *) dst; |
888 | 881 | ||
889 | if (rt && rt->rt6i_node && (rt->rt6i_node->fn_sernum == cookie)) | 882 | if (rt->rt6i_node && (rt->rt6i_node->fn_sernum == cookie)) |
890 | return dst; | 883 | return dst; |
891 | 884 | ||
892 | return NULL; | 885 | return NULL; |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 6963a6b6763e..9b6dbba80d31 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -1740,8 +1740,11 @@ process: | |||
1740 | if (!tcp_prequeue(sk, skb)) | 1740 | if (!tcp_prequeue(sk, skb)) |
1741 | ret = tcp_v6_do_rcv(sk, skb); | 1741 | ret = tcp_v6_do_rcv(sk, skb); |
1742 | } | 1742 | } |
1743 | } else | 1743 | } else if (unlikely(sk_add_backlog(sk, skb))) { |
1744 | sk_add_backlog(sk, skb); | 1744 | bh_unlock_sock(sk); |
1745 | NET_INC_STATS_BH(net, LINUX_MIB_TCPBACKLOGDROP); | ||
1746 | goto discard_and_relse; | ||
1747 | } | ||
1745 | bh_unlock_sock(sk); | 1748 | bh_unlock_sock(sk); |
1746 | 1749 | ||
1747 | sock_put(sk); | 1750 | sock_put(sk); |
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 52b8347ae3b2..3c0c9c755c92 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -583,16 +583,20 @@ static void flush_stack(struct sock **stack, unsigned int count, | |||
583 | bh_lock_sock(sk); | 583 | bh_lock_sock(sk); |
584 | if (!sock_owned_by_user(sk)) | 584 | if (!sock_owned_by_user(sk)) |
585 | udpv6_queue_rcv_skb(sk, skb1); | 585 | udpv6_queue_rcv_skb(sk, skb1); |
586 | else | 586 | else if (sk_add_backlog(sk, skb1)) { |
587 | sk_add_backlog(sk, skb1); | 587 | kfree_skb(skb1); |
588 | bh_unlock_sock(sk); | ||
589 | goto drop; | ||
590 | } | ||
588 | bh_unlock_sock(sk); | 591 | bh_unlock_sock(sk); |
589 | } else { | 592 | continue; |
590 | atomic_inc(&sk->sk_drops); | ||
591 | UDP6_INC_STATS_BH(sock_net(sk), | ||
592 | UDP_MIB_RCVBUFERRORS, IS_UDPLITE(sk)); | ||
593 | UDP6_INC_STATS_BH(sock_net(sk), | ||
594 | UDP_MIB_INERRORS, IS_UDPLITE(sk)); | ||
595 | } | 593 | } |
594 | drop: | ||
595 | atomic_inc(&sk->sk_drops); | ||
596 | UDP6_INC_STATS_BH(sock_net(sk), | ||
597 | UDP_MIB_RCVBUFERRORS, IS_UDPLITE(sk)); | ||
598 | UDP6_INC_STATS_BH(sock_net(sk), | ||
599 | UDP_MIB_INERRORS, IS_UDPLITE(sk)); | ||
596 | } | 600 | } |
597 | } | 601 | } |
598 | /* | 602 | /* |
@@ -754,8 +758,12 @@ int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, | |||
754 | bh_lock_sock(sk); | 758 | bh_lock_sock(sk); |
755 | if (!sock_owned_by_user(sk)) | 759 | if (!sock_owned_by_user(sk)) |
756 | udpv6_queue_rcv_skb(sk, skb); | 760 | udpv6_queue_rcv_skb(sk, skb); |
757 | else | 761 | else if (sk_add_backlog(sk, skb)) { |
758 | sk_add_backlog(sk, skb); | 762 | atomic_inc(&sk->sk_drops); |
763 | bh_unlock_sock(sk); | ||
764 | sock_put(sk); | ||
765 | goto discard; | ||
766 | } | ||
759 | bh_unlock_sock(sk); | 767 | bh_unlock_sock(sk); |
760 | sock_put(sk); | 768 | sock_put(sk); |
761 | return 0; | 769 | return 0; |
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c index dbdc696f5fc5..ae181651c75a 100644 --- a/net/ipv6/xfrm6_policy.c +++ b/net/ipv6/xfrm6_policy.c | |||
@@ -116,7 +116,8 @@ static int xfrm6_init_path(struct xfrm_dst *path, struct dst_entry *dst, | |||
116 | return 0; | 116 | return 0; |
117 | } | 117 | } |
118 | 118 | ||
119 | static int xfrm6_fill_dst(struct xfrm_dst *xdst, struct net_device *dev) | 119 | static int xfrm6_fill_dst(struct xfrm_dst *xdst, struct net_device *dev, |
120 | struct flowi *fl) | ||
120 | { | 121 | { |
121 | struct rt6_info *rt = (struct rt6_info*)xdst->route; | 122 | struct rt6_info *rt = (struct rt6_info*)xdst->route; |
122 | 123 | ||
diff --git a/net/irda/ircomm/ircomm_param.c b/net/irda/ircomm/ircomm_param.c index d57aefd9fe77..0804532d970f 100644 --- a/net/irda/ircomm/ircomm_param.c +++ b/net/irda/ircomm/ircomm_param.c | |||
@@ -474,7 +474,7 @@ static int ircomm_param_dce(void *instance, irda_param_t *param, int get) | |||
474 | /* Check if any of the settings have changed */ | 474 | /* Check if any of the settings have changed */ |
475 | if (dce & 0x0f) { | 475 | if (dce & 0x0f) { |
476 | if (dce & IRCOMM_DELTA_CTS) { | 476 | if (dce & IRCOMM_DELTA_CTS) { |
477 | IRDA_DEBUG(2, "%s(), CTS \n", __func__ ); | 477 | IRDA_DEBUG(2, "%s(), CTS\n", __func__ ); |
478 | } | 478 | } |
479 | } | 479 | } |
480 | 480 | ||
diff --git a/net/llc/llc_c_ac.c b/net/llc/llc_c_ac.c index 019c780512e8..86d6985b9d49 100644 --- a/net/llc/llc_c_ac.c +++ b/net/llc/llc_c_ac.c | |||
@@ -1437,7 +1437,7 @@ static void llc_process_tmr_ev(struct sock *sk, struct sk_buff *skb) | |||
1437 | llc_conn_state_process(sk, skb); | 1437 | llc_conn_state_process(sk, skb); |
1438 | else { | 1438 | else { |
1439 | llc_set_backlog_type(skb, LLC_EVENT); | 1439 | llc_set_backlog_type(skb, LLC_EVENT); |
1440 | sk_add_backlog(sk, skb); | 1440 | __sk_add_backlog(sk, skb); |
1441 | } | 1441 | } |
1442 | } | 1442 | } |
1443 | } | 1443 | } |
diff --git a/net/llc/llc_conn.c b/net/llc/llc_conn.c index a8dde9b010da..a12144da7974 100644 --- a/net/llc/llc_conn.c +++ b/net/llc/llc_conn.c | |||
@@ -827,7 +827,8 @@ void llc_conn_handler(struct llc_sap *sap, struct sk_buff *skb) | |||
827 | else { | 827 | else { |
828 | dprintk("%s: adding to backlog...\n", __func__); | 828 | dprintk("%s: adding to backlog...\n", __func__); |
829 | llc_set_backlog_type(skb, LLC_PACKET); | 829 | llc_set_backlog_type(skb, LLC_PACKET); |
830 | sk_add_backlog(sk, skb); | 830 | if (sk_add_backlog(sk, skb)) |
831 | goto drop_unlock; | ||
831 | } | 832 | } |
832 | out: | 833 | out: |
833 | bh_unlock_sock(sk); | 834 | bh_unlock_sock(sk); |
diff --git a/net/llc/llc_core.c b/net/llc/llc_core.c index 78167e81dfeb..2bb0ddff8c0f 100644 --- a/net/llc/llc_core.c +++ b/net/llc/llc_core.c | |||
@@ -144,12 +144,6 @@ static struct packet_type llc_tr_packet_type __read_mostly = { | |||
144 | 144 | ||
145 | static int __init llc_init(void) | 145 | static int __init llc_init(void) |
146 | { | 146 | { |
147 | struct net_device *dev; | ||
148 | |||
149 | dev = first_net_device(&init_net); | ||
150 | if (dev != NULL) | ||
151 | dev = next_net_device(dev); | ||
152 | |||
153 | dev_add_pack(&llc_packet_type); | 147 | dev_add_pack(&llc_packet_type); |
154 | dev_add_pack(&llc_tr_packet_type); | 148 | dev_add_pack(&llc_tr_packet_type); |
155 | return 0; | 149 | return 0; |
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index 9affe2cd185f..b4ddb2f83914 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c | |||
@@ -48,20 +48,24 @@ static ssize_t ieee80211_if_write( | |||
48 | ssize_t (*write)(struct ieee80211_sub_if_data *, const char *, int)) | 48 | ssize_t (*write)(struct ieee80211_sub_if_data *, const char *, int)) |
49 | { | 49 | { |
50 | u8 *buf; | 50 | u8 *buf; |
51 | ssize_t ret = -ENODEV; | 51 | ssize_t ret; |
52 | 52 | ||
53 | buf = kzalloc(count, GFP_KERNEL); | 53 | buf = kmalloc(count, GFP_KERNEL); |
54 | if (!buf) | 54 | if (!buf) |
55 | return -ENOMEM; | 55 | return -ENOMEM; |
56 | 56 | ||
57 | ret = -EFAULT; | ||
57 | if (copy_from_user(buf, userbuf, count)) | 58 | if (copy_from_user(buf, userbuf, count)) |
58 | return -EFAULT; | 59 | goto freebuf; |
59 | 60 | ||
61 | ret = -ENODEV; | ||
60 | rtnl_lock(); | 62 | rtnl_lock(); |
61 | if (sdata->dev->reg_state == NETREG_REGISTERED) | 63 | if (sdata->dev->reg_state == NETREG_REGISTERED) |
62 | ret = (*write)(sdata, buf, count); | 64 | ret = (*write)(sdata, buf, count); |
63 | rtnl_unlock(); | 65 | rtnl_unlock(); |
64 | 66 | ||
67 | freebuf: | ||
68 | kfree(buf); | ||
65 | return ret; | 69 | return ret; |
66 | } | 70 | } |
67 | 71 | ||
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index bc4e20e57ff5..1a29c4a8139e 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c | |||
@@ -744,7 +744,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
744 | break; | 744 | break; |
745 | default: | 745 | default: |
746 | /* should not get here, PLINK_BLOCKED is dealt with at the | 746 | /* should not get here, PLINK_BLOCKED is dealt with at the |
747 | * beggining of the function | 747 | * beginning of the function |
748 | */ | 748 | */ |
749 | spin_unlock_bh(&sta->lock); | 749 | spin_unlock_bh(&sta->lock); |
750 | break; | 750 | break; |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 65eafda5738a..34e0650e9ef8 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -436,10 +436,12 @@ static void ieee80211_enable_ps(struct ieee80211_local *local, | |||
436 | if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) | 436 | if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) |
437 | ieee80211_send_nullfunc(local, sdata, 1); | 437 | ieee80211_send_nullfunc(local, sdata, 1); |
438 | 438 | ||
439 | if (!(local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)) { | 439 | if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) && |
440 | conf->flags |= IEEE80211_CONF_PS; | 440 | (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)) |
441 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); | 441 | return; |
442 | } | 442 | |
443 | conf->flags |= IEEE80211_CONF_PS; | ||
444 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); | ||
443 | } | 445 | } |
444 | } | 446 | } |
445 | 447 | ||
@@ -558,7 +560,8 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work) | |||
558 | (!(ifmgd->flags & IEEE80211_STA_NULLFUNC_ACKED))) | 560 | (!(ifmgd->flags & IEEE80211_STA_NULLFUNC_ACKED))) |
559 | ieee80211_send_nullfunc(local, sdata, 1); | 561 | ieee80211_send_nullfunc(local, sdata, 1); |
560 | 562 | ||
561 | if (!(local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) || | 563 | if (!((local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) && |
564 | (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK)) || | ||
562 | (ifmgd->flags & IEEE80211_STA_NULLFUNC_ACKED)) { | 565 | (ifmgd->flags & IEEE80211_STA_NULLFUNC_ACKED)) { |
563 | ifmgd->flags &= ~IEEE80211_STA_NULLFUNC_ACKED; | 566 | ifmgd->flags &= ~IEEE80211_STA_NULLFUNC_ACKED; |
564 | local->hw.conf.flags |= IEEE80211_CONF_PS; | 567 | local->hw.conf.flags |= IEEE80211_CONF_PS; |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 211c475f73c6..56422d894351 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -434,6 +434,7 @@ int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU) | |||
434 | /* check if STA exists already */ | 434 | /* check if STA exists already */ |
435 | if (sta_info_get_bss(sdata, sta->sta.addr)) { | 435 | if (sta_info_get_bss(sdata, sta->sta.addr)) { |
436 | spin_unlock_irqrestore(&local->sta_lock, flags); | 436 | spin_unlock_irqrestore(&local->sta_lock, flags); |
437 | mutex_unlock(&local->sta_mtx); | ||
437 | rcu_read_lock(); | 438 | rcu_read_lock(); |
438 | err = -EEXIST; | 439 | err = -EEXIST; |
439 | goto out_free; | 440 | goto out_free; |
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 2b2af631d2b8..569410a85953 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c | |||
@@ -582,7 +582,9 @@ nla_put_failure: | |||
582 | nlmsg_failure: | 582 | nlmsg_failure: |
583 | kfree_skb(skb); | 583 | kfree_skb(skb); |
584 | errout: | 584 | errout: |
585 | nfnetlink_set_err(net, 0, group, -ENOBUFS); | 585 | if (nfnetlink_set_err(net, 0, group, -ENOBUFS) > 0) |
586 | return -ENOBUFS; | ||
587 | |||
586 | return 0; | 588 | return 0; |
587 | } | 589 | } |
588 | #endif /* CONFIG_NF_CONNTRACK_EVENTS */ | 590 | #endif /* CONFIG_NF_CONNTRACK_EVENTS */ |
diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c index 8dd75d90efc0..c6cd1b84eddd 100644 --- a/net/netfilter/nf_conntrack_sip.c +++ b/net/netfilter/nf_conntrack_sip.c | |||
@@ -284,7 +284,7 @@ EXPORT_SYMBOL_GPL(ct_sip_parse_request); | |||
284 | * tabs, spaces and continuation lines, which are treated as a single whitespace | 284 | * tabs, spaces and continuation lines, which are treated as a single whitespace |
285 | * character. | 285 | * character. |
286 | * | 286 | * |
287 | * Some headers may appear multiple times. A comma seperated list of values is | 287 | * Some headers may appear multiple times. A comma separated list of values is |
288 | * equivalent to multiple headers. | 288 | * equivalent to multiple headers. |
289 | */ | 289 | */ |
290 | static const struct sip_header ct_sip_hdrs[] = { | 290 | static const struct sip_header ct_sip_hdrs[] = { |
@@ -421,7 +421,7 @@ int ct_sip_get_header(const struct nf_conn *ct, const char *dptr, | |||
421 | } | 421 | } |
422 | EXPORT_SYMBOL_GPL(ct_sip_get_header); | 422 | EXPORT_SYMBOL_GPL(ct_sip_get_header); |
423 | 423 | ||
424 | /* Get next header field in a list of comma seperated values */ | 424 | /* Get next header field in a list of comma separated values */ |
425 | static int ct_sip_next_header(const struct nf_conn *ct, const char *dptr, | 425 | static int ct_sip_next_header(const struct nf_conn *ct, const char *dptr, |
426 | unsigned int dataoff, unsigned int datalen, | 426 | unsigned int dataoff, unsigned int datalen, |
427 | enum sip_header_types type, | 427 | enum sip_header_types type, |
diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c index 8eb0cc23ada3..6afa3d52ea5f 100644 --- a/net/netfilter/nfnetlink.c +++ b/net/netfilter/nfnetlink.c | |||
@@ -113,9 +113,9 @@ int nfnetlink_send(struct sk_buff *skb, struct net *net, u32 pid, | |||
113 | } | 113 | } |
114 | EXPORT_SYMBOL_GPL(nfnetlink_send); | 114 | EXPORT_SYMBOL_GPL(nfnetlink_send); |
115 | 115 | ||
116 | void nfnetlink_set_err(struct net *net, u32 pid, u32 group, int error) | 116 | int nfnetlink_set_err(struct net *net, u32 pid, u32 group, int error) |
117 | { | 117 | { |
118 | netlink_set_err(net->nfnl, pid, group, error); | 118 | return netlink_set_err(net->nfnl, pid, group, error); |
119 | } | 119 | } |
120 | EXPORT_SYMBOL_GPL(nfnetlink_set_err); | 120 | EXPORT_SYMBOL_GPL(nfnetlink_set_err); |
121 | 121 | ||
diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c index d952806b6469..9e9c48963942 100644 --- a/net/netfilter/xt_hashlimit.c +++ b/net/netfilter/xt_hashlimit.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * xt_hashlimit - Netfilter module to limit the number of packets per time | 2 | * xt_hashlimit - Netfilter module to limit the number of packets per time |
3 | * seperately for each hashbucket (sourceip/sourceport/dstip/dstport) | 3 | * separately for each hashbucket (sourceip/sourceport/dstip/dstport) |
4 | * | 4 | * |
5 | * (C) 2003-2004 by Harald Welte <laforge@netfilter.org> | 5 | * (C) 2003-2004 by Harald Welte <laforge@netfilter.org> |
6 | * Copyright © CC Computer Consultants GmbH, 2007 - 2008 | 6 | * Copyright © CC Computer Consultants GmbH, 2007 - 2008 |
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 320d0423a240..274d977166b7 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c | |||
@@ -545,7 +545,7 @@ static int netlink_autobind(struct socket *sock) | |||
545 | struct hlist_head *head; | 545 | struct hlist_head *head; |
546 | struct sock *osk; | 546 | struct sock *osk; |
547 | struct hlist_node *node; | 547 | struct hlist_node *node; |
548 | s32 pid = current->tgid; | 548 | s32 pid = task_tgid_vnr(current); |
549 | int err; | 549 | int err; |
550 | static s32 rover = -4097; | 550 | static s32 rover = -4097; |
551 | 551 | ||
@@ -1093,6 +1093,7 @@ static inline int do_one_set_err(struct sock *sk, | |||
1093 | struct netlink_set_err_data *p) | 1093 | struct netlink_set_err_data *p) |
1094 | { | 1094 | { |
1095 | struct netlink_sock *nlk = nlk_sk(sk); | 1095 | struct netlink_sock *nlk = nlk_sk(sk); |
1096 | int ret = 0; | ||
1096 | 1097 | ||
1097 | if (sk == p->exclude_sk) | 1098 | if (sk == p->exclude_sk) |
1098 | goto out; | 1099 | goto out; |
@@ -1104,10 +1105,15 @@ static inline int do_one_set_err(struct sock *sk, | |||
1104 | !test_bit(p->group - 1, nlk->groups)) | 1105 | !test_bit(p->group - 1, nlk->groups)) |
1105 | goto out; | 1106 | goto out; |
1106 | 1107 | ||
1108 | if (p->code == ENOBUFS && nlk->flags & NETLINK_RECV_NO_ENOBUFS) { | ||
1109 | ret = 1; | ||
1110 | goto out; | ||
1111 | } | ||
1112 | |||
1107 | sk->sk_err = p->code; | 1113 | sk->sk_err = p->code; |
1108 | sk->sk_error_report(sk); | 1114 | sk->sk_error_report(sk); |
1109 | out: | 1115 | out: |
1110 | return 0; | 1116 | return ret; |
1111 | } | 1117 | } |
1112 | 1118 | ||
1113 | /** | 1119 | /** |
@@ -1116,12 +1122,16 @@ out: | |||
1116 | * @pid: the PID of a process that we want to skip (if any) | 1122 | * @pid: the PID of a process that we want to skip (if any) |
1117 | * @groups: the broadcast group that will notice the error | 1123 | * @groups: the broadcast group that will notice the error |
1118 | * @code: error code, must be negative (as usual in kernelspace) | 1124 | * @code: error code, must be negative (as usual in kernelspace) |
1125 | * | ||
1126 | * This function returns the number of broadcast listeners that have set the | ||
1127 | * NETLINK_RECV_NO_ENOBUFS socket option. | ||
1119 | */ | 1128 | */ |
1120 | void netlink_set_err(struct sock *ssk, u32 pid, u32 group, int code) | 1129 | int netlink_set_err(struct sock *ssk, u32 pid, u32 group, int code) |
1121 | { | 1130 | { |
1122 | struct netlink_set_err_data info; | 1131 | struct netlink_set_err_data info; |
1123 | struct hlist_node *node; | 1132 | struct hlist_node *node; |
1124 | struct sock *sk; | 1133 | struct sock *sk; |
1134 | int ret = 0; | ||
1125 | 1135 | ||
1126 | info.exclude_sk = ssk; | 1136 | info.exclude_sk = ssk; |
1127 | info.pid = pid; | 1137 | info.pid = pid; |
@@ -1132,9 +1142,10 @@ void netlink_set_err(struct sock *ssk, u32 pid, u32 group, int code) | |||
1132 | read_lock(&nl_table_lock); | 1142 | read_lock(&nl_table_lock); |
1133 | 1143 | ||
1134 | sk_for_each_bound(sk, node, &nl_table[ssk->sk_protocol].mc_list) | 1144 | sk_for_each_bound(sk, node, &nl_table[ssk->sk_protocol].mc_list) |
1135 | do_one_set_err(sk, &info); | 1145 | ret += do_one_set_err(sk, &info); |
1136 | 1146 | ||
1137 | read_unlock(&nl_table_lock); | 1147 | read_unlock(&nl_table_lock); |
1148 | return ret; | ||
1138 | } | 1149 | } |
1139 | EXPORT_SYMBOL(netlink_set_err); | 1150 | EXPORT_SYMBOL(netlink_set_err); |
1140 | 1151 | ||
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 031a5e6fb4aa..1612d417d10c 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c | |||
@@ -1688,6 +1688,8 @@ static int packet_dev_mc(struct net_device *dev, struct packet_mclist *i, | |||
1688 | { | 1688 | { |
1689 | switch (i->type) { | 1689 | switch (i->type) { |
1690 | case PACKET_MR_MULTICAST: | 1690 | case PACKET_MR_MULTICAST: |
1691 | if (i->alen != dev->addr_len) | ||
1692 | return -EINVAL; | ||
1691 | if (what > 0) | 1693 | if (what > 0) |
1692 | return dev_mc_add(dev, i->addr, i->alen, 0); | 1694 | return dev_mc_add(dev, i->addr, i->alen, 0); |
1693 | else | 1695 | else |
@@ -1700,6 +1702,8 @@ static int packet_dev_mc(struct net_device *dev, struct packet_mclist *i, | |||
1700 | return dev_set_allmulti(dev, what); | 1702 | return dev_set_allmulti(dev, what); |
1701 | break; | 1703 | break; |
1702 | case PACKET_MR_UNICAST: | 1704 | case PACKET_MR_UNICAST: |
1705 | if (i->alen != dev->addr_len) | ||
1706 | return -EINVAL; | ||
1703 | if (what > 0) | 1707 | if (what > 0) |
1704 | return dev_unicast_add(dev, i->addr); | 1708 | return dev_unicast_add(dev, i->addr); |
1705 | else | 1709 | else |
@@ -1734,7 +1738,7 @@ static int packet_mc_add(struct sock *sk, struct packet_mreq_max *mreq) | |||
1734 | goto done; | 1738 | goto done; |
1735 | 1739 | ||
1736 | err = -EINVAL; | 1740 | err = -EINVAL; |
1737 | if (mreq->mr_alen != dev->addr_len) | 1741 | if (mreq->mr_alen > dev->addr_len) |
1738 | goto done; | 1742 | goto done; |
1739 | 1743 | ||
1740 | err = -ENOBUFS; | 1744 | err = -ENOBUFS; |
diff --git a/net/phonet/pn_dev.c b/net/phonet/pn_dev.c index c597cc53a6fb..5c6ae0c701c0 100644 --- a/net/phonet/pn_dev.c +++ b/net/phonet/pn_dev.c | |||
@@ -107,8 +107,7 @@ static void phonet_device_destroy(struct net_device *dev) | |||
107 | if (pnd) { | 107 | if (pnd) { |
108 | u8 addr; | 108 | u8 addr; |
109 | 109 | ||
110 | for (addr = find_first_bit(pnd->addrs, 64); addr < 64; | 110 | for_each_set_bit(addr, pnd->addrs, 64) |
111 | addr = find_next_bit(pnd->addrs, 64, 1+addr)) | ||
112 | phonet_address_notify(RTM_DELADDR, dev, addr); | 111 | phonet_address_notify(RTM_DELADDR, dev, addr); |
113 | kfree(pnd); | 112 | kfree(pnd); |
114 | } | 113 | } |
diff --git a/net/phonet/pn_netlink.c b/net/phonet/pn_netlink.c index 2e6c7eb8e76a..fe2e7088ee07 100644 --- a/net/phonet/pn_netlink.c +++ b/net/phonet/pn_netlink.c | |||
@@ -141,8 +141,7 @@ static int getaddr_dumpit(struct sk_buff *skb, struct netlink_callback *cb) | |||
141 | continue; | 141 | continue; |
142 | 142 | ||
143 | addr_idx = 0; | 143 | addr_idx = 0; |
144 | for (addr = find_first_bit(pnd->addrs, 64); addr < 64; | 144 | for_each_set_bit(addr, pnd->addrs, 64) { |
145 | addr = find_next_bit(pnd->addrs, 64, 1+addr)) { | ||
146 | if (addr_idx++ < addr_start_idx) | 145 | if (addr_idx++ < addr_start_idx) |
147 | continue; | 146 | continue; |
148 | 147 | ||
diff --git a/net/rds/af_rds.c b/net/rds/af_rds.c index 853c52be781f..c2e45e8efa20 100644 --- a/net/rds/af_rds.c +++ b/net/rds/af_rds.c | |||
@@ -159,7 +159,8 @@ static unsigned int rds_poll(struct file *file, struct socket *sock, | |||
159 | 159 | ||
160 | poll_wait(file, sk->sk_sleep, wait); | 160 | poll_wait(file, sk->sk_sleep, wait); |
161 | 161 | ||
162 | poll_wait(file, &rds_poll_waitq, wait); | 162 | if (rs->rs_seen_congestion) |
163 | poll_wait(file, &rds_poll_waitq, wait); | ||
163 | 164 | ||
164 | read_lock_irqsave(&rs->rs_recv_lock, flags); | 165 | read_lock_irqsave(&rs->rs_recv_lock, flags); |
165 | if (!rs->rs_cong_monitor) { | 166 | if (!rs->rs_cong_monitor) { |
@@ -181,6 +182,10 @@ static unsigned int rds_poll(struct file *file, struct socket *sock, | |||
181 | mask |= (POLLOUT | POLLWRNORM); | 182 | mask |= (POLLOUT | POLLWRNORM); |
182 | read_unlock_irqrestore(&rs->rs_recv_lock, flags); | 183 | read_unlock_irqrestore(&rs->rs_recv_lock, flags); |
183 | 184 | ||
185 | /* clear state any time we wake a seen-congested socket */ | ||
186 | if (mask) | ||
187 | rs->rs_seen_congestion = 0; | ||
188 | |||
184 | return mask; | 189 | return mask; |
185 | } | 190 | } |
186 | 191 | ||
@@ -446,7 +451,6 @@ static void rds_sock_inc_info(struct socket *sock, unsigned int len, | |||
446 | struct rds_info_lengths *lens) | 451 | struct rds_info_lengths *lens) |
447 | { | 452 | { |
448 | struct rds_sock *rs; | 453 | struct rds_sock *rs; |
449 | struct sock *sk; | ||
450 | struct rds_incoming *inc; | 454 | struct rds_incoming *inc; |
451 | unsigned long flags; | 455 | unsigned long flags; |
452 | unsigned int total = 0; | 456 | unsigned int total = 0; |
@@ -456,7 +460,6 @@ static void rds_sock_inc_info(struct socket *sock, unsigned int len, | |||
456 | spin_lock_irqsave(&rds_sock_lock, flags); | 460 | spin_lock_irqsave(&rds_sock_lock, flags); |
457 | 461 | ||
458 | list_for_each_entry(rs, &rds_sock_list, rs_item) { | 462 | list_for_each_entry(rs, &rds_sock_list, rs_item) { |
459 | sk = rds_rs_to_sk(rs); | ||
460 | read_lock(&rs->rs_recv_lock); | 463 | read_lock(&rs->rs_recv_lock); |
461 | 464 | ||
462 | /* XXX too lazy to maintain counts.. */ | 465 | /* XXX too lazy to maintain counts.. */ |
diff --git a/net/rds/cong.c b/net/rds/cong.c index 6d06cac2649c..dd2711df640b 100644 --- a/net/rds/cong.c +++ b/net/rds/cong.c | |||
@@ -218,8 +218,6 @@ void rds_cong_queue_updates(struct rds_cong_map *map) | |||
218 | spin_lock_irqsave(&rds_cong_lock, flags); | 218 | spin_lock_irqsave(&rds_cong_lock, flags); |
219 | 219 | ||
220 | list_for_each_entry(conn, &map->m_conn_list, c_map_item) { | 220 | list_for_each_entry(conn, &map->m_conn_list, c_map_item) { |
221 | if (conn->c_loopback) | ||
222 | continue; | ||
223 | if (!test_and_set_bit(0, &conn->c_map_queued)) { | 221 | if (!test_and_set_bit(0, &conn->c_map_queued)) { |
224 | rds_stats_inc(s_cong_update_queued); | 222 | rds_stats_inc(s_cong_update_queued); |
225 | queue_delayed_work(rds_wq, &conn->c_send_w, 0); | 223 | queue_delayed_work(rds_wq, &conn->c_send_w, 0); |
diff --git a/net/rds/ib_cm.c b/net/rds/ib_cm.c index 647cb8ffc39b..e1f124bf03bb 100644 --- a/net/rds/ib_cm.c +++ b/net/rds/ib_cm.c | |||
@@ -203,9 +203,10 @@ static void rds_ib_qp_event_handler(struct ib_event *event, void *data) | |||
203 | rdma_notify(ic->i_cm_id, IB_EVENT_COMM_EST); | 203 | rdma_notify(ic->i_cm_id, IB_EVENT_COMM_EST); |
204 | break; | 204 | break; |
205 | default: | 205 | default: |
206 | rds_ib_conn_error(conn, "RDS/IB: Fatal QP Event %u " | 206 | rdsdebug("Fatal QP Event %u " |
207 | "- connection %pI4->%pI4, reconnecting\n", | 207 | "- connection %pI4->%pI4, reconnecting\n", |
208 | event->event, &conn->c_laddr, &conn->c_faddr); | 208 | event->event, &conn->c_laddr, &conn->c_faddr); |
209 | rds_conn_drop(conn); | ||
209 | break; | 210 | break; |
210 | } | 211 | } |
211 | } | 212 | } |
diff --git a/net/rds/ib_rdma.c b/net/rds/ib_rdma.c index 4b0da865a72c..cfb1d904ed00 100644 --- a/net/rds/ib_rdma.c +++ b/net/rds/ib_rdma.c | |||
@@ -234,8 +234,8 @@ void rds_ib_destroy_mr_pool(struct rds_ib_mr_pool *pool) | |||
234 | { | 234 | { |
235 | flush_workqueue(rds_wq); | 235 | flush_workqueue(rds_wq); |
236 | rds_ib_flush_mr_pool(pool, 1); | 236 | rds_ib_flush_mr_pool(pool, 1); |
237 | BUG_ON(atomic_read(&pool->item_count)); | 237 | WARN_ON(atomic_read(&pool->item_count)); |
238 | BUG_ON(atomic_read(&pool->free_pinned)); | 238 | WARN_ON(atomic_read(&pool->free_pinned)); |
239 | kfree(pool); | 239 | kfree(pool); |
240 | } | 240 | } |
241 | 241 | ||
@@ -440,6 +440,7 @@ static void __rds_ib_teardown_mr(struct rds_ib_mr *ibmr) | |||
440 | 440 | ||
441 | /* FIXME we need a way to tell a r/w MR | 441 | /* FIXME we need a way to tell a r/w MR |
442 | * from a r/o MR */ | 442 | * from a r/o MR */ |
443 | BUG_ON(in_interrupt()); | ||
443 | set_page_dirty(page); | 444 | set_page_dirty(page); |
444 | put_page(page); | 445 | put_page(page); |
445 | } | 446 | } |
diff --git a/net/rds/ib_recv.c b/net/rds/ib_recv.c index 04dc0d3f3c95..c338881eca71 100644 --- a/net/rds/ib_recv.c +++ b/net/rds/ib_recv.c | |||
@@ -468,8 +468,8 @@ static void rds_ib_send_ack(struct rds_ib_connection *ic, unsigned int adv_credi | |||
468 | set_bit(IB_ACK_REQUESTED, &ic->i_ack_flags); | 468 | set_bit(IB_ACK_REQUESTED, &ic->i_ack_flags); |
469 | 469 | ||
470 | rds_ib_stats_inc(s_ib_ack_send_failure); | 470 | rds_ib_stats_inc(s_ib_ack_send_failure); |
471 | /* Need to finesse this later. */ | 471 | |
472 | BUG(); | 472 | rds_ib_conn_error(ic->conn, "sending ack failed\n"); |
473 | } else | 473 | } else |
474 | rds_ib_stats_inc(s_ib_ack_sent); | 474 | rds_ib_stats_inc(s_ib_ack_sent); |
475 | } | 475 | } |
diff --git a/net/rds/ib_send.c b/net/rds/ib_send.c index a10fab6886d1..17fa80803ab0 100644 --- a/net/rds/ib_send.c +++ b/net/rds/ib_send.c | |||
@@ -243,8 +243,12 @@ void rds_ib_send_cq_comp_handler(struct ib_cq *cq, void *context) | |||
243 | struct rds_message *rm; | 243 | struct rds_message *rm; |
244 | 244 | ||
245 | rm = rds_send_get_message(conn, send->s_op); | 245 | rm = rds_send_get_message(conn, send->s_op); |
246 | if (rm) | 246 | if (rm) { |
247 | if (rm->m_rdma_op) | ||
248 | rds_ib_send_unmap_rdma(ic, rm->m_rdma_op); | ||
247 | rds_ib_send_rdma_complete(rm, wc.status); | 249 | rds_ib_send_rdma_complete(rm, wc.status); |
250 | rds_message_put(rm); | ||
251 | } | ||
248 | } | 252 | } |
249 | 253 | ||
250 | oldest = (oldest + 1) % ic->i_send_ring.w_nr; | 254 | oldest = (oldest + 1) % ic->i_send_ring.w_nr; |
@@ -482,6 +486,13 @@ int rds_ib_xmit(struct rds_connection *conn, struct rds_message *rm, | |||
482 | BUG_ON(off % RDS_FRAG_SIZE); | 486 | BUG_ON(off % RDS_FRAG_SIZE); |
483 | BUG_ON(hdr_off != 0 && hdr_off != sizeof(struct rds_header)); | 487 | BUG_ON(hdr_off != 0 && hdr_off != sizeof(struct rds_header)); |
484 | 488 | ||
489 | /* Do not send cong updates to IB loopback */ | ||
490 | if (conn->c_loopback | ||
491 | && rm->m_inc.i_hdr.h_flags & RDS_FLAG_CONG_BITMAP) { | ||
492 | rds_cong_map_updated(conn->c_fcong, ~(u64) 0); | ||
493 | return sizeof(struct rds_header) + RDS_CONG_MAP_BYTES; | ||
494 | } | ||
495 | |||
485 | /* FIXME we may overallocate here */ | 496 | /* FIXME we may overallocate here */ |
486 | if (be32_to_cpu(rm->m_inc.i_hdr.h_len) == 0) | 497 | if (be32_to_cpu(rm->m_inc.i_hdr.h_len) == 0) |
487 | i = 1; | 498 | i = 1; |
@@ -574,8 +585,7 @@ int rds_ib_xmit(struct rds_connection *conn, struct rds_message *rm, | |||
574 | rds_ib_send_grab_credits(ic, 0, &posted, 1, RDS_MAX_ADV_CREDIT - adv_credits); | 585 | rds_ib_send_grab_credits(ic, 0, &posted, 1, RDS_MAX_ADV_CREDIT - adv_credits); |
575 | adv_credits += posted; | 586 | adv_credits += posted; |
576 | BUG_ON(adv_credits > 255); | 587 | BUG_ON(adv_credits > 255); |
577 | } else if (ic->i_rm != rm) | 588 | } |
578 | BUG(); | ||
579 | 589 | ||
580 | send = &ic->i_sends[pos]; | 590 | send = &ic->i_sends[pos]; |
581 | first = send; | 591 | first = send; |
@@ -714,8 +724,8 @@ add_header: | |||
714 | ic->i_rm = prev->s_rm; | 724 | ic->i_rm = prev->s_rm; |
715 | prev->s_rm = NULL; | 725 | prev->s_rm = NULL; |
716 | } | 726 | } |
717 | /* Finesse this later */ | 727 | |
718 | BUG(); | 728 | rds_ib_conn_error(ic->conn, "ib_post_send failed\n"); |
719 | goto out; | 729 | goto out; |
720 | } | 730 | } |
721 | 731 | ||
diff --git a/net/rds/iw_cm.c b/net/rds/iw_cm.c index 394cf6b4d0aa..6bc638fd252c 100644 --- a/net/rds/iw_cm.c +++ b/net/rds/iw_cm.c | |||
@@ -156,9 +156,11 @@ static void rds_iw_qp_event_handler(struct ib_event *event, void *data) | |||
156 | case IB_EVENT_QP_REQ_ERR: | 156 | case IB_EVENT_QP_REQ_ERR: |
157 | case IB_EVENT_QP_FATAL: | 157 | case IB_EVENT_QP_FATAL: |
158 | default: | 158 | default: |
159 | rds_iw_conn_error(conn, "RDS/IW: Fatal QP Event %u - connection %pI4->%pI4...reconnecting\n", | 159 | rdsdebug("Fatal QP Event %u " |
160 | "- connection %pI4->%pI4, reconnecting\n", | ||
160 | event->event, &conn->c_laddr, | 161 | event->event, &conn->c_laddr, |
161 | &conn->c_faddr); | 162 | &conn->c_faddr); |
163 | rds_conn_drop(conn); | ||
162 | break; | 164 | break; |
163 | } | 165 | } |
164 | } | 166 | } |
diff --git a/net/rds/iw_recv.c b/net/rds/iw_recv.c index 54af7d6b92da..337e4e5025e2 100644 --- a/net/rds/iw_recv.c +++ b/net/rds/iw_recv.c | |||
@@ -468,8 +468,8 @@ static void rds_iw_send_ack(struct rds_iw_connection *ic, unsigned int adv_credi | |||
468 | set_bit(IB_ACK_REQUESTED, &ic->i_ack_flags); | 468 | set_bit(IB_ACK_REQUESTED, &ic->i_ack_flags); |
469 | 469 | ||
470 | rds_iw_stats_inc(s_iw_ack_send_failure); | 470 | rds_iw_stats_inc(s_iw_ack_send_failure); |
471 | /* Need to finesse this later. */ | 471 | |
472 | BUG(); | 472 | rds_iw_conn_error(ic->conn, "sending ack failed\n"); |
473 | } else | 473 | } else |
474 | rds_iw_stats_inc(s_iw_ack_sent); | 474 | rds_iw_stats_inc(s_iw_ack_sent); |
475 | } | 475 | } |
diff --git a/net/rds/iw_send.c b/net/rds/iw_send.c index 1379e9d66a78..52182ff7519e 100644 --- a/net/rds/iw_send.c +++ b/net/rds/iw_send.c | |||
@@ -616,8 +616,7 @@ int rds_iw_xmit(struct rds_connection *conn, struct rds_message *rm, | |||
616 | rds_iw_send_grab_credits(ic, 0, &posted, 1, RDS_MAX_ADV_CREDIT - adv_credits); | 616 | rds_iw_send_grab_credits(ic, 0, &posted, 1, RDS_MAX_ADV_CREDIT - adv_credits); |
617 | adv_credits += posted; | 617 | adv_credits += posted; |
618 | BUG_ON(adv_credits > 255); | 618 | BUG_ON(adv_credits > 255); |
619 | } else if (ic->i_rm != rm) | 619 | } |
620 | BUG(); | ||
621 | 620 | ||
622 | send = &ic->i_sends[pos]; | 621 | send = &ic->i_sends[pos]; |
623 | first = send; | 622 | first = send; |
diff --git a/net/rds/loop.c b/net/rds/loop.c index 4a61997f554d..93a45f1ce61f 100644 --- a/net/rds/loop.c +++ b/net/rds/loop.c | |||
@@ -80,16 +80,9 @@ static int rds_loop_xmit_cong_map(struct rds_connection *conn, | |||
80 | struct rds_cong_map *map, | 80 | struct rds_cong_map *map, |
81 | unsigned long offset) | 81 | unsigned long offset) |
82 | { | 82 | { |
83 | unsigned long i; | ||
84 | |||
85 | BUG_ON(offset); | 83 | BUG_ON(offset); |
86 | BUG_ON(map != conn->c_lcong); | 84 | BUG_ON(map != conn->c_lcong); |
87 | 85 | ||
88 | for (i = 0; i < RDS_CONG_MAP_PAGES; i++) { | ||
89 | memcpy((void *)conn->c_fcong->m_page_addrs[i], | ||
90 | (void *)map->m_page_addrs[i], PAGE_SIZE); | ||
91 | } | ||
92 | |||
93 | rds_cong_map_updated(conn->c_fcong, ~(u64) 0); | 86 | rds_cong_map_updated(conn->c_fcong, ~(u64) 0); |
94 | 87 | ||
95 | return sizeof(struct rds_header) + RDS_CONG_MAP_BYTES; | 88 | return sizeof(struct rds_header) + RDS_CONG_MAP_BYTES; |
diff --git a/net/rds/rdma.c b/net/rds/rdma.c index 4c64daa1f5d5..61b359d9dffd 100644 --- a/net/rds/rdma.c +++ b/net/rds/rdma.c | |||
@@ -438,8 +438,10 @@ void rds_rdma_free_op(struct rds_rdma_op *ro) | |||
438 | /* Mark page dirty if it was possibly modified, which | 438 | /* Mark page dirty if it was possibly modified, which |
439 | * is the case for a RDMA_READ which copies from remote | 439 | * is the case for a RDMA_READ which copies from remote |
440 | * to local memory */ | 440 | * to local memory */ |
441 | if (!ro->r_write) | 441 | if (!ro->r_write) { |
442 | BUG_ON(in_interrupt()); | ||
442 | set_page_dirty(page); | 443 | set_page_dirty(page); |
444 | } | ||
443 | put_page(page); | 445 | put_page(page); |
444 | } | 446 | } |
445 | 447 | ||
diff --git a/net/rds/rdma_transport.c b/net/rds/rdma_transport.c index 9ece910ea394..5ea82fc47c3e 100644 --- a/net/rds/rdma_transport.c +++ b/net/rds/rdma_transport.c | |||
@@ -101,7 +101,7 @@ int rds_rdma_cm_event_handler(struct rdma_cm_id *cm_id, | |||
101 | break; | 101 | break; |
102 | 102 | ||
103 | case RDMA_CM_EVENT_DISCONNECTED: | 103 | case RDMA_CM_EVENT_DISCONNECTED: |
104 | printk(KERN_WARNING "RDS/RDMA: DISCONNECT event - dropping connection " | 104 | rdsdebug("DISCONNECT event - dropping connection " |
105 | "%pI4->%pI4\n", &conn->c_laddr, | 105 | "%pI4->%pI4\n", &conn->c_laddr, |
106 | &conn->c_faddr); | 106 | &conn->c_faddr); |
107 | rds_conn_drop(conn); | 107 | rds_conn_drop(conn); |
@@ -109,8 +109,7 @@ int rds_rdma_cm_event_handler(struct rdma_cm_id *cm_id, | |||
109 | 109 | ||
110 | default: | 110 | default: |
111 | /* things like device disconnect? */ | 111 | /* things like device disconnect? */ |
112 | printk(KERN_ERR "unknown event %u\n", event->event); | 112 | printk(KERN_ERR "RDS: unknown event %u!\n", event->event); |
113 | BUG(); | ||
114 | break; | 113 | break; |
115 | } | 114 | } |
116 | 115 | ||
diff --git a/net/rds/rds.h b/net/rds/rds.h index 85d6f897ecc7..4bec6e2ed495 100644 --- a/net/rds/rds.h +++ b/net/rds/rds.h | |||
@@ -388,6 +388,8 @@ struct rds_sock { | |||
388 | 388 | ||
389 | /* flag indicating we were congested or not */ | 389 | /* flag indicating we were congested or not */ |
390 | int rs_congested; | 390 | int rs_congested; |
391 | /* seen congestion (ENOBUFS) when sending? */ | ||
392 | int rs_seen_congestion; | ||
391 | 393 | ||
392 | /* rs_lock protects all these adjacent members before the newline */ | 394 | /* rs_lock protects all these adjacent members before the newline */ |
393 | spinlock_t rs_lock; | 395 | spinlock_t rs_lock; |
diff --git a/net/rds/send.c b/net/rds/send.c index b2fccfc20769..4629a0b63bbd 100644 --- a/net/rds/send.c +++ b/net/rds/send.c | |||
@@ -507,12 +507,13 @@ EXPORT_SYMBOL_GPL(rds_send_get_message); | |||
507 | */ | 507 | */ |
508 | void rds_send_remove_from_sock(struct list_head *messages, int status) | 508 | void rds_send_remove_from_sock(struct list_head *messages, int status) |
509 | { | 509 | { |
510 | unsigned long flags = 0; /* silence gcc :P */ | 510 | unsigned long flags; |
511 | struct rds_sock *rs = NULL; | 511 | struct rds_sock *rs = NULL; |
512 | struct rds_message *rm; | 512 | struct rds_message *rm; |
513 | 513 | ||
514 | local_irq_save(flags); | ||
515 | while (!list_empty(messages)) { | 514 | while (!list_empty(messages)) { |
515 | int was_on_sock = 0; | ||
516 | |||
516 | rm = list_entry(messages->next, struct rds_message, | 517 | rm = list_entry(messages->next, struct rds_message, |
517 | m_conn_item); | 518 | m_conn_item); |
518 | list_del_init(&rm->m_conn_item); | 519 | list_del_init(&rm->m_conn_item); |
@@ -527,20 +528,19 @@ void rds_send_remove_from_sock(struct list_head *messages, int status) | |||
527 | * while we're messing with it. It does not prevent the | 528 | * while we're messing with it. It does not prevent the |
528 | * message from being removed from the socket, though. | 529 | * message from being removed from the socket, though. |
529 | */ | 530 | */ |
530 | spin_lock(&rm->m_rs_lock); | 531 | spin_lock_irqsave(&rm->m_rs_lock, flags); |
531 | if (!test_bit(RDS_MSG_ON_SOCK, &rm->m_flags)) | 532 | if (!test_bit(RDS_MSG_ON_SOCK, &rm->m_flags)) |
532 | goto unlock_and_drop; | 533 | goto unlock_and_drop; |
533 | 534 | ||
534 | if (rs != rm->m_rs) { | 535 | if (rs != rm->m_rs) { |
535 | if (rs) { | 536 | if (rs) { |
536 | spin_unlock(&rs->rs_lock); | ||
537 | rds_wake_sk_sleep(rs); | 537 | rds_wake_sk_sleep(rs); |
538 | sock_put(rds_rs_to_sk(rs)); | 538 | sock_put(rds_rs_to_sk(rs)); |
539 | } | 539 | } |
540 | rs = rm->m_rs; | 540 | rs = rm->m_rs; |
541 | spin_lock(&rs->rs_lock); | ||
542 | sock_hold(rds_rs_to_sk(rs)); | 541 | sock_hold(rds_rs_to_sk(rs)); |
543 | } | 542 | } |
543 | spin_lock(&rs->rs_lock); | ||
544 | 544 | ||
545 | if (test_and_clear_bit(RDS_MSG_ON_SOCK, &rm->m_flags)) { | 545 | if (test_and_clear_bit(RDS_MSG_ON_SOCK, &rm->m_flags)) { |
546 | struct rds_rdma_op *ro = rm->m_rdma_op; | 546 | struct rds_rdma_op *ro = rm->m_rdma_op; |
@@ -557,21 +557,22 @@ void rds_send_remove_from_sock(struct list_head *messages, int status) | |||
557 | notifier->n_status = status; | 557 | notifier->n_status = status; |
558 | rm->m_rdma_op->r_notifier = NULL; | 558 | rm->m_rdma_op->r_notifier = NULL; |
559 | } | 559 | } |
560 | rds_message_put(rm); | 560 | was_on_sock = 1; |
561 | rm->m_rs = NULL; | 561 | rm->m_rs = NULL; |
562 | } | 562 | } |
563 | spin_unlock(&rs->rs_lock); | ||
563 | 564 | ||
564 | unlock_and_drop: | 565 | unlock_and_drop: |
565 | spin_unlock(&rm->m_rs_lock); | 566 | spin_unlock_irqrestore(&rm->m_rs_lock, flags); |
566 | rds_message_put(rm); | 567 | rds_message_put(rm); |
568 | if (was_on_sock) | ||
569 | rds_message_put(rm); | ||
567 | } | 570 | } |
568 | 571 | ||
569 | if (rs) { | 572 | if (rs) { |
570 | spin_unlock(&rs->rs_lock); | ||
571 | rds_wake_sk_sleep(rs); | 573 | rds_wake_sk_sleep(rs); |
572 | sock_put(rds_rs_to_sk(rs)); | 574 | sock_put(rds_rs_to_sk(rs)); |
573 | } | 575 | } |
574 | local_irq_restore(flags); | ||
575 | } | 576 | } |
576 | 577 | ||
577 | /* | 578 | /* |
@@ -633,9 +634,6 @@ void rds_send_drop_to(struct rds_sock *rs, struct sockaddr_in *dest) | |||
633 | list_move(&rm->m_sock_item, &list); | 634 | list_move(&rm->m_sock_item, &list); |
634 | rds_send_sndbuf_remove(rs, rm); | 635 | rds_send_sndbuf_remove(rs, rm); |
635 | clear_bit(RDS_MSG_ON_SOCK, &rm->m_flags); | 636 | clear_bit(RDS_MSG_ON_SOCK, &rm->m_flags); |
636 | |||
637 | /* If this is a RDMA operation, notify the app. */ | ||
638 | __rds_rdma_send_complete(rs, rm, RDS_RDMA_CANCELED); | ||
639 | } | 637 | } |
640 | 638 | ||
641 | /* order flag updates with the rs lock */ | 639 | /* order flag updates with the rs lock */ |
@@ -644,9 +642,6 @@ void rds_send_drop_to(struct rds_sock *rs, struct sockaddr_in *dest) | |||
644 | 642 | ||
645 | spin_unlock_irqrestore(&rs->rs_lock, flags); | 643 | spin_unlock_irqrestore(&rs->rs_lock, flags); |
646 | 644 | ||
647 | if (wake) | ||
648 | rds_wake_sk_sleep(rs); | ||
649 | |||
650 | conn = NULL; | 645 | conn = NULL; |
651 | 646 | ||
652 | /* now remove the messages from the conn list as needed */ | 647 | /* now remove the messages from the conn list as needed */ |
@@ -654,6 +649,10 @@ void rds_send_drop_to(struct rds_sock *rs, struct sockaddr_in *dest) | |||
654 | /* We do this here rather than in the loop above, so that | 649 | /* We do this here rather than in the loop above, so that |
655 | * we don't have to nest m_rs_lock under rs->rs_lock */ | 650 | * we don't have to nest m_rs_lock under rs->rs_lock */ |
656 | spin_lock_irqsave(&rm->m_rs_lock, flags2); | 651 | spin_lock_irqsave(&rm->m_rs_lock, flags2); |
652 | /* If this is a RDMA operation, notify the app. */ | ||
653 | spin_lock(&rs->rs_lock); | ||
654 | __rds_rdma_send_complete(rs, rm, RDS_RDMA_CANCELED); | ||
655 | spin_unlock(&rs->rs_lock); | ||
657 | rm->m_rs = NULL; | 656 | rm->m_rs = NULL; |
658 | spin_unlock_irqrestore(&rm->m_rs_lock, flags2); | 657 | spin_unlock_irqrestore(&rm->m_rs_lock, flags2); |
659 | 658 | ||
@@ -682,6 +681,9 @@ void rds_send_drop_to(struct rds_sock *rs, struct sockaddr_in *dest) | |||
682 | if (conn) | 681 | if (conn) |
683 | spin_unlock_irqrestore(&conn->c_lock, flags); | 682 | spin_unlock_irqrestore(&conn->c_lock, flags); |
684 | 683 | ||
684 | if (wake) | ||
685 | rds_wake_sk_sleep(rs); | ||
686 | |||
685 | while (!list_empty(&list)) { | 687 | while (!list_empty(&list)) { |
686 | rm = list_entry(list.next, struct rds_message, m_sock_item); | 688 | rm = list_entry(list.next, struct rds_message, m_sock_item); |
687 | list_del_init(&rm->m_sock_item); | 689 | list_del_init(&rm->m_sock_item); |
@@ -815,7 +817,7 @@ int rds_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, | |||
815 | int ret = 0; | 817 | int ret = 0; |
816 | int queued = 0, allocated_mr = 0; | 818 | int queued = 0, allocated_mr = 0; |
817 | int nonblock = msg->msg_flags & MSG_DONTWAIT; | 819 | int nonblock = msg->msg_flags & MSG_DONTWAIT; |
818 | long timeo = sock_rcvtimeo(sk, nonblock); | 820 | long timeo = sock_sndtimeo(sk, nonblock); |
819 | 821 | ||
820 | /* Mirror Linux UDP mirror of BSD error message compatibility */ | 822 | /* Mirror Linux UDP mirror of BSD error message compatibility */ |
821 | /* XXX: Perhaps MSG_MORE someday */ | 823 | /* XXX: Perhaps MSG_MORE someday */ |
@@ -894,8 +896,10 @@ int rds_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, | |||
894 | queue_delayed_work(rds_wq, &conn->c_conn_w, 0); | 896 | queue_delayed_work(rds_wq, &conn->c_conn_w, 0); |
895 | 897 | ||
896 | ret = rds_cong_wait(conn->c_fcong, dport, nonblock, rs); | 898 | ret = rds_cong_wait(conn->c_fcong, dport, nonblock, rs); |
897 | if (ret) | 899 | if (ret) { |
900 | rs->rs_seen_congestion = 1; | ||
898 | goto out; | 901 | goto out; |
902 | } | ||
899 | 903 | ||
900 | while (!rds_send_queue_rm(rs, conn, rm, rs->rs_bound_port, | 904 | while (!rds_send_queue_rm(rs, conn, rm, rs->rs_bound_port, |
901 | dport, &queued)) { | 905 | dport, &queued)) { |
diff --git a/net/rds/tcp_recv.c b/net/rds/tcp_recv.c index c00dafffbb5a..40bfcf887465 100644 --- a/net/rds/tcp_recv.c +++ b/net/rds/tcp_recv.c | |||
@@ -97,6 +97,7 @@ int rds_tcp_inc_copy_to_user(struct rds_incoming *inc, struct iovec *first_iov, | |||
97 | goto out; | 97 | goto out; |
98 | } | 98 | } |
99 | 99 | ||
100 | rds_stats_add(s_copy_to_user, to_copy); | ||
100 | size -= to_copy; | 101 | size -= to_copy; |
101 | ret += to_copy; | 102 | ret += to_copy; |
102 | skb_off += to_copy; | 103 | skb_off += to_copy; |
diff --git a/net/rds/tcp_send.c b/net/rds/tcp_send.c index 34fdcc059e54..a28b895ff0d1 100644 --- a/net/rds/tcp_send.c +++ b/net/rds/tcp_send.c | |||
@@ -240,7 +240,9 @@ void rds_tcp_write_space(struct sock *sk) | |||
240 | tc->t_last_seen_una = rds_tcp_snd_una(tc); | 240 | tc->t_last_seen_una = rds_tcp_snd_una(tc); |
241 | rds_send_drop_acked(conn, rds_tcp_snd_una(tc), rds_tcp_is_acked); | 241 | rds_send_drop_acked(conn, rds_tcp_snd_una(tc), rds_tcp_is_acked); |
242 | 242 | ||
243 | queue_delayed_work(rds_wq, &conn->c_send_w, 0); | 243 | if ((atomic_read(&sk->sk_wmem_alloc) << 1) <= sk->sk_sndbuf) |
244 | queue_delayed_work(rds_wq, &conn->c_send_w, 0); | ||
245 | |||
244 | out: | 246 | out: |
245 | read_unlock(&sk->sk_callback_lock); | 247 | read_unlock(&sk->sk_callback_lock); |
246 | 248 | ||
diff --git a/net/rds/threads.c b/net/rds/threads.c index 00fa10e59af8..786c20eaaf5e 100644 --- a/net/rds/threads.c +++ b/net/rds/threads.c | |||
@@ -259,7 +259,7 @@ void rds_threads_exit(void) | |||
259 | 259 | ||
260 | int __init rds_threads_init(void) | 260 | int __init rds_threads_init(void) |
261 | { | 261 | { |
262 | rds_wq = create_singlethread_workqueue("krdsd"); | 262 | rds_wq = create_workqueue("krdsd"); |
263 | if (rds_wq == NULL) | 263 | if (rds_wq == NULL) |
264 | return -ENOMEM; | 264 | return -ENOMEM; |
265 | 265 | ||
diff --git a/net/sched/act_api.c b/net/sched/act_api.c index 64f5e328cee9..7a558da99bb6 100644 --- a/net/sched/act_api.c +++ b/net/sched/act_api.c | |||
@@ -667,7 +667,8 @@ nlmsg_failure: | |||
667 | } | 667 | } |
668 | 668 | ||
669 | static int | 669 | static int |
670 | act_get_notify(u32 pid, struct nlmsghdr *n, struct tc_action *a, int event) | 670 | act_get_notify(struct net *net, u32 pid, struct nlmsghdr *n, |
671 | struct tc_action *a, int event) | ||
671 | { | 672 | { |
672 | struct sk_buff *skb; | 673 | struct sk_buff *skb; |
673 | 674 | ||
@@ -679,7 +680,7 @@ act_get_notify(u32 pid, struct nlmsghdr *n, struct tc_action *a, int event) | |||
679 | return -EINVAL; | 680 | return -EINVAL; |
680 | } | 681 | } |
681 | 682 | ||
682 | return rtnl_unicast(skb, &init_net, pid); | 683 | return rtnl_unicast(skb, net, pid); |
683 | } | 684 | } |
684 | 685 | ||
685 | static struct tc_action * | 686 | static struct tc_action * |
@@ -749,7 +750,8 @@ static struct tc_action *create_a(int i) | |||
749 | return act; | 750 | return act; |
750 | } | 751 | } |
751 | 752 | ||
752 | static int tca_action_flush(struct nlattr *nla, struct nlmsghdr *n, u32 pid) | 753 | static int tca_action_flush(struct net *net, struct nlattr *nla, |
754 | struct nlmsghdr *n, u32 pid) | ||
753 | { | 755 | { |
754 | struct sk_buff *skb; | 756 | struct sk_buff *skb; |
755 | unsigned char *b; | 757 | unsigned char *b; |
@@ -808,7 +810,7 @@ static int tca_action_flush(struct nlattr *nla, struct nlmsghdr *n, u32 pid) | |||
808 | nlh->nlmsg_flags |= NLM_F_ROOT; | 810 | nlh->nlmsg_flags |= NLM_F_ROOT; |
809 | module_put(a->ops->owner); | 811 | module_put(a->ops->owner); |
810 | kfree(a); | 812 | kfree(a); |
811 | err = rtnetlink_send(skb, &init_net, pid, RTNLGRP_TC, n->nlmsg_flags&NLM_F_ECHO); | 813 | err = rtnetlink_send(skb, net, pid, RTNLGRP_TC, n->nlmsg_flags&NLM_F_ECHO); |
812 | if (err > 0) | 814 | if (err > 0) |
813 | return 0; | 815 | return 0; |
814 | 816 | ||
@@ -825,7 +827,8 @@ noflush_out: | |||
825 | } | 827 | } |
826 | 828 | ||
827 | static int | 829 | static int |
828 | tca_action_gd(struct nlattr *nla, struct nlmsghdr *n, u32 pid, int event) | 830 | tca_action_gd(struct net *net, struct nlattr *nla, struct nlmsghdr *n, |
831 | u32 pid, int event) | ||
829 | { | 832 | { |
830 | int i, ret; | 833 | int i, ret; |
831 | struct nlattr *tb[TCA_ACT_MAX_PRIO+1]; | 834 | struct nlattr *tb[TCA_ACT_MAX_PRIO+1]; |
@@ -837,7 +840,7 @@ tca_action_gd(struct nlattr *nla, struct nlmsghdr *n, u32 pid, int event) | |||
837 | 840 | ||
838 | if (event == RTM_DELACTION && n->nlmsg_flags&NLM_F_ROOT) { | 841 | if (event == RTM_DELACTION && n->nlmsg_flags&NLM_F_ROOT) { |
839 | if (tb[1] != NULL) | 842 | if (tb[1] != NULL) |
840 | return tca_action_flush(tb[1], n, pid); | 843 | return tca_action_flush(net, tb[1], n, pid); |
841 | else | 844 | else |
842 | return -EINVAL; | 845 | return -EINVAL; |
843 | } | 846 | } |
@@ -858,7 +861,7 @@ tca_action_gd(struct nlattr *nla, struct nlmsghdr *n, u32 pid, int event) | |||
858 | } | 861 | } |
859 | 862 | ||
860 | if (event == RTM_GETACTION) | 863 | if (event == RTM_GETACTION) |
861 | ret = act_get_notify(pid, n, head, event); | 864 | ret = act_get_notify(net, pid, n, head, event); |
862 | else { /* delete */ | 865 | else { /* delete */ |
863 | struct sk_buff *skb; | 866 | struct sk_buff *skb; |
864 | 867 | ||
@@ -877,7 +880,7 @@ tca_action_gd(struct nlattr *nla, struct nlmsghdr *n, u32 pid, int event) | |||
877 | 880 | ||
878 | /* now do the delete */ | 881 | /* now do the delete */ |
879 | tcf_action_destroy(head, 0); | 882 | tcf_action_destroy(head, 0); |
880 | ret = rtnetlink_send(skb, &init_net, pid, RTNLGRP_TC, | 883 | ret = rtnetlink_send(skb, net, pid, RTNLGRP_TC, |
881 | n->nlmsg_flags&NLM_F_ECHO); | 884 | n->nlmsg_flags&NLM_F_ECHO); |
882 | if (ret > 0) | 885 | if (ret > 0) |
883 | return 0; | 886 | return 0; |
@@ -888,8 +891,8 @@ err: | |||
888 | return ret; | 891 | return ret; |
889 | } | 892 | } |
890 | 893 | ||
891 | static int tcf_add_notify(struct tc_action *a, u32 pid, u32 seq, int event, | 894 | static int tcf_add_notify(struct net *net, struct tc_action *a, |
892 | u16 flags) | 895 | u32 pid, u32 seq, int event, u16 flags) |
893 | { | 896 | { |
894 | struct tcamsg *t; | 897 | struct tcamsg *t; |
895 | struct nlmsghdr *nlh; | 898 | struct nlmsghdr *nlh; |
@@ -922,7 +925,7 @@ static int tcf_add_notify(struct tc_action *a, u32 pid, u32 seq, int event, | |||
922 | nlh->nlmsg_len = skb_tail_pointer(skb) - b; | 925 | nlh->nlmsg_len = skb_tail_pointer(skb) - b; |
923 | NETLINK_CB(skb).dst_group = RTNLGRP_TC; | 926 | NETLINK_CB(skb).dst_group = RTNLGRP_TC; |
924 | 927 | ||
925 | err = rtnetlink_send(skb, &init_net, pid, RTNLGRP_TC, flags&NLM_F_ECHO); | 928 | err = rtnetlink_send(skb, net, pid, RTNLGRP_TC, flags&NLM_F_ECHO); |
926 | if (err > 0) | 929 | if (err > 0) |
927 | err = 0; | 930 | err = 0; |
928 | return err; | 931 | return err; |
@@ -935,7 +938,8 @@ nlmsg_failure: | |||
935 | 938 | ||
936 | 939 | ||
937 | static int | 940 | static int |
938 | tcf_action_add(struct nlattr *nla, struct nlmsghdr *n, u32 pid, int ovr) | 941 | tcf_action_add(struct net *net, struct nlattr *nla, struct nlmsghdr *n, |
942 | u32 pid, int ovr) | ||
939 | { | 943 | { |
940 | int ret = 0; | 944 | int ret = 0; |
941 | struct tc_action *act; | 945 | struct tc_action *act; |
@@ -953,7 +957,7 @@ tcf_action_add(struct nlattr *nla, struct nlmsghdr *n, u32 pid, int ovr) | |||
953 | /* dump then free all the actions after update; inserted policy | 957 | /* dump then free all the actions after update; inserted policy |
954 | * stays intact | 958 | * stays intact |
955 | * */ | 959 | * */ |
956 | ret = tcf_add_notify(act, pid, seq, RTM_NEWACTION, n->nlmsg_flags); | 960 | ret = tcf_add_notify(net, act, pid, seq, RTM_NEWACTION, n->nlmsg_flags); |
957 | for (a = act; a; a = act) { | 961 | for (a = act; a; a = act) { |
958 | act = a->next; | 962 | act = a->next; |
959 | kfree(a); | 963 | kfree(a); |
@@ -969,9 +973,6 @@ static int tc_ctl_action(struct sk_buff *skb, struct nlmsghdr *n, void *arg) | |||
969 | u32 pid = skb ? NETLINK_CB(skb).pid : 0; | 973 | u32 pid = skb ? NETLINK_CB(skb).pid : 0; |
970 | int ret = 0, ovr = 0; | 974 | int ret = 0, ovr = 0; |
971 | 975 | ||
972 | if (!net_eq(net, &init_net)) | ||
973 | return -EINVAL; | ||
974 | |||
975 | ret = nlmsg_parse(n, sizeof(struct tcamsg), tca, TCA_ACT_MAX, NULL); | 976 | ret = nlmsg_parse(n, sizeof(struct tcamsg), tca, TCA_ACT_MAX, NULL); |
976 | if (ret < 0) | 977 | if (ret < 0) |
977 | return ret; | 978 | return ret; |
@@ -994,15 +995,17 @@ static int tc_ctl_action(struct sk_buff *skb, struct nlmsghdr *n, void *arg) | |||
994 | if (n->nlmsg_flags&NLM_F_REPLACE) | 995 | if (n->nlmsg_flags&NLM_F_REPLACE) |
995 | ovr = 1; | 996 | ovr = 1; |
996 | replay: | 997 | replay: |
997 | ret = tcf_action_add(tca[TCA_ACT_TAB], n, pid, ovr); | 998 | ret = tcf_action_add(net, tca[TCA_ACT_TAB], n, pid, ovr); |
998 | if (ret == -EAGAIN) | 999 | if (ret == -EAGAIN) |
999 | goto replay; | 1000 | goto replay; |
1000 | break; | 1001 | break; |
1001 | case RTM_DELACTION: | 1002 | case RTM_DELACTION: |
1002 | ret = tca_action_gd(tca[TCA_ACT_TAB], n, pid, RTM_DELACTION); | 1003 | ret = tca_action_gd(net, tca[TCA_ACT_TAB], n, |
1004 | pid, RTM_DELACTION); | ||
1003 | break; | 1005 | break; |
1004 | case RTM_GETACTION: | 1006 | case RTM_GETACTION: |
1005 | ret = tca_action_gd(tca[TCA_ACT_TAB], n, pid, RTM_GETACTION); | 1007 | ret = tca_action_gd(net, tca[TCA_ACT_TAB], n, |
1008 | pid, RTM_GETACTION); | ||
1006 | break; | 1009 | break; |
1007 | default: | 1010 | default: |
1008 | BUG(); | 1011 | BUG(); |
@@ -1042,7 +1045,6 @@ find_dump_kind(const struct nlmsghdr *n) | |||
1042 | static int | 1045 | static int |
1043 | tc_dump_action(struct sk_buff *skb, struct netlink_callback *cb) | 1046 | tc_dump_action(struct sk_buff *skb, struct netlink_callback *cb) |
1044 | { | 1047 | { |
1045 | struct net *net = sock_net(skb->sk); | ||
1046 | struct nlmsghdr *nlh; | 1048 | struct nlmsghdr *nlh; |
1047 | unsigned char *b = skb_tail_pointer(skb); | 1049 | unsigned char *b = skb_tail_pointer(skb); |
1048 | struct nlattr *nest; | 1050 | struct nlattr *nest; |
@@ -1052,9 +1054,6 @@ tc_dump_action(struct sk_buff *skb, struct netlink_callback *cb) | |||
1052 | struct tcamsg *t = (struct tcamsg *) NLMSG_DATA(cb->nlh); | 1054 | struct tcamsg *t = (struct tcamsg *) NLMSG_DATA(cb->nlh); |
1053 | struct nlattr *kind = find_dump_kind(cb->nlh); | 1055 | struct nlattr *kind = find_dump_kind(cb->nlh); |
1054 | 1056 | ||
1055 | if (!net_eq(net, &init_net)) | ||
1056 | return 0; | ||
1057 | |||
1058 | if (kind == NULL) { | 1057 | if (kind == NULL) { |
1059 | printk("tc_dump_action: action bad kind\n"); | 1058 | printk("tc_dump_action: action bad kind\n"); |
1060 | return 0; | 1059 | return 0; |
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index 3725d8fa29db..4a795d966172 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c | |||
@@ -98,8 +98,9 @@ out: | |||
98 | } | 98 | } |
99 | EXPORT_SYMBOL(unregister_tcf_proto_ops); | 99 | EXPORT_SYMBOL(unregister_tcf_proto_ops); |
100 | 100 | ||
101 | static int tfilter_notify(struct sk_buff *oskb, struct nlmsghdr *n, | 101 | static int tfilter_notify(struct net *net, struct sk_buff *oskb, |
102 | struct tcf_proto *tp, unsigned long fh, int event); | 102 | struct nlmsghdr *n, struct tcf_proto *tp, |
103 | unsigned long fh, int event); | ||
103 | 104 | ||
104 | 105 | ||
105 | /* Select new prio value from the range, managed by kernel. */ | 106 | /* Select new prio value from the range, managed by kernel. */ |
@@ -137,9 +138,6 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n, void *arg) | |||
137 | int err; | 138 | int err; |
138 | int tp_created = 0; | 139 | int tp_created = 0; |
139 | 140 | ||
140 | if (!net_eq(net, &init_net)) | ||
141 | return -EINVAL; | ||
142 | |||
143 | replay: | 141 | replay: |
144 | t = NLMSG_DATA(n); | 142 | t = NLMSG_DATA(n); |
145 | protocol = TC_H_MIN(t->tcm_info); | 143 | protocol = TC_H_MIN(t->tcm_info); |
@@ -158,7 +156,7 @@ replay: | |||
158 | /* Find head of filter chain. */ | 156 | /* Find head of filter chain. */ |
159 | 157 | ||
160 | /* Find link */ | 158 | /* Find link */ |
161 | dev = __dev_get_by_index(&init_net, t->tcm_ifindex); | 159 | dev = __dev_get_by_index(net, t->tcm_ifindex); |
162 | if (dev == NULL) | 160 | if (dev == NULL) |
163 | return -ENODEV; | 161 | return -ENODEV; |
164 | 162 | ||
@@ -282,7 +280,7 @@ replay: | |||
282 | *back = tp->next; | 280 | *back = tp->next; |
283 | spin_unlock_bh(root_lock); | 281 | spin_unlock_bh(root_lock); |
284 | 282 | ||
285 | tfilter_notify(skb, n, tp, fh, RTM_DELTFILTER); | 283 | tfilter_notify(net, skb, n, tp, fh, RTM_DELTFILTER); |
286 | tcf_destroy(tp); | 284 | tcf_destroy(tp); |
287 | err = 0; | 285 | err = 0; |
288 | goto errout; | 286 | goto errout; |
@@ -305,10 +303,10 @@ replay: | |||
305 | case RTM_DELTFILTER: | 303 | case RTM_DELTFILTER: |
306 | err = tp->ops->delete(tp, fh); | 304 | err = tp->ops->delete(tp, fh); |
307 | if (err == 0) | 305 | if (err == 0) |
308 | tfilter_notify(skb, n, tp, fh, RTM_DELTFILTER); | 306 | tfilter_notify(net, skb, n, tp, fh, RTM_DELTFILTER); |
309 | goto errout; | 307 | goto errout; |
310 | case RTM_GETTFILTER: | 308 | case RTM_GETTFILTER: |
311 | err = tfilter_notify(skb, n, tp, fh, RTM_NEWTFILTER); | 309 | err = tfilter_notify(net, skb, n, tp, fh, RTM_NEWTFILTER); |
312 | goto errout; | 310 | goto errout; |
313 | default: | 311 | default: |
314 | err = -EINVAL; | 312 | err = -EINVAL; |
@@ -324,7 +322,7 @@ replay: | |||
324 | *back = tp; | 322 | *back = tp; |
325 | spin_unlock_bh(root_lock); | 323 | spin_unlock_bh(root_lock); |
326 | } | 324 | } |
327 | tfilter_notify(skb, n, tp, fh, RTM_NEWTFILTER); | 325 | tfilter_notify(net, skb, n, tp, fh, RTM_NEWTFILTER); |
328 | } else { | 326 | } else { |
329 | if (tp_created) | 327 | if (tp_created) |
330 | tcf_destroy(tp); | 328 | tcf_destroy(tp); |
@@ -370,8 +368,9 @@ nla_put_failure: | |||
370 | return -1; | 368 | return -1; |
371 | } | 369 | } |
372 | 370 | ||
373 | static int tfilter_notify(struct sk_buff *oskb, struct nlmsghdr *n, | 371 | static int tfilter_notify(struct net *net, struct sk_buff *oskb, |
374 | struct tcf_proto *tp, unsigned long fh, int event) | 372 | struct nlmsghdr *n, struct tcf_proto *tp, |
373 | unsigned long fh, int event) | ||
375 | { | 374 | { |
376 | struct sk_buff *skb; | 375 | struct sk_buff *skb; |
377 | u32 pid = oskb ? NETLINK_CB(oskb).pid : 0; | 376 | u32 pid = oskb ? NETLINK_CB(oskb).pid : 0; |
@@ -385,7 +384,7 @@ static int tfilter_notify(struct sk_buff *oskb, struct nlmsghdr *n, | |||
385 | return -EINVAL; | 384 | return -EINVAL; |
386 | } | 385 | } |
387 | 386 | ||
388 | return rtnetlink_send(skb, &init_net, pid, RTNLGRP_TC, | 387 | return rtnetlink_send(skb, net, pid, RTNLGRP_TC, |
389 | n->nlmsg_flags & NLM_F_ECHO); | 388 | n->nlmsg_flags & NLM_F_ECHO); |
390 | } | 389 | } |
391 | 390 | ||
@@ -418,12 +417,9 @@ static int tc_dump_tfilter(struct sk_buff *skb, struct netlink_callback *cb) | |||
418 | const struct Qdisc_class_ops *cops; | 417 | const struct Qdisc_class_ops *cops; |
419 | struct tcf_dump_args arg; | 418 | struct tcf_dump_args arg; |
420 | 419 | ||
421 | if (!net_eq(net, &init_net)) | ||
422 | return 0; | ||
423 | |||
424 | if (cb->nlh->nlmsg_len < NLMSG_LENGTH(sizeof(*tcm))) | 420 | if (cb->nlh->nlmsg_len < NLMSG_LENGTH(sizeof(*tcm))) |
425 | return skb->len; | 421 | return skb->len; |
426 | if ((dev = __dev_get_by_index(&init_net, tcm->tcm_ifindex)) == NULL) | 422 | if ((dev = __dev_get_by_index(net, tcm->tcm_ifindex)) == NULL) |
427 | return skb->len; | 423 | return skb->len; |
428 | 424 | ||
429 | if (!tcm->tcm_parent) | 425 | if (!tcm->tcm_parent) |
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c index 07372f60bee3..1ef76871a57b 100644 --- a/net/sched/cls_u32.c +++ b/net/sched/cls_u32.c | |||
@@ -772,10 +772,10 @@ static int __init init_u32(void) | |||
772 | printk(" Performance counters on\n"); | 772 | printk(" Performance counters on\n"); |
773 | #endif | 773 | #endif |
774 | #ifdef CONFIG_NET_CLS_IND | 774 | #ifdef CONFIG_NET_CLS_IND |
775 | printk(" input device check on \n"); | 775 | printk(" input device check on\n"); |
776 | #endif | 776 | #endif |
777 | #ifdef CONFIG_NET_CLS_ACT | 777 | #ifdef CONFIG_NET_CLS_ACT |
778 | printk(" Actions configured \n"); | 778 | printk(" Actions configured\n"); |
779 | #endif | 779 | #endif |
780 | return register_tcf_proto_ops(&cls_u32_ops); | 780 | return register_tcf_proto_ops(&cls_u32_ops); |
781 | } | 781 | } |
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index 6cd491013b50..6d6fe16289f3 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c | |||
@@ -34,10 +34,12 @@ | |||
34 | #include <net/netlink.h> | 34 | #include <net/netlink.h> |
35 | #include <net/pkt_sched.h> | 35 | #include <net/pkt_sched.h> |
36 | 36 | ||
37 | static int qdisc_notify(struct sk_buff *oskb, struct nlmsghdr *n, u32 clid, | 37 | static int qdisc_notify(struct net *net, struct sk_buff *oskb, |
38 | struct nlmsghdr *n, u32 clid, | ||
38 | struct Qdisc *old, struct Qdisc *new); | 39 | struct Qdisc *old, struct Qdisc *new); |
39 | static int tclass_notify(struct sk_buff *oskb, struct nlmsghdr *n, | 40 | static int tclass_notify(struct net *net, struct sk_buff *oskb, |
40 | struct Qdisc *q, unsigned long cl, int event); | 41 | struct nlmsghdr *n, struct Qdisc *q, |
42 | unsigned long cl, int event); | ||
41 | 43 | ||
42 | /* | 44 | /* |
43 | 45 | ||
@@ -638,11 +640,12 @@ void qdisc_tree_decrease_qlen(struct Qdisc *sch, unsigned int n) | |||
638 | } | 640 | } |
639 | EXPORT_SYMBOL(qdisc_tree_decrease_qlen); | 641 | EXPORT_SYMBOL(qdisc_tree_decrease_qlen); |
640 | 642 | ||
641 | static void notify_and_destroy(struct sk_buff *skb, struct nlmsghdr *n, u32 clid, | 643 | static void notify_and_destroy(struct net *net, struct sk_buff *skb, |
644 | struct nlmsghdr *n, u32 clid, | ||
642 | struct Qdisc *old, struct Qdisc *new) | 645 | struct Qdisc *old, struct Qdisc *new) |
643 | { | 646 | { |
644 | if (new || old) | 647 | if (new || old) |
645 | qdisc_notify(skb, n, clid, old, new); | 648 | qdisc_notify(net, skb, n, clid, old, new); |
646 | 649 | ||
647 | if (old) | 650 | if (old) |
648 | qdisc_destroy(old); | 651 | qdisc_destroy(old); |
@@ -662,6 +665,7 @@ static int qdisc_graft(struct net_device *dev, struct Qdisc *parent, | |||
662 | struct Qdisc *new, struct Qdisc *old) | 665 | struct Qdisc *new, struct Qdisc *old) |
663 | { | 666 | { |
664 | struct Qdisc *q = old; | 667 | struct Qdisc *q = old; |
668 | struct net *net = dev_net(dev); | ||
665 | int err = 0; | 669 | int err = 0; |
666 | 670 | ||
667 | if (parent == NULL) { | 671 | if (parent == NULL) { |
@@ -698,12 +702,13 @@ static int qdisc_graft(struct net_device *dev, struct Qdisc *parent, | |||
698 | } | 702 | } |
699 | 703 | ||
700 | if (!ingress) { | 704 | if (!ingress) { |
701 | notify_and_destroy(skb, n, classid, dev->qdisc, new); | 705 | notify_and_destroy(net, skb, n, classid, |
706 | dev->qdisc, new); | ||
702 | if (new && !new->ops->attach) | 707 | if (new && !new->ops->attach) |
703 | atomic_inc(&new->refcnt); | 708 | atomic_inc(&new->refcnt); |
704 | dev->qdisc = new ? : &noop_qdisc; | 709 | dev->qdisc = new ? : &noop_qdisc; |
705 | } else { | 710 | } else { |
706 | notify_and_destroy(skb, n, classid, old, new); | 711 | notify_and_destroy(net, skb, n, classid, old, new); |
707 | } | 712 | } |
708 | 713 | ||
709 | if (dev->flags & IFF_UP) | 714 | if (dev->flags & IFF_UP) |
@@ -721,7 +726,7 @@ static int qdisc_graft(struct net_device *dev, struct Qdisc *parent, | |||
721 | err = -ENOENT; | 726 | err = -ENOENT; |
722 | } | 727 | } |
723 | if (!err) | 728 | if (!err) |
724 | notify_and_destroy(skb, n, classid, old, new); | 729 | notify_and_destroy(net, skb, n, classid, old, new); |
725 | } | 730 | } |
726 | return err; | 731 | return err; |
727 | } | 732 | } |
@@ -947,10 +952,7 @@ static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg) | |||
947 | struct Qdisc *p = NULL; | 952 | struct Qdisc *p = NULL; |
948 | int err; | 953 | int err; |
949 | 954 | ||
950 | if (!net_eq(net, &init_net)) | 955 | if ((dev = __dev_get_by_index(net, tcm->tcm_ifindex)) == NULL) |
951 | return -EINVAL; | ||
952 | |||
953 | if ((dev = __dev_get_by_index(&init_net, tcm->tcm_ifindex)) == NULL) | ||
954 | return -ENODEV; | 956 | return -ENODEV; |
955 | 957 | ||
956 | err = nlmsg_parse(n, sizeof(*tcm), tca, TCA_MAX, NULL); | 958 | err = nlmsg_parse(n, sizeof(*tcm), tca, TCA_MAX, NULL); |
@@ -990,7 +992,7 @@ static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg) | |||
990 | if ((err = qdisc_graft(dev, p, skb, n, clid, NULL, q)) != 0) | 992 | if ((err = qdisc_graft(dev, p, skb, n, clid, NULL, q)) != 0) |
991 | return err; | 993 | return err; |
992 | } else { | 994 | } else { |
993 | qdisc_notify(skb, n, clid, NULL, q); | 995 | qdisc_notify(net, skb, n, clid, NULL, q); |
994 | } | 996 | } |
995 | return 0; | 997 | return 0; |
996 | } | 998 | } |
@@ -1009,16 +1011,13 @@ static int tc_modify_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg) | |||
1009 | struct Qdisc *q, *p; | 1011 | struct Qdisc *q, *p; |
1010 | int err; | 1012 | int err; |
1011 | 1013 | ||
1012 | if (!net_eq(net, &init_net)) | ||
1013 | return -EINVAL; | ||
1014 | |||
1015 | replay: | 1014 | replay: |
1016 | /* Reinit, just in case something touches this. */ | 1015 | /* Reinit, just in case something touches this. */ |
1017 | tcm = NLMSG_DATA(n); | 1016 | tcm = NLMSG_DATA(n); |
1018 | clid = tcm->tcm_parent; | 1017 | clid = tcm->tcm_parent; |
1019 | q = p = NULL; | 1018 | q = p = NULL; |
1020 | 1019 | ||
1021 | if ((dev = __dev_get_by_index(&init_net, tcm->tcm_ifindex)) == NULL) | 1020 | if ((dev = __dev_get_by_index(net, tcm->tcm_ifindex)) == NULL) |
1022 | return -ENODEV; | 1021 | return -ENODEV; |
1023 | 1022 | ||
1024 | err = nlmsg_parse(n, sizeof(*tcm), tca, TCA_MAX, NULL); | 1023 | err = nlmsg_parse(n, sizeof(*tcm), tca, TCA_MAX, NULL); |
@@ -1105,7 +1104,7 @@ replay: | |||
1105 | return -EINVAL; | 1104 | return -EINVAL; |
1106 | err = qdisc_change(q, tca); | 1105 | err = qdisc_change(q, tca); |
1107 | if (err == 0) | 1106 | if (err == 0) |
1108 | qdisc_notify(skb, n, clid, NULL, q); | 1107 | qdisc_notify(net, skb, n, clid, NULL, q); |
1109 | return err; | 1108 | return err; |
1110 | 1109 | ||
1111 | create_n_graft: | 1110 | create_n_graft: |
@@ -1195,8 +1194,9 @@ nla_put_failure: | |||
1195 | return -1; | 1194 | return -1; |
1196 | } | 1195 | } |
1197 | 1196 | ||
1198 | static int qdisc_notify(struct sk_buff *oskb, struct nlmsghdr *n, | 1197 | static int qdisc_notify(struct net *net, struct sk_buff *oskb, |
1199 | u32 clid, struct Qdisc *old, struct Qdisc *new) | 1198 | struct nlmsghdr *n, u32 clid, |
1199 | struct Qdisc *old, struct Qdisc *new) | ||
1200 | { | 1200 | { |
1201 | struct sk_buff *skb; | 1201 | struct sk_buff *skb; |
1202 | u32 pid = oskb ? NETLINK_CB(oskb).pid : 0; | 1202 | u32 pid = oskb ? NETLINK_CB(oskb).pid : 0; |
@@ -1215,7 +1215,7 @@ static int qdisc_notify(struct sk_buff *oskb, struct nlmsghdr *n, | |||
1215 | } | 1215 | } |
1216 | 1216 | ||
1217 | if (skb->len) | 1217 | if (skb->len) |
1218 | return rtnetlink_send(skb, &init_net, pid, RTNLGRP_TC, n->nlmsg_flags&NLM_F_ECHO); | 1218 | return rtnetlink_send(skb, net, pid, RTNLGRP_TC, n->nlmsg_flags&NLM_F_ECHO); |
1219 | 1219 | ||
1220 | err_out: | 1220 | err_out: |
1221 | kfree_skb(skb); | 1221 | kfree_skb(skb); |
@@ -1274,15 +1274,12 @@ static int tc_dump_qdisc(struct sk_buff *skb, struct netlink_callback *cb) | |||
1274 | int s_idx, s_q_idx; | 1274 | int s_idx, s_q_idx; |
1275 | struct net_device *dev; | 1275 | struct net_device *dev; |
1276 | 1276 | ||
1277 | if (!net_eq(net, &init_net)) | ||
1278 | return 0; | ||
1279 | |||
1280 | s_idx = cb->args[0]; | 1277 | s_idx = cb->args[0]; |
1281 | s_q_idx = q_idx = cb->args[1]; | 1278 | s_q_idx = q_idx = cb->args[1]; |
1282 | 1279 | ||
1283 | rcu_read_lock(); | 1280 | rcu_read_lock(); |
1284 | idx = 0; | 1281 | idx = 0; |
1285 | for_each_netdev_rcu(&init_net, dev) { | 1282 | for_each_netdev_rcu(net, dev) { |
1286 | struct netdev_queue *dev_queue; | 1283 | struct netdev_queue *dev_queue; |
1287 | 1284 | ||
1288 | if (idx < s_idx) | 1285 | if (idx < s_idx) |
@@ -1334,10 +1331,7 @@ static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, void *arg) | |||
1334 | u32 qid = TC_H_MAJ(clid); | 1331 | u32 qid = TC_H_MAJ(clid); |
1335 | int err; | 1332 | int err; |
1336 | 1333 | ||
1337 | if (!net_eq(net, &init_net)) | 1334 | if ((dev = __dev_get_by_index(net, tcm->tcm_ifindex)) == NULL) |
1338 | return -EINVAL; | ||
1339 | |||
1340 | if ((dev = __dev_get_by_index(&init_net, tcm->tcm_ifindex)) == NULL) | ||
1341 | return -ENODEV; | 1335 | return -ENODEV; |
1342 | 1336 | ||
1343 | err = nlmsg_parse(n, sizeof(*tcm), tca, TCA_MAX, NULL); | 1337 | err = nlmsg_parse(n, sizeof(*tcm), tca, TCA_MAX, NULL); |
@@ -1418,10 +1412,10 @@ static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, void *arg) | |||
1418 | if (cops->delete) | 1412 | if (cops->delete) |
1419 | err = cops->delete(q, cl); | 1413 | err = cops->delete(q, cl); |
1420 | if (err == 0) | 1414 | if (err == 0) |
1421 | tclass_notify(skb, n, q, cl, RTM_DELTCLASS); | 1415 | tclass_notify(net, skb, n, q, cl, RTM_DELTCLASS); |
1422 | goto out; | 1416 | goto out; |
1423 | case RTM_GETTCLASS: | 1417 | case RTM_GETTCLASS: |
1424 | err = tclass_notify(skb, n, q, cl, RTM_NEWTCLASS); | 1418 | err = tclass_notify(net, skb, n, q, cl, RTM_NEWTCLASS); |
1425 | goto out; | 1419 | goto out; |
1426 | default: | 1420 | default: |
1427 | err = -EINVAL; | 1421 | err = -EINVAL; |
@@ -1434,7 +1428,7 @@ static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, void *arg) | |||
1434 | if (cops->change) | 1428 | if (cops->change) |
1435 | err = cops->change(q, clid, pid, tca, &new_cl); | 1429 | err = cops->change(q, clid, pid, tca, &new_cl); |
1436 | if (err == 0) | 1430 | if (err == 0) |
1437 | tclass_notify(skb, n, q, new_cl, RTM_NEWTCLASS); | 1431 | tclass_notify(net, skb, n, q, new_cl, RTM_NEWTCLASS); |
1438 | 1432 | ||
1439 | out: | 1433 | out: |
1440 | if (cl) | 1434 | if (cl) |
@@ -1486,8 +1480,9 @@ nla_put_failure: | |||
1486 | return -1; | 1480 | return -1; |
1487 | } | 1481 | } |
1488 | 1482 | ||
1489 | static int tclass_notify(struct sk_buff *oskb, struct nlmsghdr *n, | 1483 | static int tclass_notify(struct net *net, struct sk_buff *oskb, |
1490 | struct Qdisc *q, unsigned long cl, int event) | 1484 | struct nlmsghdr *n, struct Qdisc *q, |
1485 | unsigned long cl, int event) | ||
1491 | { | 1486 | { |
1492 | struct sk_buff *skb; | 1487 | struct sk_buff *skb; |
1493 | u32 pid = oskb ? NETLINK_CB(oskb).pid : 0; | 1488 | u32 pid = oskb ? NETLINK_CB(oskb).pid : 0; |
@@ -1501,7 +1496,7 @@ static int tclass_notify(struct sk_buff *oskb, struct nlmsghdr *n, | |||
1501 | return -EINVAL; | 1496 | return -EINVAL; |
1502 | } | 1497 | } |
1503 | 1498 | ||
1504 | return rtnetlink_send(skb, &init_net, pid, RTNLGRP_TC, n->nlmsg_flags&NLM_F_ECHO); | 1499 | return rtnetlink_send(skb, net, pid, RTNLGRP_TC, n->nlmsg_flags&NLM_F_ECHO); |
1505 | } | 1500 | } |
1506 | 1501 | ||
1507 | struct qdisc_dump_args | 1502 | struct qdisc_dump_args |
@@ -1576,12 +1571,9 @@ static int tc_dump_tclass(struct sk_buff *skb, struct netlink_callback *cb) | |||
1576 | struct net_device *dev; | 1571 | struct net_device *dev; |
1577 | int t, s_t; | 1572 | int t, s_t; |
1578 | 1573 | ||
1579 | if (!net_eq(net, &init_net)) | ||
1580 | return 0; | ||
1581 | |||
1582 | if (cb->nlh->nlmsg_len < NLMSG_LENGTH(sizeof(*tcm))) | 1574 | if (cb->nlh->nlmsg_len < NLMSG_LENGTH(sizeof(*tcm))) |
1583 | return 0; | 1575 | return 0; |
1584 | if ((dev = dev_get_by_index(&init_net, tcm->tcm_ifindex)) == NULL) | 1576 | if ((dev = dev_get_by_index(net, tcm->tcm_ifindex)) == NULL) |
1585 | return 0; | 1577 | return 0; |
1586 | 1578 | ||
1587 | s_t = cb->args[0]; | 1579 | s_t = cb->args[0]; |
@@ -1701,15 +1693,55 @@ static const struct file_operations psched_fops = { | |||
1701 | .llseek = seq_lseek, | 1693 | .llseek = seq_lseek, |
1702 | .release = single_release, | 1694 | .release = single_release, |
1703 | }; | 1695 | }; |
1696 | |||
1697 | static int __net_init psched_net_init(struct net *net) | ||
1698 | { | ||
1699 | struct proc_dir_entry *e; | ||
1700 | |||
1701 | e = proc_net_fops_create(net, "psched", 0, &psched_fops); | ||
1702 | if (e == NULL) | ||
1703 | return -ENOMEM; | ||
1704 | |||
1705 | return 0; | ||
1706 | } | ||
1707 | |||
1708 | static void __net_exit psched_net_exit(struct net *net) | ||
1709 | { | ||
1710 | proc_net_remove(net, "psched"); | ||
1711 | |||
1712 | return; | ||
1713 | } | ||
1714 | #else | ||
1715 | static int __net_init psched_net_init(struct net *net) | ||
1716 | { | ||
1717 | return 0; | ||
1718 | } | ||
1719 | |||
1720 | static void __net_exit psched_net_exit(struct net *net) | ||
1721 | { | ||
1722 | } | ||
1704 | #endif | 1723 | #endif |
1705 | 1724 | ||
1725 | static struct pernet_operations psched_net_ops = { | ||
1726 | .init = psched_net_init, | ||
1727 | .exit = psched_net_exit, | ||
1728 | }; | ||
1729 | |||
1706 | static int __init pktsched_init(void) | 1730 | static int __init pktsched_init(void) |
1707 | { | 1731 | { |
1732 | int err; | ||
1733 | |||
1734 | err = register_pernet_subsys(&psched_net_ops); | ||
1735 | if (err) { | ||
1736 | printk(KERN_ERR "pktsched_init: " | ||
1737 | "cannot initialize per netns operations\n"); | ||
1738 | return err; | ||
1739 | } | ||
1740 | |||
1708 | register_qdisc(&pfifo_qdisc_ops); | 1741 | register_qdisc(&pfifo_qdisc_ops); |
1709 | register_qdisc(&bfifo_qdisc_ops); | 1742 | register_qdisc(&bfifo_qdisc_ops); |
1710 | register_qdisc(&pfifo_head_drop_qdisc_ops); | 1743 | register_qdisc(&pfifo_head_drop_qdisc_ops); |
1711 | register_qdisc(&mq_qdisc_ops); | 1744 | register_qdisc(&mq_qdisc_ops); |
1712 | proc_net_fops_create(&init_net, "psched", 0, &psched_fops); | ||
1713 | 1745 | ||
1714 | rtnl_register(PF_UNSPEC, RTM_NEWQDISC, tc_modify_qdisc, NULL); | 1746 | rtnl_register(PF_UNSPEC, RTM_NEWQDISC, tc_modify_qdisc, NULL); |
1715 | rtnl_register(PF_UNSPEC, RTM_DELQDISC, tc_get_qdisc, NULL); | 1747 | rtnl_register(PF_UNSPEC, RTM_DELQDISC, tc_get_qdisc, NULL); |
diff --git a/net/sctp/input.c b/net/sctp/input.c index c0c973e67add..3d74b264ea22 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c | |||
@@ -75,7 +75,7 @@ static struct sctp_association *__sctp_lookup_association( | |||
75 | const union sctp_addr *peer, | 75 | const union sctp_addr *peer, |
76 | struct sctp_transport **pt); | 76 | struct sctp_transport **pt); |
77 | 77 | ||
78 | static void sctp_add_backlog(struct sock *sk, struct sk_buff *skb); | 78 | static int sctp_add_backlog(struct sock *sk, struct sk_buff *skb); |
79 | 79 | ||
80 | 80 | ||
81 | /* Calculate the SCTP checksum of an SCTP packet. */ | 81 | /* Calculate the SCTP checksum of an SCTP packet. */ |
@@ -265,8 +265,13 @@ int sctp_rcv(struct sk_buff *skb) | |||
265 | } | 265 | } |
266 | 266 | ||
267 | if (sock_owned_by_user(sk)) { | 267 | if (sock_owned_by_user(sk)) { |
268 | if (sctp_add_backlog(sk, skb)) { | ||
269 | sctp_bh_unlock_sock(sk); | ||
270 | sctp_chunk_free(chunk); | ||
271 | skb = NULL; /* sctp_chunk_free already freed the skb */ | ||
272 | goto discard_release; | ||
273 | } | ||
268 | SCTP_INC_STATS_BH(SCTP_MIB_IN_PKT_BACKLOG); | 274 | SCTP_INC_STATS_BH(SCTP_MIB_IN_PKT_BACKLOG); |
269 | sctp_add_backlog(sk, skb); | ||
270 | } else { | 275 | } else { |
271 | SCTP_INC_STATS_BH(SCTP_MIB_IN_PKT_SOFTIRQ); | 276 | SCTP_INC_STATS_BH(SCTP_MIB_IN_PKT_SOFTIRQ); |
272 | sctp_inq_push(&chunk->rcvr->inqueue, chunk); | 277 | sctp_inq_push(&chunk->rcvr->inqueue, chunk); |
@@ -336,8 +341,10 @@ int sctp_backlog_rcv(struct sock *sk, struct sk_buff *skb) | |||
336 | sctp_bh_lock_sock(sk); | 341 | sctp_bh_lock_sock(sk); |
337 | 342 | ||
338 | if (sock_owned_by_user(sk)) { | 343 | if (sock_owned_by_user(sk)) { |
339 | sk_add_backlog(sk, skb); | 344 | if (sk_add_backlog(sk, skb)) |
340 | backloged = 1; | 345 | sctp_chunk_free(chunk); |
346 | else | ||
347 | backloged = 1; | ||
341 | } else | 348 | } else |
342 | sctp_inq_push(inqueue, chunk); | 349 | sctp_inq_push(inqueue, chunk); |
343 | 350 | ||
@@ -362,22 +369,27 @@ done: | |||
362 | return 0; | 369 | return 0; |
363 | } | 370 | } |
364 | 371 | ||
365 | static void sctp_add_backlog(struct sock *sk, struct sk_buff *skb) | 372 | static int sctp_add_backlog(struct sock *sk, struct sk_buff *skb) |
366 | { | 373 | { |
367 | struct sctp_chunk *chunk = SCTP_INPUT_CB(skb)->chunk; | 374 | struct sctp_chunk *chunk = SCTP_INPUT_CB(skb)->chunk; |
368 | struct sctp_ep_common *rcvr = chunk->rcvr; | 375 | struct sctp_ep_common *rcvr = chunk->rcvr; |
376 | int ret; | ||
369 | 377 | ||
370 | /* Hold the assoc/ep while hanging on the backlog queue. | 378 | ret = sk_add_backlog(sk, skb); |
371 | * This way, we know structures we need will not disappear from us | 379 | if (!ret) { |
372 | */ | 380 | /* Hold the assoc/ep while hanging on the backlog queue. |
373 | if (SCTP_EP_TYPE_ASSOCIATION == rcvr->type) | 381 | * This way, we know structures we need will not disappear |
374 | sctp_association_hold(sctp_assoc(rcvr)); | 382 | * from us |
375 | else if (SCTP_EP_TYPE_SOCKET == rcvr->type) | 383 | */ |
376 | sctp_endpoint_hold(sctp_ep(rcvr)); | 384 | if (SCTP_EP_TYPE_ASSOCIATION == rcvr->type) |
377 | else | 385 | sctp_association_hold(sctp_assoc(rcvr)); |
378 | BUG(); | 386 | else if (SCTP_EP_TYPE_SOCKET == rcvr->type) |
387 | sctp_endpoint_hold(sctp_ep(rcvr)); | ||
388 | else | ||
389 | BUG(); | ||
390 | } | ||
391 | return ret; | ||
379 | 392 | ||
380 | sk_add_backlog(sk, skb); | ||
381 | } | 393 | } |
382 | 394 | ||
383 | /* Handle icmp frag needed error. */ | 395 | /* Handle icmp frag needed error. */ |
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index 1d7ac70ba39f..240dceba06e5 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c | |||
@@ -371,7 +371,7 @@ static void sctp_v6_copy_addrlist(struct list_head *addrlist, | |||
371 | } | 371 | } |
372 | 372 | ||
373 | read_lock_bh(&in6_dev->lock); | 373 | read_lock_bh(&in6_dev->lock); |
374 | for (ifp = in6_dev->addr_list; ifp; ifp = ifp->if_next) { | 374 | list_for_each_entry(ifp, &in6_dev->addr_list, if_list) { |
375 | /* Add the address to the local list. */ | 375 | /* Add the address to the local list. */ |
376 | addr = t_new(struct sctp_sockaddr_entry, GFP_ATOMIC); | 376 | addr = t_new(struct sctp_sockaddr_entry, GFP_ATOMIC); |
377 | if (addr) { | 377 | if (addr) { |
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index 4e4ca65cd320..500886bda9b4 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c | |||
@@ -475,7 +475,7 @@ static void sctp_do_8_2_transport_strike(struct sctp_association *asoc, | |||
475 | * used to provide an upper bound to this doubling operation. | 475 | * used to provide an upper bound to this doubling operation. |
476 | * | 476 | * |
477 | * Special Case: the first HB doesn't trigger exponential backoff. | 477 | * Special Case: the first HB doesn't trigger exponential backoff. |
478 | * The first unacknowleged HB triggers it. We do this with a flag | 478 | * The first unacknowledged HB triggers it. We do this with a flag |
479 | * that indicates that we have an outstanding HB. | 479 | * that indicates that we have an outstanding HB. |
480 | */ | 480 | */ |
481 | if (!is_hb || transport->hb_sent) { | 481 | if (!is_hb || transport->hb_sent) { |
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index f6d1e59c4151..dfc5c127efd4 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -3720,6 +3720,9 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk) | |||
3720 | SCTP_DBG_OBJCNT_INC(sock); | 3720 | SCTP_DBG_OBJCNT_INC(sock); |
3721 | percpu_counter_inc(&sctp_sockets_allocated); | 3721 | percpu_counter_inc(&sctp_sockets_allocated); |
3722 | 3722 | ||
3723 | /* Set socket backlog limit. */ | ||
3724 | sk->sk_backlog.limit = sysctl_sctp_rmem[1]; | ||
3725 | |||
3723 | local_bh_disable(); | 3726 | local_bh_disable(); |
3724 | sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1); | 3727 | sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1); |
3725 | local_bh_enable(); | 3728 | local_bh_enable(); |
diff --git a/net/sunrpc/addr.c b/net/sunrpc/addr.c index 6dcdd2517819..f845d9d72f73 100644 --- a/net/sunrpc/addr.c +++ b/net/sunrpc/addr.c | |||
@@ -71,8 +71,9 @@ static size_t rpc_ntop6(const struct sockaddr *sap, | |||
71 | if (unlikely(len == 0)) | 71 | if (unlikely(len == 0)) |
72 | return len; | 72 | return len; |
73 | 73 | ||
74 | if (!(ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL) && | 74 | if (!(ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL)) |
75 | !(ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_SITELOCAL)) | 75 | return len; |
76 | if (sin6->sin6_scope_id == 0) | ||
76 | return len; | 77 | return len; |
77 | 78 | ||
78 | rc = snprintf(scopebuf, sizeof(scopebuf), "%c%u", | 79 | rc = snprintf(scopebuf, sizeof(scopebuf), "%c%u", |
@@ -165,8 +166,7 @@ static int rpc_parse_scope_id(const char *buf, const size_t buflen, | |||
165 | if (*delim != IPV6_SCOPE_DELIMITER) | 166 | if (*delim != IPV6_SCOPE_DELIMITER) |
166 | return 0; | 167 | return 0; |
167 | 168 | ||
168 | if (!(ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL) && | 169 | if (!(ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL)) |
169 | !(ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_SITELOCAL)) | ||
170 | return 0; | 170 | return 0; |
171 | 171 | ||
172 | len = (buf + buflen) - delim - 1; | 172 | len = (buf + buflen) - delim - 1; |
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index f7a7f8380e38..0cfccc2a0297 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c | |||
@@ -206,8 +206,14 @@ gss_fill_context(const void *p, const void *end, struct gss_cl_ctx *ctx, struct | |||
206 | ctx->gc_win = window_size; | 206 | ctx->gc_win = window_size; |
207 | /* gssd signals an error by passing ctx->gc_win = 0: */ | 207 | /* gssd signals an error by passing ctx->gc_win = 0: */ |
208 | if (ctx->gc_win == 0) { | 208 | if (ctx->gc_win == 0) { |
209 | /* in which case, p points to an error code which we ignore */ | 209 | /* |
210 | p = ERR_PTR(-EACCES); | 210 | * in which case, p points to an error code. Anything other |
211 | * than -EKEYEXPIRED gets converted to -EACCES. | ||
212 | */ | ||
213 | p = simple_get_bytes(p, end, &ret, sizeof(ret)); | ||
214 | if (!IS_ERR(p)) | ||
215 | p = (ret == -EKEYEXPIRED) ? ERR_PTR(-EKEYEXPIRED) : | ||
216 | ERR_PTR(-EACCES); | ||
211 | goto err; | 217 | goto err; |
212 | } | 218 | } |
213 | /* copy the opaque wire context */ | 219 | /* copy the opaque wire context */ |
@@ -646,6 +652,7 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen) | |||
646 | err = PTR_ERR(p); | 652 | err = PTR_ERR(p); |
647 | switch (err) { | 653 | switch (err) { |
648 | case -EACCES: | 654 | case -EACCES: |
655 | case -EKEYEXPIRED: | ||
649 | gss_msg->msg.errno = err; | 656 | gss_msg->msg.errno = err; |
650 | err = mlen; | 657 | err = mlen; |
651 | break; | 658 | break; |
diff --git a/net/sunrpc/auth_gss/gss_spkm3_token.c b/net/sunrpc/auth_gss/gss_spkm3_token.c index 3308157436d2..a99825d7caa0 100644 --- a/net/sunrpc/auth_gss/gss_spkm3_token.c +++ b/net/sunrpc/auth_gss/gss_spkm3_token.c | |||
@@ -223,7 +223,7 @@ spkm3_verify_mic_token(unsigned char **tokp, int *mic_hdrlen, unsigned char **ck | |||
223 | 223 | ||
224 | /* only support SPKM_MIC_TOK */ | 224 | /* only support SPKM_MIC_TOK */ |
225 | if((ptr[6] != 0x01) || (ptr[7] != 0x01)) { | 225 | if((ptr[6] != 0x01) || (ptr[7] != 0x01)) { |
226 | dprintk("RPC: ERROR unsupported SPKM3 token \n"); | 226 | dprintk("RPC: ERROR unsupported SPKM3 token\n"); |
227 | goto out; | 227 | goto out; |
228 | } | 228 | } |
229 | 229 | ||
diff --git a/net/sunrpc/bc_svc.c b/net/sunrpc/bc_svc.c index 13f214f53120..8a610fb0cfec 100644 --- a/net/sunrpc/bc_svc.c +++ b/net/sunrpc/bc_svc.c | |||
@@ -75,7 +75,7 @@ int bc_send(struct rpc_rqst *req) | |||
75 | rpc_put_task(task); | 75 | rpc_put_task(task); |
76 | } | 76 | } |
77 | return ret; | 77 | return ret; |
78 | dprintk("RPC: bc_send ret= %d \n", ret); | 78 | dprintk("RPC: bc_send ret= %d\n", ret); |
79 | } | 79 | } |
80 | 80 | ||
81 | #endif /* CONFIG_NFS_V4_1 */ | 81 | #endif /* CONFIG_NFS_V4_1 */ |
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index 9ea45383480e..8d63f8fd29b7 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c | |||
@@ -999,19 +999,14 @@ rpc_fill_super(struct super_block *sb, void *data, int silent) | |||
999 | inode = rpc_get_inode(sb, S_IFDIR | 0755); | 999 | inode = rpc_get_inode(sb, S_IFDIR | 0755); |
1000 | if (!inode) | 1000 | if (!inode) |
1001 | return -ENOMEM; | 1001 | return -ENOMEM; |
1002 | root = d_alloc_root(inode); | 1002 | sb->s_root = root = d_alloc_root(inode); |
1003 | if (!root) { | 1003 | if (!root) { |
1004 | iput(inode); | 1004 | iput(inode); |
1005 | return -ENOMEM; | 1005 | return -ENOMEM; |
1006 | } | 1006 | } |
1007 | if (rpc_populate(root, files, RPCAUTH_lockd, RPCAUTH_RootEOF, NULL)) | 1007 | if (rpc_populate(root, files, RPCAUTH_lockd, RPCAUTH_RootEOF, NULL)) |
1008 | goto out; | 1008 | return -ENOMEM; |
1009 | sb->s_root = root; | ||
1010 | return 0; | 1009 | return 0; |
1011 | out: | ||
1012 | d_genocide(root); | ||
1013 | dput(root); | ||
1014 | return -ENOMEM; | ||
1015 | } | 1010 | } |
1016 | 1011 | ||
1017 | static int | 1012 | static int |
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c index 538ca433a56c..8420a4205b76 100644 --- a/net/sunrpc/svc.c +++ b/net/sunrpc/svc.c | |||
@@ -133,7 +133,7 @@ svc_pool_map_choose_mode(void) | |||
133 | return SVC_POOL_PERNODE; | 133 | return SVC_POOL_PERNODE; |
134 | } | 134 | } |
135 | 135 | ||
136 | node = any_online_node(node_online_map); | 136 | node = first_online_node; |
137 | if (nr_cpus_node(node) > 2) { | 137 | if (nr_cpus_node(node) > 2) { |
138 | /* | 138 | /* |
139 | * Non-trivial SMP, or CONFIG_NUMA on | 139 | * Non-trivial SMP, or CONFIG_NUMA on |
@@ -506,6 +506,10 @@ svc_init_buffer(struct svc_rqst *rqstp, unsigned int size) | |||
506 | { | 506 | { |
507 | unsigned int pages, arghi; | 507 | unsigned int pages, arghi; |
508 | 508 | ||
509 | /* bc_xprt uses fore channel allocated buffers */ | ||
510 | if (svc_is_backchannel(rqstp)) | ||
511 | return 1; | ||
512 | |||
509 | pages = size / PAGE_SIZE + 1; /* extra page as we hold both request and reply. | 513 | pages = size / PAGE_SIZE + 1; /* extra page as we hold both request and reply. |
510 | * We assume one is at most one page | 514 | * We assume one is at most one page |
511 | */ | 515 | */ |
diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c index 7d1f9e928f69..8f0f1fb3dc52 100644 --- a/net/sunrpc/svc_xprt.c +++ b/net/sunrpc/svc_xprt.c | |||
@@ -173,11 +173,13 @@ static struct svc_xprt *__svc_xpo_create(struct svc_xprt_class *xcl, | |||
173 | .sin_addr.s_addr = htonl(INADDR_ANY), | 173 | .sin_addr.s_addr = htonl(INADDR_ANY), |
174 | .sin_port = htons(port), | 174 | .sin_port = htons(port), |
175 | }; | 175 | }; |
176 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
176 | struct sockaddr_in6 sin6 = { | 177 | struct sockaddr_in6 sin6 = { |
177 | .sin6_family = AF_INET6, | 178 | .sin6_family = AF_INET6, |
178 | .sin6_addr = IN6ADDR_ANY_INIT, | 179 | .sin6_addr = IN6ADDR_ANY_INIT, |
179 | .sin6_port = htons(port), | 180 | .sin6_port = htons(port), |
180 | }; | 181 | }; |
182 | #endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */ | ||
181 | struct sockaddr *sap; | 183 | struct sockaddr *sap; |
182 | size_t len; | 184 | size_t len; |
183 | 185 | ||
@@ -186,10 +188,12 @@ static struct svc_xprt *__svc_xpo_create(struct svc_xprt_class *xcl, | |||
186 | sap = (struct sockaddr *)&sin; | 188 | sap = (struct sockaddr *)&sin; |
187 | len = sizeof(sin); | 189 | len = sizeof(sin); |
188 | break; | 190 | break; |
191 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
189 | case PF_INET6: | 192 | case PF_INET6: |
190 | sap = (struct sockaddr *)&sin6; | 193 | sap = (struct sockaddr *)&sin6; |
191 | len = sizeof(sin6); | 194 | len = sizeof(sin6); |
192 | break; | 195 | break; |
196 | #endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */ | ||
193 | default: | 197 | default: |
194 | return ERR_PTR(-EAFNOSUPPORT); | 198 | return ERR_PTR(-EAFNOSUPPORT); |
195 | } | 199 | } |
@@ -231,7 +235,10 @@ int svc_create_xprt(struct svc_serv *serv, const char *xprt_name, | |||
231 | err: | 235 | err: |
232 | spin_unlock(&svc_xprt_class_lock); | 236 | spin_unlock(&svc_xprt_class_lock); |
233 | dprintk("svc: transport %s not found\n", xprt_name); | 237 | dprintk("svc: transport %s not found\n", xprt_name); |
234 | return -ENOENT; | 238 | |
239 | /* This errno is exposed to user space. Provide a reasonable | ||
240 | * perror msg for a bad transport. */ | ||
241 | return -EPROTONOSUPPORT; | ||
235 | } | 242 | } |
236 | EXPORT_SYMBOL_GPL(svc_create_xprt); | 243 | EXPORT_SYMBOL_GPL(svc_create_xprt); |
237 | 244 | ||
@@ -699,8 +706,10 @@ int svc_recv(struct svc_rqst *rqstp, long timeout) | |||
699 | spin_unlock_bh(&pool->sp_lock); | 706 | spin_unlock_bh(&pool->sp_lock); |
700 | 707 | ||
701 | len = 0; | 708 | len = 0; |
702 | if (test_bit(XPT_LISTENER, &xprt->xpt_flags) && | 709 | if (test_bit(XPT_CLOSE, &xprt->xpt_flags)) { |
703 | !test_bit(XPT_CLOSE, &xprt->xpt_flags)) { | 710 | dprintk("svc_recv: found XPT_CLOSE\n"); |
711 | svc_delete_xprt(xprt); | ||
712 | } else if (test_bit(XPT_LISTENER, &xprt->xpt_flags)) { | ||
704 | struct svc_xprt *newxpt; | 713 | struct svc_xprt *newxpt; |
705 | newxpt = xprt->xpt_ops->xpo_accept(xprt); | 714 | newxpt = xprt->xpt_ops->xpo_accept(xprt); |
706 | if (newxpt) { | 715 | if (newxpt) { |
@@ -726,7 +735,7 @@ int svc_recv(struct svc_rqst *rqstp, long timeout) | |||
726 | svc_xprt_received(newxpt); | 735 | svc_xprt_received(newxpt); |
727 | } | 736 | } |
728 | svc_xprt_received(xprt); | 737 | svc_xprt_received(xprt); |
729 | } else if (!test_bit(XPT_CLOSE, &xprt->xpt_flags)) { | 738 | } else { |
730 | dprintk("svc: server %p, pool %u, transport %p, inuse=%d\n", | 739 | dprintk("svc: server %p, pool %u, transport %p, inuse=%d\n", |
731 | rqstp, pool->sp_id, xprt, | 740 | rqstp, pool->sp_id, xprt, |
732 | atomic_read(&xprt->xpt_ref.refcount)); | 741 | atomic_read(&xprt->xpt_ref.refcount)); |
@@ -739,11 +748,6 @@ int svc_recv(struct svc_rqst *rqstp, long timeout) | |||
739 | dprintk("svc: got len=%d\n", len); | 748 | dprintk("svc: got len=%d\n", len); |
740 | } | 749 | } |
741 | 750 | ||
742 | if (test_bit(XPT_CLOSE, &xprt->xpt_flags)) { | ||
743 | dprintk("svc_recv: found XPT_CLOSE\n"); | ||
744 | svc_delete_xprt(xprt); | ||
745 | } | ||
746 | |||
747 | /* No data, incomplete (TCP) read, or accept() */ | 751 | /* No data, incomplete (TCP) read, or accept() */ |
748 | if (len == 0 || len == -EAGAIN) { | 752 | if (len == 0 || len == -EAGAIN) { |
749 | rqstp->rq_res.len = 0; | 753 | rqstp->rq_res.len = 0; |
@@ -889,11 +893,8 @@ void svc_delete_xprt(struct svc_xprt *xprt) | |||
889 | if (test_bit(XPT_TEMP, &xprt->xpt_flags)) | 893 | if (test_bit(XPT_TEMP, &xprt->xpt_flags)) |
890 | serv->sv_tmpcnt--; | 894 | serv->sv_tmpcnt--; |
891 | 895 | ||
892 | for (dr = svc_deferred_dequeue(xprt); dr; | 896 | while ((dr = svc_deferred_dequeue(xprt)) != NULL) |
893 | dr = svc_deferred_dequeue(xprt)) { | ||
894 | svc_xprt_put(xprt); | ||
895 | kfree(dr); | 897 | kfree(dr); |
896 | } | ||
897 | 898 | ||
898 | svc_xprt_put(xprt); | 899 | svc_xprt_put(xprt); |
899 | spin_unlock_bh(&serv->sv_lock); | 900 | spin_unlock_bh(&serv->sv_lock); |
diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c index d8c041114497..afdcb0459a83 100644 --- a/net/sunrpc/svcauth_unix.c +++ b/net/sunrpc/svcauth_unix.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
16 | #define RPCDBG_FACILITY RPCDBG_AUTH | 16 | #define RPCDBG_FACILITY RPCDBG_AUTH |
17 | 17 | ||
18 | #include <linux/sunrpc/clnt.h> | ||
18 | 19 | ||
19 | /* | 20 | /* |
20 | * AUTHUNIX and AUTHNULL credentials are both handled here. | 21 | * AUTHUNIX and AUTHNULL credentials are both handled here. |
@@ -187,10 +188,13 @@ static int ip_map_parse(struct cache_detail *cd, | |||
187 | * for scratch: */ | 188 | * for scratch: */ |
188 | char *buf = mesg; | 189 | char *buf = mesg; |
189 | int len; | 190 | int len; |
190 | int b1, b2, b3, b4, b5, b6, b7, b8; | ||
191 | char c; | ||
192 | char class[8]; | 191 | char class[8]; |
193 | struct in6_addr addr; | 192 | union { |
193 | struct sockaddr sa; | ||
194 | struct sockaddr_in s4; | ||
195 | struct sockaddr_in6 s6; | ||
196 | } address; | ||
197 | struct sockaddr_in6 sin6; | ||
194 | int err; | 198 | int err; |
195 | 199 | ||
196 | struct ip_map *ipmp; | 200 | struct ip_map *ipmp; |
@@ -209,24 +213,24 @@ static int ip_map_parse(struct cache_detail *cd, | |||
209 | len = qword_get(&mesg, buf, mlen); | 213 | len = qword_get(&mesg, buf, mlen); |
210 | if (len <= 0) return -EINVAL; | 214 | if (len <= 0) return -EINVAL; |
211 | 215 | ||
212 | if (sscanf(buf, "%u.%u.%u.%u%c", &b1, &b2, &b3, &b4, &c) == 4) { | 216 | if (rpc_pton(buf, len, &address.sa, sizeof(address)) == 0) |
213 | addr.s6_addr32[0] = 0; | ||
214 | addr.s6_addr32[1] = 0; | ||
215 | addr.s6_addr32[2] = htonl(0xffff); | ||
216 | addr.s6_addr32[3] = | ||
217 | htonl((((((b1<<8)|b2)<<8)|b3)<<8)|b4); | ||
218 | } else if (sscanf(buf, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x%c", | ||
219 | &b1, &b2, &b3, &b4, &b5, &b6, &b7, &b8, &c) == 8) { | ||
220 | addr.s6_addr16[0] = htons(b1); | ||
221 | addr.s6_addr16[1] = htons(b2); | ||
222 | addr.s6_addr16[2] = htons(b3); | ||
223 | addr.s6_addr16[3] = htons(b4); | ||
224 | addr.s6_addr16[4] = htons(b5); | ||
225 | addr.s6_addr16[5] = htons(b6); | ||
226 | addr.s6_addr16[6] = htons(b7); | ||
227 | addr.s6_addr16[7] = htons(b8); | ||
228 | } else | ||
229 | return -EINVAL; | 217 | return -EINVAL; |
218 | switch (address.sa.sa_family) { | ||
219 | case AF_INET: | ||
220 | /* Form a mapped IPv4 address in sin6 */ | ||
221 | memset(&sin6, 0, sizeof(sin6)); | ||
222 | sin6.sin6_family = AF_INET6; | ||
223 | sin6.sin6_addr.s6_addr32[2] = htonl(0xffff); | ||
224 | sin6.sin6_addr.s6_addr32[3] = address.s4.sin_addr.s_addr; | ||
225 | break; | ||
226 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
227 | case AF_INET6: | ||
228 | memcpy(&sin6, &address.s6, sizeof(sin6)); | ||
229 | break; | ||
230 | #endif | ||
231 | default: | ||
232 | return -EINVAL; | ||
233 | } | ||
230 | 234 | ||
231 | expiry = get_expiry(&mesg); | 235 | expiry = get_expiry(&mesg); |
232 | if (expiry ==0) | 236 | if (expiry ==0) |
@@ -243,7 +247,8 @@ static int ip_map_parse(struct cache_detail *cd, | |||
243 | } else | 247 | } else |
244 | dom = NULL; | 248 | dom = NULL; |
245 | 249 | ||
246 | ipmp = ip_map_lookup(class, &addr); | 250 | /* IPv6 scope IDs are ignored for now */ |
251 | ipmp = ip_map_lookup(class, &sin6.sin6_addr); | ||
247 | if (ipmp) { | 252 | if (ipmp) { |
248 | err = ip_map_update(ipmp, | 253 | err = ip_map_update(ipmp, |
249 | container_of(dom, struct unix_domain, h), | 254 | container_of(dom, struct unix_domain, h), |
@@ -619,7 +624,7 @@ static int unix_gid_show(struct seq_file *m, | |||
619 | else | 624 | else |
620 | glen = 0; | 625 | glen = 0; |
621 | 626 | ||
622 | seq_printf(m, "%d %d:", ug->uid, glen); | 627 | seq_printf(m, "%u %d:", ug->uid, glen); |
623 | for (i = 0; i < glen; i++) | 628 | for (i = 0; i < glen; i++) |
624 | seq_printf(m, " %d", GROUP_AT(ug->gi, i)); | 629 | seq_printf(m, " %d", GROUP_AT(ug->gi, i)); |
625 | seq_printf(m, "\n"); | 630 | seq_printf(m, "\n"); |
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index 870929e08e5d..a29f259204e6 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c | |||
@@ -968,6 +968,7 @@ static int svc_tcp_recv_record(struct svc_sock *svsk, struct svc_rqst *rqstp) | |||
968 | return len; | 968 | return len; |
969 | err_delete: | 969 | err_delete: |
970 | set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags); | 970 | set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags); |
971 | svc_xprt_received(&svsk->sk_xprt); | ||
971 | err_again: | 972 | err_again: |
972 | return -EAGAIN; | 973 | return -EAGAIN; |
973 | } | 974 | } |
@@ -1357,7 +1358,7 @@ int svc_addsock(struct svc_serv *serv, const int fd, char *name_return, | |||
1357 | 1358 | ||
1358 | if (!so) | 1359 | if (!so) |
1359 | return err; | 1360 | return err; |
1360 | if (so->sk->sk_family != AF_INET) | 1361 | if ((so->sk->sk_family != PF_INET) && (so->sk->sk_family != PF_INET6)) |
1361 | err = -EAFNOSUPPORT; | 1362 | err = -EAFNOSUPPORT; |
1362 | else if (so->sk->sk_protocol != IPPROTO_TCP && | 1363 | else if (so->sk->sk_protocol != IPPROTO_TCP && |
1363 | so->sk->sk_protocol != IPPROTO_UDP) | 1364 | so->sk->sk_protocol != IPPROTO_UDP) |
diff --git a/net/sunrpc/xprtrdma/transport.c b/net/sunrpc/xprtrdma/transport.c index 7018eef1dcdd..f96c2fe6137b 100644 --- a/net/sunrpc/xprtrdma/transport.c +++ b/net/sunrpc/xprtrdma/transport.c | |||
@@ -160,16 +160,15 @@ xprt_rdma_format_addresses(struct rpc_xprt *xprt) | |||
160 | (void)rpc_ntop(sap, buf, sizeof(buf)); | 160 | (void)rpc_ntop(sap, buf, sizeof(buf)); |
161 | xprt->address_strings[RPC_DISPLAY_ADDR] = kstrdup(buf, GFP_KERNEL); | 161 | xprt->address_strings[RPC_DISPLAY_ADDR] = kstrdup(buf, GFP_KERNEL); |
162 | 162 | ||
163 | (void)snprintf(buf, sizeof(buf), "%u", rpc_get_port(sap)); | 163 | snprintf(buf, sizeof(buf), "%u", rpc_get_port(sap)); |
164 | xprt->address_strings[RPC_DISPLAY_PORT] = kstrdup(buf, GFP_KERNEL); | 164 | xprt->address_strings[RPC_DISPLAY_PORT] = kstrdup(buf, GFP_KERNEL); |
165 | 165 | ||
166 | xprt->address_strings[RPC_DISPLAY_PROTO] = "rdma"; | 166 | xprt->address_strings[RPC_DISPLAY_PROTO] = "rdma"; |
167 | 167 | ||
168 | (void)snprintf(buf, sizeof(buf), "%02x%02x%02x%02x", | 168 | snprintf(buf, sizeof(buf), "%08x", ntohl(sin->sin_addr.s_addr)); |
169 | NIPQUAD(sin->sin_addr.s_addr)); | ||
170 | xprt->address_strings[RPC_DISPLAY_HEX_ADDR] = kstrdup(buf, GFP_KERNEL); | 169 | xprt->address_strings[RPC_DISPLAY_HEX_ADDR] = kstrdup(buf, GFP_KERNEL); |
171 | 170 | ||
172 | (void)snprintf(buf, sizeof(buf), "%4hx", rpc_get_port(sap)); | 171 | snprintf(buf, sizeof(buf), "%4hx", rpc_get_port(sap)); |
173 | xprt->address_strings[RPC_DISPLAY_HEX_PORT] = kstrdup(buf, GFP_KERNEL); | 172 | xprt->address_strings[RPC_DISPLAY_HEX_PORT] = kstrdup(buf, GFP_KERNEL); |
174 | 173 | ||
175 | /* netid */ | 174 | /* netid */ |
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 3d739e5d15d8..75ab08eac66b 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c | |||
@@ -297,12 +297,11 @@ static void xs_format_common_peer_addresses(struct rpc_xprt *xprt) | |||
297 | switch (sap->sa_family) { | 297 | switch (sap->sa_family) { |
298 | case AF_INET: | 298 | case AF_INET: |
299 | sin = xs_addr_in(xprt); | 299 | sin = xs_addr_in(xprt); |
300 | (void)snprintf(buf, sizeof(buf), "%02x%02x%02x%02x", | 300 | snprintf(buf, sizeof(buf), "%08x", ntohl(sin->sin_addr.s_addr)); |
301 | NIPQUAD(sin->sin_addr.s_addr)); | ||
302 | break; | 301 | break; |
303 | case AF_INET6: | 302 | case AF_INET6: |
304 | sin6 = xs_addr_in6(xprt); | 303 | sin6 = xs_addr_in6(xprt); |
305 | (void)snprintf(buf, sizeof(buf), "%pi6", &sin6->sin6_addr); | 304 | snprintf(buf, sizeof(buf), "%pi6", &sin6->sin6_addr); |
306 | break; | 305 | break; |
307 | default: | 306 | default: |
308 | BUG(); | 307 | BUG(); |
@@ -315,10 +314,10 @@ static void xs_format_common_peer_ports(struct rpc_xprt *xprt) | |||
315 | struct sockaddr *sap = xs_addr(xprt); | 314 | struct sockaddr *sap = xs_addr(xprt); |
316 | char buf[128]; | 315 | char buf[128]; |
317 | 316 | ||
318 | (void)snprintf(buf, sizeof(buf), "%u", rpc_get_port(sap)); | 317 | snprintf(buf, sizeof(buf), "%u", rpc_get_port(sap)); |
319 | xprt->address_strings[RPC_DISPLAY_PORT] = kstrdup(buf, GFP_KERNEL); | 318 | xprt->address_strings[RPC_DISPLAY_PORT] = kstrdup(buf, GFP_KERNEL); |
320 | 319 | ||
321 | (void)snprintf(buf, sizeof(buf), "%4hx", rpc_get_port(sap)); | 320 | snprintf(buf, sizeof(buf), "%4hx", rpc_get_port(sap)); |
322 | xprt->address_strings[RPC_DISPLAY_HEX_PORT] = kstrdup(buf, GFP_KERNEL); | 321 | xprt->address_strings[RPC_DISPLAY_HEX_PORT] = kstrdup(buf, GFP_KERNEL); |
323 | } | 322 | } |
324 | 323 | ||
@@ -1912,6 +1911,11 @@ static void xs_tcp_setup_socket(struct rpc_xprt *xprt, | |||
1912 | case -EALREADY: | 1911 | case -EALREADY: |
1913 | xprt_clear_connecting(xprt); | 1912 | xprt_clear_connecting(xprt); |
1914 | return; | 1913 | return; |
1914 | case -EINVAL: | ||
1915 | /* Happens, for instance, if the user specified a link | ||
1916 | * local IPv6 address without a scope-id. | ||
1917 | */ | ||
1918 | goto out; | ||
1915 | } | 1919 | } |
1916 | out_eagain: | 1920 | out_eagain: |
1917 | status = -EAGAIN; | 1921 | status = -EAGAIN; |
@@ -2100,7 +2104,7 @@ static void xs_tcp_print_stats(struct rpc_xprt *xprt, struct seq_file *seq) | |||
2100 | * we allocate pages instead doing a kmalloc like rpc_malloc is because we want | 2104 | * we allocate pages instead doing a kmalloc like rpc_malloc is because we want |
2101 | * to use the server side send routines. | 2105 | * to use the server side send routines. |
2102 | */ | 2106 | */ |
2103 | void *bc_malloc(struct rpc_task *task, size_t size) | 2107 | static void *bc_malloc(struct rpc_task *task, size_t size) |
2104 | { | 2108 | { |
2105 | struct page *page; | 2109 | struct page *page; |
2106 | struct rpc_buffer *buf; | 2110 | struct rpc_buffer *buf; |
@@ -2120,7 +2124,7 @@ void *bc_malloc(struct rpc_task *task, size_t size) | |||
2120 | /* | 2124 | /* |
2121 | * Free the space allocated in the bc_alloc routine | 2125 | * Free the space allocated in the bc_alloc routine |
2122 | */ | 2126 | */ |
2123 | void bc_free(void *buffer) | 2127 | static void bc_free(void *buffer) |
2124 | { | 2128 | { |
2125 | struct rpc_buffer *buf; | 2129 | struct rpc_buffer *buf; |
2126 | 2130 | ||
diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c index a3bfd4064912..90a051912c03 100644 --- a/net/tipc/bcast.c +++ b/net/tipc/bcast.c | |||
@@ -558,10 +558,7 @@ static int tipc_bcbearer_send(struct sk_buff *buf, | |||
558 | struct tipc_bearer *unused1, | 558 | struct tipc_bearer *unused1, |
559 | struct tipc_media_addr *unused2) | 559 | struct tipc_media_addr *unused2) |
560 | { | 560 | { |
561 | static int send_count = 0; | ||
562 | |||
563 | int bp_index; | 561 | int bp_index; |
564 | int swap_time; | ||
565 | 562 | ||
566 | /* Prepare buffer for broadcasting (if first time trying to send it) */ | 563 | /* Prepare buffer for broadcasting (if first time trying to send it) */ |
567 | 564 | ||
@@ -575,11 +572,6 @@ static int tipc_bcbearer_send(struct sk_buff *buf, | |||
575 | msg_set_mc_netid(msg, tipc_net_id); | 572 | msg_set_mc_netid(msg, tipc_net_id); |
576 | } | 573 | } |
577 | 574 | ||
578 | /* Determine if bearer pairs should be swapped following this attempt */ | ||
579 | |||
580 | if ((swap_time = (++send_count >= 10))) | ||
581 | send_count = 0; | ||
582 | |||
583 | /* Send buffer over bearers until all targets reached */ | 575 | /* Send buffer over bearers until all targets reached */ |
584 | 576 | ||
585 | bcbearer->remains = tipc_cltr_bcast_nodes; | 577 | bcbearer->remains = tipc_cltr_bcast_nodes; |
@@ -595,21 +587,22 @@ static int tipc_bcbearer_send(struct sk_buff *buf, | |||
595 | if (bcbearer->remains_new.count == bcbearer->remains.count) | 587 | if (bcbearer->remains_new.count == bcbearer->remains.count) |
596 | continue; /* bearer pair doesn't add anything */ | 588 | continue; /* bearer pair doesn't add anything */ |
597 | 589 | ||
598 | if (!p->publ.blocked && | 590 | if (p->publ.blocked || |
599 | !p->media->send_msg(buf, &p->publ, &p->media->bcast_addr)) { | 591 | p->media->send_msg(buf, &p->publ, &p->media->bcast_addr)) { |
600 | if (swap_time && s && !s->publ.blocked) | 592 | /* unable to send on primary bearer */ |
601 | goto swap; | 593 | if (!s || s->publ.blocked || |
602 | else | 594 | s->media->send_msg(buf, &s->publ, |
603 | goto update; | 595 | &s->media->bcast_addr)) { |
596 | /* unable to send on either bearer */ | ||
597 | continue; | ||
598 | } | ||
599 | } | ||
600 | |||
601 | if (s) { | ||
602 | bcbearer->bpairs[bp_index].primary = s; | ||
603 | bcbearer->bpairs[bp_index].secondary = p; | ||
604 | } | 604 | } |
605 | 605 | ||
606 | if (!s || s->publ.blocked || | ||
607 | s->media->send_msg(buf, &s->publ, &s->media->bcast_addr)) | ||
608 | continue; /* unable to send using bearer pair */ | ||
609 | swap: | ||
610 | bcbearer->bpairs[bp_index].primary = s; | ||
611 | bcbearer->bpairs[bp_index].secondary = p; | ||
612 | update: | ||
613 | if (bcbearer->remains_new.count == 0) | 606 | if (bcbearer->remains_new.count == 0) |
614 | return 0; | 607 | return 0; |
615 | 608 | ||
diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index 327011fcc407..78091375ca12 100644 --- a/net/tipc/bearer.c +++ b/net/tipc/bearer.c | |||
@@ -45,10 +45,10 @@ | |||
45 | 45 | ||
46 | #define MAX_ADDR_STR 32 | 46 | #define MAX_ADDR_STR 32 |
47 | 47 | ||
48 | static struct media *media_list = NULL; | 48 | static struct media media_list[MAX_MEDIA]; |
49 | static u32 media_count = 0; | 49 | static u32 media_count = 0; |
50 | 50 | ||
51 | struct bearer *tipc_bearers = NULL; | 51 | struct bearer tipc_bearers[MAX_BEARERS]; |
52 | 52 | ||
53 | /** | 53 | /** |
54 | * media_name_valid - validate media name | 54 | * media_name_valid - validate media name |
@@ -108,9 +108,11 @@ int tipc_register_media(u32 media_type, | |||
108 | int res = -EINVAL; | 108 | int res = -EINVAL; |
109 | 109 | ||
110 | write_lock_bh(&tipc_net_lock); | 110 | write_lock_bh(&tipc_net_lock); |
111 | if (!media_list) | ||
112 | goto exit; | ||
113 | 111 | ||
112 | if (tipc_mode != TIPC_NET_MODE) { | ||
113 | warn("Media <%s> rejected, not in networked mode yet\n", name); | ||
114 | goto exit; | ||
115 | } | ||
114 | if (!media_name_valid(name)) { | 116 | if (!media_name_valid(name)) { |
115 | warn("Media <%s> rejected, illegal name\n", name); | 117 | warn("Media <%s> rejected, illegal name\n", name); |
116 | goto exit; | 118 | goto exit; |
@@ -660,33 +662,10 @@ int tipc_disable_bearer(const char *name) | |||
660 | 662 | ||
661 | 663 | ||
662 | 664 | ||
663 | int tipc_bearer_init(void) | ||
664 | { | ||
665 | int res; | ||
666 | |||
667 | write_lock_bh(&tipc_net_lock); | ||
668 | tipc_bearers = kcalloc(MAX_BEARERS, sizeof(struct bearer), GFP_ATOMIC); | ||
669 | media_list = kcalloc(MAX_MEDIA, sizeof(struct media), GFP_ATOMIC); | ||
670 | if (tipc_bearers && media_list) { | ||
671 | res = 0; | ||
672 | } else { | ||
673 | kfree(tipc_bearers); | ||
674 | kfree(media_list); | ||
675 | tipc_bearers = NULL; | ||
676 | media_list = NULL; | ||
677 | res = -ENOMEM; | ||
678 | } | ||
679 | write_unlock_bh(&tipc_net_lock); | ||
680 | return res; | ||
681 | } | ||
682 | |||
683 | void tipc_bearer_stop(void) | 665 | void tipc_bearer_stop(void) |
684 | { | 666 | { |
685 | u32 i; | 667 | u32 i; |
686 | 668 | ||
687 | if (!tipc_bearers) | ||
688 | return; | ||
689 | |||
690 | for (i = 0; i < MAX_BEARERS; i++) { | 669 | for (i = 0; i < MAX_BEARERS; i++) { |
691 | if (tipc_bearers[i].active) | 670 | if (tipc_bearers[i].active) |
692 | tipc_bearers[i].publ.blocked = 1; | 671 | tipc_bearers[i].publ.blocked = 1; |
@@ -695,10 +674,6 @@ void tipc_bearer_stop(void) | |||
695 | if (tipc_bearers[i].active) | 674 | if (tipc_bearers[i].active) |
696 | bearer_disable(tipc_bearers[i].publ.name); | 675 | bearer_disable(tipc_bearers[i].publ.name); |
697 | } | 676 | } |
698 | kfree(tipc_bearers); | ||
699 | kfree(media_list); | ||
700 | tipc_bearers = NULL; | ||
701 | media_list = NULL; | ||
702 | media_count = 0; | 677 | media_count = 0; |
703 | } | 678 | } |
704 | 679 | ||
diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h index ca5734892713..000228e93f9e 100644 --- a/net/tipc/bearer.h +++ b/net/tipc/bearer.h | |||
@@ -114,7 +114,7 @@ struct bearer_name { | |||
114 | 114 | ||
115 | struct link; | 115 | struct link; |
116 | 116 | ||
117 | extern struct bearer *tipc_bearers; | 117 | extern struct bearer tipc_bearers[]; |
118 | 118 | ||
119 | void tipc_media_addr_printf(struct print_buf *pb, struct tipc_media_addr *a); | 119 | void tipc_media_addr_printf(struct print_buf *pb, struct tipc_media_addr *a); |
120 | struct sk_buff *tipc_media_get_names(void); | 120 | struct sk_buff *tipc_media_get_names(void); |
diff --git a/net/tipc/link.c b/net/tipc/link.c index 6f50f6423f63..c76e82e5f982 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c | |||
@@ -877,7 +877,7 @@ static void link_state_event(struct link *l_ptr, unsigned event) | |||
877 | case TIMEOUT_EVT: | 877 | case TIMEOUT_EVT: |
878 | dbg_link("TIM "); | 878 | dbg_link("TIM "); |
879 | if (l_ptr->next_in_no != l_ptr->checkpoint) { | 879 | if (l_ptr->next_in_no != l_ptr->checkpoint) { |
880 | dbg_link("-> WW \n"); | 880 | dbg_link("-> WW\n"); |
881 | l_ptr->state = WORKING_WORKING; | 881 | l_ptr->state = WORKING_WORKING; |
882 | l_ptr->fsm_msg_cnt = 0; | 882 | l_ptr->fsm_msg_cnt = 0; |
883 | l_ptr->checkpoint = l_ptr->next_in_no; | 883 | l_ptr->checkpoint = l_ptr->next_in_no; |
@@ -934,7 +934,7 @@ static void link_state_event(struct link *l_ptr, unsigned event) | |||
934 | link_set_timer(l_ptr, cont_intv); | 934 | link_set_timer(l_ptr, cont_intv); |
935 | break; | 935 | break; |
936 | case RESET_MSG: | 936 | case RESET_MSG: |
937 | dbg_link("RES \n"); | 937 | dbg_link("RES\n"); |
938 | dbg_link(" -> RR\n"); | 938 | dbg_link(" -> RR\n"); |
939 | l_ptr->state = RESET_RESET; | 939 | l_ptr->state = RESET_RESET; |
940 | l_ptr->fsm_msg_cnt = 0; | 940 | l_ptr->fsm_msg_cnt = 0; |
@@ -947,7 +947,7 @@ static void link_state_event(struct link *l_ptr, unsigned event) | |||
947 | l_ptr->started = 1; | 947 | l_ptr->started = 1; |
948 | /* fall through */ | 948 | /* fall through */ |
949 | case TIMEOUT_EVT: | 949 | case TIMEOUT_EVT: |
950 | dbg_link("TIM \n"); | 950 | dbg_link("TIM\n"); |
951 | tipc_link_send_proto_msg(l_ptr, RESET_MSG, 0, 0, 0, 0, 0); | 951 | tipc_link_send_proto_msg(l_ptr, RESET_MSG, 0, 0, 0, 0, 0); |
952 | l_ptr->fsm_msg_cnt++; | 952 | l_ptr->fsm_msg_cnt++; |
953 | link_set_timer(l_ptr, cont_intv); | 953 | link_set_timer(l_ptr, cont_intv); |
@@ -1553,7 +1553,7 @@ u32 tipc_link_push_packet(struct link *l_ptr) | |||
1553 | 1553 | ||
1554 | /* Continue retransmission now, if there is anything: */ | 1554 | /* Continue retransmission now, if there is anything: */ |
1555 | 1555 | ||
1556 | if (r_q_size && buf && !skb_cloned(buf)) { | 1556 | if (r_q_size && buf) { |
1557 | msg_set_ack(buf_msg(buf), mod(l_ptr->next_in_no - 1)); | 1557 | msg_set_ack(buf_msg(buf), mod(l_ptr->next_in_no - 1)); |
1558 | msg_set_bcast_ack(buf_msg(buf), l_ptr->owner->bclink.last_in); | 1558 | msg_set_bcast_ack(buf_msg(buf), l_ptr->owner->bclink.last_in); |
1559 | if (tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) { | 1559 | if (tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) { |
@@ -1722,15 +1722,16 @@ void tipc_link_retransmit(struct link *l_ptr, struct sk_buff *buf, | |||
1722 | dbg("Retransmitting %u in link %x\n", retransmits, l_ptr); | 1722 | dbg("Retransmitting %u in link %x\n", retransmits, l_ptr); |
1723 | 1723 | ||
1724 | if (tipc_bearer_congested(l_ptr->b_ptr, l_ptr)) { | 1724 | if (tipc_bearer_congested(l_ptr->b_ptr, l_ptr)) { |
1725 | if (!skb_cloned(buf)) { | 1725 | if (l_ptr->retransm_queue_size == 0) { |
1726 | msg_dbg(msg, ">NO_RETR->BCONG>"); | 1726 | msg_dbg(msg, ">NO_RETR->BCONG>"); |
1727 | dbg_print_link(l_ptr, " "); | 1727 | dbg_print_link(l_ptr, " "); |
1728 | l_ptr->retransm_queue_head = msg_seqno(msg); | 1728 | l_ptr->retransm_queue_head = msg_seqno(msg); |
1729 | l_ptr->retransm_queue_size = retransmits; | 1729 | l_ptr->retransm_queue_size = retransmits; |
1730 | return; | ||
1731 | } else { | 1730 | } else { |
1732 | /* Don't retransmit if driver already has the buffer */ | 1731 | err("Unexpected retransmit on link %s (qsize=%d)\n", |
1732 | l_ptr->name, l_ptr->retransm_queue_size); | ||
1733 | } | 1733 | } |
1734 | return; | ||
1734 | } else { | 1735 | } else { |
1735 | /* Detect repeated retransmit failures on uncongested bearer */ | 1736 | /* Detect repeated retransmit failures on uncongested bearer */ |
1736 | 1737 | ||
@@ -1745,7 +1746,7 @@ void tipc_link_retransmit(struct link *l_ptr, struct sk_buff *buf, | |||
1745 | } | 1746 | } |
1746 | } | 1747 | } |
1747 | 1748 | ||
1748 | while (retransmits && (buf != l_ptr->next_out) && buf && !skb_cloned(buf)) { | 1749 | while (retransmits && (buf != l_ptr->next_out) && buf) { |
1749 | msg = buf_msg(buf); | 1750 | msg = buf_msg(buf); |
1750 | msg_set_ack(msg, mod(l_ptr->next_in_no - 1)); | 1751 | msg_set_ack(msg, mod(l_ptr->next_in_no - 1)); |
1751 | msg_set_bcast_ack(msg, l_ptr->owner->bclink.last_in); | 1752 | msg_set_bcast_ack(msg, l_ptr->owner->bclink.last_in); |
@@ -1882,6 +1883,15 @@ void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *tb_ptr) | |||
1882 | (msg_destnode(msg) != tipc_own_addr))) | 1883 | (msg_destnode(msg) != tipc_own_addr))) |
1883 | goto cont; | 1884 | goto cont; |
1884 | 1885 | ||
1886 | /* Discard non-routeable messages destined for another node */ | ||
1887 | |||
1888 | if (unlikely(!msg_isdata(msg) && | ||
1889 | (msg_destnode(msg) != tipc_own_addr))) { | ||
1890 | if ((msg_user(msg) != CONN_MANAGER) && | ||
1891 | (msg_user(msg) != MSG_FRAGMENTER)) | ||
1892 | goto cont; | ||
1893 | } | ||
1894 | |||
1885 | /* Locate unicast link endpoint that should handle message */ | 1895 | /* Locate unicast link endpoint that should handle message */ |
1886 | 1896 | ||
1887 | n_ptr = tipc_node_find(msg_prevnode(msg)); | 1897 | n_ptr = tipc_node_find(msg_prevnode(msg)); |
@@ -3285,7 +3295,7 @@ static void link_dump_rec_queue(struct link *l_ptr) | |||
3285 | info("buffer %x invalid\n", crs); | 3295 | info("buffer %x invalid\n", crs); |
3286 | return; | 3296 | return; |
3287 | } | 3297 | } |
3288 | msg_dbg(buf_msg(crs), "In rec queue: \n"); | 3298 | msg_dbg(buf_msg(crs), "In rec queue:\n"); |
3289 | crs = crs->next; | 3299 | crs = crs->next; |
3290 | } | 3300 | } |
3291 | } | 3301 | } |
diff --git a/net/tipc/net.c b/net/tipc/net.c index 7906608bf510..79ce8fa2b77a 100644 --- a/net/tipc/net.c +++ b/net/tipc/net.c | |||
@@ -116,7 +116,8 @@ | |||
116 | */ | 116 | */ |
117 | 117 | ||
118 | DEFINE_RWLOCK(tipc_net_lock); | 118 | DEFINE_RWLOCK(tipc_net_lock); |
119 | struct network tipc_net = { NULL }; | 119 | struct _zone *tipc_zones[256] = { NULL, }; |
120 | struct network tipc_net = { tipc_zones }; | ||
120 | 121 | ||
121 | struct tipc_node *tipc_net_select_remote_node(u32 addr, u32 ref) | 122 | struct tipc_node *tipc_net_select_remote_node(u32 addr, u32 ref) |
122 | { | 123 | { |
@@ -158,28 +159,12 @@ void tipc_net_send_external_routes(u32 dest) | |||
158 | } | 159 | } |
159 | } | 160 | } |
160 | 161 | ||
161 | static int net_init(void) | ||
162 | { | ||
163 | memset(&tipc_net, 0, sizeof(tipc_net)); | ||
164 | tipc_net.zones = kcalloc(tipc_max_zones + 1, sizeof(struct _zone *), GFP_ATOMIC); | ||
165 | if (!tipc_net.zones) { | ||
166 | return -ENOMEM; | ||
167 | } | ||
168 | return 0; | ||
169 | } | ||
170 | |||
171 | static void net_stop(void) | 162 | static void net_stop(void) |
172 | { | 163 | { |
173 | u32 z_num; | 164 | u32 z_num; |
174 | 165 | ||
175 | if (!tipc_net.zones) | 166 | for (z_num = 1; z_num <= tipc_max_zones; z_num++) |
176 | return; | ||
177 | |||
178 | for (z_num = 1; z_num <= tipc_max_zones; z_num++) { | ||
179 | tipc_zone_delete(tipc_net.zones[z_num]); | 167 | tipc_zone_delete(tipc_net.zones[z_num]); |
180 | } | ||
181 | kfree(tipc_net.zones); | ||
182 | tipc_net.zones = NULL; | ||
183 | } | 168 | } |
184 | 169 | ||
185 | static void net_route_named_msg(struct sk_buff *buf) | 170 | static void net_route_named_msg(struct sk_buff *buf) |
@@ -282,9 +267,7 @@ int tipc_net_start(u32 addr) | |||
282 | tipc_named_reinit(); | 267 | tipc_named_reinit(); |
283 | tipc_port_reinit(); | 268 | tipc_port_reinit(); |
284 | 269 | ||
285 | if ((res = tipc_bearer_init()) || | 270 | if ((res = tipc_cltr_init()) || |
286 | (res = net_init()) || | ||
287 | (res = tipc_cltr_init()) || | ||
288 | (res = tipc_bclink_init())) { | 271 | (res = tipc_bclink_init())) { |
289 | return res; | 272 | return res; |
290 | } | 273 | } |
@@ -308,6 +291,6 @@ void tipc_net_stop(void) | |||
308 | tipc_bclink_stop(); | 291 | tipc_bclink_stop(); |
309 | net_stop(); | 292 | net_stop(); |
310 | write_unlock_bh(&tipc_net_lock); | 293 | write_unlock_bh(&tipc_net_lock); |
311 | info("Left network mode \n"); | 294 | info("Left network mode\n"); |
312 | } | 295 | } |
313 | 296 | ||
diff --git a/net/tipc/node.c b/net/tipc/node.c index 2c24e7d6d950..17cc394f424f 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c | |||
@@ -278,7 +278,7 @@ struct tipc_node *tipc_node_attach_link(struct link *l_ptr) | |||
278 | n_ptr->link_cnt++; | 278 | n_ptr->link_cnt++; |
279 | return n_ptr; | 279 | return n_ptr; |
280 | } | 280 | } |
281 | err("Attempt to establish second link on <%s> to %s \n", | 281 | err("Attempt to establish second link on <%s> to %s\n", |
282 | l_ptr->b_ptr->publ.name, | 282 | l_ptr->b_ptr->publ.name, |
283 | addr_string_fill(addr_string, l_ptr->addr)); | 283 | addr_string_fill(addr_string, l_ptr->addr)); |
284 | } | 284 | } |
diff --git a/net/tipc/ref.c b/net/tipc/ref.c index 414fc34b8bea..8dea66500cf5 100644 --- a/net/tipc/ref.c +++ b/net/tipc/ref.c | |||
@@ -153,11 +153,11 @@ void tipc_ref_table_stop(void) | |||
153 | 153 | ||
154 | u32 tipc_ref_acquire(void *object, spinlock_t **lock) | 154 | u32 tipc_ref_acquire(void *object, spinlock_t **lock) |
155 | { | 155 | { |
156 | struct reference *entry; | ||
157 | u32 index; | 156 | u32 index; |
158 | u32 index_mask; | 157 | u32 index_mask; |
159 | u32 next_plus_upper; | 158 | u32 next_plus_upper; |
160 | u32 ref; | 159 | u32 ref; |
160 | struct reference *entry = NULL; | ||
161 | 161 | ||
162 | if (!object) { | 162 | if (!object) { |
163 | err("Attempt to acquire reference to non-existent object\n"); | 163 | err("Attempt to acquire reference to non-existent object\n"); |
@@ -175,30 +175,36 @@ u32 tipc_ref_acquire(void *object, spinlock_t **lock) | |||
175 | index = tipc_ref_table.first_free; | 175 | index = tipc_ref_table.first_free; |
176 | entry = &(tipc_ref_table.entries[index]); | 176 | entry = &(tipc_ref_table.entries[index]); |
177 | index_mask = tipc_ref_table.index_mask; | 177 | index_mask = tipc_ref_table.index_mask; |
178 | /* take lock in case a previous user of entry still holds it */ | ||
179 | spin_lock_bh(&entry->lock); | ||
180 | next_plus_upper = entry->ref; | 178 | next_plus_upper = entry->ref; |
181 | tipc_ref_table.first_free = next_plus_upper & index_mask; | 179 | tipc_ref_table.first_free = next_plus_upper & index_mask; |
182 | ref = (next_plus_upper & ~index_mask) + index; | 180 | ref = (next_plus_upper & ~index_mask) + index; |
183 | entry->ref = ref; | ||
184 | entry->object = object; | ||
185 | *lock = &entry->lock; | ||
186 | } | 181 | } |
187 | else if (tipc_ref_table.init_point < tipc_ref_table.capacity) { | 182 | else if (tipc_ref_table.init_point < tipc_ref_table.capacity) { |
188 | index = tipc_ref_table.init_point++; | 183 | index = tipc_ref_table.init_point++; |
189 | entry = &(tipc_ref_table.entries[index]); | 184 | entry = &(tipc_ref_table.entries[index]); |
190 | spin_lock_init(&entry->lock); | 185 | spin_lock_init(&entry->lock); |
191 | spin_lock_bh(&entry->lock); | ||
192 | ref = tipc_ref_table.start_mask + index; | 186 | ref = tipc_ref_table.start_mask + index; |
193 | entry->ref = ref; | ||
194 | entry->object = object; | ||
195 | *lock = &entry->lock; | ||
196 | } | 187 | } |
197 | else { | 188 | else { |
198 | ref = 0; | 189 | ref = 0; |
199 | } | 190 | } |
200 | write_unlock_bh(&ref_table_lock); | 191 | write_unlock_bh(&ref_table_lock); |
201 | 192 | ||
193 | /* | ||
194 | * Grab the lock so no one else can modify this entry | ||
195 | * While we assign its ref value & object pointer | ||
196 | */ | ||
197 | if (entry) { | ||
198 | spin_lock_bh(&entry->lock); | ||
199 | entry->ref = ref; | ||
200 | entry->object = object; | ||
201 | *lock = &entry->lock; | ||
202 | /* | ||
203 | * keep it locked, the caller is responsible | ||
204 | * for unlocking this when they're done with it | ||
205 | */ | ||
206 | } | ||
207 | |||
202 | return ref; | 208 | return ref; |
203 | } | 209 | } |
204 | 210 | ||
diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 1ea64f09cc45..4b235fc1c70f 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c | |||
@@ -1322,8 +1322,10 @@ static u32 dispatch(struct tipc_port *tport, struct sk_buff *buf) | |||
1322 | if (!sock_owned_by_user(sk)) { | 1322 | if (!sock_owned_by_user(sk)) { |
1323 | res = filter_rcv(sk, buf); | 1323 | res = filter_rcv(sk, buf); |
1324 | } else { | 1324 | } else { |
1325 | sk_add_backlog(sk, buf); | 1325 | if (sk_add_backlog(sk, buf)) |
1326 | res = TIPC_OK; | 1326 | res = TIPC_ERR_OVERLOAD; |
1327 | else | ||
1328 | res = TIPC_OK; | ||
1327 | } | 1329 | } |
1328 | bh_unlock_sock(sk); | 1330 | bh_unlock_sock(sk); |
1329 | 1331 | ||
diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c index ac91f0dfa144..ff123e56114a 100644 --- a/net/tipc/subscr.c +++ b/net/tipc/subscr.c | |||
@@ -76,19 +76,6 @@ struct top_srv { | |||
76 | static struct top_srv topsrv = { 0 }; | 76 | static struct top_srv topsrv = { 0 }; |
77 | 77 | ||
78 | /** | 78 | /** |
79 | * htohl - convert value to endianness used by destination | ||
80 | * @in: value to convert | ||
81 | * @swap: non-zero if endianness must be reversed | ||
82 | * | ||
83 | * Returns converted value | ||
84 | */ | ||
85 | |||
86 | static u32 htohl(u32 in, int swap) | ||
87 | { | ||
88 | return swap ? swab32(in) : in; | ||
89 | } | ||
90 | |||
91 | /** | ||
92 | * subscr_send_event - send a message containing a tipc_event to the subscriber | 79 | * subscr_send_event - send a message containing a tipc_event to the subscriber |
93 | * | 80 | * |
94 | * Note: Must not hold subscriber's server port lock, since tipc_send() will | 81 | * Note: Must not hold subscriber's server port lock, since tipc_send() will |
@@ -107,11 +94,11 @@ static void subscr_send_event(struct subscription *sub, | |||
107 | msg_sect.iov_base = (void *)&sub->evt; | 94 | msg_sect.iov_base = (void *)&sub->evt; |
108 | msg_sect.iov_len = sizeof(struct tipc_event); | 95 | msg_sect.iov_len = sizeof(struct tipc_event); |
109 | 96 | ||
110 | sub->evt.event = htohl(event, sub->swap); | 97 | sub->evt.event = htonl(event); |
111 | sub->evt.found_lower = htohl(found_lower, sub->swap); | 98 | sub->evt.found_lower = htonl(found_lower); |
112 | sub->evt.found_upper = htohl(found_upper, sub->swap); | 99 | sub->evt.found_upper = htonl(found_upper); |
113 | sub->evt.port.ref = htohl(port_ref, sub->swap); | 100 | sub->evt.port.ref = htonl(port_ref); |
114 | sub->evt.port.node = htohl(node, sub->swap); | 101 | sub->evt.port.node = htonl(node); |
115 | tipc_send(sub->server_ref, 1, &msg_sect); | 102 | tipc_send(sub->server_ref, 1, &msg_sect); |
116 | } | 103 | } |
117 | 104 | ||
@@ -287,16 +274,23 @@ static void subscr_cancel(struct tipc_subscr *s, | |||
287 | { | 274 | { |
288 | struct subscription *sub; | 275 | struct subscription *sub; |
289 | struct subscription *sub_temp; | 276 | struct subscription *sub_temp; |
277 | __u32 type, lower, upper; | ||
290 | int found = 0; | 278 | int found = 0; |
291 | 279 | ||
292 | /* Find first matching subscription, exit if not found */ | 280 | /* Find first matching subscription, exit if not found */ |
293 | 281 | ||
282 | type = ntohl(s->seq.type); | ||
283 | lower = ntohl(s->seq.lower); | ||
284 | upper = ntohl(s->seq.upper); | ||
285 | |||
294 | list_for_each_entry_safe(sub, sub_temp, &subscriber->subscription_list, | 286 | list_for_each_entry_safe(sub, sub_temp, &subscriber->subscription_list, |
295 | subscription_list) { | 287 | subscription_list) { |
296 | if (!memcmp(s, &sub->evt.s, sizeof(struct tipc_subscr))) { | 288 | if ((type == sub->seq.type) && |
297 | found = 1; | 289 | (lower == sub->seq.lower) && |
298 | break; | 290 | (upper == sub->seq.upper)) { |
299 | } | 291 | found = 1; |
292 | break; | ||
293 | } | ||
300 | } | 294 | } |
301 | if (!found) | 295 | if (!found) |
302 | return; | 296 | return; |
@@ -325,16 +319,10 @@ static struct subscription *subscr_subscribe(struct tipc_subscr *s, | |||
325 | struct subscriber *subscriber) | 319 | struct subscriber *subscriber) |
326 | { | 320 | { |
327 | struct subscription *sub; | 321 | struct subscription *sub; |
328 | int swap; | ||
329 | |||
330 | /* Determine subscriber's endianness */ | ||
331 | |||
332 | swap = !(s->filter & (TIPC_SUB_PORTS | TIPC_SUB_SERVICE)); | ||
333 | 322 | ||
334 | /* Detect & process a subscription cancellation request */ | 323 | /* Detect & process a subscription cancellation request */ |
335 | 324 | ||
336 | if (s->filter & htohl(TIPC_SUB_CANCEL, swap)) { | 325 | if (ntohl(s->filter) & TIPC_SUB_CANCEL) { |
337 | s->filter &= ~htohl(TIPC_SUB_CANCEL, swap); | ||
338 | subscr_cancel(s, subscriber); | 326 | subscr_cancel(s, subscriber); |
339 | return NULL; | 327 | return NULL; |
340 | } | 328 | } |
@@ -359,11 +347,11 @@ static struct subscription *subscr_subscribe(struct tipc_subscr *s, | |||
359 | 347 | ||
360 | /* Initialize subscription object */ | 348 | /* Initialize subscription object */ |
361 | 349 | ||
362 | sub->seq.type = htohl(s->seq.type, swap); | 350 | sub->seq.type = ntohl(s->seq.type); |
363 | sub->seq.lower = htohl(s->seq.lower, swap); | 351 | sub->seq.lower = ntohl(s->seq.lower); |
364 | sub->seq.upper = htohl(s->seq.upper, swap); | 352 | sub->seq.upper = ntohl(s->seq.upper); |
365 | sub->timeout = htohl(s->timeout, swap); | 353 | sub->timeout = ntohl(s->timeout); |
366 | sub->filter = htohl(s->filter, swap); | 354 | sub->filter = ntohl(s->filter); |
367 | if ((!(sub->filter & TIPC_SUB_PORTS) == | 355 | if ((!(sub->filter & TIPC_SUB_PORTS) == |
368 | !(sub->filter & TIPC_SUB_SERVICE)) || | 356 | !(sub->filter & TIPC_SUB_SERVICE)) || |
369 | (sub->seq.lower > sub->seq.upper)) { | 357 | (sub->seq.lower > sub->seq.upper)) { |
@@ -376,7 +364,6 @@ static struct subscription *subscr_subscribe(struct tipc_subscr *s, | |||
376 | INIT_LIST_HEAD(&sub->nameseq_list); | 364 | INIT_LIST_HEAD(&sub->nameseq_list); |
377 | list_add(&sub->subscription_list, &subscriber->subscription_list); | 365 | list_add(&sub->subscription_list, &subscriber->subscription_list); |
378 | sub->server_ref = subscriber->port_ref; | 366 | sub->server_ref = subscriber->port_ref; |
379 | sub->swap = swap; | ||
380 | memcpy(&sub->evt.s, s, sizeof(struct tipc_subscr)); | 367 | memcpy(&sub->evt.s, s, sizeof(struct tipc_subscr)); |
381 | atomic_inc(&topsrv.subscription_count); | 368 | atomic_inc(&topsrv.subscription_count); |
382 | if (sub->timeout != TIPC_WAIT_FOREVER) { | 369 | if (sub->timeout != TIPC_WAIT_FOREVER) { |
diff --git a/net/tipc/subscr.h b/net/tipc/subscr.h index 45d89bf4d202..c20f496d95b2 100644 --- a/net/tipc/subscr.h +++ b/net/tipc/subscr.h | |||
@@ -53,7 +53,6 @@ typedef void (*tipc_subscr_event) (struct subscription *sub, | |||
53 | * @nameseq_list: adjacent subscriptions in name sequence's subscription list | 53 | * @nameseq_list: adjacent subscriptions in name sequence's subscription list |
54 | * @subscription_list: adjacent subscriptions in subscriber's subscription list | 54 | * @subscription_list: adjacent subscriptions in subscriber's subscription list |
55 | * @server_ref: object reference of server port associated with subscription | 55 | * @server_ref: object reference of server port associated with subscription |
56 | * @swap: indicates if subscriber uses opposite endianness in its messages | ||
57 | * @evt: template for events generated by subscription | 56 | * @evt: template for events generated by subscription |
58 | */ | 57 | */ |
59 | 58 | ||
@@ -66,7 +65,6 @@ struct subscription { | |||
66 | struct list_head nameseq_list; | 65 | struct list_head nameseq_list; |
67 | struct list_head subscription_list; | 66 | struct list_head subscription_list; |
68 | u32 server_ref; | 67 | u32 server_ref; |
69 | int swap; | ||
70 | struct tipc_event evt; | 68 | struct tipc_event evt; |
71 | }; | 69 | }; |
72 | 70 | ||
diff --git a/net/wimax/op-reset.c b/net/wimax/op-reset.c index 4dc82a54ba30..68bedf3e5443 100644 --- a/net/wimax/op-reset.c +++ b/net/wimax/op-reset.c | |||
@@ -110,7 +110,6 @@ int wimax_gnl_doit_reset(struct sk_buff *skb, struct genl_info *info) | |||
110 | { | 110 | { |
111 | int result, ifindex; | 111 | int result, ifindex; |
112 | struct wimax_dev *wimax_dev; | 112 | struct wimax_dev *wimax_dev; |
113 | struct device *dev; | ||
114 | 113 | ||
115 | d_fnstart(3, NULL, "(skb %p info %p)\n", skb, info); | 114 | d_fnstart(3, NULL, "(skb %p info %p)\n", skb, info); |
116 | result = -ENODEV; | 115 | result = -ENODEV; |
@@ -123,7 +122,6 @@ int wimax_gnl_doit_reset(struct sk_buff *skb, struct genl_info *info) | |||
123 | wimax_dev = wimax_dev_get_by_genl_info(info, ifindex); | 122 | wimax_dev = wimax_dev_get_by_genl_info(info, ifindex); |
124 | if (wimax_dev == NULL) | 123 | if (wimax_dev == NULL) |
125 | goto error_no_wimax_dev; | 124 | goto error_no_wimax_dev; |
126 | dev = wimax_dev_to_dev(wimax_dev); | ||
127 | /* Execute the operation and send the result back to user space */ | 125 | /* Execute the operation and send the result back to user space */ |
128 | result = wimax_reset(wimax_dev); | 126 | result = wimax_reset(wimax_dev); |
129 | dev_put(wimax_dev->net_dev); | 127 | dev_put(wimax_dev->net_dev); |
diff --git a/net/wimax/op-state-get.c b/net/wimax/op-state-get.c index 11ad3356eb56..aff8776e2d41 100644 --- a/net/wimax/op-state-get.c +++ b/net/wimax/op-state-get.c | |||
@@ -53,7 +53,6 @@ int wimax_gnl_doit_state_get(struct sk_buff *skb, struct genl_info *info) | |||
53 | { | 53 | { |
54 | int result, ifindex; | 54 | int result, ifindex; |
55 | struct wimax_dev *wimax_dev; | 55 | struct wimax_dev *wimax_dev; |
56 | struct device *dev; | ||
57 | 56 | ||
58 | d_fnstart(3, NULL, "(skb %p info %p)\n", skb, info); | 57 | d_fnstart(3, NULL, "(skb %p info %p)\n", skb, info); |
59 | result = -ENODEV; | 58 | result = -ENODEV; |
@@ -66,7 +65,6 @@ int wimax_gnl_doit_state_get(struct sk_buff *skb, struct genl_info *info) | |||
66 | wimax_dev = wimax_dev_get_by_genl_info(info, ifindex); | 65 | wimax_dev = wimax_dev_get_by_genl_info(info, ifindex); |
67 | if (wimax_dev == NULL) | 66 | if (wimax_dev == NULL) |
68 | goto error_no_wimax_dev; | 67 | goto error_no_wimax_dev; |
69 | dev = wimax_dev_to_dev(wimax_dev); | ||
70 | /* Execute the operation and send the result back to user space */ | 68 | /* Execute the operation and send the result back to user space */ |
71 | result = wimax_state_get(wimax_dev); | 69 | result = wimax_state_get(wimax_dev); |
72 | dev_put(wimax_dev->net_dev); | 70 | dev_put(wimax_dev->net_dev); |
diff --git a/net/x25/x25_dev.c b/net/x25/x25_dev.c index 3e1efe534645..52e304212241 100644 --- a/net/x25/x25_dev.c +++ b/net/x25/x25_dev.c | |||
@@ -53,7 +53,7 @@ static int x25_receive_data(struct sk_buff *skb, struct x25_neigh *nb) | |||
53 | if (!sock_owned_by_user(sk)) { | 53 | if (!sock_owned_by_user(sk)) { |
54 | queued = x25_process_rx_frame(sk, skb); | 54 | queued = x25_process_rx_frame(sk, skb); |
55 | } else { | 55 | } else { |
56 | sk_add_backlog(sk, skb); | 56 | queued = !sk_add_backlog(sk, skb); |
57 | } | 57 | } |
58 | bh_unlock_sock(sk); | 58 | bh_unlock_sock(sk); |
59 | sock_put(sk); | 59 | sock_put(sk); |
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 34a5ef8316e7..843e066649cb 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c | |||
@@ -1372,7 +1372,8 @@ static inline int xfrm_init_path(struct xfrm_dst *path, struct dst_entry *dst, | |||
1372 | return err; | 1372 | return err; |
1373 | } | 1373 | } |
1374 | 1374 | ||
1375 | static inline int xfrm_fill_dst(struct xfrm_dst *xdst, struct net_device *dev) | 1375 | static inline int xfrm_fill_dst(struct xfrm_dst *xdst, struct net_device *dev, |
1376 | struct flowi *fl) | ||
1376 | { | 1377 | { |
1377 | struct xfrm_policy_afinfo *afinfo = | 1378 | struct xfrm_policy_afinfo *afinfo = |
1378 | xfrm_policy_get_afinfo(xdst->u.dst.ops->family); | 1379 | xfrm_policy_get_afinfo(xdst->u.dst.ops->family); |
@@ -1381,7 +1382,7 @@ static inline int xfrm_fill_dst(struct xfrm_dst *xdst, struct net_device *dev) | |||
1381 | if (!afinfo) | 1382 | if (!afinfo) |
1382 | return -EINVAL; | 1383 | return -EINVAL; |
1383 | 1384 | ||
1384 | err = afinfo->fill_dst(xdst, dev); | 1385 | err = afinfo->fill_dst(xdst, dev, fl); |
1385 | 1386 | ||
1386 | xfrm_policy_put_afinfo(afinfo); | 1387 | xfrm_policy_put_afinfo(afinfo); |
1387 | 1388 | ||
@@ -1486,7 +1487,7 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy, | |||
1486 | for (dst_prev = dst0; dst_prev != dst; dst_prev = dst_prev->child) { | 1487 | for (dst_prev = dst0; dst_prev != dst; dst_prev = dst_prev->child) { |
1487 | struct xfrm_dst *xdst = (struct xfrm_dst *)dst_prev; | 1488 | struct xfrm_dst *xdst = (struct xfrm_dst *)dst_prev; |
1488 | 1489 | ||
1489 | err = xfrm_fill_dst(xdst, dev); | 1490 | err = xfrm_fill_dst(xdst, dev, fl); |
1490 | if (err) | 1491 | if (err) |
1491 | goto free_dst; | 1492 | goto free_dst; |
1492 | 1493 | ||