diff options
Diffstat (limited to 'net')
162 files changed, 2342 insertions, 933 deletions
diff --git a/net/9p/client.c b/net/9p/client.c index dd43a8289b0d..5bf5f227dbe0 100644 --- a/net/9p/client.c +++ b/net/9p/client.c | |||
@@ -60,9 +60,9 @@ static struct p9_req_t * | |||
60 | p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...); | 60 | p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...); |
61 | 61 | ||
62 | /** | 62 | /** |
63 | * v9fs_parse_options - parse mount options into session structure | 63 | * parse_options - parse mount options into client structure |
64 | * @options: options string passed from mount | 64 | * @opts: options string passed from mount |
65 | * @v9ses: existing v9fs session information | 65 | * @clnt: existing v9fs client information |
66 | * | 66 | * |
67 | * Return 0 upon success, -ERRNO upon failure | 67 | * Return 0 upon success, -ERRNO upon failure |
68 | */ | 68 | */ |
@@ -117,9 +117,6 @@ static int parse_opts(char *opts, struct p9_client *clnt) | |||
117 | } | 117 | } |
118 | } | 118 | } |
119 | 119 | ||
120 | if (!clnt->trans_mod) | ||
121 | clnt->trans_mod = v9fs_get_default_trans(); | ||
122 | |||
123 | kfree(options); | 120 | kfree(options); |
124 | return ret; | 121 | return ret; |
125 | } | 122 | } |
@@ -235,7 +232,7 @@ EXPORT_SYMBOL(p9_tag_lookup); | |||
235 | 232 | ||
236 | /** | 233 | /** |
237 | * p9_tag_init - setup tags structure and contents | 234 | * p9_tag_init - setup tags structure and contents |
238 | * @tags: tags structure from the client struct | 235 | * @c: v9fs client struct |
239 | * | 236 | * |
240 | * This initializes the tags structure for each client instance. | 237 | * This initializes the tags structure for each client instance. |
241 | * | 238 | * |
@@ -261,7 +258,7 @@ error: | |||
261 | 258 | ||
262 | /** | 259 | /** |
263 | * p9_tag_cleanup - cleans up tags structure and reclaims resources | 260 | * p9_tag_cleanup - cleans up tags structure and reclaims resources |
264 | * @tags: tags structure from the client struct | 261 | * @c: v9fs client struct |
265 | * | 262 | * |
266 | * This frees resources associated with the tags structure | 263 | * This frees resources associated with the tags structure |
267 | * | 264 | * |
@@ -414,14 +411,9 @@ static int p9_check_errors(struct p9_client *c, struct p9_req_t *req) | |||
414 | if (c->dotu) | 411 | if (c->dotu) |
415 | err = -ecode; | 412 | err = -ecode; |
416 | 413 | ||
417 | if (!err) { | 414 | if (!err || !IS_ERR_VALUE(err)) |
418 | err = p9_errstr2errno(ename, strlen(ename)); | 415 | err = p9_errstr2errno(ename, strlen(ename)); |
419 | 416 | ||
420 | /* string match failed */ | ||
421 | if (!err) | ||
422 | err = -ESERVERFAULT; | ||
423 | } | ||
424 | |||
425 | P9_DPRINTK(P9_DEBUG_9P, "<<< RERROR (%d) %s\n", -ecode, ename); | 417 | P9_DPRINTK(P9_DEBUG_9P, "<<< RERROR (%d) %s\n", -ecode, ename); |
426 | 418 | ||
427 | kfree(ename); | 419 | kfree(ename); |
@@ -433,8 +425,8 @@ static int p9_check_errors(struct p9_client *c, struct p9_req_t *req) | |||
433 | 425 | ||
434 | /** | 426 | /** |
435 | * p9_client_flush - flush (cancel) a request | 427 | * p9_client_flush - flush (cancel) a request |
436 | * c: client state | 428 | * @c: client state |
437 | * req: request to cancel | 429 | * @oldreq: request to cancel |
438 | * | 430 | * |
439 | * This sents a flush for a particular requests and links | 431 | * This sents a flush for a particular requests and links |
440 | * the flush request to the original request. The current | 432 | * the flush request to the original request. The current |
@@ -689,6 +681,9 @@ struct p9_client *p9_client_create(const char *dev_name, char *options) | |||
689 | if (err < 0) | 681 | if (err < 0) |
690 | goto error; | 682 | goto error; |
691 | 683 | ||
684 | if (!clnt->trans_mod) | ||
685 | clnt->trans_mod = v9fs_get_default_trans(); | ||
686 | |||
692 | if (clnt->trans_mod == NULL) { | 687 | if (clnt->trans_mod == NULL) { |
693 | err = -EPROTONOSUPPORT; | 688 | err = -EPROTONOSUPPORT; |
694 | P9_DPRINTK(P9_DEBUG_ERROR, | 689 | P9_DPRINTK(P9_DEBUG_ERROR, |
@@ -1098,7 +1093,6 @@ p9_client_read(struct p9_fid *fid, char *data, char __user *udata, u64 offset, | |||
1098 | 1093 | ||
1099 | if (data) { | 1094 | if (data) { |
1100 | memmove(data, dataptr, count); | 1095 | memmove(data, dataptr, count); |
1101 | data += count; | ||
1102 | } | 1096 | } |
1103 | 1097 | ||
1104 | if (udata) { | 1098 | if (udata) { |
@@ -1192,9 +1186,9 @@ struct p9_wstat *p9_client_stat(struct p9_fid *fid) | |||
1192 | 1186 | ||
1193 | err = p9pdu_readf(req->rc, clnt->dotu, "wS", &ignored, ret); | 1187 | err = p9pdu_readf(req->rc, clnt->dotu, "wS", &ignored, ret); |
1194 | if (err) { | 1188 | if (err) { |
1195 | ret = ERR_PTR(err); | ||
1196 | p9pdu_dump(1, req->rc); | 1189 | p9pdu_dump(1, req->rc); |
1197 | goto free_and_error; | 1190 | p9_free_req(clnt, req); |
1191 | goto error; | ||
1198 | } | 1192 | } |
1199 | 1193 | ||
1200 | P9_DPRINTK(P9_DEBUG_9P, | 1194 | P9_DPRINTK(P9_DEBUG_9P, |
@@ -1211,8 +1205,6 @@ struct p9_wstat *p9_client_stat(struct p9_fid *fid) | |||
1211 | p9_free_req(clnt, req); | 1205 | p9_free_req(clnt, req); |
1212 | return ret; | 1206 | return ret; |
1213 | 1207 | ||
1214 | free_and_error: | ||
1215 | p9_free_req(clnt, req); | ||
1216 | error: | 1208 | error: |
1217 | kfree(ret); | 1209 | kfree(ret); |
1218 | return ERR_PTR(err); | 1210 | return ERR_PTR(err); |
diff --git a/net/9p/error.c b/net/9p/error.c index fdebe4314062..52518512a93e 100644 --- a/net/9p/error.c +++ b/net/9p/error.c | |||
@@ -239,7 +239,7 @@ int p9_errstr2errno(char *errstr, int len) | |||
239 | errstr[len] = 0; | 239 | errstr[len] = 0; |
240 | printk(KERN_ERR "%s: server reported unknown error %s\n", | 240 | printk(KERN_ERR "%s: server reported unknown error %s\n", |
241 | __func__, errstr); | 241 | __func__, errstr); |
242 | errno = 1; | 242 | errno = ESERVERFAULT; |
243 | } | 243 | } |
244 | 244 | ||
245 | return -errno; | 245 | return -errno; |
diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c index a2a1814c7a8d..8d934dd7fd54 100644 --- a/net/9p/trans_fd.c +++ b/net/9p/trans_fd.c | |||
@@ -119,8 +119,8 @@ struct p9_poll_wait { | |||
119 | * @wpos: write position for current frame | 119 | * @wpos: write position for current frame |
120 | * @wsize: amount of data to write for current frame | 120 | * @wsize: amount of data to write for current frame |
121 | * @wbuf: current write buffer | 121 | * @wbuf: current write buffer |
122 | * @poll_pending_link: pending links to be polled per conn | ||
122 | * @poll_wait: array of wait_q's for various worker threads | 123 | * @poll_wait: array of wait_q's for various worker threads |
123 | * @poll_waddr: ???? | ||
124 | * @pt: poll state | 124 | * @pt: poll state |
125 | * @rq: current read work | 125 | * @rq: current read work |
126 | * @wq: current write work | 126 | * @wq: current write work |
@@ -700,9 +700,9 @@ static int p9_fd_cancel(struct p9_client *client, struct p9_req_t *req) | |||
700 | } | 700 | } |
701 | 701 | ||
702 | /** | 702 | /** |
703 | * parse_options - parse mount options into session structure | 703 | * parse_opts - parse mount options into p9_fd_opts structure |
704 | * @options: options string passed from mount | 704 | * @params: options string passed from mount |
705 | * @opts: transport-specific structure to parse options into | 705 | * @opts: fd transport-specific structure to parse options into |
706 | * | 706 | * |
707 | * Returns 0 upon success, -ERRNO upon failure | 707 | * Returns 0 upon success, -ERRNO upon failure |
708 | */ | 708 | */ |
@@ -735,12 +735,14 @@ static int parse_opts(char *params, struct p9_fd_opts *opts) | |||
735 | if (!*p) | 735 | if (!*p) |
736 | continue; | 736 | continue; |
737 | token = match_token(p, tokens, args); | 737 | token = match_token(p, tokens, args); |
738 | r = match_int(&args[0], &option); | 738 | if (token != Opt_err) { |
739 | if (r < 0) { | 739 | r = match_int(&args[0], &option); |
740 | P9_DPRINTK(P9_DEBUG_ERROR, | 740 | if (r < 0) { |
741 | "integer field, but no integer?\n"); | 741 | P9_DPRINTK(P9_DEBUG_ERROR, |
742 | ret = r; | 742 | "integer field, but no integer?\n"); |
743 | continue; | 743 | ret = r; |
744 | continue; | ||
745 | } | ||
744 | } | 746 | } |
745 | switch (token) { | 747 | switch (token) { |
746 | case Opt_port: | 748 | case Opt_port: |
diff --git a/net/9p/trans_rdma.c b/net/9p/trans_rdma.c index ac4990041ebb..65cb29db03f8 100644 --- a/net/9p/trans_rdma.c +++ b/net/9p/trans_rdma.c | |||
@@ -67,14 +67,15 @@ | |||
67 | * @pd: Protection Domain pointer | 67 | * @pd: Protection Domain pointer |
68 | * @qp: Queue Pair pointer | 68 | * @qp: Queue Pair pointer |
69 | * @cq: Completion Queue pointer | 69 | * @cq: Completion Queue pointer |
70 | * @dm_mr: DMA Memory Region pointer | ||
70 | * @lkey: The local access only memory region key | 71 | * @lkey: The local access only memory region key |
71 | * @timeout: Number of uSecs to wait for connection management events | 72 | * @timeout: Number of uSecs to wait for connection management events |
72 | * @sq_depth: The depth of the Send Queue | 73 | * @sq_depth: The depth of the Send Queue |
73 | * @sq_sem: Semaphore for the SQ | 74 | * @sq_sem: Semaphore for the SQ |
74 | * @rq_depth: The depth of the Receive Queue. | 75 | * @rq_depth: The depth of the Receive Queue. |
76 | * @rq_count: Count of requests in the Receive Queue. | ||
75 | * @addr: The remote peer's address | 77 | * @addr: The remote peer's address |
76 | * @req_lock: Protects the active request list | 78 | * @req_lock: Protects the active request list |
77 | * @send_wait: Wait list when the SQ fills up | ||
78 | * @cm_done: Completion event for connection management tracking | 79 | * @cm_done: Completion event for connection management tracking |
79 | */ | 80 | */ |
80 | struct p9_trans_rdma { | 81 | struct p9_trans_rdma { |
@@ -154,9 +155,9 @@ static match_table_t tokens = { | |||
154 | }; | 155 | }; |
155 | 156 | ||
156 | /** | 157 | /** |
157 | * parse_options - parse mount options into session structure | 158 | * parse_opts - parse mount options into rdma options structure |
158 | * @options: options string passed from mount | 159 | * @params: options string passed from mount |
159 | * @opts: transport-specific structure to parse options into | 160 | * @opts: rdma transport-specific structure to parse options into |
160 | * | 161 | * |
161 | * Returns 0 upon success, -ERRNO upon failure | 162 | * Returns 0 upon success, -ERRNO upon failure |
162 | */ | 163 | */ |
diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c index a49484e67e1d..9bf0b737aa51 100644 --- a/net/9p/trans_virtio.c +++ b/net/9p/trans_virtio.c | |||
@@ -57,11 +57,9 @@ static int chan_index; | |||
57 | * @initialized: whether the channel is initialized | 57 | * @initialized: whether the channel is initialized |
58 | * @inuse: whether the channel is in use | 58 | * @inuse: whether the channel is in use |
59 | * @lock: protects multiple elements within this structure | 59 | * @lock: protects multiple elements within this structure |
60 | * @client: client instance | ||
60 | * @vdev: virtio dev associated with this channel | 61 | * @vdev: virtio dev associated with this channel |
61 | * @vq: virtio queue associated with this channel | 62 | * @vq: virtio queue associated with this channel |
62 | * @tagpool: accounting for tag ids (and request slots) | ||
63 | * @reqs: array of request slots | ||
64 | * @max_tag: current number of request_slots allocated | ||
65 | * @sg: scatter gather list which is used to pack a request (protected?) | 63 | * @sg: scatter gather list which is used to pack a request (protected?) |
66 | * | 64 | * |
67 | * We keep all per-channel information in a structure. | 65 | * We keep all per-channel information in a structure. |
@@ -92,7 +90,7 @@ static unsigned int rest_of_page(void *data) | |||
92 | 90 | ||
93 | /** | 91 | /** |
94 | * p9_virtio_close - reclaim resources of a channel | 92 | * p9_virtio_close - reclaim resources of a channel |
95 | * @trans: transport state | 93 | * @client: client instance |
96 | * | 94 | * |
97 | * This reclaims a channel by freeing its resources and | 95 | * This reclaims a channel by freeing its resources and |
98 | * reseting its inuse flag. | 96 | * reseting its inuse flag. |
@@ -181,9 +179,8 @@ static int p9_virtio_cancel(struct p9_client *client, struct p9_req_t *req) | |||
181 | 179 | ||
182 | /** | 180 | /** |
183 | * p9_virtio_request - issue a request | 181 | * p9_virtio_request - issue a request |
184 | * @t: transport state | 182 | * @client: client instance issuing the request |
185 | * @tc: &p9_fcall request to transmit | 183 | * @req: request to be issued |
186 | * @rc: &p9_fcall to put reponse into | ||
187 | * | 184 | * |
188 | */ | 185 | */ |
189 | 186 | ||
diff --git a/net/appletalk/atalk_proc.c b/net/appletalk/atalk_proc.c index fd8e0847b254..80caad1a31a5 100644 --- a/net/appletalk/atalk_proc.c +++ b/net/appletalk/atalk_proc.c | |||
@@ -204,8 +204,8 @@ static int atalk_seq_socket_show(struct seq_file *seq, void *v) | |||
204 | "%02X %d\n", | 204 | "%02X %d\n", |
205 | s->sk_type, ntohs(at->src_net), at->src_node, at->src_port, | 205 | s->sk_type, ntohs(at->src_net), at->src_node, at->src_port, |
206 | ntohs(at->dest_net), at->dest_node, at->dest_port, | 206 | ntohs(at->dest_net), at->dest_node, at->dest_port, |
207 | atomic_read(&s->sk_wmem_alloc), | 207 | sk_wmem_alloc_get(s), |
208 | atomic_read(&s->sk_rmem_alloc), | 208 | sk_rmem_alloc_get(s), |
209 | s->sk_state, SOCK_INODE(s->sk_socket)->i_uid); | 209 | s->sk_state, SOCK_INODE(s->sk_socket)->i_uid); |
210 | out: | 210 | out: |
211 | return 0; | 211 | return 0; |
diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c index b603cbacdc58..875eda5dbad7 100644 --- a/net/appletalk/ddp.c +++ b/net/appletalk/ddp.c | |||
@@ -54,6 +54,7 @@ | |||
54 | #include <linux/capability.h> | 54 | #include <linux/capability.h> |
55 | #include <linux/module.h> | 55 | #include <linux/module.h> |
56 | #include <linux/if_arp.h> | 56 | #include <linux/if_arp.h> |
57 | #include <linux/smp_lock.h> | ||
57 | #include <linux/termios.h> /* For TIOCOUTQ/INQ */ | 58 | #include <linux/termios.h> /* For TIOCOUTQ/INQ */ |
58 | #include <net/datalink.h> | 59 | #include <net/datalink.h> |
59 | #include <net/psnap.h> | 60 | #include <net/psnap.h> |
@@ -162,8 +163,7 @@ static void atalk_destroy_timer(unsigned long data) | |||
162 | { | 163 | { |
163 | struct sock *sk = (struct sock *)data; | 164 | struct sock *sk = (struct sock *)data; |
164 | 165 | ||
165 | if (atomic_read(&sk->sk_wmem_alloc) || | 166 | if (sk_has_allocations(sk)) { |
166 | atomic_read(&sk->sk_rmem_alloc)) { | ||
167 | sk->sk_timer.expires = jiffies + SOCK_DESTROY_TIME; | 167 | sk->sk_timer.expires = jiffies + SOCK_DESTROY_TIME; |
168 | add_timer(&sk->sk_timer); | 168 | add_timer(&sk->sk_timer); |
169 | } else | 169 | } else |
@@ -175,8 +175,7 @@ static inline void atalk_destroy_socket(struct sock *sk) | |||
175 | atalk_remove_socket(sk); | 175 | atalk_remove_socket(sk); |
176 | skb_queue_purge(&sk->sk_receive_queue); | 176 | skb_queue_purge(&sk->sk_receive_queue); |
177 | 177 | ||
178 | if (atomic_read(&sk->sk_wmem_alloc) || | 178 | if (sk_has_allocations(sk)) { |
179 | atomic_read(&sk->sk_rmem_alloc)) { | ||
180 | setup_timer(&sk->sk_timer, atalk_destroy_timer, | 179 | setup_timer(&sk->sk_timer, atalk_destroy_timer, |
181 | (unsigned long)sk); | 180 | (unsigned long)sk); |
182 | sk->sk_timer.expires = jiffies + SOCK_DESTROY_TIME; | 181 | sk->sk_timer.expires = jiffies + SOCK_DESTROY_TIME; |
@@ -1239,6 +1238,7 @@ static int atalk_getname(struct socket *sock, struct sockaddr *uaddr, | |||
1239 | return -ENOBUFS; | 1238 | return -ENOBUFS; |
1240 | 1239 | ||
1241 | *uaddr_len = sizeof(struct sockaddr_at); | 1240 | *uaddr_len = sizeof(struct sockaddr_at); |
1241 | memset(&sat.sat_zero, 0, sizeof(sat.sat_zero)); | ||
1242 | 1242 | ||
1243 | if (peer) { | 1243 | if (peer) { |
1244 | if (sk->sk_state != TCP_ESTABLISHED) | 1244 | if (sk->sk_state != TCP_ESTABLISHED) |
@@ -1750,8 +1750,7 @@ static int atalk_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
1750 | switch (cmd) { | 1750 | switch (cmd) { |
1751 | /* Protocol layer */ | 1751 | /* Protocol layer */ |
1752 | case TIOCOUTQ: { | 1752 | case TIOCOUTQ: { |
1753 | long amount = sk->sk_sndbuf - | 1753 | long amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk); |
1754 | atomic_read(&sk->sk_wmem_alloc); | ||
1755 | 1754 | ||
1756 | if (amount < 0) | 1755 | if (amount < 0) |
1757 | amount = 0; | 1756 | amount = 0; |
diff --git a/net/atm/common.c b/net/atm/common.c index d34edbe754c8..8c4d843eb17f 100644 --- a/net/atm/common.c +++ b/net/atm/common.c | |||
@@ -62,15 +62,15 @@ static struct sk_buff *alloc_tx(struct atm_vcc *vcc,unsigned int size) | |||
62 | struct sk_buff *skb; | 62 | struct sk_buff *skb; |
63 | struct sock *sk = sk_atm(vcc); | 63 | struct sock *sk = sk_atm(vcc); |
64 | 64 | ||
65 | if (atomic_read(&sk->sk_wmem_alloc) && !atm_may_send(vcc, size)) { | 65 | if (sk_wmem_alloc_get(sk) && !atm_may_send(vcc, size)) { |
66 | pr_debug("Sorry: wmem_alloc = %d, size = %d, sndbuf = %d\n", | 66 | pr_debug("Sorry: wmem_alloc = %d, size = %d, sndbuf = %d\n", |
67 | atomic_read(&sk->sk_wmem_alloc), size, | 67 | sk_wmem_alloc_get(sk), size, |
68 | sk->sk_sndbuf); | 68 | sk->sk_sndbuf); |
69 | return NULL; | 69 | return NULL; |
70 | } | 70 | } |
71 | while (!(skb = alloc_skb(size,GFP_KERNEL))) schedule(); | 71 | while (!(skb = alloc_skb(size, GFP_KERNEL))) |
72 | pr_debug("AlTx %d += %d\n", atomic_read(&sk->sk_wmem_alloc), | 72 | schedule(); |
73 | skb->truesize); | 73 | pr_debug("AlTx %d += %d\n", sk_wmem_alloc_get(sk), skb->truesize); |
74 | atomic_add(skb->truesize, &sk->sk_wmem_alloc); | 74 | atomic_add(skb->truesize, &sk->sk_wmem_alloc); |
75 | return skb; | 75 | return skb; |
76 | } | 76 | } |
@@ -92,7 +92,7 @@ static void vcc_sock_destruct(struct sock *sk) | |||
92 | static void vcc_def_wakeup(struct sock *sk) | 92 | static void vcc_def_wakeup(struct sock *sk) |
93 | { | 93 | { |
94 | read_lock(&sk->sk_callback_lock); | 94 | read_lock(&sk->sk_callback_lock); |
95 | if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) | 95 | if (sk_has_sleeper(sk)) |
96 | wake_up(sk->sk_sleep); | 96 | wake_up(sk->sk_sleep); |
97 | read_unlock(&sk->sk_callback_lock); | 97 | read_unlock(&sk->sk_callback_lock); |
98 | } | 98 | } |
@@ -110,7 +110,7 @@ static void vcc_write_space(struct sock *sk) | |||
110 | read_lock(&sk->sk_callback_lock); | 110 | read_lock(&sk->sk_callback_lock); |
111 | 111 | ||
112 | if (vcc_writable(sk)) { | 112 | if (vcc_writable(sk)) { |
113 | if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) | 113 | if (sk_has_sleeper(sk)) |
114 | wake_up_interruptible(sk->sk_sleep); | 114 | wake_up_interruptible(sk->sk_sleep); |
115 | 115 | ||
116 | sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); | 116 | sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); |
@@ -145,7 +145,7 @@ int vcc_create(struct net *net, struct socket *sock, int protocol, int family) | |||
145 | memset(&vcc->local,0,sizeof(struct sockaddr_atmsvc)); | 145 | memset(&vcc->local,0,sizeof(struct sockaddr_atmsvc)); |
146 | memset(&vcc->remote,0,sizeof(struct sockaddr_atmsvc)); | 146 | memset(&vcc->remote,0,sizeof(struct sockaddr_atmsvc)); |
147 | vcc->qos.txtp.max_sdu = 1 << 16; /* for meta VCs */ | 147 | vcc->qos.txtp.max_sdu = 1 << 16; /* for meta VCs */ |
148 | atomic_set(&sk->sk_wmem_alloc, 0); | 148 | atomic_set(&sk->sk_wmem_alloc, 1); |
149 | atomic_set(&sk->sk_rmem_alloc, 0); | 149 | atomic_set(&sk->sk_rmem_alloc, 0); |
150 | vcc->push = NULL; | 150 | vcc->push = NULL; |
151 | vcc->pop = NULL; | 151 | vcc->pop = NULL; |
@@ -594,7 +594,7 @@ unsigned int vcc_poll(struct file *file, struct socket *sock, poll_table *wait) | |||
594 | struct atm_vcc *vcc; | 594 | struct atm_vcc *vcc; |
595 | unsigned int mask; | 595 | unsigned int mask; |
596 | 596 | ||
597 | poll_wait(file, sk->sk_sleep, wait); | 597 | sock_poll_wait(file, sk->sk_sleep, wait); |
598 | mask = 0; | 598 | mask = 0; |
599 | 599 | ||
600 | vcc = ATM_SD(sock); | 600 | vcc = ATM_SD(sock); |
diff --git a/net/atm/ioctl.c b/net/atm/ioctl.c index 76ed3c8d26e6..4da8892ced5f 100644 --- a/net/atm/ioctl.c +++ b/net/atm/ioctl.c | |||
@@ -63,8 +63,7 @@ static int do_vcc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg | |||
63 | error = -EINVAL; | 63 | error = -EINVAL; |
64 | goto done; | 64 | goto done; |
65 | } | 65 | } |
66 | error = put_user(sk->sk_sndbuf - | 66 | error = put_user(sk->sk_sndbuf - sk_wmem_alloc_get(sk), |
67 | atomic_read(&sk->sk_wmem_alloc), | ||
68 | (int __user *) argp) ? -EFAULT : 0; | 67 | (int __user *) argp) ? -EFAULT : 0; |
69 | goto done; | 68 | goto done; |
70 | case SIOCINQ: | 69 | case SIOCINQ: |
diff --git a/net/atm/proc.c b/net/atm/proc.c index e7b3b273907d..38de5ff61ecd 100644 --- a/net/atm/proc.c +++ b/net/atm/proc.c | |||
@@ -204,8 +204,8 @@ static void vcc_info(struct seq_file *seq, struct atm_vcc *vcc) | |||
204 | seq_printf(seq, "%3d", sk->sk_family); | 204 | seq_printf(seq, "%3d", sk->sk_family); |
205 | } | 205 | } |
206 | seq_printf(seq, " %04lx %5d %7d/%7d %7d/%7d [%d]\n", vcc->flags, sk->sk_err, | 206 | seq_printf(seq, " %04lx %5d %7d/%7d %7d/%7d [%d]\n", vcc->flags, sk->sk_err, |
207 | atomic_read(&sk->sk_wmem_alloc), sk->sk_sndbuf, | 207 | sk_wmem_alloc_get(sk), sk->sk_sndbuf, |
208 | atomic_read(&sk->sk_rmem_alloc), sk->sk_rcvbuf, | 208 | sk_rmem_alloc_get(sk), sk->sk_rcvbuf, |
209 | atomic_read(&sk->sk_refcnt)); | 209 | atomic_read(&sk->sk_refcnt)); |
210 | } | 210 | } |
211 | 211 | ||
diff --git a/net/atm/raw.c b/net/atm/raw.c index b0a2d8cb6744..cbfcc71a17b1 100644 --- a/net/atm/raw.c +++ b/net/atm/raw.c | |||
@@ -33,7 +33,7 @@ static void atm_pop_raw(struct atm_vcc *vcc,struct sk_buff *skb) | |||
33 | struct sock *sk = sk_atm(vcc); | 33 | struct sock *sk = sk_atm(vcc); |
34 | 34 | ||
35 | pr_debug("APopR (%d) %d -= %d\n", vcc->vci, | 35 | pr_debug("APopR (%d) %d -= %d\n", vcc->vci, |
36 | atomic_read(&sk->sk_wmem_alloc), skb->truesize); | 36 | sk_wmem_alloc_get(sk), skb->truesize); |
37 | atomic_sub(skb->truesize, &sk->sk_wmem_alloc); | 37 | atomic_sub(skb->truesize, &sk->sk_wmem_alloc); |
38 | dev_kfree_skb_any(skb); | 38 | dev_kfree_skb_any(skb); |
39 | sk->sk_write_space(sk); | 39 | sk->sk_write_space(sk); |
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c index fd9d06f291dc..da0f64f82b57 100644 --- a/net/ax25/af_ax25.c +++ b/net/ax25/af_ax25.c | |||
@@ -330,8 +330,7 @@ void ax25_destroy_socket(ax25_cb *ax25) | |||
330 | } | 330 | } |
331 | 331 | ||
332 | if (ax25->sk != NULL) { | 332 | if (ax25->sk != NULL) { |
333 | if (atomic_read(&ax25->sk->sk_wmem_alloc) || | 333 | if (sk_has_allocations(ax25->sk)) { |
334 | atomic_read(&ax25->sk->sk_rmem_alloc)) { | ||
335 | /* Defer: outstanding buffers */ | 334 | /* Defer: outstanding buffers */ |
336 | setup_timer(&ax25->dtimer, ax25_destroy_timer, | 335 | setup_timer(&ax25->dtimer, ax25_destroy_timer, |
337 | (unsigned long)ax25); | 336 | (unsigned long)ax25); |
@@ -1691,7 +1690,8 @@ static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
1691 | switch (cmd) { | 1690 | switch (cmd) { |
1692 | case TIOCOUTQ: { | 1691 | case TIOCOUTQ: { |
1693 | long amount; | 1692 | long amount; |
1694 | amount = sk->sk_sndbuf - atomic_read(&sk->sk_wmem_alloc); | 1693 | |
1694 | amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk); | ||
1695 | if (amount < 0) | 1695 | if (amount < 0) |
1696 | amount = 0; | 1696 | amount = 0; |
1697 | res = put_user(amount, (int __user *)argp); | 1697 | res = put_user(amount, (int __user *)argp); |
@@ -1781,8 +1781,8 @@ static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
1781 | ax25_info.idletimer = ax25_display_timer(&ax25->idletimer) / (60 * HZ); | 1781 | ax25_info.idletimer = ax25_display_timer(&ax25->idletimer) / (60 * HZ); |
1782 | ax25_info.n2count = ax25->n2count; | 1782 | ax25_info.n2count = ax25->n2count; |
1783 | ax25_info.state = ax25->state; | 1783 | ax25_info.state = ax25->state; |
1784 | ax25_info.rcv_q = atomic_read(&sk->sk_rmem_alloc); | 1784 | ax25_info.rcv_q = sk_wmem_alloc_get(sk); |
1785 | ax25_info.snd_q = atomic_read(&sk->sk_wmem_alloc); | 1785 | ax25_info.snd_q = sk_rmem_alloc_get(sk); |
1786 | ax25_info.vs = ax25->vs; | 1786 | ax25_info.vs = ax25->vs; |
1787 | ax25_info.vr = ax25->vr; | 1787 | ax25_info.vr = ax25->vr; |
1788 | ax25_info.va = ax25->va; | 1788 | ax25_info.va = ax25->va; |
@@ -1922,8 +1922,8 @@ static int ax25_info_show(struct seq_file *seq, void *v) | |||
1922 | 1922 | ||
1923 | if (ax25->sk != NULL) { | 1923 | if (ax25->sk != NULL) { |
1924 | seq_printf(seq, " %d %d %lu\n", | 1924 | seq_printf(seq, " %d %d %lu\n", |
1925 | atomic_read(&ax25->sk->sk_wmem_alloc), | 1925 | sk_wmem_alloc_get(ax25->sk), |
1926 | atomic_read(&ax25->sk->sk_rmem_alloc), | 1926 | sk_rmem_alloc_get(ax25->sk), |
1927 | sock_i_ino(ax25->sk)); | 1927 | sock_i_ino(ax25->sk)); |
1928 | } else { | 1928 | } else { |
1929 | seq_puts(seq, " * * *\n"); | 1929 | seq_puts(seq, " * * *\n"); |
diff --git a/net/ax25/ax25_in.c b/net/ax25/ax25_in.c index 5f1d2107a1dd..de56d3983de0 100644 --- a/net/ax25/ax25_in.c +++ b/net/ax25/ax25_in.c | |||
@@ -437,8 +437,7 @@ free: | |||
437 | int ax25_kiss_rcv(struct sk_buff *skb, struct net_device *dev, | 437 | int ax25_kiss_rcv(struct sk_buff *skb, struct net_device *dev, |
438 | struct packet_type *ptype, struct net_device *orig_dev) | 438 | struct packet_type *ptype, struct net_device *orig_dev) |
439 | { | 439 | { |
440 | skb->sk = NULL; /* Initially we don't know who it's for */ | 440 | skb_orphan(skb); |
441 | skb->destructor = NULL; /* Who initializes this, dammit?! */ | ||
442 | 441 | ||
443 | if (!net_eq(dev_net(dev), &init_net)) { | 442 | if (!net_eq(dev_net(dev), &init_net)) { |
444 | kfree_skb(skb); | 443 | kfree_skb(skb); |
diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index 02b9baa1930b..0250e0600150 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c | |||
@@ -337,7 +337,7 @@ int bt_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
337 | if (sk->sk_state == BT_LISTEN) | 337 | if (sk->sk_state == BT_LISTEN) |
338 | return -EINVAL; | 338 | return -EINVAL; |
339 | 339 | ||
340 | amount = sk->sk_sndbuf - atomic_read(&sk->sk_wmem_alloc); | 340 | amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk); |
341 | if (amount < 0) | 341 | if (amount < 0) |
342 | amount = 0; | 342 | amount = 0; |
343 | err = put_user(amount, (int __user *) arg); | 343 | err = put_user(amount, (int __user *) arg); |
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index e50566ebf9f9..94b3388c188b 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c | |||
@@ -2080,28 +2080,41 @@ static CLASS_ATTR(rfcomm_dlc, S_IRUGO, rfcomm_dlc_sysfs_show, NULL); | |||
2080 | /* ---- Initialization ---- */ | 2080 | /* ---- Initialization ---- */ |
2081 | static int __init rfcomm_init(void) | 2081 | static int __init rfcomm_init(void) |
2082 | { | 2082 | { |
2083 | int ret; | ||
2084 | |||
2083 | l2cap_load(); | 2085 | l2cap_load(); |
2084 | 2086 | ||
2085 | hci_register_cb(&rfcomm_cb); | 2087 | hci_register_cb(&rfcomm_cb); |
2086 | 2088 | ||
2087 | rfcomm_thread = kthread_run(rfcomm_run, NULL, "krfcommd"); | 2089 | rfcomm_thread = kthread_run(rfcomm_run, NULL, "krfcommd"); |
2088 | if (IS_ERR(rfcomm_thread)) { | 2090 | if (IS_ERR(rfcomm_thread)) { |
2089 | hci_unregister_cb(&rfcomm_cb); | 2091 | ret = PTR_ERR(rfcomm_thread); |
2090 | return PTR_ERR(rfcomm_thread); | 2092 | goto out_thread; |
2091 | } | 2093 | } |
2092 | 2094 | ||
2093 | if (class_create_file(bt_class, &class_attr_rfcomm_dlc) < 0) | 2095 | if (class_create_file(bt_class, &class_attr_rfcomm_dlc) < 0) |
2094 | BT_ERR("Failed to create RFCOMM info file"); | 2096 | BT_ERR("Failed to create RFCOMM info file"); |
2095 | 2097 | ||
2096 | rfcomm_init_sockets(); | 2098 | ret = rfcomm_init_ttys(); |
2099 | if (ret) | ||
2100 | goto out_tty; | ||
2097 | 2101 | ||
2098 | #ifdef CONFIG_BT_RFCOMM_TTY | 2102 | ret = rfcomm_init_sockets(); |
2099 | rfcomm_init_ttys(); | 2103 | if (ret) |
2100 | #endif | 2104 | goto out_sock; |
2101 | 2105 | ||
2102 | BT_INFO("RFCOMM ver %s", VERSION); | 2106 | BT_INFO("RFCOMM ver %s", VERSION); |
2103 | 2107 | ||
2104 | return 0; | 2108 | return 0; |
2109 | |||
2110 | out_sock: | ||
2111 | rfcomm_cleanup_ttys(); | ||
2112 | out_tty: | ||
2113 | kthread_stop(rfcomm_thread); | ||
2114 | out_thread: | ||
2115 | hci_unregister_cb(&rfcomm_cb); | ||
2116 | |||
2117 | return ret; | ||
2105 | } | 2118 | } |
2106 | 2119 | ||
2107 | static void __exit rfcomm_exit(void) | 2120 | static void __exit rfcomm_exit(void) |
@@ -2112,9 +2125,7 @@ static void __exit rfcomm_exit(void) | |||
2112 | 2125 | ||
2113 | kthread_stop(rfcomm_thread); | 2126 | kthread_stop(rfcomm_thread); |
2114 | 2127 | ||
2115 | #ifdef CONFIG_BT_RFCOMM_TTY | ||
2116 | rfcomm_cleanup_ttys(); | 2128 | rfcomm_cleanup_ttys(); |
2117 | #endif | ||
2118 | 2129 | ||
2119 | rfcomm_cleanup_sockets(); | 2130 | rfcomm_cleanup_sockets(); |
2120 | } | 2131 | } |
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index 7f482784e9f7..0b85e8116859 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c | |||
@@ -1132,7 +1132,7 @@ error: | |||
1132 | return err; | 1132 | return err; |
1133 | } | 1133 | } |
1134 | 1134 | ||
1135 | void __exit rfcomm_cleanup_sockets(void) | 1135 | void rfcomm_cleanup_sockets(void) |
1136 | { | 1136 | { |
1137 | class_remove_file(bt_class, &class_attr_rfcomm); | 1137 | class_remove_file(bt_class, &class_attr_rfcomm); |
1138 | 1138 | ||
diff --git a/net/bridge/br.c b/net/bridge/br.c index 9aac5213105a..e1241c76239a 100644 --- a/net/bridge/br.c +++ b/net/bridge/br.c | |||
@@ -93,7 +93,7 @@ static void __exit br_deinit(void) | |||
93 | 93 | ||
94 | unregister_pernet_subsys(&br_net_ops); | 94 | unregister_pernet_subsys(&br_net_ops); |
95 | 95 | ||
96 | synchronize_net(); | 96 | rcu_barrier(); /* Wait for completion of call_rcu()'s */ |
97 | 97 | ||
98 | br_netfilter_fini(); | 98 | br_netfilter_fini(); |
99 | #if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE) | 99 | #if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE) |
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index 8a96672e2c5c..eb404dc3ed6e 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c | |||
@@ -424,7 +424,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) | |||
424 | err2: | 424 | err2: |
425 | br_fdb_delete_by_port(br, p, 1); | 425 | br_fdb_delete_by_port(br, p, 1); |
426 | err1: | 426 | err1: |
427 | kobject_del(&p->kobj); | 427 | kobject_put(&p->kobj); |
428 | err0: | 428 | err0: |
429 | dev_set_promiscuity(dev, -1); | 429 | dev_set_promiscuity(dev, -1); |
430 | put_back: | 430 | put_back: |
diff --git a/net/can/bcm.c b/net/can/bcm.c index 95d7f32643ae..72720c710351 100644 --- a/net/can/bcm.c +++ b/net/can/bcm.c | |||
@@ -75,6 +75,7 @@ static __initdata const char banner[] = KERN_INFO | |||
75 | MODULE_DESCRIPTION("PF_CAN broadcast manager protocol"); | 75 | MODULE_DESCRIPTION("PF_CAN broadcast manager protocol"); |
76 | MODULE_LICENSE("Dual BSD/GPL"); | 76 | MODULE_LICENSE("Dual BSD/GPL"); |
77 | MODULE_AUTHOR("Oliver Hartkopp <oliver.hartkopp@volkswagen.de>"); | 77 | MODULE_AUTHOR("Oliver Hartkopp <oliver.hartkopp@volkswagen.de>"); |
78 | MODULE_ALIAS("can-proto-2"); | ||
78 | 79 | ||
79 | /* easy access to can_frame payload */ | 80 | /* easy access to can_frame payload */ |
80 | static inline u64 GET_U64(const struct can_frame *cp) | 81 | static inline u64 GET_U64(const struct can_frame *cp) |
@@ -1469,6 +1470,9 @@ static int bcm_release(struct socket *sock) | |||
1469 | bo->ifindex = 0; | 1470 | bo->ifindex = 0; |
1470 | } | 1471 | } |
1471 | 1472 | ||
1473 | sock_orphan(sk); | ||
1474 | sock->sk = NULL; | ||
1475 | |||
1472 | release_sock(sk); | 1476 | release_sock(sk); |
1473 | sock_put(sk); | 1477 | sock_put(sk); |
1474 | 1478 | ||
diff --git a/net/can/raw.c b/net/can/raw.c index 6aa154e806ae..db3152df7d2b 100644 --- a/net/can/raw.c +++ b/net/can/raw.c | |||
@@ -62,6 +62,7 @@ static __initdata const char banner[] = | |||
62 | MODULE_DESCRIPTION("PF_CAN raw protocol"); | 62 | MODULE_DESCRIPTION("PF_CAN raw protocol"); |
63 | MODULE_LICENSE("Dual BSD/GPL"); | 63 | MODULE_LICENSE("Dual BSD/GPL"); |
64 | MODULE_AUTHOR("Urs Thuermann <urs.thuermann@volkswagen.de>"); | 64 | MODULE_AUTHOR("Urs Thuermann <urs.thuermann@volkswagen.de>"); |
65 | MODULE_ALIAS("can-proto-1"); | ||
65 | 66 | ||
66 | #define MASK_ALL 0 | 67 | #define MASK_ALL 0 |
67 | 68 | ||
@@ -306,6 +307,9 @@ static int raw_release(struct socket *sock) | |||
306 | ro->bound = 0; | 307 | ro->bound = 0; |
307 | ro->count = 0; | 308 | ro->count = 0; |
308 | 309 | ||
310 | sock_orphan(sk); | ||
311 | sock->sk = NULL; | ||
312 | |||
309 | release_sock(sk); | 313 | release_sock(sk); |
310 | sock_put(sk); | 314 | sock_put(sk); |
311 | 315 | ||
@@ -397,6 +401,7 @@ static int raw_getname(struct socket *sock, struct sockaddr *uaddr, | |||
397 | if (peer) | 401 | if (peer) |
398 | return -EOPNOTSUPP; | 402 | return -EOPNOTSUPP; |
399 | 403 | ||
404 | memset(addr, 0, sizeof(*addr)); | ||
400 | addr->can_family = AF_CAN; | 405 | addr->can_family = AF_CAN; |
401 | addr->can_ifindex = ro->ifindex; | 406 | addr->can_ifindex = ro->ifindex; |
402 | 407 | ||
diff --git a/net/core/datagram.c b/net/core/datagram.c index 58abee1f1df1..b0fe69211eef 100644 --- a/net/core/datagram.c +++ b/net/core/datagram.c | |||
@@ -712,7 +712,7 @@ unsigned int datagram_poll(struct file *file, struct socket *sock, | |||
712 | struct sock *sk = sock->sk; | 712 | struct sock *sk = sock->sk; |
713 | unsigned int mask; | 713 | unsigned int mask; |
714 | 714 | ||
715 | poll_wait(file, sk->sk_sleep, wait); | 715 | sock_poll_wait(file, sk->sk_sleep, wait); |
716 | mask = 0; | 716 | mask = 0; |
717 | 717 | ||
718 | /* exceptional events? */ | 718 | /* exceptional events? */ |
diff --git a/net/core/dev.c b/net/core/dev.c index 576a61574a93..6a94475aee85 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -2310,8 +2310,6 @@ ncls: | |||
2310 | if (!skb) | 2310 | if (!skb) |
2311 | goto out; | 2311 | goto out; |
2312 | 2312 | ||
2313 | skb_orphan(skb); | ||
2314 | |||
2315 | type = skb->protocol; | 2313 | type = skb->protocol; |
2316 | list_for_each_entry_rcu(ptype, | 2314 | list_for_each_entry_rcu(ptype, |
2317 | &ptype_base[ntohs(type) & PTYPE_HASH_MASK], list) { | 2315 | &ptype_base[ntohs(type) & PTYPE_HASH_MASK], list) { |
@@ -2825,9 +2823,11 @@ static void net_rx_action(struct softirq_action *h) | |||
2825 | * move the instance around on the list at-will. | 2823 | * move the instance around on the list at-will. |
2826 | */ | 2824 | */ |
2827 | if (unlikely(work == weight)) { | 2825 | if (unlikely(work == weight)) { |
2828 | if (unlikely(napi_disable_pending(n))) | 2826 | if (unlikely(napi_disable_pending(n))) { |
2829 | __napi_complete(n); | 2827 | local_irq_enable(); |
2830 | else | 2828 | napi_complete(n); |
2829 | local_irq_disable(); | ||
2830 | } else | ||
2831 | list_move_tail(&n->poll_list, list); | 2831 | list_move_tail(&n->poll_list, list); |
2832 | } | 2832 | } |
2833 | 2833 | ||
@@ -3461,10 +3461,10 @@ void __dev_set_rx_mode(struct net_device *dev) | |||
3461 | /* Unicast addresses changes may only happen under the rtnl, | 3461 | /* Unicast addresses changes may only happen under the rtnl, |
3462 | * therefore calling __dev_set_promiscuity here is safe. | 3462 | * therefore calling __dev_set_promiscuity here is safe. |
3463 | */ | 3463 | */ |
3464 | if (dev->uc_count > 0 && !dev->uc_promisc) { | 3464 | if (dev->uc.count > 0 && !dev->uc_promisc) { |
3465 | __dev_set_promiscuity(dev, 1); | 3465 | __dev_set_promiscuity(dev, 1); |
3466 | dev->uc_promisc = 1; | 3466 | dev->uc_promisc = 1; |
3467 | } else if (dev->uc_count == 0 && dev->uc_promisc) { | 3467 | } else if (dev->uc.count == 0 && dev->uc_promisc) { |
3468 | __dev_set_promiscuity(dev, -1); | 3468 | __dev_set_promiscuity(dev, -1); |
3469 | dev->uc_promisc = 0; | 3469 | dev->uc_promisc = 0; |
3470 | } | 3470 | } |
@@ -3483,9 +3483,8 @@ void dev_set_rx_mode(struct net_device *dev) | |||
3483 | 3483 | ||
3484 | /* hw addresses list handling functions */ | 3484 | /* hw addresses list handling functions */ |
3485 | 3485 | ||
3486 | static int __hw_addr_add(struct list_head *list, int *delta, | 3486 | static int __hw_addr_add(struct netdev_hw_addr_list *list, unsigned char *addr, |
3487 | unsigned char *addr, int addr_len, | 3487 | int addr_len, unsigned char addr_type) |
3488 | unsigned char addr_type) | ||
3489 | { | 3488 | { |
3490 | struct netdev_hw_addr *ha; | 3489 | struct netdev_hw_addr *ha; |
3491 | int alloc_size; | 3490 | int alloc_size; |
@@ -3493,7 +3492,7 @@ static int __hw_addr_add(struct list_head *list, int *delta, | |||
3493 | if (addr_len > MAX_ADDR_LEN) | 3492 | if (addr_len > MAX_ADDR_LEN) |
3494 | return -EINVAL; | 3493 | return -EINVAL; |
3495 | 3494 | ||
3496 | list_for_each_entry(ha, list, list) { | 3495 | list_for_each_entry(ha, &list->list, list) { |
3497 | if (!memcmp(ha->addr, addr, addr_len) && | 3496 | if (!memcmp(ha->addr, addr, addr_len) && |
3498 | ha->type == addr_type) { | 3497 | ha->type == addr_type) { |
3499 | ha->refcount++; | 3498 | ha->refcount++; |
@@ -3512,9 +3511,8 @@ static int __hw_addr_add(struct list_head *list, int *delta, | |||
3512 | ha->type = addr_type; | 3511 | ha->type = addr_type; |
3513 | ha->refcount = 1; | 3512 | ha->refcount = 1; |
3514 | ha->synced = false; | 3513 | ha->synced = false; |
3515 | list_add_tail_rcu(&ha->list, list); | 3514 | list_add_tail_rcu(&ha->list, &list->list); |
3516 | if (delta) | 3515 | list->count++; |
3517 | (*delta)++; | ||
3518 | return 0; | 3516 | return 0; |
3519 | } | 3517 | } |
3520 | 3518 | ||
@@ -3526,120 +3524,121 @@ static void ha_rcu_free(struct rcu_head *head) | |||
3526 | kfree(ha); | 3524 | kfree(ha); |
3527 | } | 3525 | } |
3528 | 3526 | ||
3529 | static int __hw_addr_del(struct list_head *list, int *delta, | 3527 | static int __hw_addr_del(struct netdev_hw_addr_list *list, unsigned char *addr, |
3530 | unsigned char *addr, int addr_len, | 3528 | int addr_len, unsigned char addr_type) |
3531 | unsigned char addr_type) | ||
3532 | { | 3529 | { |
3533 | struct netdev_hw_addr *ha; | 3530 | struct netdev_hw_addr *ha; |
3534 | 3531 | ||
3535 | list_for_each_entry(ha, list, list) { | 3532 | list_for_each_entry(ha, &list->list, list) { |
3536 | if (!memcmp(ha->addr, addr, addr_len) && | 3533 | if (!memcmp(ha->addr, addr, addr_len) && |
3537 | (ha->type == addr_type || !addr_type)) { | 3534 | (ha->type == addr_type || !addr_type)) { |
3538 | if (--ha->refcount) | 3535 | if (--ha->refcount) |
3539 | return 0; | 3536 | return 0; |
3540 | list_del_rcu(&ha->list); | 3537 | list_del_rcu(&ha->list); |
3541 | call_rcu(&ha->rcu_head, ha_rcu_free); | 3538 | call_rcu(&ha->rcu_head, ha_rcu_free); |
3542 | if (delta) | 3539 | list->count--; |
3543 | (*delta)--; | ||
3544 | return 0; | 3540 | return 0; |
3545 | } | 3541 | } |
3546 | } | 3542 | } |
3547 | return -ENOENT; | 3543 | return -ENOENT; |
3548 | } | 3544 | } |
3549 | 3545 | ||
3550 | static int __hw_addr_add_multiple(struct list_head *to_list, int *to_delta, | 3546 | static int __hw_addr_add_multiple(struct netdev_hw_addr_list *to_list, |
3551 | struct list_head *from_list, int addr_len, | 3547 | struct netdev_hw_addr_list *from_list, |
3548 | int addr_len, | ||
3552 | unsigned char addr_type) | 3549 | unsigned char addr_type) |
3553 | { | 3550 | { |
3554 | int err; | 3551 | int err; |
3555 | struct netdev_hw_addr *ha, *ha2; | 3552 | struct netdev_hw_addr *ha, *ha2; |
3556 | unsigned char type; | 3553 | unsigned char type; |
3557 | 3554 | ||
3558 | list_for_each_entry(ha, from_list, list) { | 3555 | list_for_each_entry(ha, &from_list->list, list) { |
3559 | type = addr_type ? addr_type : ha->type; | 3556 | type = addr_type ? addr_type : ha->type; |
3560 | err = __hw_addr_add(to_list, to_delta, ha->addr, | 3557 | err = __hw_addr_add(to_list, ha->addr, addr_len, type); |
3561 | addr_len, type); | ||
3562 | if (err) | 3558 | if (err) |
3563 | goto unroll; | 3559 | goto unroll; |
3564 | } | 3560 | } |
3565 | return 0; | 3561 | return 0; |
3566 | 3562 | ||
3567 | unroll: | 3563 | unroll: |
3568 | list_for_each_entry(ha2, from_list, list) { | 3564 | list_for_each_entry(ha2, &from_list->list, list) { |
3569 | if (ha2 == ha) | 3565 | if (ha2 == ha) |
3570 | break; | 3566 | break; |
3571 | type = addr_type ? addr_type : ha2->type; | 3567 | type = addr_type ? addr_type : ha2->type; |
3572 | __hw_addr_del(to_list, to_delta, ha2->addr, | 3568 | __hw_addr_del(to_list, ha2->addr, addr_len, type); |
3573 | addr_len, type); | ||
3574 | } | 3569 | } |
3575 | return err; | 3570 | return err; |
3576 | } | 3571 | } |
3577 | 3572 | ||
3578 | static void __hw_addr_del_multiple(struct list_head *to_list, int *to_delta, | 3573 | static void __hw_addr_del_multiple(struct netdev_hw_addr_list *to_list, |
3579 | struct list_head *from_list, int addr_len, | 3574 | struct netdev_hw_addr_list *from_list, |
3575 | int addr_len, | ||
3580 | unsigned char addr_type) | 3576 | unsigned char addr_type) |
3581 | { | 3577 | { |
3582 | struct netdev_hw_addr *ha; | 3578 | struct netdev_hw_addr *ha; |
3583 | unsigned char type; | 3579 | unsigned char type; |
3584 | 3580 | ||
3585 | list_for_each_entry(ha, from_list, list) { | 3581 | list_for_each_entry(ha, &from_list->list, list) { |
3586 | type = addr_type ? addr_type : ha->type; | 3582 | type = addr_type ? addr_type : ha->type; |
3587 | __hw_addr_del(to_list, to_delta, ha->addr, | 3583 | __hw_addr_del(to_list, ha->addr, addr_len, addr_type); |
3588 | addr_len, addr_type); | ||
3589 | } | 3584 | } |
3590 | } | 3585 | } |
3591 | 3586 | ||
3592 | static int __hw_addr_sync(struct list_head *to_list, int *to_delta, | 3587 | static int __hw_addr_sync(struct netdev_hw_addr_list *to_list, |
3593 | struct list_head *from_list, int *from_delta, | 3588 | struct netdev_hw_addr_list *from_list, |
3594 | int addr_len) | 3589 | int addr_len) |
3595 | { | 3590 | { |
3596 | int err = 0; | 3591 | int err = 0; |
3597 | struct netdev_hw_addr *ha, *tmp; | 3592 | struct netdev_hw_addr *ha, *tmp; |
3598 | 3593 | ||
3599 | list_for_each_entry_safe(ha, tmp, from_list, list) { | 3594 | list_for_each_entry_safe(ha, tmp, &from_list->list, list) { |
3600 | if (!ha->synced) { | 3595 | if (!ha->synced) { |
3601 | err = __hw_addr_add(to_list, to_delta, ha->addr, | 3596 | err = __hw_addr_add(to_list, ha->addr, |
3602 | addr_len, ha->type); | 3597 | addr_len, ha->type); |
3603 | if (err) | 3598 | if (err) |
3604 | break; | 3599 | break; |
3605 | ha->synced = true; | 3600 | ha->synced = true; |
3606 | ha->refcount++; | 3601 | ha->refcount++; |
3607 | } else if (ha->refcount == 1) { | 3602 | } else if (ha->refcount == 1) { |
3608 | __hw_addr_del(to_list, to_delta, ha->addr, | 3603 | __hw_addr_del(to_list, ha->addr, addr_len, ha->type); |
3609 | addr_len, ha->type); | 3604 | __hw_addr_del(from_list, ha->addr, addr_len, ha->type); |
3610 | __hw_addr_del(from_list, from_delta, ha->addr, | ||
3611 | addr_len, ha->type); | ||
3612 | } | 3605 | } |
3613 | } | 3606 | } |
3614 | return err; | 3607 | return err; |
3615 | } | 3608 | } |
3616 | 3609 | ||
3617 | static void __hw_addr_unsync(struct list_head *to_list, int *to_delta, | 3610 | static void __hw_addr_unsync(struct netdev_hw_addr_list *to_list, |
3618 | struct list_head *from_list, int *from_delta, | 3611 | struct netdev_hw_addr_list *from_list, |
3619 | int addr_len) | 3612 | int addr_len) |
3620 | { | 3613 | { |
3621 | struct netdev_hw_addr *ha, *tmp; | 3614 | struct netdev_hw_addr *ha, *tmp; |
3622 | 3615 | ||
3623 | list_for_each_entry_safe(ha, tmp, from_list, list) { | 3616 | list_for_each_entry_safe(ha, tmp, &from_list->list, list) { |
3624 | if (ha->synced) { | 3617 | if (ha->synced) { |
3625 | __hw_addr_del(to_list, to_delta, ha->addr, | 3618 | __hw_addr_del(to_list, ha->addr, |
3626 | addr_len, ha->type); | 3619 | addr_len, ha->type); |
3627 | ha->synced = false; | 3620 | ha->synced = false; |
3628 | __hw_addr_del(from_list, from_delta, ha->addr, | 3621 | __hw_addr_del(from_list, ha->addr, |
3629 | addr_len, ha->type); | 3622 | addr_len, ha->type); |
3630 | } | 3623 | } |
3631 | } | 3624 | } |
3632 | } | 3625 | } |
3633 | 3626 | ||
3634 | 3627 | static void __hw_addr_flush(struct netdev_hw_addr_list *list) | |
3635 | static void __hw_addr_flush(struct list_head *list) | ||
3636 | { | 3628 | { |
3637 | struct netdev_hw_addr *ha, *tmp; | 3629 | struct netdev_hw_addr *ha, *tmp; |
3638 | 3630 | ||
3639 | list_for_each_entry_safe(ha, tmp, list, list) { | 3631 | list_for_each_entry_safe(ha, tmp, &list->list, list) { |
3640 | list_del_rcu(&ha->list); | 3632 | list_del_rcu(&ha->list); |
3641 | call_rcu(&ha->rcu_head, ha_rcu_free); | 3633 | call_rcu(&ha->rcu_head, ha_rcu_free); |
3642 | } | 3634 | } |
3635 | list->count = 0; | ||
3636 | } | ||
3637 | |||
3638 | static void __hw_addr_init(struct netdev_hw_addr_list *list) | ||
3639 | { | ||
3640 | INIT_LIST_HEAD(&list->list); | ||
3641 | list->count = 0; | ||
3643 | } | 3642 | } |
3644 | 3643 | ||
3645 | /* Device addresses handling functions */ | 3644 | /* Device addresses handling functions */ |
@@ -3648,7 +3647,7 @@ static void dev_addr_flush(struct net_device *dev) | |||
3648 | { | 3647 | { |
3649 | /* rtnl_mutex must be held here */ | 3648 | /* rtnl_mutex must be held here */ |
3650 | 3649 | ||
3651 | __hw_addr_flush(&dev->dev_addr_list); | 3650 | __hw_addr_flush(&dev->dev_addrs); |
3652 | dev->dev_addr = NULL; | 3651 | dev->dev_addr = NULL; |
3653 | } | 3652 | } |
3654 | 3653 | ||
@@ -3660,16 +3659,16 @@ static int dev_addr_init(struct net_device *dev) | |||
3660 | 3659 | ||
3661 | /* rtnl_mutex must be held here */ | 3660 | /* rtnl_mutex must be held here */ |
3662 | 3661 | ||
3663 | INIT_LIST_HEAD(&dev->dev_addr_list); | 3662 | __hw_addr_init(&dev->dev_addrs); |
3664 | memset(addr, 0, sizeof(addr)); | 3663 | memset(addr, 0, sizeof(addr)); |
3665 | err = __hw_addr_add(&dev->dev_addr_list, NULL, addr, sizeof(addr), | 3664 | err = __hw_addr_add(&dev->dev_addrs, addr, sizeof(addr), |
3666 | NETDEV_HW_ADDR_T_LAN); | 3665 | NETDEV_HW_ADDR_T_LAN); |
3667 | if (!err) { | 3666 | if (!err) { |
3668 | /* | 3667 | /* |
3669 | * Get the first (previously created) address from the list | 3668 | * Get the first (previously created) address from the list |
3670 | * and set dev_addr pointer to this location. | 3669 | * and set dev_addr pointer to this location. |
3671 | */ | 3670 | */ |
3672 | ha = list_first_entry(&dev->dev_addr_list, | 3671 | ha = list_first_entry(&dev->dev_addrs.list, |
3673 | struct netdev_hw_addr, list); | 3672 | struct netdev_hw_addr, list); |
3674 | dev->dev_addr = ha->addr; | 3673 | dev->dev_addr = ha->addr; |
3675 | } | 3674 | } |
@@ -3694,8 +3693,7 @@ int dev_addr_add(struct net_device *dev, unsigned char *addr, | |||
3694 | 3693 | ||
3695 | ASSERT_RTNL(); | 3694 | ASSERT_RTNL(); |
3696 | 3695 | ||
3697 | err = __hw_addr_add(&dev->dev_addr_list, NULL, addr, dev->addr_len, | 3696 | err = __hw_addr_add(&dev->dev_addrs, addr, dev->addr_len, addr_type); |
3698 | addr_type); | ||
3699 | if (!err) | 3697 | if (!err) |
3700 | call_netdevice_notifiers(NETDEV_CHANGEADDR, dev); | 3698 | call_netdevice_notifiers(NETDEV_CHANGEADDR, dev); |
3701 | return err; | 3699 | return err; |
@@ -3725,11 +3723,12 @@ int dev_addr_del(struct net_device *dev, unsigned char *addr, | |||
3725 | * We can not remove the first address from the list because | 3723 | * We can not remove the first address from the list because |
3726 | * dev->dev_addr points to that. | 3724 | * dev->dev_addr points to that. |
3727 | */ | 3725 | */ |
3728 | ha = list_first_entry(&dev->dev_addr_list, struct netdev_hw_addr, list); | 3726 | ha = list_first_entry(&dev->dev_addrs.list, |
3727 | struct netdev_hw_addr, list); | ||
3729 | if (ha->addr == dev->dev_addr && ha->refcount == 1) | 3728 | if (ha->addr == dev->dev_addr && ha->refcount == 1) |
3730 | return -ENOENT; | 3729 | return -ENOENT; |
3731 | 3730 | ||
3732 | err = __hw_addr_del(&dev->dev_addr_list, NULL, addr, dev->addr_len, | 3731 | err = __hw_addr_del(&dev->dev_addrs, addr, dev->addr_len, |
3733 | addr_type); | 3732 | addr_type); |
3734 | if (!err) | 3733 | if (!err) |
3735 | call_netdevice_notifiers(NETDEV_CHANGEADDR, dev); | 3734 | call_netdevice_notifiers(NETDEV_CHANGEADDR, dev); |
@@ -3757,8 +3756,7 @@ int dev_addr_add_multiple(struct net_device *to_dev, | |||
3757 | 3756 | ||
3758 | if (from_dev->addr_len != to_dev->addr_len) | 3757 | if (from_dev->addr_len != to_dev->addr_len) |
3759 | return -EINVAL; | 3758 | return -EINVAL; |
3760 | err = __hw_addr_add_multiple(&to_dev->dev_addr_list, NULL, | 3759 | err = __hw_addr_add_multiple(&to_dev->dev_addrs, &from_dev->dev_addrs, |
3761 | &from_dev->dev_addr_list, | ||
3762 | to_dev->addr_len, addr_type); | 3760 | to_dev->addr_len, addr_type); |
3763 | if (!err) | 3761 | if (!err) |
3764 | call_netdevice_notifiers(NETDEV_CHANGEADDR, to_dev); | 3762 | call_netdevice_notifiers(NETDEV_CHANGEADDR, to_dev); |
@@ -3784,15 +3782,14 @@ int dev_addr_del_multiple(struct net_device *to_dev, | |||
3784 | 3782 | ||
3785 | if (from_dev->addr_len != to_dev->addr_len) | 3783 | if (from_dev->addr_len != to_dev->addr_len) |
3786 | return -EINVAL; | 3784 | return -EINVAL; |
3787 | __hw_addr_del_multiple(&to_dev->dev_addr_list, NULL, | 3785 | __hw_addr_del_multiple(&to_dev->dev_addrs, &from_dev->dev_addrs, |
3788 | &from_dev->dev_addr_list, | ||
3789 | to_dev->addr_len, addr_type); | 3786 | to_dev->addr_len, addr_type); |
3790 | call_netdevice_notifiers(NETDEV_CHANGEADDR, to_dev); | 3787 | call_netdevice_notifiers(NETDEV_CHANGEADDR, to_dev); |
3791 | return 0; | 3788 | return 0; |
3792 | } | 3789 | } |
3793 | EXPORT_SYMBOL(dev_addr_del_multiple); | 3790 | EXPORT_SYMBOL(dev_addr_del_multiple); |
3794 | 3791 | ||
3795 | /* unicast and multicast addresses handling functions */ | 3792 | /* multicast addresses handling functions */ |
3796 | 3793 | ||
3797 | int __dev_addr_delete(struct dev_addr_list **list, int *count, | 3794 | int __dev_addr_delete(struct dev_addr_list **list, int *count, |
3798 | void *addr, int alen, int glbl) | 3795 | void *addr, int alen, int glbl) |
@@ -3868,10 +3865,12 @@ int dev_unicast_delete(struct net_device *dev, void *addr) | |||
3868 | 3865 | ||
3869 | ASSERT_RTNL(); | 3866 | ASSERT_RTNL(); |
3870 | 3867 | ||
3871 | err = __hw_addr_del(&dev->uc_list, &dev->uc_count, addr, | 3868 | netif_addr_lock_bh(dev); |
3872 | dev->addr_len, NETDEV_HW_ADDR_T_UNICAST); | 3869 | err = __hw_addr_del(&dev->uc, addr, dev->addr_len, |
3870 | NETDEV_HW_ADDR_T_UNICAST); | ||
3873 | if (!err) | 3871 | if (!err) |
3874 | __dev_set_rx_mode(dev); | 3872 | __dev_set_rx_mode(dev); |
3873 | netif_addr_unlock_bh(dev); | ||
3875 | return err; | 3874 | return err; |
3876 | } | 3875 | } |
3877 | EXPORT_SYMBOL(dev_unicast_delete); | 3876 | EXPORT_SYMBOL(dev_unicast_delete); |
@@ -3892,10 +3891,12 @@ int dev_unicast_add(struct net_device *dev, void *addr) | |||
3892 | 3891 | ||
3893 | ASSERT_RTNL(); | 3892 | ASSERT_RTNL(); |
3894 | 3893 | ||
3895 | err = __hw_addr_add(&dev->uc_list, &dev->uc_count, addr, | 3894 | netif_addr_lock_bh(dev); |
3896 | dev->addr_len, NETDEV_HW_ADDR_T_UNICAST); | 3895 | err = __hw_addr_add(&dev->uc, addr, dev->addr_len, |
3896 | NETDEV_HW_ADDR_T_UNICAST); | ||
3897 | if (!err) | 3897 | if (!err) |
3898 | __dev_set_rx_mode(dev); | 3898 | __dev_set_rx_mode(dev); |
3899 | netif_addr_unlock_bh(dev); | ||
3899 | return err; | 3900 | return err; |
3900 | } | 3901 | } |
3901 | EXPORT_SYMBOL(dev_unicast_add); | 3902 | EXPORT_SYMBOL(dev_unicast_add); |
@@ -3952,7 +3953,8 @@ void __dev_addr_unsync(struct dev_addr_list **to, int *to_count, | |||
3952 | * @from: source device | 3953 | * @from: source device |
3953 | * | 3954 | * |
3954 | * Add newly added addresses to the destination device and release | 3955 | * Add newly added addresses to the destination device and release |
3955 | * addresses that have no users left. | 3956 | * addresses that have no users left. The source device must be |
3957 | * locked by netif_tx_lock_bh. | ||
3956 | * | 3958 | * |
3957 | * This function is intended to be called from the dev->set_rx_mode | 3959 | * This function is intended to be called from the dev->set_rx_mode |
3958 | * function of layered software devices. | 3960 | * function of layered software devices. |
@@ -3961,15 +3963,14 @@ int dev_unicast_sync(struct net_device *to, struct net_device *from) | |||
3961 | { | 3963 | { |
3962 | int err = 0; | 3964 | int err = 0; |
3963 | 3965 | ||
3964 | ASSERT_RTNL(); | ||
3965 | |||
3966 | if (to->addr_len != from->addr_len) | 3966 | if (to->addr_len != from->addr_len) |
3967 | return -EINVAL; | 3967 | return -EINVAL; |
3968 | 3968 | ||
3969 | err = __hw_addr_sync(&to->uc_list, &to->uc_count, | 3969 | netif_addr_lock_bh(to); |
3970 | &from->uc_list, &from->uc_count, to->addr_len); | 3970 | err = __hw_addr_sync(&to->uc, &from->uc, to->addr_len); |
3971 | if (!err) | 3971 | if (!err) |
3972 | __dev_set_rx_mode(to); | 3972 | __dev_set_rx_mode(to); |
3973 | netif_addr_unlock_bh(to); | ||
3973 | return err; | 3974 | return err; |
3974 | } | 3975 | } |
3975 | EXPORT_SYMBOL(dev_unicast_sync); | 3976 | EXPORT_SYMBOL(dev_unicast_sync); |
@@ -3985,30 +3986,28 @@ EXPORT_SYMBOL(dev_unicast_sync); | |||
3985 | */ | 3986 | */ |
3986 | void dev_unicast_unsync(struct net_device *to, struct net_device *from) | 3987 | void dev_unicast_unsync(struct net_device *to, struct net_device *from) |
3987 | { | 3988 | { |
3988 | ASSERT_RTNL(); | ||
3989 | |||
3990 | if (to->addr_len != from->addr_len) | 3989 | if (to->addr_len != from->addr_len) |
3991 | return; | 3990 | return; |
3992 | 3991 | ||
3993 | __hw_addr_unsync(&to->uc_list, &to->uc_count, | 3992 | netif_addr_lock_bh(from); |
3994 | &from->uc_list, &from->uc_count, to->addr_len); | 3993 | netif_addr_lock(to); |
3994 | __hw_addr_unsync(&to->uc, &from->uc, to->addr_len); | ||
3995 | __dev_set_rx_mode(to); | 3995 | __dev_set_rx_mode(to); |
3996 | netif_addr_unlock(to); | ||
3997 | netif_addr_unlock_bh(from); | ||
3996 | } | 3998 | } |
3997 | EXPORT_SYMBOL(dev_unicast_unsync); | 3999 | EXPORT_SYMBOL(dev_unicast_unsync); |
3998 | 4000 | ||
3999 | static void dev_unicast_flush(struct net_device *dev) | 4001 | static void dev_unicast_flush(struct net_device *dev) |
4000 | { | 4002 | { |
4001 | /* rtnl_mutex must be held here */ | 4003 | netif_addr_lock_bh(dev); |
4002 | 4004 | __hw_addr_flush(&dev->uc); | |
4003 | __hw_addr_flush(&dev->uc_list); | 4005 | netif_addr_unlock_bh(dev); |
4004 | dev->uc_count = 0; | ||
4005 | } | 4006 | } |
4006 | 4007 | ||
4007 | static void dev_unicast_init(struct net_device *dev) | 4008 | static void dev_unicast_init(struct net_device *dev) |
4008 | { | 4009 | { |
4009 | /* rtnl_mutex must be held here */ | 4010 | __hw_addr_init(&dev->uc); |
4010 | |||
4011 | INIT_LIST_HEAD(&dev->uc_list); | ||
4012 | } | 4011 | } |
4013 | 4012 | ||
4014 | 4013 | ||
diff --git a/net/core/gen_estimator.c b/net/core/gen_estimator.c index 78e5bfc454ae..493775f4f2f1 100644 --- a/net/core/gen_estimator.c +++ b/net/core/gen_estimator.c | |||
@@ -81,7 +81,7 @@ | |||
81 | struct gen_estimator | 81 | struct gen_estimator |
82 | { | 82 | { |
83 | struct list_head list; | 83 | struct list_head list; |
84 | struct gnet_stats_basic *bstats; | 84 | struct gnet_stats_basic_packed *bstats; |
85 | struct gnet_stats_rate_est *rate_est; | 85 | struct gnet_stats_rate_est *rate_est; |
86 | spinlock_t *stats_lock; | 86 | spinlock_t *stats_lock; |
87 | int ewma_log; | 87 | int ewma_log; |
@@ -165,7 +165,7 @@ static void gen_add_node(struct gen_estimator *est) | |||
165 | } | 165 | } |
166 | 166 | ||
167 | static | 167 | static |
168 | struct gen_estimator *gen_find_node(const struct gnet_stats_basic *bstats, | 168 | struct gen_estimator *gen_find_node(const struct gnet_stats_basic_packed *bstats, |
169 | const struct gnet_stats_rate_est *rate_est) | 169 | const struct gnet_stats_rate_est *rate_est) |
170 | { | 170 | { |
171 | struct rb_node *p = est_root.rb_node; | 171 | struct rb_node *p = est_root.rb_node; |
@@ -202,7 +202,7 @@ struct gen_estimator *gen_find_node(const struct gnet_stats_basic *bstats, | |||
202 | * | 202 | * |
203 | * NOTE: Called under rtnl_mutex | 203 | * NOTE: Called under rtnl_mutex |
204 | */ | 204 | */ |
205 | int gen_new_estimator(struct gnet_stats_basic *bstats, | 205 | int gen_new_estimator(struct gnet_stats_basic_packed *bstats, |
206 | struct gnet_stats_rate_est *rate_est, | 206 | struct gnet_stats_rate_est *rate_est, |
207 | spinlock_t *stats_lock, | 207 | spinlock_t *stats_lock, |
208 | struct nlattr *opt) | 208 | struct nlattr *opt) |
@@ -262,7 +262,7 @@ static void __gen_kill_estimator(struct rcu_head *head) | |||
262 | * | 262 | * |
263 | * NOTE: Called under rtnl_mutex | 263 | * NOTE: Called under rtnl_mutex |
264 | */ | 264 | */ |
265 | void gen_kill_estimator(struct gnet_stats_basic *bstats, | 265 | void gen_kill_estimator(struct gnet_stats_basic_packed *bstats, |
266 | struct gnet_stats_rate_est *rate_est) | 266 | struct gnet_stats_rate_est *rate_est) |
267 | { | 267 | { |
268 | struct gen_estimator *e; | 268 | struct gen_estimator *e; |
@@ -292,7 +292,7 @@ EXPORT_SYMBOL(gen_kill_estimator); | |||
292 | * | 292 | * |
293 | * Returns 0 on success or a negative error code. | 293 | * Returns 0 on success or a negative error code. |
294 | */ | 294 | */ |
295 | int gen_replace_estimator(struct gnet_stats_basic *bstats, | 295 | int gen_replace_estimator(struct gnet_stats_basic_packed *bstats, |
296 | struct gnet_stats_rate_est *rate_est, | 296 | struct gnet_stats_rate_est *rate_est, |
297 | spinlock_t *stats_lock, struct nlattr *opt) | 297 | spinlock_t *stats_lock, struct nlattr *opt) |
298 | { | 298 | { |
@@ -308,7 +308,7 @@ EXPORT_SYMBOL(gen_replace_estimator); | |||
308 | * | 308 | * |
309 | * Returns true if estimator is active, and false if not. | 309 | * Returns true if estimator is active, and false if not. |
310 | */ | 310 | */ |
311 | bool gen_estimator_active(const struct gnet_stats_basic *bstats, | 311 | bool gen_estimator_active(const struct gnet_stats_basic_packed *bstats, |
312 | const struct gnet_stats_rate_est *rate_est) | 312 | const struct gnet_stats_rate_est *rate_est) |
313 | { | 313 | { |
314 | ASSERT_RTNL(); | 314 | ASSERT_RTNL(); |
diff --git a/net/core/gen_stats.c b/net/core/gen_stats.c index c3d0ffeac243..8569310268ab 100644 --- a/net/core/gen_stats.c +++ b/net/core/gen_stats.c | |||
@@ -106,16 +106,21 @@ gnet_stats_start_copy(struct sk_buff *skb, int type, spinlock_t *lock, | |||
106 | * if the room in the socket buffer was not sufficient. | 106 | * if the room in the socket buffer was not sufficient. |
107 | */ | 107 | */ |
108 | int | 108 | int |
109 | gnet_stats_copy_basic(struct gnet_dump *d, struct gnet_stats_basic *b) | 109 | gnet_stats_copy_basic(struct gnet_dump *d, struct gnet_stats_basic_packed *b) |
110 | { | 110 | { |
111 | if (d->compat_tc_stats) { | 111 | if (d->compat_tc_stats) { |
112 | d->tc_stats.bytes = b->bytes; | 112 | d->tc_stats.bytes = b->bytes; |
113 | d->tc_stats.packets = b->packets; | 113 | d->tc_stats.packets = b->packets; |
114 | } | 114 | } |
115 | 115 | ||
116 | if (d->tail) | 116 | if (d->tail) { |
117 | return gnet_stats_copy(d, TCA_STATS_BASIC, b, sizeof(*b)); | 117 | struct gnet_stats_basic sb; |
118 | 118 | ||
119 | memset(&sb, 0, sizeof(sb)); | ||
120 | sb.bytes = b->bytes; | ||
121 | sb.packets = b->packets; | ||
122 | return gnet_stats_copy(d, TCA_STATS_BASIC, &sb, sizeof(sb)); | ||
123 | } | ||
119 | return 0; | 124 | return 0; |
120 | } | 125 | } |
121 | 126 | ||
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index b7292a2719dc..197283072cc8 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c | |||
@@ -488,7 +488,7 @@ int net_assign_generic(struct net *net, int id, void *data) | |||
488 | */ | 488 | */ |
489 | 489 | ||
490 | ng->len = id; | 490 | ng->len = id; |
491 | memcpy(&ng->ptr, &old_ng->ptr, old_ng->len); | 491 | memcpy(&ng->ptr, &old_ng->ptr, old_ng->len * sizeof(void*)); |
492 | 492 | ||
493 | rcu_assign_pointer(net->gen, ng); | 493 | rcu_assign_pointer(net->gen, ng); |
494 | call_rcu(&old_ng->rcu, net_generic_release); | 494 | call_rcu(&old_ng->rcu, net_generic_release); |
diff --git a/net/core/netpoll.c b/net/core/netpoll.c index 9675f312830d..1b76eb11deb4 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c | |||
@@ -319,6 +319,11 @@ static void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb) | |||
319 | 319 | ||
320 | udelay(USEC_PER_POLL); | 320 | udelay(USEC_PER_POLL); |
321 | } | 321 | } |
322 | |||
323 | WARN_ONCE(!irqs_disabled(), | ||
324 | "netpoll_send_skb(): %s enabled interrupts in poll (%pF)\n", | ||
325 | dev->name, ops->ndo_start_xmit); | ||
326 | |||
322 | local_irq_restore(flags); | 327 | local_irq_restore(flags); |
323 | } | 328 | } |
324 | 329 | ||
@@ -740,7 +745,7 @@ int netpoll_setup(struct netpoll *np) | |||
740 | np->name); | 745 | np->name); |
741 | break; | 746 | break; |
742 | } | 747 | } |
743 | cond_resched(); | 748 | msleep(1); |
744 | } | 749 | } |
745 | 750 | ||
746 | /* If carrier appears to come up instantly, we don't | 751 | /* If carrier appears to come up instantly, we don't |
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 5c93435b0347..9e0597d189b0 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
@@ -204,6 +204,10 @@ struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask, | |||
204 | skb->end = skb->tail + size; | 204 | skb->end = skb->tail + size; |
205 | kmemcheck_annotate_bitfield(skb, flags1); | 205 | kmemcheck_annotate_bitfield(skb, flags1); |
206 | kmemcheck_annotate_bitfield(skb, flags2); | 206 | kmemcheck_annotate_bitfield(skb, flags2); |
207 | #ifdef NET_SKBUFF_DATA_USES_OFFSET | ||
208 | skb->mac_header = ~0U; | ||
209 | #endif | ||
210 | |||
207 | /* make sure we initialize shinfo sequentially */ | 211 | /* make sure we initialize shinfo sequentially */ |
208 | shinfo = skb_shinfo(skb); | 212 | shinfo = skb_shinfo(skb); |
209 | atomic_set(&shinfo->dataref, 1); | 213 | atomic_set(&shinfo->dataref, 1); |
@@ -665,7 +669,8 @@ static void copy_skb_header(struct sk_buff *new, const struct sk_buff *old) | |||
665 | /* {transport,network,mac}_header are relative to skb->head */ | 669 | /* {transport,network,mac}_header are relative to skb->head */ |
666 | new->transport_header += offset; | 670 | new->transport_header += offset; |
667 | new->network_header += offset; | 671 | new->network_header += offset; |
668 | new->mac_header += offset; | 672 | if (skb_mac_header_was_set(new)) |
673 | new->mac_header += offset; | ||
669 | #endif | 674 | #endif |
670 | skb_shinfo(new)->gso_size = skb_shinfo(old)->gso_size; | 675 | skb_shinfo(new)->gso_size = skb_shinfo(old)->gso_size; |
671 | skb_shinfo(new)->gso_segs = skb_shinfo(old)->gso_segs; | 676 | skb_shinfo(new)->gso_segs = skb_shinfo(old)->gso_segs; |
@@ -847,7 +852,8 @@ int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail, | |||
847 | skb->tail += off; | 852 | skb->tail += off; |
848 | skb->transport_header += off; | 853 | skb->transport_header += off; |
849 | skb->network_header += off; | 854 | skb->network_header += off; |
850 | skb->mac_header += off; | 855 | if (skb_mac_header_was_set(skb)) |
856 | skb->mac_header += off; | ||
851 | skb->csum_start += nhead; | 857 | skb->csum_start += nhead; |
852 | skb->cloned = 0; | 858 | skb->cloned = 0; |
853 | skb->hdr_len = 0; | 859 | skb->hdr_len = 0; |
@@ -939,7 +945,8 @@ struct sk_buff *skb_copy_expand(const struct sk_buff *skb, | |||
939 | #ifdef NET_SKBUFF_DATA_USES_OFFSET | 945 | #ifdef NET_SKBUFF_DATA_USES_OFFSET |
940 | n->transport_header += off; | 946 | n->transport_header += off; |
941 | n->network_header += off; | 947 | n->network_header += off; |
942 | n->mac_header += off; | 948 | if (skb_mac_header_was_set(skb)) |
949 | n->mac_header += off; | ||
943 | #endif | 950 | #endif |
944 | 951 | ||
945 | return n; | 952 | return n; |
diff --git a/net/core/sock.c b/net/core/sock.c index b0ba569bc973..bbb25be7ddfe 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
@@ -631,7 +631,7 @@ set_rcvbuf: | |||
631 | 631 | ||
632 | case SO_TIMESTAMPING: | 632 | case SO_TIMESTAMPING: |
633 | if (val & ~SOF_TIMESTAMPING_MASK) { | 633 | if (val & ~SOF_TIMESTAMPING_MASK) { |
634 | ret = EINVAL; | 634 | ret = -EINVAL; |
635 | break; | 635 | break; |
636 | } | 636 | } |
637 | sock_valbool_flag(sk, SOCK_TIMESTAMPING_TX_HARDWARE, | 637 | sock_valbool_flag(sk, SOCK_TIMESTAMPING_TX_HARDWARE, |
@@ -919,13 +919,19 @@ static inline void sock_lock_init(struct sock *sk) | |||
919 | af_family_keys + sk->sk_family); | 919 | af_family_keys + sk->sk_family); |
920 | } | 920 | } |
921 | 921 | ||
922 | /* | ||
923 | * Copy all fields from osk to nsk but nsk->sk_refcnt must not change yet, | ||
924 | * even temporarly, because of RCU lookups. sk_node should also be left as is. | ||
925 | */ | ||
922 | static void sock_copy(struct sock *nsk, const struct sock *osk) | 926 | static void sock_copy(struct sock *nsk, const struct sock *osk) |
923 | { | 927 | { |
924 | #ifdef CONFIG_SECURITY_NETWORK | 928 | #ifdef CONFIG_SECURITY_NETWORK |
925 | void *sptr = nsk->sk_security; | 929 | void *sptr = nsk->sk_security; |
926 | #endif | 930 | #endif |
927 | 931 | BUILD_BUG_ON(offsetof(struct sock, sk_copy_start) != | |
928 | memcpy(nsk, osk, osk->sk_prot->obj_size); | 932 | sizeof(osk->sk_node) + sizeof(osk->sk_refcnt)); |
933 | memcpy(&nsk->sk_copy_start, &osk->sk_copy_start, | ||
934 | osk->sk_prot->obj_size - offsetof(struct sock, sk_copy_start)); | ||
929 | #ifdef CONFIG_SECURITY_NETWORK | 935 | #ifdef CONFIG_SECURITY_NETWORK |
930 | nsk->sk_security = sptr; | 936 | nsk->sk_security = sptr; |
931 | security_sk_clone(osk, nsk); | 937 | security_sk_clone(osk, nsk); |
@@ -939,8 +945,23 @@ static struct sock *sk_prot_alloc(struct proto *prot, gfp_t priority, | |||
939 | struct kmem_cache *slab; | 945 | struct kmem_cache *slab; |
940 | 946 | ||
941 | slab = prot->slab; | 947 | slab = prot->slab; |
942 | if (slab != NULL) | 948 | if (slab != NULL) { |
943 | sk = kmem_cache_alloc(slab, priority); | 949 | sk = kmem_cache_alloc(slab, priority & ~__GFP_ZERO); |
950 | if (!sk) | ||
951 | return sk; | ||
952 | if (priority & __GFP_ZERO) { | ||
953 | /* | ||
954 | * caches using SLAB_DESTROY_BY_RCU should let | ||
955 | * sk_node.next un-modified. Special care is taken | ||
956 | * when initializing object to zero. | ||
957 | */ | ||
958 | if (offsetof(struct sock, sk_node.next) != 0) | ||
959 | memset(sk, 0, offsetof(struct sock, sk_node.next)); | ||
960 | memset(&sk->sk_node.pprev, 0, | ||
961 | prot->obj_size - offsetof(struct sock, | ||
962 | sk_node.pprev)); | ||
963 | } | ||
964 | } | ||
944 | else | 965 | else |
945 | sk = kmalloc(prot->obj_size, priority); | 966 | sk = kmalloc(prot->obj_size, priority); |
946 | 967 | ||
@@ -1125,6 +1146,11 @@ struct sock *sk_clone(const struct sock *sk, const gfp_t priority) | |||
1125 | 1146 | ||
1126 | newsk->sk_err = 0; | 1147 | newsk->sk_err = 0; |
1127 | newsk->sk_priority = 0; | 1148 | newsk->sk_priority = 0; |
1149 | /* | ||
1150 | * Before updating sk_refcnt, we must commit prior changes to memory | ||
1151 | * (Documentation/RCU/rculist_nulls.txt for details) | ||
1152 | */ | ||
1153 | smp_wmb(); | ||
1128 | atomic_set(&newsk->sk_refcnt, 2); | 1154 | atomic_set(&newsk->sk_refcnt, 2); |
1129 | 1155 | ||
1130 | /* | 1156 | /* |
@@ -1715,7 +1741,7 @@ EXPORT_SYMBOL(sock_no_sendpage); | |||
1715 | static void sock_def_wakeup(struct sock *sk) | 1741 | static void sock_def_wakeup(struct sock *sk) |
1716 | { | 1742 | { |
1717 | read_lock(&sk->sk_callback_lock); | 1743 | read_lock(&sk->sk_callback_lock); |
1718 | if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) | 1744 | if (sk_has_sleeper(sk)) |
1719 | wake_up_interruptible_all(sk->sk_sleep); | 1745 | wake_up_interruptible_all(sk->sk_sleep); |
1720 | read_unlock(&sk->sk_callback_lock); | 1746 | read_unlock(&sk->sk_callback_lock); |
1721 | } | 1747 | } |
@@ -1723,7 +1749,7 @@ static void sock_def_wakeup(struct sock *sk) | |||
1723 | static void sock_def_error_report(struct sock *sk) | 1749 | static void sock_def_error_report(struct sock *sk) |
1724 | { | 1750 | { |
1725 | read_lock(&sk->sk_callback_lock); | 1751 | read_lock(&sk->sk_callback_lock); |
1726 | if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) | 1752 | if (sk_has_sleeper(sk)) |
1727 | wake_up_interruptible_poll(sk->sk_sleep, POLLERR); | 1753 | wake_up_interruptible_poll(sk->sk_sleep, POLLERR); |
1728 | sk_wake_async(sk, SOCK_WAKE_IO, POLL_ERR); | 1754 | sk_wake_async(sk, SOCK_WAKE_IO, POLL_ERR); |
1729 | read_unlock(&sk->sk_callback_lock); | 1755 | read_unlock(&sk->sk_callback_lock); |
@@ -1732,7 +1758,7 @@ static void sock_def_error_report(struct sock *sk) | |||
1732 | static void sock_def_readable(struct sock *sk, int len) | 1758 | static void sock_def_readable(struct sock *sk, int len) |
1733 | { | 1759 | { |
1734 | read_lock(&sk->sk_callback_lock); | 1760 | read_lock(&sk->sk_callback_lock); |
1735 | if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) | 1761 | if (sk_has_sleeper(sk)) |
1736 | wake_up_interruptible_sync_poll(sk->sk_sleep, POLLIN | | 1762 | wake_up_interruptible_sync_poll(sk->sk_sleep, POLLIN | |
1737 | POLLRDNORM | POLLRDBAND); | 1763 | POLLRDNORM | POLLRDBAND); |
1738 | sk_wake_async(sk, SOCK_WAKE_WAITD, POLL_IN); | 1764 | sk_wake_async(sk, SOCK_WAKE_WAITD, POLL_IN); |
@@ -1747,7 +1773,7 @@ static void sock_def_write_space(struct sock *sk) | |||
1747 | * progress. --DaveM | 1773 | * progress. --DaveM |
1748 | */ | 1774 | */ |
1749 | if ((atomic_read(&sk->sk_wmem_alloc) << 1) <= sk->sk_sndbuf) { | 1775 | if ((atomic_read(&sk->sk_wmem_alloc) << 1) <= sk->sk_sndbuf) { |
1750 | if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) | 1776 | if (sk_has_sleeper(sk)) |
1751 | wake_up_interruptible_sync_poll(sk->sk_sleep, POLLOUT | | 1777 | wake_up_interruptible_sync_poll(sk->sk_sleep, POLLOUT | |
1752 | POLLWRNORM | POLLWRBAND); | 1778 | POLLWRNORM | POLLWRBAND); |
1753 | 1779 | ||
@@ -1840,6 +1866,11 @@ void sock_init_data(struct socket *sock, struct sock *sk) | |||
1840 | 1866 | ||
1841 | sk->sk_stamp = ktime_set(-1L, 0); | 1867 | sk->sk_stamp = ktime_set(-1L, 0); |
1842 | 1868 | ||
1869 | /* | ||
1870 | * Before updating sk_refcnt, we must commit prior changes to memory | ||
1871 | * (Documentation/RCU/rculist_nulls.txt for details) | ||
1872 | */ | ||
1873 | smp_wmb(); | ||
1843 | atomic_set(&sk->sk_refcnt, 1); | 1874 | atomic_set(&sk->sk_refcnt, 1); |
1844 | atomic_set(&sk->sk_wmem_alloc, 1); | 1875 | atomic_set(&sk->sk_wmem_alloc, 1); |
1845 | atomic_set(&sk->sk_drops, 0); | 1876 | atomic_set(&sk->sk_drops, 0); |
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index 05ea7440d9e5..3e70faab2989 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c | |||
@@ -85,7 +85,7 @@ static inline __u32 dccp_v6_init_sequence(struct sk_buff *skb) | |||
85 | } | 85 | } |
86 | 86 | ||
87 | static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | 87 | static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, |
88 | int type, int code, int offset, __be32 info) | 88 | u8 type, u8 code, int offset, __be32 info) |
89 | { | 89 | { |
90 | struct ipv6hdr *hdr = (struct ipv6hdr *)skb->data; | 90 | struct ipv6hdr *hdr = (struct ipv6hdr *)skb->data; |
91 | const struct dccp_hdr *dh = (struct dccp_hdr *)(skb->data + offset); | 91 | const struct dccp_hdr *dh = (struct dccp_hdr *)(skb->data + offset); |
diff --git a/net/dccp/output.c b/net/dccp/output.c index c0e88c16d088..c96119fda688 100644 --- a/net/dccp/output.c +++ b/net/dccp/output.c | |||
@@ -196,7 +196,7 @@ void dccp_write_space(struct sock *sk) | |||
196 | { | 196 | { |
197 | read_lock(&sk->sk_callback_lock); | 197 | read_lock(&sk->sk_callback_lock); |
198 | 198 | ||
199 | if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) | 199 | if (sk_has_sleeper(sk)) |
200 | wake_up_interruptible(sk->sk_sleep); | 200 | wake_up_interruptible(sk->sk_sleep); |
201 | /* Should agree with poll, otherwise some programs break */ | 201 | /* Should agree with poll, otherwise some programs break */ |
202 | if (sock_writeable(sk)) | 202 | if (sock_writeable(sk)) |
diff --git a/net/dccp/proto.c b/net/dccp/proto.c index 314a1b5c033c..1bca9205104e 100644 --- a/net/dccp/proto.c +++ b/net/dccp/proto.c | |||
@@ -311,7 +311,7 @@ unsigned int dccp_poll(struct file *file, struct socket *sock, | |||
311 | unsigned int mask; | 311 | unsigned int mask; |
312 | struct sock *sk = sock->sk; | 312 | struct sock *sk = sock->sk; |
313 | 313 | ||
314 | poll_wait(file, sk->sk_sleep, wait); | 314 | sock_poll_wait(file, sk->sk_sleep, wait); |
315 | if (sk->sk_state == DCCP_LISTEN) | 315 | if (sk->sk_state == DCCP_LISTEN) |
316 | return inet_csk_listen_poll(sk); | 316 | return inet_csk_listen_poll(sk); |
317 | 317 | ||
@@ -1066,7 +1066,7 @@ static int __init dccp_init(void) | |||
1066 | (dccp_hashinfo.ehash_size - 1)) | 1066 | (dccp_hashinfo.ehash_size - 1)) |
1067 | dccp_hashinfo.ehash_size--; | 1067 | dccp_hashinfo.ehash_size--; |
1068 | dccp_hashinfo.ehash = (struct inet_ehash_bucket *) | 1068 | dccp_hashinfo.ehash = (struct inet_ehash_bucket *) |
1069 | __get_free_pages(GFP_ATOMIC, ehash_order); | 1069 | __get_free_pages(GFP_ATOMIC|__GFP_NOWARN, ehash_order); |
1070 | } while (!dccp_hashinfo.ehash && --ehash_order > 0); | 1070 | } while (!dccp_hashinfo.ehash && --ehash_order > 0); |
1071 | 1071 | ||
1072 | if (!dccp_hashinfo.ehash) { | 1072 | if (!dccp_hashinfo.ehash) { |
@@ -1091,7 +1091,7 @@ static int __init dccp_init(void) | |||
1091 | bhash_order > 0) | 1091 | bhash_order > 0) |
1092 | continue; | 1092 | continue; |
1093 | dccp_hashinfo.bhash = (struct inet_bind_hashbucket *) | 1093 | dccp_hashinfo.bhash = (struct inet_bind_hashbucket *) |
1094 | __get_free_pages(GFP_ATOMIC, bhash_order); | 1094 | __get_free_pages(GFP_ATOMIC|__GFP_NOWARN, bhash_order); |
1095 | } while (!dccp_hashinfo.bhash && --bhash_order >= 0); | 1095 | } while (!dccp_hashinfo.bhash && --bhash_order >= 0); |
1096 | 1096 | ||
1097 | if (!dccp_hashinfo.bhash) { | 1097 | if (!dccp_hashinfo.bhash) { |
@@ -1159,6 +1159,7 @@ static void __exit dccp_fini(void) | |||
1159 | kmem_cache_destroy(dccp_hashinfo.bind_bucket_cachep); | 1159 | kmem_cache_destroy(dccp_hashinfo.bind_bucket_cachep); |
1160 | dccp_ackvec_exit(); | 1160 | dccp_ackvec_exit(); |
1161 | dccp_sysctl_exit(); | 1161 | dccp_sysctl_exit(); |
1162 | percpu_counter_destroy(&dccp_orphan_count); | ||
1162 | } | 1163 | } |
1163 | 1164 | ||
1164 | module_init(dccp_init); | 1165 | module_init(dccp_init); |
diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c index a5e3a593e472..77d40289653c 100644 --- a/net/decnet/af_decnet.c +++ b/net/decnet/af_decnet.c | |||
@@ -1240,7 +1240,7 @@ static int dn_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
1240 | return val; | 1240 | return val; |
1241 | 1241 | ||
1242 | case TIOCOUTQ: | 1242 | case TIOCOUTQ: |
1243 | amount = sk->sk_sndbuf - atomic_read(&sk->sk_wmem_alloc); | 1243 | amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk); |
1244 | if (amount < 0) | 1244 | if (amount < 0) |
1245 | amount = 0; | 1245 | amount = 0; |
1246 | err = put_user(amount, (int __user *)arg); | 1246 | err = put_user(amount, (int __user *)arg); |
@@ -2413,6 +2413,8 @@ static void __exit decnet_exit(void) | |||
2413 | proc_net_remove(&init_net, "decnet"); | 2413 | proc_net_remove(&init_net, "decnet"); |
2414 | 2414 | ||
2415 | proto_unregister(&dn_proto); | 2415 | proto_unregister(&dn_proto); |
2416 | |||
2417 | rcu_barrier_bh(); /* Wait for completion of call_rcu_bh()'s */ | ||
2416 | } | 2418 | } |
2417 | module_exit(decnet_exit); | 2419 | module_exit(decnet_exit); |
2418 | #endif | 2420 | #endif |
diff --git a/net/dsa/mv88e6xxx.c b/net/dsa/mv88e6xxx.c index 4e4d8b5ad03d..efe661a9def4 100644 --- a/net/dsa/mv88e6xxx.c +++ b/net/dsa/mv88e6xxx.c | |||
@@ -418,7 +418,7 @@ static int mv88e6xxx_stats_wait(struct dsa_switch *ds) | |||
418 | int i; | 418 | int i; |
419 | 419 | ||
420 | for (i = 0; i < 10; i++) { | 420 | for (i = 0; i < 10; i++) { |
421 | ret = REG_READ(REG_GLOBAL2, 0x1d); | 421 | ret = REG_READ(REG_GLOBAL, 0x1d); |
422 | if ((ret & 0x8000) == 0) | 422 | if ((ret & 0x8000) == 0) |
423 | return 0; | 423 | return 0; |
424 | } | 424 | } |
diff --git a/net/econet/af_econet.c b/net/econet/af_econet.c index 8121bf0029e3..f0bbc57926cd 100644 --- a/net/econet/af_econet.c +++ b/net/econet/af_econet.c | |||
@@ -520,6 +520,7 @@ static int econet_getname(struct socket *sock, struct sockaddr *uaddr, | |||
520 | if (peer) | 520 | if (peer) |
521 | return -EOPNOTSUPP; | 521 | return -EOPNOTSUPP; |
522 | 522 | ||
523 | memset(sec, 0, sizeof(*sec)); | ||
523 | mutex_lock(&econet_mutex); | 524 | mutex_lock(&econet_mutex); |
524 | 525 | ||
525 | sk = sock->sk; | 526 | sk = sock->sk; |
@@ -540,8 +541,7 @@ static void econet_destroy_timer(unsigned long data) | |||
540 | { | 541 | { |
541 | struct sock *sk=(struct sock *)data; | 542 | struct sock *sk=(struct sock *)data; |
542 | 543 | ||
543 | if (!atomic_read(&sk->sk_wmem_alloc) && | 544 | if (!sk_has_allocations(sk)) { |
544 | !atomic_read(&sk->sk_rmem_alloc)) { | ||
545 | sk_free(sk); | 545 | sk_free(sk); |
546 | return; | 546 | return; |
547 | } | 547 | } |
@@ -579,8 +579,7 @@ static int econet_release(struct socket *sock) | |||
579 | 579 | ||
580 | skb_queue_purge(&sk->sk_receive_queue); | 580 | skb_queue_purge(&sk->sk_receive_queue); |
581 | 581 | ||
582 | if (atomic_read(&sk->sk_rmem_alloc) || | 582 | if (sk_has_allocations(sk)) { |
583 | atomic_read(&sk->sk_wmem_alloc)) { | ||
584 | sk->sk_timer.data = (unsigned long)sk; | 583 | sk->sk_timer.data = (unsigned long)sk; |
585 | sk->sk_timer.expires = jiffies + HZ; | 584 | sk->sk_timer.expires = jiffies + HZ; |
586 | sk->sk_timer.function = econet_destroy_timer; | 585 | sk->sk_timer.function = econet_destroy_timer; |
diff --git a/net/ieee802154/af_ieee802154.c b/net/ieee802154/af_ieee802154.c index 882a927cefae..af661805b9fa 100644 --- a/net/ieee802154/af_ieee802154.c +++ b/net/ieee802154/af_ieee802154.c | |||
@@ -39,14 +39,6 @@ | |||
39 | 39 | ||
40 | #include "af802154.h" | 40 | #include "af802154.h" |
41 | 41 | ||
42 | #define DBG_DUMP(data, len) { \ | ||
43 | int i; \ | ||
44 | pr_debug("function: %s: data: len %d:\n", __func__, len); \ | ||
45 | for (i = 0; i < len; i++) {\ | ||
46 | pr_debug("%02x: %02x\n", i, (data)[i]); \ | ||
47 | } \ | ||
48 | } | ||
49 | |||
50 | /* | 42 | /* |
51 | * Utility function for families | 43 | * Utility function for families |
52 | */ | 44 | */ |
@@ -144,7 +136,7 @@ static int ieee802154_dev_ioctl(struct sock *sk, struct ifreq __user *arg, | |||
144 | unsigned int cmd) | 136 | unsigned int cmd) |
145 | { | 137 | { |
146 | struct ifreq ifr; | 138 | struct ifreq ifr; |
147 | int ret = -EINVAL; | 139 | int ret = -ENOIOCTLCMD; |
148 | struct net_device *dev; | 140 | struct net_device *dev; |
149 | 141 | ||
150 | if (copy_from_user(&ifr, arg, sizeof(struct ifreq))) | 142 | if (copy_from_user(&ifr, arg, sizeof(struct ifreq))) |
@@ -154,8 +146,10 @@ static int ieee802154_dev_ioctl(struct sock *sk, struct ifreq __user *arg, | |||
154 | 146 | ||
155 | dev_load(sock_net(sk), ifr.ifr_name); | 147 | dev_load(sock_net(sk), ifr.ifr_name); |
156 | dev = dev_get_by_name(sock_net(sk), ifr.ifr_name); | 148 | dev = dev_get_by_name(sock_net(sk), ifr.ifr_name); |
157 | if (dev->type == ARPHRD_IEEE802154 || | 149 | |
158 | dev->type == ARPHRD_IEEE802154_PHY) | 150 | if ((dev->type == ARPHRD_IEEE802154 || |
151 | dev->type == ARPHRD_IEEE802154_PHY) && | ||
152 | dev->netdev_ops->ndo_do_ioctl) | ||
159 | ret = dev->netdev_ops->ndo_do_ioctl(dev, &ifr, cmd); | 153 | ret = dev->netdev_ops->ndo_do_ioctl(dev, &ifr, cmd); |
160 | 154 | ||
161 | if (!ret && copy_to_user(arg, &ifr, sizeof(struct ifreq))) | 155 | if (!ret && copy_to_user(arg, &ifr, sizeof(struct ifreq))) |
@@ -302,10 +296,12 @@ static struct net_proto_family ieee802154_family_ops = { | |||
302 | static int ieee802154_rcv(struct sk_buff *skb, struct net_device *dev, | 296 | static int ieee802154_rcv(struct sk_buff *skb, struct net_device *dev, |
303 | struct packet_type *pt, struct net_device *orig_dev) | 297 | struct packet_type *pt, struct net_device *orig_dev) |
304 | { | 298 | { |
305 | DBG_DUMP(skb->data, skb->len); | ||
306 | if (!netif_running(dev)) | 299 | if (!netif_running(dev)) |
307 | return -ENODEV; | 300 | return -ENODEV; |
308 | pr_debug("got frame, type %d, dev %p\n", dev->type, dev); | 301 | pr_debug("got frame, type %d, dev %p\n", dev->type, dev); |
302 | #ifdef DEBUG | ||
303 | print_hex_dump_bytes("ieee802154_rcv ", DUMP_PREFIX_NONE, skb->data, skb->len); | ||
304 | #endif | ||
309 | 305 | ||
310 | if (!net_eq(dev_net(dev), &init_net)) | 306 | if (!net_eq(dev_net(dev), &init_net)) |
311 | goto drop; | 307 | goto drop; |
diff --git a/net/ieee802154/dgram.c b/net/ieee802154/dgram.c index 1779677aed46..ba8b214dda8f 100644 --- a/net/ieee802154/dgram.c +++ b/net/ieee802154/dgram.c | |||
@@ -126,7 +126,8 @@ static int dgram_ioctl(struct sock *sk, int cmd, unsigned long arg) | |||
126 | switch (cmd) { | 126 | switch (cmd) { |
127 | case SIOCOUTQ: | 127 | case SIOCOUTQ: |
128 | { | 128 | { |
129 | int amount = atomic_read(&sk->sk_wmem_alloc); | 129 | int amount = sk_wmem_alloc_get(sk); |
130 | |||
130 | return put_user(amount, (int __user *)arg); | 131 | return put_user(amount, (int __user *)arg); |
131 | } | 132 | } |
132 | 133 | ||
@@ -376,6 +377,18 @@ int ieee802154_dgram_deliver(struct net_device *dev, struct sk_buff *skb) | |||
376 | return ret; | 377 | return ret; |
377 | } | 378 | } |
378 | 379 | ||
380 | static int dgram_getsockopt(struct sock *sk, int level, int optname, | ||
381 | char __user *optval, int __user *optlen) | ||
382 | { | ||
383 | return -EOPNOTSUPP; | ||
384 | } | ||
385 | |||
386 | static int dgram_setsockopt(struct sock *sk, int level, int optname, | ||
387 | char __user *optval, int __user optlen) | ||
388 | { | ||
389 | return -EOPNOTSUPP; | ||
390 | } | ||
391 | |||
379 | struct proto ieee802154_dgram_prot = { | 392 | struct proto ieee802154_dgram_prot = { |
380 | .name = "IEEE-802.15.4-MAC", | 393 | .name = "IEEE-802.15.4-MAC", |
381 | .owner = THIS_MODULE, | 394 | .owner = THIS_MODULE, |
@@ -390,5 +403,7 @@ struct proto ieee802154_dgram_prot = { | |||
390 | .connect = dgram_connect, | 403 | .connect = dgram_connect, |
391 | .disconnect = dgram_disconnect, | 404 | .disconnect = dgram_disconnect, |
392 | .ioctl = dgram_ioctl, | 405 | .ioctl = dgram_ioctl, |
406 | .getsockopt = dgram_getsockopt, | ||
407 | .setsockopt = dgram_setsockopt, | ||
393 | }; | 408 | }; |
394 | 409 | ||
diff --git a/net/ieee802154/netlink.c b/net/ieee802154/netlink.c index 105ad10876af..27eda9fdf3c2 100644 --- a/net/ieee802154/netlink.c +++ b/net/ieee802154/netlink.c | |||
@@ -276,6 +276,9 @@ static struct net_device *ieee802154_nl_get_dev(struct genl_info *info) | |||
276 | else | 276 | else |
277 | return NULL; | 277 | return NULL; |
278 | 278 | ||
279 | if (!dev) | ||
280 | return NULL; | ||
281 | |||
279 | if (dev->type != ARPHRD_IEEE802154) { | 282 | if (dev->type != ARPHRD_IEEE802154) { |
280 | dev_put(dev); | 283 | dev_put(dev); |
281 | return NULL; | 284 | return NULL; |
@@ -521,3 +524,6 @@ static void __exit ieee802154_nl_exit(void) | |||
521 | } | 524 | } |
522 | module_exit(ieee802154_nl_exit); | 525 | module_exit(ieee802154_nl_exit); |
523 | 526 | ||
527 | MODULE_LICENSE("GPL v2"); | ||
528 | MODULE_DESCRIPTION("ieee 802.15.4 configuration interface"); | ||
529 | |||
diff --git a/net/ieee802154/raw.c b/net/ieee802154/raw.c index fca44d59f97e..9315977c4c61 100644 --- a/net/ieee802154/raw.c +++ b/net/ieee802154/raw.c | |||
@@ -238,6 +238,18 @@ void ieee802154_raw_deliver(struct net_device *dev, struct sk_buff *skb) | |||
238 | read_unlock(&raw_lock); | 238 | read_unlock(&raw_lock); |
239 | } | 239 | } |
240 | 240 | ||
241 | static int raw_getsockopt(struct sock *sk, int level, int optname, | ||
242 | char __user *optval, int __user *optlen) | ||
243 | { | ||
244 | return -EOPNOTSUPP; | ||
245 | } | ||
246 | |||
247 | static int raw_setsockopt(struct sock *sk, int level, int optname, | ||
248 | char __user *optval, int __user optlen) | ||
249 | { | ||
250 | return -EOPNOTSUPP; | ||
251 | } | ||
252 | |||
241 | struct proto ieee802154_raw_prot = { | 253 | struct proto ieee802154_raw_prot = { |
242 | .name = "IEEE-802.15.4-RAW", | 254 | .name = "IEEE-802.15.4-RAW", |
243 | .owner = THIS_MODULE, | 255 | .owner = THIS_MODULE, |
@@ -250,5 +262,7 @@ struct proto ieee802154_raw_prot = { | |||
250 | .unhash = raw_unhash, | 262 | .unhash = raw_unhash, |
251 | .connect = raw_connect, | 263 | .connect = raw_connect, |
252 | .disconnect = raw_disconnect, | 264 | .disconnect = raw_disconnect, |
265 | .getsockopt = raw_getsockopt, | ||
266 | .setsockopt = raw_setsockopt, | ||
253 | }; | 267 | }; |
254 | 268 | ||
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index 8a3881e28aca..090e9991ac2a 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c | |||
@@ -801,11 +801,8 @@ static int arp_process(struct sk_buff *skb) | |||
801 | * cache. | 801 | * cache. |
802 | */ | 802 | */ |
803 | 803 | ||
804 | /* | 804 | /* Special case: IPv4 duplicate address detection packet (RFC2131) */ |
805 | * Special case: IPv4 duplicate address detection packet (RFC2131) | 805 | if (sip == 0) { |
806 | * and Gratuitous ARP/ARP Announce. (RFC3927, Section 2.4) | ||
807 | */ | ||
808 | if (sip == 0 || tip == sip) { | ||
809 | if (arp->ar_op == htons(ARPOP_REQUEST) && | 806 | if (arp->ar_op == htons(ARPOP_REQUEST) && |
810 | inet_addr_type(net, tip) == RTN_LOCAL && | 807 | inet_addr_type(net, tip) == RTN_LOCAL && |
811 | !arp_ignore(in_dev, sip, tip)) | 808 | !arp_ignore(in_dev, sip, tip)) |
@@ -1307,7 +1304,9 @@ static void arp_format_neigh_entry(struct seq_file *seq, | |||
1307 | hbuffer[k++] = hex_asc_lo(n->ha[j]); | 1304 | hbuffer[k++] = hex_asc_lo(n->ha[j]); |
1308 | hbuffer[k++] = ':'; | 1305 | hbuffer[k++] = ':'; |
1309 | } | 1306 | } |
1310 | hbuffer[--k] = 0; | 1307 | if (k != 0) |
1308 | --k; | ||
1309 | hbuffer[k] = 0; | ||
1311 | #if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE) | 1310 | #if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE) |
1312 | } | 1311 | } |
1313 | #endif | 1312 | #endif |
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index d1a39b1277d6..63c2fa7b68c4 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c | |||
@@ -316,8 +316,8 @@ static inline void check_tnode(const struct tnode *tn) | |||
316 | 316 | ||
317 | static const int halve_threshold = 25; | 317 | static const int halve_threshold = 25; |
318 | static const int inflate_threshold = 50; | 318 | static const int inflate_threshold = 50; |
319 | static const int halve_threshold_root = 8; | 319 | static const int halve_threshold_root = 15; |
320 | static const int inflate_threshold_root = 15; | 320 | static const int inflate_threshold_root = 25; |
321 | 321 | ||
322 | 322 | ||
323 | static void __alias_free_mem(struct rcu_head *head) | 323 | static void __alias_free_mem(struct rcu_head *head) |
@@ -391,13 +391,8 @@ static inline void tnode_free(struct tnode *tn) | |||
391 | static void tnode_free_safe(struct tnode *tn) | 391 | static void tnode_free_safe(struct tnode *tn) |
392 | { | 392 | { |
393 | BUG_ON(IS_LEAF(tn)); | 393 | BUG_ON(IS_LEAF(tn)); |
394 | 394 | tn->tnode_free = tnode_free_head; | |
395 | if (node_parent((struct node *) tn)) { | 395 | tnode_free_head = tn; |
396 | tn->tnode_free = tnode_free_head; | ||
397 | tnode_free_head = tn; | ||
398 | } else { | ||
399 | tnode_free(tn); | ||
400 | } | ||
401 | } | 396 | } |
402 | 397 | ||
403 | static void tnode_free_flush(void) | 398 | static void tnode_free_flush(void) |
@@ -1009,7 +1004,7 @@ fib_find_node(struct trie *t, u32 key) | |||
1009 | return NULL; | 1004 | return NULL; |
1010 | } | 1005 | } |
1011 | 1006 | ||
1012 | static struct node *trie_rebalance(struct trie *t, struct tnode *tn) | 1007 | static void trie_rebalance(struct trie *t, struct tnode *tn) |
1013 | { | 1008 | { |
1014 | int wasfull; | 1009 | int wasfull; |
1015 | t_key cindex, key; | 1010 | t_key cindex, key; |
@@ -1026,6 +1021,9 @@ static struct node *trie_rebalance(struct trie *t, struct tnode *tn) | |||
1026 | (struct node *)tn, wasfull); | 1021 | (struct node *)tn, wasfull); |
1027 | 1022 | ||
1028 | tp = node_parent((struct node *) tn); | 1023 | tp = node_parent((struct node *) tn); |
1024 | if (!tp) | ||
1025 | rcu_assign_pointer(t->trie, (struct node *)tn); | ||
1026 | |||
1029 | tnode_free_flush(); | 1027 | tnode_free_flush(); |
1030 | if (!tp) | 1028 | if (!tp) |
1031 | break; | 1029 | break; |
@@ -1033,12 +1031,13 @@ static struct node *trie_rebalance(struct trie *t, struct tnode *tn) | |||
1033 | } | 1031 | } |
1034 | 1032 | ||
1035 | /* Handle last (top) tnode */ | 1033 | /* Handle last (top) tnode */ |
1036 | if (IS_TNODE(tn)) { | 1034 | if (IS_TNODE(tn)) |
1037 | tn = (struct tnode *)resize(t, (struct tnode *)tn); | 1035 | tn = (struct tnode *)resize(t, (struct tnode *)tn); |
1038 | tnode_free_flush(); | ||
1039 | } | ||
1040 | 1036 | ||
1041 | return (struct node *)tn; | 1037 | rcu_assign_pointer(t->trie, (struct node *)tn); |
1038 | tnode_free_flush(); | ||
1039 | |||
1040 | return; | ||
1042 | } | 1041 | } |
1043 | 1042 | ||
1044 | /* only used from updater-side */ | 1043 | /* only used from updater-side */ |
@@ -1186,7 +1185,7 @@ static struct list_head *fib_insert_node(struct trie *t, u32 key, int plen) | |||
1186 | 1185 | ||
1187 | /* Rebalance the trie */ | 1186 | /* Rebalance the trie */ |
1188 | 1187 | ||
1189 | rcu_assign_pointer(t->trie, trie_rebalance(t, tp)); | 1188 | trie_rebalance(t, tp); |
1190 | done: | 1189 | done: |
1191 | return fa_head; | 1190 | return fa_head; |
1192 | } | 1191 | } |
@@ -1605,7 +1604,7 @@ static void trie_leaf_remove(struct trie *t, struct leaf *l) | |||
1605 | if (tp) { | 1604 | if (tp) { |
1606 | t_key cindex = tkey_extract_bits(l->key, tp->pos, tp->bits); | 1605 | t_key cindex = tkey_extract_bits(l->key, tp->pos, tp->bits); |
1607 | put_child(t, (struct tnode *)tp, cindex, NULL); | 1606 | put_child(t, (struct tnode *)tp, cindex, NULL); |
1608 | rcu_assign_pointer(t->trie, trie_rebalance(t, tp)); | 1607 | trie_rebalance(t, tp); |
1609 | } else | 1608 | } else |
1610 | rcu_assign_pointer(t->trie, NULL); | 1609 | rcu_assign_pointer(t->trie, NULL); |
1611 | 1610 | ||
diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c index b0b273503e2a..a706a47f4dbb 100644 --- a/net/ipv4/inet_diag.c +++ b/net/ipv4/inet_diag.c | |||
@@ -156,10 +156,10 @@ static int inet_csk_diag_fill(struct sock *sk, | |||
156 | r->idiag_inode = sock_i_ino(sk); | 156 | r->idiag_inode = sock_i_ino(sk); |
157 | 157 | ||
158 | if (minfo) { | 158 | if (minfo) { |
159 | minfo->idiag_rmem = atomic_read(&sk->sk_rmem_alloc); | 159 | minfo->idiag_rmem = sk_rmem_alloc_get(sk); |
160 | minfo->idiag_wmem = sk->sk_wmem_queued; | 160 | minfo->idiag_wmem = sk->sk_wmem_queued; |
161 | minfo->idiag_fmem = sk->sk_forward_alloc; | 161 | minfo->idiag_fmem = sk->sk_forward_alloc; |
162 | minfo->idiag_tmem = atomic_read(&sk->sk_wmem_alloc); | 162 | minfo->idiag_tmem = sk_wmem_alloc_get(sk); |
163 | } | 163 | } |
164 | 164 | ||
165 | handler->idiag_get_info(sk, r, info); | 165 | handler->idiag_get_info(sk, r, info); |
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 44e2a3d2359a..82c11dd10a62 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c | |||
@@ -735,10 +735,10 @@ static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) | |||
735 | } | 735 | } |
736 | 736 | ||
737 | tos = tiph->tos; | 737 | tos = tiph->tos; |
738 | if (tos&1) { | 738 | if (tos == 1) { |
739 | tos = 0; | ||
739 | if (skb->protocol == htons(ETH_P_IP)) | 740 | if (skb->protocol == htons(ETH_P_IP)) |
740 | tos = old_iph->tos; | 741 | tos = old_iph->tos; |
741 | tos &= ~1; | ||
742 | } | 742 | } |
743 | 743 | ||
744 | { | 744 | { |
@@ -951,7 +951,7 @@ static int ipgre_tunnel_bind_dev(struct net_device *dev) | |||
951 | addend += 4; | 951 | addend += 4; |
952 | } | 952 | } |
953 | dev->needed_headroom = addend + hlen; | 953 | dev->needed_headroom = addend + hlen; |
954 | mtu -= dev->hard_header_len - addend; | 954 | mtu -= dev->hard_header_len + addend; |
955 | 955 | ||
956 | if (mtu < 68) | 956 | if (mtu < 68) |
957 | mtu = 68; | 957 | mtu = 68; |
diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c index 490ce20faf38..db46b4b5b2b9 100644 --- a/net/ipv4/ip_input.c +++ b/net/ipv4/ip_input.c | |||
@@ -440,6 +440,9 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, | |||
440 | /* Remove any debris in the socket control block */ | 440 | /* Remove any debris in the socket control block */ |
441 | memset(IPCB(skb), 0, sizeof(struct inet_skb_parm)); | 441 | memset(IPCB(skb), 0, sizeof(struct inet_skb_parm)); |
442 | 442 | ||
443 | /* Must drop socket now because of tproxy. */ | ||
444 | skb_orphan(skb); | ||
445 | |||
443 | return NF_HOOK(PF_INET, NF_INET_PRE_ROUTING, skb, dev, NULL, | 446 | return NF_HOOK(PF_INET, NF_INET_PRE_ROUTING, skb, dev, NULL, |
444 | ip_rcv_finish); | 447 | ip_rcv_finish); |
445 | 448 | ||
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 247026282669..7ffcd96fe591 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c | |||
@@ -813,6 +813,8 @@ int ip_append_data(struct sock *sk, | |||
813 | inet->cork.addr = ipc->addr; | 813 | inet->cork.addr = ipc->addr; |
814 | } | 814 | } |
815 | rt = *rtp; | 815 | rt = *rtp; |
816 | if (unlikely(!rt)) | ||
817 | return -EFAULT; | ||
816 | /* | 818 | /* |
817 | * We steal reference to this route, caller should not release it | 819 | * We steal reference to this route, caller should not release it |
818 | */ | 820 | */ |
@@ -1243,7 +1245,6 @@ int ip_push_pending_frames(struct sock *sk) | |||
1243 | skb->len += tmp_skb->len; | 1245 | skb->len += tmp_skb->len; |
1244 | skb->data_len += tmp_skb->len; | 1246 | skb->data_len += tmp_skb->len; |
1245 | skb->truesize += tmp_skb->truesize; | 1247 | skb->truesize += tmp_skb->truesize; |
1246 | __sock_put(tmp_skb->sk); | ||
1247 | tmp_skb->destructor = NULL; | 1248 | tmp_skb->destructor = NULL; |
1248 | tmp_skb->sk = NULL; | 1249 | tmp_skb->sk = NULL; |
1249 | } | 1250 | } |
diff --git a/net/ipv4/netfilter/nf_nat_helper.c b/net/ipv4/netfilter/nf_nat_helper.c index 155c008626c8..09172a65d9b6 100644 --- a/net/ipv4/netfilter/nf_nat_helper.c +++ b/net/ipv4/netfilter/nf_nat_helper.c | |||
@@ -191,7 +191,8 @@ nf_nat_mangle_tcp_packet(struct sk_buff *skb, | |||
191 | ct, ctinfo); | 191 | ct, ctinfo); |
192 | /* Tell TCP window tracking about seq change */ | 192 | /* Tell TCP window tracking about seq change */ |
193 | nf_conntrack_tcp_update(skb, ip_hdrlen(skb), | 193 | nf_conntrack_tcp_update(skb, ip_hdrlen(skb), |
194 | ct, CTINFO2DIR(ctinfo)); | 194 | ct, CTINFO2DIR(ctinfo), |
195 | (int)rep_len - (int)match_len); | ||
195 | 196 | ||
196 | nf_conntrack_event_cache(IPCT_NATSEQADJ, ct); | 197 | nf_conntrack_event_cache(IPCT_NATSEQADJ, ct); |
197 | } | 198 | } |
@@ -377,6 +378,7 @@ nf_nat_seq_adjust(struct sk_buff *skb, | |||
377 | struct tcphdr *tcph; | 378 | struct tcphdr *tcph; |
378 | int dir; | 379 | int dir; |
379 | __be32 newseq, newack; | 380 | __be32 newseq, newack; |
381 | s16 seqoff, ackoff; | ||
380 | struct nf_conn_nat *nat = nfct_nat(ct); | 382 | struct nf_conn_nat *nat = nfct_nat(ct); |
381 | struct nf_nat_seq *this_way, *other_way; | 383 | struct nf_nat_seq *this_way, *other_way; |
382 | 384 | ||
@@ -390,15 +392,18 @@ nf_nat_seq_adjust(struct sk_buff *skb, | |||
390 | 392 | ||
391 | tcph = (void *)skb->data + ip_hdrlen(skb); | 393 | tcph = (void *)skb->data + ip_hdrlen(skb); |
392 | if (after(ntohl(tcph->seq), this_way->correction_pos)) | 394 | if (after(ntohl(tcph->seq), this_way->correction_pos)) |
393 | newseq = htonl(ntohl(tcph->seq) + this_way->offset_after); | 395 | seqoff = this_way->offset_after; |
394 | else | 396 | else |
395 | newseq = htonl(ntohl(tcph->seq) + this_way->offset_before); | 397 | seqoff = this_way->offset_before; |
396 | 398 | ||
397 | if (after(ntohl(tcph->ack_seq) - other_way->offset_before, | 399 | if (after(ntohl(tcph->ack_seq) - other_way->offset_before, |
398 | other_way->correction_pos)) | 400 | other_way->correction_pos)) |
399 | newack = htonl(ntohl(tcph->ack_seq) - other_way->offset_after); | 401 | ackoff = other_way->offset_after; |
400 | else | 402 | else |
401 | newack = htonl(ntohl(tcph->ack_seq) - other_way->offset_before); | 403 | ackoff = other_way->offset_before; |
404 | |||
405 | newseq = htonl(ntohl(tcph->seq) + seqoff); | ||
406 | newack = htonl(ntohl(tcph->ack_seq) - ackoff); | ||
402 | 407 | ||
403 | inet_proto_csum_replace4(&tcph->check, skb, tcph->seq, newseq, 0); | 408 | inet_proto_csum_replace4(&tcph->check, skb, tcph->seq, newseq, 0); |
404 | inet_proto_csum_replace4(&tcph->check, skb, tcph->ack_seq, newack, 0); | 409 | inet_proto_csum_replace4(&tcph->check, skb, tcph->ack_seq, newack, 0); |
@@ -413,7 +418,7 @@ nf_nat_seq_adjust(struct sk_buff *skb, | |||
413 | if (!nf_nat_sack_adjust(skb, tcph, ct, ctinfo)) | 418 | if (!nf_nat_sack_adjust(skb, tcph, ct, ctinfo)) |
414 | return 0; | 419 | return 0; |
415 | 420 | ||
416 | nf_conntrack_tcp_update(skb, ip_hdrlen(skb), ct, dir); | 421 | nf_conntrack_tcp_update(skb, ip_hdrlen(skb), ct, dir, seqoff); |
417 | 422 | ||
418 | return 1; | 423 | return 1; |
419 | } | 424 | } |
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index 3dc9171a272f..2979f14bb188 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c | |||
@@ -799,7 +799,8 @@ static int raw_ioctl(struct sock *sk, int cmd, unsigned long arg) | |||
799 | { | 799 | { |
800 | switch (cmd) { | 800 | switch (cmd) { |
801 | case SIOCOUTQ: { | 801 | case SIOCOUTQ: { |
802 | int amount = atomic_read(&sk->sk_wmem_alloc); | 802 | int amount = sk_wmem_alloc_get(sk); |
803 | |||
803 | return put_user(amount, (int __user *)arg); | 804 | return put_user(amount, (int __user *)arg); |
804 | } | 805 | } |
805 | case SIOCINQ: { | 806 | case SIOCINQ: { |
@@ -935,8 +936,8 @@ static void raw_sock_seq_show(struct seq_file *seq, struct sock *sp, int i) | |||
935 | seq_printf(seq, "%4d: %08X:%04X %08X:%04X" | 936 | seq_printf(seq, "%4d: %08X:%04X %08X:%04X" |
936 | " %02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p %d\n", | 937 | " %02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p %d\n", |
937 | i, src, srcp, dest, destp, sp->sk_state, | 938 | i, src, srcp, dest, destp, sp->sk_state, |
938 | atomic_read(&sp->sk_wmem_alloc), | 939 | sk_wmem_alloc_get(sp), |
939 | atomic_read(&sp->sk_rmem_alloc), | 940 | sk_rmem_alloc_get(sp), |
940 | 0, 0L, 0, sock_i_uid(sp), 0, sock_i_ino(sp), | 941 | 0, 0L, 0, sock_i_uid(sp), 0, sock_i_ino(sp), |
941 | atomic_read(&sp->sk_refcnt), sp, atomic_read(&sp->sk_drops)); | 942 | atomic_read(&sp->sk_refcnt), sp, atomic_read(&sp->sk_drops)); |
942 | } | 943 | } |
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index cd76b3cb7092..278f46f5011b 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
@@ -1085,8 +1085,35 @@ restart: | |||
1085 | now = jiffies; | 1085 | now = jiffies; |
1086 | 1086 | ||
1087 | if (!rt_caching(dev_net(rt->u.dst.dev))) { | 1087 | if (!rt_caching(dev_net(rt->u.dst.dev))) { |
1088 | rt_drop(rt); | 1088 | /* |
1089 | return 0; | 1089 | * If we're not caching, just tell the caller we |
1090 | * were successful and don't touch the route. The | ||
1091 | * caller hold the sole reference to the cache entry, and | ||
1092 | * it will be released when the caller is done with it. | ||
1093 | * If we drop it here, the callers have no way to resolve routes | ||
1094 | * when we're not caching. Instead, just point *rp at rt, so | ||
1095 | * the caller gets a single use out of the route | ||
1096 | * Note that we do rt_free on this new route entry, so that | ||
1097 | * once its refcount hits zero, we are still able to reap it | ||
1098 | * (Thanks Alexey) | ||
1099 | * Note also the rt_free uses call_rcu. We don't actually | ||
1100 | * need rcu protection here, this is just our path to get | ||
1101 | * on the route gc list. | ||
1102 | */ | ||
1103 | |||
1104 | if (rt->rt_type == RTN_UNICAST || rt->fl.iif == 0) { | ||
1105 | int err = arp_bind_neighbour(&rt->u.dst); | ||
1106 | if (err) { | ||
1107 | if (net_ratelimit()) | ||
1108 | printk(KERN_WARNING | ||
1109 | "Neighbour table failure & not caching routes.\n"); | ||
1110 | rt_drop(rt); | ||
1111 | return err; | ||
1112 | } | ||
1113 | } | ||
1114 | |||
1115 | rt_free(rt); | ||
1116 | goto skip_hashing; | ||
1090 | } | 1117 | } |
1091 | 1118 | ||
1092 | rthp = &rt_hash_table[hash].chain; | 1119 | rthp = &rt_hash_table[hash].chain; |
@@ -1203,7 +1230,8 @@ restart: | |||
1203 | #if RT_CACHE_DEBUG >= 2 | 1230 | #if RT_CACHE_DEBUG >= 2 |
1204 | if (rt->u.dst.rt_next) { | 1231 | if (rt->u.dst.rt_next) { |
1205 | struct rtable *trt; | 1232 | struct rtable *trt; |
1206 | printk(KERN_DEBUG "rt_cache @%02x: %pI4", hash, &rt->rt_dst); | 1233 | printk(KERN_DEBUG "rt_cache @%02x: %pI4", |
1234 | hash, &rt->rt_dst); | ||
1207 | for (trt = rt->u.dst.rt_next; trt; trt = trt->u.dst.rt_next) | 1235 | for (trt = rt->u.dst.rt_next; trt; trt = trt->u.dst.rt_next) |
1208 | printk(" . %pI4", &trt->rt_dst); | 1236 | printk(" . %pI4", &trt->rt_dst); |
1209 | printk("\n"); | 1237 | printk("\n"); |
@@ -1217,6 +1245,8 @@ restart: | |||
1217 | rcu_assign_pointer(rt_hash_table[hash].chain, rt); | 1245 | rcu_assign_pointer(rt_hash_table[hash].chain, rt); |
1218 | 1246 | ||
1219 | spin_unlock_bh(rt_hash_lock_addr(hash)); | 1247 | spin_unlock_bh(rt_hash_lock_addr(hash)); |
1248 | |||
1249 | skip_hashing: | ||
1220 | if (rp) | 1250 | if (rp) |
1221 | *rp = rt; | 1251 | *rp = rt; |
1222 | else | 1252 | else |
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 17b89c523f9d..91145244ea63 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
@@ -339,7 +339,7 @@ unsigned int tcp_poll(struct file *file, struct socket *sock, poll_table *wait) | |||
339 | struct sock *sk = sock->sk; | 339 | struct sock *sk = sock->sk; |
340 | struct tcp_sock *tp = tcp_sk(sk); | 340 | struct tcp_sock *tp = tcp_sk(sk); |
341 | 341 | ||
342 | poll_wait(file, sk->sk_sleep, wait); | 342 | sock_poll_wait(file, sk->sk_sleep, wait); |
343 | if (sk->sk_state == TCP_LISTEN) | 343 | if (sk->sk_state == TCP_LISTEN) |
344 | return inet_csk_listen_poll(sk); | 344 | return inet_csk_listen_poll(sk); |
345 | 345 | ||
@@ -903,13 +903,17 @@ int tcp_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, | |||
903 | iov++; | 903 | iov++; |
904 | 904 | ||
905 | while (seglen > 0) { | 905 | while (seglen > 0) { |
906 | int copy; | 906 | int copy = 0; |
907 | int max = size_goal; | ||
907 | 908 | ||
908 | skb = tcp_write_queue_tail(sk); | 909 | skb = tcp_write_queue_tail(sk); |
910 | if (tcp_send_head(sk)) { | ||
911 | if (skb->ip_summed == CHECKSUM_NONE) | ||
912 | max = mss_now; | ||
913 | copy = max - skb->len; | ||
914 | } | ||
909 | 915 | ||
910 | if (!tcp_send_head(sk) || | 916 | if (copy <= 0) { |
911 | (copy = size_goal - skb->len) <= 0) { | ||
912 | |||
913 | new_segment: | 917 | new_segment: |
914 | /* Allocate new segment. If the interface is SG, | 918 | /* Allocate new segment. If the interface is SG, |
915 | * allocate skb fitting to single page. | 919 | * allocate skb fitting to single page. |
@@ -930,6 +934,7 @@ new_segment: | |||
930 | 934 | ||
931 | skb_entail(sk, skb); | 935 | skb_entail(sk, skb); |
932 | copy = size_goal; | 936 | copy = size_goal; |
937 | max = size_goal; | ||
933 | } | 938 | } |
934 | 939 | ||
935 | /* Try to append data to the end of skb. */ | 940 | /* Try to append data to the end of skb. */ |
@@ -1028,7 +1033,7 @@ new_segment: | |||
1028 | if ((seglen -= copy) == 0 && iovlen == 0) | 1033 | if ((seglen -= copy) == 0 && iovlen == 0) |
1029 | goto out; | 1034 | goto out; |
1030 | 1035 | ||
1031 | if (skb->len < size_goal || (flags & MSG_OOB)) | 1036 | if (skb->len < max || (flags & MSG_OOB)) |
1032 | continue; | 1037 | continue; |
1033 | 1038 | ||
1034 | if (forced_push(tp)) { | 1039 | if (forced_push(tp)) { |
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 5a1ca2698c88..6d88219c5e22 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -1160,6 +1160,7 @@ struct request_sock_ops tcp_request_sock_ops __read_mostly = { | |||
1160 | #ifdef CONFIG_TCP_MD5SIG | 1160 | #ifdef CONFIG_TCP_MD5SIG |
1161 | static struct tcp_request_sock_ops tcp_request_sock_ipv4_ops = { | 1161 | static struct tcp_request_sock_ops tcp_request_sock_ipv4_ops = { |
1162 | .md5_lookup = tcp_v4_reqsk_md5_lookup, | 1162 | .md5_lookup = tcp_v4_reqsk_md5_lookup, |
1163 | .calc_md5_hash = tcp_v4_md5_hash_skb, | ||
1163 | }; | 1164 | }; |
1164 | #endif | 1165 | #endif |
1165 | 1166 | ||
@@ -1373,7 +1374,7 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
1373 | */ | 1374 | */ |
1374 | char *newkey = kmemdup(key->key, key->keylen, GFP_ATOMIC); | 1375 | char *newkey = kmemdup(key->key, key->keylen, GFP_ATOMIC); |
1375 | if (newkey != NULL) | 1376 | if (newkey != NULL) |
1376 | tcp_v4_md5_do_add(newsk, inet_sk(sk)->daddr, | 1377 | tcp_v4_md5_do_add(newsk, newinet->daddr, |
1377 | newkey, key->keylen); | 1378 | newkey, key->keylen); |
1378 | newsk->sk_route_caps &= ~NETIF_F_GSO_MASK; | 1379 | newsk->sk_route_caps &= ~NETIF_F_GSO_MASK; |
1379 | } | 1380 | } |
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index 43bbba7926ee..f8d67ccc64f3 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c | |||
@@ -128,7 +128,8 @@ tcp_timewait_state_process(struct inet_timewait_sock *tw, struct sk_buff *skb, | |||
128 | goto kill_with_rst; | 128 | goto kill_with_rst; |
129 | 129 | ||
130 | /* Dup ACK? */ | 130 | /* Dup ACK? */ |
131 | if (!after(TCP_SKB_CB(skb)->end_seq, tcptw->tw_rcv_nxt) || | 131 | if (!th->ack || |
132 | !after(TCP_SKB_CB(skb)->end_seq, tcptw->tw_rcv_nxt) || | ||
132 | TCP_SKB_CB(skb)->end_seq == TCP_SKB_CB(skb)->seq) { | 133 | TCP_SKB_CB(skb)->end_seq == TCP_SKB_CB(skb)->seq) { |
133 | inet_twsk_put(tw); | 134 | inet_twsk_put(tw); |
134 | return TCP_TW_SUCCESS; | 135 | return TCP_TW_SUCCESS; |
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 416fc4c2e7eb..bd62712848fa 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c | |||
@@ -725,7 +725,8 @@ static void tcp_queue_skb(struct sock *sk, struct sk_buff *skb) | |||
725 | static void tcp_set_skb_tso_segs(struct sock *sk, struct sk_buff *skb, | 725 | static void tcp_set_skb_tso_segs(struct sock *sk, struct sk_buff *skb, |
726 | unsigned int mss_now) | 726 | unsigned int mss_now) |
727 | { | 727 | { |
728 | if (skb->len <= mss_now || !sk_can_gso(sk)) { | 728 | if (skb->len <= mss_now || !sk_can_gso(sk) || |
729 | skb->ip_summed == CHECKSUM_NONE) { | ||
729 | /* Avoid the costly divide in the normal | 730 | /* Avoid the costly divide in the normal |
730 | * non-TSO case. | 731 | * non-TSO case. |
731 | */ | 732 | */ |
@@ -2260,7 +2261,7 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst, | |||
2260 | #ifdef CONFIG_TCP_MD5SIG | 2261 | #ifdef CONFIG_TCP_MD5SIG |
2261 | /* Okay, we have all we need - do the md5 hash if needed */ | 2262 | /* Okay, we have all we need - do the md5 hash if needed */ |
2262 | if (md5) { | 2263 | if (md5) { |
2263 | tp->af_specific->calc_md5_hash(md5_hash_location, | 2264 | tcp_rsk(req)->af_specific->calc_md5_hash(md5_hash_location, |
2264 | md5, NULL, req, skb); | 2265 | md5, NULL, req, skb); |
2265 | } | 2266 | } |
2266 | #endif | 2267 | #endif |
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 8f4158d7c9a6..80e3812837ad 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
@@ -840,7 +840,8 @@ int udp_ioctl(struct sock *sk, int cmd, unsigned long arg) | |||
840 | switch (cmd) { | 840 | switch (cmd) { |
841 | case SIOCOUTQ: | 841 | case SIOCOUTQ: |
842 | { | 842 | { |
843 | int amount = atomic_read(&sk->sk_wmem_alloc); | 843 | int amount = sk_wmem_alloc_get(sk); |
844 | |||
844 | return put_user(amount, (int __user *)arg); | 845 | return put_user(amount, (int __user *)arg); |
845 | } | 846 | } |
846 | 847 | ||
@@ -1721,8 +1722,8 @@ static void udp4_format_sock(struct sock *sp, struct seq_file *f, | |||
1721 | seq_printf(f, "%4d: %08X:%04X %08X:%04X" | 1722 | seq_printf(f, "%4d: %08X:%04X %08X:%04X" |
1722 | " %02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p %d%n", | 1723 | " %02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p %d%n", |
1723 | bucket, src, srcp, dest, destp, sp->sk_state, | 1724 | bucket, src, srcp, dest, destp, sp->sk_state, |
1724 | atomic_read(&sp->sk_wmem_alloc), | 1725 | sk_wmem_alloc_get(sp), |
1725 | atomic_read(&sp->sk_rmem_alloc), | 1726 | sk_rmem_alloc_get(sp), |
1726 | 0, 0L, 0, sock_i_uid(sp), 0, sock_i_ino(sp), | 1727 | 0, 0L, 0, sock_i_uid(sp), 0, sock_i_ino(sp), |
1727 | atomic_read(&sp->sk_refcnt), sp, | 1728 | atomic_read(&sp->sk_refcnt), sp, |
1728 | atomic_read(&sp->sk_drops), len); | 1729 | atomic_read(&sp->sk_drops), len); |
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c index 60d918c96a4f..0071ee6f441f 100644 --- a/net/ipv4/xfrm4_policy.c +++ b/net/ipv4/xfrm4_policy.c | |||
@@ -136,7 +136,8 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse) | |||
136 | case IPPROTO_TCP: | 136 | case IPPROTO_TCP: |
137 | case IPPROTO_SCTP: | 137 | case IPPROTO_SCTP: |
138 | case IPPROTO_DCCP: | 138 | case IPPROTO_DCCP: |
139 | if (pskb_may_pull(skb, xprth + 4 - skb->data)) { | 139 | if (xprth + 4 < skb->data || |
140 | pskb_may_pull(skb, xprth + 4 - skb->data)) { | ||
140 | __be16 *ports = (__be16 *)xprth; | 141 | __be16 *ports = (__be16 *)xprth; |
141 | 142 | ||
142 | fl->fl_ip_sport = ports[!!reverse]; | 143 | fl->fl_ip_sport = ports[!!reverse]; |
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 8c1e86afbbf5..43b3c9f89c12 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -1916,8 +1916,32 @@ ok: | |||
1916 | update_lft = 1; | 1916 | update_lft = 1; |
1917 | else if (stored_lft <= MIN_VALID_LIFETIME) { | 1917 | else if (stored_lft <= MIN_VALID_LIFETIME) { |
1918 | /* valid_lft <= stored_lft is always true */ | 1918 | /* valid_lft <= stored_lft is always true */ |
1919 | /* XXX: IPsec */ | 1919 | /* |
1920 | update_lft = 0; | 1920 | * RFC 4862 Section 5.5.3e: |
1921 | * "Note that the preferred lifetime of | ||
1922 | * the corresponding address is always | ||
1923 | * reset to the Preferred Lifetime in | ||
1924 | * the received Prefix Information | ||
1925 | * option, regardless of whether the | ||
1926 | * valid lifetime is also reset or | ||
1927 | * ignored." | ||
1928 | * | ||
1929 | * So if the preferred lifetime in | ||
1930 | * this advertisement is different | ||
1931 | * than what we have stored, but the | ||
1932 | * valid lifetime is invalid, just | ||
1933 | * reset prefered_lft. | ||
1934 | * | ||
1935 | * We must set the valid lifetime | ||
1936 | * to the stored lifetime since we'll | ||
1937 | * be updating the timestamp below, | ||
1938 | * else we'll set it back to the | ||
1939 | * minumum. | ||
1940 | */ | ||
1941 | if (prefered_lft != ifp->prefered_lft) { | ||
1942 | valid_lft = stored_lft; | ||
1943 | update_lft = 1; | ||
1944 | } | ||
1921 | } else { | 1945 | } else { |
1922 | valid_lft = MIN_VALID_LIFETIME; | 1946 | valid_lft = MIN_VALID_LIFETIME; |
1923 | if (valid_lft < prefered_lft) | 1947 | if (valid_lft < prefered_lft) |
@@ -3085,7 +3109,7 @@ restart: | |||
3085 | spin_unlock(&ifp->lock); | 3109 | spin_unlock(&ifp->lock); |
3086 | continue; | 3110 | continue; |
3087 | } else if (age >= ifp->prefered_lft) { | 3111 | } else if (age >= ifp->prefered_lft) { |
3088 | /* jiffies - ifp->tsamp > age >= ifp->prefered_lft */ | 3112 | /* jiffies - ifp->tstamp > age >= ifp->prefered_lft */ |
3089 | int deprecate = 0; | 3113 | int deprecate = 0; |
3090 | 3114 | ||
3091 | if (!(ifp->flags&IFA_F_DEPRECATED)) { | 3115 | if (!(ifp->flags&IFA_F_DEPRECATED)) { |
@@ -3362,7 +3386,10 @@ static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa, | |||
3362 | valid = ifa->valid_lft; | 3386 | valid = ifa->valid_lft; |
3363 | if (preferred != INFINITY_LIFE_TIME) { | 3387 | if (preferred != INFINITY_LIFE_TIME) { |
3364 | long tval = (jiffies - ifa->tstamp)/HZ; | 3388 | long tval = (jiffies - ifa->tstamp)/HZ; |
3365 | preferred -= tval; | 3389 | if (preferred > tval) |
3390 | preferred -= tval; | ||
3391 | else | ||
3392 | preferred = 0; | ||
3366 | if (valid != INFINITY_LIFE_TIME) | 3393 | if (valid != INFINITY_LIFE_TIME) |
3367 | valid -= tval; | 3394 | valid -= tval; |
3368 | } | 3395 | } |
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 85b3d0036afd..45f9a2a42d56 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c | |||
@@ -306,8 +306,10 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
306 | v4addr != htonl(INADDR_ANY) && | 306 | v4addr != htonl(INADDR_ANY) && |
307 | chk_addr_ret != RTN_LOCAL && | 307 | chk_addr_ret != RTN_LOCAL && |
308 | chk_addr_ret != RTN_MULTICAST && | 308 | chk_addr_ret != RTN_MULTICAST && |
309 | chk_addr_ret != RTN_BROADCAST) | 309 | chk_addr_ret != RTN_BROADCAST) { |
310 | err = -EADDRNOTAVAIL; | ||
310 | goto out; | 311 | goto out; |
312 | } | ||
311 | } else { | 313 | } else { |
312 | if (addr_type != IPV6_ADDR_ANY) { | 314 | if (addr_type != IPV6_ADDR_ANY) { |
313 | struct net_device *dev = NULL; | 315 | struct net_device *dev = NULL; |
@@ -1284,6 +1286,8 @@ static void __exit inet6_exit(void) | |||
1284 | proto_unregister(&udplitev6_prot); | 1286 | proto_unregister(&udplitev6_prot); |
1285 | proto_unregister(&udpv6_prot); | 1287 | proto_unregister(&udpv6_prot); |
1286 | proto_unregister(&tcpv6_prot); | 1288 | proto_unregister(&tcpv6_prot); |
1289 | |||
1290 | rcu_barrier(); /* Wait for completion of call_rcu()'s */ | ||
1287 | } | 1291 | } |
1288 | module_exit(inet6_exit); | 1292 | module_exit(inet6_exit); |
1289 | 1293 | ||
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c index 52449f7a1b71..86f42a288c4b 100644 --- a/net/ipv6/ah6.c +++ b/net/ipv6/ah6.c | |||
@@ -405,7 +405,7 @@ out: | |||
405 | } | 405 | } |
406 | 406 | ||
407 | static void ah6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | 407 | static void ah6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, |
408 | int type, int code, int offset, __be32 info) | 408 | u8 type, u8 code, int offset, __be32 info) |
409 | { | 409 | { |
410 | struct net *net = dev_net(skb->dev); | 410 | struct net *net = dev_net(skb->dev); |
411 | struct ipv6hdr *iph = (struct ipv6hdr*)skb->data; | 411 | struct ipv6hdr *iph = (struct ipv6hdr*)skb->data; |
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c index c2f250150db1..678bb95b1525 100644 --- a/net/ipv6/esp6.c +++ b/net/ipv6/esp6.c | |||
@@ -354,7 +354,7 @@ static u32 esp6_get_mtu(struct xfrm_state *x, int mtu) | |||
354 | } | 354 | } |
355 | 355 | ||
356 | static void esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | 356 | static void esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, |
357 | int type, int code, int offset, __be32 info) | 357 | u8 type, u8 code, int offset, __be32 info) |
358 | { | 358 | { |
359 | struct net *net = dev_net(skb->dev); | 359 | struct net *net = dev_net(skb->dev); |
360 | struct ipv6hdr *iph = (struct ipv6hdr*)skb->data; | 360 | struct ipv6hdr *iph = (struct ipv6hdr*)skb->data; |
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index 36dff8807183..eab62a7a8f06 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c | |||
@@ -117,7 +117,7 @@ static __inline__ void icmpv6_xmit_unlock(struct sock *sk) | |||
117 | /* | 117 | /* |
118 | * Slightly more convenient version of icmpv6_send. | 118 | * Slightly more convenient version of icmpv6_send. |
119 | */ | 119 | */ |
120 | void icmpv6_param_prob(struct sk_buff *skb, int code, int pos) | 120 | void icmpv6_param_prob(struct sk_buff *skb, u8 code, int pos) |
121 | { | 121 | { |
122 | icmpv6_send(skb, ICMPV6_PARAMPROB, code, pos, skb->dev); | 122 | icmpv6_send(skb, ICMPV6_PARAMPROB, code, pos, skb->dev); |
123 | kfree_skb(skb); | 123 | kfree_skb(skb); |
@@ -161,7 +161,7 @@ static int is_ineligible(struct sk_buff *skb) | |||
161 | /* | 161 | /* |
162 | * Check the ICMP output rate limit | 162 | * Check the ICMP output rate limit |
163 | */ | 163 | */ |
164 | static inline int icmpv6_xrlim_allow(struct sock *sk, int type, | 164 | static inline int icmpv6_xrlim_allow(struct sock *sk, u8 type, |
165 | struct flowi *fl) | 165 | struct flowi *fl) |
166 | { | 166 | { |
167 | struct dst_entry *dst; | 167 | struct dst_entry *dst; |
@@ -305,7 +305,7 @@ static inline void mip6_addr_swap(struct sk_buff *skb) {} | |||
305 | /* | 305 | /* |
306 | * Send an ICMP message in response to a packet in error | 306 | * Send an ICMP message in response to a packet in error |
307 | */ | 307 | */ |
308 | void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info, | 308 | void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info, |
309 | struct net_device *dev) | 309 | struct net_device *dev) |
310 | { | 310 | { |
311 | struct net *net = dev_net(skb->dev); | 311 | struct net *net = dev_net(skb->dev); |
@@ -590,7 +590,7 @@ out: | |||
590 | icmpv6_xmit_unlock(sk); | 590 | icmpv6_xmit_unlock(sk); |
591 | } | 591 | } |
592 | 592 | ||
593 | static void icmpv6_notify(struct sk_buff *skb, int type, int code, __be32 info) | 593 | static void icmpv6_notify(struct sk_buff *skb, u8 type, u8 code, __be32 info) |
594 | { | 594 | { |
595 | struct inet6_protocol *ipprot; | 595 | struct inet6_protocol *ipprot; |
596 | int inner_offset; | 596 | int inner_offset; |
@@ -643,7 +643,7 @@ static int icmpv6_rcv(struct sk_buff *skb) | |||
643 | struct in6_addr *saddr, *daddr; | 643 | struct in6_addr *saddr, *daddr; |
644 | struct ipv6hdr *orig_hdr; | 644 | struct ipv6hdr *orig_hdr; |
645 | struct icmp6hdr *hdr; | 645 | struct icmp6hdr *hdr; |
646 | int type; | 646 | u8 type; |
647 | 647 | ||
648 | if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) { | 648 | if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) { |
649 | struct sec_path *sp = skb_sec_path(skb); | 649 | struct sec_path *sp = skb_sec_path(skb); |
@@ -914,7 +914,7 @@ static const struct icmp6_err { | |||
914 | }, | 914 | }, |
915 | }; | 915 | }; |
916 | 916 | ||
917 | int icmpv6_err_convert(int type, int code, int *err) | 917 | int icmpv6_err_convert(u8 type, u8 code, int *err) |
918 | { | 918 | { |
919 | int fatal = 0; | 919 | int fatal = 0; |
920 | 920 | ||
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index c3a07d75b5f5..6d6a4277c677 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c | |||
@@ -139,6 +139,9 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt | |||
139 | 139 | ||
140 | rcu_read_unlock(); | 140 | rcu_read_unlock(); |
141 | 141 | ||
142 | /* Must drop socket now because of tproxy. */ | ||
143 | skb_orphan(skb); | ||
144 | |||
142 | return NF_HOOK(PF_INET6, NF_INET_PRE_ROUTING, skb, dev, NULL, | 145 | return NF_HOOK(PF_INET6, NF_INET_PRE_ROUTING, skb, dev, NULL, |
143 | ip6_rcv_finish); | 146 | ip6_rcv_finish); |
144 | err: | 147 | err: |
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 7c76e3d18215..87f8419a68fd 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
@@ -1484,7 +1484,6 @@ int ip6_push_pending_frames(struct sock *sk) | |||
1484 | skb->len += tmp_skb->len; | 1484 | skb->len += tmp_skb->len; |
1485 | skb->data_len += tmp_skb->len; | 1485 | skb->data_len += tmp_skb->len; |
1486 | skb->truesize += tmp_skb->truesize; | 1486 | skb->truesize += tmp_skb->truesize; |
1487 | __sock_put(tmp_skb->sk); | ||
1488 | tmp_skb->destructor = NULL; | 1487 | tmp_skb->destructor = NULL; |
1489 | tmp_skb->sk = NULL; | 1488 | tmp_skb->sk = NULL; |
1490 | } | 1489 | } |
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 404d16a97d5c..51f410e7775a 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c | |||
@@ -394,13 +394,13 @@ parse_tlv_tnl_enc_lim(struct sk_buff *skb, __u8 * raw) | |||
394 | 394 | ||
395 | static int | 395 | static int |
396 | ip6_tnl_err(struct sk_buff *skb, __u8 ipproto, struct inet6_skb_parm *opt, | 396 | ip6_tnl_err(struct sk_buff *skb, __u8 ipproto, struct inet6_skb_parm *opt, |
397 | int *type, int *code, int *msg, __u32 *info, int offset) | 397 | u8 *type, u8 *code, int *msg, __u32 *info, int offset) |
398 | { | 398 | { |
399 | struct ipv6hdr *ipv6h = (struct ipv6hdr *) skb->data; | 399 | struct ipv6hdr *ipv6h = (struct ipv6hdr *) skb->data; |
400 | struct ip6_tnl *t; | 400 | struct ip6_tnl *t; |
401 | int rel_msg = 0; | 401 | int rel_msg = 0; |
402 | int rel_type = ICMPV6_DEST_UNREACH; | 402 | u8 rel_type = ICMPV6_DEST_UNREACH; |
403 | int rel_code = ICMPV6_ADDR_UNREACH; | 403 | u8 rel_code = ICMPV6_ADDR_UNREACH; |
404 | __u32 rel_info = 0; | 404 | __u32 rel_info = 0; |
405 | __u16 len; | 405 | __u16 len; |
406 | int err = -ENOENT; | 406 | int err = -ENOENT; |
@@ -488,11 +488,11 @@ out: | |||
488 | 488 | ||
489 | static int | 489 | static int |
490 | ip4ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | 490 | ip4ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, |
491 | int type, int code, int offset, __be32 info) | 491 | u8 type, u8 code, int offset, __be32 info) |
492 | { | 492 | { |
493 | int rel_msg = 0; | 493 | int rel_msg = 0; |
494 | int rel_type = type; | 494 | u8 rel_type = type; |
495 | int rel_code = code; | 495 | u8 rel_code = code; |
496 | __u32 rel_info = ntohl(info); | 496 | __u32 rel_info = ntohl(info); |
497 | int err; | 497 | int err; |
498 | struct sk_buff *skb2; | 498 | struct sk_buff *skb2; |
@@ -586,11 +586,11 @@ out: | |||
586 | 586 | ||
587 | static int | 587 | static int |
588 | ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | 588 | ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, |
589 | int type, int code, int offset, __be32 info) | 589 | u8 type, u8 code, int offset, __be32 info) |
590 | { | 590 | { |
591 | int rel_msg = 0; | 591 | int rel_msg = 0; |
592 | int rel_type = type; | 592 | u8 rel_type = type; |
593 | int rel_code = code; | 593 | u8 rel_code = code; |
594 | __u32 rel_info = ntohl(info); | 594 | __u32 rel_info = ntohl(info); |
595 | int err; | 595 | int err; |
596 | 596 | ||
diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c index 3a0b3be7ece5..79c172f1ff01 100644 --- a/net/ipv6/ipcomp6.c +++ b/net/ipv6/ipcomp6.c | |||
@@ -51,7 +51,7 @@ | |||
51 | #include <linux/mutex.h> | 51 | #include <linux/mutex.h> |
52 | 52 | ||
53 | static void ipcomp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | 53 | static void ipcomp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, |
54 | int type, int code, int offset, __be32 info) | 54 | u8 type, u8 code, int offset, __be32 info) |
55 | { | 55 | { |
56 | __be32 spi; | 56 | __be32 spi; |
57 | struct ipv6hdr *iph = (struct ipv6hdr*)skb->data; | 57 | struct ipv6hdr *iph = (struct ipv6hdr*)skb->data; |
diff --git a/net/ipv6/mip6.c b/net/ipv6/mip6.c index f995e19c87a9..f797e8c6f3b3 100644 --- a/net/ipv6/mip6.c +++ b/net/ipv6/mip6.c | |||
@@ -54,7 +54,7 @@ static inline void *mip6_padn(__u8 *data, __u8 padlen) | |||
54 | return data + padlen; | 54 | return data + padlen; |
55 | } | 55 | } |
56 | 56 | ||
57 | static inline void mip6_param_prob(struct sk_buff *skb, int code, int pos) | 57 | static inline void mip6_param_prob(struct sk_buff *skb, u8 code, int pos) |
58 | { | 58 | { |
59 | icmpv6_send(skb, ICMPV6_PARAMPROB, code, pos, skb->dev); | 59 | icmpv6_send(skb, ICMPV6_PARAMPROB, code, pos, skb->dev); |
60 | } | 60 | } |
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 36a090d87a3d..d6c3c1c34b2d 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c | |||
@@ -310,7 +310,7 @@ out: | |||
310 | 310 | ||
311 | static void rawv6_err(struct sock *sk, struct sk_buff *skb, | 311 | static void rawv6_err(struct sock *sk, struct sk_buff *skb, |
312 | struct inet6_skb_parm *opt, | 312 | struct inet6_skb_parm *opt, |
313 | int type, int code, int offset, __be32 info) | 313 | u8 type, u8 code, int offset, __be32 info) |
314 | { | 314 | { |
315 | struct inet_sock *inet = inet_sk(sk); | 315 | struct inet_sock *inet = inet_sk(sk); |
316 | struct ipv6_pinfo *np = inet6_sk(sk); | 316 | struct ipv6_pinfo *np = inet6_sk(sk); |
@@ -343,7 +343,7 @@ static void rawv6_err(struct sock *sk, struct sk_buff *skb, | |||
343 | } | 343 | } |
344 | 344 | ||
345 | void raw6_icmp_error(struct sk_buff *skb, int nexthdr, | 345 | void raw6_icmp_error(struct sk_buff *skb, int nexthdr, |
346 | int type, int code, int inner_offset, __be32 info) | 346 | u8 type, u8 code, int inner_offset, __be32 info) |
347 | { | 347 | { |
348 | struct sock *sk; | 348 | struct sock *sk; |
349 | int hash; | 349 | int hash; |
@@ -1130,7 +1130,8 @@ static int rawv6_ioctl(struct sock *sk, int cmd, unsigned long arg) | |||
1130 | switch(cmd) { | 1130 | switch(cmd) { |
1131 | case SIOCOUTQ: | 1131 | case SIOCOUTQ: |
1132 | { | 1132 | { |
1133 | int amount = atomic_read(&sk->sk_wmem_alloc); | 1133 | int amount = sk_wmem_alloc_get(sk); |
1134 | |||
1134 | return put_user(amount, (int __user *)arg); | 1135 | return put_user(amount, (int __user *)arg); |
1135 | } | 1136 | } |
1136 | case SIOCINQ: | 1137 | case SIOCINQ: |
@@ -1236,8 +1237,8 @@ static void raw6_sock_seq_show(struct seq_file *seq, struct sock *sp, int i) | |||
1236 | dest->s6_addr32[0], dest->s6_addr32[1], | 1237 | dest->s6_addr32[0], dest->s6_addr32[1], |
1237 | dest->s6_addr32[2], dest->s6_addr32[3], destp, | 1238 | dest->s6_addr32[2], dest->s6_addr32[3], destp, |
1238 | sp->sk_state, | 1239 | sp->sk_state, |
1239 | atomic_read(&sp->sk_wmem_alloc), | 1240 | sk_wmem_alloc_get(sp), |
1240 | atomic_read(&sp->sk_rmem_alloc), | 1241 | sk_rmem_alloc_get(sp), |
1241 | 0, 0L, 0, | 1242 | 0, 0L, 0, |
1242 | sock_i_uid(sp), 0, | 1243 | sock_i_uid(sp), 0, |
1243 | sock_i_ino(sp), | 1244 | sock_i_ino(sp), |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 658293ea05ba..1473ee0a1f51 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -1865,7 +1865,7 @@ int ipv6_route_ioctl(struct net *net, unsigned int cmd, void __user *arg) | |||
1865 | * Drop the packet on the floor | 1865 | * Drop the packet on the floor |
1866 | */ | 1866 | */ |
1867 | 1867 | ||
1868 | static int ip6_pkt_drop(struct sk_buff *skb, int code, int ipstats_mib_noroutes) | 1868 | static int ip6_pkt_drop(struct sk_buff *skb, u8 code, int ipstats_mib_noroutes) |
1869 | { | 1869 | { |
1870 | int type; | 1870 | int type; |
1871 | struct dst_entry *dst = skb_dst(skb); | 1871 | struct dst_entry *dst = skb_dst(skb); |
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 68e52308e552..98b7327d0949 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c | |||
@@ -1018,6 +1018,7 @@ static void ipip6_tunnel_setup(struct net_device *dev) | |||
1018 | dev->hard_header_len = LL_MAX_HEADER + sizeof(struct iphdr); | 1018 | dev->hard_header_len = LL_MAX_HEADER + sizeof(struct iphdr); |
1019 | dev->mtu = ETH_DATA_LEN - sizeof(struct iphdr); | 1019 | dev->mtu = ETH_DATA_LEN - sizeof(struct iphdr); |
1020 | dev->flags = IFF_NOARP; | 1020 | dev->flags = IFF_NOARP; |
1021 | dev->priv_flags &= ~IFF_XMIT_DST_RELEASE; | ||
1021 | dev->iflink = 0; | 1022 | dev->iflink = 0; |
1022 | dev->addr_len = 4; | 1023 | dev->addr_len = 4; |
1023 | dev->features |= NETIF_F_NETNS_LOCAL; | 1024 | dev->features |= NETIF_F_NETNS_LOCAL; |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 53b6a4192b16..d849dd53b788 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -317,7 +317,7 @@ failure: | |||
317 | } | 317 | } |
318 | 318 | ||
319 | static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | 319 | static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, |
320 | int type, int code, int offset, __be32 info) | 320 | u8 type, u8 code, int offset, __be32 info) |
321 | { | 321 | { |
322 | struct ipv6hdr *hdr = (struct ipv6hdr*)skb->data; | 322 | struct ipv6hdr *hdr = (struct ipv6hdr*)skb->data; |
323 | const struct tcphdr *th = (struct tcphdr *)(skb->data+offset); | 323 | const struct tcphdr *th = (struct tcphdr *)(skb->data+offset); |
@@ -896,6 +896,7 @@ struct request_sock_ops tcp6_request_sock_ops __read_mostly = { | |||
896 | #ifdef CONFIG_TCP_MD5SIG | 896 | #ifdef CONFIG_TCP_MD5SIG |
897 | static struct tcp_request_sock_ops tcp_request_sock_ipv6_ops = { | 897 | static struct tcp_request_sock_ops tcp_request_sock_ipv6_ops = { |
898 | .md5_lookup = tcp_v6_reqsk_md5_lookup, | 898 | .md5_lookup = tcp_v6_reqsk_md5_lookup, |
899 | .calc_md5_hash = tcp_v6_md5_hash_skb, | ||
899 | }; | 900 | }; |
900 | #endif | 901 | #endif |
901 | 902 | ||
@@ -1441,7 +1442,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
1441 | */ | 1442 | */ |
1442 | char *newkey = kmemdup(key->key, key->keylen, GFP_ATOMIC); | 1443 | char *newkey = kmemdup(key->key, key->keylen, GFP_ATOMIC); |
1443 | if (newkey != NULL) | 1444 | if (newkey != NULL) |
1444 | tcp_v6_md5_do_add(newsk, &inet6_sk(sk)->daddr, | 1445 | tcp_v6_md5_do_add(newsk, &newnp->daddr, |
1445 | newkey, key->keylen); | 1446 | newkey, key->keylen); |
1446 | } | 1447 | } |
1447 | #endif | 1448 | #endif |
diff --git a/net/ipv6/tunnel6.c b/net/ipv6/tunnel6.c index 669f280989c3..633ad789effc 100644 --- a/net/ipv6/tunnel6.c +++ b/net/ipv6/tunnel6.c | |||
@@ -124,7 +124,7 @@ drop: | |||
124 | } | 124 | } |
125 | 125 | ||
126 | static void tunnel6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | 126 | static void tunnel6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, |
127 | int type, int code, int offset, __be32 info) | 127 | u8 type, u8 code, int offset, __be32 info) |
128 | { | 128 | { |
129 | struct xfrm6_tunnel *handler; | 129 | struct xfrm6_tunnel *handler; |
130 | 130 | ||
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index fc333d854728..33b59bd92c4d 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -312,7 +312,7 @@ csum_copy_err: | |||
312 | } | 312 | } |
313 | 313 | ||
314 | void __udp6_lib_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | 314 | void __udp6_lib_err(struct sk_buff *skb, struct inet6_skb_parm *opt, |
315 | int type, int code, int offset, __be32 info, | 315 | u8 type, u8 code, int offset, __be32 info, |
316 | struct udp_table *udptable) | 316 | struct udp_table *udptable) |
317 | { | 317 | { |
318 | struct ipv6_pinfo *np; | 318 | struct ipv6_pinfo *np; |
@@ -346,8 +346,8 @@ out: | |||
346 | } | 346 | } |
347 | 347 | ||
348 | static __inline__ void udpv6_err(struct sk_buff *skb, | 348 | static __inline__ void udpv6_err(struct sk_buff *skb, |
349 | struct inet6_skb_parm *opt, int type, | 349 | struct inet6_skb_parm *opt, u8 type, |
350 | int code, int offset, __be32 info ) | 350 | u8 code, int offset, __be32 info ) |
351 | { | 351 | { |
352 | __udp6_lib_err(skb, opt, type, code, offset, info, &udp_table); | 352 | __udp6_lib_err(skb, opt, type, code, offset, info, &udp_table); |
353 | } | 353 | } |
@@ -1061,8 +1061,8 @@ static void udp6_sock_seq_show(struct seq_file *seq, struct sock *sp, int bucket | |||
1061 | dest->s6_addr32[0], dest->s6_addr32[1], | 1061 | dest->s6_addr32[0], dest->s6_addr32[1], |
1062 | dest->s6_addr32[2], dest->s6_addr32[3], destp, | 1062 | dest->s6_addr32[2], dest->s6_addr32[3], destp, |
1063 | sp->sk_state, | 1063 | sp->sk_state, |
1064 | atomic_read(&sp->sk_wmem_alloc), | 1064 | sk_wmem_alloc_get(sp), |
1065 | atomic_read(&sp->sk_rmem_alloc), | 1065 | sk_rmem_alloc_get(sp), |
1066 | 0, 0L, 0, | 1066 | 0, 0L, 0, |
1067 | sock_i_uid(sp), 0, | 1067 | sock_i_uid(sp), 0, |
1068 | sock_i_ino(sp), | 1068 | sock_i_ino(sp), |
diff --git a/net/ipv6/udp_impl.h b/net/ipv6/udp_impl.h index 23779208c334..6bb303471e20 100644 --- a/net/ipv6/udp_impl.h +++ b/net/ipv6/udp_impl.h | |||
@@ -9,7 +9,7 @@ | |||
9 | 9 | ||
10 | extern int __udp6_lib_rcv(struct sk_buff *, struct udp_table *, int ); | 10 | extern int __udp6_lib_rcv(struct sk_buff *, struct udp_table *, int ); |
11 | extern void __udp6_lib_err(struct sk_buff *, struct inet6_skb_parm *, | 11 | extern void __udp6_lib_err(struct sk_buff *, struct inet6_skb_parm *, |
12 | int , int , int , __be32 , struct udp_table *); | 12 | u8 , u8 , int , __be32 , struct udp_table *); |
13 | 13 | ||
14 | extern int udp_v6_get_port(struct sock *sk, unsigned short snum); | 14 | extern int udp_v6_get_port(struct sock *sk, unsigned short snum); |
15 | 15 | ||
diff --git a/net/ipv6/udplite.c b/net/ipv6/udplite.c index ba162a824585..4818c48688f2 100644 --- a/net/ipv6/udplite.c +++ b/net/ipv6/udplite.c | |||
@@ -20,7 +20,7 @@ static int udplitev6_rcv(struct sk_buff *skb) | |||
20 | 20 | ||
21 | static void udplitev6_err(struct sk_buff *skb, | 21 | static void udplitev6_err(struct sk_buff *skb, |
22 | struct inet6_skb_parm *opt, | 22 | struct inet6_skb_parm *opt, |
23 | int type, int code, int offset, __be32 info) | 23 | u8 type, u8 code, int offset, __be32 info) |
24 | { | 24 | { |
25 | __udp6_lib_err(skb, opt, type, code, offset, info, &udplite_table); | 25 | __udp6_lib_err(skb, opt, type, code, offset, info, &udplite_table); |
26 | } | 26 | } |
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c index b4b16a43f277..3a3c677bc0f2 100644 --- a/net/ipv6/xfrm6_policy.c +++ b/net/ipv6/xfrm6_policy.c | |||
@@ -157,7 +157,8 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse) | |||
157 | ipv6_addr_copy(&fl->fl6_dst, reverse ? &hdr->saddr : &hdr->daddr); | 157 | ipv6_addr_copy(&fl->fl6_dst, reverse ? &hdr->saddr : &hdr->daddr); |
158 | ipv6_addr_copy(&fl->fl6_src, reverse ? &hdr->daddr : &hdr->saddr); | 158 | ipv6_addr_copy(&fl->fl6_src, reverse ? &hdr->daddr : &hdr->saddr); |
159 | 159 | ||
160 | while (pskb_may_pull(skb, nh + offset + 1 - skb->data)) { | 160 | while (nh + offset + 1 < skb->data || |
161 | pskb_may_pull(skb, nh + offset + 1 - skb->data)) { | ||
161 | nh = skb_network_header(skb); | 162 | nh = skb_network_header(skb); |
162 | exthdr = (struct ipv6_opt_hdr *)(nh + offset); | 163 | exthdr = (struct ipv6_opt_hdr *)(nh + offset); |
163 | 164 | ||
@@ -177,7 +178,8 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse) | |||
177 | case IPPROTO_TCP: | 178 | case IPPROTO_TCP: |
178 | case IPPROTO_SCTP: | 179 | case IPPROTO_SCTP: |
179 | case IPPROTO_DCCP: | 180 | case IPPROTO_DCCP: |
180 | if (!onlyproto && pskb_may_pull(skb, nh + offset + 4 - skb->data)) { | 181 | if (!onlyproto && (nh + offset + 4 < skb->data || |
182 | pskb_may_pull(skb, nh + offset + 4 - skb->data))) { | ||
181 | __be16 *ports = (__be16 *)exthdr; | 183 | __be16 *ports = (__be16 *)exthdr; |
182 | 184 | ||
183 | fl->fl_ip_sport = ports[!!reverse]; | 185 | fl->fl_ip_sport = ports[!!reverse]; |
diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c index 80193db224d9..81a95c00e503 100644 --- a/net/ipv6/xfrm6_tunnel.c +++ b/net/ipv6/xfrm6_tunnel.c | |||
@@ -262,7 +262,7 @@ static int xfrm6_tunnel_rcv(struct sk_buff *skb) | |||
262 | } | 262 | } |
263 | 263 | ||
264 | static int xfrm6_tunnel_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | 264 | static int xfrm6_tunnel_err(struct sk_buff *skb, struct inet6_skb_parm *opt, |
265 | int type, int code, int offset, __be32 info) | 265 | u8 type, u8 code, int offset, __be32 info) |
266 | { | 266 | { |
267 | /* xfrm6_tunnel native err handling */ | 267 | /* xfrm6_tunnel native err handling */ |
268 | switch (type) { | 268 | switch (type) { |
diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c index 1627050e29fd..f1118d92a191 100644 --- a/net/ipx/af_ipx.c +++ b/net/ipx/af_ipx.c | |||
@@ -41,6 +41,7 @@ | |||
41 | #include <linux/netdevice.h> | 41 | #include <linux/netdevice.h> |
42 | #include <linux/uio.h> | 42 | #include <linux/uio.h> |
43 | #include <linux/skbuff.h> | 43 | #include <linux/skbuff.h> |
44 | #include <linux/smp_lock.h> | ||
44 | #include <linux/socket.h> | 45 | #include <linux/socket.h> |
45 | #include <linux/sockios.h> | 46 | #include <linux/sockios.h> |
46 | #include <linux/string.h> | 47 | #include <linux/string.h> |
@@ -1835,7 +1836,7 @@ static int ipx_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
1835 | 1836 | ||
1836 | switch (cmd) { | 1837 | switch (cmd) { |
1837 | case TIOCOUTQ: | 1838 | case TIOCOUTQ: |
1838 | amount = sk->sk_sndbuf - atomic_read(&sk->sk_wmem_alloc); | 1839 | amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk); |
1839 | if (amount < 0) | 1840 | if (amount < 0) |
1840 | amount = 0; | 1841 | amount = 0; |
1841 | rc = put_user(amount, (int __user *)argp); | 1842 | rc = put_user(amount, (int __user *)argp); |
diff --git a/net/ipx/ipx_proc.c b/net/ipx/ipx_proc.c index 5ed97ad0e2e3..576178482f89 100644 --- a/net/ipx/ipx_proc.c +++ b/net/ipx/ipx_proc.c | |||
@@ -280,8 +280,8 @@ static int ipx_seq_socket_show(struct seq_file *seq, void *v) | |||
280 | } | 280 | } |
281 | 281 | ||
282 | seq_printf(seq, "%08X %08X %02X %03d\n", | 282 | seq_printf(seq, "%08X %08X %02X %03d\n", |
283 | atomic_read(&s->sk_wmem_alloc), | 283 | sk_wmem_alloc_get(s), |
284 | atomic_read(&s->sk_rmem_alloc), | 284 | sk_rmem_alloc_get(s), |
285 | s->sk_state, SOCK_INODE(s->sk_socket)->i_uid); | 285 | s->sk_state, SOCK_INODE(s->sk_socket)->i_uid); |
286 | out: | 286 | out: |
287 | return 0; | 287 | return 0; |
diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c index 3eb5bcc75f99..50b43c57d5d8 100644 --- a/net/irda/af_irda.c +++ b/net/irda/af_irda.c | |||
@@ -45,6 +45,7 @@ | |||
45 | #include <linux/capability.h> | 45 | #include <linux/capability.h> |
46 | #include <linux/module.h> | 46 | #include <linux/module.h> |
47 | #include <linux/types.h> | 47 | #include <linux/types.h> |
48 | #include <linux/smp_lock.h> | ||
48 | #include <linux/socket.h> | 49 | #include <linux/socket.h> |
49 | #include <linux/sockios.h> | 50 | #include <linux/sockios.h> |
50 | #include <linux/init.h> | 51 | #include <linux/init.h> |
@@ -714,6 +715,7 @@ static int irda_getname(struct socket *sock, struct sockaddr *uaddr, | |||
714 | struct sock *sk = sock->sk; | 715 | struct sock *sk = sock->sk; |
715 | struct irda_sock *self = irda_sk(sk); | 716 | struct irda_sock *self = irda_sk(sk); |
716 | 717 | ||
718 | memset(&saddr, 0, sizeof(saddr)); | ||
717 | if (peer) { | 719 | if (peer) { |
718 | if (sk->sk_state != TCP_ESTABLISHED) | 720 | if (sk->sk_state != TCP_ESTABLISHED) |
719 | return -ENOTCONN; | 721 | return -ENOTCONN; |
@@ -913,9 +915,6 @@ static int irda_accept(struct socket *sock, struct socket *newsock, int flags) | |||
913 | /* Clean up the original one to keep it in listen state */ | 915 | /* Clean up the original one to keep it in listen state */ |
914 | irttp_listen(self->tsap); | 916 | irttp_listen(self->tsap); |
915 | 917 | ||
916 | /* Wow ! What is that ? Jean II */ | ||
917 | skb->sk = NULL; | ||
918 | skb->destructor = NULL; | ||
919 | kfree_skb(skb); | 918 | kfree_skb(skb); |
920 | sk->sk_ack_backlog--; | 919 | sk->sk_ack_backlog--; |
921 | 920 | ||
@@ -1762,7 +1761,8 @@ static int irda_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
1762 | switch (cmd) { | 1761 | switch (cmd) { |
1763 | case TIOCOUTQ: { | 1762 | case TIOCOUTQ: { |
1764 | long amount; | 1763 | long amount; |
1765 | amount = sk->sk_sndbuf - atomic_read(&sk->sk_wmem_alloc); | 1764 | |
1765 | amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk); | ||
1766 | if (amount < 0) | 1766 | if (amount < 0) |
1767 | amount = 0; | 1767 | amount = 0; |
1768 | if (put_user(amount, (unsigned int __user *)arg)) | 1768 | if (put_user(amount, (unsigned int __user *)arg)) |
diff --git a/net/irda/ircomm/ircomm_lmp.c b/net/irda/ircomm/ircomm_lmp.c index 67c99d20857f..7ba96618660e 100644 --- a/net/irda/ircomm/ircomm_lmp.c +++ b/net/irda/ircomm/ircomm_lmp.c | |||
@@ -196,6 +196,7 @@ static int ircomm_lmp_data_request(struct ircomm_cb *self, | |||
196 | /* Don't forget to refcount it - see ircomm_tty_do_softint() */ | 196 | /* Don't forget to refcount it - see ircomm_tty_do_softint() */ |
197 | skb_get(skb); | 197 | skb_get(skb); |
198 | 198 | ||
199 | skb_orphan(skb); | ||
199 | skb->destructor = ircomm_lmp_flow_control; | 200 | skb->destructor = ircomm_lmp_flow_control; |
200 | 201 | ||
201 | if ((self->pkt_count++ > 7) && (self->flow_status == FLOW_START)) { | 202 | if ((self->pkt_count++ > 7) && (self->flow_status == FLOW_START)) { |
diff --git a/net/irda/irnet/irnet.h b/net/irda/irnet/irnet.h index bccf4d0059f0..b001c361ad30 100644 --- a/net/irda/irnet/irnet.h +++ b/net/irda/irnet/irnet.h | |||
@@ -241,7 +241,6 @@ | |||
241 | #include <linux/module.h> | 241 | #include <linux/module.h> |
242 | 242 | ||
243 | #include <linux/kernel.h> | 243 | #include <linux/kernel.h> |
244 | #include <linux/smp_lock.h> | ||
245 | #include <linux/skbuff.h> | 244 | #include <linux/skbuff.h> |
246 | #include <linux/tty.h> | 245 | #include <linux/tty.h> |
247 | #include <linux/proc_fs.h> | 246 | #include <linux/proc_fs.h> |
diff --git a/net/irda/irnet/irnet_ppp.c b/net/irda/irnet/irnet_ppp.c index 6d8ae03c14f5..68cbcb19cbd8 100644 --- a/net/irda/irnet/irnet_ppp.c +++ b/net/irda/irnet/irnet_ppp.c | |||
@@ -13,6 +13,7 @@ | |||
13 | * 2) as a control channel (write commands, read events) | 13 | * 2) as a control channel (write commands, read events) |
14 | */ | 14 | */ |
15 | 15 | ||
16 | #include <linux/smp_lock.h> | ||
16 | #include "irnet_ppp.h" /* Private header */ | 17 | #include "irnet_ppp.h" /* Private header */ |
17 | /* Please put other headers in irnet.h - Thanks */ | 18 | /* Please put other headers in irnet.h - Thanks */ |
18 | 19 | ||
diff --git a/net/irda/irttp.c b/net/irda/irttp.c index ecf4eb2717cb..9cb79f95bf63 100644 --- a/net/irda/irttp.c +++ b/net/irda/irttp.c | |||
@@ -1453,6 +1453,7 @@ struct tsap_cb *irttp_dup(struct tsap_cb *orig, void *instance) | |||
1453 | } | 1453 | } |
1454 | /* Dup */ | 1454 | /* Dup */ |
1455 | memcpy(new, orig, sizeof(struct tsap_cb)); | 1455 | memcpy(new, orig, sizeof(struct tsap_cb)); |
1456 | spin_lock_init(&new->lock); | ||
1456 | 1457 | ||
1457 | /* We don't need the old instance any more */ | 1458 | /* We don't need the old instance any more */ |
1458 | spin_unlock_irqrestore(&irttp->tsaps->hb_spinlock, flags); | 1459 | spin_unlock_irqrestore(&irttp->tsaps->hb_spinlock, flags); |
diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c index 656cbd195825..49c15b48408e 100644 --- a/net/iucv/af_iucv.c +++ b/net/iucv/af_iucv.c | |||
@@ -54,6 +54,38 @@ static const u8 iprm_shutdown[8] = | |||
54 | #define CB_TRGCLS(skb) ((skb)->cb + CB_TAG_LEN) /* iucv msg target class */ | 54 | #define CB_TRGCLS(skb) ((skb)->cb + CB_TAG_LEN) /* iucv msg target class */ |
55 | #define CB_TRGCLS_LEN (TRGCLS_SIZE) | 55 | #define CB_TRGCLS_LEN (TRGCLS_SIZE) |
56 | 56 | ||
57 | #define __iucv_sock_wait(sk, condition, timeo, ret) \ | ||
58 | do { \ | ||
59 | DEFINE_WAIT(__wait); \ | ||
60 | long __timeo = timeo; \ | ||
61 | ret = 0; \ | ||
62 | while (!(condition)) { \ | ||
63 | prepare_to_wait(sk->sk_sleep, &__wait, TASK_INTERRUPTIBLE); \ | ||
64 | if (!__timeo) { \ | ||
65 | ret = -EAGAIN; \ | ||
66 | break; \ | ||
67 | } \ | ||
68 | if (signal_pending(current)) { \ | ||
69 | ret = sock_intr_errno(__timeo); \ | ||
70 | break; \ | ||
71 | } \ | ||
72 | release_sock(sk); \ | ||
73 | __timeo = schedule_timeout(__timeo); \ | ||
74 | lock_sock(sk); \ | ||
75 | ret = sock_error(sk); \ | ||
76 | if (ret) \ | ||
77 | break; \ | ||
78 | } \ | ||
79 | finish_wait(sk->sk_sleep, &__wait); \ | ||
80 | } while (0) | ||
81 | |||
82 | #define iucv_sock_wait(sk, condition, timeo) \ | ||
83 | ({ \ | ||
84 | int __ret = 0; \ | ||
85 | if (!(condition)) \ | ||
86 | __iucv_sock_wait(sk, condition, timeo, __ret); \ | ||
87 | __ret; \ | ||
88 | }) | ||
57 | 89 | ||
58 | static void iucv_sock_kill(struct sock *sk); | 90 | static void iucv_sock_kill(struct sock *sk); |
59 | static void iucv_sock_close(struct sock *sk); | 91 | static void iucv_sock_close(struct sock *sk); |
@@ -238,6 +270,48 @@ static inline size_t iucv_msg_length(struct iucv_message *msg) | |||
238 | return msg->length; | 270 | return msg->length; |
239 | } | 271 | } |
240 | 272 | ||
273 | /** | ||
274 | * iucv_sock_in_state() - check for specific states | ||
275 | * @sk: sock structure | ||
276 | * @state: first iucv sk state | ||
277 | * @state: second iucv sk state | ||
278 | * | ||
279 | * Returns true if the socket in either in the first or second state. | ||
280 | */ | ||
281 | static int iucv_sock_in_state(struct sock *sk, int state, int state2) | ||
282 | { | ||
283 | return (sk->sk_state == state || sk->sk_state == state2); | ||
284 | } | ||
285 | |||
286 | /** | ||
287 | * iucv_below_msglim() - function to check if messages can be sent | ||
288 | * @sk: sock structure | ||
289 | * | ||
290 | * Returns true if the send queue length is lower than the message limit. | ||
291 | * Always returns true if the socket is not connected (no iucv path for | ||
292 | * checking the message limit). | ||
293 | */ | ||
294 | static inline int iucv_below_msglim(struct sock *sk) | ||
295 | { | ||
296 | struct iucv_sock *iucv = iucv_sk(sk); | ||
297 | |||
298 | if (sk->sk_state != IUCV_CONNECTED) | ||
299 | return 1; | ||
300 | return (skb_queue_len(&iucv->send_skb_q) < iucv->path->msglim); | ||
301 | } | ||
302 | |||
303 | /** | ||
304 | * iucv_sock_wake_msglim() - Wake up thread waiting on msg limit | ||
305 | */ | ||
306 | static void iucv_sock_wake_msglim(struct sock *sk) | ||
307 | { | ||
308 | read_lock(&sk->sk_callback_lock); | ||
309 | if (sk_has_sleeper(sk)) | ||
310 | wake_up_interruptible_all(sk->sk_sleep); | ||
311 | sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); | ||
312 | read_unlock(&sk->sk_callback_lock); | ||
313 | } | ||
314 | |||
241 | /* Timers */ | 315 | /* Timers */ |
242 | static void iucv_sock_timeout(unsigned long arg) | 316 | static void iucv_sock_timeout(unsigned long arg) |
243 | { | 317 | { |
@@ -329,7 +403,9 @@ static void iucv_sock_close(struct sock *sk) | |||
329 | timeo = sk->sk_lingertime; | 403 | timeo = sk->sk_lingertime; |
330 | else | 404 | else |
331 | timeo = IUCV_DISCONN_TIMEOUT; | 405 | timeo = IUCV_DISCONN_TIMEOUT; |
332 | err = iucv_sock_wait_state(sk, IUCV_CLOSED, 0, timeo); | 406 | err = iucv_sock_wait(sk, |
407 | iucv_sock_in_state(sk, IUCV_CLOSED, 0), | ||
408 | timeo); | ||
333 | } | 409 | } |
334 | 410 | ||
335 | case IUCV_CLOSING: /* fall through */ | 411 | case IUCV_CLOSING: /* fall through */ |
@@ -510,39 +586,6 @@ struct sock *iucv_accept_dequeue(struct sock *parent, struct socket *newsock) | |||
510 | return NULL; | 586 | return NULL; |
511 | } | 587 | } |
512 | 588 | ||
513 | int iucv_sock_wait_state(struct sock *sk, int state, int state2, | ||
514 | unsigned long timeo) | ||
515 | { | ||
516 | DECLARE_WAITQUEUE(wait, current); | ||
517 | int err = 0; | ||
518 | |||
519 | add_wait_queue(sk->sk_sleep, &wait); | ||
520 | while (sk->sk_state != state && sk->sk_state != state2) { | ||
521 | set_current_state(TASK_INTERRUPTIBLE); | ||
522 | |||
523 | if (!timeo) { | ||
524 | err = -EAGAIN; | ||
525 | break; | ||
526 | } | ||
527 | |||
528 | if (signal_pending(current)) { | ||
529 | err = sock_intr_errno(timeo); | ||
530 | break; | ||
531 | } | ||
532 | |||
533 | release_sock(sk); | ||
534 | timeo = schedule_timeout(timeo); | ||
535 | lock_sock(sk); | ||
536 | |||
537 | err = sock_error(sk); | ||
538 | if (err) | ||
539 | break; | ||
540 | } | ||
541 | set_current_state(TASK_RUNNING); | ||
542 | remove_wait_queue(sk->sk_sleep, &wait); | ||
543 | return err; | ||
544 | } | ||
545 | |||
546 | /* Bind an unbound socket */ | 589 | /* Bind an unbound socket */ |
547 | static int iucv_sock_bind(struct socket *sock, struct sockaddr *addr, | 590 | static int iucv_sock_bind(struct socket *sock, struct sockaddr *addr, |
548 | int addr_len) | 591 | int addr_len) |
@@ -687,8 +730,9 @@ static int iucv_sock_connect(struct socket *sock, struct sockaddr *addr, | |||
687 | } | 730 | } |
688 | 731 | ||
689 | if (sk->sk_state != IUCV_CONNECTED) { | 732 | if (sk->sk_state != IUCV_CONNECTED) { |
690 | err = iucv_sock_wait_state(sk, IUCV_CONNECTED, IUCV_DISCONN, | 733 | err = iucv_sock_wait(sk, iucv_sock_in_state(sk, IUCV_CONNECTED, |
691 | sock_sndtimeo(sk, flags & O_NONBLOCK)); | 734 | IUCV_DISCONN), |
735 | sock_sndtimeo(sk, flags & O_NONBLOCK)); | ||
692 | } | 736 | } |
693 | 737 | ||
694 | if (sk->sk_state == IUCV_DISCONN) { | 738 | if (sk->sk_state == IUCV_DISCONN) { |
@@ -842,9 +886,11 @@ static int iucv_sock_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
842 | struct iucv_message txmsg; | 886 | struct iucv_message txmsg; |
843 | struct cmsghdr *cmsg; | 887 | struct cmsghdr *cmsg; |
844 | int cmsg_done; | 888 | int cmsg_done; |
889 | long timeo; | ||
845 | char user_id[9]; | 890 | char user_id[9]; |
846 | char appl_id[9]; | 891 | char appl_id[9]; |
847 | int err; | 892 | int err; |
893 | int noblock = msg->msg_flags & MSG_DONTWAIT; | ||
848 | 894 | ||
849 | err = sock_error(sk); | 895 | err = sock_error(sk); |
850 | if (err) | 896 | if (err) |
@@ -864,108 +910,119 @@ static int iucv_sock_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
864 | goto out; | 910 | goto out; |
865 | } | 911 | } |
866 | 912 | ||
867 | if (sk->sk_state == IUCV_CONNECTED) { | 913 | /* Return if the socket is not in connected state */ |
868 | /* initialize defaults */ | 914 | if (sk->sk_state != IUCV_CONNECTED) { |
869 | cmsg_done = 0; /* check for duplicate headers */ | 915 | err = -ENOTCONN; |
870 | txmsg.class = 0; | 916 | goto out; |
917 | } | ||
871 | 918 | ||
872 | /* iterate over control messages */ | 919 | /* initialize defaults */ |
873 | for (cmsg = CMSG_FIRSTHDR(msg); cmsg; | 920 | cmsg_done = 0; /* check for duplicate headers */ |
874 | cmsg = CMSG_NXTHDR(msg, cmsg)) { | 921 | txmsg.class = 0; |
875 | 922 | ||
876 | if (!CMSG_OK(msg, cmsg)) { | 923 | /* iterate over control messages */ |
877 | err = -EINVAL; | 924 | for (cmsg = CMSG_FIRSTHDR(msg); cmsg; |
878 | goto out; | 925 | cmsg = CMSG_NXTHDR(msg, cmsg)) { |
879 | } | 926 | |
927 | if (!CMSG_OK(msg, cmsg)) { | ||
928 | err = -EINVAL; | ||
929 | goto out; | ||
930 | } | ||
931 | |||
932 | if (cmsg->cmsg_level != SOL_IUCV) | ||
933 | continue; | ||
880 | 934 | ||
881 | if (cmsg->cmsg_level != SOL_IUCV) | 935 | if (cmsg->cmsg_type & cmsg_done) { |
882 | continue; | 936 | err = -EINVAL; |
937 | goto out; | ||
938 | } | ||
939 | cmsg_done |= cmsg->cmsg_type; | ||
883 | 940 | ||
884 | if (cmsg->cmsg_type & cmsg_done) { | 941 | switch (cmsg->cmsg_type) { |
942 | case SCM_IUCV_TRGCLS: | ||
943 | if (cmsg->cmsg_len != CMSG_LEN(TRGCLS_SIZE)) { | ||
885 | err = -EINVAL; | 944 | err = -EINVAL; |
886 | goto out; | 945 | goto out; |
887 | } | 946 | } |
888 | cmsg_done |= cmsg->cmsg_type; | ||
889 | |||
890 | switch (cmsg->cmsg_type) { | ||
891 | case SCM_IUCV_TRGCLS: | ||
892 | if (cmsg->cmsg_len != CMSG_LEN(TRGCLS_SIZE)) { | ||
893 | err = -EINVAL; | ||
894 | goto out; | ||
895 | } | ||
896 | 947 | ||
897 | /* set iucv message target class */ | 948 | /* set iucv message target class */ |
898 | memcpy(&txmsg.class, | 949 | memcpy(&txmsg.class, |
899 | (void *) CMSG_DATA(cmsg), TRGCLS_SIZE); | 950 | (void *) CMSG_DATA(cmsg), TRGCLS_SIZE); |
900 | 951 | ||
901 | break; | 952 | break; |
902 | 953 | ||
903 | default: | 954 | default: |
904 | err = -EINVAL; | 955 | err = -EINVAL; |
905 | goto out; | 956 | goto out; |
906 | break; | 957 | break; |
907 | } | ||
908 | } | 958 | } |
959 | } | ||
909 | 960 | ||
910 | /* allocate one skb for each iucv message: | 961 | /* allocate one skb for each iucv message: |
911 | * this is fine for SOCK_SEQPACKET (unless we want to support | 962 | * this is fine for SOCK_SEQPACKET (unless we want to support |
912 | * segmented records using the MSG_EOR flag), but | 963 | * segmented records using the MSG_EOR flag), but |
913 | * for SOCK_STREAM we might want to improve it in future */ | 964 | * for SOCK_STREAM we might want to improve it in future */ |
914 | if (!(skb = sock_alloc_send_skb(sk, len, | 965 | skb = sock_alloc_send_skb(sk, len, noblock, &err); |
915 | msg->msg_flags & MSG_DONTWAIT, | 966 | if (!skb) |
916 | &err))) | 967 | goto out; |
917 | goto out; | 968 | if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) { |
969 | err = -EFAULT; | ||
970 | goto fail; | ||
971 | } | ||
918 | 972 | ||
919 | if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) { | 973 | /* wait if outstanding messages for iucv path has reached */ |
920 | err = -EFAULT; | 974 | timeo = sock_sndtimeo(sk, noblock); |
921 | goto fail; | 975 | err = iucv_sock_wait(sk, iucv_below_msglim(sk), timeo); |
922 | } | 976 | if (err) |
977 | goto fail; | ||
923 | 978 | ||
924 | /* increment and save iucv message tag for msg_completion cbk */ | 979 | /* return -ECONNRESET if the socket is no longer connected */ |
925 | txmsg.tag = iucv->send_tag++; | 980 | if (sk->sk_state != IUCV_CONNECTED) { |
926 | memcpy(CB_TAG(skb), &txmsg.tag, CB_TAG_LEN); | 981 | err = -ECONNRESET; |
927 | skb_queue_tail(&iucv->send_skb_q, skb); | 982 | goto fail; |
983 | } | ||
928 | 984 | ||
929 | if (((iucv->path->flags & IUCV_IPRMDATA) & iucv->flags) | 985 | /* increment and save iucv message tag for msg_completion cbk */ |
930 | && skb->len <= 7) { | 986 | txmsg.tag = iucv->send_tag++; |
931 | err = iucv_send_iprm(iucv->path, &txmsg, skb); | 987 | memcpy(CB_TAG(skb), &txmsg.tag, CB_TAG_LEN); |
988 | skb_queue_tail(&iucv->send_skb_q, skb); | ||
932 | 989 | ||
933 | /* on success: there is no message_complete callback | 990 | if (((iucv->path->flags & IUCV_IPRMDATA) & iucv->flags) |
934 | * for an IPRMDATA msg; remove skb from send queue */ | 991 | && skb->len <= 7) { |
935 | if (err == 0) { | 992 | err = iucv_send_iprm(iucv->path, &txmsg, skb); |
936 | skb_unlink(skb, &iucv->send_skb_q); | ||
937 | kfree_skb(skb); | ||
938 | } | ||
939 | 993 | ||
940 | /* this error should never happen since the | 994 | /* on success: there is no message_complete callback |
941 | * IUCV_IPRMDATA path flag is set... sever path */ | 995 | * for an IPRMDATA msg; remove skb from send queue */ |
942 | if (err == 0x15) { | 996 | if (err == 0) { |
943 | iucv_path_sever(iucv->path, NULL); | 997 | skb_unlink(skb, &iucv->send_skb_q); |
944 | skb_unlink(skb, &iucv->send_skb_q); | 998 | kfree_skb(skb); |
945 | err = -EPIPE; | 999 | } |
946 | goto fail; | 1000 | |
947 | } | 1001 | /* this error should never happen since the |
948 | } else | 1002 | * IUCV_IPRMDATA path flag is set... sever path */ |
949 | err = iucv_message_send(iucv->path, &txmsg, 0, 0, | 1003 | if (err == 0x15) { |
950 | (void *) skb->data, skb->len); | 1004 | iucv_path_sever(iucv->path, NULL); |
951 | if (err) { | ||
952 | if (err == 3) { | ||
953 | user_id[8] = 0; | ||
954 | memcpy(user_id, iucv->dst_user_id, 8); | ||
955 | appl_id[8] = 0; | ||
956 | memcpy(appl_id, iucv->dst_name, 8); | ||
957 | pr_err("Application %s on z/VM guest %s" | ||
958 | " exceeds message limit\n", | ||
959 | user_id, appl_id); | ||
960 | } | ||
961 | skb_unlink(skb, &iucv->send_skb_q); | 1005 | skb_unlink(skb, &iucv->send_skb_q); |
962 | err = -EPIPE; | 1006 | err = -EPIPE; |
963 | goto fail; | 1007 | goto fail; |
964 | } | 1008 | } |
965 | 1009 | } else | |
966 | } else { | 1010 | err = iucv_message_send(iucv->path, &txmsg, 0, 0, |
967 | err = -ENOTCONN; | 1011 | (void *) skb->data, skb->len); |
968 | goto out; | 1012 | if (err) { |
1013 | if (err == 3) { | ||
1014 | user_id[8] = 0; | ||
1015 | memcpy(user_id, iucv->dst_user_id, 8); | ||
1016 | appl_id[8] = 0; | ||
1017 | memcpy(appl_id, iucv->dst_name, 8); | ||
1018 | pr_err("Application %s on z/VM guest %s" | ||
1019 | " exceeds message limit\n", | ||
1020 | appl_id, user_id); | ||
1021 | err = -EAGAIN; | ||
1022 | } else | ||
1023 | err = -EPIPE; | ||
1024 | skb_unlink(skb, &iucv->send_skb_q); | ||
1025 | goto fail; | ||
969 | } | 1026 | } |
970 | 1027 | ||
971 | release_sock(sk); | 1028 | release_sock(sk); |
@@ -1199,7 +1256,7 @@ unsigned int iucv_sock_poll(struct file *file, struct socket *sock, | |||
1199 | struct sock *sk = sock->sk; | 1256 | struct sock *sk = sock->sk; |
1200 | unsigned int mask = 0; | 1257 | unsigned int mask = 0; |
1201 | 1258 | ||
1202 | poll_wait(file, sk->sk_sleep, wait); | 1259 | sock_poll_wait(file, sk->sk_sleep, wait); |
1203 | 1260 | ||
1204 | if (sk->sk_state == IUCV_LISTEN) | 1261 | if (sk->sk_state == IUCV_LISTEN) |
1205 | return iucv_accept_poll(sk); | 1262 | return iucv_accept_poll(sk); |
@@ -1581,7 +1638,11 @@ static void iucv_callback_txdone(struct iucv_path *path, | |||
1581 | 1638 | ||
1582 | spin_unlock_irqrestore(&list->lock, flags); | 1639 | spin_unlock_irqrestore(&list->lock, flags); |
1583 | 1640 | ||
1584 | kfree_skb(this); | 1641 | if (this) { |
1642 | kfree_skb(this); | ||
1643 | /* wake up any process waiting for sending */ | ||
1644 | iucv_sock_wake_msglim(sk); | ||
1645 | } | ||
1585 | } | 1646 | } |
1586 | BUG_ON(!this); | 1647 | BUG_ON(!this); |
1587 | 1648 | ||
diff --git a/net/key/af_key.c b/net/key/af_key.c index 643c1be2d02e..dba9abd27f90 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c | |||
@@ -3662,8 +3662,8 @@ static int pfkey_seq_show(struct seq_file *f, void *v) | |||
3662 | seq_printf(f ,"%p %-6d %-6u %-6u %-6u %-6lu\n", | 3662 | seq_printf(f ,"%p %-6d %-6u %-6u %-6u %-6lu\n", |
3663 | s, | 3663 | s, |
3664 | atomic_read(&s->sk_refcnt), | 3664 | atomic_read(&s->sk_refcnt), |
3665 | atomic_read(&s->sk_rmem_alloc), | 3665 | sk_rmem_alloc_get(s), |
3666 | atomic_read(&s->sk_wmem_alloc), | 3666 | sk_wmem_alloc_get(s), |
3667 | sock_i_uid(s), | 3667 | sock_i_uid(s), |
3668 | sock_i_ino(s) | 3668 | sock_i_ino(s) |
3669 | ); | 3669 | ); |
diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c index 9208cf5f2bd5..c45eee1c0e8d 100644 --- a/net/llc/af_llc.c +++ b/net/llc/af_llc.c | |||
@@ -914,6 +914,7 @@ static int llc_ui_getname(struct socket *sock, struct sockaddr *uaddr, | |||
914 | struct llc_sock *llc = llc_sk(sk); | 914 | struct llc_sock *llc = llc_sk(sk); |
915 | int rc = 0; | 915 | int rc = 0; |
916 | 916 | ||
917 | memset(&sllc, 0, sizeof(sllc)); | ||
917 | lock_sock(sk); | 918 | lock_sock(sk); |
918 | if (sock_flag(sk, SOCK_ZAPPED)) | 919 | if (sock_flag(sk, SOCK_ZAPPED)) |
919 | goto out; | 920 | goto out; |
diff --git a/net/llc/llc_proc.c b/net/llc/llc_proc.c index d208b3396d94..f97be471fe2e 100644 --- a/net/llc/llc_proc.c +++ b/net/llc/llc_proc.c | |||
@@ -134,8 +134,8 @@ static int llc_seq_socket_show(struct seq_file *seq, void *v) | |||
134 | seq_printf(seq, "@%02X ", llc->sap->laddr.lsap); | 134 | seq_printf(seq, "@%02X ", llc->sap->laddr.lsap); |
135 | llc_ui_format_mac(seq, llc->daddr.mac); | 135 | llc_ui_format_mac(seq, llc->daddr.mac); |
136 | seq_printf(seq, "@%02X %8d %8d %2d %3d %4d\n", llc->daddr.lsap, | 136 | seq_printf(seq, "@%02X %8d %8d %2d %3d %4d\n", llc->daddr.lsap, |
137 | atomic_read(&sk->sk_wmem_alloc), | 137 | sk_wmem_alloc_get(sk), |
138 | atomic_read(&sk->sk_rmem_alloc) - llc->copied_seq, | 138 | sk_rmem_alloc_get(sk) - llc->copied_seq, |
139 | sk->sk_state, | 139 | sk->sk_state, |
140 | sk->sk_socket ? SOCK_INODE(sk->sk_socket)->i_uid : -1, | 140 | sk->sk_socket ? SOCK_INODE(sk->sk_socket)->i_uid : -1, |
141 | llc->link); | 141 | llc->link); |
diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig index ba2643a43c73..7836ee928983 100644 --- a/net/mac80211/Kconfig +++ b/net/mac80211/Kconfig | |||
@@ -83,6 +83,7 @@ endmenu | |||
83 | config MAC80211_MESH | 83 | config MAC80211_MESH |
84 | bool "Enable mac80211 mesh networking (pre-802.11s) support" | 84 | bool "Enable mac80211 mesh networking (pre-802.11s) support" |
85 | depends on MAC80211 && EXPERIMENTAL | 85 | depends on MAC80211 && EXPERIMENTAL |
86 | depends on BROKEN | ||
86 | ---help--- | 87 | ---help--- |
87 | This options enables support of Draft 802.11s mesh networking. | 88 | This options enables support of Draft 802.11s mesh networking. |
88 | The implementation is based on Draft 1.08 of the Mesh Networking | 89 | The implementation is based on Draft 1.08 of the Mesh Networking |
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index 9e5762ad307d..a24e59816b93 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c | |||
@@ -381,6 +381,14 @@ static void ieee80211_agg_splice_packets(struct ieee80211_local *local, | |||
381 | &local->hw, queue, | 381 | &local->hw, queue, |
382 | IEEE80211_QUEUE_STOP_REASON_AGGREGATION); | 382 | IEEE80211_QUEUE_STOP_REASON_AGGREGATION); |
383 | 383 | ||
384 | if (!(sta->ampdu_mlme.tid_state_tx[tid] & HT_ADDBA_REQUESTED_MSK)) | ||
385 | return; | ||
386 | |||
387 | if (WARN(!sta->ampdu_mlme.tid_tx[tid], | ||
388 | "TID %d gone but expected when splicing aggregates from" | ||
389 | "the pending queue\n", tid)) | ||
390 | return; | ||
391 | |||
384 | if (!skb_queue_empty(&sta->ampdu_mlme.tid_tx[tid]->pending)) { | 392 | if (!skb_queue_empty(&sta->ampdu_mlme.tid_tx[tid]->pending)) { |
385 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); | 393 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); |
386 | /* mark queue as pending, it is stopped already */ | 394 | /* mark queue as pending, it is stopped already */ |
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index 11c72311f35b..6c439cd5ccea 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c | |||
@@ -163,6 +163,29 @@ static const struct file_operations noack_ops = { | |||
163 | .open = mac80211_open_file_generic | 163 | .open = mac80211_open_file_generic |
164 | }; | 164 | }; |
165 | 165 | ||
166 | static ssize_t queues_read(struct file *file, char __user *user_buf, | ||
167 | size_t count, loff_t *ppos) | ||
168 | { | ||
169 | struct ieee80211_local *local = file->private_data; | ||
170 | unsigned long flags; | ||
171 | char buf[IEEE80211_MAX_QUEUES * 20]; | ||
172 | int q, res = 0; | ||
173 | |||
174 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); | ||
175 | for (q = 0; q < local->hw.queues; q++) | ||
176 | res += sprintf(buf + res, "%02d: %#.8lx/%d\n", q, | ||
177 | local->queue_stop_reasons[q], | ||
178 | __netif_subqueue_stopped(local->mdev, q)); | ||
179 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | ||
180 | |||
181 | return simple_read_from_buffer(user_buf, count, ppos, buf, res); | ||
182 | } | ||
183 | |||
184 | static const struct file_operations queues_ops = { | ||
185 | .read = queues_read, | ||
186 | .open = mac80211_open_file_generic | ||
187 | }; | ||
188 | |||
166 | /* statistics stuff */ | 189 | /* statistics stuff */ |
167 | 190 | ||
168 | #define DEBUGFS_STATS_FILE(name, buflen, fmt, value...) \ | 191 | #define DEBUGFS_STATS_FILE(name, buflen, fmt, value...) \ |
@@ -298,6 +321,7 @@ void debugfs_hw_add(struct ieee80211_local *local) | |||
298 | DEBUGFS_ADD(total_ps_buffered); | 321 | DEBUGFS_ADD(total_ps_buffered); |
299 | DEBUGFS_ADD(wep_iv); | 322 | DEBUGFS_ADD(wep_iv); |
300 | DEBUGFS_ADD(tsf); | 323 | DEBUGFS_ADD(tsf); |
324 | DEBUGFS_ADD(queues); | ||
301 | DEBUGFS_ADD_MODE(reset, 0200); | 325 | DEBUGFS_ADD_MODE(reset, 0200); |
302 | DEBUGFS_ADD(noack); | 326 | DEBUGFS_ADD(noack); |
303 | 327 | ||
@@ -350,6 +374,7 @@ void debugfs_hw_del(struct ieee80211_local *local) | |||
350 | DEBUGFS_DEL(total_ps_buffered); | 374 | DEBUGFS_DEL(total_ps_buffered); |
351 | DEBUGFS_DEL(wep_iv); | 375 | DEBUGFS_DEL(wep_iv); |
352 | DEBUGFS_DEL(tsf); | 376 | DEBUGFS_DEL(tsf); |
377 | DEBUGFS_DEL(queues); | ||
353 | DEBUGFS_DEL(reset); | 378 | DEBUGFS_DEL(reset); |
354 | DEBUGFS_DEL(noack); | 379 | DEBUGFS_DEL(noack); |
355 | 380 | ||
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 4dbc28964196..68eb5052179a 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -783,6 +783,7 @@ struct ieee80211_local { | |||
783 | struct dentry *total_ps_buffered; | 783 | struct dentry *total_ps_buffered; |
784 | struct dentry *wep_iv; | 784 | struct dentry *wep_iv; |
785 | struct dentry *tsf; | 785 | struct dentry *tsf; |
786 | struct dentry *queues; | ||
786 | struct dentry *reset; | 787 | struct dentry *reset; |
787 | struct dentry *noack; | 788 | struct dentry *noack; |
788 | struct dentry *statistics; | 789 | struct dentry *statistics; |
@@ -1100,7 +1101,6 @@ void ieee802_11_parse_elems(u8 *start, size_t len, | |||
1100 | u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, | 1101 | u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, |
1101 | struct ieee802_11_elems *elems, | 1102 | struct ieee802_11_elems *elems, |
1102 | u64 filter, u32 crc); | 1103 | u64 filter, u32 crc); |
1103 | int ieee80211_set_freq(struct ieee80211_sub_if_data *sdata, int freq); | ||
1104 | u32 ieee80211_mandatory_rates(struct ieee80211_local *local, | 1104 | u32 ieee80211_mandatory_rates(struct ieee80211_local *local, |
1105 | enum ieee80211_band band); | 1105 | enum ieee80211_band band); |
1106 | 1106 | ||
diff --git a/net/mac80211/key.c b/net/mac80211/key.c index ce267565e180..659a42d529e3 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c | |||
@@ -67,6 +67,8 @@ static DECLARE_WORK(todo_work, key_todo); | |||
67 | * | 67 | * |
68 | * @key: key to add to do item for | 68 | * @key: key to add to do item for |
69 | * @flag: todo flag(s) | 69 | * @flag: todo flag(s) |
70 | * | ||
71 | * Must be called with IRQs or softirqs disabled. | ||
70 | */ | 72 | */ |
71 | static void add_todo(struct ieee80211_key *key, u32 flag) | 73 | static void add_todo(struct ieee80211_key *key, u32 flag) |
72 | { | 74 | { |
@@ -140,9 +142,9 @@ static void ieee80211_key_enable_hw_accel(struct ieee80211_key *key) | |||
140 | ret = drv_set_key(key->local, SET_KEY, &sdata->vif, sta, &key->conf); | 142 | ret = drv_set_key(key->local, SET_KEY, &sdata->vif, sta, &key->conf); |
141 | 143 | ||
142 | if (!ret) { | 144 | if (!ret) { |
143 | spin_lock(&todo_lock); | 145 | spin_lock_bh(&todo_lock); |
144 | key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE; | 146 | key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE; |
145 | spin_unlock(&todo_lock); | 147 | spin_unlock_bh(&todo_lock); |
146 | } | 148 | } |
147 | 149 | ||
148 | if (ret && ret != -ENOSPC && ret != -EOPNOTSUPP) | 150 | if (ret && ret != -ENOSPC && ret != -EOPNOTSUPP) |
@@ -164,12 +166,12 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key) | |||
164 | if (!key || !key->local->ops->set_key) | 166 | if (!key || !key->local->ops->set_key) |
165 | return; | 167 | return; |
166 | 168 | ||
167 | spin_lock(&todo_lock); | 169 | spin_lock_bh(&todo_lock); |
168 | if (!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) { | 170 | if (!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) { |
169 | spin_unlock(&todo_lock); | 171 | spin_unlock_bh(&todo_lock); |
170 | return; | 172 | return; |
171 | } | 173 | } |
172 | spin_unlock(&todo_lock); | 174 | spin_unlock_bh(&todo_lock); |
173 | 175 | ||
174 | sta = get_sta_for_key(key); | 176 | sta = get_sta_for_key(key); |
175 | sdata = key->sdata; | 177 | sdata = key->sdata; |
@@ -188,9 +190,9 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key) | |||
188 | wiphy_name(key->local->hw.wiphy), | 190 | wiphy_name(key->local->hw.wiphy), |
189 | key->conf.keyidx, sta ? sta->addr : bcast_addr, ret); | 191 | key->conf.keyidx, sta ? sta->addr : bcast_addr, ret); |
190 | 192 | ||
191 | spin_lock(&todo_lock); | 193 | spin_lock_bh(&todo_lock); |
192 | key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE; | 194 | key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE; |
193 | spin_unlock(&todo_lock); | 195 | spin_unlock_bh(&todo_lock); |
194 | } | 196 | } |
195 | 197 | ||
196 | static void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, | 198 | static void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, |
@@ -437,14 +439,14 @@ void ieee80211_key_link(struct ieee80211_key *key, | |||
437 | 439 | ||
438 | __ieee80211_key_replace(sdata, sta, old_key, key); | 440 | __ieee80211_key_replace(sdata, sta, old_key, key); |
439 | 441 | ||
440 | spin_unlock_irqrestore(&sdata->local->key_lock, flags); | ||
441 | |||
442 | /* free old key later */ | 442 | /* free old key later */ |
443 | add_todo(old_key, KEY_FLAG_TODO_DELETE); | 443 | add_todo(old_key, KEY_FLAG_TODO_DELETE); |
444 | 444 | ||
445 | add_todo(key, KEY_FLAG_TODO_ADD_DEBUGFS); | 445 | add_todo(key, KEY_FLAG_TODO_ADD_DEBUGFS); |
446 | if (netif_running(sdata->dev)) | 446 | if (netif_running(sdata->dev)) |
447 | add_todo(key, KEY_FLAG_TODO_HWACCEL_ADD); | 447 | add_todo(key, KEY_FLAG_TODO_HWACCEL_ADD); |
448 | |||
449 | spin_unlock_irqrestore(&sdata->local->key_lock, flags); | ||
448 | } | 450 | } |
449 | 451 | ||
450 | static void __ieee80211_key_free(struct ieee80211_key *key) | 452 | static void __ieee80211_key_free(struct ieee80211_key *key) |
@@ -547,7 +549,7 @@ static void __ieee80211_key_todo(void) | |||
547 | */ | 549 | */ |
548 | synchronize_rcu(); | 550 | synchronize_rcu(); |
549 | 551 | ||
550 | spin_lock(&todo_lock); | 552 | spin_lock_bh(&todo_lock); |
551 | while (!list_empty(&todo_list)) { | 553 | while (!list_empty(&todo_list)) { |
552 | key = list_first_entry(&todo_list, struct ieee80211_key, todo); | 554 | key = list_first_entry(&todo_list, struct ieee80211_key, todo); |
553 | list_del_init(&key->todo); | 555 | list_del_init(&key->todo); |
@@ -558,7 +560,7 @@ static void __ieee80211_key_todo(void) | |||
558 | KEY_FLAG_TODO_HWACCEL_REMOVE | | 560 | KEY_FLAG_TODO_HWACCEL_REMOVE | |
559 | KEY_FLAG_TODO_DELETE); | 561 | KEY_FLAG_TODO_DELETE); |
560 | key->flags &= ~todoflags; | 562 | key->flags &= ~todoflags; |
561 | spin_unlock(&todo_lock); | 563 | spin_unlock_bh(&todo_lock); |
562 | 564 | ||
563 | work_done = false; | 565 | work_done = false; |
564 | 566 | ||
@@ -591,9 +593,9 @@ static void __ieee80211_key_todo(void) | |||
591 | 593 | ||
592 | WARN_ON(!work_done); | 594 | WARN_ON(!work_done); |
593 | 595 | ||
594 | spin_lock(&todo_lock); | 596 | spin_lock_bh(&todo_lock); |
595 | } | 597 | } |
596 | spin_unlock(&todo_lock); | 598 | spin_unlock_bh(&todo_lock); |
597 | } | 599 | } |
598 | 600 | ||
599 | void ieee80211_key_todo(void) | 601 | void ieee80211_key_todo(void) |
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index fc712e60705d..11cf45bce38a 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
@@ -494,7 +494,7 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) | |||
494 | * should it be using the interface and enqueuing | 494 | * should it be using the interface and enqueuing |
495 | * frames at this very time on another CPU. | 495 | * frames at this very time on another CPU. |
496 | */ | 496 | */ |
497 | synchronize_rcu(); | 497 | rcu_barrier(); /* Wait for RX path and call_rcu()'s */ |
498 | skb_queue_purge(&sdata->u.mesh.skb_queue); | 498 | skb_queue_purge(&sdata->u.mesh.skb_queue); |
499 | } | 499 | } |
500 | 500 | ||
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index 003cb470ac84..f49ef288e2e2 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c | |||
@@ -637,7 +637,7 @@ static void mesh_queue_preq(struct mesh_path *mpath, u8 flags) | |||
637 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 637 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
638 | struct mesh_preq_queue *preq_node; | 638 | struct mesh_preq_queue *preq_node; |
639 | 639 | ||
640 | preq_node = kmalloc(sizeof(struct mesh_preq_queue), GFP_KERNEL); | 640 | preq_node = kmalloc(sizeof(struct mesh_preq_queue), GFP_ATOMIC); |
641 | if (!preq_node) { | 641 | if (!preq_node) { |
642 | printk(KERN_DEBUG "Mesh HWMP: could not allocate PREQ node\n"); | 642 | printk(KERN_DEBUG "Mesh HWMP: could not allocate PREQ node\n"); |
643 | return; | 643 | return; |
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index 3c72557df45a..479597e88583 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c | |||
@@ -175,6 +175,8 @@ int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata) | |||
175 | int err = 0; | 175 | int err = 0; |
176 | u32 hash_idx; | 176 | u32 hash_idx; |
177 | 177 | ||
178 | might_sleep(); | ||
179 | |||
178 | if (memcmp(dst, sdata->dev->dev_addr, ETH_ALEN) == 0) | 180 | if (memcmp(dst, sdata->dev->dev_addr, ETH_ALEN) == 0) |
179 | /* never add ourselves as neighbours */ | 181 | /* never add ourselves as neighbours */ |
180 | return -ENOTSUPP; | 182 | return -ENOTSUPP; |
@@ -265,6 +267,7 @@ int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata) | |||
265 | int err = 0; | 267 | int err = 0; |
266 | u32 hash_idx; | 268 | u32 hash_idx; |
267 | 269 | ||
270 | might_sleep(); | ||
268 | 271 | ||
269 | if (memcmp(dst, sdata->dev->dev_addr, ETH_ALEN) == 0) | 272 | if (memcmp(dst, sdata->dev->dev_addr, ETH_ALEN) == 0) |
270 | /* never add ourselves as neighbours */ | 273 | /* never add ourselves as neighbours */ |
@@ -491,8 +494,10 @@ void mesh_path_tx_pending(struct mesh_path *mpath) | |||
491 | * @skb: frame to discard | 494 | * @skb: frame to discard |
492 | * @sdata: network subif the frame was to be sent through | 495 | * @sdata: network subif the frame was to be sent through |
493 | * | 496 | * |
494 | * If the frame was beign forwarded from another MP, a PERR frame will be sent | 497 | * If the frame was being forwarded from another MP, a PERR frame will be sent |
495 | * to the precursor. | 498 | * to the precursor. The precursor's address (i.e. the previous hop) was saved |
499 | * in addr1 of the frame-to-be-forwarded, and would only be overwritten once | ||
500 | * the destination is successfully resolved. | ||
496 | * | 501 | * |
497 | * Locking: the function must me called within a rcu_read_lock region | 502 | * Locking: the function must me called within a rcu_read_lock region |
498 | */ | 503 | */ |
@@ -507,7 +512,7 @@ void mesh_path_discard_frame(struct sk_buff *skb, | |||
507 | u8 *ra, *da; | 512 | u8 *ra, *da; |
508 | 513 | ||
509 | da = hdr->addr3; | 514 | da = hdr->addr3; |
510 | ra = hdr->addr2; | 515 | ra = hdr->addr1; |
511 | mpath = mesh_path_lookup(da, sdata); | 516 | mpath = mesh_path_lookup(da, sdata); |
512 | if (mpath) | 517 | if (mpath) |
513 | dsn = ++mpath->dsn; | 518 | dsn = ++mpath->dsn; |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index d779c57a8220..07e7e41816be 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -721,7 +721,7 @@ void ieee80211_dynamic_ps_timer(unsigned long data) | |||
721 | { | 721 | { |
722 | struct ieee80211_local *local = (void *) data; | 722 | struct ieee80211_local *local = (void *) data; |
723 | 723 | ||
724 | if (local->quiescing) | 724 | if (local->quiescing || local->suspended) |
725 | return; | 725 | return; |
726 | 726 | ||
727 | queue_work(local->hw.workqueue, &local->dynamic_ps_enable_work); | 727 | queue_work(local->hw.workqueue, &local->dynamic_ps_enable_work); |
@@ -1102,14 +1102,6 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1102 | struct sta_info *sta; | 1102 | struct sta_info *sta; |
1103 | u32 changed = 0, config_changed = 0; | 1103 | u32 changed = 0, config_changed = 0; |
1104 | 1104 | ||
1105 | rcu_read_lock(); | ||
1106 | |||
1107 | sta = sta_info_get(local, ifmgd->bssid); | ||
1108 | if (!sta) { | ||
1109 | rcu_read_unlock(); | ||
1110 | return; | ||
1111 | } | ||
1112 | |||
1113 | if (deauth) { | 1105 | if (deauth) { |
1114 | ifmgd->direct_probe_tries = 0; | 1106 | ifmgd->direct_probe_tries = 0; |
1115 | ifmgd->auth_tries = 0; | 1107 | ifmgd->auth_tries = 0; |
@@ -1120,7 +1112,11 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1120 | netif_tx_stop_all_queues(sdata->dev); | 1112 | netif_tx_stop_all_queues(sdata->dev); |
1121 | netif_carrier_off(sdata->dev); | 1113 | netif_carrier_off(sdata->dev); |
1122 | 1114 | ||
1123 | ieee80211_sta_tear_down_BA_sessions(sta); | 1115 | rcu_read_lock(); |
1116 | sta = sta_info_get(local, ifmgd->bssid); | ||
1117 | if (sta) | ||
1118 | ieee80211_sta_tear_down_BA_sessions(sta); | ||
1119 | rcu_read_unlock(); | ||
1124 | 1120 | ||
1125 | bss = ieee80211_rx_bss_get(local, ifmgd->bssid, | 1121 | bss = ieee80211_rx_bss_get(local, ifmgd->bssid, |
1126 | conf->channel->center_freq, | 1122 | conf->channel->center_freq, |
@@ -1156,8 +1152,6 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1156 | ifmgd->ssid, ifmgd->ssid_len); | 1152 | ifmgd->ssid, ifmgd->ssid_len); |
1157 | } | 1153 | } |
1158 | 1154 | ||
1159 | rcu_read_unlock(); | ||
1160 | |||
1161 | ieee80211_set_wmm_default(sdata); | 1155 | ieee80211_set_wmm_default(sdata); |
1162 | 1156 | ||
1163 | ieee80211_recalc_idle(local); | 1157 | ieee80211_recalc_idle(local); |
@@ -2223,7 +2217,10 @@ static int ieee80211_sta_config_auth(struct ieee80211_sub_if_data *sdata) | |||
2223 | capa_mask, capa_val); | 2217 | capa_mask, capa_val); |
2224 | 2218 | ||
2225 | if (bss) { | 2219 | if (bss) { |
2226 | ieee80211_set_freq(sdata, bss->cbss.channel->center_freq); | 2220 | local->oper_channel = bss->cbss.channel; |
2221 | local->oper_channel_type = NL80211_CHAN_NO_HT; | ||
2222 | ieee80211_hw_config(local, 0); | ||
2223 | |||
2227 | if (!(ifmgd->flags & IEEE80211_STA_SSID_SET)) | 2224 | if (!(ifmgd->flags & IEEE80211_STA_SSID_SET)) |
2228 | ieee80211_sta_set_ssid(sdata, bss->ssid, | 2225 | ieee80211_sta_set_ssid(sdata, bss->ssid, |
2229 | bss->ssid_len); | 2226 | bss->ssid_len); |
@@ -2445,6 +2442,14 @@ void ieee80211_sta_req_auth(struct ieee80211_sub_if_data *sdata) | |||
2445 | ieee80211_set_disassoc(sdata, true, true, | 2442 | ieee80211_set_disassoc(sdata, true, true, |
2446 | WLAN_REASON_DEAUTH_LEAVING); | 2443 | WLAN_REASON_DEAUTH_LEAVING); |
2447 | 2444 | ||
2445 | if (ifmgd->ssid_len == 0) { | ||
2446 | /* | ||
2447 | * Only allow association to be started if a valid SSID | ||
2448 | * is configured. | ||
2449 | */ | ||
2450 | return; | ||
2451 | } | ||
2452 | |||
2448 | if (!(ifmgd->flags & IEEE80211_STA_EXT_SME) || | 2453 | if (!(ifmgd->flags & IEEE80211_STA_EXT_SME) || |
2449 | ifmgd->state != IEEE80211_STA_MLME_ASSOCIATE) | 2454 | ifmgd->state != IEEE80211_STA_MLME_ASSOCIATE) |
2450 | set_bit(IEEE80211_STA_REQ_AUTH, &ifmgd->request); | 2455 | set_bit(IEEE80211_STA_REQ_AUTH, &ifmgd->request); |
@@ -2476,6 +2481,10 @@ int ieee80211_sta_set_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size | |||
2476 | ifmgd = &sdata->u.mgd; | 2481 | ifmgd = &sdata->u.mgd; |
2477 | 2482 | ||
2478 | if (ifmgd->ssid_len != len || memcmp(ifmgd->ssid, ssid, len) != 0) { | 2483 | if (ifmgd->ssid_len != len || memcmp(ifmgd->ssid, ssid, len) != 0) { |
2484 | if (ifmgd->state == IEEE80211_STA_MLME_ASSOCIATED) | ||
2485 | ieee80211_set_disassoc(sdata, true, true, | ||
2486 | WLAN_REASON_DEAUTH_LEAVING); | ||
2487 | |||
2479 | /* | 2488 | /* |
2480 | * Do not use reassociation if SSID is changed (different ESS). | 2489 | * Do not use reassociation if SSID is changed (different ESS). |
2481 | */ | 2490 | */ |
@@ -2500,6 +2509,11 @@ int ieee80211_sta_set_bssid(struct ieee80211_sub_if_data *sdata, u8 *bssid) | |||
2500 | { | 2509 | { |
2501 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 2510 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
2502 | 2511 | ||
2512 | if (compare_ether_addr(bssid, ifmgd->bssid) != 0 && | ||
2513 | ifmgd->state == IEEE80211_STA_MLME_ASSOCIATED) | ||
2514 | ieee80211_set_disassoc(sdata, true, true, | ||
2515 | WLAN_REASON_DEAUTH_LEAVING); | ||
2516 | |||
2503 | if (is_valid_ether_addr(bssid)) { | 2517 | if (is_valid_ether_addr(bssid)) { |
2504 | memcpy(ifmgd->bssid, bssid, ETH_ALEN); | 2518 | memcpy(ifmgd->bssid, bssid, ETH_ALEN); |
2505 | ifmgd->flags |= IEEE80211_STA_BSSID_SET; | 2519 | ifmgd->flags |= IEEE80211_STA_BSSID_SET; |
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index 7a549f9deb96..5e3d476972f9 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c | |||
@@ -55,15 +55,6 @@ int __ieee80211_suspend(struct ieee80211_hw *hw) | |||
55 | 55 | ||
56 | rcu_read_unlock(); | 56 | rcu_read_unlock(); |
57 | 57 | ||
58 | /* flush again, in case driver queued work */ | ||
59 | flush_workqueue(local->hw.workqueue); | ||
60 | |||
61 | /* stop hardware - this must stop RX */ | ||
62 | if (local->open_count) { | ||
63 | ieee80211_led_radio(local, false); | ||
64 | drv_stop(local); | ||
65 | } | ||
66 | |||
67 | /* remove STAs */ | 58 | /* remove STAs */ |
68 | spin_lock_irqsave(&local->sta_lock, flags); | 59 | spin_lock_irqsave(&local->sta_lock, flags); |
69 | list_for_each_entry(sta, &local->sta_list, list) { | 60 | list_for_each_entry(sta, &local->sta_list, list) { |
@@ -111,7 +102,22 @@ int __ieee80211_suspend(struct ieee80211_hw *hw) | |||
111 | drv_remove_interface(local, &conf); | 102 | drv_remove_interface(local, &conf); |
112 | } | 103 | } |
113 | 104 | ||
105 | /* stop hardware - this must stop RX */ | ||
106 | if (local->open_count) { | ||
107 | ieee80211_led_radio(local, false); | ||
108 | drv_stop(local); | ||
109 | } | ||
110 | |||
111 | /* | ||
112 | * flush again, in case driver queued work -- it | ||
113 | * shouldn't be doing (or cancel everything in the | ||
114 | * stop callback) that but better safe than sorry. | ||
115 | */ | ||
116 | flush_workqueue(local->hw.workqueue); | ||
117 | |||
114 | local->suspended = true; | 118 | local->suspended = true; |
119 | /* need suspended to be visible before quiescing is false */ | ||
120 | barrier(); | ||
115 | local->quiescing = false; | 121 | local->quiescing = false; |
116 | 122 | ||
117 | return 0; | 123 | return 0; |
diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c index b218b98fba7f..37771abd8f5a 100644 --- a/net/mac80211/rc80211_minstrel.c +++ b/net/mac80211/rc80211_minstrel.c | |||
@@ -66,7 +66,7 @@ rix_to_ndx(struct minstrel_sta_info *mi, int rix) | |||
66 | for (i = rix; i >= 0; i--) | 66 | for (i = rix; i >= 0; i--) |
67 | if (mi->r[i].rix == rix) | 67 | if (mi->r[i].rix == rix) |
68 | break; | 68 | break; |
69 | WARN_ON(mi->r[i].rix != rix); | 69 | WARN_ON(i < 0); |
70 | return i; | 70 | return i; |
71 | } | 71 | } |
72 | 72 | ||
@@ -181,6 +181,9 @@ minstrel_tx_status(void *priv, struct ieee80211_supported_band *sband, | |||
181 | break; | 181 | break; |
182 | 182 | ||
183 | ndx = rix_to_ndx(mi, ar[i].idx); | 183 | ndx = rix_to_ndx(mi, ar[i].idx); |
184 | if (ndx < 0) | ||
185 | continue; | ||
186 | |||
184 | mi->r[ndx].attempts += ar[i].count; | 187 | mi->r[ndx].attempts += ar[i].count; |
185 | 188 | ||
186 | if ((i != IEEE80211_TX_MAX_RATES - 1) && (ar[i + 1].idx < 0)) | 189 | if ((i != IEEE80211_TX_MAX_RATES - 1) && (ar[i + 1].idx < 0)) |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index de5bba7f910a..0936fc24942d 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -2453,6 +2453,18 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
2453 | return; | 2453 | return; |
2454 | } | 2454 | } |
2455 | 2455 | ||
2456 | /* | ||
2457 | * If we're suspending, it is possible although not too likely | ||
2458 | * that we'd be receiving frames after having already partially | ||
2459 | * quiesced the stack. We can't process such frames then since | ||
2460 | * that might, for example, cause stations to be added or other | ||
2461 | * driver callbacks be invoked. | ||
2462 | */ | ||
2463 | if (unlikely(local->quiescing || local->suspended)) { | ||
2464 | kfree_skb(skb); | ||
2465 | return; | ||
2466 | } | ||
2467 | |||
2456 | if (status->flag & RX_FLAG_HT) { | 2468 | if (status->flag & RX_FLAG_HT) { |
2457 | /* rate_idx is MCS index */ | 2469 | /* rate_idx is MCS index */ |
2458 | if (WARN_ON(status->rate_idx < 0 || | 2470 | if (WARN_ON(status->rate_idx < 0 || |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index d238a8939a09..3a8922cd1038 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -1455,7 +1455,7 @@ int ieee80211_master_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
1455 | monitor_iface = UNKNOWN_ADDRESS; | 1455 | monitor_iface = UNKNOWN_ADDRESS; |
1456 | 1456 | ||
1457 | len_rthdr = ieee80211_get_radiotap_len(skb->data); | 1457 | len_rthdr = ieee80211_get_radiotap_len(skb->data); |
1458 | hdr = (struct ieee80211_hdr *)skb->data + len_rthdr; | 1458 | hdr = (struct ieee80211_hdr *)(skb->data + len_rthdr); |
1459 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | 1459 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
1460 | 1460 | ||
1461 | /* check the header is complete in the frame */ | 1461 | /* check the header is complete in the frame */ |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 66ce96a69f31..915e77769312 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -774,31 +774,6 @@ void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, | |||
774 | dev_queue_xmit(skb); | 774 | dev_queue_xmit(skb); |
775 | } | 775 | } |
776 | 776 | ||
777 | int ieee80211_set_freq(struct ieee80211_sub_if_data *sdata, int freqMHz) | ||
778 | { | ||
779 | int ret = -EINVAL; | ||
780 | struct ieee80211_channel *chan; | ||
781 | struct ieee80211_local *local = sdata->local; | ||
782 | |||
783 | chan = ieee80211_get_channel(local->hw.wiphy, freqMHz); | ||
784 | |||
785 | if (chan && !(chan->flags & IEEE80211_CHAN_DISABLED)) { | ||
786 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC && | ||
787 | chan->flags & IEEE80211_CHAN_NO_IBSS) | ||
788 | return ret; | ||
789 | local->oper_channel = chan; | ||
790 | local->oper_channel_type = NL80211_CHAN_NO_HT; | ||
791 | |||
792 | if (local->sw_scanning || local->hw_scanning) | ||
793 | ret = 0; | ||
794 | else | ||
795 | ret = ieee80211_hw_config( | ||
796 | local, IEEE80211_CONF_CHANGE_CHANNEL); | ||
797 | } | ||
798 | |||
799 | return ret; | ||
800 | } | ||
801 | |||
802 | u32 ieee80211_mandatory_rates(struct ieee80211_local *local, | 777 | u32 ieee80211_mandatory_rates(struct ieee80211_local *local, |
803 | enum ieee80211_band band) | 778 | enum ieee80211_band band) |
804 | { | 779 | { |
diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c index d2d81b103341..1da81f456744 100644 --- a/net/mac80211/wext.c +++ b/net/mac80211/wext.c | |||
@@ -55,6 +55,8 @@ static int ieee80211_ioctl_siwfreq(struct net_device *dev, | |||
55 | struct iw_freq *freq, char *extra) | 55 | struct iw_freq *freq, char *extra) |
56 | { | 56 | { |
57 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 57 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
58 | struct ieee80211_local *local = sdata->local; | ||
59 | struct ieee80211_channel *chan; | ||
58 | 60 | ||
59 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) | 61 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) |
60 | return cfg80211_ibss_wext_siwfreq(dev, info, freq, extra); | 62 | return cfg80211_ibss_wext_siwfreq(dev, info, freq, extra); |
@@ -69,17 +71,38 @@ static int ieee80211_ioctl_siwfreq(struct net_device *dev, | |||
69 | IEEE80211_STA_AUTO_CHANNEL_SEL; | 71 | IEEE80211_STA_AUTO_CHANNEL_SEL; |
70 | return 0; | 72 | return 0; |
71 | } else | 73 | } else |
72 | return ieee80211_set_freq(sdata, | 74 | chan = ieee80211_get_channel(local->hw.wiphy, |
73 | ieee80211_channel_to_frequency(freq->m)); | 75 | ieee80211_channel_to_frequency(freq->m)); |
74 | } else { | 76 | } else { |
75 | int i, div = 1000000; | 77 | int i, div = 1000000; |
76 | for (i = 0; i < freq->e; i++) | 78 | for (i = 0; i < freq->e; i++) |
77 | div /= 10; | 79 | div /= 10; |
78 | if (div > 0) | 80 | if (div <= 0) |
79 | return ieee80211_set_freq(sdata, freq->m / div); | ||
80 | else | ||
81 | return -EINVAL; | 81 | return -EINVAL; |
82 | chan = ieee80211_get_channel(local->hw.wiphy, freq->m / div); | ||
82 | } | 83 | } |
84 | |||
85 | if (!chan) | ||
86 | return -EINVAL; | ||
87 | |||
88 | if (chan->flags & IEEE80211_CHAN_DISABLED) | ||
89 | return -EINVAL; | ||
90 | |||
91 | /* | ||
92 | * no change except maybe auto -> fixed, ignore the HT | ||
93 | * setting so you can fix a channel you're on already | ||
94 | */ | ||
95 | if (local->oper_channel == chan) | ||
96 | return 0; | ||
97 | |||
98 | if (sdata->vif.type == NL80211_IFTYPE_STATION) | ||
99 | ieee80211_sta_req_auth(sdata); | ||
100 | |||
101 | local->oper_channel = chan; | ||
102 | local->oper_channel_type = NL80211_CHAN_NO_HT; | ||
103 | ieee80211_hw_config(local, 0); | ||
104 | |||
105 | return 0; | ||
83 | } | 106 | } |
84 | 107 | ||
85 | 108 | ||
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 5f72b94b4918..b5869b9574b0 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c | |||
@@ -335,7 +335,8 @@ begin: | |||
335 | h = __nf_conntrack_find(net, tuple); | 335 | h = __nf_conntrack_find(net, tuple); |
336 | if (h) { | 336 | if (h) { |
337 | ct = nf_ct_tuplehash_to_ctrack(h); | 337 | ct = nf_ct_tuplehash_to_ctrack(h); |
338 | if (unlikely(!atomic_inc_not_zero(&ct->ct_general.use))) | 338 | if (unlikely(nf_ct_is_dying(ct) || |
339 | !atomic_inc_not_zero(&ct->ct_general.use))) | ||
339 | h = NULL; | 340 | h = NULL; |
340 | else { | 341 | else { |
341 | if (unlikely(!nf_ct_tuple_equal(tuple, &h->tuple))) { | 342 | if (unlikely(!nf_ct_tuple_equal(tuple, &h->tuple))) { |
@@ -425,7 +426,6 @@ __nf_conntrack_confirm(struct sk_buff *skb) | |||
425 | /* Remove from unconfirmed list */ | 426 | /* Remove from unconfirmed list */ |
426 | hlist_nulls_del_rcu(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode); | 427 | hlist_nulls_del_rcu(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode); |
427 | 428 | ||
428 | __nf_conntrack_hash_insert(ct, hash, repl_hash); | ||
429 | /* Timer relative to confirmation time, not original | 429 | /* Timer relative to confirmation time, not original |
430 | setting time, otherwise we'd get timer wrap in | 430 | setting time, otherwise we'd get timer wrap in |
431 | weird delay cases. */ | 431 | weird delay cases. */ |
@@ -433,8 +433,16 @@ __nf_conntrack_confirm(struct sk_buff *skb) | |||
433 | add_timer(&ct->timeout); | 433 | add_timer(&ct->timeout); |
434 | atomic_inc(&ct->ct_general.use); | 434 | atomic_inc(&ct->ct_general.use); |
435 | set_bit(IPS_CONFIRMED_BIT, &ct->status); | 435 | set_bit(IPS_CONFIRMED_BIT, &ct->status); |
436 | |||
437 | /* Since the lookup is lockless, hash insertion must be done after | ||
438 | * starting the timer and setting the CONFIRMED bit. The RCU barriers | ||
439 | * guarantee that no other CPU can find the conntrack before the above | ||
440 | * stores are visible. | ||
441 | */ | ||
442 | __nf_conntrack_hash_insert(ct, hash, repl_hash); | ||
436 | NF_CT_STAT_INC(net, insert); | 443 | NF_CT_STAT_INC(net, insert); |
437 | spin_unlock_bh(&nf_conntrack_lock); | 444 | spin_unlock_bh(&nf_conntrack_lock); |
445 | |||
438 | help = nfct_help(ct); | 446 | help = nfct_help(ct); |
439 | if (help && help->helper) | 447 | if (help && help->helper) |
440 | nf_conntrack_event_cache(IPCT_HELPER, ct); | 448 | nf_conntrack_event_cache(IPCT_HELPER, ct); |
@@ -503,7 +511,8 @@ static noinline int early_drop(struct net *net, unsigned int hash) | |||
503 | cnt++; | 511 | cnt++; |
504 | } | 512 | } |
505 | 513 | ||
506 | if (ct && unlikely(!atomic_inc_not_zero(&ct->ct_general.use))) | 514 | if (ct && unlikely(nf_ct_is_dying(ct) || |
515 | !atomic_inc_not_zero(&ct->ct_general.use))) | ||
507 | ct = NULL; | 516 | ct = NULL; |
508 | if (ct || cnt >= NF_CT_EVICTION_RANGE) | 517 | if (ct || cnt >= NF_CT_EVICTION_RANGE) |
509 | break; | 518 | break; |
@@ -552,23 +561,38 @@ struct nf_conn *nf_conntrack_alloc(struct net *net, | |||
552 | } | 561 | } |
553 | } | 562 | } |
554 | 563 | ||
555 | ct = kmem_cache_zalloc(nf_conntrack_cachep, gfp); | 564 | /* |
565 | * Do not use kmem_cache_zalloc(), as this cache uses | ||
566 | * SLAB_DESTROY_BY_RCU. | ||
567 | */ | ||
568 | ct = kmem_cache_alloc(nf_conntrack_cachep, gfp); | ||
556 | if (ct == NULL) { | 569 | if (ct == NULL) { |
557 | pr_debug("nf_conntrack_alloc: Can't alloc conntrack.\n"); | 570 | pr_debug("nf_conntrack_alloc: Can't alloc conntrack.\n"); |
558 | atomic_dec(&net->ct.count); | 571 | atomic_dec(&net->ct.count); |
559 | return ERR_PTR(-ENOMEM); | 572 | return ERR_PTR(-ENOMEM); |
560 | } | 573 | } |
561 | 574 | /* | |
575 | * Let ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode.next | ||
576 | * and ct->tuplehash[IP_CT_DIR_REPLY].hnnode.next unchanged. | ||
577 | */ | ||
578 | memset(&ct->tuplehash[IP_CT_DIR_MAX], 0, | ||
579 | sizeof(*ct) - offsetof(struct nf_conn, tuplehash[IP_CT_DIR_MAX])); | ||
562 | spin_lock_init(&ct->lock); | 580 | spin_lock_init(&ct->lock); |
563 | atomic_set(&ct->ct_general.use, 1); | ||
564 | ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple = *orig; | 581 | ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple = *orig; |
582 | ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode.pprev = NULL; | ||
565 | ct->tuplehash[IP_CT_DIR_REPLY].tuple = *repl; | 583 | ct->tuplehash[IP_CT_DIR_REPLY].tuple = *repl; |
584 | ct->tuplehash[IP_CT_DIR_REPLY].hnnode.pprev = NULL; | ||
566 | /* Don't set timer yet: wait for confirmation */ | 585 | /* Don't set timer yet: wait for confirmation */ |
567 | setup_timer(&ct->timeout, death_by_timeout, (unsigned long)ct); | 586 | setup_timer(&ct->timeout, death_by_timeout, (unsigned long)ct); |
568 | #ifdef CONFIG_NET_NS | 587 | #ifdef CONFIG_NET_NS |
569 | ct->ct_net = net; | 588 | ct->ct_net = net; |
570 | #endif | 589 | #endif |
571 | 590 | ||
591 | /* | ||
592 | * changes to lookup keys must be done before setting refcnt to 1 | ||
593 | */ | ||
594 | smp_wmb(); | ||
595 | atomic_set(&ct->ct_general.use, 1); | ||
572 | return ct; | 596 | return ct; |
573 | } | 597 | } |
574 | EXPORT_SYMBOL_GPL(nf_conntrack_alloc); | 598 | EXPORT_SYMBOL_GPL(nf_conntrack_alloc); |
@@ -1267,13 +1291,19 @@ err_cache: | |||
1267 | return ret; | 1291 | return ret; |
1268 | } | 1292 | } |
1269 | 1293 | ||
1294 | /* | ||
1295 | * We need to use special "null" values, not used in hash table | ||
1296 | */ | ||
1297 | #define UNCONFIRMED_NULLS_VAL ((1<<30)+0) | ||
1298 | #define DYING_NULLS_VAL ((1<<30)+1) | ||
1299 | |||
1270 | static int nf_conntrack_init_net(struct net *net) | 1300 | static int nf_conntrack_init_net(struct net *net) |
1271 | { | 1301 | { |
1272 | int ret; | 1302 | int ret; |
1273 | 1303 | ||
1274 | atomic_set(&net->ct.count, 0); | 1304 | atomic_set(&net->ct.count, 0); |
1275 | INIT_HLIST_NULLS_HEAD(&net->ct.unconfirmed, 0); | 1305 | INIT_HLIST_NULLS_HEAD(&net->ct.unconfirmed, UNCONFIRMED_NULLS_VAL); |
1276 | INIT_HLIST_NULLS_HEAD(&net->ct.dying, 0); | 1306 | INIT_HLIST_NULLS_HEAD(&net->ct.dying, DYING_NULLS_VAL); |
1277 | net->ct.stat = alloc_percpu(struct ip_conntrack_stat); | 1307 | net->ct.stat = alloc_percpu(struct ip_conntrack_stat); |
1278 | if (!net->ct.stat) { | 1308 | if (!net->ct.stat) { |
1279 | ret = -ENOMEM; | 1309 | ret = -ENOMEM; |
diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c index afde8f991646..2032dfe25ca8 100644 --- a/net/netfilter/nf_conntrack_expect.c +++ b/net/netfilter/nf_conntrack_expect.c | |||
@@ -617,8 +617,10 @@ err1: | |||
617 | void nf_conntrack_expect_fini(struct net *net) | 617 | void nf_conntrack_expect_fini(struct net *net) |
618 | { | 618 | { |
619 | exp_proc_remove(net); | 619 | exp_proc_remove(net); |
620 | if (net_eq(net, &init_net)) | 620 | if (net_eq(net, &init_net)) { |
621 | rcu_barrier(); /* Wait for call_rcu() before destroy */ | ||
621 | kmem_cache_destroy(nf_ct_expect_cachep); | 622 | kmem_cache_destroy(nf_ct_expect_cachep); |
623 | } | ||
622 | nf_ct_free_hashtable(net->ct.expect_hash, net->ct.expect_vmalloc, | 624 | nf_ct_free_hashtable(net->ct.expect_hash, net->ct.expect_vmalloc, |
623 | nf_ct_expect_hsize); | 625 | nf_ct_expect_hsize); |
624 | } | 626 | } |
diff --git a/net/netfilter/nf_conntrack_extend.c b/net/netfilter/nf_conntrack_extend.c index 4b2c769d555f..fef95be334bd 100644 --- a/net/netfilter/nf_conntrack_extend.c +++ b/net/netfilter/nf_conntrack_extend.c | |||
@@ -186,6 +186,6 @@ void nf_ct_extend_unregister(struct nf_ct_ext_type *type) | |||
186 | rcu_assign_pointer(nf_ct_ext_types[type->id], NULL); | 186 | rcu_assign_pointer(nf_ct_ext_types[type->id], NULL); |
187 | update_alloc_size(type); | 187 | update_alloc_size(type); |
188 | mutex_unlock(&nf_ct_ext_type_mutex); | 188 | mutex_unlock(&nf_ct_ext_type_mutex); |
189 | synchronize_rcu(); | 189 | rcu_barrier(); /* Wait for completion of call_rcu()'s */ |
190 | } | 190 | } |
191 | EXPORT_SYMBOL_GPL(nf_ct_extend_unregister); | 191 | EXPORT_SYMBOL_GPL(nf_ct_extend_unregister); |
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c index 33fc0a443f3d..97a82ba75376 100644 --- a/net/netfilter/nf_conntrack_proto_tcp.c +++ b/net/netfilter/nf_conntrack_proto_tcp.c | |||
@@ -720,8 +720,8 @@ static bool tcp_in_window(const struct nf_conn *ct, | |||
720 | /* Caller must linearize skb at tcp header. */ | 720 | /* Caller must linearize skb at tcp header. */ |
721 | void nf_conntrack_tcp_update(const struct sk_buff *skb, | 721 | void nf_conntrack_tcp_update(const struct sk_buff *skb, |
722 | unsigned int dataoff, | 722 | unsigned int dataoff, |
723 | struct nf_conn *ct, | 723 | struct nf_conn *ct, int dir, |
724 | int dir) | 724 | s16 offset) |
725 | { | 725 | { |
726 | const struct tcphdr *tcph = (const void *)skb->data + dataoff; | 726 | const struct tcphdr *tcph = (const void *)skb->data + dataoff; |
727 | const struct ip_ct_tcp_state *sender = &ct->proto.tcp.seen[dir]; | 727 | const struct ip_ct_tcp_state *sender = &ct->proto.tcp.seen[dir]; |
@@ -734,7 +734,7 @@ void nf_conntrack_tcp_update(const struct sk_buff *skb, | |||
734 | /* | 734 | /* |
735 | * We have to worry for the ack in the reply packet only... | 735 | * We have to worry for the ack in the reply packet only... |
736 | */ | 736 | */ |
737 | if (after(end, ct->proto.tcp.seen[dir].td_end)) | 737 | if (ct->proto.tcp.seen[dir].td_end + offset == end) |
738 | ct->proto.tcp.seen[dir].td_end = end; | 738 | ct->proto.tcp.seen[dir].td_end = end; |
739 | ct->proto.tcp.last_end = end; | 739 | ct->proto.tcp.last_end = end; |
740 | spin_unlock_bh(&ct->lock); | 740 | spin_unlock_bh(&ct->lock); |
diff --git a/net/netfilter/nf_log.c b/net/netfilter/nf_log.c index 2fefe147750a..4e620305f28c 100644 --- a/net/netfilter/nf_log.c +++ b/net/netfilter/nf_log.c | |||
@@ -47,7 +47,6 @@ int nf_log_register(u_int8_t pf, struct nf_logger *logger) | |||
47 | mutex_lock(&nf_log_mutex); | 47 | mutex_lock(&nf_log_mutex); |
48 | 48 | ||
49 | if (pf == NFPROTO_UNSPEC) { | 49 | if (pf == NFPROTO_UNSPEC) { |
50 | int i; | ||
51 | for (i = NFPROTO_UNSPEC; i < NFPROTO_NUMPROTO; i++) | 50 | for (i = NFPROTO_UNSPEC; i < NFPROTO_NUMPROTO; i++) |
52 | list_add_tail(&(logger->list[i]), &(nf_loggers_l[i])); | 51 | list_add_tail(&(logger->list[i]), &(nf_loggers_l[i])); |
53 | } else { | 52 | } else { |
@@ -216,7 +215,7 @@ static const struct file_operations nflog_file_ops = { | |||
216 | #endif /* PROC_FS */ | 215 | #endif /* PROC_FS */ |
217 | 216 | ||
218 | #ifdef CONFIG_SYSCTL | 217 | #ifdef CONFIG_SYSCTL |
219 | struct ctl_path nf_log_sysctl_path[] = { | 218 | static struct ctl_path nf_log_sysctl_path[] = { |
220 | { .procname = "net", .ctl_name = CTL_NET, }, | 219 | { .procname = "net", .ctl_name = CTL_NET, }, |
221 | { .procname = "netfilter", .ctl_name = NET_NETFILTER, }, | 220 | { .procname = "netfilter", .ctl_name = NET_NETFILTER, }, |
222 | { .procname = "nf_log", .ctl_name = CTL_UNNUMBERED, }, | 221 | { .procname = "nf_log", .ctl_name = CTL_UNNUMBERED, }, |
@@ -228,19 +227,26 @@ static struct ctl_table nf_log_sysctl_table[NFPROTO_NUMPROTO+1]; | |||
228 | static struct ctl_table_header *nf_log_dir_header; | 227 | static struct ctl_table_header *nf_log_dir_header; |
229 | 228 | ||
230 | static int nf_log_proc_dostring(ctl_table *table, int write, struct file *filp, | 229 | static int nf_log_proc_dostring(ctl_table *table, int write, struct file *filp, |
231 | void *buffer, size_t *lenp, loff_t *ppos) | 230 | void __user *buffer, size_t *lenp, loff_t *ppos) |
232 | { | 231 | { |
233 | const struct nf_logger *logger; | 232 | const struct nf_logger *logger; |
233 | char buf[NFLOGGER_NAME_LEN]; | ||
234 | size_t size = *lenp; | ||
234 | int r = 0; | 235 | int r = 0; |
235 | int tindex = (unsigned long)table->extra1; | 236 | int tindex = (unsigned long)table->extra1; |
236 | 237 | ||
237 | if (write) { | 238 | if (write) { |
238 | if (!strcmp(buffer, "NONE")) { | 239 | if (size > sizeof(buf)) |
240 | size = sizeof(buf); | ||
241 | if (copy_from_user(buf, buffer, size)) | ||
242 | return -EFAULT; | ||
243 | |||
244 | if (!strcmp(buf, "NONE")) { | ||
239 | nf_log_unbind_pf(tindex); | 245 | nf_log_unbind_pf(tindex); |
240 | return 0; | 246 | return 0; |
241 | } | 247 | } |
242 | mutex_lock(&nf_log_mutex); | 248 | mutex_lock(&nf_log_mutex); |
243 | logger = __find_logger(tindex, buffer); | 249 | logger = __find_logger(tindex, buf); |
244 | if (logger == NULL) { | 250 | if (logger == NULL) { |
245 | mutex_unlock(&nf_log_mutex); | 251 | mutex_unlock(&nf_log_mutex); |
246 | return -ENOENT; | 252 | return -ENOENT; |
diff --git a/net/netfilter/xt_NFQUEUE.c b/net/netfilter/xt_NFQUEUE.c index 498b45101df7..f28f6a5fc02d 100644 --- a/net/netfilter/xt_NFQUEUE.c +++ b/net/netfilter/xt_NFQUEUE.c | |||
@@ -40,12 +40,12 @@ nfqueue_tg(struct sk_buff *skb, const struct xt_target_param *par) | |||
40 | static u32 hash_v4(const struct sk_buff *skb) | 40 | static u32 hash_v4(const struct sk_buff *skb) |
41 | { | 41 | { |
42 | const struct iphdr *iph = ip_hdr(skb); | 42 | const struct iphdr *iph = ip_hdr(skb); |
43 | u32 ipaddr; | 43 | __be32 ipaddr; |
44 | 44 | ||
45 | /* packets in either direction go into same queue */ | 45 | /* packets in either direction go into same queue */ |
46 | ipaddr = iph->saddr ^ iph->daddr; | 46 | ipaddr = iph->saddr ^ iph->daddr; |
47 | 47 | ||
48 | return jhash_2words(ipaddr, iph->protocol, jhash_initval); | 48 | return jhash_2words((__force u32)ipaddr, iph->protocol, jhash_initval); |
49 | } | 49 | } |
50 | 50 | ||
51 | static unsigned int | 51 | static unsigned int |
@@ -63,14 +63,14 @@ nfqueue_tg4_v1(struct sk_buff *skb, const struct xt_target_param *par) | |||
63 | static u32 hash_v6(const struct sk_buff *skb) | 63 | static u32 hash_v6(const struct sk_buff *skb) |
64 | { | 64 | { |
65 | const struct ipv6hdr *ip6h = ipv6_hdr(skb); | 65 | const struct ipv6hdr *ip6h = ipv6_hdr(skb); |
66 | u32 addr[4]; | 66 | __be32 addr[4]; |
67 | 67 | ||
68 | addr[0] = ip6h->saddr.s6_addr32[0] ^ ip6h->daddr.s6_addr32[0]; | 68 | addr[0] = ip6h->saddr.s6_addr32[0] ^ ip6h->daddr.s6_addr32[0]; |
69 | addr[1] = ip6h->saddr.s6_addr32[1] ^ ip6h->daddr.s6_addr32[1]; | 69 | addr[1] = ip6h->saddr.s6_addr32[1] ^ ip6h->daddr.s6_addr32[1]; |
70 | addr[2] = ip6h->saddr.s6_addr32[2] ^ ip6h->daddr.s6_addr32[2]; | 70 | addr[2] = ip6h->saddr.s6_addr32[2] ^ ip6h->daddr.s6_addr32[2]; |
71 | addr[3] = ip6h->saddr.s6_addr32[3] ^ ip6h->daddr.s6_addr32[3]; | 71 | addr[3] = ip6h->saddr.s6_addr32[3] ^ ip6h->daddr.s6_addr32[3]; |
72 | 72 | ||
73 | return jhash2(addr, ARRAY_SIZE(addr), jhash_initval); | 73 | return jhash2((__force u32 *)addr, ARRAY_SIZE(addr), jhash_initval); |
74 | } | 74 | } |
75 | 75 | ||
76 | static unsigned int | 76 | static unsigned int |
diff --git a/net/netfilter/xt_RATEEST.c b/net/netfilter/xt_RATEEST.c index 43f5676b1af4..d80b8192e0d4 100644 --- a/net/netfilter/xt_RATEEST.c +++ b/net/netfilter/xt_RATEEST.c | |||
@@ -74,7 +74,7 @@ static unsigned int | |||
74 | xt_rateest_tg(struct sk_buff *skb, const struct xt_target_param *par) | 74 | xt_rateest_tg(struct sk_buff *skb, const struct xt_target_param *par) |
75 | { | 75 | { |
76 | const struct xt_rateest_target_info *info = par->targinfo; | 76 | const struct xt_rateest_target_info *info = par->targinfo; |
77 | struct gnet_stats_basic *stats = &info->est->bstats; | 77 | struct gnet_stats_basic_packed *stats = &info->est->bstats; |
78 | 78 | ||
79 | spin_lock_bh(&info->est->lock); | 79 | spin_lock_bh(&info->est->lock); |
80 | stats->bytes += skb->len; | 80 | stats->bytes += skb->len; |
diff --git a/net/netfilter/xt_cluster.c b/net/netfilter/xt_cluster.c index 69a639f35403..225ee3ecd69d 100644 --- a/net/netfilter/xt_cluster.c +++ b/net/netfilter/xt_cluster.c | |||
@@ -15,14 +15,14 @@ | |||
15 | #include <net/netfilter/nf_conntrack.h> | 15 | #include <net/netfilter/nf_conntrack.h> |
16 | #include <linux/netfilter/xt_cluster.h> | 16 | #include <linux/netfilter/xt_cluster.h> |
17 | 17 | ||
18 | static inline u_int32_t nf_ct_orig_ipv4_src(const struct nf_conn *ct) | 18 | static inline u32 nf_ct_orig_ipv4_src(const struct nf_conn *ct) |
19 | { | 19 | { |
20 | return ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip; | 20 | return (__force u32)ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip; |
21 | } | 21 | } |
22 | 22 | ||
23 | static inline const void *nf_ct_orig_ipv6_src(const struct nf_conn *ct) | 23 | static inline const u32 *nf_ct_orig_ipv6_src(const struct nf_conn *ct) |
24 | { | 24 | { |
25 | return ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip6; | 25 | return (__force u32 *)ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip6; |
26 | } | 26 | } |
27 | 27 | ||
28 | static inline u_int32_t | 28 | static inline u_int32_t |
diff --git a/net/netfilter/xt_conntrack.c b/net/netfilter/xt_conntrack.c index 0b7139f3dd78..fc581800698e 100644 --- a/net/netfilter/xt_conntrack.c +++ b/net/netfilter/xt_conntrack.c | |||
@@ -129,7 +129,7 @@ conntrack_addrcmp(const union nf_inet_addr *kaddr, | |||
129 | 129 | ||
130 | static inline bool | 130 | static inline bool |
131 | conntrack_mt_origsrc(const struct nf_conn *ct, | 131 | conntrack_mt_origsrc(const struct nf_conn *ct, |
132 | const struct xt_conntrack_mtinfo1 *info, | 132 | const struct xt_conntrack_mtinfo2 *info, |
133 | u_int8_t family) | 133 | u_int8_t family) |
134 | { | 134 | { |
135 | return conntrack_addrcmp(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3, | 135 | return conntrack_addrcmp(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3, |
@@ -138,7 +138,7 @@ conntrack_mt_origsrc(const struct nf_conn *ct, | |||
138 | 138 | ||
139 | static inline bool | 139 | static inline bool |
140 | conntrack_mt_origdst(const struct nf_conn *ct, | 140 | conntrack_mt_origdst(const struct nf_conn *ct, |
141 | const struct xt_conntrack_mtinfo1 *info, | 141 | const struct xt_conntrack_mtinfo2 *info, |
142 | u_int8_t family) | 142 | u_int8_t family) |
143 | { | 143 | { |
144 | return conntrack_addrcmp(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3, | 144 | return conntrack_addrcmp(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3, |
@@ -147,7 +147,7 @@ conntrack_mt_origdst(const struct nf_conn *ct, | |||
147 | 147 | ||
148 | static inline bool | 148 | static inline bool |
149 | conntrack_mt_replsrc(const struct nf_conn *ct, | 149 | conntrack_mt_replsrc(const struct nf_conn *ct, |
150 | const struct xt_conntrack_mtinfo1 *info, | 150 | const struct xt_conntrack_mtinfo2 *info, |
151 | u_int8_t family) | 151 | u_int8_t family) |
152 | { | 152 | { |
153 | return conntrack_addrcmp(&ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3, | 153 | return conntrack_addrcmp(&ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3, |
@@ -156,7 +156,7 @@ conntrack_mt_replsrc(const struct nf_conn *ct, | |||
156 | 156 | ||
157 | static inline bool | 157 | static inline bool |
158 | conntrack_mt_repldst(const struct nf_conn *ct, | 158 | conntrack_mt_repldst(const struct nf_conn *ct, |
159 | const struct xt_conntrack_mtinfo1 *info, | 159 | const struct xt_conntrack_mtinfo2 *info, |
160 | u_int8_t family) | 160 | u_int8_t family) |
161 | { | 161 | { |
162 | return conntrack_addrcmp(&ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3, | 162 | return conntrack_addrcmp(&ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3, |
@@ -164,7 +164,7 @@ conntrack_mt_repldst(const struct nf_conn *ct, | |||
164 | } | 164 | } |
165 | 165 | ||
166 | static inline bool | 166 | static inline bool |
167 | ct_proto_port_check(const struct xt_conntrack_mtinfo1 *info, | 167 | ct_proto_port_check(const struct xt_conntrack_mtinfo2 *info, |
168 | const struct nf_conn *ct) | 168 | const struct nf_conn *ct) |
169 | { | 169 | { |
170 | const struct nf_conntrack_tuple *tuple; | 170 | const struct nf_conntrack_tuple *tuple; |
@@ -204,7 +204,7 @@ ct_proto_port_check(const struct xt_conntrack_mtinfo1 *info, | |||
204 | static bool | 204 | static bool |
205 | conntrack_mt(const struct sk_buff *skb, const struct xt_match_param *par) | 205 | conntrack_mt(const struct sk_buff *skb, const struct xt_match_param *par) |
206 | { | 206 | { |
207 | const struct xt_conntrack_mtinfo1 *info = par->matchinfo; | 207 | const struct xt_conntrack_mtinfo2 *info = par->matchinfo; |
208 | enum ip_conntrack_info ctinfo; | 208 | enum ip_conntrack_info ctinfo; |
209 | const struct nf_conn *ct; | 209 | const struct nf_conn *ct; |
210 | unsigned int statebit; | 210 | unsigned int statebit; |
@@ -278,6 +278,16 @@ conntrack_mt(const struct sk_buff *skb, const struct xt_match_param *par) | |||
278 | return true; | 278 | return true; |
279 | } | 279 | } |
280 | 280 | ||
281 | static bool | ||
282 | conntrack_mt_v1(const struct sk_buff *skb, const struct xt_match_param *par) | ||
283 | { | ||
284 | const struct xt_conntrack_mtinfo2 *const *info = par->matchinfo; | ||
285 | struct xt_match_param newpar = *par; | ||
286 | |||
287 | newpar.matchinfo = *info; | ||
288 | return conntrack_mt(skb, &newpar); | ||
289 | } | ||
290 | |||
281 | static bool conntrack_mt_check(const struct xt_mtchk_param *par) | 291 | static bool conntrack_mt_check(const struct xt_mtchk_param *par) |
282 | { | 292 | { |
283 | if (nf_ct_l3proto_try_module_get(par->family) < 0) { | 293 | if (nf_ct_l3proto_try_module_get(par->family) < 0) { |
@@ -288,11 +298,45 @@ static bool conntrack_mt_check(const struct xt_mtchk_param *par) | |||
288 | return true; | 298 | return true; |
289 | } | 299 | } |
290 | 300 | ||
301 | static bool conntrack_mt_check_v1(const struct xt_mtchk_param *par) | ||
302 | { | ||
303 | struct xt_conntrack_mtinfo1 *info = par->matchinfo; | ||
304 | struct xt_conntrack_mtinfo2 *up; | ||
305 | int ret = conntrack_mt_check(par); | ||
306 | |||
307 | if (ret < 0) | ||
308 | return ret; | ||
309 | |||
310 | up = kmalloc(sizeof(*up), GFP_KERNEL); | ||
311 | if (up == NULL) { | ||
312 | nf_ct_l3proto_module_put(par->family); | ||
313 | return -ENOMEM; | ||
314 | } | ||
315 | |||
316 | /* | ||
317 | * The strategy here is to minimize the overhead of v1 matching, | ||
318 | * by prebuilding a v2 struct and putting the pointer into the | ||
319 | * v1 dataspace. | ||
320 | */ | ||
321 | memcpy(up, info, offsetof(typeof(*info), state_mask)); | ||
322 | up->state_mask = info->state_mask; | ||
323 | up->status_mask = info->status_mask; | ||
324 | *(void **)info = up; | ||
325 | return true; | ||
326 | } | ||
327 | |||
291 | static void conntrack_mt_destroy(const struct xt_mtdtor_param *par) | 328 | static void conntrack_mt_destroy(const struct xt_mtdtor_param *par) |
292 | { | 329 | { |
293 | nf_ct_l3proto_module_put(par->family); | 330 | nf_ct_l3proto_module_put(par->family); |
294 | } | 331 | } |
295 | 332 | ||
333 | static void conntrack_mt_destroy_v1(const struct xt_mtdtor_param *par) | ||
334 | { | ||
335 | struct xt_conntrack_mtinfo2 **info = par->matchinfo; | ||
336 | kfree(*info); | ||
337 | conntrack_mt_destroy(par); | ||
338 | } | ||
339 | |||
296 | #ifdef CONFIG_COMPAT | 340 | #ifdef CONFIG_COMPAT |
297 | struct compat_xt_conntrack_info | 341 | struct compat_xt_conntrack_info |
298 | { | 342 | { |
@@ -363,6 +407,16 @@ static struct xt_match conntrack_mt_reg[] __read_mostly = { | |||
363 | .revision = 1, | 407 | .revision = 1, |
364 | .family = NFPROTO_UNSPEC, | 408 | .family = NFPROTO_UNSPEC, |
365 | .matchsize = sizeof(struct xt_conntrack_mtinfo1), | 409 | .matchsize = sizeof(struct xt_conntrack_mtinfo1), |
410 | .match = conntrack_mt_v1, | ||
411 | .checkentry = conntrack_mt_check_v1, | ||
412 | .destroy = conntrack_mt_destroy_v1, | ||
413 | .me = THIS_MODULE, | ||
414 | }, | ||
415 | { | ||
416 | .name = "conntrack", | ||
417 | .revision = 2, | ||
418 | .family = NFPROTO_UNSPEC, | ||
419 | .matchsize = sizeof(struct xt_conntrack_mtinfo2), | ||
366 | .match = conntrack_mt, | 420 | .match = conntrack_mt, |
367 | .checkentry = conntrack_mt_check, | 421 | .checkentry = conntrack_mt_check, |
368 | .destroy = conntrack_mt_destroy, | 422 | .destroy = conntrack_mt_destroy, |
diff --git a/net/netfilter/xt_osf.c b/net/netfilter/xt_osf.c index 863e40977a4d..0f482e2440b4 100644 --- a/net/netfilter/xt_osf.c +++ b/net/netfilter/xt_osf.c | |||
@@ -330,7 +330,8 @@ static bool xt_osf_match_packet(const struct sk_buff *skb, | |||
330 | fcount++; | 330 | fcount++; |
331 | 331 | ||
332 | if (info->flags & XT_OSF_LOG) | 332 | if (info->flags & XT_OSF_LOG) |
333 | nf_log_packet(p->hooknum, 0, skb, p->in, p->out, NULL, | 333 | nf_log_packet(p->family, p->hooknum, skb, |
334 | p->in, p->out, NULL, | ||
334 | "%s [%s:%s] : %pi4:%d -> %pi4:%d hops=%d\n", | 335 | "%s [%s:%s] : %pi4:%d -> %pi4:%d hops=%d\n", |
335 | f->genre, f->version, f->subtype, | 336 | f->genre, f->version, f->subtype, |
336 | &ip->saddr, ntohs(tcp->source), | 337 | &ip->saddr, ntohs(tcp->source), |
@@ -345,7 +346,7 @@ static bool xt_osf_match_packet(const struct sk_buff *skb, | |||
345 | rcu_read_unlock(); | 346 | rcu_read_unlock(); |
346 | 347 | ||
347 | if (!fcount && (info->flags & XT_OSF_LOG)) | 348 | if (!fcount && (info->flags & XT_OSF_LOG)) |
348 | nf_log_packet(p->hooknum, 0, skb, p->in, p->out, NULL, | 349 | nf_log_packet(p->family, p->hooknum, skb, p->in, p->out, NULL, |
349 | "Remote OS is not known: %pi4:%u -> %pi4:%u\n", | 350 | "Remote OS is not known: %pi4:%u -> %pi4:%u\n", |
350 | &ip->saddr, ntohs(tcp->source), | 351 | &ip->saddr, ntohs(tcp->source), |
351 | &ip->daddr, ntohs(tcp->dest)); | 352 | &ip->daddr, ntohs(tcp->dest)); |
diff --git a/net/netfilter/xt_quota.c b/net/netfilter/xt_quota.c index 01dd07b764ec..390b7d09fe51 100644 --- a/net/netfilter/xt_quota.c +++ b/net/netfilter/xt_quota.c | |||
@@ -52,8 +52,9 @@ static bool quota_mt_check(const struct xt_mtchk_param *par) | |||
52 | 52 | ||
53 | q->master = kmalloc(sizeof(*q->master), GFP_KERNEL); | 53 | q->master = kmalloc(sizeof(*q->master), GFP_KERNEL); |
54 | if (q->master == NULL) | 54 | if (q->master == NULL) |
55 | return -ENOMEM; | 55 | return false; |
56 | 56 | ||
57 | q->master->quota = q->quota; | ||
57 | return true; | 58 | return true; |
58 | } | 59 | } |
59 | 60 | ||
diff --git a/net/netfilter/xt_rateest.c b/net/netfilter/xt_rateest.c index 220a1d588ee0..4fc6a917f6de 100644 --- a/net/netfilter/xt_rateest.c +++ b/net/netfilter/xt_rateest.c | |||
@@ -66,7 +66,7 @@ xt_rateest_mt(const struct sk_buff *skb, const struct xt_match_param *par) | |||
66 | if (info->flags & XT_RATEEST_MATCH_BPS) | 66 | if (info->flags & XT_RATEEST_MATCH_BPS) |
67 | ret &= bps1 == bps2; | 67 | ret &= bps1 == bps2; |
68 | if (info->flags & XT_RATEEST_MATCH_PPS) | 68 | if (info->flags & XT_RATEEST_MATCH_PPS) |
69 | ret &= pps2 == pps2; | 69 | ret &= pps1 == pps2; |
70 | break; | 70 | break; |
71 | } | 71 | } |
72 | 72 | ||
diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c index b0e582f2d37a..16e6c4378ff1 100644 --- a/net/netlabel/netlabel_kapi.c +++ b/net/netlabel/netlabel_kapi.c | |||
@@ -151,7 +151,7 @@ int netlbl_cfg_unlbl_map_add(const char *domain, | |||
151 | addr6 = addr; | 151 | addr6 = addr; |
152 | mask6 = mask; | 152 | mask6 = mask; |
153 | map6 = kzalloc(sizeof(*map6), GFP_ATOMIC); | 153 | map6 = kzalloc(sizeof(*map6), GFP_ATOMIC); |
154 | if (map4 == NULL) | 154 | if (map6 == NULL) |
155 | goto cfg_unlbl_map_add_failure; | 155 | goto cfg_unlbl_map_add_failure; |
156 | map6->type = NETLBL_NLTYPE_UNLABELED; | 156 | map6->type = NETLBL_NLTYPE_UNLABELED; |
157 | ipv6_addr_copy(&map6->list.addr, addr6); | 157 | ipv6_addr_copy(&map6->list.addr, addr6); |
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 8b6bbb3032b0..2936fa3b6dc8 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c | |||
@@ -1914,8 +1914,8 @@ static int netlink_seq_show(struct seq_file *seq, void *v) | |||
1914 | s->sk_protocol, | 1914 | s->sk_protocol, |
1915 | nlk->pid, | 1915 | nlk->pid, |
1916 | nlk->groups ? (u32)nlk->groups[0] : 0, | 1916 | nlk->groups ? (u32)nlk->groups[0] : 0, |
1917 | atomic_read(&s->sk_rmem_alloc), | 1917 | sk_rmem_alloc_get(s), |
1918 | atomic_read(&s->sk_wmem_alloc), | 1918 | sk_wmem_alloc_get(s), |
1919 | nlk->cb, | 1919 | nlk->cb, |
1920 | atomic_read(&s->sk_refcnt), | 1920 | atomic_read(&s->sk_refcnt), |
1921 | atomic_read(&s->sk_drops) | 1921 | atomic_read(&s->sk_drops) |
diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c index 3be0e016ab7d..ce1a34b99c23 100644 --- a/net/netrom/af_netrom.c +++ b/net/netrom/af_netrom.c | |||
@@ -286,8 +286,7 @@ void nr_destroy_socket(struct sock *sk) | |||
286 | kfree_skb(skb); | 286 | kfree_skb(skb); |
287 | } | 287 | } |
288 | 288 | ||
289 | if (atomic_read(&sk->sk_wmem_alloc) || | 289 | if (sk_has_allocations(sk)) { |
290 | atomic_read(&sk->sk_rmem_alloc)) { | ||
291 | /* Defer: outstanding buffers */ | 290 | /* Defer: outstanding buffers */ |
292 | sk->sk_timer.function = nr_destroy_timer; | 291 | sk->sk_timer.function = nr_destroy_timer; |
293 | sk->sk_timer.expires = jiffies + 2 * HZ; | 292 | sk->sk_timer.expires = jiffies + 2 * HZ; |
@@ -848,6 +847,7 @@ static int nr_getname(struct socket *sock, struct sockaddr *uaddr, | |||
848 | sax->fsa_ax25.sax25_family = AF_NETROM; | 847 | sax->fsa_ax25.sax25_family = AF_NETROM; |
849 | sax->fsa_ax25.sax25_ndigis = 1; | 848 | sax->fsa_ax25.sax25_ndigis = 1; |
850 | sax->fsa_ax25.sax25_call = nr->user_addr; | 849 | sax->fsa_ax25.sax25_call = nr->user_addr; |
850 | memset(sax->fsa_digipeater, 0, sizeof(sax->fsa_digipeater)); | ||
851 | sax->fsa_digipeater[0] = nr->dest_addr; | 851 | sax->fsa_digipeater[0] = nr->dest_addr; |
852 | *uaddr_len = sizeof(struct full_sockaddr_ax25); | 852 | *uaddr_len = sizeof(struct full_sockaddr_ax25); |
853 | } else { | 853 | } else { |
@@ -1206,7 +1206,7 @@ static int nr_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
1206 | long amount; | 1206 | long amount; |
1207 | 1207 | ||
1208 | lock_sock(sk); | 1208 | lock_sock(sk); |
1209 | amount = sk->sk_sndbuf - atomic_read(&sk->sk_wmem_alloc); | 1209 | amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk); |
1210 | if (amount < 0) | 1210 | if (amount < 0) |
1211 | amount = 0; | 1211 | amount = 0; |
1212 | release_sock(sk); | 1212 | release_sock(sk); |
@@ -1342,8 +1342,8 @@ static int nr_info_show(struct seq_file *seq, void *v) | |||
1342 | nr->n2count, | 1342 | nr->n2count, |
1343 | nr->n2, | 1343 | nr->n2, |
1344 | nr->window, | 1344 | nr->window, |
1345 | atomic_read(&s->sk_wmem_alloc), | 1345 | sk_wmem_alloc_get(s), |
1346 | atomic_read(&s->sk_rmem_alloc), | 1346 | sk_rmem_alloc_get(s), |
1347 | s->sk_socket ? SOCK_INODE(s->sk_socket)->i_ino : 0L); | 1347 | s->sk_socket ? SOCK_INODE(s->sk_socket)->i_ino : 0L); |
1348 | 1348 | ||
1349 | bh_unlock_sock(s); | 1349 | bh_unlock_sock(s); |
diff --git a/net/netrom/nr_route.c b/net/netrom/nr_route.c index e943c16552a2..4eb1ac9a7679 100644 --- a/net/netrom/nr_route.c +++ b/net/netrom/nr_route.c | |||
@@ -630,23 +630,23 @@ out: | |||
630 | return dev; | 630 | return dev; |
631 | } | 631 | } |
632 | 632 | ||
633 | static ax25_digi *nr_call_to_digi(int ndigis, ax25_address *digipeaters) | 633 | static ax25_digi *nr_call_to_digi(ax25_digi *digi, int ndigis, |
634 | ax25_address *digipeaters) | ||
634 | { | 635 | { |
635 | static ax25_digi ax25_digi; | ||
636 | int i; | 636 | int i; |
637 | 637 | ||
638 | if (ndigis == 0) | 638 | if (ndigis == 0) |
639 | return NULL; | 639 | return NULL; |
640 | 640 | ||
641 | for (i = 0; i < ndigis; i++) { | 641 | for (i = 0; i < ndigis; i++) { |
642 | ax25_digi.calls[i] = digipeaters[i]; | 642 | digi->calls[i] = digipeaters[i]; |
643 | ax25_digi.repeated[i] = 0; | 643 | digi->repeated[i] = 0; |
644 | } | 644 | } |
645 | 645 | ||
646 | ax25_digi.ndigi = ndigis; | 646 | digi->ndigi = ndigis; |
647 | ax25_digi.lastrepeat = -1; | 647 | digi->lastrepeat = -1; |
648 | 648 | ||
649 | return &ax25_digi; | 649 | return digi; |
650 | } | 650 | } |
651 | 651 | ||
652 | /* | 652 | /* |
@@ -656,6 +656,7 @@ int nr_rt_ioctl(unsigned int cmd, void __user *arg) | |||
656 | { | 656 | { |
657 | struct nr_route_struct nr_route; | 657 | struct nr_route_struct nr_route; |
658 | struct net_device *dev; | 658 | struct net_device *dev; |
659 | ax25_digi digi; | ||
659 | int ret; | 660 | int ret; |
660 | 661 | ||
661 | switch (cmd) { | 662 | switch (cmd) { |
@@ -673,13 +674,15 @@ int nr_rt_ioctl(unsigned int cmd, void __user *arg) | |||
673 | ret = nr_add_node(&nr_route.callsign, | 674 | ret = nr_add_node(&nr_route.callsign, |
674 | nr_route.mnemonic, | 675 | nr_route.mnemonic, |
675 | &nr_route.neighbour, | 676 | &nr_route.neighbour, |
676 | nr_call_to_digi(nr_route.ndigis, nr_route.digipeaters), | 677 | nr_call_to_digi(&digi, nr_route.ndigis, |
678 | nr_route.digipeaters), | ||
677 | dev, nr_route.quality, | 679 | dev, nr_route.quality, |
678 | nr_route.obs_count); | 680 | nr_route.obs_count); |
679 | break; | 681 | break; |
680 | case NETROM_NEIGH: | 682 | case NETROM_NEIGH: |
681 | ret = nr_add_neigh(&nr_route.callsign, | 683 | ret = nr_add_neigh(&nr_route.callsign, |
682 | nr_call_to_digi(nr_route.ndigis, nr_route.digipeaters), | 684 | nr_call_to_digi(&digi, nr_route.ndigis, |
685 | nr_route.digipeaters), | ||
683 | dev, nr_route.quality); | 686 | dev, nr_route.quality); |
684 | break; | 687 | break; |
685 | default: | 688 | default: |
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 4f76e5552d8e..ebe5718baa31 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c | |||
@@ -1987,7 +1987,8 @@ static int packet_ioctl(struct socket *sock, unsigned int cmd, | |||
1987 | switch (cmd) { | 1987 | switch (cmd) { |
1988 | case SIOCOUTQ: | 1988 | case SIOCOUTQ: |
1989 | { | 1989 | { |
1990 | int amount = atomic_read(&sk->sk_wmem_alloc); | 1990 | int amount = sk_wmem_alloc_get(sk); |
1991 | |||
1991 | return put_user(amount, (int __user *)arg); | 1992 | return put_user(amount, (int __user *)arg); |
1992 | } | 1993 | } |
1993 | case SIOCINQ: | 1994 | case SIOCINQ: |
diff --git a/net/phonet/pn_dev.c b/net/phonet/pn_dev.c index 80a322d77909..c2b77a698695 100644 --- a/net/phonet/pn_dev.c +++ b/net/phonet/pn_dev.c | |||
@@ -69,17 +69,34 @@ static struct phonet_device *__phonet_get(struct net_device *dev) | |||
69 | return NULL; | 69 | return NULL; |
70 | } | 70 | } |
71 | 71 | ||
72 | static void __phonet_device_free(struct phonet_device *pnd) | 72 | static void phonet_device_destroy(struct net_device *dev) |
73 | { | 73 | { |
74 | list_del(&pnd->list); | 74 | struct phonet_device_list *pndevs = phonet_device_list(dev_net(dev)); |
75 | kfree(pnd); | 75 | struct phonet_device *pnd; |
76 | |||
77 | ASSERT_RTNL(); | ||
78 | |||
79 | spin_lock_bh(&pndevs->lock); | ||
80 | pnd = __phonet_get(dev); | ||
81 | if (pnd) | ||
82 | list_del(&pnd->list); | ||
83 | spin_unlock_bh(&pndevs->lock); | ||
84 | |||
85 | if (pnd) { | ||
86 | u8 addr; | ||
87 | |||
88 | for (addr = find_first_bit(pnd->addrs, 64); addr < 64; | ||
89 | addr = find_next_bit(pnd->addrs, 64, 1+addr)) | ||
90 | phonet_address_notify(RTM_DELADDR, dev, addr); | ||
91 | kfree(pnd); | ||
92 | } | ||
76 | } | 93 | } |
77 | 94 | ||
78 | struct net_device *phonet_device_get(struct net *net) | 95 | struct net_device *phonet_device_get(struct net *net) |
79 | { | 96 | { |
80 | struct phonet_device_list *pndevs = phonet_device_list(net); | 97 | struct phonet_device_list *pndevs = phonet_device_list(net); |
81 | struct phonet_device *pnd; | 98 | struct phonet_device *pnd; |
82 | struct net_device *dev; | 99 | struct net_device *dev = NULL; |
83 | 100 | ||
84 | spin_lock_bh(&pndevs->lock); | 101 | spin_lock_bh(&pndevs->lock); |
85 | list_for_each_entry(pnd, &pndevs->list, list) { | 102 | list_for_each_entry(pnd, &pndevs->list, list) { |
@@ -126,8 +143,10 @@ int phonet_address_del(struct net_device *dev, u8 addr) | |||
126 | pnd = __phonet_get(dev); | 143 | pnd = __phonet_get(dev); |
127 | if (!pnd || !test_and_clear_bit(addr >> 2, pnd->addrs)) | 144 | if (!pnd || !test_and_clear_bit(addr >> 2, pnd->addrs)) |
128 | err = -EADDRNOTAVAIL; | 145 | err = -EADDRNOTAVAIL; |
129 | else if (bitmap_empty(pnd->addrs, 64)) | 146 | else if (bitmap_empty(pnd->addrs, 64)) { |
130 | __phonet_device_free(pnd); | 147 | list_del(&pnd->list); |
148 | kfree(pnd); | ||
149 | } | ||
131 | spin_unlock_bh(&pndevs->lock); | 150 | spin_unlock_bh(&pndevs->lock); |
132 | return err; | 151 | return err; |
133 | } | 152 | } |
@@ -181,18 +200,8 @@ static int phonet_device_notify(struct notifier_block *me, unsigned long what, | |||
181 | { | 200 | { |
182 | struct net_device *dev = arg; | 201 | struct net_device *dev = arg; |
183 | 202 | ||
184 | if (what == NETDEV_UNREGISTER) { | 203 | if (what == NETDEV_UNREGISTER) |
185 | struct phonet_device_list *pndevs; | 204 | phonet_device_destroy(dev); |
186 | struct phonet_device *pnd; | ||
187 | |||
188 | /* Destroy phonet-specific device data */ | ||
189 | pndevs = phonet_device_list(dev_net(dev)); | ||
190 | spin_lock_bh(&pndevs->lock); | ||
191 | pnd = __phonet_get(dev); | ||
192 | if (pnd) | ||
193 | __phonet_device_free(pnd); | ||
194 | spin_unlock_bh(&pndevs->lock); | ||
195 | } | ||
196 | return 0; | 205 | return 0; |
197 | 206 | ||
198 | } | 207 | } |
@@ -218,11 +227,12 @@ static int phonet_init_net(struct net *net) | |||
218 | static void phonet_exit_net(struct net *net) | 227 | static void phonet_exit_net(struct net *net) |
219 | { | 228 | { |
220 | struct phonet_net *pnn = net_generic(net, phonet_net_id); | 229 | struct phonet_net *pnn = net_generic(net, phonet_net_id); |
221 | struct phonet_device *pnd, *n; | 230 | struct net_device *dev; |
222 | |||
223 | list_for_each_entry_safe(pnd, n, &pnn->pndevs.list, list) | ||
224 | __phonet_device_free(pnd); | ||
225 | 231 | ||
232 | rtnl_lock(); | ||
233 | for_each_netdev(net, dev) | ||
234 | phonet_device_destroy(dev); | ||
235 | rtnl_unlock(); | ||
226 | kfree(pnn); | 236 | kfree(pnn); |
227 | } | 237 | } |
228 | 238 | ||
diff --git a/net/phonet/pn_netlink.c b/net/phonet/pn_netlink.c index cec4e5951681..f8b4cee434c2 100644 --- a/net/phonet/pn_netlink.c +++ b/net/phonet/pn_netlink.c | |||
@@ -32,7 +32,7 @@ | |||
32 | static int fill_addr(struct sk_buff *skb, struct net_device *dev, u8 addr, | 32 | static int fill_addr(struct sk_buff *skb, struct net_device *dev, u8 addr, |
33 | u32 pid, u32 seq, int event); | 33 | u32 pid, u32 seq, int event); |
34 | 34 | ||
35 | static void rtmsg_notify(int event, struct net_device *dev, u8 addr) | 35 | void phonet_address_notify(int event, struct net_device *dev, u8 addr) |
36 | { | 36 | { |
37 | struct sk_buff *skb; | 37 | struct sk_buff *skb; |
38 | int err = -ENOBUFS; | 38 | int err = -ENOBUFS; |
@@ -94,7 +94,7 @@ static int addr_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *attr) | |||
94 | else | 94 | else |
95 | err = phonet_address_del(dev, pnaddr); | 95 | err = phonet_address_del(dev, pnaddr); |
96 | if (!err) | 96 | if (!err) |
97 | rtmsg_notify(nlh->nlmsg_type, dev, pnaddr); | 97 | phonet_address_notify(nlh->nlmsg_type, dev, pnaddr); |
98 | return err; | 98 | return err; |
99 | } | 99 | } |
100 | 100 | ||
diff --git a/net/rfkill/core.c b/net/rfkill/core.c index 4e68ab439d5d..2fc4a1724eb8 100644 --- a/net/rfkill/core.c +++ b/net/rfkill/core.c | |||
@@ -56,7 +56,6 @@ struct rfkill { | |||
56 | u32 idx; | 56 | u32 idx; |
57 | 57 | ||
58 | bool registered; | 58 | bool registered; |
59 | bool suspended; | ||
60 | bool persistent; | 59 | bool persistent; |
61 | 60 | ||
62 | const struct rfkill_ops *ops; | 61 | const struct rfkill_ops *ops; |
@@ -224,7 +223,7 @@ static void rfkill_send_events(struct rfkill *rfkill, enum rfkill_operation op) | |||
224 | 223 | ||
225 | static void rfkill_event(struct rfkill *rfkill) | 224 | static void rfkill_event(struct rfkill *rfkill) |
226 | { | 225 | { |
227 | if (!rfkill->registered || rfkill->suspended) | 226 | if (!rfkill->registered) |
228 | return; | 227 | return; |
229 | 228 | ||
230 | kobject_uevent(&rfkill->dev.kobj, KOBJ_CHANGE); | 229 | kobject_uevent(&rfkill->dev.kobj, KOBJ_CHANGE); |
@@ -270,6 +269,9 @@ static void rfkill_set_block(struct rfkill *rfkill, bool blocked) | |||
270 | unsigned long flags; | 269 | unsigned long flags; |
271 | int err; | 270 | int err; |
272 | 271 | ||
272 | if (unlikely(rfkill->dev.power.power_state.event & PM_EVENT_SLEEP)) | ||
273 | return; | ||
274 | |||
273 | /* | 275 | /* |
274 | * Some platforms (...!) generate input events which affect the | 276 | * Some platforms (...!) generate input events which affect the |
275 | * _hard_ kill state -- whenever something tries to change the | 277 | * _hard_ kill state -- whenever something tries to change the |
@@ -292,9 +294,6 @@ static void rfkill_set_block(struct rfkill *rfkill, bool blocked) | |||
292 | rfkill->state |= RFKILL_BLOCK_SW_SETCALL; | 294 | rfkill->state |= RFKILL_BLOCK_SW_SETCALL; |
293 | spin_unlock_irqrestore(&rfkill->lock, flags); | 295 | spin_unlock_irqrestore(&rfkill->lock, flags); |
294 | 296 | ||
295 | if (unlikely(rfkill->dev.power.power_state.event & PM_EVENT_SLEEP)) | ||
296 | return; | ||
297 | |||
298 | err = rfkill->ops->set_block(rfkill->data, blocked); | 297 | err = rfkill->ops->set_block(rfkill->data, blocked); |
299 | 298 | ||
300 | spin_lock_irqsave(&rfkill->lock, flags); | 299 | spin_lock_irqsave(&rfkill->lock, flags); |
@@ -508,19 +507,32 @@ bool rfkill_set_sw_state(struct rfkill *rfkill, bool blocked) | |||
508 | blocked = blocked || hwblock; | 507 | blocked = blocked || hwblock; |
509 | spin_unlock_irqrestore(&rfkill->lock, flags); | 508 | spin_unlock_irqrestore(&rfkill->lock, flags); |
510 | 509 | ||
511 | if (!rfkill->registered) { | 510 | if (!rfkill->registered) |
512 | rfkill->persistent = true; | 511 | return blocked; |
513 | } else { | ||
514 | if (prev != blocked && !hwblock) | ||
515 | schedule_work(&rfkill->uevent_work); | ||
516 | 512 | ||
517 | rfkill_led_trigger_event(rfkill); | 513 | if (prev != blocked && !hwblock) |
518 | } | 514 | schedule_work(&rfkill->uevent_work); |
515 | |||
516 | rfkill_led_trigger_event(rfkill); | ||
519 | 517 | ||
520 | return blocked; | 518 | return blocked; |
521 | } | 519 | } |
522 | EXPORT_SYMBOL(rfkill_set_sw_state); | 520 | EXPORT_SYMBOL(rfkill_set_sw_state); |
523 | 521 | ||
522 | void rfkill_init_sw_state(struct rfkill *rfkill, bool blocked) | ||
523 | { | ||
524 | unsigned long flags; | ||
525 | |||
526 | BUG_ON(!rfkill); | ||
527 | BUG_ON(rfkill->registered); | ||
528 | |||
529 | spin_lock_irqsave(&rfkill->lock, flags); | ||
530 | __rfkill_set_sw_state(rfkill, blocked); | ||
531 | rfkill->persistent = true; | ||
532 | spin_unlock_irqrestore(&rfkill->lock, flags); | ||
533 | } | ||
534 | EXPORT_SYMBOL(rfkill_init_sw_state); | ||
535 | |||
524 | void rfkill_set_states(struct rfkill *rfkill, bool sw, bool hw) | 536 | void rfkill_set_states(struct rfkill *rfkill, bool sw, bool hw) |
525 | { | 537 | { |
526 | unsigned long flags; | 538 | unsigned long flags; |
@@ -537,6 +549,10 @@ void rfkill_set_states(struct rfkill *rfkill, bool sw, bool hw) | |||
537 | swprev = !!(rfkill->state & RFKILL_BLOCK_SW); | 549 | swprev = !!(rfkill->state & RFKILL_BLOCK_SW); |
538 | hwprev = !!(rfkill->state & RFKILL_BLOCK_HW); | 550 | hwprev = !!(rfkill->state & RFKILL_BLOCK_HW); |
539 | __rfkill_set_sw_state(rfkill, sw); | 551 | __rfkill_set_sw_state(rfkill, sw); |
552 | if (hw) | ||
553 | rfkill->state |= RFKILL_BLOCK_HW; | ||
554 | else | ||
555 | rfkill->state &= ~RFKILL_BLOCK_HW; | ||
540 | 556 | ||
541 | spin_unlock_irqrestore(&rfkill->lock, flags); | 557 | spin_unlock_irqrestore(&rfkill->lock, flags); |
542 | 558 | ||
@@ -598,6 +614,15 @@ static ssize_t rfkill_idx_show(struct device *dev, | |||
598 | return sprintf(buf, "%d\n", rfkill->idx); | 614 | return sprintf(buf, "%d\n", rfkill->idx); |
599 | } | 615 | } |
600 | 616 | ||
617 | static ssize_t rfkill_persistent_show(struct device *dev, | ||
618 | struct device_attribute *attr, | ||
619 | char *buf) | ||
620 | { | ||
621 | struct rfkill *rfkill = to_rfkill(dev); | ||
622 | |||
623 | return sprintf(buf, "%d\n", rfkill->persistent); | ||
624 | } | ||
625 | |||
601 | static u8 user_state_from_blocked(unsigned long state) | 626 | static u8 user_state_from_blocked(unsigned long state) |
602 | { | 627 | { |
603 | if (state & RFKILL_BLOCK_HW) | 628 | if (state & RFKILL_BLOCK_HW) |
@@ -627,15 +652,26 @@ static ssize_t rfkill_state_store(struct device *dev, | |||
627 | struct device_attribute *attr, | 652 | struct device_attribute *attr, |
628 | const char *buf, size_t count) | 653 | const char *buf, size_t count) |
629 | { | 654 | { |
630 | /* | 655 | struct rfkill *rfkill = to_rfkill(dev); |
631 | * The intention was that userspace can only take control over | 656 | unsigned long state; |
632 | * a given device when/if rfkill-input doesn't control it due | 657 | int err; |
633 | * to user_claim. Since user_claim is currently unsupported, | 658 | |
634 | * we never support changing the state from userspace -- this | 659 | if (!capable(CAP_NET_ADMIN)) |
635 | * can be implemented again later. | 660 | return -EPERM; |
636 | */ | 661 | |
662 | err = strict_strtoul(buf, 0, &state); | ||
663 | if (err) | ||
664 | return err; | ||
637 | 665 | ||
638 | return -EPERM; | 666 | if (state != RFKILL_USER_STATE_SOFT_BLOCKED && |
667 | state != RFKILL_USER_STATE_UNBLOCKED) | ||
668 | return -EINVAL; | ||
669 | |||
670 | mutex_lock(&rfkill_global_mutex); | ||
671 | rfkill_set_block(rfkill, state == RFKILL_USER_STATE_SOFT_BLOCKED); | ||
672 | mutex_unlock(&rfkill_global_mutex); | ||
673 | |||
674 | return err ?: count; | ||
639 | } | 675 | } |
640 | 676 | ||
641 | static ssize_t rfkill_claim_show(struct device *dev, | 677 | static ssize_t rfkill_claim_show(struct device *dev, |
@@ -656,6 +692,7 @@ static struct device_attribute rfkill_dev_attrs[] = { | |||
656 | __ATTR(name, S_IRUGO, rfkill_name_show, NULL), | 692 | __ATTR(name, S_IRUGO, rfkill_name_show, NULL), |
657 | __ATTR(type, S_IRUGO, rfkill_type_show, NULL), | 693 | __ATTR(type, S_IRUGO, rfkill_type_show, NULL), |
658 | __ATTR(index, S_IRUGO, rfkill_idx_show, NULL), | 694 | __ATTR(index, S_IRUGO, rfkill_idx_show, NULL), |
695 | __ATTR(persistent, S_IRUGO, rfkill_persistent_show, NULL), | ||
659 | __ATTR(state, S_IRUGO|S_IWUSR, rfkill_state_show, rfkill_state_store), | 696 | __ATTR(state, S_IRUGO|S_IWUSR, rfkill_state_show, rfkill_state_store), |
660 | __ATTR(claim, S_IRUGO|S_IWUSR, rfkill_claim_show, rfkill_claim_store), | 697 | __ATTR(claim, S_IRUGO|S_IWUSR, rfkill_claim_show, rfkill_claim_store), |
661 | __ATTR_NULL | 698 | __ATTR_NULL |
@@ -718,8 +755,6 @@ static int rfkill_suspend(struct device *dev, pm_message_t state) | |||
718 | 755 | ||
719 | rfkill_pause_polling(rfkill); | 756 | rfkill_pause_polling(rfkill); |
720 | 757 | ||
721 | rfkill->suspended = true; | ||
722 | |||
723 | return 0; | 758 | return 0; |
724 | } | 759 | } |
725 | 760 | ||
@@ -728,10 +763,10 @@ static int rfkill_resume(struct device *dev) | |||
728 | struct rfkill *rfkill = to_rfkill(dev); | 763 | struct rfkill *rfkill = to_rfkill(dev); |
729 | bool cur; | 764 | bool cur; |
730 | 765 | ||
731 | cur = !!(rfkill->state & RFKILL_BLOCK_SW); | 766 | if (!rfkill->persistent) { |
732 | rfkill_set_block(rfkill, cur); | 767 | cur = !!(rfkill->state & RFKILL_BLOCK_SW); |
733 | 768 | rfkill_set_block(rfkill, cur); | |
734 | rfkill->suspended = false; | 769 | } |
735 | 770 | ||
736 | rfkill_resume_polling(rfkill); | 771 | rfkill_resume_polling(rfkill); |
737 | 772 | ||
diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c index 877a7f65f707..e5f478ca3d61 100644 --- a/net/rose/af_rose.c +++ b/net/rose/af_rose.c | |||
@@ -92,23 +92,21 @@ static void rose_set_lockdep_key(struct net_device *dev) | |||
92 | /* | 92 | /* |
93 | * Convert a ROSE address into text. | 93 | * Convert a ROSE address into text. |
94 | */ | 94 | */ |
95 | const char *rose2asc(const rose_address *addr) | 95 | char *rose2asc(char *buf, const rose_address *addr) |
96 | { | 96 | { |
97 | static char buffer[11]; | ||
98 | |||
99 | if (addr->rose_addr[0] == 0x00 && addr->rose_addr[1] == 0x00 && | 97 | if (addr->rose_addr[0] == 0x00 && addr->rose_addr[1] == 0x00 && |
100 | addr->rose_addr[2] == 0x00 && addr->rose_addr[3] == 0x00 && | 98 | addr->rose_addr[2] == 0x00 && addr->rose_addr[3] == 0x00 && |
101 | addr->rose_addr[4] == 0x00) { | 99 | addr->rose_addr[4] == 0x00) { |
102 | strcpy(buffer, "*"); | 100 | strcpy(buf, "*"); |
103 | } else { | 101 | } else { |
104 | sprintf(buffer, "%02X%02X%02X%02X%02X", addr->rose_addr[0] & 0xFF, | 102 | sprintf(buf, "%02X%02X%02X%02X%02X", addr->rose_addr[0] & 0xFF, |
105 | addr->rose_addr[1] & 0xFF, | 103 | addr->rose_addr[1] & 0xFF, |
106 | addr->rose_addr[2] & 0xFF, | 104 | addr->rose_addr[2] & 0xFF, |
107 | addr->rose_addr[3] & 0xFF, | 105 | addr->rose_addr[3] & 0xFF, |
108 | addr->rose_addr[4] & 0xFF); | 106 | addr->rose_addr[4] & 0xFF); |
109 | } | 107 | } |
110 | 108 | ||
111 | return buffer; | 109 | return buf; |
112 | } | 110 | } |
113 | 111 | ||
114 | /* | 112 | /* |
@@ -356,8 +354,7 @@ void rose_destroy_socket(struct sock *sk) | |||
356 | kfree_skb(skb); | 354 | kfree_skb(skb); |
357 | } | 355 | } |
358 | 356 | ||
359 | if (atomic_read(&sk->sk_wmem_alloc) || | 357 | if (sk_has_allocations(sk)) { |
360 | atomic_read(&sk->sk_rmem_alloc)) { | ||
361 | /* Defer: outstanding buffers */ | 358 | /* Defer: outstanding buffers */ |
362 | setup_timer(&sk->sk_timer, rose_destroy_timer, | 359 | setup_timer(&sk->sk_timer, rose_destroy_timer, |
363 | (unsigned long)sk); | 360 | (unsigned long)sk); |
@@ -957,6 +954,7 @@ static int rose_getname(struct socket *sock, struct sockaddr *uaddr, | |||
957 | struct rose_sock *rose = rose_sk(sk); | 954 | struct rose_sock *rose = rose_sk(sk); |
958 | int n; | 955 | int n; |
959 | 956 | ||
957 | memset(srose, 0, sizeof(*srose)); | ||
960 | if (peer != 0) { | 958 | if (peer != 0) { |
961 | if (sk->sk_state != TCP_ESTABLISHED) | 959 | if (sk->sk_state != TCP_ESTABLISHED) |
962 | return -ENOTCONN; | 960 | return -ENOTCONN; |
@@ -1310,7 +1308,8 @@ static int rose_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
1310 | switch (cmd) { | 1308 | switch (cmd) { |
1311 | case TIOCOUTQ: { | 1309 | case TIOCOUTQ: { |
1312 | long amount; | 1310 | long amount; |
1313 | amount = sk->sk_sndbuf - atomic_read(&sk->sk_wmem_alloc); | 1311 | |
1312 | amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk); | ||
1314 | if (amount < 0) | 1313 | if (amount < 0) |
1315 | amount = 0; | 1314 | amount = 0; |
1316 | return put_user(amount, (unsigned int __user *) argp); | 1315 | return put_user(amount, (unsigned int __user *) argp); |
@@ -1437,7 +1436,7 @@ static void rose_info_stop(struct seq_file *seq, void *v) | |||
1437 | 1436 | ||
1438 | static int rose_info_show(struct seq_file *seq, void *v) | 1437 | static int rose_info_show(struct seq_file *seq, void *v) |
1439 | { | 1438 | { |
1440 | char buf[11]; | 1439 | char buf[11], rsbuf[11]; |
1441 | 1440 | ||
1442 | if (v == SEQ_START_TOKEN) | 1441 | if (v == SEQ_START_TOKEN) |
1443 | seq_puts(seq, | 1442 | seq_puts(seq, |
@@ -1455,8 +1454,8 @@ static int rose_info_show(struct seq_file *seq, void *v) | |||
1455 | devname = dev->name; | 1454 | devname = dev->name; |
1456 | 1455 | ||
1457 | seq_printf(seq, "%-10s %-9s ", | 1456 | seq_printf(seq, "%-10s %-9s ", |
1458 | rose2asc(&rose->dest_addr), | 1457 | rose2asc(rsbuf, &rose->dest_addr), |
1459 | ax2asc(buf, &rose->dest_call)); | 1458 | ax2asc(buf, &rose->dest_call)); |
1460 | 1459 | ||
1461 | if (ax25cmp(&rose->source_call, &null_ax25_address) == 0) | 1460 | if (ax25cmp(&rose->source_call, &null_ax25_address) == 0) |
1462 | callsign = "??????-?"; | 1461 | callsign = "??????-?"; |
@@ -1465,7 +1464,7 @@ static int rose_info_show(struct seq_file *seq, void *v) | |||
1465 | 1464 | ||
1466 | seq_printf(seq, | 1465 | seq_printf(seq, |
1467 | "%-10s %-9s %-5s %3.3X %05d %d %d %d %d %3lu %3lu %3lu %3lu %3lu %3lu/%03lu %5d %5d %ld\n", | 1466 | "%-10s %-9s %-5s %3.3X %05d %d %d %d %d %3lu %3lu %3lu %3lu %3lu %3lu/%03lu %5d %5d %ld\n", |
1468 | rose2asc(&rose->source_addr), | 1467 | rose2asc(rsbuf, &rose->source_addr), |
1469 | callsign, | 1468 | callsign, |
1470 | devname, | 1469 | devname, |
1471 | rose->lci & 0x0FFF, | 1470 | rose->lci & 0x0FFF, |
@@ -1481,8 +1480,8 @@ static int rose_info_show(struct seq_file *seq, void *v) | |||
1481 | rose->hb / HZ, | 1480 | rose->hb / HZ, |
1482 | ax25_display_timer(&rose->idletimer) / (60 * HZ), | 1481 | ax25_display_timer(&rose->idletimer) / (60 * HZ), |
1483 | rose->idle / (60 * HZ), | 1482 | rose->idle / (60 * HZ), |
1484 | atomic_read(&s->sk_wmem_alloc), | 1483 | sk_wmem_alloc_get(s), |
1485 | atomic_read(&s->sk_rmem_alloc), | 1484 | sk_rmem_alloc_get(s), |
1486 | s->sk_socket ? SOCK_INODE(s->sk_socket)->i_ino : 0L); | 1485 | s->sk_socket ? SOCK_INODE(s->sk_socket)->i_ino : 0L); |
1487 | } | 1486 | } |
1488 | 1487 | ||
diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c index a81066a1010a..9478d9b3d977 100644 --- a/net/rose/rose_route.c +++ b/net/rose/rose_route.c | |||
@@ -1104,6 +1104,7 @@ static void rose_node_stop(struct seq_file *seq, void *v) | |||
1104 | 1104 | ||
1105 | static int rose_node_show(struct seq_file *seq, void *v) | 1105 | static int rose_node_show(struct seq_file *seq, void *v) |
1106 | { | 1106 | { |
1107 | char rsbuf[11]; | ||
1107 | int i; | 1108 | int i; |
1108 | 1109 | ||
1109 | if (v == SEQ_START_TOKEN) | 1110 | if (v == SEQ_START_TOKEN) |
@@ -1112,13 +1113,13 @@ static int rose_node_show(struct seq_file *seq, void *v) | |||
1112 | const struct rose_node *rose_node = v; | 1113 | const struct rose_node *rose_node = v; |
1113 | /* if (rose_node->loopback) { | 1114 | /* if (rose_node->loopback) { |
1114 | seq_printf(seq, "%-10s %04d 1 loopback\n", | 1115 | seq_printf(seq, "%-10s %04d 1 loopback\n", |
1115 | rose2asc(&rose_node->address), | 1116 | rose2asc(rsbuf, &rose_node->address), |
1116 | rose_node->mask); | 1117 | rose_node->mask); |
1117 | } else { */ | 1118 | } else { */ |
1118 | seq_printf(seq, "%-10s %04d %d", | 1119 | seq_printf(seq, "%-10s %04d %d", |
1119 | rose2asc(&rose_node->address), | 1120 | rose2asc(rsbuf, &rose_node->address), |
1120 | rose_node->mask, | 1121 | rose_node->mask, |
1121 | rose_node->count); | 1122 | rose_node->count); |
1122 | 1123 | ||
1123 | for (i = 0; i < rose_node->count; i++) | 1124 | for (i = 0; i < rose_node->count; i++) |
1124 | seq_printf(seq, " %05d", | 1125 | seq_printf(seq, " %05d", |
@@ -1267,7 +1268,7 @@ static void rose_route_stop(struct seq_file *seq, void *v) | |||
1267 | 1268 | ||
1268 | static int rose_route_show(struct seq_file *seq, void *v) | 1269 | static int rose_route_show(struct seq_file *seq, void *v) |
1269 | { | 1270 | { |
1270 | char buf[11]; | 1271 | char buf[11], rsbuf[11]; |
1271 | 1272 | ||
1272 | if (v == SEQ_START_TOKEN) | 1273 | if (v == SEQ_START_TOKEN) |
1273 | seq_puts(seq, | 1274 | seq_puts(seq, |
@@ -1279,7 +1280,7 @@ static int rose_route_show(struct seq_file *seq, void *v) | |||
1279 | seq_printf(seq, | 1280 | seq_printf(seq, |
1280 | "%3.3X %-10s %-9s %05d ", | 1281 | "%3.3X %-10s %-9s %05d ", |
1281 | rose_route->lci1, | 1282 | rose_route->lci1, |
1282 | rose2asc(&rose_route->src_addr), | 1283 | rose2asc(rsbuf, &rose_route->src_addr), |
1283 | ax2asc(buf, &rose_route->src_call), | 1284 | ax2asc(buf, &rose_route->src_call), |
1284 | rose_route->neigh1->number); | 1285 | rose_route->neigh1->number); |
1285 | else | 1286 | else |
@@ -1289,10 +1290,10 @@ static int rose_route_show(struct seq_file *seq, void *v) | |||
1289 | if (rose_route->neigh2) | 1290 | if (rose_route->neigh2) |
1290 | seq_printf(seq, | 1291 | seq_printf(seq, |
1291 | "%3.3X %-10s %-9s %05d\n", | 1292 | "%3.3X %-10s %-9s %05d\n", |
1292 | rose_route->lci2, | 1293 | rose_route->lci2, |
1293 | rose2asc(&rose_route->dest_addr), | 1294 | rose2asc(rsbuf, &rose_route->dest_addr), |
1294 | ax2asc(buf, &rose_route->dest_call), | 1295 | ax2asc(buf, &rose_route->dest_call), |
1295 | rose_route->neigh2->number); | 1296 | rose_route->neigh2->number); |
1296 | else | 1297 | else |
1297 | seq_puts(seq, | 1298 | seq_puts(seq, |
1298 | "000 * * 00000\n"); | 1299 | "000 * * 00000\n"); |
diff --git a/net/rxrpc/af_rxrpc.c b/net/rxrpc/af_rxrpc.c index eac5e7bb7365..bfe493ebf27c 100644 --- a/net/rxrpc/af_rxrpc.c +++ b/net/rxrpc/af_rxrpc.c | |||
@@ -63,7 +63,7 @@ static void rxrpc_write_space(struct sock *sk) | |||
63 | _enter("%p", sk); | 63 | _enter("%p", sk); |
64 | read_lock(&sk->sk_callback_lock); | 64 | read_lock(&sk->sk_callback_lock); |
65 | if (rxrpc_writable(sk)) { | 65 | if (rxrpc_writable(sk)) { |
66 | if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) | 66 | if (sk_has_sleeper(sk)) |
67 | wake_up_interruptible(sk->sk_sleep); | 67 | wake_up_interruptible(sk->sk_sleep); |
68 | sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); | 68 | sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); |
69 | } | 69 | } |
@@ -588,7 +588,7 @@ static unsigned int rxrpc_poll(struct file *file, struct socket *sock, | |||
588 | unsigned int mask; | 588 | unsigned int mask; |
589 | struct sock *sk = sock->sk; | 589 | struct sock *sk = sock->sk; |
590 | 590 | ||
591 | poll_wait(file, sk->sk_sleep, wait); | 591 | sock_poll_wait(file, sk->sk_sleep, wait); |
592 | mask = 0; | 592 | mask = 0; |
593 | 593 | ||
594 | /* the socket is readable if there are any messages waiting on the Rx | 594 | /* the socket is readable if there are any messages waiting on the Rx |
diff --git a/net/sched/act_police.c b/net/sched/act_police.c index f8f047b61245..723964c3ee4f 100644 --- a/net/sched/act_police.c +++ b/net/sched/act_police.c | |||
@@ -294,6 +294,8 @@ static int tcf_act_police(struct sk_buff *skb, struct tc_action *a, | |||
294 | if (police->tcfp_ewma_rate && | 294 | if (police->tcfp_ewma_rate && |
295 | police->tcf_rate_est.bps >= police->tcfp_ewma_rate) { | 295 | police->tcf_rate_est.bps >= police->tcfp_ewma_rate) { |
296 | police->tcf_qstats.overlimits++; | 296 | police->tcf_qstats.overlimits++; |
297 | if (police->tcf_action == TC_ACT_SHOT) | ||
298 | police->tcf_qstats.drops++; | ||
297 | spin_unlock(&police->tcf_lock); | 299 | spin_unlock(&police->tcf_lock); |
298 | return police->tcf_action; | 300 | return police->tcf_action; |
299 | } | 301 | } |
@@ -327,6 +329,8 @@ static int tcf_act_police(struct sk_buff *skb, struct tc_action *a, | |||
327 | } | 329 | } |
328 | 330 | ||
329 | police->tcf_qstats.overlimits++; | 331 | police->tcf_qstats.overlimits++; |
332 | if (police->tcf_action == TC_ACT_SHOT) | ||
333 | police->tcf_qstats.drops++; | ||
330 | spin_unlock(&police->tcf_lock); | 334 | spin_unlock(&police->tcf_lock); |
331 | return police->tcf_action; | 335 | return police->tcf_action; |
332 | } | 336 | } |
diff --git a/net/sched/em_meta.c b/net/sched/em_meta.c index 266151ae85a3..18d85d259104 100644 --- a/net/sched/em_meta.c +++ b/net/sched/em_meta.c | |||
@@ -349,13 +349,13 @@ META_COLLECTOR(int_sk_type) | |||
349 | META_COLLECTOR(int_sk_rmem_alloc) | 349 | META_COLLECTOR(int_sk_rmem_alloc) |
350 | { | 350 | { |
351 | SKIP_NONLOCAL(skb); | 351 | SKIP_NONLOCAL(skb); |
352 | dst->value = atomic_read(&skb->sk->sk_rmem_alloc); | 352 | dst->value = sk_rmem_alloc_get(skb->sk); |
353 | } | 353 | } |
354 | 354 | ||
355 | META_COLLECTOR(int_sk_wmem_alloc) | 355 | META_COLLECTOR(int_sk_wmem_alloc) |
356 | { | 356 | { |
357 | SKIP_NONLOCAL(skb); | 357 | SKIP_NONLOCAL(skb); |
358 | dst->value = atomic_read(&skb->sk->sk_wmem_alloc); | 358 | dst->value = sk_wmem_alloc_get(skb->sk); |
359 | } | 359 | } |
360 | 360 | ||
361 | META_COLLECTOR(int_sk_omem_alloc) | 361 | META_COLLECTOR(int_sk_omem_alloc) |
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index 24d17ce9c294..92e6f3a52c13 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c | |||
@@ -458,7 +458,7 @@ EXPORT_SYMBOL(qdisc_warn_nonwc); | |||
458 | static enum hrtimer_restart qdisc_watchdog(struct hrtimer *timer) | 458 | static enum hrtimer_restart qdisc_watchdog(struct hrtimer *timer) |
459 | { | 459 | { |
460 | struct qdisc_watchdog *wd = container_of(timer, struct qdisc_watchdog, | 460 | struct qdisc_watchdog *wd = container_of(timer, struct qdisc_watchdog, |
461 | timer); | 461 | timer.timer); |
462 | 462 | ||
463 | wd->qdisc->flags &= ~TCQ_F_THROTTLED; | 463 | wd->qdisc->flags &= ~TCQ_F_THROTTLED; |
464 | __netif_schedule(qdisc_root(wd->qdisc)); | 464 | __netif_schedule(qdisc_root(wd->qdisc)); |
@@ -468,8 +468,8 @@ static enum hrtimer_restart qdisc_watchdog(struct hrtimer *timer) | |||
468 | 468 | ||
469 | void qdisc_watchdog_init(struct qdisc_watchdog *wd, struct Qdisc *qdisc) | 469 | void qdisc_watchdog_init(struct qdisc_watchdog *wd, struct Qdisc *qdisc) |
470 | { | 470 | { |
471 | hrtimer_init(&wd->timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); | 471 | tasklet_hrtimer_init(&wd->timer, qdisc_watchdog, |
472 | wd->timer.function = qdisc_watchdog; | 472 | CLOCK_MONOTONIC, HRTIMER_MODE_ABS); |
473 | wd->qdisc = qdisc; | 473 | wd->qdisc = qdisc; |
474 | } | 474 | } |
475 | EXPORT_SYMBOL(qdisc_watchdog_init); | 475 | EXPORT_SYMBOL(qdisc_watchdog_init); |
@@ -485,13 +485,13 @@ void qdisc_watchdog_schedule(struct qdisc_watchdog *wd, psched_time_t expires) | |||
485 | wd->qdisc->flags |= TCQ_F_THROTTLED; | 485 | wd->qdisc->flags |= TCQ_F_THROTTLED; |
486 | time = ktime_set(0, 0); | 486 | time = ktime_set(0, 0); |
487 | time = ktime_add_ns(time, PSCHED_TICKS2NS(expires)); | 487 | time = ktime_add_ns(time, PSCHED_TICKS2NS(expires)); |
488 | hrtimer_start(&wd->timer, time, HRTIMER_MODE_ABS); | 488 | tasklet_hrtimer_start(&wd->timer, time, HRTIMER_MODE_ABS); |
489 | } | 489 | } |
490 | EXPORT_SYMBOL(qdisc_watchdog_schedule); | 490 | EXPORT_SYMBOL(qdisc_watchdog_schedule); |
491 | 491 | ||
492 | void qdisc_watchdog_cancel(struct qdisc_watchdog *wd) | 492 | void qdisc_watchdog_cancel(struct qdisc_watchdog *wd) |
493 | { | 493 | { |
494 | hrtimer_cancel(&wd->timer); | 494 | tasklet_hrtimer_cancel(&wd->timer); |
495 | wd->qdisc->flags &= ~TCQ_F_THROTTLED; | 495 | wd->qdisc->flags &= ~TCQ_F_THROTTLED; |
496 | } | 496 | } |
497 | EXPORT_SYMBOL(qdisc_watchdog_cancel); | 497 | EXPORT_SYMBOL(qdisc_watchdog_cancel); |
diff --git a/net/sched/sch_atm.c b/net/sched/sch_atm.c index 2a8b83af7c47..ab82f145f689 100644 --- a/net/sched/sch_atm.c +++ b/net/sched/sch_atm.c | |||
@@ -49,7 +49,7 @@ struct atm_flow_data { | |||
49 | struct socket *sock; /* for closing */ | 49 | struct socket *sock; /* for closing */ |
50 | u32 classid; /* x:y type ID */ | 50 | u32 classid; /* x:y type ID */ |
51 | int ref; /* reference count */ | 51 | int ref; /* reference count */ |
52 | struct gnet_stats_basic bstats; | 52 | struct gnet_stats_basic_packed bstats; |
53 | struct gnet_stats_queue qstats; | 53 | struct gnet_stats_queue qstats; |
54 | struct atm_flow_data *next; | 54 | struct atm_flow_data *next; |
55 | struct atm_flow_data *excess; /* flow for excess traffic; | 55 | struct atm_flow_data *excess; /* flow for excess traffic; |
diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c index 23a167670fd5..149b0405c5ec 100644 --- a/net/sched/sch_cbq.c +++ b/net/sched/sch_cbq.c | |||
@@ -128,7 +128,7 @@ struct cbq_class | |||
128 | long avgidle; | 128 | long avgidle; |
129 | long deficit; /* Saved deficit for WRR */ | 129 | long deficit; /* Saved deficit for WRR */ |
130 | psched_time_t penalized; | 130 | psched_time_t penalized; |
131 | struct gnet_stats_basic bstats; | 131 | struct gnet_stats_basic_packed bstats; |
132 | struct gnet_stats_queue qstats; | 132 | struct gnet_stats_queue qstats; |
133 | struct gnet_stats_rate_est rate_est; | 133 | struct gnet_stats_rate_est rate_est; |
134 | struct tc_cbq_xstats xstats; | 134 | struct tc_cbq_xstats xstats; |
@@ -163,7 +163,7 @@ struct cbq_sched_data | |||
163 | psched_time_t now_rt; /* Cached real time */ | 163 | psched_time_t now_rt; /* Cached real time */ |
164 | unsigned pmask; | 164 | unsigned pmask; |
165 | 165 | ||
166 | struct hrtimer delay_timer; | 166 | struct tasklet_hrtimer delay_timer; |
167 | struct qdisc_watchdog watchdog; /* Watchdog timer, | 167 | struct qdisc_watchdog watchdog; /* Watchdog timer, |
168 | started when CBQ has | 168 | started when CBQ has |
169 | backlog, but cannot | 169 | backlog, but cannot |
@@ -503,6 +503,8 @@ static void cbq_ovl_delay(struct cbq_class *cl) | |||
503 | cl->undertime = q->now + delay; | 503 | cl->undertime = q->now + delay; |
504 | 504 | ||
505 | if (delay > 0) { | 505 | if (delay > 0) { |
506 | struct hrtimer *ht; | ||
507 | |||
506 | sched += delay + cl->penalty; | 508 | sched += delay + cl->penalty; |
507 | cl->penalized = sched; | 509 | cl->penalized = sched; |
508 | cl->cpriority = TC_CBQ_MAXPRIO; | 510 | cl->cpriority = TC_CBQ_MAXPRIO; |
@@ -510,12 +512,12 @@ static void cbq_ovl_delay(struct cbq_class *cl) | |||
510 | 512 | ||
511 | expires = ktime_set(0, 0); | 513 | expires = ktime_set(0, 0); |
512 | expires = ktime_add_ns(expires, PSCHED_TICKS2NS(sched)); | 514 | expires = ktime_add_ns(expires, PSCHED_TICKS2NS(sched)); |
513 | if (hrtimer_try_to_cancel(&q->delay_timer) && | 515 | ht = &q->delay_timer.timer; |
514 | ktime_to_ns(ktime_sub( | 516 | if (hrtimer_try_to_cancel(ht) && |
515 | hrtimer_get_expires(&q->delay_timer), | 517 | ktime_to_ns(ktime_sub(hrtimer_get_expires(ht), |
516 | expires)) > 0) | 518 | expires)) > 0) |
517 | hrtimer_set_expires(&q->delay_timer, expires); | 519 | hrtimer_set_expires(ht, expires); |
518 | hrtimer_restart(&q->delay_timer); | 520 | hrtimer_restart(ht); |
519 | cl->delayed = 1; | 521 | cl->delayed = 1; |
520 | cl->xstats.overactions++; | 522 | cl->xstats.overactions++; |
521 | return; | 523 | return; |
@@ -591,7 +593,7 @@ static psched_tdiff_t cbq_undelay_prio(struct cbq_sched_data *q, int prio, | |||
591 | static enum hrtimer_restart cbq_undelay(struct hrtimer *timer) | 593 | static enum hrtimer_restart cbq_undelay(struct hrtimer *timer) |
592 | { | 594 | { |
593 | struct cbq_sched_data *q = container_of(timer, struct cbq_sched_data, | 595 | struct cbq_sched_data *q = container_of(timer, struct cbq_sched_data, |
594 | delay_timer); | 596 | delay_timer.timer); |
595 | struct Qdisc *sch = q->watchdog.qdisc; | 597 | struct Qdisc *sch = q->watchdog.qdisc; |
596 | psched_time_t now; | 598 | psched_time_t now; |
597 | psched_tdiff_t delay = 0; | 599 | psched_tdiff_t delay = 0; |
@@ -621,7 +623,7 @@ static enum hrtimer_restart cbq_undelay(struct hrtimer *timer) | |||
621 | 623 | ||
622 | time = ktime_set(0, 0); | 624 | time = ktime_set(0, 0); |
623 | time = ktime_add_ns(time, PSCHED_TICKS2NS(now + delay)); | 625 | time = ktime_add_ns(time, PSCHED_TICKS2NS(now + delay)); |
624 | hrtimer_start(&q->delay_timer, time, HRTIMER_MODE_ABS); | 626 | tasklet_hrtimer_start(&q->delay_timer, time, HRTIMER_MODE_ABS); |
625 | } | 627 | } |
626 | 628 | ||
627 | sch->flags &= ~TCQ_F_THROTTLED; | 629 | sch->flags &= ~TCQ_F_THROTTLED; |
@@ -1214,7 +1216,7 @@ cbq_reset(struct Qdisc* sch) | |||
1214 | q->tx_class = NULL; | 1216 | q->tx_class = NULL; |
1215 | q->tx_borrowed = NULL; | 1217 | q->tx_borrowed = NULL; |
1216 | qdisc_watchdog_cancel(&q->watchdog); | 1218 | qdisc_watchdog_cancel(&q->watchdog); |
1217 | hrtimer_cancel(&q->delay_timer); | 1219 | tasklet_hrtimer_cancel(&q->delay_timer); |
1218 | q->toplevel = TC_CBQ_MAXLEVEL; | 1220 | q->toplevel = TC_CBQ_MAXLEVEL; |
1219 | q->now = psched_get_time(); | 1221 | q->now = psched_get_time(); |
1220 | q->now_rt = q->now; | 1222 | q->now_rt = q->now; |
@@ -1397,7 +1399,8 @@ static int cbq_init(struct Qdisc *sch, struct nlattr *opt) | |||
1397 | q->link.minidle = -0x7FFFFFFF; | 1399 | q->link.minidle = -0x7FFFFFFF; |
1398 | 1400 | ||
1399 | qdisc_watchdog_init(&q->watchdog, sch); | 1401 | qdisc_watchdog_init(&q->watchdog, sch); |
1400 | hrtimer_init(&q->delay_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); | 1402 | tasklet_hrtimer_init(&q->delay_timer, cbq_undelay, |
1403 | CLOCK_MONOTONIC, HRTIMER_MODE_ABS); | ||
1401 | q->delay_timer.function = cbq_undelay; | 1404 | q->delay_timer.function = cbq_undelay; |
1402 | q->toplevel = TC_CBQ_MAXLEVEL; | 1405 | q->toplevel = TC_CBQ_MAXLEVEL; |
1403 | q->now = psched_get_time(); | 1406 | q->now = psched_get_time(); |
diff --git a/net/sched/sch_drr.c b/net/sched/sch_drr.c index 7597fe146866..12b2fb04b29b 100644 --- a/net/sched/sch_drr.c +++ b/net/sched/sch_drr.c | |||
@@ -22,7 +22,7 @@ struct drr_class { | |||
22 | unsigned int refcnt; | 22 | unsigned int refcnt; |
23 | unsigned int filter_cnt; | 23 | unsigned int filter_cnt; |
24 | 24 | ||
25 | struct gnet_stats_basic bstats; | 25 | struct gnet_stats_basic_packed bstats; |
26 | struct gnet_stats_queue qstats; | 26 | struct gnet_stats_queue qstats; |
27 | struct gnet_stats_rate_est rate_est; | 27 | struct gnet_stats_rate_est rate_est; |
28 | struct list_head alist; | 28 | struct list_head alist; |
diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c index 362c2811b2df..dad0144423da 100644 --- a/net/sched/sch_hfsc.c +++ b/net/sched/sch_hfsc.c | |||
@@ -116,7 +116,7 @@ struct hfsc_class | |||
116 | struct Qdisc_class_common cl_common; | 116 | struct Qdisc_class_common cl_common; |
117 | unsigned int refcnt; /* usage count */ | 117 | unsigned int refcnt; /* usage count */ |
118 | 118 | ||
119 | struct gnet_stats_basic bstats; | 119 | struct gnet_stats_basic_packed bstats; |
120 | struct gnet_stats_queue qstats; | 120 | struct gnet_stats_queue qstats; |
121 | struct gnet_stats_rate_est rate_est; | 121 | struct gnet_stats_rate_est rate_est; |
122 | unsigned int level; /* class level in hierarchy */ | 122 | unsigned int level; /* class level in hierarchy */ |
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c index 88cd02626621..ec4d46399d59 100644 --- a/net/sched/sch_htb.c +++ b/net/sched/sch_htb.c | |||
@@ -74,7 +74,7 @@ enum htb_cmode { | |||
74 | struct htb_class { | 74 | struct htb_class { |
75 | struct Qdisc_class_common common; | 75 | struct Qdisc_class_common common; |
76 | /* general class parameters */ | 76 | /* general class parameters */ |
77 | struct gnet_stats_basic bstats; | 77 | struct gnet_stats_basic_packed bstats; |
78 | struct gnet_stats_queue qstats; | 78 | struct gnet_stats_queue qstats; |
79 | struct gnet_stats_rate_est rate_est; | 79 | struct gnet_stats_rate_est rate_est; |
80 | struct tc_htb_xstats xstats; /* our special stats */ | 80 | struct tc_htb_xstats xstats; /* our special stats */ |
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index a63de3f7f185..6a4b19094143 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c | |||
@@ -133,7 +133,7 @@ static struct notifier_block sctp_inet6addr_notifier = { | |||
133 | 133 | ||
134 | /* ICMP error handler. */ | 134 | /* ICMP error handler. */ |
135 | SCTP_STATIC void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | 135 | SCTP_STATIC void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, |
136 | int type, int code, int offset, __be32 info) | 136 | u8 type, u8 code, int offset, __be32 info) |
137 | { | 137 | { |
138 | struct inet6_dev *idev; | 138 | struct inet6_dev *idev; |
139 | struct sock *sk; | 139 | struct sock *sk; |
diff --git a/net/sctp/output.c b/net/sctp/output.c index b76411444515..b94c21190566 100644 --- a/net/sctp/output.c +++ b/net/sctp/output.c | |||
@@ -407,7 +407,7 @@ int sctp_packet_transmit(struct sctp_packet *packet) | |||
407 | } | 407 | } |
408 | dst = dst_clone(tp->dst); | 408 | dst = dst_clone(tp->dst); |
409 | skb_dst_set(nskb, dst); | 409 | skb_dst_set(nskb, dst); |
410 | if (dst) | 410 | if (!dst) |
411 | goto no_route; | 411 | goto no_route; |
412 | 412 | ||
413 | /* Build the SCTP header. */ | 413 | /* Build the SCTP header. */ |
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 79cbd47f4df7..a76da657244a 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c | |||
@@ -160,6 +160,7 @@ static void sctp_proc_exit(void) | |||
160 | remove_proc_entry("sctp", init_net.proc_net); | 160 | remove_proc_entry("sctp", init_net.proc_net); |
161 | } | 161 | } |
162 | #endif | 162 | #endif |
163 | percpu_counter_destroy(&sctp_sockets_allocated); | ||
163 | } | 164 | } |
164 | 165 | ||
165 | /* Private helper to extract ipv4 address and stash them in | 166 | /* Private helper to extract ipv4 address and stash them in |
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 0f01e5d8a24f..971890dbfea0 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -130,7 +130,7 @@ static inline int sctp_wspace(struct sctp_association *asoc) | |||
130 | if (asoc->ep->sndbuf_policy) | 130 | if (asoc->ep->sndbuf_policy) |
131 | amt = asoc->sndbuf_used; | 131 | amt = asoc->sndbuf_used; |
132 | else | 132 | else |
133 | amt = atomic_read(&asoc->base.sk->sk_wmem_alloc); | 133 | amt = sk_wmem_alloc_get(asoc->base.sk); |
134 | 134 | ||
135 | if (amt >= asoc->base.sk->sk_sndbuf) { | 135 | if (amt >= asoc->base.sk->sk_sndbuf) { |
136 | if (asoc->base.sk->sk_userlocks & SOCK_SNDBUF_LOCK) | 136 | if (asoc->base.sk->sk_userlocks & SOCK_SNDBUF_LOCK) |
@@ -6523,7 +6523,7 @@ static int sctp_writeable(struct sock *sk) | |||
6523 | { | 6523 | { |
6524 | int amt = 0; | 6524 | int amt = 0; |
6525 | 6525 | ||
6526 | amt = sk->sk_sndbuf - atomic_read(&sk->sk_wmem_alloc); | 6526 | amt = sk->sk_sndbuf - sk_wmem_alloc_get(sk); |
6527 | if (amt < 0) | 6527 | if (amt < 0) |
6528 | amt = 0; | 6528 | amt = 0; |
6529 | return amt; | 6529 | return amt; |
@@ -6652,21 +6652,6 @@ static void sctp_wait_for_close(struct sock *sk, long timeout) | |||
6652 | finish_wait(sk->sk_sleep, &wait); | 6652 | finish_wait(sk->sk_sleep, &wait); |
6653 | } | 6653 | } |
6654 | 6654 | ||
6655 | static void sctp_sock_rfree_frag(struct sk_buff *skb) | ||
6656 | { | ||
6657 | struct sk_buff *frag; | ||
6658 | |||
6659 | if (!skb->data_len) | ||
6660 | goto done; | ||
6661 | |||
6662 | /* Don't forget the fragments. */ | ||
6663 | skb_walk_frags(skb, frag) | ||
6664 | sctp_sock_rfree_frag(frag); | ||
6665 | |||
6666 | done: | ||
6667 | sctp_sock_rfree(skb); | ||
6668 | } | ||
6669 | |||
6670 | static void sctp_skb_set_owner_r_frag(struct sk_buff *skb, struct sock *sk) | 6655 | static void sctp_skb_set_owner_r_frag(struct sk_buff *skb, struct sock *sk) |
6671 | { | 6656 | { |
6672 | struct sk_buff *frag; | 6657 | struct sk_buff *frag; |
@@ -6776,7 +6761,6 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk, | |||
6776 | sctp_skb_for_each(skb, &oldsk->sk_receive_queue, tmp) { | 6761 | sctp_skb_for_each(skb, &oldsk->sk_receive_queue, tmp) { |
6777 | event = sctp_skb2event(skb); | 6762 | event = sctp_skb2event(skb); |
6778 | if (event->asoc == assoc) { | 6763 | if (event->asoc == assoc) { |
6779 | sctp_sock_rfree_frag(skb); | ||
6780 | __skb_unlink(skb, &oldsk->sk_receive_queue); | 6764 | __skb_unlink(skb, &oldsk->sk_receive_queue); |
6781 | __skb_queue_tail(&newsk->sk_receive_queue, skb); | 6765 | __skb_queue_tail(&newsk->sk_receive_queue, skb); |
6782 | sctp_skb_set_owner_r_frag(skb, newsk); | 6766 | sctp_skb_set_owner_r_frag(skb, newsk); |
@@ -6807,7 +6791,6 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk, | |||
6807 | sctp_skb_for_each(skb, &oldsp->pd_lobby, tmp) { | 6791 | sctp_skb_for_each(skb, &oldsp->pd_lobby, tmp) { |
6808 | event = sctp_skb2event(skb); | 6792 | event = sctp_skb2event(skb); |
6809 | if (event->asoc == assoc) { | 6793 | if (event->asoc == assoc) { |
6810 | sctp_sock_rfree_frag(skb); | ||
6811 | __skb_unlink(skb, &oldsp->pd_lobby); | 6794 | __skb_unlink(skb, &oldsp->pd_lobby); |
6812 | __skb_queue_tail(queue, skb); | 6795 | __skb_queue_tail(queue, skb); |
6813 | sctp_skb_set_owner_r_frag(skb, newsk); | 6796 | sctp_skb_set_owner_r_frag(skb, newsk); |
@@ -6822,15 +6805,11 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk, | |||
6822 | 6805 | ||
6823 | } | 6806 | } |
6824 | 6807 | ||
6825 | sctp_skb_for_each(skb, &assoc->ulpq.reasm, tmp) { | 6808 | sctp_skb_for_each(skb, &assoc->ulpq.reasm, tmp) |
6826 | sctp_sock_rfree_frag(skb); | ||
6827 | sctp_skb_set_owner_r_frag(skb, newsk); | 6809 | sctp_skb_set_owner_r_frag(skb, newsk); |
6828 | } | ||
6829 | 6810 | ||
6830 | sctp_skb_for_each(skb, &assoc->ulpq.lobby, tmp) { | 6811 | sctp_skb_for_each(skb, &assoc->ulpq.lobby, tmp) |
6831 | sctp_sock_rfree_frag(skb); | ||
6832 | sctp_skb_set_owner_r_frag(skb, newsk); | 6812 | sctp_skb_set_owner_r_frag(skb, newsk); |
6833 | } | ||
6834 | 6813 | ||
6835 | /* Set the type of socket to indicate that it is peeled off from the | 6814 | /* Set the type of socket to indicate that it is peeled off from the |
6836 | * original UDP-style socket or created with the accept() call on a | 6815 | * original UDP-style socket or created with the accept() call on a |
diff --git a/net/socket.c b/net/socket.c index 791d71a36a93..6d4716559047 100644 --- a/net/socket.c +++ b/net/socket.c | |||
@@ -736,7 +736,7 @@ static ssize_t sock_sendpage(struct file *file, struct page *page, | |||
736 | if (more) | 736 | if (more) |
737 | flags |= MSG_MORE; | 737 | flags |= MSG_MORE; |
738 | 738 | ||
739 | return sock->ops->sendpage(sock, page, offset, size, flags); | 739 | return kernel_sendpage(sock, page, offset, size, flags); |
740 | } | 740 | } |
741 | 741 | ||
742 | static ssize_t sock_splice_read(struct file *file, loff_t *ppos, | 742 | static ssize_t sock_splice_read(struct file *file, loff_t *ppos, |
diff --git a/net/sunrpc/Makefile b/net/sunrpc/Makefile index 5369aa369b35..db73fd2a3f0e 100644 --- a/net/sunrpc/Makefile +++ b/net/sunrpc/Makefile | |||
@@ -13,5 +13,6 @@ sunrpc-y := clnt.o xprt.o socklib.o xprtsock.o sched.o \ | |||
13 | rpcb_clnt.o timer.o xdr.o \ | 13 | rpcb_clnt.o timer.o xdr.o \ |
14 | sunrpc_syms.o cache.o rpc_pipe.o \ | 14 | sunrpc_syms.o cache.o rpc_pipe.o \ |
15 | svc_xprt.o | 15 | svc_xprt.o |
16 | sunrpc-$(CONFIG_NFS_V4_1) += backchannel_rqst.o bc_svc.o | ||
16 | sunrpc-$(CONFIG_PROC_FS) += stats.o | 17 | sunrpc-$(CONFIG_PROC_FS) += stats.o |
17 | sunrpc-$(CONFIG_SYSCTL) += sysctl.o | 18 | sunrpc-$(CONFIG_SYSCTL) += sysctl.o |
diff --git a/net/sunrpc/backchannel_rqst.c b/net/sunrpc/backchannel_rqst.c new file mode 100644 index 000000000000..553621fb2c41 --- /dev/null +++ b/net/sunrpc/backchannel_rqst.c | |||
@@ -0,0 +1,281 @@ | |||
1 | /****************************************************************************** | ||
2 | |||
3 | (c) 2007 Network Appliance, Inc. All Rights Reserved. | ||
4 | (c) 2009 NetApp. All Rights Reserved. | ||
5 | |||
6 | NetApp provides this source code under the GPL v2 License. | ||
7 | The GPL v2 license is available at | ||
8 | http://opensource.org/licenses/gpl-license.php. | ||
9 | |||
10 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
11 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
12 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
13 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | ||
14 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | ||
15 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | ||
16 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | ||
17 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||
18 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||
19 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
20 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
21 | |||
22 | ******************************************************************************/ | ||
23 | |||
24 | #include <linux/tcp.h> | ||
25 | #include <linux/sunrpc/xprt.h> | ||
26 | |||
27 | #ifdef RPC_DEBUG | ||
28 | #define RPCDBG_FACILITY RPCDBG_TRANS | ||
29 | #endif | ||
30 | |||
31 | #if defined(CONFIG_NFS_V4_1) | ||
32 | |||
33 | /* | ||
34 | * Helper routines that track the number of preallocation elements | ||
35 | * on the transport. | ||
36 | */ | ||
37 | static inline int xprt_need_to_requeue(struct rpc_xprt *xprt) | ||
38 | { | ||
39 | return xprt->bc_alloc_count > 0; | ||
40 | } | ||
41 | |||
42 | static inline void xprt_inc_alloc_count(struct rpc_xprt *xprt, unsigned int n) | ||
43 | { | ||
44 | xprt->bc_alloc_count += n; | ||
45 | } | ||
46 | |||
47 | static inline int xprt_dec_alloc_count(struct rpc_xprt *xprt, unsigned int n) | ||
48 | { | ||
49 | return xprt->bc_alloc_count -= n; | ||
50 | } | ||
51 | |||
52 | /* | ||
53 | * Free the preallocated rpc_rqst structure and the memory | ||
54 | * buffers hanging off of it. | ||
55 | */ | ||
56 | static void xprt_free_allocation(struct rpc_rqst *req) | ||
57 | { | ||
58 | struct xdr_buf *xbufp; | ||
59 | |||
60 | dprintk("RPC: free allocations for req= %p\n", req); | ||
61 | BUG_ON(test_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state)); | ||
62 | xbufp = &req->rq_private_buf; | ||
63 | free_page((unsigned long)xbufp->head[0].iov_base); | ||
64 | xbufp = &req->rq_snd_buf; | ||
65 | free_page((unsigned long)xbufp->head[0].iov_base); | ||
66 | list_del(&req->rq_bc_pa_list); | ||
67 | kfree(req); | ||
68 | } | ||
69 | |||
70 | /* | ||
71 | * Preallocate up to min_reqs structures and related buffers for use | ||
72 | * by the backchannel. This function can be called multiple times | ||
73 | * when creating new sessions that use the same rpc_xprt. The | ||
74 | * preallocated buffers are added to the pool of resources used by | ||
75 | * the rpc_xprt. Anyone of these resources may be used used by an | ||
76 | * incoming callback request. It's up to the higher levels in the | ||
77 | * stack to enforce that the maximum number of session slots is not | ||
78 | * being exceeded. | ||
79 | * | ||
80 | * Some callback arguments can be large. For example, a pNFS server | ||
81 | * using multiple deviceids. The list can be unbound, but the client | ||
82 | * has the ability to tell the server the maximum size of the callback | ||
83 | * requests. Each deviceID is 16 bytes, so allocate one page | ||
84 | * for the arguments to have enough room to receive a number of these | ||
85 | * deviceIDs. The NFS client indicates to the pNFS server that its | ||
86 | * callback requests can be up to 4096 bytes in size. | ||
87 | */ | ||
88 | int xprt_setup_backchannel(struct rpc_xprt *xprt, unsigned int min_reqs) | ||
89 | { | ||
90 | struct page *page_rcv = NULL, *page_snd = NULL; | ||
91 | struct xdr_buf *xbufp = NULL; | ||
92 | struct rpc_rqst *req, *tmp; | ||
93 | struct list_head tmp_list; | ||
94 | int i; | ||
95 | |||
96 | dprintk("RPC: setup backchannel transport\n"); | ||
97 | |||
98 | /* | ||
99 | * We use a temporary list to keep track of the preallocated | ||
100 | * buffers. Once we're done building the list we splice it | ||
101 | * into the backchannel preallocation list off of the rpc_xprt | ||
102 | * struct. This helps minimize the amount of time the list | ||
103 | * lock is held on the rpc_xprt struct. It also makes cleanup | ||
104 | * easier in case of memory allocation errors. | ||
105 | */ | ||
106 | INIT_LIST_HEAD(&tmp_list); | ||
107 | for (i = 0; i < min_reqs; i++) { | ||
108 | /* Pre-allocate one backchannel rpc_rqst */ | ||
109 | req = kzalloc(sizeof(struct rpc_rqst), GFP_KERNEL); | ||
110 | if (req == NULL) { | ||
111 | printk(KERN_ERR "Failed to create bc rpc_rqst\n"); | ||
112 | goto out_free; | ||
113 | } | ||
114 | |||
115 | /* Add the allocated buffer to the tmp list */ | ||
116 | dprintk("RPC: adding req= %p\n", req); | ||
117 | list_add(&req->rq_bc_pa_list, &tmp_list); | ||
118 | |||
119 | req->rq_xprt = xprt; | ||
120 | INIT_LIST_HEAD(&req->rq_list); | ||
121 | INIT_LIST_HEAD(&req->rq_bc_list); | ||
122 | |||
123 | /* Preallocate one XDR receive buffer */ | ||
124 | page_rcv = alloc_page(GFP_KERNEL); | ||
125 | if (page_rcv == NULL) { | ||
126 | printk(KERN_ERR "Failed to create bc receive xbuf\n"); | ||
127 | goto out_free; | ||
128 | } | ||
129 | xbufp = &req->rq_rcv_buf; | ||
130 | xbufp->head[0].iov_base = page_address(page_rcv); | ||
131 | xbufp->head[0].iov_len = PAGE_SIZE; | ||
132 | xbufp->tail[0].iov_base = NULL; | ||
133 | xbufp->tail[0].iov_len = 0; | ||
134 | xbufp->page_len = 0; | ||
135 | xbufp->len = PAGE_SIZE; | ||
136 | xbufp->buflen = PAGE_SIZE; | ||
137 | |||
138 | /* Preallocate one XDR send buffer */ | ||
139 | page_snd = alloc_page(GFP_KERNEL); | ||
140 | if (page_snd == NULL) { | ||
141 | printk(KERN_ERR "Failed to create bc snd xbuf\n"); | ||
142 | goto out_free; | ||
143 | } | ||
144 | |||
145 | xbufp = &req->rq_snd_buf; | ||
146 | xbufp->head[0].iov_base = page_address(page_snd); | ||
147 | xbufp->head[0].iov_len = 0; | ||
148 | xbufp->tail[0].iov_base = NULL; | ||
149 | xbufp->tail[0].iov_len = 0; | ||
150 | xbufp->page_len = 0; | ||
151 | xbufp->len = 0; | ||
152 | xbufp->buflen = PAGE_SIZE; | ||
153 | } | ||
154 | |||
155 | /* | ||
156 | * Add the temporary list to the backchannel preallocation list | ||
157 | */ | ||
158 | spin_lock_bh(&xprt->bc_pa_lock); | ||
159 | list_splice(&tmp_list, &xprt->bc_pa_list); | ||
160 | xprt_inc_alloc_count(xprt, min_reqs); | ||
161 | spin_unlock_bh(&xprt->bc_pa_lock); | ||
162 | |||
163 | dprintk("RPC: setup backchannel transport done\n"); | ||
164 | return 0; | ||
165 | |||
166 | out_free: | ||
167 | /* | ||
168 | * Memory allocation failed, free the temporary list | ||
169 | */ | ||
170 | list_for_each_entry_safe(req, tmp, &tmp_list, rq_bc_pa_list) | ||
171 | xprt_free_allocation(req); | ||
172 | |||
173 | dprintk("RPC: setup backchannel transport failed\n"); | ||
174 | return -1; | ||
175 | } | ||
176 | EXPORT_SYMBOL(xprt_setup_backchannel); | ||
177 | |||
178 | /* | ||
179 | * Destroys the backchannel preallocated structures. | ||
180 | * Since these structures may have been allocated by multiple calls | ||
181 | * to xprt_setup_backchannel, we only destroy up to the maximum number | ||
182 | * of reqs specified by the caller. | ||
183 | * @xprt: the transport holding the preallocated strucures | ||
184 | * @max_reqs the maximum number of preallocated structures to destroy | ||
185 | */ | ||
186 | void xprt_destroy_backchannel(struct rpc_xprt *xprt, unsigned int max_reqs) | ||
187 | { | ||
188 | struct rpc_rqst *req = NULL, *tmp = NULL; | ||
189 | |||
190 | dprintk("RPC: destroy backchannel transport\n"); | ||
191 | |||
192 | BUG_ON(max_reqs == 0); | ||
193 | spin_lock_bh(&xprt->bc_pa_lock); | ||
194 | xprt_dec_alloc_count(xprt, max_reqs); | ||
195 | list_for_each_entry_safe(req, tmp, &xprt->bc_pa_list, rq_bc_pa_list) { | ||
196 | dprintk("RPC: req=%p\n", req); | ||
197 | xprt_free_allocation(req); | ||
198 | if (--max_reqs == 0) | ||
199 | break; | ||
200 | } | ||
201 | spin_unlock_bh(&xprt->bc_pa_lock); | ||
202 | |||
203 | dprintk("RPC: backchannel list empty= %s\n", | ||
204 | list_empty(&xprt->bc_pa_list) ? "true" : "false"); | ||
205 | } | ||
206 | EXPORT_SYMBOL(xprt_destroy_backchannel); | ||
207 | |||
208 | /* | ||
209 | * One or more rpc_rqst structure have been preallocated during the | ||
210 | * backchannel setup. Buffer space for the send and private XDR buffers | ||
211 | * has been preallocated as well. Use xprt_alloc_bc_request to allocate | ||
212 | * to this request. Use xprt_free_bc_request to return it. | ||
213 | * | ||
214 | * We know that we're called in soft interrupt context, grab the spin_lock | ||
215 | * since there is no need to grab the bottom half spin_lock. | ||
216 | * | ||
217 | * Return an available rpc_rqst, otherwise NULL if non are available. | ||
218 | */ | ||
219 | struct rpc_rqst *xprt_alloc_bc_request(struct rpc_xprt *xprt) | ||
220 | { | ||
221 | struct rpc_rqst *req; | ||
222 | |||
223 | dprintk("RPC: allocate a backchannel request\n"); | ||
224 | spin_lock(&xprt->bc_pa_lock); | ||
225 | if (!list_empty(&xprt->bc_pa_list)) { | ||
226 | req = list_first_entry(&xprt->bc_pa_list, struct rpc_rqst, | ||
227 | rq_bc_pa_list); | ||
228 | list_del(&req->rq_bc_pa_list); | ||
229 | } else { | ||
230 | req = NULL; | ||
231 | } | ||
232 | spin_unlock(&xprt->bc_pa_lock); | ||
233 | |||
234 | if (req != NULL) { | ||
235 | set_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state); | ||
236 | req->rq_reply_bytes_recvd = 0; | ||
237 | req->rq_bytes_sent = 0; | ||
238 | memcpy(&req->rq_private_buf, &req->rq_rcv_buf, | ||
239 | sizeof(req->rq_private_buf)); | ||
240 | } | ||
241 | dprintk("RPC: backchannel req=%p\n", req); | ||
242 | return req; | ||
243 | } | ||
244 | |||
245 | /* | ||
246 | * Return the preallocated rpc_rqst structure and XDR buffers | ||
247 | * associated with this rpc_task. | ||
248 | */ | ||
249 | void xprt_free_bc_request(struct rpc_rqst *req) | ||
250 | { | ||
251 | struct rpc_xprt *xprt = req->rq_xprt; | ||
252 | |||
253 | dprintk("RPC: free backchannel req=%p\n", req); | ||
254 | |||
255 | smp_mb__before_clear_bit(); | ||
256 | BUG_ON(!test_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state)); | ||
257 | clear_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state); | ||
258 | smp_mb__after_clear_bit(); | ||
259 | |||
260 | if (!xprt_need_to_requeue(xprt)) { | ||
261 | /* | ||
262 | * The last remaining session was destroyed while this | ||
263 | * entry was in use. Free the entry and don't attempt | ||
264 | * to add back to the list because there is no need to | ||
265 | * have anymore preallocated entries. | ||
266 | */ | ||
267 | dprintk("RPC: Last session removed req=%p\n", req); | ||
268 | xprt_free_allocation(req); | ||
269 | return; | ||
270 | } | ||
271 | |||
272 | /* | ||
273 | * Return it to the list of preallocations so that it | ||
274 | * may be reused by a new callback request. | ||
275 | */ | ||
276 | spin_lock_bh(&xprt->bc_pa_lock); | ||
277 | list_add(&req->rq_bc_pa_list, &xprt->bc_pa_list); | ||
278 | spin_unlock_bh(&xprt->bc_pa_lock); | ||
279 | } | ||
280 | |||
281 | #endif /* CONFIG_NFS_V4_1 */ | ||
diff --git a/net/sunrpc/bc_svc.c b/net/sunrpc/bc_svc.c new file mode 100644 index 000000000000..13f214f53120 --- /dev/null +++ b/net/sunrpc/bc_svc.c | |||
@@ -0,0 +1,81 @@ | |||
1 | /****************************************************************************** | ||
2 | |||
3 | (c) 2007 Network Appliance, Inc. All Rights Reserved. | ||
4 | (c) 2009 NetApp. All Rights Reserved. | ||
5 | |||
6 | NetApp provides this source code under the GPL v2 License. | ||
7 | The GPL v2 license is available at | ||
8 | http://opensource.org/licenses/gpl-license.php. | ||
9 | |||
10 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
11 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
12 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
13 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | ||
14 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | ||
15 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | ||
16 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | ||
17 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||
18 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||
19 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
20 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
21 | |||
22 | ******************************************************************************/ | ||
23 | |||
24 | /* | ||
25 | * The NFSv4.1 callback service helper routines. | ||
26 | * They implement the transport level processing required to send the | ||
27 | * reply over an existing open connection previously established by the client. | ||
28 | */ | ||
29 | |||
30 | #if defined(CONFIG_NFS_V4_1) | ||
31 | |||
32 | #include <linux/module.h> | ||
33 | |||
34 | #include <linux/sunrpc/xprt.h> | ||
35 | #include <linux/sunrpc/sched.h> | ||
36 | #include <linux/sunrpc/bc_xprt.h> | ||
37 | |||
38 | #define RPCDBG_FACILITY RPCDBG_SVCDSP | ||
39 | |||
40 | void bc_release_request(struct rpc_task *task) | ||
41 | { | ||
42 | struct rpc_rqst *req = task->tk_rqstp; | ||
43 | |||
44 | dprintk("RPC: bc_release_request: task= %p\n", task); | ||
45 | |||
46 | /* | ||
47 | * Release this request only if it's a backchannel | ||
48 | * preallocated request | ||
49 | */ | ||
50 | if (!bc_prealloc(req)) | ||
51 | return; | ||
52 | xprt_free_bc_request(req); | ||
53 | } | ||
54 | |||
55 | /* Empty callback ops */ | ||
56 | static const struct rpc_call_ops nfs41_callback_ops = { | ||
57 | }; | ||
58 | |||
59 | |||
60 | /* | ||
61 | * Send the callback reply | ||
62 | */ | ||
63 | int bc_send(struct rpc_rqst *req) | ||
64 | { | ||
65 | struct rpc_task *task; | ||
66 | int ret; | ||
67 | |||
68 | dprintk("RPC: bc_send req= %p\n", req); | ||
69 | task = rpc_run_bc_task(req, &nfs41_callback_ops); | ||
70 | if (IS_ERR(task)) | ||
71 | ret = PTR_ERR(task); | ||
72 | else { | ||
73 | BUG_ON(atomic_read(&task->tk_count) != 1); | ||
74 | ret = task->tk_status; | ||
75 | rpc_put_task(task); | ||
76 | } | ||
77 | return ret; | ||
78 | dprintk("RPC: bc_send ret= %d \n", ret); | ||
79 | } | ||
80 | |||
81 | #endif /* CONFIG_NFS_V4_1 */ | ||
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index 20029a79a5de..ff0c23053d2f 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c | |||
@@ -488,7 +488,7 @@ static void do_cache_clean(struct work_struct *work) | |||
488 | { | 488 | { |
489 | int delay = 5; | 489 | int delay = 5; |
490 | if (cache_clean() == -1) | 490 | if (cache_clean() == -1) |
491 | delay = 30*HZ; | 491 | delay = round_jiffies_relative(30*HZ); |
492 | 492 | ||
493 | if (list_empty(&cache_list)) | 493 | if (list_empty(&cache_list)) |
494 | delay = 0; | 494 | delay = 0; |
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 5abab094441f..df1039f077c2 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
@@ -28,7 +28,6 @@ | |||
28 | #include <linux/kallsyms.h> | 28 | #include <linux/kallsyms.h> |
29 | #include <linux/mm.h> | 29 | #include <linux/mm.h> |
30 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
31 | #include <linux/smp_lock.h> | ||
32 | #include <linux/utsname.h> | 31 | #include <linux/utsname.h> |
33 | #include <linux/workqueue.h> | 32 | #include <linux/workqueue.h> |
34 | #include <linux/in6.h> | 33 | #include <linux/in6.h> |
@@ -36,7 +35,9 @@ | |||
36 | #include <linux/sunrpc/clnt.h> | 35 | #include <linux/sunrpc/clnt.h> |
37 | #include <linux/sunrpc/rpc_pipe_fs.h> | 36 | #include <linux/sunrpc/rpc_pipe_fs.h> |
38 | #include <linux/sunrpc/metrics.h> | 37 | #include <linux/sunrpc/metrics.h> |
38 | #include <linux/sunrpc/bc_xprt.h> | ||
39 | 39 | ||
40 | #include "sunrpc.h" | ||
40 | 41 | ||
41 | #ifdef RPC_DEBUG | 42 | #ifdef RPC_DEBUG |
42 | # define RPCDBG_FACILITY RPCDBG_CALL | 43 | # define RPCDBG_FACILITY RPCDBG_CALL |
@@ -63,6 +64,9 @@ static void call_decode(struct rpc_task *task); | |||
63 | static void call_bind(struct rpc_task *task); | 64 | static void call_bind(struct rpc_task *task); |
64 | static void call_bind_status(struct rpc_task *task); | 65 | static void call_bind_status(struct rpc_task *task); |
65 | static void call_transmit(struct rpc_task *task); | 66 | static void call_transmit(struct rpc_task *task); |
67 | #if defined(CONFIG_NFS_V4_1) | ||
68 | static void call_bc_transmit(struct rpc_task *task); | ||
69 | #endif /* CONFIG_NFS_V4_1 */ | ||
66 | static void call_status(struct rpc_task *task); | 70 | static void call_status(struct rpc_task *task); |
67 | static void call_transmit_status(struct rpc_task *task); | 71 | static void call_transmit_status(struct rpc_task *task); |
68 | static void call_refresh(struct rpc_task *task); | 72 | static void call_refresh(struct rpc_task *task); |
@@ -613,6 +617,50 @@ rpc_call_async(struct rpc_clnt *clnt, const struct rpc_message *msg, int flags, | |||
613 | } | 617 | } |
614 | EXPORT_SYMBOL_GPL(rpc_call_async); | 618 | EXPORT_SYMBOL_GPL(rpc_call_async); |
615 | 619 | ||
620 | #if defined(CONFIG_NFS_V4_1) | ||
621 | /** | ||
622 | * rpc_run_bc_task - Allocate a new RPC task for backchannel use, then run | ||
623 | * rpc_execute against it | ||
624 | * @ops: RPC call ops | ||
625 | */ | ||
626 | struct rpc_task *rpc_run_bc_task(struct rpc_rqst *req, | ||
627 | const struct rpc_call_ops *tk_ops) | ||
628 | { | ||
629 | struct rpc_task *task; | ||
630 | struct xdr_buf *xbufp = &req->rq_snd_buf; | ||
631 | struct rpc_task_setup task_setup_data = { | ||
632 | .callback_ops = tk_ops, | ||
633 | }; | ||
634 | |||
635 | dprintk("RPC: rpc_run_bc_task req= %p\n", req); | ||
636 | /* | ||
637 | * Create an rpc_task to send the data | ||
638 | */ | ||
639 | task = rpc_new_task(&task_setup_data); | ||
640 | if (!task) { | ||
641 | xprt_free_bc_request(req); | ||
642 | goto out; | ||
643 | } | ||
644 | task->tk_rqstp = req; | ||
645 | |||
646 | /* | ||
647 | * Set up the xdr_buf length. | ||
648 | * This also indicates that the buffer is XDR encoded already. | ||
649 | */ | ||
650 | xbufp->len = xbufp->head[0].iov_len + xbufp->page_len + | ||
651 | xbufp->tail[0].iov_len; | ||
652 | |||
653 | task->tk_action = call_bc_transmit; | ||
654 | atomic_inc(&task->tk_count); | ||
655 | BUG_ON(atomic_read(&task->tk_count) != 2); | ||
656 | rpc_execute(task); | ||
657 | |||
658 | out: | ||
659 | dprintk("RPC: rpc_run_bc_task: task= %p\n", task); | ||
660 | return task; | ||
661 | } | ||
662 | #endif /* CONFIG_NFS_V4_1 */ | ||
663 | |||
616 | void | 664 | void |
617 | rpc_call_start(struct rpc_task *task) | 665 | rpc_call_start(struct rpc_task *task) |
618 | { | 666 | { |
@@ -695,6 +743,19 @@ void rpc_force_rebind(struct rpc_clnt *clnt) | |||
695 | EXPORT_SYMBOL_GPL(rpc_force_rebind); | 743 | EXPORT_SYMBOL_GPL(rpc_force_rebind); |
696 | 744 | ||
697 | /* | 745 | /* |
746 | * Restart an (async) RPC call from the call_prepare state. | ||
747 | * Usually called from within the exit handler. | ||
748 | */ | ||
749 | void | ||
750 | rpc_restart_call_prepare(struct rpc_task *task) | ||
751 | { | ||
752 | if (RPC_ASSASSINATED(task)) | ||
753 | return; | ||
754 | task->tk_action = rpc_prepare_task; | ||
755 | } | ||
756 | EXPORT_SYMBOL_GPL(rpc_restart_call_prepare); | ||
757 | |||
758 | /* | ||
698 | * Restart an (async) RPC call. Usually called from within the | 759 | * Restart an (async) RPC call. Usually called from within the |
699 | * exit handler. | 760 | * exit handler. |
700 | */ | 761 | */ |
@@ -876,6 +937,7 @@ static inline void | |||
876 | rpc_task_force_reencode(struct rpc_task *task) | 937 | rpc_task_force_reencode(struct rpc_task *task) |
877 | { | 938 | { |
878 | task->tk_rqstp->rq_snd_buf.len = 0; | 939 | task->tk_rqstp->rq_snd_buf.len = 0; |
940 | task->tk_rqstp->rq_bytes_sent = 0; | ||
879 | } | 941 | } |
880 | 942 | ||
881 | static inline void | 943 | static inline void |
@@ -1085,7 +1147,7 @@ call_transmit(struct rpc_task *task) | |||
1085 | * in order to allow access to the socket to other RPC requests. | 1147 | * in order to allow access to the socket to other RPC requests. |
1086 | */ | 1148 | */ |
1087 | call_transmit_status(task); | 1149 | call_transmit_status(task); |
1088 | if (task->tk_msg.rpc_proc->p_decode != NULL) | 1150 | if (rpc_reply_expected(task)) |
1089 | return; | 1151 | return; |
1090 | task->tk_action = rpc_exit_task; | 1152 | task->tk_action = rpc_exit_task; |
1091 | rpc_wake_up_queued_task(&task->tk_xprt->pending, task); | 1153 | rpc_wake_up_queued_task(&task->tk_xprt->pending, task); |
@@ -1120,6 +1182,72 @@ call_transmit_status(struct rpc_task *task) | |||
1120 | } | 1182 | } |
1121 | } | 1183 | } |
1122 | 1184 | ||
1185 | #if defined(CONFIG_NFS_V4_1) | ||
1186 | /* | ||
1187 | * 5b. Send the backchannel RPC reply. On error, drop the reply. In | ||
1188 | * addition, disconnect on connectivity errors. | ||
1189 | */ | ||
1190 | static void | ||
1191 | call_bc_transmit(struct rpc_task *task) | ||
1192 | { | ||
1193 | struct rpc_rqst *req = task->tk_rqstp; | ||
1194 | |||
1195 | BUG_ON(task->tk_status != 0); | ||
1196 | task->tk_status = xprt_prepare_transmit(task); | ||
1197 | if (task->tk_status == -EAGAIN) { | ||
1198 | /* | ||
1199 | * Could not reserve the transport. Try again after the | ||
1200 | * transport is released. | ||
1201 | */ | ||
1202 | task->tk_status = 0; | ||
1203 | task->tk_action = call_bc_transmit; | ||
1204 | return; | ||
1205 | } | ||
1206 | |||
1207 | task->tk_action = rpc_exit_task; | ||
1208 | if (task->tk_status < 0) { | ||
1209 | printk(KERN_NOTICE "RPC: Could not send backchannel reply " | ||
1210 | "error: %d\n", task->tk_status); | ||
1211 | return; | ||
1212 | } | ||
1213 | |||
1214 | xprt_transmit(task); | ||
1215 | xprt_end_transmit(task); | ||
1216 | dprint_status(task); | ||
1217 | switch (task->tk_status) { | ||
1218 | case 0: | ||
1219 | /* Success */ | ||
1220 | break; | ||
1221 | case -EHOSTDOWN: | ||
1222 | case -EHOSTUNREACH: | ||
1223 | case -ENETUNREACH: | ||
1224 | case -ETIMEDOUT: | ||
1225 | /* | ||
1226 | * Problem reaching the server. Disconnect and let the | ||
1227 | * forechannel reestablish the connection. The server will | ||
1228 | * have to retransmit the backchannel request and we'll | ||
1229 | * reprocess it. Since these ops are idempotent, there's no | ||
1230 | * need to cache our reply at this time. | ||
1231 | */ | ||
1232 | printk(KERN_NOTICE "RPC: Could not send backchannel reply " | ||
1233 | "error: %d\n", task->tk_status); | ||
1234 | xprt_conditional_disconnect(task->tk_xprt, | ||
1235 | req->rq_connect_cookie); | ||
1236 | break; | ||
1237 | default: | ||
1238 | /* | ||
1239 | * We were unable to reply and will have to drop the | ||
1240 | * request. The server should reconnect and retransmit. | ||
1241 | */ | ||
1242 | BUG_ON(task->tk_status == -EAGAIN); | ||
1243 | printk(KERN_NOTICE "RPC: Could not send backchannel reply " | ||
1244 | "error: %d\n", task->tk_status); | ||
1245 | break; | ||
1246 | } | ||
1247 | rpc_wake_up_queued_task(&req->rq_xprt->pending, task); | ||
1248 | } | ||
1249 | #endif /* CONFIG_NFS_V4_1 */ | ||
1250 | |||
1123 | /* | 1251 | /* |
1124 | * 6. Sort out the RPC call status | 1252 | * 6. Sort out the RPC call status |
1125 | */ | 1253 | */ |
@@ -1130,8 +1258,8 @@ call_status(struct rpc_task *task) | |||
1130 | struct rpc_rqst *req = task->tk_rqstp; | 1258 | struct rpc_rqst *req = task->tk_rqstp; |
1131 | int status; | 1259 | int status; |
1132 | 1260 | ||
1133 | if (req->rq_received > 0 && !req->rq_bytes_sent) | 1261 | if (req->rq_reply_bytes_recvd > 0 && !req->rq_bytes_sent) |
1134 | task->tk_status = req->rq_received; | 1262 | task->tk_status = req->rq_reply_bytes_recvd; |
1135 | 1263 | ||
1136 | dprint_status(task); | 1264 | dprint_status(task); |
1137 | 1265 | ||
@@ -1248,7 +1376,7 @@ call_decode(struct rpc_task *task) | |||
1248 | 1376 | ||
1249 | /* | 1377 | /* |
1250 | * Ensure that we see all writes made by xprt_complete_rqst() | 1378 | * Ensure that we see all writes made by xprt_complete_rqst() |
1251 | * before it changed req->rq_received. | 1379 | * before it changed req->rq_reply_bytes_recvd. |
1252 | */ | 1380 | */ |
1253 | smp_rmb(); | 1381 | smp_rmb(); |
1254 | req->rq_rcv_buf.len = req->rq_private_buf.len; | 1382 | req->rq_rcv_buf.len = req->rq_private_buf.len; |
@@ -1289,7 +1417,7 @@ out_retry: | |||
1289 | task->tk_status = 0; | 1417 | task->tk_status = 0; |
1290 | /* Note: rpc_verify_header() may have freed the RPC slot */ | 1418 | /* Note: rpc_verify_header() may have freed the RPC slot */ |
1291 | if (task->tk_rqstp == req) { | 1419 | if (task->tk_rqstp == req) { |
1292 | req->rq_received = req->rq_rcv_buf.len = 0; | 1420 | req->rq_reply_bytes_recvd = req->rq_rcv_buf.len = 0; |
1293 | if (task->tk_client->cl_discrtry) | 1421 | if (task->tk_client->cl_discrtry) |
1294 | xprt_conditional_disconnect(task->tk_xprt, | 1422 | xprt_conditional_disconnect(task->tk_xprt, |
1295 | req->rq_connect_cookie); | 1423 | req->rq_connect_cookie); |
@@ -1377,13 +1505,14 @@ rpc_verify_header(struct rpc_task *task) | |||
1377 | } | 1505 | } |
1378 | if ((len -= 3) < 0) | 1506 | if ((len -= 3) < 0) |
1379 | goto out_overflow; | 1507 | goto out_overflow; |
1380 | p += 1; /* skip XID */ | ||
1381 | 1508 | ||
1509 | p += 1; /* skip XID */ | ||
1382 | if ((n = ntohl(*p++)) != RPC_REPLY) { | 1510 | if ((n = ntohl(*p++)) != RPC_REPLY) { |
1383 | dprintk("RPC: %5u %s: not an RPC reply: %x\n", | 1511 | dprintk("RPC: %5u %s: not an RPC reply: %x\n", |
1384 | task->tk_pid, __func__, n); | 1512 | task->tk_pid, __func__, n); |
1385 | goto out_garbage; | 1513 | goto out_garbage; |
1386 | } | 1514 | } |
1515 | |||
1387 | if ((n = ntohl(*p++)) != RPC_MSG_ACCEPTED) { | 1516 | if ((n = ntohl(*p++)) != RPC_MSG_ACCEPTED) { |
1388 | if (--len < 0) | 1517 | if (--len < 0) |
1389 | goto out_overflow; | 1518 | goto out_overflow; |
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index ff50a0546865..8f459abe97cf 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c | |||
@@ -16,7 +16,6 @@ | |||
16 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
17 | #include <linux/mempool.h> | 17 | #include <linux/mempool.h> |
18 | #include <linux/smp.h> | 18 | #include <linux/smp.h> |
19 | #include <linux/smp_lock.h> | ||
20 | #include <linux/spinlock.h> | 19 | #include <linux/spinlock.h> |
21 | #include <linux/mutex.h> | 20 | #include <linux/mutex.h> |
22 | 21 | ||
@@ -569,7 +568,7 @@ EXPORT_SYMBOL_GPL(rpc_delay); | |||
569 | /* | 568 | /* |
570 | * Helper to call task->tk_ops->rpc_call_prepare | 569 | * Helper to call task->tk_ops->rpc_call_prepare |
571 | */ | 570 | */ |
572 | static void rpc_prepare_task(struct rpc_task *task) | 571 | void rpc_prepare_task(struct rpc_task *task) |
573 | { | 572 | { |
574 | task->tk_ops->rpc_call_prepare(task, task->tk_calldata); | 573 | task->tk_ops->rpc_call_prepare(task, task->tk_calldata); |
575 | } | 574 | } |
diff --git a/net/sunrpc/stats.c b/net/sunrpc/stats.c index 1ef6e46d9da2..1b4e6791ecf3 100644 --- a/net/sunrpc/stats.c +++ b/net/sunrpc/stats.c | |||
@@ -141,12 +141,14 @@ EXPORT_SYMBOL_GPL(rpc_free_iostats); | |||
141 | void rpc_count_iostats(struct rpc_task *task) | 141 | void rpc_count_iostats(struct rpc_task *task) |
142 | { | 142 | { |
143 | struct rpc_rqst *req = task->tk_rqstp; | 143 | struct rpc_rqst *req = task->tk_rqstp; |
144 | struct rpc_iostats *stats = task->tk_client->cl_metrics; | 144 | struct rpc_iostats *stats; |
145 | struct rpc_iostats *op_metrics; | 145 | struct rpc_iostats *op_metrics; |
146 | long rtt, execute, queue; | 146 | long rtt, execute, queue; |
147 | 147 | ||
148 | if (!stats || !req) | 148 | if (!task->tk_client || !task->tk_client->cl_metrics || !req) |
149 | return; | 149 | return; |
150 | |||
151 | stats = task->tk_client->cl_metrics; | ||
150 | op_metrics = &stats[task->tk_msg.rpc_proc->p_statidx]; | 152 | op_metrics = &stats[task->tk_msg.rpc_proc->p_statidx]; |
151 | 153 | ||
152 | op_metrics->om_ops++; | 154 | op_metrics->om_ops++; |
@@ -154,7 +156,7 @@ void rpc_count_iostats(struct rpc_task *task) | |||
154 | op_metrics->om_timeouts += task->tk_timeouts; | 156 | op_metrics->om_timeouts += task->tk_timeouts; |
155 | 157 | ||
156 | op_metrics->om_bytes_sent += task->tk_bytes_sent; | 158 | op_metrics->om_bytes_sent += task->tk_bytes_sent; |
157 | op_metrics->om_bytes_recv += req->rq_received; | 159 | op_metrics->om_bytes_recv += req->rq_reply_bytes_recvd; |
158 | 160 | ||
159 | queue = (long)req->rq_xtime - task->tk_start; | 161 | queue = (long)req->rq_xtime - task->tk_start; |
160 | if (queue < 0) | 162 | if (queue < 0) |
diff --git a/net/sunrpc/sunrpc.h b/net/sunrpc/sunrpc.h new file mode 100644 index 000000000000..5d9dd742264b --- /dev/null +++ b/net/sunrpc/sunrpc.h | |||
@@ -0,0 +1,37 @@ | |||
1 | /****************************************************************************** | ||
2 | |||
3 | (c) 2008 NetApp. All Rights Reserved. | ||
4 | |||
5 | NetApp provides this source code under the GPL v2 License. | ||
6 | The GPL v2 license is available at | ||
7 | http://opensource.org/licenses/gpl-license.php. | ||
8 | |||
9 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
10 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
11 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
12 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | ||
13 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | ||
14 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | ||
15 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | ||
16 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||
17 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||
18 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
19 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
20 | |||
21 | ******************************************************************************/ | ||
22 | |||
23 | /* | ||
24 | * Functions and macros used internally by RPC | ||
25 | */ | ||
26 | |||
27 | #ifndef _NET_SUNRPC_SUNRPC_H | ||
28 | #define _NET_SUNRPC_SUNRPC_H | ||
29 | |||
30 | static inline int rpc_reply_expected(struct rpc_task *task) | ||
31 | { | ||
32 | return (task->tk_msg.rpc_proc != NULL) && | ||
33 | (task->tk_msg.rpc_proc->p_decode != NULL); | ||
34 | } | ||
35 | |||
36 | #endif /* _NET_SUNRPC_SUNRPC_H */ | ||
37 | |||
diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c index 843629f55763..adaa81982f74 100644 --- a/net/sunrpc/sunrpc_syms.c +++ b/net/sunrpc/sunrpc_syms.c | |||
@@ -66,6 +66,7 @@ cleanup_sunrpc(void) | |||
66 | #ifdef CONFIG_PROC_FS | 66 | #ifdef CONFIG_PROC_FS |
67 | rpc_proc_exit(); | 67 | rpc_proc_exit(); |
68 | #endif | 68 | #endif |
69 | rcu_barrier(); /* Wait for completion of call_rcu()'s */ | ||
69 | } | 70 | } |
70 | MODULE_LICENSE("GPL"); | 71 | MODULE_LICENSE("GPL"); |
71 | module_init(init_sunrpc); | 72 | module_init(init_sunrpc); |
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c index 5ed8931dfe98..952f206ff307 100644 --- a/net/sunrpc/svc.c +++ b/net/sunrpc/svc.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/sunrpc/stats.h> | 25 | #include <linux/sunrpc/stats.h> |
26 | #include <linux/sunrpc/svcsock.h> | 26 | #include <linux/sunrpc/svcsock.h> |
27 | #include <linux/sunrpc/clnt.h> | 27 | #include <linux/sunrpc/clnt.h> |
28 | #include <linux/sunrpc/bc_xprt.h> | ||
28 | 29 | ||
29 | #define RPCDBG_FACILITY RPCDBG_SVCDSP | 30 | #define RPCDBG_FACILITY RPCDBG_SVCDSP |
30 | 31 | ||
@@ -486,6 +487,10 @@ svc_destroy(struct svc_serv *serv) | |||
486 | if (svc_serv_is_pooled(serv)) | 487 | if (svc_serv_is_pooled(serv)) |
487 | svc_pool_map_put(); | 488 | svc_pool_map_put(); |
488 | 489 | ||
490 | #if defined(CONFIG_NFS_V4_1) | ||
491 | svc_sock_destroy(serv->bc_xprt); | ||
492 | #endif /* CONFIG_NFS_V4_1 */ | ||
493 | |||
489 | svc_unregister(serv); | 494 | svc_unregister(serv); |
490 | kfree(serv->sv_pools); | 495 | kfree(serv->sv_pools); |
491 | kfree(serv); | 496 | kfree(serv); |
@@ -970,20 +975,18 @@ svc_printk(struct svc_rqst *rqstp, const char *fmt, ...) | |||
970 | } | 975 | } |
971 | 976 | ||
972 | /* | 977 | /* |
973 | * Process the RPC request. | 978 | * Common routine for processing the RPC request. |
974 | */ | 979 | */ |
975 | int | 980 | static int |
976 | svc_process(struct svc_rqst *rqstp) | 981 | svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv) |
977 | { | 982 | { |
978 | struct svc_program *progp; | 983 | struct svc_program *progp; |
979 | struct svc_version *versp = NULL; /* compiler food */ | 984 | struct svc_version *versp = NULL; /* compiler food */ |
980 | struct svc_procedure *procp = NULL; | 985 | struct svc_procedure *procp = NULL; |
981 | struct kvec * argv = &rqstp->rq_arg.head[0]; | ||
982 | struct kvec * resv = &rqstp->rq_res.head[0]; | ||
983 | struct svc_serv *serv = rqstp->rq_server; | 986 | struct svc_serv *serv = rqstp->rq_server; |
984 | kxdrproc_t xdr; | 987 | kxdrproc_t xdr; |
985 | __be32 *statp; | 988 | __be32 *statp; |
986 | u32 dir, prog, vers, proc; | 989 | u32 prog, vers, proc; |
987 | __be32 auth_stat, rpc_stat; | 990 | __be32 auth_stat, rpc_stat; |
988 | int auth_res; | 991 | int auth_res; |
989 | __be32 *reply_statp; | 992 | __be32 *reply_statp; |
@@ -993,19 +996,6 @@ svc_process(struct svc_rqst *rqstp) | |||
993 | if (argv->iov_len < 6*4) | 996 | if (argv->iov_len < 6*4) |
994 | goto err_short_len; | 997 | goto err_short_len; |
995 | 998 | ||
996 | /* setup response xdr_buf. | ||
997 | * Initially it has just one page | ||
998 | */ | ||
999 | rqstp->rq_resused = 1; | ||
1000 | resv->iov_base = page_address(rqstp->rq_respages[0]); | ||
1001 | resv->iov_len = 0; | ||
1002 | rqstp->rq_res.pages = rqstp->rq_respages + 1; | ||
1003 | rqstp->rq_res.len = 0; | ||
1004 | rqstp->rq_res.page_base = 0; | ||
1005 | rqstp->rq_res.page_len = 0; | ||
1006 | rqstp->rq_res.buflen = PAGE_SIZE; | ||
1007 | rqstp->rq_res.tail[0].iov_base = NULL; | ||
1008 | rqstp->rq_res.tail[0].iov_len = 0; | ||
1009 | /* Will be turned off only in gss privacy case: */ | 999 | /* Will be turned off only in gss privacy case: */ |
1010 | rqstp->rq_splice_ok = 1; | 1000 | rqstp->rq_splice_ok = 1; |
1011 | /* Will be turned off only when NFSv4 Sessions are used */ | 1001 | /* Will be turned off only when NFSv4 Sessions are used */ |
@@ -1014,17 +1004,13 @@ svc_process(struct svc_rqst *rqstp) | |||
1014 | /* Setup reply header */ | 1004 | /* Setup reply header */ |
1015 | rqstp->rq_xprt->xpt_ops->xpo_prep_reply_hdr(rqstp); | 1005 | rqstp->rq_xprt->xpt_ops->xpo_prep_reply_hdr(rqstp); |
1016 | 1006 | ||
1017 | rqstp->rq_xid = svc_getu32(argv); | ||
1018 | svc_putu32(resv, rqstp->rq_xid); | 1007 | svc_putu32(resv, rqstp->rq_xid); |
1019 | 1008 | ||
1020 | dir = svc_getnl(argv); | ||
1021 | vers = svc_getnl(argv); | 1009 | vers = svc_getnl(argv); |
1022 | 1010 | ||
1023 | /* First words of reply: */ | 1011 | /* First words of reply: */ |
1024 | svc_putnl(resv, 1); /* REPLY */ | 1012 | svc_putnl(resv, 1); /* REPLY */ |
1025 | 1013 | ||
1026 | if (dir != 0) /* direction != CALL */ | ||
1027 | goto err_bad_dir; | ||
1028 | if (vers != 2) /* RPC version number */ | 1014 | if (vers != 2) /* RPC version number */ |
1029 | goto err_bad_rpc; | 1015 | goto err_bad_rpc; |
1030 | 1016 | ||
@@ -1147,7 +1133,7 @@ svc_process(struct svc_rqst *rqstp) | |||
1147 | sendit: | 1133 | sendit: |
1148 | if (svc_authorise(rqstp)) | 1134 | if (svc_authorise(rqstp)) |
1149 | goto dropit; | 1135 | goto dropit; |
1150 | return svc_send(rqstp); | 1136 | return 1; /* Caller can now send it */ |
1151 | 1137 | ||
1152 | dropit: | 1138 | dropit: |
1153 | svc_authorise(rqstp); /* doesn't hurt to call this twice */ | 1139 | svc_authorise(rqstp); /* doesn't hurt to call this twice */ |
@@ -1161,12 +1147,6 @@ err_short_len: | |||
1161 | 1147 | ||
1162 | goto dropit; /* drop request */ | 1148 | goto dropit; /* drop request */ |
1163 | 1149 | ||
1164 | err_bad_dir: | ||
1165 | svc_printk(rqstp, "bad direction %d, dropping request\n", dir); | ||
1166 | |||
1167 | serv->sv_stats->rpcbadfmt++; | ||
1168 | goto dropit; /* drop request */ | ||
1169 | |||
1170 | err_bad_rpc: | 1150 | err_bad_rpc: |
1171 | serv->sv_stats->rpcbadfmt++; | 1151 | serv->sv_stats->rpcbadfmt++; |
1172 | svc_putnl(resv, 1); /* REJECT */ | 1152 | svc_putnl(resv, 1); /* REJECT */ |
@@ -1220,6 +1200,100 @@ err_bad: | |||
1220 | EXPORT_SYMBOL_GPL(svc_process); | 1200 | EXPORT_SYMBOL_GPL(svc_process); |
1221 | 1201 | ||
1222 | /* | 1202 | /* |
1203 | * Process the RPC request. | ||
1204 | */ | ||
1205 | int | ||
1206 | svc_process(struct svc_rqst *rqstp) | ||
1207 | { | ||
1208 | struct kvec *argv = &rqstp->rq_arg.head[0]; | ||
1209 | struct kvec *resv = &rqstp->rq_res.head[0]; | ||
1210 | struct svc_serv *serv = rqstp->rq_server; | ||
1211 | u32 dir; | ||
1212 | int error; | ||
1213 | |||
1214 | /* | ||
1215 | * Setup response xdr_buf. | ||
1216 | * Initially it has just one page | ||
1217 | */ | ||
1218 | rqstp->rq_resused = 1; | ||
1219 | resv->iov_base = page_address(rqstp->rq_respages[0]); | ||
1220 | resv->iov_len = 0; | ||
1221 | rqstp->rq_res.pages = rqstp->rq_respages + 1; | ||
1222 | rqstp->rq_res.len = 0; | ||
1223 | rqstp->rq_res.page_base = 0; | ||
1224 | rqstp->rq_res.page_len = 0; | ||
1225 | rqstp->rq_res.buflen = PAGE_SIZE; | ||
1226 | rqstp->rq_res.tail[0].iov_base = NULL; | ||
1227 | rqstp->rq_res.tail[0].iov_len = 0; | ||
1228 | |||
1229 | rqstp->rq_xid = svc_getu32(argv); | ||
1230 | |||
1231 | dir = svc_getnl(argv); | ||
1232 | if (dir != 0) { | ||
1233 | /* direction != CALL */ | ||
1234 | svc_printk(rqstp, "bad direction %d, dropping request\n", dir); | ||
1235 | serv->sv_stats->rpcbadfmt++; | ||
1236 | svc_drop(rqstp); | ||
1237 | return 0; | ||
1238 | } | ||
1239 | |||
1240 | error = svc_process_common(rqstp, argv, resv); | ||
1241 | if (error <= 0) | ||
1242 | return error; | ||
1243 | |||
1244 | return svc_send(rqstp); | ||
1245 | } | ||
1246 | |||
1247 | #if defined(CONFIG_NFS_V4_1) | ||
1248 | /* | ||
1249 | * Process a backchannel RPC request that arrived over an existing | ||
1250 | * outbound connection | ||
1251 | */ | ||
1252 | int | ||
1253 | bc_svc_process(struct svc_serv *serv, struct rpc_rqst *req, | ||
1254 | struct svc_rqst *rqstp) | ||
1255 | { | ||
1256 | struct kvec *argv = &rqstp->rq_arg.head[0]; | ||
1257 | struct kvec *resv = &rqstp->rq_res.head[0]; | ||
1258 | int error; | ||
1259 | |||
1260 | /* Build the svc_rqst used by the common processing routine */ | ||
1261 | rqstp->rq_xprt = serv->bc_xprt; | ||
1262 | rqstp->rq_xid = req->rq_xid; | ||
1263 | rqstp->rq_prot = req->rq_xprt->prot; | ||
1264 | rqstp->rq_server = serv; | ||
1265 | |||
1266 | rqstp->rq_addrlen = sizeof(req->rq_xprt->addr); | ||
1267 | memcpy(&rqstp->rq_addr, &req->rq_xprt->addr, rqstp->rq_addrlen); | ||
1268 | memcpy(&rqstp->rq_arg, &req->rq_rcv_buf, sizeof(rqstp->rq_arg)); | ||
1269 | memcpy(&rqstp->rq_res, &req->rq_snd_buf, sizeof(rqstp->rq_res)); | ||
1270 | |||
1271 | /* reset result send buffer "put" position */ | ||
1272 | resv->iov_len = 0; | ||
1273 | |||
1274 | if (rqstp->rq_prot != IPPROTO_TCP) { | ||
1275 | printk(KERN_ERR "No support for Non-TCP transports!\n"); | ||
1276 | BUG(); | ||
1277 | } | ||
1278 | |||
1279 | /* | ||
1280 | * Skip the next two words because they've already been | ||
1281 | * processed in the trasport | ||
1282 | */ | ||
1283 | svc_getu32(argv); /* XID */ | ||
1284 | svc_getnl(argv); /* CALLDIR */ | ||
1285 | |||
1286 | error = svc_process_common(rqstp, argv, resv); | ||
1287 | if (error <= 0) | ||
1288 | return error; | ||
1289 | |||
1290 | memcpy(&req->rq_snd_buf, &rqstp->rq_res, sizeof(req->rq_snd_buf)); | ||
1291 | return bc_send(req); | ||
1292 | } | ||
1293 | EXPORT_SYMBOL(bc_svc_process); | ||
1294 | #endif /* CONFIG_NFS_V4_1 */ | ||
1295 | |||
1296 | /* | ||
1223 | * Return (transport-specific) limit on the rpc payload. | 1297 | * Return (transport-specific) limit on the rpc payload. |
1224 | */ | 1298 | */ |
1225 | u32 svc_max_payload(const struct svc_rqst *rqstp) | 1299 | u32 svc_max_payload(const struct svc_rqst *rqstp) |
diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c index c200d92e57e4..27d44332f017 100644 --- a/net/sunrpc/svc_xprt.c +++ b/net/sunrpc/svc_xprt.c | |||
@@ -5,12 +5,14 @@ | |||
5 | */ | 5 | */ |
6 | 6 | ||
7 | #include <linux/sched.h> | 7 | #include <linux/sched.h> |
8 | #include <linux/smp_lock.h> | ||
8 | #include <linux/errno.h> | 9 | #include <linux/errno.h> |
9 | #include <linux/freezer.h> | 10 | #include <linux/freezer.h> |
10 | #include <linux/kthread.h> | 11 | #include <linux/kthread.h> |
11 | #include <net/sock.h> | 12 | #include <net/sock.h> |
12 | #include <linux/sunrpc/stats.h> | 13 | #include <linux/sunrpc/stats.h> |
13 | #include <linux/sunrpc/svc_xprt.h> | 14 | #include <linux/sunrpc/svc_xprt.h> |
15 | #include <linux/sunrpc/svcsock.h> | ||
14 | 16 | ||
15 | #define RPCDBG_FACILITY RPCDBG_SVCXPRT | 17 | #define RPCDBG_FACILITY RPCDBG_SVCXPRT |
16 | 18 | ||
@@ -1097,36 +1099,58 @@ struct svc_xprt *svc_find_xprt(struct svc_serv *serv, const char *xcl_name, | |||
1097 | } | 1099 | } |
1098 | EXPORT_SYMBOL_GPL(svc_find_xprt); | 1100 | EXPORT_SYMBOL_GPL(svc_find_xprt); |
1099 | 1101 | ||
1100 | /* | 1102 | static int svc_one_xprt_name(const struct svc_xprt *xprt, |
1101 | * Format a buffer with a list of the active transports. A zero for | 1103 | char *pos, int remaining) |
1102 | * the buflen parameter disables target buffer overflow checking. | 1104 | { |
1105 | int len; | ||
1106 | |||
1107 | len = snprintf(pos, remaining, "%s %u\n", | ||
1108 | xprt->xpt_class->xcl_name, | ||
1109 | svc_xprt_local_port(xprt)); | ||
1110 | if (len >= remaining) | ||
1111 | return -ENAMETOOLONG; | ||
1112 | return len; | ||
1113 | } | ||
1114 | |||
1115 | /** | ||
1116 | * svc_xprt_names - format a buffer with a list of transport names | ||
1117 | * @serv: pointer to an RPC service | ||
1118 | * @buf: pointer to a buffer to be filled in | ||
1119 | * @buflen: length of buffer to be filled in | ||
1120 | * | ||
1121 | * Fills in @buf with a string containing a list of transport names, | ||
1122 | * each name terminated with '\n'. | ||
1123 | * | ||
1124 | * Returns positive length of the filled-in string on success; otherwise | ||
1125 | * a negative errno value is returned if an error occurs. | ||
1103 | */ | 1126 | */ |
1104 | int svc_xprt_names(struct svc_serv *serv, char *buf, int buflen) | 1127 | int svc_xprt_names(struct svc_serv *serv, char *buf, const int buflen) |
1105 | { | 1128 | { |
1106 | struct svc_xprt *xprt; | 1129 | struct svc_xprt *xprt; |
1107 | char xprt_str[64]; | 1130 | int len, totlen; |
1108 | int totlen = 0; | 1131 | char *pos; |
1109 | int len; | ||
1110 | 1132 | ||
1111 | /* Sanity check args */ | 1133 | /* Sanity check args */ |
1112 | if (!serv) | 1134 | if (!serv) |
1113 | return 0; | 1135 | return 0; |
1114 | 1136 | ||
1115 | spin_lock_bh(&serv->sv_lock); | 1137 | spin_lock_bh(&serv->sv_lock); |
1138 | |||
1139 | pos = buf; | ||
1140 | totlen = 0; | ||
1116 | list_for_each_entry(xprt, &serv->sv_permsocks, xpt_list) { | 1141 | list_for_each_entry(xprt, &serv->sv_permsocks, xpt_list) { |
1117 | len = snprintf(xprt_str, sizeof(xprt_str), | 1142 | len = svc_one_xprt_name(xprt, pos, buflen - totlen); |
1118 | "%s %d\n", xprt->xpt_class->xcl_name, | 1143 | if (len < 0) { |
1119 | svc_xprt_local_port(xprt)); | 1144 | *buf = '\0'; |
1120 | /* If the string was truncated, replace with error string */ | 1145 | totlen = len; |
1121 | if (len >= sizeof(xprt_str)) | 1146 | } |
1122 | strcpy(xprt_str, "name-too-long\n"); | 1147 | if (len <= 0) |
1123 | /* Don't overflow buffer */ | ||
1124 | len = strlen(xprt_str); | ||
1125 | if (buflen && (len + totlen >= buflen)) | ||
1126 | break; | 1148 | break; |
1127 | strcpy(buf+totlen, xprt_str); | 1149 | |
1150 | pos += len; | ||
1128 | totlen += len; | 1151 | totlen += len; |
1129 | } | 1152 | } |
1153 | |||
1130 | spin_unlock_bh(&serv->sv_lock); | 1154 | spin_unlock_bh(&serv->sv_lock); |
1131 | return totlen; | 1155 | return totlen; |
1132 | } | 1156 | } |
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index 9d504234af4a..23128ee191ae 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c | |||
@@ -240,42 +240,76 @@ out: | |||
240 | /* | 240 | /* |
241 | * Report socket names for nfsdfs | 241 | * Report socket names for nfsdfs |
242 | */ | 242 | */ |
243 | static int one_sock_name(char *buf, struct svc_sock *svsk) | 243 | static int svc_one_sock_name(struct svc_sock *svsk, char *buf, int remaining) |
244 | { | 244 | { |
245 | const struct sock *sk = svsk->sk_sk; | ||
246 | const char *proto_name = sk->sk_protocol == IPPROTO_UDP ? | ||
247 | "udp" : "tcp"; | ||
245 | int len; | 248 | int len; |
246 | 249 | ||
247 | switch(svsk->sk_sk->sk_family) { | 250 | switch (sk->sk_family) { |
248 | case AF_INET: | 251 | case PF_INET: |
249 | len = sprintf(buf, "ipv4 %s %pI4 %d\n", | 252 | len = snprintf(buf, remaining, "ipv4 %s %pI4 %d\n", |
250 | svsk->sk_sk->sk_protocol == IPPROTO_UDP ? | 253 | proto_name, |
251 | "udp" : "tcp", | 254 | &inet_sk(sk)->rcv_saddr, |
252 | &inet_sk(svsk->sk_sk)->rcv_saddr, | 255 | inet_sk(sk)->num); |
253 | inet_sk(svsk->sk_sk)->num); | 256 | break; |
257 | case PF_INET6: | ||
258 | len = snprintf(buf, remaining, "ipv6 %s %pI6 %d\n", | ||
259 | proto_name, | ||
260 | &inet6_sk(sk)->rcv_saddr, | ||
261 | inet_sk(sk)->num); | ||
254 | break; | 262 | break; |
255 | default: | 263 | default: |
256 | len = sprintf(buf, "*unknown-%d*\n", | 264 | len = snprintf(buf, remaining, "*unknown-%d*\n", |
257 | svsk->sk_sk->sk_family); | 265 | sk->sk_family); |
266 | } | ||
267 | |||
268 | if (len >= remaining) { | ||
269 | *buf = '\0'; | ||
270 | return -ENAMETOOLONG; | ||
258 | } | 271 | } |
259 | return len; | 272 | return len; |
260 | } | 273 | } |
261 | 274 | ||
262 | int | 275 | /** |
263 | svc_sock_names(char *buf, struct svc_serv *serv, char *toclose) | 276 | * svc_sock_names - construct a list of listener names in a string |
277 | * @serv: pointer to RPC service | ||
278 | * @buf: pointer to a buffer to fill in with socket names | ||
279 | * @buflen: size of the buffer to be filled | ||
280 | * @toclose: pointer to '\0'-terminated C string containing the name | ||
281 | * of a listener to be closed | ||
282 | * | ||
283 | * Fills in @buf with a '\n'-separated list of names of listener | ||
284 | * sockets. If @toclose is not NULL, the socket named by @toclose | ||
285 | * is closed, and is not included in the output list. | ||
286 | * | ||
287 | * Returns positive length of the socket name string, or a negative | ||
288 | * errno value on error. | ||
289 | */ | ||
290 | int svc_sock_names(struct svc_serv *serv, char *buf, const size_t buflen, | ||
291 | const char *toclose) | ||
264 | { | 292 | { |
265 | struct svc_sock *svsk, *closesk = NULL; | 293 | struct svc_sock *svsk, *closesk = NULL; |
266 | int len = 0; | 294 | int len = 0; |
267 | 295 | ||
268 | if (!serv) | 296 | if (!serv) |
269 | return 0; | 297 | return 0; |
298 | |||
270 | spin_lock_bh(&serv->sv_lock); | 299 | spin_lock_bh(&serv->sv_lock); |
271 | list_for_each_entry(svsk, &serv->sv_permsocks, sk_xprt.xpt_list) { | 300 | list_for_each_entry(svsk, &serv->sv_permsocks, sk_xprt.xpt_list) { |
272 | int onelen = one_sock_name(buf+len, svsk); | 301 | int onelen = svc_one_sock_name(svsk, buf + len, buflen - len); |
273 | if (toclose && strcmp(toclose, buf+len) == 0) | 302 | if (onelen < 0) { |
303 | len = onelen; | ||
304 | break; | ||
305 | } | ||
306 | if (toclose && strcmp(toclose, buf + len) == 0) | ||
274 | closesk = svsk; | 307 | closesk = svsk; |
275 | else | 308 | else |
276 | len += onelen; | 309 | len += onelen; |
277 | } | 310 | } |
278 | spin_unlock_bh(&serv->sv_lock); | 311 | spin_unlock_bh(&serv->sv_lock); |
312 | |||
279 | if (closesk) | 313 | if (closesk) |
280 | /* Should unregister with portmap, but you cannot | 314 | /* Should unregister with portmap, but you cannot |
281 | * unregister just one protocol... | 315 | * unregister just one protocol... |
@@ -346,6 +380,7 @@ static void svc_sock_setbufsize(struct socket *sock, unsigned int snd, | |||
346 | sock->sk->sk_sndbuf = snd * 2; | 380 | sock->sk->sk_sndbuf = snd * 2; |
347 | sock->sk->sk_rcvbuf = rcv * 2; | 381 | sock->sk->sk_rcvbuf = rcv * 2; |
348 | sock->sk->sk_userlocks |= SOCK_SNDBUF_LOCK|SOCK_RCVBUF_LOCK; | 382 | sock->sk->sk_userlocks |= SOCK_SNDBUF_LOCK|SOCK_RCVBUF_LOCK; |
383 | sock->sk->sk_write_space(sock->sk); | ||
349 | release_sock(sock->sk); | 384 | release_sock(sock->sk); |
350 | #endif | 385 | #endif |
351 | } | 386 | } |
@@ -387,6 +422,15 @@ static void svc_write_space(struct sock *sk) | |||
387 | } | 422 | } |
388 | } | 423 | } |
389 | 424 | ||
425 | static void svc_tcp_write_space(struct sock *sk) | ||
426 | { | ||
427 | struct socket *sock = sk->sk_socket; | ||
428 | |||
429 | if (sk_stream_wspace(sk) >= sk_stream_min_wspace(sk) && sock) | ||
430 | clear_bit(SOCK_NOSPACE, &sock->flags); | ||
431 | svc_write_space(sk); | ||
432 | } | ||
433 | |||
390 | /* | 434 | /* |
391 | * Copy the UDP datagram's destination address to the rqstp structure. | 435 | * Copy the UDP datagram's destination address to the rqstp structure. |
392 | * The 'destination' address in this case is the address to which the | 436 | * The 'destination' address in this case is the address to which the |
@@ -427,13 +471,14 @@ static int svc_udp_recvfrom(struct svc_rqst *rqstp) | |||
427 | long all[SVC_PKTINFO_SPACE / sizeof(long)]; | 471 | long all[SVC_PKTINFO_SPACE / sizeof(long)]; |
428 | } buffer; | 472 | } buffer; |
429 | struct cmsghdr *cmh = &buffer.hdr; | 473 | struct cmsghdr *cmh = &buffer.hdr; |
430 | int err, len; | ||
431 | struct msghdr msg = { | 474 | struct msghdr msg = { |
432 | .msg_name = svc_addr(rqstp), | 475 | .msg_name = svc_addr(rqstp), |
433 | .msg_control = cmh, | 476 | .msg_control = cmh, |
434 | .msg_controllen = sizeof(buffer), | 477 | .msg_controllen = sizeof(buffer), |
435 | .msg_flags = MSG_DONTWAIT, | 478 | .msg_flags = MSG_DONTWAIT, |
436 | }; | 479 | }; |
480 | size_t len; | ||
481 | int err; | ||
437 | 482 | ||
438 | if (test_and_clear_bit(XPT_CHNGBUF, &svsk->sk_xprt.xpt_flags)) | 483 | if (test_and_clear_bit(XPT_CHNGBUF, &svsk->sk_xprt.xpt_flags)) |
439 | /* udp sockets need large rcvbuf as all pending | 484 | /* udp sockets need large rcvbuf as all pending |
@@ -465,8 +510,8 @@ static int svc_udp_recvfrom(struct svc_rqst *rqstp) | |||
465 | return -EAGAIN; | 510 | return -EAGAIN; |
466 | } | 511 | } |
467 | len = svc_addr_len(svc_addr(rqstp)); | 512 | len = svc_addr_len(svc_addr(rqstp)); |
468 | if (len < 0) | 513 | if (len == 0) |
469 | return len; | 514 | return -EAFNOSUPPORT; |
470 | rqstp->rq_addrlen = len; | 515 | rqstp->rq_addrlen = len; |
471 | if (skb->tstamp.tv64 == 0) { | 516 | if (skb->tstamp.tv64 == 0) { |
472 | skb->tstamp = ktime_get_real(); | 517 | skb->tstamp = ktime_get_real(); |
@@ -980,25 +1025,16 @@ static void svc_tcp_prep_reply_hdr(struct svc_rqst *rqstp) | |||
980 | static int svc_tcp_has_wspace(struct svc_xprt *xprt) | 1025 | static int svc_tcp_has_wspace(struct svc_xprt *xprt) |
981 | { | 1026 | { |
982 | struct svc_sock *svsk = container_of(xprt, struct svc_sock, sk_xprt); | 1027 | struct svc_sock *svsk = container_of(xprt, struct svc_sock, sk_xprt); |
983 | struct svc_serv *serv = svsk->sk_xprt.xpt_server; | 1028 | struct svc_serv *serv = svsk->sk_xprt.xpt_server; |
984 | int required; | 1029 | int required; |
985 | int wspace; | ||
986 | 1030 | ||
987 | /* | 1031 | if (test_bit(XPT_LISTENER, &xprt->xpt_flags)) |
988 | * Set the SOCK_NOSPACE flag before checking the available | 1032 | return 1; |
989 | * sock space. | 1033 | required = atomic_read(&xprt->xpt_reserved) + serv->sv_max_mesg; |
990 | */ | 1034 | if (sk_stream_wspace(svsk->sk_sk) >= required) |
1035 | return 1; | ||
991 | set_bit(SOCK_NOSPACE, &svsk->sk_sock->flags); | 1036 | set_bit(SOCK_NOSPACE, &svsk->sk_sock->flags); |
992 | required = atomic_read(&svsk->sk_xprt.xpt_reserved) + serv->sv_max_mesg; | 1037 | return 0; |
993 | wspace = sk_stream_wspace(svsk->sk_sk); | ||
994 | |||
995 | if (wspace < sk_stream_min_wspace(svsk->sk_sk)) | ||
996 | return 0; | ||
997 | if (required * 2 > wspace) | ||
998 | return 0; | ||
999 | |||
1000 | clear_bit(SOCK_NOSPACE, &svsk->sk_sock->flags); | ||
1001 | return 1; | ||
1002 | } | 1038 | } |
1003 | 1039 | ||
1004 | static struct svc_xprt *svc_tcp_create(struct svc_serv *serv, | 1040 | static struct svc_xprt *svc_tcp_create(struct svc_serv *serv, |
@@ -1054,7 +1090,7 @@ static void svc_tcp_init(struct svc_sock *svsk, struct svc_serv *serv) | |||
1054 | dprintk("setting up TCP socket for reading\n"); | 1090 | dprintk("setting up TCP socket for reading\n"); |
1055 | sk->sk_state_change = svc_tcp_state_change; | 1091 | sk->sk_state_change = svc_tcp_state_change; |
1056 | sk->sk_data_ready = svc_tcp_data_ready; | 1092 | sk->sk_data_ready = svc_tcp_data_ready; |
1057 | sk->sk_write_space = svc_write_space; | 1093 | sk->sk_write_space = svc_tcp_write_space; |
1058 | 1094 | ||
1059 | svsk->sk_reclen = 0; | 1095 | svsk->sk_reclen = 0; |
1060 | svsk->sk_tcplen = 0; | 1096 | svsk->sk_tcplen = 0; |
@@ -1148,9 +1184,19 @@ static struct svc_sock *svc_setup_socket(struct svc_serv *serv, | |||
1148 | return svsk; | 1184 | return svsk; |
1149 | } | 1185 | } |
1150 | 1186 | ||
1151 | int svc_addsock(struct svc_serv *serv, | 1187 | /** |
1152 | int fd, | 1188 | * svc_addsock - add a listener socket to an RPC service |
1153 | char *name_return) | 1189 | * @serv: pointer to RPC service to which to add a new listener |
1190 | * @fd: file descriptor of the new listener | ||
1191 | * @name_return: pointer to buffer to fill in with name of listener | ||
1192 | * @len: size of the buffer | ||
1193 | * | ||
1194 | * Fills in socket name and returns positive length of name if successful. | ||
1195 | * Name is terminated with '\n'. On error, returns a negative errno | ||
1196 | * value. | ||
1197 | */ | ||
1198 | int svc_addsock(struct svc_serv *serv, const int fd, char *name_return, | ||
1199 | const size_t len) | ||
1154 | { | 1200 | { |
1155 | int err = 0; | 1201 | int err = 0; |
1156 | struct socket *so = sockfd_lookup(fd, &err); | 1202 | struct socket *so = sockfd_lookup(fd, &err); |
@@ -1190,7 +1236,7 @@ int svc_addsock(struct svc_serv *serv, | |||
1190 | sockfd_put(so); | 1236 | sockfd_put(so); |
1191 | return err; | 1237 | return err; |
1192 | } | 1238 | } |
1193 | return one_sock_name(name_return, svsk); | 1239 | return svc_one_sock_name(svsk, name_return, len); |
1194 | } | 1240 | } |
1195 | EXPORT_SYMBOL_GPL(svc_addsock); | 1241 | EXPORT_SYMBOL_GPL(svc_addsock); |
1196 | 1242 | ||
@@ -1327,3 +1373,42 @@ static void svc_sock_free(struct svc_xprt *xprt) | |||
1327 | sock_release(svsk->sk_sock); | 1373 | sock_release(svsk->sk_sock); |
1328 | kfree(svsk); | 1374 | kfree(svsk); |
1329 | } | 1375 | } |
1376 | |||
1377 | /* | ||
1378 | * Create a svc_xprt. | ||
1379 | * | ||
1380 | * For internal use only (e.g. nfsv4.1 backchannel). | ||
1381 | * Callers should typically use the xpo_create() method. | ||
1382 | */ | ||
1383 | struct svc_xprt *svc_sock_create(struct svc_serv *serv, int prot) | ||
1384 | { | ||
1385 | struct svc_sock *svsk; | ||
1386 | struct svc_xprt *xprt = NULL; | ||
1387 | |||
1388 | dprintk("svc: %s\n", __func__); | ||
1389 | svsk = kzalloc(sizeof(*svsk), GFP_KERNEL); | ||
1390 | if (!svsk) | ||
1391 | goto out; | ||
1392 | |||
1393 | xprt = &svsk->sk_xprt; | ||
1394 | if (prot == IPPROTO_TCP) | ||
1395 | svc_xprt_init(&svc_tcp_class, xprt, serv); | ||
1396 | else if (prot == IPPROTO_UDP) | ||
1397 | svc_xprt_init(&svc_udp_class, xprt, serv); | ||
1398 | else | ||
1399 | BUG(); | ||
1400 | out: | ||
1401 | dprintk("svc: %s return %p\n", __func__, xprt); | ||
1402 | return xprt; | ||
1403 | } | ||
1404 | EXPORT_SYMBOL_GPL(svc_sock_create); | ||
1405 | |||
1406 | /* | ||
1407 | * Destroy a svc_sock. | ||
1408 | */ | ||
1409 | void svc_sock_destroy(struct svc_xprt *xprt) | ||
1410 | { | ||
1411 | if (xprt) | ||
1412 | kfree(container_of(xprt, struct svc_sock, sk_xprt)); | ||
1413 | } | ||
1414 | EXPORT_SYMBOL_GPL(svc_sock_destroy); | ||
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index 06ca058572f2..f412a852bc73 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c | |||
@@ -12,8 +12,9 @@ | |||
12 | * - Next, the caller puts together the RPC message, stuffs it into | 12 | * - Next, the caller puts together the RPC message, stuffs it into |
13 | * the request struct, and calls xprt_transmit(). | 13 | * the request struct, and calls xprt_transmit(). |
14 | * - xprt_transmit sends the message and installs the caller on the | 14 | * - xprt_transmit sends the message and installs the caller on the |
15 | * transport's wait list. At the same time, it installs a timer that | 15 | * transport's wait list. At the same time, if a reply is expected, |
16 | * is run after the packet's timeout has expired. | 16 | * it installs a timer that is run after the packet's timeout has |
17 | * expired. | ||
17 | * - When a packet arrives, the data_ready handler walks the list of | 18 | * - When a packet arrives, the data_ready handler walks the list of |
18 | * pending requests for that transport. If a matching XID is found, the | 19 | * pending requests for that transport. If a matching XID is found, the |
19 | * caller is woken up, and the timer removed. | 20 | * caller is woken up, and the timer removed. |
@@ -46,6 +47,8 @@ | |||
46 | #include <linux/sunrpc/clnt.h> | 47 | #include <linux/sunrpc/clnt.h> |
47 | #include <linux/sunrpc/metrics.h> | 48 | #include <linux/sunrpc/metrics.h> |
48 | 49 | ||
50 | #include "sunrpc.h" | ||
51 | |||
49 | /* | 52 | /* |
50 | * Local variables | 53 | * Local variables |
51 | */ | 54 | */ |
@@ -192,8 +195,8 @@ EXPORT_SYMBOL_GPL(xprt_load_transport); | |||
192 | */ | 195 | */ |
193 | int xprt_reserve_xprt(struct rpc_task *task) | 196 | int xprt_reserve_xprt(struct rpc_task *task) |
194 | { | 197 | { |
195 | struct rpc_xprt *xprt = task->tk_xprt; | ||
196 | struct rpc_rqst *req = task->tk_rqstp; | 198 | struct rpc_rqst *req = task->tk_rqstp; |
199 | struct rpc_xprt *xprt = req->rq_xprt; | ||
197 | 200 | ||
198 | if (test_and_set_bit(XPRT_LOCKED, &xprt->state)) { | 201 | if (test_and_set_bit(XPRT_LOCKED, &xprt->state)) { |
199 | if (task == xprt->snd_task) | 202 | if (task == xprt->snd_task) |
@@ -803,9 +806,10 @@ void xprt_complete_rqst(struct rpc_task *task, int copied) | |||
803 | 806 | ||
804 | list_del_init(&req->rq_list); | 807 | list_del_init(&req->rq_list); |
805 | req->rq_private_buf.len = copied; | 808 | req->rq_private_buf.len = copied; |
806 | /* Ensure all writes are done before we update req->rq_received */ | 809 | /* Ensure all writes are done before we update */ |
810 | /* req->rq_reply_bytes_recvd */ | ||
807 | smp_wmb(); | 811 | smp_wmb(); |
808 | req->rq_received = copied; | 812 | req->rq_reply_bytes_recvd = copied; |
809 | rpc_wake_up_queued_task(&xprt->pending, task); | 813 | rpc_wake_up_queued_task(&xprt->pending, task); |
810 | } | 814 | } |
811 | EXPORT_SYMBOL_GPL(xprt_complete_rqst); | 815 | EXPORT_SYMBOL_GPL(xprt_complete_rqst); |
@@ -820,7 +824,7 @@ static void xprt_timer(struct rpc_task *task) | |||
820 | dprintk("RPC: %5u xprt_timer\n", task->tk_pid); | 824 | dprintk("RPC: %5u xprt_timer\n", task->tk_pid); |
821 | 825 | ||
822 | spin_lock_bh(&xprt->transport_lock); | 826 | spin_lock_bh(&xprt->transport_lock); |
823 | if (!req->rq_received) { | 827 | if (!req->rq_reply_bytes_recvd) { |
824 | if (xprt->ops->timer) | 828 | if (xprt->ops->timer) |
825 | xprt->ops->timer(task); | 829 | xprt->ops->timer(task); |
826 | } else | 830 | } else |
@@ -842,8 +846,8 @@ int xprt_prepare_transmit(struct rpc_task *task) | |||
842 | dprintk("RPC: %5u xprt_prepare_transmit\n", task->tk_pid); | 846 | dprintk("RPC: %5u xprt_prepare_transmit\n", task->tk_pid); |
843 | 847 | ||
844 | spin_lock_bh(&xprt->transport_lock); | 848 | spin_lock_bh(&xprt->transport_lock); |
845 | if (req->rq_received && !req->rq_bytes_sent) { | 849 | if (req->rq_reply_bytes_recvd && !req->rq_bytes_sent) { |
846 | err = req->rq_received; | 850 | err = req->rq_reply_bytes_recvd; |
847 | goto out_unlock; | 851 | goto out_unlock; |
848 | } | 852 | } |
849 | if (!xprt->ops->reserve_xprt(task)) | 853 | if (!xprt->ops->reserve_xprt(task)) |
@@ -855,7 +859,7 @@ out_unlock: | |||
855 | 859 | ||
856 | void xprt_end_transmit(struct rpc_task *task) | 860 | void xprt_end_transmit(struct rpc_task *task) |
857 | { | 861 | { |
858 | xprt_release_write(task->tk_xprt, task); | 862 | xprt_release_write(task->tk_rqstp->rq_xprt, task); |
859 | } | 863 | } |
860 | 864 | ||
861 | /** | 865 | /** |
@@ -872,8 +876,11 @@ void xprt_transmit(struct rpc_task *task) | |||
872 | 876 | ||
873 | dprintk("RPC: %5u xprt_transmit(%u)\n", task->tk_pid, req->rq_slen); | 877 | dprintk("RPC: %5u xprt_transmit(%u)\n", task->tk_pid, req->rq_slen); |
874 | 878 | ||
875 | if (!req->rq_received) { | 879 | if (!req->rq_reply_bytes_recvd) { |
876 | if (list_empty(&req->rq_list)) { | 880 | if (list_empty(&req->rq_list) && rpc_reply_expected(task)) { |
881 | /* | ||
882 | * Add to the list only if we're expecting a reply | ||
883 | */ | ||
877 | spin_lock_bh(&xprt->transport_lock); | 884 | spin_lock_bh(&xprt->transport_lock); |
878 | /* Update the softirq receive buffer */ | 885 | /* Update the softirq receive buffer */ |
879 | memcpy(&req->rq_private_buf, &req->rq_rcv_buf, | 886 | memcpy(&req->rq_private_buf, &req->rq_rcv_buf, |
@@ -908,8 +915,13 @@ void xprt_transmit(struct rpc_task *task) | |||
908 | /* Don't race with disconnect */ | 915 | /* Don't race with disconnect */ |
909 | if (!xprt_connected(xprt)) | 916 | if (!xprt_connected(xprt)) |
910 | task->tk_status = -ENOTCONN; | 917 | task->tk_status = -ENOTCONN; |
911 | else if (!req->rq_received) | 918 | else if (!req->rq_reply_bytes_recvd && rpc_reply_expected(task)) { |
919 | /* | ||
920 | * Sleep on the pending queue since | ||
921 | * we're expecting a reply. | ||
922 | */ | ||
912 | rpc_sleep_on(&xprt->pending, task, xprt_timer); | 923 | rpc_sleep_on(&xprt->pending, task, xprt_timer); |
924 | } | ||
913 | spin_unlock_bh(&xprt->transport_lock); | 925 | spin_unlock_bh(&xprt->transport_lock); |
914 | } | 926 | } |
915 | 927 | ||
@@ -982,11 +994,17 @@ static void xprt_request_init(struct rpc_task *task, struct rpc_xprt *xprt) | |||
982 | */ | 994 | */ |
983 | void xprt_release(struct rpc_task *task) | 995 | void xprt_release(struct rpc_task *task) |
984 | { | 996 | { |
985 | struct rpc_xprt *xprt = task->tk_xprt; | 997 | struct rpc_xprt *xprt; |
986 | struct rpc_rqst *req; | 998 | struct rpc_rqst *req; |
999 | int is_bc_request; | ||
987 | 1000 | ||
988 | if (!(req = task->tk_rqstp)) | 1001 | if (!(req = task->tk_rqstp)) |
989 | return; | 1002 | return; |
1003 | |||
1004 | /* Preallocated backchannel request? */ | ||
1005 | is_bc_request = bc_prealloc(req); | ||
1006 | |||
1007 | xprt = req->rq_xprt; | ||
990 | rpc_count_iostats(task); | 1008 | rpc_count_iostats(task); |
991 | spin_lock_bh(&xprt->transport_lock); | 1009 | spin_lock_bh(&xprt->transport_lock); |
992 | xprt->ops->release_xprt(xprt, task); | 1010 | xprt->ops->release_xprt(xprt, task); |
@@ -999,10 +1017,19 @@ void xprt_release(struct rpc_task *task) | |||
999 | mod_timer(&xprt->timer, | 1017 | mod_timer(&xprt->timer, |
1000 | xprt->last_used + xprt->idle_timeout); | 1018 | xprt->last_used + xprt->idle_timeout); |
1001 | spin_unlock_bh(&xprt->transport_lock); | 1019 | spin_unlock_bh(&xprt->transport_lock); |
1002 | xprt->ops->buf_free(req->rq_buffer); | 1020 | if (!bc_prealloc(req)) |
1021 | xprt->ops->buf_free(req->rq_buffer); | ||
1003 | task->tk_rqstp = NULL; | 1022 | task->tk_rqstp = NULL; |
1004 | if (req->rq_release_snd_buf) | 1023 | if (req->rq_release_snd_buf) |
1005 | req->rq_release_snd_buf(req); | 1024 | req->rq_release_snd_buf(req); |
1025 | |||
1026 | /* | ||
1027 | * Early exit if this is a backchannel preallocated request. | ||
1028 | * There is no need to have it added to the RPC slot list. | ||
1029 | */ | ||
1030 | if (is_bc_request) | ||
1031 | return; | ||
1032 | |||
1006 | memset(req, 0, sizeof(*req)); /* mark unused */ | 1033 | memset(req, 0, sizeof(*req)); /* mark unused */ |
1007 | 1034 | ||
1008 | dprintk("RPC: %5u release request %p\n", task->tk_pid, req); | 1035 | dprintk("RPC: %5u release request %p\n", task->tk_pid, req); |
@@ -1049,6 +1076,11 @@ found: | |||
1049 | 1076 | ||
1050 | INIT_LIST_HEAD(&xprt->free); | 1077 | INIT_LIST_HEAD(&xprt->free); |
1051 | INIT_LIST_HEAD(&xprt->recv); | 1078 | INIT_LIST_HEAD(&xprt->recv); |
1079 | #if defined(CONFIG_NFS_V4_1) | ||
1080 | spin_lock_init(&xprt->bc_pa_lock); | ||
1081 | INIT_LIST_HEAD(&xprt->bc_pa_list); | ||
1082 | #endif /* CONFIG_NFS_V4_1 */ | ||
1083 | |||
1052 | INIT_WORK(&xprt->task_cleanup, xprt_autoclose); | 1084 | INIT_WORK(&xprt->task_cleanup, xprt_autoclose); |
1053 | setup_timer(&xprt->timer, xprt_init_autodisconnect, | 1085 | setup_timer(&xprt->timer, xprt_init_autodisconnect, |
1054 | (unsigned long)xprt); | 1086 | (unsigned long)xprt); |
diff --git a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c index 42a6f9f20285..9e884383134f 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c +++ b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c | |||
@@ -397,14 +397,14 @@ static int rdma_read_xdr(struct svcxprt_rdma *xprt, | |||
397 | if (!ch) | 397 | if (!ch) |
398 | return 0; | 398 | return 0; |
399 | 399 | ||
400 | /* Allocate temporary reply and chunk maps */ | ||
401 | rpl_map = svc_rdma_get_req_map(); | ||
402 | chl_map = svc_rdma_get_req_map(); | ||
403 | |||
404 | svc_rdma_rcl_chunk_counts(ch, &ch_count, &byte_count); | 400 | svc_rdma_rcl_chunk_counts(ch, &ch_count, &byte_count); |
405 | if (ch_count > RPCSVC_MAXPAGES) | 401 | if (ch_count > RPCSVC_MAXPAGES) |
406 | return -EINVAL; | 402 | return -EINVAL; |
407 | 403 | ||
404 | /* Allocate temporary reply and chunk maps */ | ||
405 | rpl_map = svc_rdma_get_req_map(); | ||
406 | chl_map = svc_rdma_get_req_map(); | ||
407 | |||
408 | if (!xprt->sc_frmr_pg_list_len) | 408 | if (!xprt->sc_frmr_pg_list_len) |
409 | sge_count = map_read_chunks(xprt, rqstp, hdr_ctxt, rmsgp, | 409 | sge_count = map_read_chunks(xprt, rqstp, hdr_ctxt, rmsgp, |
410 | rpl_map, chl_map, ch_count, | 410 | rpl_map, chl_map, ch_count, |
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 6c2d61586551..83c73c4d017a 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c | |||
@@ -34,6 +34,9 @@ | |||
34 | #include <linux/sunrpc/sched.h> | 34 | #include <linux/sunrpc/sched.h> |
35 | #include <linux/sunrpc/xprtsock.h> | 35 | #include <linux/sunrpc/xprtsock.h> |
36 | #include <linux/file.h> | 36 | #include <linux/file.h> |
37 | #ifdef CONFIG_NFS_V4_1 | ||
38 | #include <linux/sunrpc/bc_xprt.h> | ||
39 | #endif | ||
37 | 40 | ||
38 | #include <net/sock.h> | 41 | #include <net/sock.h> |
39 | #include <net/checksum.h> | 42 | #include <net/checksum.h> |
@@ -270,6 +273,13 @@ struct sock_xprt { | |||
270 | #define TCP_RCV_COPY_FRAGHDR (1UL << 1) | 273 | #define TCP_RCV_COPY_FRAGHDR (1UL << 1) |
271 | #define TCP_RCV_COPY_XID (1UL << 2) | 274 | #define TCP_RCV_COPY_XID (1UL << 2) |
272 | #define TCP_RCV_COPY_DATA (1UL << 3) | 275 | #define TCP_RCV_COPY_DATA (1UL << 3) |
276 | #define TCP_RCV_READ_CALLDIR (1UL << 4) | ||
277 | #define TCP_RCV_COPY_CALLDIR (1UL << 5) | ||
278 | |||
279 | /* | ||
280 | * TCP RPC flags | ||
281 | */ | ||
282 | #define TCP_RPC_REPLY (1UL << 6) | ||
273 | 283 | ||
274 | static inline struct sockaddr *xs_addr(struct rpc_xprt *xprt) | 284 | static inline struct sockaddr *xs_addr(struct rpc_xprt *xprt) |
275 | { | 285 | { |
@@ -956,7 +966,7 @@ static inline void xs_tcp_read_fraghdr(struct rpc_xprt *xprt, struct xdr_skb_rea | |||
956 | transport->tcp_offset = 0; | 966 | transport->tcp_offset = 0; |
957 | 967 | ||
958 | /* Sanity check of the record length */ | 968 | /* Sanity check of the record length */ |
959 | if (unlikely(transport->tcp_reclen < 4)) { | 969 | if (unlikely(transport->tcp_reclen < 8)) { |
960 | dprintk("RPC: invalid TCP record fragment length\n"); | 970 | dprintk("RPC: invalid TCP record fragment length\n"); |
961 | xprt_force_disconnect(xprt); | 971 | xprt_force_disconnect(xprt); |
962 | return; | 972 | return; |
@@ -991,33 +1001,77 @@ static inline void xs_tcp_read_xid(struct sock_xprt *transport, struct xdr_skb_r | |||
991 | if (used != len) | 1001 | if (used != len) |
992 | return; | 1002 | return; |
993 | transport->tcp_flags &= ~TCP_RCV_COPY_XID; | 1003 | transport->tcp_flags &= ~TCP_RCV_COPY_XID; |
994 | transport->tcp_flags |= TCP_RCV_COPY_DATA; | 1004 | transport->tcp_flags |= TCP_RCV_READ_CALLDIR; |
995 | transport->tcp_copied = 4; | 1005 | transport->tcp_copied = 4; |
996 | dprintk("RPC: reading reply for XID %08x\n", | 1006 | dprintk("RPC: reading %s XID %08x\n", |
1007 | (transport->tcp_flags & TCP_RPC_REPLY) ? "reply for" | ||
1008 | : "request with", | ||
997 | ntohl(transport->tcp_xid)); | 1009 | ntohl(transport->tcp_xid)); |
998 | xs_tcp_check_fraghdr(transport); | 1010 | xs_tcp_check_fraghdr(transport); |
999 | } | 1011 | } |
1000 | 1012 | ||
1001 | static inline void xs_tcp_read_request(struct rpc_xprt *xprt, struct xdr_skb_reader *desc) | 1013 | static inline void xs_tcp_read_calldir(struct sock_xprt *transport, |
1014 | struct xdr_skb_reader *desc) | ||
1002 | { | 1015 | { |
1003 | struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); | 1016 | size_t len, used; |
1004 | struct rpc_rqst *req; | 1017 | u32 offset; |
1018 | __be32 calldir; | ||
1019 | |||
1020 | /* | ||
1021 | * We want transport->tcp_offset to be 8 at the end of this routine | ||
1022 | * (4 bytes for the xid and 4 bytes for the call/reply flag). | ||
1023 | * When this function is called for the first time, | ||
1024 | * transport->tcp_offset is 4 (after having already read the xid). | ||
1025 | */ | ||
1026 | offset = transport->tcp_offset - sizeof(transport->tcp_xid); | ||
1027 | len = sizeof(calldir) - offset; | ||
1028 | dprintk("RPC: reading CALL/REPLY flag (%Zu bytes)\n", len); | ||
1029 | used = xdr_skb_read_bits(desc, &calldir, len); | ||
1030 | transport->tcp_offset += used; | ||
1031 | if (used != len) | ||
1032 | return; | ||
1033 | transport->tcp_flags &= ~TCP_RCV_READ_CALLDIR; | ||
1034 | transport->tcp_flags |= TCP_RCV_COPY_CALLDIR; | ||
1035 | transport->tcp_flags |= TCP_RCV_COPY_DATA; | ||
1036 | /* | ||
1037 | * We don't yet have the XDR buffer, so we will write the calldir | ||
1038 | * out after we get the buffer from the 'struct rpc_rqst' | ||
1039 | */ | ||
1040 | if (ntohl(calldir) == RPC_REPLY) | ||
1041 | transport->tcp_flags |= TCP_RPC_REPLY; | ||
1042 | else | ||
1043 | transport->tcp_flags &= ~TCP_RPC_REPLY; | ||
1044 | dprintk("RPC: reading %s CALL/REPLY flag %08x\n", | ||
1045 | (transport->tcp_flags & TCP_RPC_REPLY) ? | ||
1046 | "reply for" : "request with", calldir); | ||
1047 | xs_tcp_check_fraghdr(transport); | ||
1048 | } | ||
1049 | |||
1050 | static inline void xs_tcp_read_common(struct rpc_xprt *xprt, | ||
1051 | struct xdr_skb_reader *desc, | ||
1052 | struct rpc_rqst *req) | ||
1053 | { | ||
1054 | struct sock_xprt *transport = | ||
1055 | container_of(xprt, struct sock_xprt, xprt); | ||
1005 | struct xdr_buf *rcvbuf; | 1056 | struct xdr_buf *rcvbuf; |
1006 | size_t len; | 1057 | size_t len; |
1007 | ssize_t r; | 1058 | ssize_t r; |
1008 | 1059 | ||
1009 | /* Find and lock the request corresponding to this xid */ | 1060 | rcvbuf = &req->rq_private_buf; |
1010 | spin_lock(&xprt->transport_lock); | 1061 | |
1011 | req = xprt_lookup_rqst(xprt, transport->tcp_xid); | 1062 | if (transport->tcp_flags & TCP_RCV_COPY_CALLDIR) { |
1012 | if (!req) { | 1063 | /* |
1013 | transport->tcp_flags &= ~TCP_RCV_COPY_DATA; | 1064 | * Save the RPC direction in the XDR buffer |
1014 | dprintk("RPC: XID %08x request not found!\n", | 1065 | */ |
1015 | ntohl(transport->tcp_xid)); | 1066 | __be32 calldir = transport->tcp_flags & TCP_RPC_REPLY ? |
1016 | spin_unlock(&xprt->transport_lock); | 1067 | htonl(RPC_REPLY) : 0; |
1017 | return; | 1068 | |
1069 | memcpy(rcvbuf->head[0].iov_base + transport->tcp_copied, | ||
1070 | &calldir, sizeof(calldir)); | ||
1071 | transport->tcp_copied += sizeof(calldir); | ||
1072 | transport->tcp_flags &= ~TCP_RCV_COPY_CALLDIR; | ||
1018 | } | 1073 | } |
1019 | 1074 | ||
1020 | rcvbuf = &req->rq_private_buf; | ||
1021 | len = desc->count; | 1075 | len = desc->count; |
1022 | if (len > transport->tcp_reclen - transport->tcp_offset) { | 1076 | if (len > transport->tcp_reclen - transport->tcp_offset) { |
1023 | struct xdr_skb_reader my_desc; | 1077 | struct xdr_skb_reader my_desc; |
@@ -1054,7 +1108,7 @@ static inline void xs_tcp_read_request(struct rpc_xprt *xprt, struct xdr_skb_rea | |||
1054 | "tcp_offset = %u, tcp_reclen = %u\n", | 1108 | "tcp_offset = %u, tcp_reclen = %u\n", |
1055 | xprt, transport->tcp_copied, | 1109 | xprt, transport->tcp_copied, |
1056 | transport->tcp_offset, transport->tcp_reclen); | 1110 | transport->tcp_offset, transport->tcp_reclen); |
1057 | goto out; | 1111 | return; |
1058 | } | 1112 | } |
1059 | 1113 | ||
1060 | dprintk("RPC: XID %08x read %Zd bytes\n", | 1114 | dprintk("RPC: XID %08x read %Zd bytes\n", |
@@ -1070,11 +1124,125 @@ static inline void xs_tcp_read_request(struct rpc_xprt *xprt, struct xdr_skb_rea | |||
1070 | transport->tcp_flags &= ~TCP_RCV_COPY_DATA; | 1124 | transport->tcp_flags &= ~TCP_RCV_COPY_DATA; |
1071 | } | 1125 | } |
1072 | 1126 | ||
1073 | out: | 1127 | return; |
1128 | } | ||
1129 | |||
1130 | /* | ||
1131 | * Finds the request corresponding to the RPC xid and invokes the common | ||
1132 | * tcp read code to read the data. | ||
1133 | */ | ||
1134 | static inline int xs_tcp_read_reply(struct rpc_xprt *xprt, | ||
1135 | struct xdr_skb_reader *desc) | ||
1136 | { | ||
1137 | struct sock_xprt *transport = | ||
1138 | container_of(xprt, struct sock_xprt, xprt); | ||
1139 | struct rpc_rqst *req; | ||
1140 | |||
1141 | dprintk("RPC: read reply XID %08x\n", ntohl(transport->tcp_xid)); | ||
1142 | |||
1143 | /* Find and lock the request corresponding to this xid */ | ||
1144 | spin_lock(&xprt->transport_lock); | ||
1145 | req = xprt_lookup_rqst(xprt, transport->tcp_xid); | ||
1146 | if (!req) { | ||
1147 | dprintk("RPC: XID %08x request not found!\n", | ||
1148 | ntohl(transport->tcp_xid)); | ||
1149 | spin_unlock(&xprt->transport_lock); | ||
1150 | return -1; | ||
1151 | } | ||
1152 | |||
1153 | xs_tcp_read_common(xprt, desc, req); | ||
1154 | |||
1074 | if (!(transport->tcp_flags & TCP_RCV_COPY_DATA)) | 1155 | if (!(transport->tcp_flags & TCP_RCV_COPY_DATA)) |
1075 | xprt_complete_rqst(req->rq_task, transport->tcp_copied); | 1156 | xprt_complete_rqst(req->rq_task, transport->tcp_copied); |
1157 | |||
1076 | spin_unlock(&xprt->transport_lock); | 1158 | spin_unlock(&xprt->transport_lock); |
1077 | xs_tcp_check_fraghdr(transport); | 1159 | return 0; |
1160 | } | ||
1161 | |||
1162 | #if defined(CONFIG_NFS_V4_1) | ||
1163 | /* | ||
1164 | * Obtains an rpc_rqst previously allocated and invokes the common | ||
1165 | * tcp read code to read the data. The result is placed in the callback | ||
1166 | * queue. | ||
1167 | * If we're unable to obtain the rpc_rqst we schedule the closing of the | ||
1168 | * connection and return -1. | ||
1169 | */ | ||
1170 | static inline int xs_tcp_read_callback(struct rpc_xprt *xprt, | ||
1171 | struct xdr_skb_reader *desc) | ||
1172 | { | ||
1173 | struct sock_xprt *transport = | ||
1174 | container_of(xprt, struct sock_xprt, xprt); | ||
1175 | struct rpc_rqst *req; | ||
1176 | |||
1177 | req = xprt_alloc_bc_request(xprt); | ||
1178 | if (req == NULL) { | ||
1179 | printk(KERN_WARNING "Callback slot table overflowed\n"); | ||
1180 | xprt_force_disconnect(xprt); | ||
1181 | return -1; | ||
1182 | } | ||
1183 | |||
1184 | req->rq_xid = transport->tcp_xid; | ||
1185 | dprintk("RPC: read callback XID %08x\n", ntohl(req->rq_xid)); | ||
1186 | xs_tcp_read_common(xprt, desc, req); | ||
1187 | |||
1188 | if (!(transport->tcp_flags & TCP_RCV_COPY_DATA)) { | ||
1189 | struct svc_serv *bc_serv = xprt->bc_serv; | ||
1190 | |||
1191 | /* | ||
1192 | * Add callback request to callback list. The callback | ||
1193 | * service sleeps on the sv_cb_waitq waiting for new | ||
1194 | * requests. Wake it up after adding enqueing the | ||
1195 | * request. | ||
1196 | */ | ||
1197 | dprintk("RPC: add callback request to list\n"); | ||
1198 | spin_lock(&bc_serv->sv_cb_lock); | ||
1199 | list_add(&req->rq_bc_list, &bc_serv->sv_cb_list); | ||
1200 | spin_unlock(&bc_serv->sv_cb_lock); | ||
1201 | wake_up(&bc_serv->sv_cb_waitq); | ||
1202 | } | ||
1203 | |||
1204 | req->rq_private_buf.len = transport->tcp_copied; | ||
1205 | |||
1206 | return 0; | ||
1207 | } | ||
1208 | |||
1209 | static inline int _xs_tcp_read_data(struct rpc_xprt *xprt, | ||
1210 | struct xdr_skb_reader *desc) | ||
1211 | { | ||
1212 | struct sock_xprt *transport = | ||
1213 | container_of(xprt, struct sock_xprt, xprt); | ||
1214 | |||
1215 | return (transport->tcp_flags & TCP_RPC_REPLY) ? | ||
1216 | xs_tcp_read_reply(xprt, desc) : | ||
1217 | xs_tcp_read_callback(xprt, desc); | ||
1218 | } | ||
1219 | #else | ||
1220 | static inline int _xs_tcp_read_data(struct rpc_xprt *xprt, | ||
1221 | struct xdr_skb_reader *desc) | ||
1222 | { | ||
1223 | return xs_tcp_read_reply(xprt, desc); | ||
1224 | } | ||
1225 | #endif /* CONFIG_NFS_V4_1 */ | ||
1226 | |||
1227 | /* | ||
1228 | * Read data off the transport. This can be either an RPC_CALL or an | ||
1229 | * RPC_REPLY. Relay the processing to helper functions. | ||
1230 | */ | ||
1231 | static void xs_tcp_read_data(struct rpc_xprt *xprt, | ||
1232 | struct xdr_skb_reader *desc) | ||
1233 | { | ||
1234 | struct sock_xprt *transport = | ||
1235 | container_of(xprt, struct sock_xprt, xprt); | ||
1236 | |||
1237 | if (_xs_tcp_read_data(xprt, desc) == 0) | ||
1238 | xs_tcp_check_fraghdr(transport); | ||
1239 | else { | ||
1240 | /* | ||
1241 | * The transport_lock protects the request handling. | ||
1242 | * There's no need to hold it to update the tcp_flags. | ||
1243 | */ | ||
1244 | transport->tcp_flags &= ~TCP_RCV_COPY_DATA; | ||
1245 | } | ||
1078 | } | 1246 | } |
1079 | 1247 | ||
1080 | static inline void xs_tcp_read_discard(struct sock_xprt *transport, struct xdr_skb_reader *desc) | 1248 | static inline void xs_tcp_read_discard(struct sock_xprt *transport, struct xdr_skb_reader *desc) |
@@ -1114,9 +1282,14 @@ static int xs_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb, uns | |||
1114 | xs_tcp_read_xid(transport, &desc); | 1282 | xs_tcp_read_xid(transport, &desc); |
1115 | continue; | 1283 | continue; |
1116 | } | 1284 | } |
1285 | /* Read in the call/reply flag */ | ||
1286 | if (transport->tcp_flags & TCP_RCV_READ_CALLDIR) { | ||
1287 | xs_tcp_read_calldir(transport, &desc); | ||
1288 | continue; | ||
1289 | } | ||
1117 | /* Read in the request data */ | 1290 | /* Read in the request data */ |
1118 | if (transport->tcp_flags & TCP_RCV_COPY_DATA) { | 1291 | if (transport->tcp_flags & TCP_RCV_COPY_DATA) { |
1119 | xs_tcp_read_request(xprt, &desc); | 1292 | xs_tcp_read_data(xprt, &desc); |
1120 | continue; | 1293 | continue; |
1121 | } | 1294 | } |
1122 | /* Skip over any trailing bytes on short reads */ | 1295 | /* Skip over any trailing bytes on short reads */ |
@@ -1792,6 +1965,7 @@ static void xs_tcp_setup_socket(struct rpc_xprt *xprt, | |||
1792 | */ | 1965 | */ |
1793 | set_bit(XPRT_CONNECTION_CLOSE, &xprt->state); | 1966 | set_bit(XPRT_CONNECTION_CLOSE, &xprt->state); |
1794 | xprt_force_disconnect(xprt); | 1967 | xprt_force_disconnect(xprt); |
1968 | break; | ||
1795 | case -ECONNREFUSED: | 1969 | case -ECONNREFUSED: |
1796 | case -ECONNRESET: | 1970 | case -ECONNRESET: |
1797 | case -ENETUNREACH: | 1971 | case -ENETUNREACH: |
@@ -2010,6 +2184,9 @@ static struct rpc_xprt_ops xs_tcp_ops = { | |||
2010 | .buf_free = rpc_free, | 2184 | .buf_free = rpc_free, |
2011 | .send_request = xs_tcp_send_request, | 2185 | .send_request = xs_tcp_send_request, |
2012 | .set_retrans_timeout = xprt_set_retrans_timeout_def, | 2186 | .set_retrans_timeout = xprt_set_retrans_timeout_def, |
2187 | #if defined(CONFIG_NFS_V4_1) | ||
2188 | .release_request = bc_release_request, | ||
2189 | #endif /* CONFIG_NFS_V4_1 */ | ||
2013 | .close = xs_tcp_close, | 2190 | .close = xs_tcp_close, |
2014 | .destroy = xs_destroy, | 2191 | .destroy = xs_destroy, |
2015 | .print_stats = xs_tcp_print_stats, | 2192 | .print_stats = xs_tcp_print_stats, |
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 9dcc6e7f96ec..fc3ebb906911 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c | |||
@@ -315,7 +315,7 @@ static void unix_write_space(struct sock *sk) | |||
315 | { | 315 | { |
316 | read_lock(&sk->sk_callback_lock); | 316 | read_lock(&sk->sk_callback_lock); |
317 | if (unix_writable(sk)) { | 317 | if (unix_writable(sk)) { |
318 | if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) | 318 | if (sk_has_sleeper(sk)) |
319 | wake_up_interruptible_sync(sk->sk_sleep); | 319 | wake_up_interruptible_sync(sk->sk_sleep); |
320 | sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); | 320 | sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT); |
321 | } | 321 | } |
@@ -1946,7 +1946,7 @@ static int unix_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
1946 | 1946 | ||
1947 | switch (cmd) { | 1947 | switch (cmd) { |
1948 | case SIOCOUTQ: | 1948 | case SIOCOUTQ: |
1949 | amount = atomic_read(&sk->sk_wmem_alloc); | 1949 | amount = sk_wmem_alloc_get(sk); |
1950 | err = put_user(amount, (int __user *)arg); | 1950 | err = put_user(amount, (int __user *)arg); |
1951 | break; | 1951 | break; |
1952 | case SIOCINQ: | 1952 | case SIOCINQ: |
@@ -1985,7 +1985,7 @@ static unsigned int unix_poll(struct file *file, struct socket *sock, poll_table | |||
1985 | struct sock *sk = sock->sk; | 1985 | struct sock *sk = sock->sk; |
1986 | unsigned int mask; | 1986 | unsigned int mask; |
1987 | 1987 | ||
1988 | poll_wait(file, sk->sk_sleep, wait); | 1988 | sock_poll_wait(file, sk->sk_sleep, wait); |
1989 | mask = 0; | 1989 | mask = 0; |
1990 | 1990 | ||
1991 | /* exceptional events? */ | 1991 | /* exceptional events? */ |
@@ -2022,7 +2022,7 @@ static unsigned int unix_dgram_poll(struct file *file, struct socket *sock, | |||
2022 | struct sock *sk = sock->sk, *other; | 2022 | struct sock *sk = sock->sk, *other; |
2023 | unsigned int mask, writable; | 2023 | unsigned int mask, writable; |
2024 | 2024 | ||
2025 | poll_wait(file, sk->sk_sleep, wait); | 2025 | sock_poll_wait(file, sk->sk_sleep, wait); |
2026 | mask = 0; | 2026 | mask = 0; |
2027 | 2027 | ||
2028 | /* exceptional events? */ | 2028 | /* exceptional events? */ |
@@ -2053,7 +2053,7 @@ static unsigned int unix_dgram_poll(struct file *file, struct socket *sock, | |||
2053 | other = unix_peer_get(sk); | 2053 | other = unix_peer_get(sk); |
2054 | if (other) { | 2054 | if (other) { |
2055 | if (unix_peer(other) != sk) { | 2055 | if (unix_peer(other) != sk) { |
2056 | poll_wait(file, &unix_sk(other)->peer_wait, | 2056 | sock_poll_wait(file, &unix_sk(other)->peer_wait, |
2057 | wait); | 2057 | wait); |
2058 | if (unix_recvq_full(other)) | 2058 | if (unix_recvq_full(other)) |
2059 | writable = 0; | 2059 | writable = 0; |
diff --git a/net/wanrouter/wanmain.c b/net/wanrouter/wanmain.c index 466e2d22d256..258daa80ad92 100644 --- a/net/wanrouter/wanmain.c +++ b/net/wanrouter/wanmain.c | |||
@@ -48,6 +48,7 @@ | |||
48 | #include <linux/kernel.h> | 48 | #include <linux/kernel.h> |
49 | #include <linux/module.h> /* support for loadable modules */ | 49 | #include <linux/module.h> /* support for loadable modules */ |
50 | #include <linux/slab.h> /* kmalloc(), kfree() */ | 50 | #include <linux/slab.h> /* kmalloc(), kfree() */ |
51 | #include <linux/smp_lock.h> | ||
51 | #include <linux/mm.h> | 52 | #include <linux/mm.h> |
52 | #include <linux/string.h> /* inline mem*, str* functions */ | 53 | #include <linux/string.h> /* inline mem*, str* functions */ |
53 | 54 | ||
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 24168560ebae..634496b3ed77 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -447,6 +447,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) | |||
447 | 447 | ||
448 | rdev = __cfg80211_drv_from_info(info); | 448 | rdev = __cfg80211_drv_from_info(info); |
449 | if (IS_ERR(rdev)) { | 449 | if (IS_ERR(rdev)) { |
450 | mutex_unlock(&cfg80211_mutex); | ||
450 | result = PTR_ERR(rdev); | 451 | result = PTR_ERR(rdev); |
451 | goto unlock; | 452 | goto unlock; |
452 | } | 453 | } |
@@ -996,7 +997,7 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info) | |||
996 | 997 | ||
997 | if (IS_ERR(hdr)) { | 998 | if (IS_ERR(hdr)) { |
998 | err = PTR_ERR(hdr); | 999 | err = PTR_ERR(hdr); |
999 | goto out; | 1000 | goto free_msg; |
1000 | } | 1001 | } |
1001 | 1002 | ||
1002 | cookie.msg = msg; | 1003 | cookie.msg = msg; |
@@ -1010,7 +1011,7 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info) | |||
1010 | &cookie, get_key_callback); | 1011 | &cookie, get_key_callback); |
1011 | 1012 | ||
1012 | if (err) | 1013 | if (err) |
1013 | goto out; | 1014 | goto free_msg; |
1014 | 1015 | ||
1015 | if (cookie.error) | 1016 | if (cookie.error) |
1016 | goto nla_put_failure; | 1017 | goto nla_put_failure; |
@@ -1021,6 +1022,7 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info) | |||
1021 | 1022 | ||
1022 | nla_put_failure: | 1023 | nla_put_failure: |
1023 | err = -ENOBUFS; | 1024 | err = -ENOBUFS; |
1025 | free_msg: | ||
1024 | nlmsg_free(msg); | 1026 | nlmsg_free(msg); |
1025 | out: | 1027 | out: |
1026 | cfg80211_put_dev(drv); | 1028 | cfg80211_put_dev(drv); |
@@ -1687,13 +1689,52 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) | |||
1687 | if (err) | 1689 | if (err) |
1688 | goto out_rtnl; | 1690 | goto out_rtnl; |
1689 | 1691 | ||
1690 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && | 1692 | err = get_vlan(info->attrs[NL80211_ATTR_STA_VLAN], drv, ¶ms.vlan); |
1691 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN) { | 1693 | if (err) |
1692 | err = -EINVAL; | ||
1693 | goto out; | 1694 | goto out; |
1695 | |||
1696 | /* validate settings */ | ||
1697 | err = 0; | ||
1698 | |||
1699 | switch (dev->ieee80211_ptr->iftype) { | ||
1700 | case NL80211_IFTYPE_AP: | ||
1701 | case NL80211_IFTYPE_AP_VLAN: | ||
1702 | /* disallow mesh-specific things */ | ||
1703 | if (params.plink_action) | ||
1704 | err = -EINVAL; | ||
1705 | break; | ||
1706 | case NL80211_IFTYPE_STATION: | ||
1707 | /* disallow everything but AUTHORIZED flag */ | ||
1708 | if (params.plink_action) | ||
1709 | err = -EINVAL; | ||
1710 | if (params.vlan) | ||
1711 | err = -EINVAL; | ||
1712 | if (params.supported_rates) | ||
1713 | err = -EINVAL; | ||
1714 | if (params.ht_capa) | ||
1715 | err = -EINVAL; | ||
1716 | if (params.listen_interval >= 0) | ||
1717 | err = -EINVAL; | ||
1718 | if (params.sta_flags_mask & ~BIT(NL80211_STA_FLAG_AUTHORIZED)) | ||
1719 | err = -EINVAL; | ||
1720 | break; | ||
1721 | case NL80211_IFTYPE_MESH_POINT: | ||
1722 | /* disallow things mesh doesn't support */ | ||
1723 | if (params.vlan) | ||
1724 | err = -EINVAL; | ||
1725 | if (params.ht_capa) | ||
1726 | err = -EINVAL; | ||
1727 | if (params.listen_interval >= 0) | ||
1728 | err = -EINVAL; | ||
1729 | if (params.supported_rates) | ||
1730 | err = -EINVAL; | ||
1731 | if (params.sta_flags_mask) | ||
1732 | err = -EINVAL; | ||
1733 | break; | ||
1734 | default: | ||
1735 | err = -EINVAL; | ||
1694 | } | 1736 | } |
1695 | 1737 | ||
1696 | err = get_vlan(info->attrs[NL80211_ATTR_STA_VLAN], drv, ¶ms.vlan); | ||
1697 | if (err) | 1738 | if (err) |
1698 | goto out; | 1739 | goto out; |
1699 | 1740 | ||
@@ -1728,9 +1769,6 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) | |||
1728 | if (!info->attrs[NL80211_ATTR_MAC]) | 1769 | if (!info->attrs[NL80211_ATTR_MAC]) |
1729 | return -EINVAL; | 1770 | return -EINVAL; |
1730 | 1771 | ||
1731 | if (!info->attrs[NL80211_ATTR_STA_AID]) | ||
1732 | return -EINVAL; | ||
1733 | |||
1734 | if (!info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]) | 1772 | if (!info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]) |
1735 | return -EINVAL; | 1773 | return -EINVAL; |
1736 | 1774 | ||
@@ -1745,9 +1783,11 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) | |||
1745 | params.listen_interval = | 1783 | params.listen_interval = |
1746 | nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]); | 1784 | nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]); |
1747 | 1785 | ||
1748 | params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]); | 1786 | if (info->attrs[NL80211_ATTR_STA_AID]) { |
1749 | if (!params.aid || params.aid > IEEE80211_MAX_AID) | 1787 | params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]); |
1750 | return -EINVAL; | 1788 | if (!params.aid || params.aid > IEEE80211_MAX_AID) |
1789 | return -EINVAL; | ||
1790 | } | ||
1751 | 1791 | ||
1752 | if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) | 1792 | if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) |
1753 | params.ht_capa = | 1793 | params.ht_capa = |
@@ -1762,13 +1802,39 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) | |||
1762 | if (err) | 1802 | if (err) |
1763 | goto out_rtnl; | 1803 | goto out_rtnl; |
1764 | 1804 | ||
1765 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && | 1805 | err = get_vlan(info->attrs[NL80211_ATTR_STA_VLAN], drv, ¶ms.vlan); |
1766 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN) { | 1806 | if (err) |
1767 | err = -EINVAL; | ||
1768 | goto out; | 1807 | goto out; |
1808 | |||
1809 | /* validate settings */ | ||
1810 | err = 0; | ||
1811 | |||
1812 | switch (dev->ieee80211_ptr->iftype) { | ||
1813 | case NL80211_IFTYPE_AP: | ||
1814 | case NL80211_IFTYPE_AP_VLAN: | ||
1815 | /* all ok but must have AID */ | ||
1816 | if (!params.aid) | ||
1817 | err = -EINVAL; | ||
1818 | break; | ||
1819 | case NL80211_IFTYPE_MESH_POINT: | ||
1820 | /* disallow things mesh doesn't support */ | ||
1821 | if (params.vlan) | ||
1822 | err = -EINVAL; | ||
1823 | if (params.aid) | ||
1824 | err = -EINVAL; | ||
1825 | if (params.ht_capa) | ||
1826 | err = -EINVAL; | ||
1827 | if (params.listen_interval >= 0) | ||
1828 | err = -EINVAL; | ||
1829 | if (params.supported_rates) | ||
1830 | err = -EINVAL; | ||
1831 | if (params.sta_flags_mask) | ||
1832 | err = -EINVAL; | ||
1833 | break; | ||
1834 | default: | ||
1835 | err = -EINVAL; | ||
1769 | } | 1836 | } |
1770 | 1837 | ||
1771 | err = get_vlan(info->attrs[NL80211_ATTR_STA_VLAN], drv, ¶ms.vlan); | ||
1772 | if (err) | 1838 | if (err) |
1773 | goto out; | 1839 | goto out; |
1774 | 1840 | ||
@@ -1812,7 +1878,8 @@ static int nl80211_del_station(struct sk_buff *skb, struct genl_info *info) | |||
1812 | goto out_rtnl; | 1878 | goto out_rtnl; |
1813 | 1879 | ||
1814 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && | 1880 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && |
1815 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN) { | 1881 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN && |
1882 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT) { | ||
1816 | err = -EINVAL; | 1883 | err = -EINVAL; |
1817 | goto out; | 1884 | goto out; |
1818 | } | 1885 | } |
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 5e14371cda70..75a406d33619 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
@@ -1089,17 +1089,18 @@ static void handle_reg_beacon(struct wiphy *wiphy, | |||
1089 | 1089 | ||
1090 | chan->beacon_found = true; | 1090 | chan->beacon_found = true; |
1091 | 1091 | ||
1092 | if (wiphy->disable_beacon_hints) | ||
1093 | return; | ||
1094 | |||
1092 | chan_before.center_freq = chan->center_freq; | 1095 | chan_before.center_freq = chan->center_freq; |
1093 | chan_before.flags = chan->flags; | 1096 | chan_before.flags = chan->flags; |
1094 | 1097 | ||
1095 | if ((chan->flags & IEEE80211_CHAN_PASSIVE_SCAN) && | 1098 | if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN) { |
1096 | !(chan->orig_flags & IEEE80211_CHAN_PASSIVE_SCAN)) { | ||
1097 | chan->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; | 1099 | chan->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; |
1098 | channel_changed = true; | 1100 | channel_changed = true; |
1099 | } | 1101 | } |
1100 | 1102 | ||
1101 | if ((chan->flags & IEEE80211_CHAN_NO_IBSS) && | 1103 | if (chan->flags & IEEE80211_CHAN_NO_IBSS) { |
1102 | !(chan->orig_flags & IEEE80211_CHAN_NO_IBSS)) { | ||
1103 | chan->flags &= ~IEEE80211_CHAN_NO_IBSS; | 1104 | chan->flags &= ~IEEE80211_CHAN_NO_IBSS; |
1104 | channel_changed = true; | 1105 | channel_changed = true; |
1105 | } | 1106 | } |
diff --git a/net/wireless/reg.h b/net/wireless/reg.h index e37829a49dc4..4e167a8e11be 100644 --- a/net/wireless/reg.h +++ b/net/wireless/reg.h | |||
@@ -30,7 +30,8 @@ int set_regdom(const struct ieee80211_regdomain *rd); | |||
30 | * non-radar 5 GHz channels. | 30 | * non-radar 5 GHz channels. |
31 | * | 31 | * |
32 | * Drivers do not need to call this, cfg80211 will do it for after a scan | 32 | * Drivers do not need to call this, cfg80211 will do it for after a scan |
33 | * on a newly found BSS. | 33 | * on a newly found BSS. If you cannot make use of this feature you can |
34 | * set the wiphy->disable_beacon_hints to true. | ||
34 | */ | 35 | */ |
35 | int regulatory_hint_found_beacon(struct wiphy *wiphy, | 36 | int regulatory_hint_found_beacon(struct wiphy *wiphy, |
36 | struct ieee80211_channel *beacon_chan, | 37 | struct ieee80211_channel *beacon_chan, |
diff --git a/net/wireless/scan.c b/net/wireless/scan.c index e95b638b919f..7e595ce24eeb 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c | |||
@@ -35,8 +35,6 @@ void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted) | |||
35 | else | 35 | else |
36 | nl80211_send_scan_done(wiphy_to_dev(request->wiphy), dev); | 36 | nl80211_send_scan_done(wiphy_to_dev(request->wiphy), dev); |
37 | 37 | ||
38 | wiphy_to_dev(request->wiphy)->scan_req = NULL; | ||
39 | |||
40 | #ifdef CONFIG_WIRELESS_EXT | 38 | #ifdef CONFIG_WIRELESS_EXT |
41 | if (!aborted) { | 39 | if (!aborted) { |
42 | memset(&wrqu, 0, sizeof(wrqu)); | 40 | memset(&wrqu, 0, sizeof(wrqu)); |
@@ -48,6 +46,7 @@ void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted) | |||
48 | dev_put(dev); | 46 | dev_put(dev); |
49 | 47 | ||
50 | out: | 48 | out: |
49 | wiphy_to_dev(request->wiphy)->scan_req = NULL; | ||
51 | kfree(request); | 50 | kfree(request); |
52 | } | 51 | } |
53 | EXPORT_SYMBOL(cfg80211_scan_done); | 52 | EXPORT_SYMBOL(cfg80211_scan_done); |
@@ -119,7 +118,7 @@ static int cmp_ies(u8 num, u8 *ies1, size_t len1, u8 *ies2, size_t len2) | |||
119 | 118 | ||
120 | if (!ie1 && !ie2) | 119 | if (!ie1 && !ie2) |
121 | return 0; | 120 | return 0; |
122 | if (!ie1) | 121 | if (!ie1 || !ie2) |
123 | return -1; | 122 | return -1; |
124 | 123 | ||
125 | r = memcmp(ie1 + 2, ie2 + 2, min(ie1[1], ie2[1])); | 124 | r = memcmp(ie1 + 2, ie2 + 2, min(ie1[1], ie2[1])); |
@@ -172,6 +171,8 @@ static bool is_mesh(struct cfg80211_bss *a, | |||
172 | ie = find_ie(WLAN_EID_MESH_CONFIG, | 171 | ie = find_ie(WLAN_EID_MESH_CONFIG, |
173 | a->information_elements, | 172 | a->information_elements, |
174 | a->len_information_elements); | 173 | a->len_information_elements); |
174 | if (!ie) | ||
175 | return false; | ||
175 | if (ie[1] != IEEE80211_MESH_CONFIG_LEN) | 176 | if (ie[1] != IEEE80211_MESH_CONFIG_LEN) |
176 | return false; | 177 | return false; |
177 | 178 | ||
@@ -366,7 +367,6 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev, | |||
366 | found = rb_find_bss(dev, res); | 367 | found = rb_find_bss(dev, res); |
367 | 368 | ||
368 | if (found) { | 369 | if (found) { |
369 | kref_get(&found->ref); | ||
370 | found->pub.beacon_interval = res->pub.beacon_interval; | 370 | found->pub.beacon_interval = res->pub.beacon_interval; |
371 | found->pub.tsf = res->pub.tsf; | 371 | found->pub.tsf = res->pub.tsf; |
372 | found->pub.signal = res->pub.signal; | 372 | found->pub.signal = res->pub.signal; |
diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c index ed80af8ca5fb..5e6c072c64d3 100644 --- a/net/x25/af_x25.c +++ b/net/x25/af_x25.c | |||
@@ -40,6 +40,7 @@ | |||
40 | #include <linux/errno.h> | 40 | #include <linux/errno.h> |
41 | #include <linux/kernel.h> | 41 | #include <linux/kernel.h> |
42 | #include <linux/sched.h> | 42 | #include <linux/sched.h> |
43 | #include <linux/smp_lock.h> | ||
43 | #include <linux/timer.h> | 44 | #include <linux/timer.h> |
44 | #include <linux/string.h> | 45 | #include <linux/string.h> |
45 | #include <linux/net.h> | 46 | #include <linux/net.h> |
@@ -332,14 +333,14 @@ static unsigned int x25_new_lci(struct x25_neigh *nb) | |||
332 | /* | 333 | /* |
333 | * Deferred destroy. | 334 | * Deferred destroy. |
334 | */ | 335 | */ |
335 | void x25_destroy_socket(struct sock *); | 336 | static void __x25_destroy_socket(struct sock *); |
336 | 337 | ||
337 | /* | 338 | /* |
338 | * handler for deferred kills. | 339 | * handler for deferred kills. |
339 | */ | 340 | */ |
340 | static void x25_destroy_timer(unsigned long data) | 341 | static void x25_destroy_timer(unsigned long data) |
341 | { | 342 | { |
342 | x25_destroy_socket((struct sock *)data); | 343 | x25_destroy_socket_from_timer((struct sock *)data); |
343 | } | 344 | } |
344 | 345 | ||
345 | /* | 346 | /* |
@@ -349,12 +350,10 @@ static void x25_destroy_timer(unsigned long data) | |||
349 | * will touch it and we are (fairly 8-) ) safe. | 350 | * will touch it and we are (fairly 8-) ) safe. |
350 | * Not static as it's used by the timer | 351 | * Not static as it's used by the timer |
351 | */ | 352 | */ |
352 | void x25_destroy_socket(struct sock *sk) | 353 | static void __x25_destroy_socket(struct sock *sk) |
353 | { | 354 | { |
354 | struct sk_buff *skb; | 355 | struct sk_buff *skb; |
355 | 356 | ||
356 | sock_hold(sk); | ||
357 | lock_sock(sk); | ||
358 | x25_stop_heartbeat(sk); | 357 | x25_stop_heartbeat(sk); |
359 | x25_stop_timer(sk); | 358 | x25_stop_timer(sk); |
360 | 359 | ||
@@ -374,8 +373,7 @@ void x25_destroy_socket(struct sock *sk) | |||
374 | kfree_skb(skb); | 373 | kfree_skb(skb); |
375 | } | 374 | } |
376 | 375 | ||
377 | if (atomic_read(&sk->sk_wmem_alloc) || | 376 | if (sk_has_allocations(sk)) { |
378 | atomic_read(&sk->sk_rmem_alloc)) { | ||
379 | /* Defer: outstanding buffers */ | 377 | /* Defer: outstanding buffers */ |
380 | sk->sk_timer.expires = jiffies + 10 * HZ; | 378 | sk->sk_timer.expires = jiffies + 10 * HZ; |
381 | sk->sk_timer.function = x25_destroy_timer; | 379 | sk->sk_timer.function = x25_destroy_timer; |
@@ -385,7 +383,22 @@ void x25_destroy_socket(struct sock *sk) | |||
385 | /* drop last reference so sock_put will free */ | 383 | /* drop last reference so sock_put will free */ |
386 | __sock_put(sk); | 384 | __sock_put(sk); |
387 | } | 385 | } |
386 | } | ||
387 | |||
388 | void x25_destroy_socket_from_timer(struct sock *sk) | ||
389 | { | ||
390 | sock_hold(sk); | ||
391 | bh_lock_sock(sk); | ||
392 | __x25_destroy_socket(sk); | ||
393 | bh_unlock_sock(sk); | ||
394 | sock_put(sk); | ||
395 | } | ||
388 | 396 | ||
397 | static void x25_destroy_socket(struct sock *sk) | ||
398 | { | ||
399 | sock_hold(sk); | ||
400 | lock_sock(sk); | ||
401 | __x25_destroy_socket(sk); | ||
389 | release_sock(sk); | 402 | release_sock(sk); |
390 | sock_put(sk); | 403 | sock_put(sk); |
391 | } | 404 | } |
@@ -1259,8 +1272,8 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
1259 | 1272 | ||
1260 | switch (cmd) { | 1273 | switch (cmd) { |
1261 | case TIOCOUTQ: { | 1274 | case TIOCOUTQ: { |
1262 | int amount = sk->sk_sndbuf - | 1275 | int amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk); |
1263 | atomic_read(&sk->sk_wmem_alloc); | 1276 | |
1264 | if (amount < 0) | 1277 | if (amount < 0) |
1265 | amount = 0; | 1278 | amount = 0; |
1266 | rc = put_user(amount, (unsigned int __user *)argp); | 1279 | rc = put_user(amount, (unsigned int __user *)argp); |
diff --git a/net/x25/x25_proc.c b/net/x25/x25_proc.c index 1afa44d25beb..0a04e62e0e18 100644 --- a/net/x25/x25_proc.c +++ b/net/x25/x25_proc.c | |||
@@ -163,8 +163,8 @@ static int x25_seq_socket_show(struct seq_file *seq, void *v) | |||
163 | devname, x25->lci & 0x0FFF, x25->state, x25->vs, x25->vr, | 163 | devname, x25->lci & 0x0FFF, x25->state, x25->vs, x25->vr, |
164 | x25->va, x25_display_timer(s) / HZ, x25->t2 / HZ, | 164 | x25->va, x25_display_timer(s) / HZ, x25->t2 / HZ, |
165 | x25->t21 / HZ, x25->t22 / HZ, x25->t23 / HZ, | 165 | x25->t21 / HZ, x25->t22 / HZ, x25->t23 / HZ, |
166 | atomic_read(&s->sk_wmem_alloc), | 166 | sk_wmem_alloc_get(s), |
167 | atomic_read(&s->sk_rmem_alloc), | 167 | sk_rmem_alloc_get(s), |
168 | s->sk_socket ? SOCK_INODE(s->sk_socket)->i_ino : 0L); | 168 | s->sk_socket ? SOCK_INODE(s->sk_socket)->i_ino : 0L); |
169 | out: | 169 | out: |
170 | return 0; | 170 | return 0; |
diff --git a/net/x25/x25_timer.c b/net/x25/x25_timer.c index d3e3e54db936..5c5db1a36399 100644 --- a/net/x25/x25_timer.c +++ b/net/x25/x25_timer.c | |||
@@ -113,7 +113,7 @@ static void x25_heartbeat_expiry(unsigned long param) | |||
113 | (sk->sk_state == TCP_LISTEN && | 113 | (sk->sk_state == TCP_LISTEN && |
114 | sock_flag(sk, SOCK_DEAD))) { | 114 | sock_flag(sk, SOCK_DEAD))) { |
115 | bh_unlock_sock(sk); | 115 | bh_unlock_sock(sk); |
116 | x25_destroy_socket(sk); | 116 | x25_destroy_socket_from_timer(sk); |
117 | return; | 117 | return; |
118 | } | 118 | } |
119 | break; | 119 | break; |
diff --git a/net/xfrm/xfrm_algo.c b/net/xfrm/xfrm_algo.c index d31ccb487730..faf54c6bf96b 100644 --- a/net/xfrm/xfrm_algo.c +++ b/net/xfrm/xfrm_algo.c | |||
@@ -292,8 +292,8 @@ static struct xfrm_algo_desc ealg_list[] = { | |||
292 | } | 292 | } |
293 | }, | 293 | }, |
294 | { | 294 | { |
295 | .name = "cbc(cast128)", | 295 | .name = "cbc(cast5)", |
296 | .compat = "cast128", | 296 | .compat = "cast5", |
297 | 297 | ||
298 | .uinfo = { | 298 | .uinfo = { |
299 | .encr = { | 299 | .encr = { |
diff --git a/net/xfrm/xfrm_hash.h b/net/xfrm/xfrm_hash.h index d401dc8f05ed..e5195c99f71e 100644 --- a/net/xfrm/xfrm_hash.h +++ b/net/xfrm/xfrm_hash.h | |||
@@ -16,7 +16,7 @@ static inline unsigned int __xfrm6_addr_hash(xfrm_address_t *addr) | |||
16 | 16 | ||
17 | static inline unsigned int __xfrm4_daddr_saddr_hash(xfrm_address_t *daddr, xfrm_address_t *saddr) | 17 | static inline unsigned int __xfrm4_daddr_saddr_hash(xfrm_address_t *daddr, xfrm_address_t *saddr) |
18 | { | 18 | { |
19 | return ntohl(daddr->a4 ^ saddr->a4); | 19 | return ntohl(daddr->a4 + saddr->a4); |
20 | } | 20 | } |
21 | 21 | ||
22 | static inline unsigned int __xfrm6_daddr_saddr_hash(xfrm_address_t *daddr, xfrm_address_t *saddr) | 22 | static inline unsigned int __xfrm6_daddr_saddr_hash(xfrm_address_t *daddr, xfrm_address_t *saddr) |
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 5f1f86565f16..f2f7c638083e 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c | |||
@@ -668,22 +668,10 @@ static struct xfrm_state *__xfrm_state_lookup(struct net *net, xfrm_address_t *d | |||
668 | hlist_for_each_entry(x, entry, net->xfrm.state_byspi+h, byspi) { | 668 | hlist_for_each_entry(x, entry, net->xfrm.state_byspi+h, byspi) { |
669 | if (x->props.family != family || | 669 | if (x->props.family != family || |
670 | x->id.spi != spi || | 670 | x->id.spi != spi || |
671 | x->id.proto != proto) | 671 | x->id.proto != proto || |
672 | xfrm_addr_cmp(&x->id.daddr, daddr, family)) | ||
672 | continue; | 673 | continue; |
673 | 674 | ||
674 | switch (family) { | ||
675 | case AF_INET: | ||
676 | if (x->id.daddr.a4 != daddr->a4) | ||
677 | continue; | ||
678 | break; | ||
679 | case AF_INET6: | ||
680 | if (!ipv6_addr_equal((struct in6_addr *)daddr, | ||
681 | (struct in6_addr *) | ||
682 | x->id.daddr.a6)) | ||
683 | continue; | ||
684 | break; | ||
685 | } | ||
686 | |||
687 | xfrm_state_hold(x); | 675 | xfrm_state_hold(x); |
688 | return x; | 676 | return x; |
689 | } | 677 | } |
@@ -699,26 +687,11 @@ static struct xfrm_state *__xfrm_state_lookup_byaddr(struct net *net, xfrm_addre | |||
699 | 687 | ||
700 | hlist_for_each_entry(x, entry, net->xfrm.state_bysrc+h, bysrc) { | 688 | hlist_for_each_entry(x, entry, net->xfrm.state_bysrc+h, bysrc) { |
701 | if (x->props.family != family || | 689 | if (x->props.family != family || |
702 | x->id.proto != proto) | 690 | x->id.proto != proto || |
691 | xfrm_addr_cmp(&x->id.daddr, daddr, family) || | ||
692 | xfrm_addr_cmp(&x->props.saddr, saddr, family)) | ||
703 | continue; | 693 | continue; |
704 | 694 | ||
705 | switch (family) { | ||
706 | case AF_INET: | ||
707 | if (x->id.daddr.a4 != daddr->a4 || | ||
708 | x->props.saddr.a4 != saddr->a4) | ||
709 | continue; | ||
710 | break; | ||
711 | case AF_INET6: | ||
712 | if (!ipv6_addr_equal((struct in6_addr *)daddr, | ||
713 | (struct in6_addr *) | ||
714 | x->id.daddr.a6) || | ||
715 | !ipv6_addr_equal((struct in6_addr *)saddr, | ||
716 | (struct in6_addr *) | ||
717 | x->props.saddr.a6)) | ||
718 | continue; | ||
719 | break; | ||
720 | } | ||
721 | |||
722 | xfrm_state_hold(x); | 695 | xfrm_state_hold(x); |
723 | return x; | 696 | return x; |
724 | } | 697 | } |
@@ -1001,25 +974,11 @@ static struct xfrm_state *__find_acq_core(struct net *net, unsigned short family | |||
1001 | x->props.family != family || | 974 | x->props.family != family || |
1002 | x->km.state != XFRM_STATE_ACQ || | 975 | x->km.state != XFRM_STATE_ACQ || |
1003 | x->id.spi != 0 || | 976 | x->id.spi != 0 || |
1004 | x->id.proto != proto) | 977 | x->id.proto != proto || |
978 | xfrm_addr_cmp(&x->id.daddr, daddr, family) || | ||
979 | xfrm_addr_cmp(&x->props.saddr, saddr, family)) | ||
1005 | continue; | 980 | continue; |
1006 | 981 | ||
1007 | switch (family) { | ||
1008 | case AF_INET: | ||
1009 | if (x->id.daddr.a4 != daddr->a4 || | ||
1010 | x->props.saddr.a4 != saddr->a4) | ||
1011 | continue; | ||
1012 | break; | ||
1013 | case AF_INET6: | ||
1014 | if (!ipv6_addr_equal((struct in6_addr *)x->id.daddr.a6, | ||
1015 | (struct in6_addr *)daddr) || | ||
1016 | !ipv6_addr_equal((struct in6_addr *) | ||
1017 | x->props.saddr.a6, | ||
1018 | (struct in6_addr *)saddr)) | ||
1019 | continue; | ||
1020 | break; | ||
1021 | } | ||
1022 | |||
1023 | xfrm_state_hold(x); | 982 | xfrm_state_hold(x); |
1024 | return x; | 983 | return x; |
1025 | } | 984 | } |