diff options
Diffstat (limited to 'net')
166 files changed, 2229 insertions, 1427 deletions
diff --git a/net/802/fc.c b/net/802/fc.c index bd345f3d29f8..b324e31401a9 100644 --- a/net/802/fc.c +++ b/net/802/fc.c | |||
@@ -11,7 +11,6 @@ | |||
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <asm/uaccess.h> | 13 | #include <asm/uaccess.h> |
14 | #include <asm/system.h> | ||
15 | #include <linux/types.h> | 14 | #include <linux/types.h> |
16 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
17 | #include <linux/string.h> | 16 | #include <linux/string.h> |
diff --git a/net/802/fddi.c b/net/802/fddi.c index 94b3ad08f39a..5ab25cd4314b 100644 --- a/net/802/fddi.c +++ b/net/802/fddi.c | |||
@@ -27,7 +27,6 @@ | |||
27 | */ | 27 | */ |
28 | 28 | ||
29 | #include <linux/module.h> | 29 | #include <linux/module.h> |
30 | #include <asm/system.h> | ||
31 | #include <linux/types.h> | 30 | #include <linux/types.h> |
32 | #include <linux/kernel.h> | 31 | #include <linux/kernel.h> |
33 | #include <linux/string.h> | 32 | #include <linux/string.h> |
diff --git a/net/802/garp.c b/net/802/garp.c index 8e21b6db3981..a5c224830439 100644 --- a/net/802/garp.c +++ b/net/802/garp.c | |||
@@ -167,7 +167,8 @@ static struct garp_attr *garp_attr_lookup(const struct garp_applicant *app, | |||
167 | return NULL; | 167 | return NULL; |
168 | } | 168 | } |
169 | 169 | ||
170 | static void garp_attr_insert(struct garp_applicant *app, struct garp_attr *new) | 170 | static struct garp_attr *garp_attr_create(struct garp_applicant *app, |
171 | const void *data, u8 len, u8 type) | ||
171 | { | 172 | { |
172 | struct rb_node *parent = NULL, **p = &app->gid.rb_node; | 173 | struct rb_node *parent = NULL, **p = &app->gid.rb_node; |
173 | struct garp_attr *attr; | 174 | struct garp_attr *attr; |
@@ -176,21 +177,16 @@ static void garp_attr_insert(struct garp_applicant *app, struct garp_attr *new) | |||
176 | while (*p) { | 177 | while (*p) { |
177 | parent = *p; | 178 | parent = *p; |
178 | attr = rb_entry(parent, struct garp_attr, node); | 179 | attr = rb_entry(parent, struct garp_attr, node); |
179 | d = garp_attr_cmp(attr, new->data, new->dlen, new->type); | 180 | d = garp_attr_cmp(attr, data, len, type); |
180 | if (d < 0) | 181 | if (d < 0) |
181 | p = &parent->rb_left; | 182 | p = &parent->rb_left; |
182 | else if (d > 0) | 183 | else if (d > 0) |
183 | p = &parent->rb_right; | 184 | p = &parent->rb_right; |
185 | else { | ||
186 | /* The attribute already exists; re-use it. */ | ||
187 | return attr; | ||
188 | } | ||
184 | } | 189 | } |
185 | rb_link_node(&new->node, parent, p); | ||
186 | rb_insert_color(&new->node, &app->gid); | ||
187 | } | ||
188 | |||
189 | static struct garp_attr *garp_attr_create(struct garp_applicant *app, | ||
190 | const void *data, u8 len, u8 type) | ||
191 | { | ||
192 | struct garp_attr *attr; | ||
193 | |||
194 | attr = kmalloc(sizeof(*attr) + len, GFP_ATOMIC); | 190 | attr = kmalloc(sizeof(*attr) + len, GFP_ATOMIC); |
195 | if (!attr) | 191 | if (!attr) |
196 | return attr; | 192 | return attr; |
@@ -198,7 +194,9 @@ static struct garp_attr *garp_attr_create(struct garp_applicant *app, | |||
198 | attr->type = type; | 194 | attr->type = type; |
199 | attr->dlen = len; | 195 | attr->dlen = len; |
200 | memcpy(attr->data, data, len); | 196 | memcpy(attr->data, data, len); |
201 | garp_attr_insert(app, attr); | 197 | |
198 | rb_link_node(&attr->node, parent, p); | ||
199 | rb_insert_color(&attr->node, &app->gid); | ||
202 | return attr; | 200 | return attr; |
203 | } | 201 | } |
204 | 202 | ||
diff --git a/net/802/hippi.c b/net/802/hippi.c index 91aca8780fd0..056794e66375 100644 --- a/net/802/hippi.c +++ b/net/802/hippi.c | |||
@@ -35,7 +35,6 @@ | |||
35 | #include <net/arp.h> | 35 | #include <net/arp.h> |
36 | #include <net/sock.h> | 36 | #include <net/sock.h> |
37 | #include <asm/uaccess.h> | 37 | #include <asm/uaccess.h> |
38 | #include <asm/system.h> | ||
39 | 38 | ||
40 | /* | 39 | /* |
41 | * Create the HIPPI MAC header for an arbitrary protocol layer | 40 | * Create the HIPPI MAC header for an arbitrary protocol layer |
diff --git a/net/802/tr.c b/net/802/tr.c index 5e20cf8a074b..b9a3a145e348 100644 --- a/net/802/tr.c +++ b/net/802/tr.c | |||
@@ -16,7 +16,6 @@ | |||
16 | */ | 16 | */ |
17 | 17 | ||
18 | #include <asm/uaccess.h> | 18 | #include <asm/uaccess.h> |
19 | #include <asm/system.h> | ||
20 | #include <linux/module.h> | 19 | #include <linux/module.h> |
21 | #include <linux/types.h> | 20 | #include <linux/types.h> |
22 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
diff --git a/net/9p/client.c b/net/9p/client.c index 776618cd2be5..b23a17c431c8 100644 --- a/net/9p/client.c +++ b/net/9p/client.c | |||
@@ -740,10 +740,18 @@ p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...) | |||
740 | c->status = Disconnected; | 740 | c->status = Disconnected; |
741 | goto reterr; | 741 | goto reterr; |
742 | } | 742 | } |
743 | again: | ||
743 | /* Wait for the response */ | 744 | /* Wait for the response */ |
744 | err = wait_event_interruptible(*req->wq, | 745 | err = wait_event_interruptible(*req->wq, |
745 | req->status >= REQ_STATUS_RCVD); | 746 | req->status >= REQ_STATUS_RCVD); |
746 | 747 | ||
748 | if ((err == -ERESTARTSYS) && (c->status == Connected) | ||
749 | && (type == P9_TFLUSH)) { | ||
750 | sigpending = 1; | ||
751 | clear_thread_flag(TIF_SIGPENDING); | ||
752 | goto again; | ||
753 | } | ||
754 | |||
747 | if (req->status == REQ_STATUS_ERROR) { | 755 | if (req->status == REQ_STATUS_ERROR) { |
748 | p9_debug(P9_DEBUG_ERROR, "req_status error %d\n", req->t_err); | 756 | p9_debug(P9_DEBUG_ERROR, "req_status error %d\n", req->t_err); |
749 | err = req->t_err; | 757 | err = req->t_err; |
@@ -1420,6 +1428,7 @@ int p9_client_clunk(struct p9_fid *fid) | |||
1420 | int err; | 1428 | int err; |
1421 | struct p9_client *clnt; | 1429 | struct p9_client *clnt; |
1422 | struct p9_req_t *req; | 1430 | struct p9_req_t *req; |
1431 | int retries = 0; | ||
1423 | 1432 | ||
1424 | if (!fid) { | 1433 | if (!fid) { |
1425 | pr_warn("%s (%d): Trying to clunk with NULL fid\n", | 1434 | pr_warn("%s (%d): Trying to clunk with NULL fid\n", |
@@ -1428,7 +1437,9 @@ int p9_client_clunk(struct p9_fid *fid) | |||
1428 | return 0; | 1437 | return 0; |
1429 | } | 1438 | } |
1430 | 1439 | ||
1431 | p9_debug(P9_DEBUG_9P, ">>> TCLUNK fid %d\n", fid->fid); | 1440 | again: |
1441 | p9_debug(P9_DEBUG_9P, ">>> TCLUNK fid %d (try %d)\n", fid->fid, | ||
1442 | retries); | ||
1432 | err = 0; | 1443 | err = 0; |
1433 | clnt = fid->clnt; | 1444 | clnt = fid->clnt; |
1434 | 1445 | ||
@@ -1444,8 +1455,14 @@ int p9_client_clunk(struct p9_fid *fid) | |||
1444 | error: | 1455 | error: |
1445 | /* | 1456 | /* |
1446 | * Fid is not valid even after a failed clunk | 1457 | * Fid is not valid even after a failed clunk |
1458 | * If interrupted, retry once then give up and | ||
1459 | * leak fid until umount. | ||
1447 | */ | 1460 | */ |
1448 | p9_fid_destroy(fid); | 1461 | if (err == -ERESTARTSYS) { |
1462 | if (retries++ == 0) | ||
1463 | goto again; | ||
1464 | } else | ||
1465 | p9_fid_destroy(fid); | ||
1449 | return err; | 1466 | return err; |
1450 | } | 1467 | } |
1451 | EXPORT_SYMBOL(p9_client_clunk); | 1468 | EXPORT_SYMBOL(p9_client_clunk); |
@@ -1470,7 +1487,10 @@ int p9_client_remove(struct p9_fid *fid) | |||
1470 | 1487 | ||
1471 | p9_free_req(clnt, req); | 1488 | p9_free_req(clnt, req); |
1472 | error: | 1489 | error: |
1473 | p9_fid_destroy(fid); | 1490 | if (err == -ERESTARTSYS) |
1491 | p9_client_clunk(fid); | ||
1492 | else | ||
1493 | p9_fid_destroy(fid); | ||
1474 | return err; | 1494 | return err; |
1475 | } | 1495 | } |
1476 | EXPORT_SYMBOL(p9_client_remove); | 1496 | EXPORT_SYMBOL(p9_client_remove); |
diff --git a/net/atm/clip.c b/net/atm/clip.c index 5de42ea309bc..8ae3a7879335 100644 --- a/net/atm/clip.c +++ b/net/atm/clip.c | |||
@@ -37,7 +37,6 @@ | |||
37 | #include <linux/param.h> /* for HZ */ | 37 | #include <linux/param.h> /* for HZ */ |
38 | #include <linux/uaccess.h> | 38 | #include <linux/uaccess.h> |
39 | #include <asm/byteorder.h> /* for htons etc. */ | 39 | #include <asm/byteorder.h> /* for htons etc. */ |
40 | #include <asm/system.h> /* save/restore_flags */ | ||
41 | #include <linux/atomic.h> | 40 | #include <linux/atomic.h> |
42 | 41 | ||
43 | #include "common.h" | 42 | #include "common.h" |
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c index 3cd0a0dc91cb..0906c194a413 100644 --- a/net/ax25/af_ax25.c +++ b/net/ax25/af_ax25.c | |||
@@ -33,7 +33,6 @@ | |||
33 | #include <linux/skbuff.h> | 33 | #include <linux/skbuff.h> |
34 | #include <net/sock.h> | 34 | #include <net/sock.h> |
35 | #include <asm/uaccess.h> | 35 | #include <asm/uaccess.h> |
36 | #include <asm/system.h> | ||
37 | #include <linux/fcntl.h> | 36 | #include <linux/fcntl.h> |
38 | #include <linux/termios.h> /* For TIOCINQ/OUTQ */ | 37 | #include <linux/termios.h> /* For TIOCINQ/OUTQ */ |
39 | #include <linux/mm.h> | 38 | #include <linux/mm.h> |
diff --git a/net/ax25/ax25_addr.c b/net/ax25/ax25_addr.c index 7e7964dd987b..9162409559cf 100644 --- a/net/ax25/ax25_addr.c +++ b/net/ax25/ax25_addr.c | |||
@@ -22,7 +22,6 @@ | |||
22 | #include <linux/skbuff.h> | 22 | #include <linux/skbuff.h> |
23 | #include <net/sock.h> | 23 | #include <net/sock.h> |
24 | #include <asm/uaccess.h> | 24 | #include <asm/uaccess.h> |
25 | #include <asm/system.h> | ||
26 | #include <linux/fcntl.h> | 25 | #include <linux/fcntl.h> |
27 | #include <linux/mm.h> | 26 | #include <linux/mm.h> |
28 | #include <linux/interrupt.h> | 27 | #include <linux/interrupt.h> |
diff --git a/net/ax25/ax25_dev.c b/net/ax25/ax25_dev.c index c1cb982f6e86..d0de30e89591 100644 --- a/net/ax25/ax25_dev.c +++ b/net/ax25/ax25_dev.c | |||
@@ -24,7 +24,6 @@ | |||
24 | #include <linux/skbuff.h> | 24 | #include <linux/skbuff.h> |
25 | #include <net/sock.h> | 25 | #include <net/sock.h> |
26 | #include <asm/uaccess.h> | 26 | #include <asm/uaccess.h> |
27 | #include <asm/system.h> | ||
28 | #include <linux/fcntl.h> | 27 | #include <linux/fcntl.h> |
29 | #include <linux/mm.h> | 28 | #include <linux/mm.h> |
30 | #include <linux/interrupt.h> | 29 | #include <linux/interrupt.h> |
diff --git a/net/ax25/ax25_ds_in.c b/net/ax25/ax25_ds_in.c index 8273b1200eee..9bd31e88aeca 100644 --- a/net/ax25/ax25_ds_in.c +++ b/net/ax25/ax25_ds_in.c | |||
@@ -23,7 +23,6 @@ | |||
23 | #include <net/sock.h> | 23 | #include <net/sock.h> |
24 | #include <net/tcp_states.h> | 24 | #include <net/tcp_states.h> |
25 | #include <asm/uaccess.h> | 25 | #include <asm/uaccess.h> |
26 | #include <asm/system.h> | ||
27 | #include <linux/fcntl.h> | 26 | #include <linux/fcntl.h> |
28 | #include <linux/mm.h> | 27 | #include <linux/mm.h> |
29 | #include <linux/interrupt.h> | 28 | #include <linux/interrupt.h> |
diff --git a/net/ax25/ax25_ds_subr.c b/net/ax25/ax25_ds_subr.c index 85816e612dc0..5ea7fd3e2af9 100644 --- a/net/ax25/ax25_ds_subr.c +++ b/net/ax25/ax25_ds_subr.c | |||
@@ -24,7 +24,6 @@ | |||
24 | #include <linux/skbuff.h> | 24 | #include <linux/skbuff.h> |
25 | #include <net/sock.h> | 25 | #include <net/sock.h> |
26 | #include <asm/uaccess.h> | 26 | #include <asm/uaccess.h> |
27 | #include <asm/system.h> | ||
28 | #include <linux/fcntl.h> | 27 | #include <linux/fcntl.h> |
29 | #include <linux/mm.h> | 28 | #include <linux/mm.h> |
30 | #include <linux/interrupt.h> | 29 | #include <linux/interrupt.h> |
diff --git a/net/ax25/ax25_ds_timer.c b/net/ax25/ax25_ds_timer.c index c7d81436213d..993c439b4f71 100644 --- a/net/ax25/ax25_ds_timer.c +++ b/net/ax25/ax25_ds_timer.c | |||
@@ -25,7 +25,6 @@ | |||
25 | #include <linux/skbuff.h> | 25 | #include <linux/skbuff.h> |
26 | #include <net/sock.h> | 26 | #include <net/sock.h> |
27 | #include <asm/uaccess.h> | 27 | #include <asm/uaccess.h> |
28 | #include <asm/system.h> | ||
29 | #include <linux/fcntl.h> | 28 | #include <linux/fcntl.h> |
30 | #include <linux/mm.h> | 29 | #include <linux/mm.h> |
31 | #include <linux/interrupt.h> | 30 | #include <linux/interrupt.h> |
diff --git a/net/ax25/ax25_iface.c b/net/ax25/ax25_iface.c index 60b545e2822a..7d5f24b82cc8 100644 --- a/net/ax25/ax25_iface.c +++ b/net/ax25/ax25_iface.c | |||
@@ -24,7 +24,6 @@ | |||
24 | #include <linux/skbuff.h> | 24 | #include <linux/skbuff.h> |
25 | #include <net/sock.h> | 25 | #include <net/sock.h> |
26 | #include <asm/uaccess.h> | 26 | #include <asm/uaccess.h> |
27 | #include <asm/system.h> | ||
28 | #include <linux/fcntl.h> | 27 | #include <linux/fcntl.h> |
29 | #include <linux/mm.h> | 28 | #include <linux/mm.h> |
30 | #include <linux/interrupt.h> | 29 | #include <linux/interrupt.h> |
diff --git a/net/ax25/ax25_in.c b/net/ax25/ax25_in.c index 9bb776541203..96f4cab3a2f9 100644 --- a/net/ax25/ax25_in.c +++ b/net/ax25/ax25_in.c | |||
@@ -27,7 +27,6 @@ | |||
27 | #include <net/sock.h> | 27 | #include <net/sock.h> |
28 | #include <net/tcp_states.h> | 28 | #include <net/tcp_states.h> |
29 | #include <asm/uaccess.h> | 29 | #include <asm/uaccess.h> |
30 | #include <asm/system.h> | ||
31 | #include <linux/fcntl.h> | 30 | #include <linux/fcntl.h> |
32 | #include <linux/mm.h> | 31 | #include <linux/mm.h> |
33 | #include <linux/interrupt.h> | 32 | #include <linux/interrupt.h> |
diff --git a/net/ax25/ax25_ip.c b/net/ax25/ax25_ip.c index cf0c47a26530..846ae4e2b115 100644 --- a/net/ax25/ax25_ip.c +++ b/net/ax25/ax25_ip.c | |||
@@ -24,7 +24,6 @@ | |||
24 | #include <linux/skbuff.h> | 24 | #include <linux/skbuff.h> |
25 | #include <net/sock.h> | 25 | #include <net/sock.h> |
26 | #include <asm/uaccess.h> | 26 | #include <asm/uaccess.h> |
27 | #include <asm/system.h> | ||
28 | #include <linux/fcntl.h> | 27 | #include <linux/fcntl.h> |
29 | #include <linux/termios.h> /* For TIOCINQ/OUTQ */ | 28 | #include <linux/termios.h> /* For TIOCINQ/OUTQ */ |
30 | #include <linux/mm.h> | 29 | #include <linux/mm.h> |
diff --git a/net/ax25/ax25_out.c b/net/ax25/ax25_out.c index 37507d806f65..be8a25e0db65 100644 --- a/net/ax25/ax25_out.c +++ b/net/ax25/ax25_out.c | |||
@@ -27,7 +27,6 @@ | |||
27 | #include <linux/netfilter.h> | 27 | #include <linux/netfilter.h> |
28 | #include <net/sock.h> | 28 | #include <net/sock.h> |
29 | #include <asm/uaccess.h> | 29 | #include <asm/uaccess.h> |
30 | #include <asm/system.h> | ||
31 | #include <linux/fcntl.h> | 30 | #include <linux/fcntl.h> |
32 | #include <linux/mm.h> | 31 | #include <linux/mm.h> |
33 | #include <linux/interrupt.h> | 32 | #include <linux/interrupt.h> |
diff --git a/net/ax25/ax25_route.c b/net/ax25/ax25_route.c index 87fddab22e0f..a65588040b9e 100644 --- a/net/ax25/ax25_route.c +++ b/net/ax25/ax25_route.c | |||
@@ -32,7 +32,6 @@ | |||
32 | #include <linux/spinlock.h> | 32 | #include <linux/spinlock.h> |
33 | #include <net/sock.h> | 33 | #include <net/sock.h> |
34 | #include <asm/uaccess.h> | 34 | #include <asm/uaccess.h> |
35 | #include <asm/system.h> | ||
36 | #include <linux/fcntl.h> | 35 | #include <linux/fcntl.h> |
37 | #include <linux/mm.h> | 36 | #include <linux/mm.h> |
38 | #include <linux/interrupt.h> | 37 | #include <linux/interrupt.h> |
diff --git a/net/ax25/ax25_std_in.c b/net/ax25/ax25_std_in.c index a8eef88d8652..3fbf8f7b2cf4 100644 --- a/net/ax25/ax25_std_in.c +++ b/net/ax25/ax25_std_in.c | |||
@@ -30,7 +30,6 @@ | |||
30 | #include <net/sock.h> | 30 | #include <net/sock.h> |
31 | #include <net/tcp_states.h> | 31 | #include <net/tcp_states.h> |
32 | #include <asm/uaccess.h> | 32 | #include <asm/uaccess.h> |
33 | #include <asm/system.h> | ||
34 | #include <linux/fcntl.h> | 33 | #include <linux/fcntl.h> |
35 | #include <linux/mm.h> | 34 | #include <linux/mm.h> |
36 | #include <linux/interrupt.h> | 35 | #include <linux/interrupt.h> |
diff --git a/net/ax25/ax25_std_subr.c b/net/ax25/ax25_std_subr.c index 277f81bb979a..8b66a41e538f 100644 --- a/net/ax25/ax25_std_subr.c +++ b/net/ax25/ax25_std_subr.c | |||
@@ -21,7 +21,6 @@ | |||
21 | #include <linux/skbuff.h> | 21 | #include <linux/skbuff.h> |
22 | #include <net/sock.h> | 22 | #include <net/sock.h> |
23 | #include <asm/uaccess.h> | 23 | #include <asm/uaccess.h> |
24 | #include <asm/system.h> | ||
25 | #include <linux/fcntl.h> | 24 | #include <linux/fcntl.h> |
26 | #include <linux/mm.h> | 25 | #include <linux/mm.h> |
27 | #include <linux/interrupt.h> | 26 | #include <linux/interrupt.h> |
diff --git a/net/ax25/ax25_std_timer.c b/net/ax25/ax25_std_timer.c index 96e4b9273250..004467c9e6e1 100644 --- a/net/ax25/ax25_std_timer.c +++ b/net/ax25/ax25_std_timer.c | |||
@@ -25,7 +25,6 @@ | |||
25 | #include <net/sock.h> | 25 | #include <net/sock.h> |
26 | #include <net/tcp_states.h> | 26 | #include <net/tcp_states.h> |
27 | #include <asm/uaccess.h> | 27 | #include <asm/uaccess.h> |
28 | #include <asm/system.h> | ||
29 | #include <linux/fcntl.h> | 28 | #include <linux/fcntl.h> |
30 | #include <linux/mm.h> | 29 | #include <linux/mm.h> |
31 | #include <linux/interrupt.h> | 30 | #include <linux/interrupt.h> |
diff --git a/net/ax25/ax25_subr.c b/net/ax25/ax25_subr.c index c6715ee4ab8f..1997538a5d23 100644 --- a/net/ax25/ax25_subr.c +++ b/net/ax25/ax25_subr.c | |||
@@ -26,7 +26,6 @@ | |||
26 | #include <net/sock.h> | 26 | #include <net/sock.h> |
27 | #include <net/tcp_states.h> | 27 | #include <net/tcp_states.h> |
28 | #include <asm/uaccess.h> | 28 | #include <asm/uaccess.h> |
29 | #include <asm/system.h> | ||
30 | #include <linux/fcntl.h> | 29 | #include <linux/fcntl.h> |
31 | #include <linux/mm.h> | 30 | #include <linux/mm.h> |
32 | #include <linux/interrupt.h> | 31 | #include <linux/interrupt.h> |
diff --git a/net/ax25/ax25_timer.c b/net/ax25/ax25_timer.c index db29ea71e80a..c3cffa79bafb 100644 --- a/net/ax25/ax25_timer.c +++ b/net/ax25/ax25_timer.c | |||
@@ -29,7 +29,6 @@ | |||
29 | #include <linux/skbuff.h> | 29 | #include <linux/skbuff.h> |
30 | #include <net/sock.h> | 30 | #include <net/sock.h> |
31 | #include <asm/uaccess.h> | 31 | #include <asm/uaccess.h> |
32 | #include <asm/system.h> | ||
33 | #include <linux/fcntl.h> | 32 | #include <linux/fcntl.h> |
34 | #include <linux/mm.h> | 33 | #include <linux/mm.h> |
35 | #include <linux/interrupt.h> | 34 | #include <linux/interrupt.h> |
diff --git a/net/ax25/ax25_uid.c b/net/ax25/ax25_uid.c index 4c83137b5954..e3c579ba6325 100644 --- a/net/ax25/ax25_uid.c +++ b/net/ax25/ax25_uid.c | |||
@@ -26,7 +26,6 @@ | |||
26 | #include <linux/skbuff.h> | 26 | #include <linux/skbuff.h> |
27 | #include <net/sock.h> | 27 | #include <net/sock.h> |
28 | #include <asm/uaccess.h> | 28 | #include <asm/uaccess.h> |
29 | #include <asm/system.h> | ||
30 | #include <linux/fcntl.h> | 29 | #include <linux/fcntl.h> |
31 | #include <linux/mm.h> | 30 | #include <linux/mm.h> |
32 | #include <linux/interrupt.h> | 31 | #include <linux/interrupt.h> |
diff --git a/net/bluetooth/bnep/sock.c b/net/bluetooth/bnep/sock.c index 9f9c8dcd8af0..180bfc45810d 100644 --- a/net/bluetooth/bnep/sock.c +++ b/net/bluetooth/bnep/sock.c | |||
@@ -42,7 +42,6 @@ | |||
42 | #include <linux/uaccess.h> | 42 | #include <linux/uaccess.h> |
43 | #include <net/sock.h> | 43 | #include <net/sock.h> |
44 | 44 | ||
45 | #include <asm/system.h> | ||
46 | 45 | ||
47 | #include "bnep.h" | 46 | #include "bnep.h" |
48 | 47 | ||
diff --git a/net/bluetooth/cmtp/sock.c b/net/bluetooth/cmtp/sock.c index 1230faaac29b..311668d14571 100644 --- a/net/bluetooth/cmtp/sock.c +++ b/net/bluetooth/cmtp/sock.c | |||
@@ -39,7 +39,6 @@ | |||
39 | 39 | ||
40 | #include <linux/isdn/capilli.h> | 40 | #include <linux/isdn/capilli.h> |
41 | 41 | ||
42 | #include <asm/system.h> | ||
43 | 42 | ||
44 | #include "cmtp.h" | 43 | #include "cmtp.h" |
45 | 44 | ||
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 947172bf1621..5238b6b3ea6a 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c | |||
@@ -37,7 +37,6 @@ | |||
37 | #include <linux/interrupt.h> | 37 | #include <linux/interrupt.h> |
38 | #include <net/sock.h> | 38 | #include <net/sock.h> |
39 | 39 | ||
40 | #include <asm/system.h> | ||
41 | #include <linux/uaccess.h> | 40 | #include <linux/uaccess.h> |
42 | #include <asm/unaligned.h> | 41 | #include <asm/unaligned.h> |
43 | 42 | ||
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index a7607e4be347..edfd61addcec 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
@@ -45,7 +45,6 @@ | |||
45 | #include <linux/crypto.h> | 45 | #include <linux/crypto.h> |
46 | #include <net/sock.h> | 46 | #include <net/sock.h> |
47 | 47 | ||
48 | #include <asm/system.h> | ||
49 | #include <linux/uaccess.h> | 48 | #include <linux/uaccess.h> |
50 | #include <asm/unaligned.h> | 49 | #include <asm/unaligned.h> |
51 | 50 | ||
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 7f87a70b8618..6c065254afc0 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c | |||
@@ -37,7 +37,6 @@ | |||
37 | #include <linux/interrupt.h> | 37 | #include <linux/interrupt.h> |
38 | #include <net/sock.h> | 38 | #include <net/sock.h> |
39 | 39 | ||
40 | #include <asm/system.h> | ||
41 | #include <linux/uaccess.h> | 40 | #include <linux/uaccess.h> |
42 | #include <asm/unaligned.h> | 41 | #include <asm/unaligned.h> |
43 | 42 | ||
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index 63afd234283e..5914623f426a 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c | |||
@@ -42,7 +42,6 @@ | |||
42 | #include <linux/ioctl.h> | 42 | #include <linux/ioctl.h> |
43 | #include <net/sock.h> | 43 | #include <net/sock.h> |
44 | 44 | ||
45 | #include <asm/system.h> | ||
46 | #include <linux/uaccess.h> | 45 | #include <linux/uaccess.h> |
47 | #include <asm/unaligned.h> | 46 | #include <asm/unaligned.h> |
48 | 47 | ||
@@ -734,7 +733,8 @@ static inline void hci_sock_cmsg(struct sock *sk, struct msghdr *msg, struct sk_ | |||
734 | data = &tv; | 733 | data = &tv; |
735 | len = sizeof(tv); | 734 | len = sizeof(tv); |
736 | #ifdef CONFIG_COMPAT | 735 | #ifdef CONFIG_COMPAT |
737 | if (msg->msg_flags & MSG_CMSG_COMPAT) { | 736 | if (!COMPAT_USE_64BIT_TIME && |
737 | (msg->msg_flags & MSG_CMSG_COMPAT)) { | ||
738 | ctv.tv_sec = tv.tv_sec; | 738 | ctv.tv_sec = tv.tv_sec; |
739 | ctv.tv_usec = tv.tv_usec; | 739 | ctv.tv_usec = tv.tv_usec; |
740 | data = &ctv; | 740 | data = &ctv; |
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 38d934a1124a..94552b33d528 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c | |||
@@ -49,7 +49,6 @@ | |||
49 | #include <linux/crc16.h> | 49 | #include <linux/crc16.h> |
50 | #include <net/sock.h> | 50 | #include <net/sock.h> |
51 | 51 | ||
52 | #include <asm/system.h> | ||
53 | #include <asm/unaligned.h> | 52 | #include <asm/unaligned.h> |
54 | 53 | ||
55 | #include <net/bluetooth/bluetooth.h> | 54 | #include <net/bluetooth/bluetooth.h> |
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index 22169c3f1482..a55a43e9f70e 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c | |||
@@ -45,7 +45,6 @@ | |||
45 | #include <linux/security.h> | 45 | #include <linux/security.h> |
46 | #include <net/sock.h> | 46 | #include <net/sock.h> |
47 | 47 | ||
48 | #include <asm/system.h> | ||
49 | #include <linux/uaccess.h> | 48 | #include <linux/uaccess.h> |
50 | 49 | ||
51 | #include <net/bluetooth/bluetooth.h> | 50 | #include <net/bluetooth/bluetooth.h> |
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index 8bf26d1bc5c1..f6ab12907963 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c | |||
@@ -44,7 +44,6 @@ | |||
44 | #include <linux/security.h> | 44 | #include <linux/security.h> |
45 | #include <net/sock.h> | 45 | #include <net/sock.h> |
46 | 46 | ||
47 | #include <asm/system.h> | ||
48 | #include <linux/uaccess.h> | 47 | #include <linux/uaccess.h> |
49 | 48 | ||
50 | #include <net/bluetooth/bluetooth.h> | 49 | #include <net/bluetooth/bluetooth.h> |
diff --git a/net/ceph/ceph_common.c b/net/ceph/ceph_common.c index 761ad9d6cc3b..cc913193d992 100644 --- a/net/ceph/ceph_common.c +++ b/net/ceph/ceph_common.c | |||
@@ -201,7 +201,9 @@ enum { | |||
201 | Opt_ip, | 201 | Opt_ip, |
202 | Opt_last_string, | 202 | Opt_last_string, |
203 | /* string args above */ | 203 | /* string args above */ |
204 | Opt_share, | ||
204 | Opt_noshare, | 205 | Opt_noshare, |
206 | Opt_crc, | ||
205 | Opt_nocrc, | 207 | Opt_nocrc, |
206 | }; | 208 | }; |
207 | 209 | ||
@@ -217,7 +219,9 @@ static match_table_t opt_tokens = { | |||
217 | {Opt_key, "key=%s"}, | 219 | {Opt_key, "key=%s"}, |
218 | {Opt_ip, "ip=%s"}, | 220 | {Opt_ip, "ip=%s"}, |
219 | /* string args above */ | 221 | /* string args above */ |
222 | {Opt_share, "share"}, | ||
220 | {Opt_noshare, "noshare"}, | 223 | {Opt_noshare, "noshare"}, |
224 | {Opt_crc, "crc"}, | ||
221 | {Opt_nocrc, "nocrc"}, | 225 | {Opt_nocrc, "nocrc"}, |
222 | {-1, NULL} | 226 | {-1, NULL} |
223 | }; | 227 | }; |
@@ -277,10 +281,11 @@ out: | |||
277 | return err; | 281 | return err; |
278 | } | 282 | } |
279 | 283 | ||
280 | int ceph_parse_options(struct ceph_options **popt, char *options, | 284 | struct ceph_options * |
281 | const char *dev_name, const char *dev_name_end, | 285 | ceph_parse_options(char *options, const char *dev_name, |
282 | int (*parse_extra_token)(char *c, void *private), | 286 | const char *dev_name_end, |
283 | void *private) | 287 | int (*parse_extra_token)(char *c, void *private), |
288 | void *private) | ||
284 | { | 289 | { |
285 | struct ceph_options *opt; | 290 | struct ceph_options *opt; |
286 | const char *c; | 291 | const char *c; |
@@ -289,7 +294,7 @@ int ceph_parse_options(struct ceph_options **popt, char *options, | |||
289 | 294 | ||
290 | opt = kzalloc(sizeof(*opt), GFP_KERNEL); | 295 | opt = kzalloc(sizeof(*opt), GFP_KERNEL); |
291 | if (!opt) | 296 | if (!opt) |
292 | return err; | 297 | return ERR_PTR(-ENOMEM); |
293 | opt->mon_addr = kcalloc(CEPH_MAX_MON, sizeof(*opt->mon_addr), | 298 | opt->mon_addr = kcalloc(CEPH_MAX_MON, sizeof(*opt->mon_addr), |
294 | GFP_KERNEL); | 299 | GFP_KERNEL); |
295 | if (!opt->mon_addr) | 300 | if (!opt->mon_addr) |
@@ -398,10 +403,16 @@ int ceph_parse_options(struct ceph_options **popt, char *options, | |||
398 | opt->mount_timeout = intval; | 403 | opt->mount_timeout = intval; |
399 | break; | 404 | break; |
400 | 405 | ||
406 | case Opt_share: | ||
407 | opt->flags &= ~CEPH_OPT_NOSHARE; | ||
408 | break; | ||
401 | case Opt_noshare: | 409 | case Opt_noshare: |
402 | opt->flags |= CEPH_OPT_NOSHARE; | 410 | opt->flags |= CEPH_OPT_NOSHARE; |
403 | break; | 411 | break; |
404 | 412 | ||
413 | case Opt_crc: | ||
414 | opt->flags &= ~CEPH_OPT_NOCRC; | ||
415 | break; | ||
405 | case Opt_nocrc: | 416 | case Opt_nocrc: |
406 | opt->flags |= CEPH_OPT_NOCRC; | 417 | opt->flags |= CEPH_OPT_NOCRC; |
407 | break; | 418 | break; |
@@ -412,12 +423,11 @@ int ceph_parse_options(struct ceph_options **popt, char *options, | |||
412 | } | 423 | } |
413 | 424 | ||
414 | /* success */ | 425 | /* success */ |
415 | *popt = opt; | 426 | return opt; |
416 | return 0; | ||
417 | 427 | ||
418 | out: | 428 | out: |
419 | ceph_destroy_options(opt); | 429 | ceph_destroy_options(opt); |
420 | return err; | 430 | return ERR_PTR(err); |
421 | } | 431 | } |
422 | EXPORT_SYMBOL(ceph_parse_options); | 432 | EXPORT_SYMBOL(ceph_parse_options); |
423 | 433 | ||
diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index ad5b70801f37..f0993af2ae4d 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c | |||
@@ -38,48 +38,54 @@ static char tag_keepalive = CEPH_MSGR_TAG_KEEPALIVE; | |||
38 | static struct lock_class_key socket_class; | 38 | static struct lock_class_key socket_class; |
39 | #endif | 39 | #endif |
40 | 40 | ||
41 | /* | ||
42 | * When skipping (ignoring) a block of input we read it into a "skip | ||
43 | * buffer," which is this many bytes in size. | ||
44 | */ | ||
45 | #define SKIP_BUF_SIZE 1024 | ||
41 | 46 | ||
42 | static void queue_con(struct ceph_connection *con); | 47 | static void queue_con(struct ceph_connection *con); |
43 | static void con_work(struct work_struct *); | 48 | static void con_work(struct work_struct *); |
44 | static void ceph_fault(struct ceph_connection *con); | 49 | static void ceph_fault(struct ceph_connection *con); |
45 | 50 | ||
46 | /* | 51 | /* |
47 | * nicely render a sockaddr as a string. | 52 | * Nicely render a sockaddr as a string. An array of formatted |
53 | * strings is used, to approximate reentrancy. | ||
48 | */ | 54 | */ |
49 | #define MAX_ADDR_STR 20 | 55 | #define ADDR_STR_COUNT_LOG 5 /* log2(# address strings in array) */ |
50 | #define MAX_ADDR_STR_LEN 60 | 56 | #define ADDR_STR_COUNT (1 << ADDR_STR_COUNT_LOG) |
51 | static char addr_str[MAX_ADDR_STR][MAX_ADDR_STR_LEN]; | 57 | #define ADDR_STR_COUNT_MASK (ADDR_STR_COUNT - 1) |
52 | static DEFINE_SPINLOCK(addr_str_lock); | 58 | #define MAX_ADDR_STR_LEN 64 /* 54 is enough */ |
53 | static int last_addr_str; | 59 | |
60 | static char addr_str[ADDR_STR_COUNT][MAX_ADDR_STR_LEN]; | ||
61 | static atomic_t addr_str_seq = ATOMIC_INIT(0); | ||
62 | |||
63 | static struct page *zero_page; /* used in certain error cases */ | ||
54 | 64 | ||
55 | const char *ceph_pr_addr(const struct sockaddr_storage *ss) | 65 | const char *ceph_pr_addr(const struct sockaddr_storage *ss) |
56 | { | 66 | { |
57 | int i; | 67 | int i; |
58 | char *s; | 68 | char *s; |
59 | struct sockaddr_in *in4 = (void *)ss; | 69 | struct sockaddr_in *in4 = (struct sockaddr_in *) ss; |
60 | struct sockaddr_in6 *in6 = (void *)ss; | 70 | struct sockaddr_in6 *in6 = (struct sockaddr_in6 *) ss; |
61 | 71 | ||
62 | spin_lock(&addr_str_lock); | 72 | i = atomic_inc_return(&addr_str_seq) & ADDR_STR_COUNT_MASK; |
63 | i = last_addr_str++; | ||
64 | if (last_addr_str == MAX_ADDR_STR) | ||
65 | last_addr_str = 0; | ||
66 | spin_unlock(&addr_str_lock); | ||
67 | s = addr_str[i]; | 73 | s = addr_str[i]; |
68 | 74 | ||
69 | switch (ss->ss_family) { | 75 | switch (ss->ss_family) { |
70 | case AF_INET: | 76 | case AF_INET: |
71 | snprintf(s, MAX_ADDR_STR_LEN, "%pI4:%u", &in4->sin_addr, | 77 | snprintf(s, MAX_ADDR_STR_LEN, "%pI4:%hu", &in4->sin_addr, |
72 | (unsigned int)ntohs(in4->sin_port)); | 78 | ntohs(in4->sin_port)); |
73 | break; | 79 | break; |
74 | 80 | ||
75 | case AF_INET6: | 81 | case AF_INET6: |
76 | snprintf(s, MAX_ADDR_STR_LEN, "[%pI6c]:%u", &in6->sin6_addr, | 82 | snprintf(s, MAX_ADDR_STR_LEN, "[%pI6c]:%hu", &in6->sin6_addr, |
77 | (unsigned int)ntohs(in6->sin6_port)); | 83 | ntohs(in6->sin6_port)); |
78 | break; | 84 | break; |
79 | 85 | ||
80 | default: | 86 | default: |
81 | snprintf(s, MAX_ADDR_STR_LEN, "(unknown sockaddr family %d)", | 87 | snprintf(s, MAX_ADDR_STR_LEN, "(unknown sockaddr family %hu)", |
82 | (int)ss->ss_family); | 88 | ss->ss_family); |
83 | } | 89 | } |
84 | 90 | ||
85 | return s; | 91 | return s; |
@@ -95,22 +101,43 @@ static void encode_my_addr(struct ceph_messenger *msgr) | |||
95 | /* | 101 | /* |
96 | * work queue for all reading and writing to/from the socket. | 102 | * work queue for all reading and writing to/from the socket. |
97 | */ | 103 | */ |
98 | struct workqueue_struct *ceph_msgr_wq; | 104 | static struct workqueue_struct *ceph_msgr_wq; |
105 | |||
106 | void _ceph_msgr_exit(void) | ||
107 | { | ||
108 | if (ceph_msgr_wq) { | ||
109 | destroy_workqueue(ceph_msgr_wq); | ||
110 | ceph_msgr_wq = NULL; | ||
111 | } | ||
112 | |||
113 | BUG_ON(zero_page == NULL); | ||
114 | kunmap(zero_page); | ||
115 | page_cache_release(zero_page); | ||
116 | zero_page = NULL; | ||
117 | } | ||
99 | 118 | ||
100 | int ceph_msgr_init(void) | 119 | int ceph_msgr_init(void) |
101 | { | 120 | { |
121 | BUG_ON(zero_page != NULL); | ||
122 | zero_page = ZERO_PAGE(0); | ||
123 | page_cache_get(zero_page); | ||
124 | |||
102 | ceph_msgr_wq = alloc_workqueue("ceph-msgr", WQ_NON_REENTRANT, 0); | 125 | ceph_msgr_wq = alloc_workqueue("ceph-msgr", WQ_NON_REENTRANT, 0); |
103 | if (!ceph_msgr_wq) { | 126 | if (ceph_msgr_wq) |
104 | pr_err("msgr_init failed to create workqueue\n"); | 127 | return 0; |
105 | return -ENOMEM; | 128 | |
106 | } | 129 | pr_err("msgr_init failed to create workqueue\n"); |
107 | return 0; | 130 | _ceph_msgr_exit(); |
131 | |||
132 | return -ENOMEM; | ||
108 | } | 133 | } |
109 | EXPORT_SYMBOL(ceph_msgr_init); | 134 | EXPORT_SYMBOL(ceph_msgr_init); |
110 | 135 | ||
111 | void ceph_msgr_exit(void) | 136 | void ceph_msgr_exit(void) |
112 | { | 137 | { |
113 | destroy_workqueue(ceph_msgr_wq); | 138 | BUG_ON(ceph_msgr_wq == NULL); |
139 | |||
140 | _ceph_msgr_exit(); | ||
114 | } | 141 | } |
115 | EXPORT_SYMBOL(ceph_msgr_exit); | 142 | EXPORT_SYMBOL(ceph_msgr_exit); |
116 | 143 | ||
@@ -128,8 +155,8 @@ EXPORT_SYMBOL(ceph_msgr_flush); | |||
128 | /* data available on socket, or listen socket received a connect */ | 155 | /* data available on socket, or listen socket received a connect */ |
129 | static void ceph_data_ready(struct sock *sk, int count_unused) | 156 | static void ceph_data_ready(struct sock *sk, int count_unused) |
130 | { | 157 | { |
131 | struct ceph_connection *con = | 158 | struct ceph_connection *con = sk->sk_user_data; |
132 | (struct ceph_connection *)sk->sk_user_data; | 159 | |
133 | if (sk->sk_state != TCP_CLOSE_WAIT) { | 160 | if (sk->sk_state != TCP_CLOSE_WAIT) { |
134 | dout("ceph_data_ready on %p state = %lu, queueing work\n", | 161 | dout("ceph_data_ready on %p state = %lu, queueing work\n", |
135 | con, con->state); | 162 | con, con->state); |
@@ -140,26 +167,30 @@ static void ceph_data_ready(struct sock *sk, int count_unused) | |||
140 | /* socket has buffer space for writing */ | 167 | /* socket has buffer space for writing */ |
141 | static void ceph_write_space(struct sock *sk) | 168 | static void ceph_write_space(struct sock *sk) |
142 | { | 169 | { |
143 | struct ceph_connection *con = | 170 | struct ceph_connection *con = sk->sk_user_data; |
144 | (struct ceph_connection *)sk->sk_user_data; | ||
145 | 171 | ||
146 | /* only queue to workqueue if there is data we want to write. */ | 172 | /* only queue to workqueue if there is data we want to write, |
173 | * and there is sufficient space in the socket buffer to accept | ||
174 | * more data. clear SOCK_NOSPACE so that ceph_write_space() | ||
175 | * doesn't get called again until try_write() fills the socket | ||
176 | * buffer. See net/ipv4/tcp_input.c:tcp_check_space() | ||
177 | * and net/core/stream.c:sk_stream_write_space(). | ||
178 | */ | ||
147 | if (test_bit(WRITE_PENDING, &con->state)) { | 179 | if (test_bit(WRITE_PENDING, &con->state)) { |
148 | dout("ceph_write_space %p queueing write work\n", con); | 180 | if (sk_stream_wspace(sk) >= sk_stream_min_wspace(sk)) { |
149 | queue_con(con); | 181 | dout("ceph_write_space %p queueing write work\n", con); |
182 | clear_bit(SOCK_NOSPACE, &sk->sk_socket->flags); | ||
183 | queue_con(con); | ||
184 | } | ||
150 | } else { | 185 | } else { |
151 | dout("ceph_write_space %p nothing to write\n", con); | 186 | dout("ceph_write_space %p nothing to write\n", con); |
152 | } | 187 | } |
153 | |||
154 | /* since we have our own write_space, clear the SOCK_NOSPACE flag */ | ||
155 | clear_bit(SOCK_NOSPACE, &sk->sk_socket->flags); | ||
156 | } | 188 | } |
157 | 189 | ||
158 | /* socket's state has changed */ | 190 | /* socket's state has changed */ |
159 | static void ceph_state_change(struct sock *sk) | 191 | static void ceph_state_change(struct sock *sk) |
160 | { | 192 | { |
161 | struct ceph_connection *con = | 193 | struct ceph_connection *con = sk->sk_user_data; |
162 | (struct ceph_connection *)sk->sk_user_data; | ||
163 | 194 | ||
164 | dout("ceph_state_change %p state = %lu sk_state = %u\n", | 195 | dout("ceph_state_change %p state = %lu sk_state = %u\n", |
165 | con, con->state, sk->sk_state); | 196 | con, con->state, sk->sk_state); |
@@ -184,6 +215,8 @@ static void ceph_state_change(struct sock *sk) | |||
184 | dout("ceph_state_change TCP_ESTABLISHED\n"); | 215 | dout("ceph_state_change TCP_ESTABLISHED\n"); |
185 | queue_con(con); | 216 | queue_con(con); |
186 | break; | 217 | break; |
218 | default: /* Everything else is uninteresting */ | ||
219 | break; | ||
187 | } | 220 | } |
188 | } | 221 | } |
189 | 222 | ||
@@ -194,7 +227,7 @@ static void set_sock_callbacks(struct socket *sock, | |||
194 | struct ceph_connection *con) | 227 | struct ceph_connection *con) |
195 | { | 228 | { |
196 | struct sock *sk = sock->sk; | 229 | struct sock *sk = sock->sk; |
197 | sk->sk_user_data = (void *)con; | 230 | sk->sk_user_data = con; |
198 | sk->sk_data_ready = ceph_data_ready; | 231 | sk->sk_data_ready = ceph_data_ready; |
199 | sk->sk_write_space = ceph_write_space; | 232 | sk->sk_write_space = ceph_write_space; |
200 | sk->sk_state_change = ceph_state_change; | 233 | sk->sk_state_change = ceph_state_change; |
@@ -208,7 +241,7 @@ static void set_sock_callbacks(struct socket *sock, | |||
208 | /* | 241 | /* |
209 | * initiate connection to a remote socket. | 242 | * initiate connection to a remote socket. |
210 | */ | 243 | */ |
211 | static struct socket *ceph_tcp_connect(struct ceph_connection *con) | 244 | static int ceph_tcp_connect(struct ceph_connection *con) |
212 | { | 245 | { |
213 | struct sockaddr_storage *paddr = &con->peer_addr.in_addr; | 246 | struct sockaddr_storage *paddr = &con->peer_addr.in_addr; |
214 | struct socket *sock; | 247 | struct socket *sock; |
@@ -218,8 +251,7 @@ static struct socket *ceph_tcp_connect(struct ceph_connection *con) | |||
218 | ret = sock_create_kern(con->peer_addr.in_addr.ss_family, SOCK_STREAM, | 251 | ret = sock_create_kern(con->peer_addr.in_addr.ss_family, SOCK_STREAM, |
219 | IPPROTO_TCP, &sock); | 252 | IPPROTO_TCP, &sock); |
220 | if (ret) | 253 | if (ret) |
221 | return ERR_PTR(ret); | 254 | return ret; |
222 | con->sock = sock; | ||
223 | sock->sk->sk_allocation = GFP_NOFS; | 255 | sock->sk->sk_allocation = GFP_NOFS; |
224 | 256 | ||
225 | #ifdef CONFIG_LOCKDEP | 257 | #ifdef CONFIG_LOCKDEP |
@@ -236,19 +268,17 @@ static struct socket *ceph_tcp_connect(struct ceph_connection *con) | |||
236 | dout("connect %s EINPROGRESS sk_state = %u\n", | 268 | dout("connect %s EINPROGRESS sk_state = %u\n", |
237 | ceph_pr_addr(&con->peer_addr.in_addr), | 269 | ceph_pr_addr(&con->peer_addr.in_addr), |
238 | sock->sk->sk_state); | 270 | sock->sk->sk_state); |
239 | ret = 0; | 271 | } else if (ret < 0) { |
240 | } | ||
241 | if (ret < 0) { | ||
242 | pr_err("connect %s error %d\n", | 272 | pr_err("connect %s error %d\n", |
243 | ceph_pr_addr(&con->peer_addr.in_addr), ret); | 273 | ceph_pr_addr(&con->peer_addr.in_addr), ret); |
244 | sock_release(sock); | 274 | sock_release(sock); |
245 | con->sock = NULL; | ||
246 | con->error_msg = "connect error"; | 275 | con->error_msg = "connect error"; |
276 | |||
277 | return ret; | ||
247 | } | 278 | } |
279 | con->sock = sock; | ||
248 | 280 | ||
249 | if (ret < 0) | 281 | return 0; |
250 | return ERR_PTR(ret); | ||
251 | return sock; | ||
252 | } | 282 | } |
253 | 283 | ||
254 | static int ceph_tcp_recvmsg(struct socket *sock, void *buf, size_t len) | 284 | static int ceph_tcp_recvmsg(struct socket *sock, void *buf, size_t len) |
@@ -284,6 +314,19 @@ static int ceph_tcp_sendmsg(struct socket *sock, struct kvec *iov, | |||
284 | return r; | 314 | return r; |
285 | } | 315 | } |
286 | 316 | ||
317 | static int ceph_tcp_sendpage(struct socket *sock, struct page *page, | ||
318 | int offset, size_t size, int more) | ||
319 | { | ||
320 | int flags = MSG_DONTWAIT | MSG_NOSIGNAL | (more ? MSG_MORE : MSG_EOR); | ||
321 | int ret; | ||
322 | |||
323 | ret = kernel_sendpage(sock, page, offset, size, flags); | ||
324 | if (ret == -EAGAIN) | ||
325 | ret = 0; | ||
326 | |||
327 | return ret; | ||
328 | } | ||
329 | |||
287 | 330 | ||
288 | /* | 331 | /* |
289 | * Shutdown/close the socket for the given connection. | 332 | * Shutdown/close the socket for the given connection. |
@@ -391,22 +434,23 @@ bool ceph_con_opened(struct ceph_connection *con) | |||
391 | */ | 434 | */ |
392 | struct ceph_connection *ceph_con_get(struct ceph_connection *con) | 435 | struct ceph_connection *ceph_con_get(struct ceph_connection *con) |
393 | { | 436 | { |
394 | dout("con_get %p nref = %d -> %d\n", con, | 437 | int nref = __atomic_add_unless(&con->nref, 1, 0); |
395 | atomic_read(&con->nref), atomic_read(&con->nref) + 1); | 438 | |
396 | if (atomic_inc_not_zero(&con->nref)) | 439 | dout("con_get %p nref = %d -> %d\n", con, nref, nref + 1); |
397 | return con; | 440 | |
398 | return NULL; | 441 | return nref ? con : NULL; |
399 | } | 442 | } |
400 | 443 | ||
401 | void ceph_con_put(struct ceph_connection *con) | 444 | void ceph_con_put(struct ceph_connection *con) |
402 | { | 445 | { |
403 | dout("con_put %p nref = %d -> %d\n", con, | 446 | int nref = atomic_dec_return(&con->nref); |
404 | atomic_read(&con->nref), atomic_read(&con->nref) - 1); | 447 | |
405 | BUG_ON(atomic_read(&con->nref) == 0); | 448 | BUG_ON(nref < 0); |
406 | if (atomic_dec_and_test(&con->nref)) { | 449 | if (nref == 0) { |
407 | BUG_ON(con->sock); | 450 | BUG_ON(con->sock); |
408 | kfree(con); | 451 | kfree(con); |
409 | } | 452 | } |
453 | dout("con_put %p nref = %d -> %d\n", con, nref + 1, nref); | ||
410 | } | 454 | } |
411 | 455 | ||
412 | /* | 456 | /* |
@@ -442,14 +486,35 @@ static u32 get_global_seq(struct ceph_messenger *msgr, u32 gt) | |||
442 | return ret; | 486 | return ret; |
443 | } | 487 | } |
444 | 488 | ||
489 | static void ceph_con_out_kvec_reset(struct ceph_connection *con) | ||
490 | { | ||
491 | con->out_kvec_left = 0; | ||
492 | con->out_kvec_bytes = 0; | ||
493 | con->out_kvec_cur = &con->out_kvec[0]; | ||
494 | } | ||
495 | |||
496 | static void ceph_con_out_kvec_add(struct ceph_connection *con, | ||
497 | size_t size, void *data) | ||
498 | { | ||
499 | int index; | ||
500 | |||
501 | index = con->out_kvec_left; | ||
502 | BUG_ON(index >= ARRAY_SIZE(con->out_kvec)); | ||
503 | |||
504 | con->out_kvec[index].iov_len = size; | ||
505 | con->out_kvec[index].iov_base = data; | ||
506 | con->out_kvec_left++; | ||
507 | con->out_kvec_bytes += size; | ||
508 | } | ||
445 | 509 | ||
446 | /* | 510 | /* |
447 | * Prepare footer for currently outgoing message, and finish things | 511 | * Prepare footer for currently outgoing message, and finish things |
448 | * off. Assumes out_kvec* are already valid.. we just add on to the end. | 512 | * off. Assumes out_kvec* are already valid.. we just add on to the end. |
449 | */ | 513 | */ |
450 | static void prepare_write_message_footer(struct ceph_connection *con, int v) | 514 | static void prepare_write_message_footer(struct ceph_connection *con) |
451 | { | 515 | { |
452 | struct ceph_msg *m = con->out_msg; | 516 | struct ceph_msg *m = con->out_msg; |
517 | int v = con->out_kvec_left; | ||
453 | 518 | ||
454 | dout("prepare_write_message_footer %p\n", con); | 519 | dout("prepare_write_message_footer %p\n", con); |
455 | con->out_kvec_is_msg = true; | 520 | con->out_kvec_is_msg = true; |
@@ -467,9 +532,9 @@ static void prepare_write_message_footer(struct ceph_connection *con, int v) | |||
467 | static void prepare_write_message(struct ceph_connection *con) | 532 | static void prepare_write_message(struct ceph_connection *con) |
468 | { | 533 | { |
469 | struct ceph_msg *m; | 534 | struct ceph_msg *m; |
470 | int v = 0; | 535 | u32 crc; |
471 | 536 | ||
472 | con->out_kvec_bytes = 0; | 537 | ceph_con_out_kvec_reset(con); |
473 | con->out_kvec_is_msg = true; | 538 | con->out_kvec_is_msg = true; |
474 | con->out_msg_done = false; | 539 | con->out_msg_done = false; |
475 | 540 | ||
@@ -477,16 +542,13 @@ static void prepare_write_message(struct ceph_connection *con) | |||
477 | * TCP packet that's a good thing. */ | 542 | * TCP packet that's a good thing. */ |
478 | if (con->in_seq > con->in_seq_acked) { | 543 | if (con->in_seq > con->in_seq_acked) { |
479 | con->in_seq_acked = con->in_seq; | 544 | con->in_seq_acked = con->in_seq; |
480 | con->out_kvec[v].iov_base = &tag_ack; | 545 | ceph_con_out_kvec_add(con, sizeof (tag_ack), &tag_ack); |
481 | con->out_kvec[v++].iov_len = 1; | ||
482 | con->out_temp_ack = cpu_to_le64(con->in_seq_acked); | 546 | con->out_temp_ack = cpu_to_le64(con->in_seq_acked); |
483 | con->out_kvec[v].iov_base = &con->out_temp_ack; | 547 | ceph_con_out_kvec_add(con, sizeof (con->out_temp_ack), |
484 | con->out_kvec[v++].iov_len = sizeof(con->out_temp_ack); | 548 | &con->out_temp_ack); |
485 | con->out_kvec_bytes = 1 + sizeof(con->out_temp_ack); | ||
486 | } | 549 | } |
487 | 550 | ||
488 | m = list_first_entry(&con->out_queue, | 551 | m = list_first_entry(&con->out_queue, struct ceph_msg, list_head); |
489 | struct ceph_msg, list_head); | ||
490 | con->out_msg = m; | 552 | con->out_msg = m; |
491 | 553 | ||
492 | /* put message on sent list */ | 554 | /* put message on sent list */ |
@@ -510,30 +572,26 @@ static void prepare_write_message(struct ceph_connection *con) | |||
510 | BUG_ON(le32_to_cpu(m->hdr.front_len) != m->front.iov_len); | 572 | BUG_ON(le32_to_cpu(m->hdr.front_len) != m->front.iov_len); |
511 | 573 | ||
512 | /* tag + hdr + front + middle */ | 574 | /* tag + hdr + front + middle */ |
513 | con->out_kvec[v].iov_base = &tag_msg; | 575 | ceph_con_out_kvec_add(con, sizeof (tag_msg), &tag_msg); |
514 | con->out_kvec[v++].iov_len = 1; | 576 | ceph_con_out_kvec_add(con, sizeof (m->hdr), &m->hdr); |
515 | con->out_kvec[v].iov_base = &m->hdr; | 577 | ceph_con_out_kvec_add(con, m->front.iov_len, m->front.iov_base); |
516 | con->out_kvec[v++].iov_len = sizeof(m->hdr); | 578 | |
517 | con->out_kvec[v++] = m->front; | ||
518 | if (m->middle) | 579 | if (m->middle) |
519 | con->out_kvec[v++] = m->middle->vec; | 580 | ceph_con_out_kvec_add(con, m->middle->vec.iov_len, |
520 | con->out_kvec_left = v; | 581 | m->middle->vec.iov_base); |
521 | con->out_kvec_bytes += 1 + sizeof(m->hdr) + m->front.iov_len + | ||
522 | (m->middle ? m->middle->vec.iov_len : 0); | ||
523 | con->out_kvec_cur = con->out_kvec; | ||
524 | 582 | ||
525 | /* fill in crc (except data pages), footer */ | 583 | /* fill in crc (except data pages), footer */ |
526 | con->out_msg->hdr.crc = | 584 | crc = crc32c(0, &m->hdr, offsetof(struct ceph_msg_header, crc)); |
527 | cpu_to_le32(crc32c(0, (void *)&m->hdr, | 585 | con->out_msg->hdr.crc = cpu_to_le32(crc); |
528 | sizeof(m->hdr) - sizeof(m->hdr.crc))); | ||
529 | con->out_msg->footer.flags = CEPH_MSG_FOOTER_COMPLETE; | 586 | con->out_msg->footer.flags = CEPH_MSG_FOOTER_COMPLETE; |
530 | con->out_msg->footer.front_crc = | 587 | |
531 | cpu_to_le32(crc32c(0, m->front.iov_base, m->front.iov_len)); | 588 | crc = crc32c(0, m->front.iov_base, m->front.iov_len); |
532 | if (m->middle) | 589 | con->out_msg->footer.front_crc = cpu_to_le32(crc); |
533 | con->out_msg->footer.middle_crc = | 590 | if (m->middle) { |
534 | cpu_to_le32(crc32c(0, m->middle->vec.iov_base, | 591 | crc = crc32c(0, m->middle->vec.iov_base, |
535 | m->middle->vec.iov_len)); | 592 | m->middle->vec.iov_len); |
536 | else | 593 | con->out_msg->footer.middle_crc = cpu_to_le32(crc); |
594 | } else | ||
537 | con->out_msg->footer.middle_crc = 0; | 595 | con->out_msg->footer.middle_crc = 0; |
538 | con->out_msg->footer.data_crc = 0; | 596 | con->out_msg->footer.data_crc = 0; |
539 | dout("prepare_write_message front_crc %u data_crc %u\n", | 597 | dout("prepare_write_message front_crc %u data_crc %u\n", |
@@ -549,11 +607,11 @@ static void prepare_write_message(struct ceph_connection *con) | |||
549 | else | 607 | else |
550 | con->out_msg_pos.page_pos = 0; | 608 | con->out_msg_pos.page_pos = 0; |
551 | con->out_msg_pos.data_pos = 0; | 609 | con->out_msg_pos.data_pos = 0; |
552 | con->out_msg_pos.did_page_crc = 0; | 610 | con->out_msg_pos.did_page_crc = false; |
553 | con->out_more = 1; /* data + footer will follow */ | 611 | con->out_more = 1; /* data + footer will follow */ |
554 | } else { | 612 | } else { |
555 | /* no, queue up footer too and be done */ | 613 | /* no, queue up footer too and be done */ |
556 | prepare_write_message_footer(con, v); | 614 | prepare_write_message_footer(con); |
557 | } | 615 | } |
558 | 616 | ||
559 | set_bit(WRITE_PENDING, &con->state); | 617 | set_bit(WRITE_PENDING, &con->state); |
@@ -568,14 +626,14 @@ static void prepare_write_ack(struct ceph_connection *con) | |||
568 | con->in_seq_acked, con->in_seq); | 626 | con->in_seq_acked, con->in_seq); |
569 | con->in_seq_acked = con->in_seq; | 627 | con->in_seq_acked = con->in_seq; |
570 | 628 | ||
571 | con->out_kvec[0].iov_base = &tag_ack; | 629 | ceph_con_out_kvec_reset(con); |
572 | con->out_kvec[0].iov_len = 1; | 630 | |
631 | ceph_con_out_kvec_add(con, sizeof (tag_ack), &tag_ack); | ||
632 | |||
573 | con->out_temp_ack = cpu_to_le64(con->in_seq_acked); | 633 | con->out_temp_ack = cpu_to_le64(con->in_seq_acked); |
574 | con->out_kvec[1].iov_base = &con->out_temp_ack; | 634 | ceph_con_out_kvec_add(con, sizeof (con->out_temp_ack), |
575 | con->out_kvec[1].iov_len = sizeof(con->out_temp_ack); | 635 | &con->out_temp_ack); |
576 | con->out_kvec_left = 2; | 636 | |
577 | con->out_kvec_bytes = 1 + sizeof(con->out_temp_ack); | ||
578 | con->out_kvec_cur = con->out_kvec; | ||
579 | con->out_more = 1; /* more will follow.. eventually.. */ | 637 | con->out_more = 1; /* more will follow.. eventually.. */ |
580 | set_bit(WRITE_PENDING, &con->state); | 638 | set_bit(WRITE_PENDING, &con->state); |
581 | } | 639 | } |
@@ -586,11 +644,8 @@ static void prepare_write_ack(struct ceph_connection *con) | |||
586 | static void prepare_write_keepalive(struct ceph_connection *con) | 644 | static void prepare_write_keepalive(struct ceph_connection *con) |
587 | { | 645 | { |
588 | dout("prepare_write_keepalive %p\n", con); | 646 | dout("prepare_write_keepalive %p\n", con); |
589 | con->out_kvec[0].iov_base = &tag_keepalive; | 647 | ceph_con_out_kvec_reset(con); |
590 | con->out_kvec[0].iov_len = 1; | 648 | ceph_con_out_kvec_add(con, sizeof (tag_keepalive), &tag_keepalive); |
591 | con->out_kvec_left = 1; | ||
592 | con->out_kvec_bytes = 1; | ||
593 | con->out_kvec_cur = con->out_kvec; | ||
594 | set_bit(WRITE_PENDING, &con->state); | 649 | set_bit(WRITE_PENDING, &con->state); |
595 | } | 650 | } |
596 | 651 | ||
@@ -619,12 +674,9 @@ static int prepare_connect_authorizer(struct ceph_connection *con) | |||
619 | con->out_connect.authorizer_protocol = cpu_to_le32(auth_protocol); | 674 | con->out_connect.authorizer_protocol = cpu_to_le32(auth_protocol); |
620 | con->out_connect.authorizer_len = cpu_to_le32(auth_len); | 675 | con->out_connect.authorizer_len = cpu_to_le32(auth_len); |
621 | 676 | ||
622 | if (auth_len) { | 677 | if (auth_len) |
623 | con->out_kvec[con->out_kvec_left].iov_base = auth_buf; | 678 | ceph_con_out_kvec_add(con, auth_len, auth_buf); |
624 | con->out_kvec[con->out_kvec_left].iov_len = auth_len; | 679 | |
625 | con->out_kvec_left++; | ||
626 | con->out_kvec_bytes += auth_len; | ||
627 | } | ||
628 | return 0; | 680 | return 0; |
629 | } | 681 | } |
630 | 682 | ||
@@ -634,22 +686,18 @@ static int prepare_connect_authorizer(struct ceph_connection *con) | |||
634 | static void prepare_write_banner(struct ceph_messenger *msgr, | 686 | static void prepare_write_banner(struct ceph_messenger *msgr, |
635 | struct ceph_connection *con) | 687 | struct ceph_connection *con) |
636 | { | 688 | { |
637 | int len = strlen(CEPH_BANNER); | 689 | ceph_con_out_kvec_reset(con); |
690 | ceph_con_out_kvec_add(con, strlen(CEPH_BANNER), CEPH_BANNER); | ||
691 | ceph_con_out_kvec_add(con, sizeof (msgr->my_enc_addr), | ||
692 | &msgr->my_enc_addr); | ||
638 | 693 | ||
639 | con->out_kvec[0].iov_base = CEPH_BANNER; | ||
640 | con->out_kvec[0].iov_len = len; | ||
641 | con->out_kvec[1].iov_base = &msgr->my_enc_addr; | ||
642 | con->out_kvec[1].iov_len = sizeof(msgr->my_enc_addr); | ||
643 | con->out_kvec_left = 2; | ||
644 | con->out_kvec_bytes = len + sizeof(msgr->my_enc_addr); | ||
645 | con->out_kvec_cur = con->out_kvec; | ||
646 | con->out_more = 0; | 694 | con->out_more = 0; |
647 | set_bit(WRITE_PENDING, &con->state); | 695 | set_bit(WRITE_PENDING, &con->state); |
648 | } | 696 | } |
649 | 697 | ||
650 | static int prepare_write_connect(struct ceph_messenger *msgr, | 698 | static int prepare_write_connect(struct ceph_messenger *msgr, |
651 | struct ceph_connection *con, | 699 | struct ceph_connection *con, |
652 | int after_banner) | 700 | int include_banner) |
653 | { | 701 | { |
654 | unsigned global_seq = get_global_seq(con->msgr, 0); | 702 | unsigned global_seq = get_global_seq(con->msgr, 0); |
655 | int proto; | 703 | int proto; |
@@ -678,22 +726,18 @@ static int prepare_write_connect(struct ceph_messenger *msgr, | |||
678 | con->out_connect.protocol_version = cpu_to_le32(proto); | 726 | con->out_connect.protocol_version = cpu_to_le32(proto); |
679 | con->out_connect.flags = 0; | 727 | con->out_connect.flags = 0; |
680 | 728 | ||
681 | if (!after_banner) { | 729 | if (include_banner) |
682 | con->out_kvec_left = 0; | 730 | prepare_write_banner(msgr, con); |
683 | con->out_kvec_bytes = 0; | 731 | else |
684 | } | 732 | ceph_con_out_kvec_reset(con); |
685 | con->out_kvec[con->out_kvec_left].iov_base = &con->out_connect; | 733 | ceph_con_out_kvec_add(con, sizeof (con->out_connect), &con->out_connect); |
686 | con->out_kvec[con->out_kvec_left].iov_len = sizeof(con->out_connect); | 734 | |
687 | con->out_kvec_left++; | ||
688 | con->out_kvec_bytes += sizeof(con->out_connect); | ||
689 | con->out_kvec_cur = con->out_kvec; | ||
690 | con->out_more = 0; | 735 | con->out_more = 0; |
691 | set_bit(WRITE_PENDING, &con->state); | 736 | set_bit(WRITE_PENDING, &con->state); |
692 | 737 | ||
693 | return prepare_connect_authorizer(con); | 738 | return prepare_connect_authorizer(con); |
694 | } | 739 | } |
695 | 740 | ||
696 | |||
697 | /* | 741 | /* |
698 | * write as much of pending kvecs to the socket as we can. | 742 | * write as much of pending kvecs to the socket as we can. |
699 | * 1 -> done | 743 | * 1 -> done |
@@ -714,17 +758,18 @@ static int write_partial_kvec(struct ceph_connection *con) | |||
714 | con->out_kvec_bytes -= ret; | 758 | con->out_kvec_bytes -= ret; |
715 | if (con->out_kvec_bytes == 0) | 759 | if (con->out_kvec_bytes == 0) |
716 | break; /* done */ | 760 | break; /* done */ |
717 | while (ret > 0) { | 761 | |
718 | if (ret >= con->out_kvec_cur->iov_len) { | 762 | /* account for full iov entries consumed */ |
719 | ret -= con->out_kvec_cur->iov_len; | 763 | while (ret >= con->out_kvec_cur->iov_len) { |
720 | con->out_kvec_cur++; | 764 | BUG_ON(!con->out_kvec_left); |
721 | con->out_kvec_left--; | 765 | ret -= con->out_kvec_cur->iov_len; |
722 | } else { | 766 | con->out_kvec_cur++; |
723 | con->out_kvec_cur->iov_len -= ret; | 767 | con->out_kvec_left--; |
724 | con->out_kvec_cur->iov_base += ret; | 768 | } |
725 | ret = 0; | 769 | /* and for a partially-consumed entry */ |
726 | break; | 770 | if (ret) { |
727 | } | 771 | con->out_kvec_cur->iov_len -= ret; |
772 | con->out_kvec_cur->iov_base += ret; | ||
728 | } | 773 | } |
729 | } | 774 | } |
730 | con->out_kvec_left = 0; | 775 | con->out_kvec_left = 0; |
@@ -773,7 +818,7 @@ static int write_partial_msg_pages(struct ceph_connection *con) | |||
773 | struct ceph_msg *msg = con->out_msg; | 818 | struct ceph_msg *msg = con->out_msg; |
774 | unsigned data_len = le32_to_cpu(msg->hdr.data_len); | 819 | unsigned data_len = le32_to_cpu(msg->hdr.data_len); |
775 | size_t len; | 820 | size_t len; |
776 | int crc = con->msgr->nocrc; | 821 | bool do_datacrc = !con->msgr->nocrc; |
777 | int ret; | 822 | int ret; |
778 | int total_max_write; | 823 | int total_max_write; |
779 | int in_trail = 0; | 824 | int in_trail = 0; |
@@ -790,9 +835,8 @@ static int write_partial_msg_pages(struct ceph_connection *con) | |||
790 | 835 | ||
791 | while (data_len > con->out_msg_pos.data_pos) { | 836 | while (data_len > con->out_msg_pos.data_pos) { |
792 | struct page *page = NULL; | 837 | struct page *page = NULL; |
793 | void *kaddr = NULL; | ||
794 | int max_write = PAGE_SIZE; | 838 | int max_write = PAGE_SIZE; |
795 | int page_shift = 0; | 839 | int bio_offset = 0; |
796 | 840 | ||
797 | total_max_write = data_len - trail_len - | 841 | total_max_write = data_len - trail_len - |
798 | con->out_msg_pos.data_pos; | 842 | con->out_msg_pos.data_pos; |
@@ -811,58 +855,47 @@ static int write_partial_msg_pages(struct ceph_connection *con) | |||
811 | 855 | ||
812 | page = list_first_entry(&msg->trail->head, | 856 | page = list_first_entry(&msg->trail->head, |
813 | struct page, lru); | 857 | struct page, lru); |
814 | if (crc) | ||
815 | kaddr = kmap(page); | ||
816 | max_write = PAGE_SIZE; | 858 | max_write = PAGE_SIZE; |
817 | } else if (msg->pages) { | 859 | } else if (msg->pages) { |
818 | page = msg->pages[con->out_msg_pos.page]; | 860 | page = msg->pages[con->out_msg_pos.page]; |
819 | if (crc) | ||
820 | kaddr = kmap(page); | ||
821 | } else if (msg->pagelist) { | 861 | } else if (msg->pagelist) { |
822 | page = list_first_entry(&msg->pagelist->head, | 862 | page = list_first_entry(&msg->pagelist->head, |
823 | struct page, lru); | 863 | struct page, lru); |
824 | if (crc) | ||
825 | kaddr = kmap(page); | ||
826 | #ifdef CONFIG_BLOCK | 864 | #ifdef CONFIG_BLOCK |
827 | } else if (msg->bio) { | 865 | } else if (msg->bio) { |
828 | struct bio_vec *bv; | 866 | struct bio_vec *bv; |
829 | 867 | ||
830 | bv = bio_iovec_idx(msg->bio_iter, msg->bio_seg); | 868 | bv = bio_iovec_idx(msg->bio_iter, msg->bio_seg); |
831 | page = bv->bv_page; | 869 | page = bv->bv_page; |
832 | page_shift = bv->bv_offset; | 870 | bio_offset = bv->bv_offset; |
833 | if (crc) | ||
834 | kaddr = kmap(page) + page_shift; | ||
835 | max_write = bv->bv_len; | 871 | max_write = bv->bv_len; |
836 | #endif | 872 | #endif |
837 | } else { | 873 | } else { |
838 | page = con->msgr->zero_page; | 874 | page = zero_page; |
839 | if (crc) | ||
840 | kaddr = page_address(con->msgr->zero_page); | ||
841 | } | 875 | } |
842 | len = min_t(int, max_write - con->out_msg_pos.page_pos, | 876 | len = min_t(int, max_write - con->out_msg_pos.page_pos, |
843 | total_max_write); | 877 | total_max_write); |
844 | 878 | ||
845 | if (crc && !con->out_msg_pos.did_page_crc) { | 879 | if (do_datacrc && !con->out_msg_pos.did_page_crc) { |
846 | void *base = kaddr + con->out_msg_pos.page_pos; | 880 | void *base; |
881 | u32 crc; | ||
847 | u32 tmpcrc = le32_to_cpu(con->out_msg->footer.data_crc); | 882 | u32 tmpcrc = le32_to_cpu(con->out_msg->footer.data_crc); |
883 | char *kaddr; | ||
848 | 884 | ||
885 | kaddr = kmap(page); | ||
849 | BUG_ON(kaddr == NULL); | 886 | BUG_ON(kaddr == NULL); |
850 | con->out_msg->footer.data_crc = | 887 | base = kaddr + con->out_msg_pos.page_pos + bio_offset; |
851 | cpu_to_le32(crc32c(tmpcrc, base, len)); | 888 | crc = crc32c(tmpcrc, base, len); |
852 | con->out_msg_pos.did_page_crc = 1; | 889 | con->out_msg->footer.data_crc = cpu_to_le32(crc); |
890 | con->out_msg_pos.did_page_crc = true; | ||
853 | } | 891 | } |
854 | ret = kernel_sendpage(con->sock, page, | 892 | ret = ceph_tcp_sendpage(con->sock, page, |
855 | con->out_msg_pos.page_pos + page_shift, | 893 | con->out_msg_pos.page_pos + bio_offset, |
856 | len, | 894 | len, 1); |
857 | MSG_DONTWAIT | MSG_NOSIGNAL | | 895 | |
858 | MSG_MORE); | 896 | if (do_datacrc) |
859 | |||
860 | if (crc && | ||
861 | (msg->pages || msg->pagelist || msg->bio || in_trail)) | ||
862 | kunmap(page); | 897 | kunmap(page); |
863 | 898 | ||
864 | if (ret == -EAGAIN) | ||
865 | ret = 0; | ||
866 | if (ret <= 0) | 899 | if (ret <= 0) |
867 | goto out; | 900 | goto out; |
868 | 901 | ||
@@ -871,7 +904,7 @@ static int write_partial_msg_pages(struct ceph_connection *con) | |||
871 | if (ret == len) { | 904 | if (ret == len) { |
872 | con->out_msg_pos.page_pos = 0; | 905 | con->out_msg_pos.page_pos = 0; |
873 | con->out_msg_pos.page++; | 906 | con->out_msg_pos.page++; |
874 | con->out_msg_pos.did_page_crc = 0; | 907 | con->out_msg_pos.did_page_crc = false; |
875 | if (in_trail) | 908 | if (in_trail) |
876 | list_move_tail(&page->lru, | 909 | list_move_tail(&page->lru, |
877 | &msg->trail->head); | 910 | &msg->trail->head); |
@@ -888,12 +921,10 @@ static int write_partial_msg_pages(struct ceph_connection *con) | |||
888 | dout("write_partial_msg_pages %p msg %p done\n", con, msg); | 921 | dout("write_partial_msg_pages %p msg %p done\n", con, msg); |
889 | 922 | ||
890 | /* prepare and queue up footer, too */ | 923 | /* prepare and queue up footer, too */ |
891 | if (!crc) | 924 | if (!do_datacrc) |
892 | con->out_msg->footer.flags |= CEPH_MSG_FOOTER_NOCRC; | 925 | con->out_msg->footer.flags |= CEPH_MSG_FOOTER_NOCRC; |
893 | con->out_kvec_bytes = 0; | 926 | ceph_con_out_kvec_reset(con); |
894 | con->out_kvec_left = 0; | 927 | prepare_write_message_footer(con); |
895 | con->out_kvec_cur = con->out_kvec; | ||
896 | prepare_write_message_footer(con, 0); | ||
897 | ret = 1; | 928 | ret = 1; |
898 | out: | 929 | out: |
899 | return ret; | 930 | return ret; |
@@ -907,12 +938,9 @@ static int write_partial_skip(struct ceph_connection *con) | |||
907 | int ret; | 938 | int ret; |
908 | 939 | ||
909 | while (con->out_skip > 0) { | 940 | while (con->out_skip > 0) { |
910 | struct kvec iov = { | 941 | size_t size = min(con->out_skip, (int) PAGE_CACHE_SIZE); |
911 | .iov_base = page_address(con->msgr->zero_page), | ||
912 | .iov_len = min(con->out_skip, (int)PAGE_CACHE_SIZE) | ||
913 | }; | ||
914 | 942 | ||
915 | ret = ceph_tcp_sendmsg(con->sock, &iov, 1, iov.iov_len, 1); | 943 | ret = ceph_tcp_sendpage(con->sock, zero_page, 0, size, 1); |
916 | if (ret <= 0) | 944 | if (ret <= 0) |
917 | goto out; | 945 | goto out; |
918 | con->out_skip -= ret; | 946 | con->out_skip -= ret; |
@@ -1085,8 +1113,8 @@ static void addr_set_port(struct sockaddr_storage *ss, int p) | |||
1085 | static int ceph_pton(const char *str, size_t len, struct sockaddr_storage *ss, | 1113 | static int ceph_pton(const char *str, size_t len, struct sockaddr_storage *ss, |
1086 | char delim, const char **ipend) | 1114 | char delim, const char **ipend) |
1087 | { | 1115 | { |
1088 | struct sockaddr_in *in4 = (void *)ss; | 1116 | struct sockaddr_in *in4 = (struct sockaddr_in *) ss; |
1089 | struct sockaddr_in6 *in6 = (void *)ss; | 1117 | struct sockaddr_in6 *in6 = (struct sockaddr_in6 *) ss; |
1090 | 1118 | ||
1091 | memset(ss, 0, sizeof(*ss)); | 1119 | memset(ss, 0, sizeof(*ss)); |
1092 | 1120 | ||
@@ -1512,10 +1540,9 @@ static int read_partial_message_section(struct ceph_connection *con, | |||
1512 | if (ret <= 0) | 1540 | if (ret <= 0) |
1513 | return ret; | 1541 | return ret; |
1514 | section->iov_len += ret; | 1542 | section->iov_len += ret; |
1515 | if (section->iov_len == sec_len) | ||
1516 | *crc = crc32c(0, section->iov_base, | ||
1517 | section->iov_len); | ||
1518 | } | 1543 | } |
1544 | if (section->iov_len == sec_len) | ||
1545 | *crc = crc32c(0, section->iov_base, section->iov_len); | ||
1519 | 1546 | ||
1520 | return 1; | 1547 | return 1; |
1521 | } | 1548 | } |
@@ -1527,7 +1554,7 @@ static struct ceph_msg *ceph_alloc_msg(struct ceph_connection *con, | |||
1527 | 1554 | ||
1528 | static int read_partial_message_pages(struct ceph_connection *con, | 1555 | static int read_partial_message_pages(struct ceph_connection *con, |
1529 | struct page **pages, | 1556 | struct page **pages, |
1530 | unsigned data_len, int datacrc) | 1557 | unsigned data_len, bool do_datacrc) |
1531 | { | 1558 | { |
1532 | void *p; | 1559 | void *p; |
1533 | int ret; | 1560 | int ret; |
@@ -1540,7 +1567,7 @@ static int read_partial_message_pages(struct ceph_connection *con, | |||
1540 | p = kmap(pages[con->in_msg_pos.page]); | 1567 | p = kmap(pages[con->in_msg_pos.page]); |
1541 | ret = ceph_tcp_recvmsg(con->sock, p + con->in_msg_pos.page_pos, | 1568 | ret = ceph_tcp_recvmsg(con->sock, p + con->in_msg_pos.page_pos, |
1542 | left); | 1569 | left); |
1543 | if (ret > 0 && datacrc) | 1570 | if (ret > 0 && do_datacrc) |
1544 | con->in_data_crc = | 1571 | con->in_data_crc = |
1545 | crc32c(con->in_data_crc, | 1572 | crc32c(con->in_data_crc, |
1546 | p + con->in_msg_pos.page_pos, ret); | 1573 | p + con->in_msg_pos.page_pos, ret); |
@@ -1560,7 +1587,7 @@ static int read_partial_message_pages(struct ceph_connection *con, | |||
1560 | #ifdef CONFIG_BLOCK | 1587 | #ifdef CONFIG_BLOCK |
1561 | static int read_partial_message_bio(struct ceph_connection *con, | 1588 | static int read_partial_message_bio(struct ceph_connection *con, |
1562 | struct bio **bio_iter, int *bio_seg, | 1589 | struct bio **bio_iter, int *bio_seg, |
1563 | unsigned data_len, int datacrc) | 1590 | unsigned data_len, bool do_datacrc) |
1564 | { | 1591 | { |
1565 | struct bio_vec *bv = bio_iovec_idx(*bio_iter, *bio_seg); | 1592 | struct bio_vec *bv = bio_iovec_idx(*bio_iter, *bio_seg); |
1566 | void *p; | 1593 | void *p; |
@@ -1576,7 +1603,7 @@ static int read_partial_message_bio(struct ceph_connection *con, | |||
1576 | 1603 | ||
1577 | ret = ceph_tcp_recvmsg(con->sock, p + con->in_msg_pos.page_pos, | 1604 | ret = ceph_tcp_recvmsg(con->sock, p + con->in_msg_pos.page_pos, |
1578 | left); | 1605 | left); |
1579 | if (ret > 0 && datacrc) | 1606 | if (ret > 0 && do_datacrc) |
1580 | con->in_data_crc = | 1607 | con->in_data_crc = |
1581 | crc32c(con->in_data_crc, | 1608 | crc32c(con->in_data_crc, |
1582 | p + con->in_msg_pos.page_pos, ret); | 1609 | p + con->in_msg_pos.page_pos, ret); |
@@ -1603,9 +1630,10 @@ static int read_partial_message(struct ceph_connection *con) | |||
1603 | int ret; | 1630 | int ret; |
1604 | int to, left; | 1631 | int to, left; |
1605 | unsigned front_len, middle_len, data_len; | 1632 | unsigned front_len, middle_len, data_len; |
1606 | int datacrc = con->msgr->nocrc; | 1633 | bool do_datacrc = !con->msgr->nocrc; |
1607 | int skip; | 1634 | int skip; |
1608 | u64 seq; | 1635 | u64 seq; |
1636 | u32 crc; | ||
1609 | 1637 | ||
1610 | dout("read_partial_message con %p msg %p\n", con, m); | 1638 | dout("read_partial_message con %p msg %p\n", con, m); |
1611 | 1639 | ||
@@ -1618,17 +1646,16 @@ static int read_partial_message(struct ceph_connection *con) | |||
1618 | if (ret <= 0) | 1646 | if (ret <= 0) |
1619 | return ret; | 1647 | return ret; |
1620 | con->in_base_pos += ret; | 1648 | con->in_base_pos += ret; |
1621 | if (con->in_base_pos == sizeof(con->in_hdr)) { | ||
1622 | u32 crc = crc32c(0, (void *)&con->in_hdr, | ||
1623 | sizeof(con->in_hdr) - sizeof(con->in_hdr.crc)); | ||
1624 | if (crc != le32_to_cpu(con->in_hdr.crc)) { | ||
1625 | pr_err("read_partial_message bad hdr " | ||
1626 | " crc %u != expected %u\n", | ||
1627 | crc, con->in_hdr.crc); | ||
1628 | return -EBADMSG; | ||
1629 | } | ||
1630 | } | ||
1631 | } | 1649 | } |
1650 | |||
1651 | crc = crc32c(0, &con->in_hdr, offsetof(struct ceph_msg_header, crc)); | ||
1652 | if (cpu_to_le32(crc) != con->in_hdr.crc) { | ||
1653 | pr_err("read_partial_message bad hdr " | ||
1654 | " crc %u != expected %u\n", | ||
1655 | crc, con->in_hdr.crc); | ||
1656 | return -EBADMSG; | ||
1657 | } | ||
1658 | |||
1632 | front_len = le32_to_cpu(con->in_hdr.front_len); | 1659 | front_len = le32_to_cpu(con->in_hdr.front_len); |
1633 | if (front_len > CEPH_MSG_MAX_FRONT_LEN) | 1660 | if (front_len > CEPH_MSG_MAX_FRONT_LEN) |
1634 | return -EIO; | 1661 | return -EIO; |
@@ -1714,7 +1741,7 @@ static int read_partial_message(struct ceph_connection *con) | |||
1714 | while (con->in_msg_pos.data_pos < data_len) { | 1741 | while (con->in_msg_pos.data_pos < data_len) { |
1715 | if (m->pages) { | 1742 | if (m->pages) { |
1716 | ret = read_partial_message_pages(con, m->pages, | 1743 | ret = read_partial_message_pages(con, m->pages, |
1717 | data_len, datacrc); | 1744 | data_len, do_datacrc); |
1718 | if (ret <= 0) | 1745 | if (ret <= 0) |
1719 | return ret; | 1746 | return ret; |
1720 | #ifdef CONFIG_BLOCK | 1747 | #ifdef CONFIG_BLOCK |
@@ -1722,7 +1749,7 @@ static int read_partial_message(struct ceph_connection *con) | |||
1722 | 1749 | ||
1723 | ret = read_partial_message_bio(con, | 1750 | ret = read_partial_message_bio(con, |
1724 | &m->bio_iter, &m->bio_seg, | 1751 | &m->bio_iter, &m->bio_seg, |
1725 | data_len, datacrc); | 1752 | data_len, do_datacrc); |
1726 | if (ret <= 0) | 1753 | if (ret <= 0) |
1727 | return ret; | 1754 | return ret; |
1728 | #endif | 1755 | #endif |
@@ -1757,7 +1784,7 @@ static int read_partial_message(struct ceph_connection *con) | |||
1757 | m, con->in_middle_crc, m->footer.middle_crc); | 1784 | m, con->in_middle_crc, m->footer.middle_crc); |
1758 | return -EBADMSG; | 1785 | return -EBADMSG; |
1759 | } | 1786 | } |
1760 | if (datacrc && | 1787 | if (do_datacrc && |
1761 | (m->footer.flags & CEPH_MSG_FOOTER_NOCRC) == 0 && | 1788 | (m->footer.flags & CEPH_MSG_FOOTER_NOCRC) == 0 && |
1762 | con->in_data_crc != le32_to_cpu(m->footer.data_crc)) { | 1789 | con->in_data_crc != le32_to_cpu(m->footer.data_crc)) { |
1763 | pr_err("read_partial_message %p data crc %u != exp. %u\n", m, | 1790 | pr_err("read_partial_message %p data crc %u != exp. %u\n", m, |
@@ -1819,7 +1846,6 @@ more: | |||
1819 | 1846 | ||
1820 | /* open the socket first? */ | 1847 | /* open the socket first? */ |
1821 | if (con->sock == NULL) { | 1848 | if (con->sock == NULL) { |
1822 | prepare_write_banner(msgr, con); | ||
1823 | prepare_write_connect(msgr, con, 1); | 1849 | prepare_write_connect(msgr, con, 1); |
1824 | prepare_read_banner(con); | 1850 | prepare_read_banner(con); |
1825 | set_bit(CONNECTING, &con->state); | 1851 | set_bit(CONNECTING, &con->state); |
@@ -1829,11 +1855,9 @@ more: | |||
1829 | con->in_tag = CEPH_MSGR_TAG_READY; | 1855 | con->in_tag = CEPH_MSGR_TAG_READY; |
1830 | dout("try_write initiating connect on %p new state %lu\n", | 1856 | dout("try_write initiating connect on %p new state %lu\n", |
1831 | con, con->state); | 1857 | con, con->state); |
1832 | con->sock = ceph_tcp_connect(con); | 1858 | ret = ceph_tcp_connect(con); |
1833 | if (IS_ERR(con->sock)) { | 1859 | if (ret < 0) { |
1834 | con->sock = NULL; | ||
1835 | con->error_msg = "connect error"; | 1860 | con->error_msg = "connect error"; |
1836 | ret = -1; | ||
1837 | goto out; | 1861 | goto out; |
1838 | } | 1862 | } |
1839 | } | 1863 | } |
@@ -1953,8 +1977,9 @@ more: | |||
1953 | * | 1977 | * |
1954 | * FIXME: there must be a better way to do this! | 1978 | * FIXME: there must be a better way to do this! |
1955 | */ | 1979 | */ |
1956 | static char buf[1024]; | 1980 | static char buf[SKIP_BUF_SIZE]; |
1957 | int skip = min(1024, -con->in_base_pos); | 1981 | int skip = min((int) sizeof (buf), -con->in_base_pos); |
1982 | |||
1958 | dout("skipping %d / %d bytes\n", skip, -con->in_base_pos); | 1983 | dout("skipping %d / %d bytes\n", skip, -con->in_base_pos); |
1959 | ret = ceph_tcp_recvmsg(con->sock, buf, skip); | 1984 | ret = ceph_tcp_recvmsg(con->sock, buf, skip); |
1960 | if (ret <= 0) | 1985 | if (ret <= 0) |
@@ -2216,15 +2241,6 @@ struct ceph_messenger *ceph_messenger_create(struct ceph_entity_addr *myaddr, | |||
2216 | 2241 | ||
2217 | spin_lock_init(&msgr->global_seq_lock); | 2242 | spin_lock_init(&msgr->global_seq_lock); |
2218 | 2243 | ||
2219 | /* the zero page is needed if a request is "canceled" while the message | ||
2220 | * is being written over the socket */ | ||
2221 | msgr->zero_page = __page_cache_alloc(GFP_KERNEL | __GFP_ZERO); | ||
2222 | if (!msgr->zero_page) { | ||
2223 | kfree(msgr); | ||
2224 | return ERR_PTR(-ENOMEM); | ||
2225 | } | ||
2226 | kmap(msgr->zero_page); | ||
2227 | |||
2228 | if (myaddr) | 2244 | if (myaddr) |
2229 | msgr->inst.addr = *myaddr; | 2245 | msgr->inst.addr = *myaddr; |
2230 | 2246 | ||
@@ -2241,8 +2257,6 @@ EXPORT_SYMBOL(ceph_messenger_create); | |||
2241 | void ceph_messenger_destroy(struct ceph_messenger *msgr) | 2257 | void ceph_messenger_destroy(struct ceph_messenger *msgr) |
2242 | { | 2258 | { |
2243 | dout("destroy %p\n", msgr); | 2259 | dout("destroy %p\n", msgr); |
2244 | kunmap(msgr->zero_page); | ||
2245 | __free_page(msgr->zero_page); | ||
2246 | kfree(msgr); | 2260 | kfree(msgr); |
2247 | dout("destroyed messenger %p\n", msgr); | 2261 | dout("destroyed messenger %p\n", msgr); |
2248 | } | 2262 | } |
diff --git a/net/ceph/osdmap.c b/net/ceph/osdmap.c index fd863fe76934..29ad46ec9dcf 100644 --- a/net/ceph/osdmap.c +++ b/net/ceph/osdmap.c | |||
@@ -283,7 +283,8 @@ static struct crush_map *crush_decode(void *pbyval, void *end) | |||
283 | ceph_decode_32_safe(p, end, yes, bad); | 283 | ceph_decode_32_safe(p, end, yes, bad); |
284 | #if BITS_PER_LONG == 32 | 284 | #if BITS_PER_LONG == 32 |
285 | err = -EINVAL; | 285 | err = -EINVAL; |
286 | if (yes > ULONG_MAX / sizeof(struct crush_rule_step)) | 286 | if (yes > (ULONG_MAX - sizeof(*r)) |
287 | / sizeof(struct crush_rule_step)) | ||
287 | goto bad; | 288 | goto bad; |
288 | #endif | 289 | #endif |
289 | r = c->rules[i] = kmalloc(sizeof(*r) + | 290 | r = c->rules[i] = kmalloc(sizeof(*r) + |
diff --git a/net/compat.c b/net/compat.c index 64b4515a64e6..e055708b8ec9 100644 --- a/net/compat.c +++ b/net/compat.c | |||
@@ -219,8 +219,6 @@ Efault: | |||
219 | 219 | ||
220 | int put_cmsg_compat(struct msghdr *kmsg, int level, int type, int len, void *data) | 220 | int put_cmsg_compat(struct msghdr *kmsg, int level, int type, int len, void *data) |
221 | { | 221 | { |
222 | struct compat_timeval ctv; | ||
223 | struct compat_timespec cts[3]; | ||
224 | struct compat_cmsghdr __user *cm = (struct compat_cmsghdr __user *) kmsg->msg_control; | 222 | struct compat_cmsghdr __user *cm = (struct compat_cmsghdr __user *) kmsg->msg_control; |
225 | struct compat_cmsghdr cmhdr; | 223 | struct compat_cmsghdr cmhdr; |
226 | int cmlen; | 224 | int cmlen; |
@@ -230,24 +228,28 @@ int put_cmsg_compat(struct msghdr *kmsg, int level, int type, int len, void *dat | |||
230 | return 0; /* XXX: return error? check spec. */ | 228 | return 0; /* XXX: return error? check spec. */ |
231 | } | 229 | } |
232 | 230 | ||
233 | if (level == SOL_SOCKET && type == SCM_TIMESTAMP) { | 231 | if (!COMPAT_USE_64BIT_TIME) { |
234 | struct timeval *tv = (struct timeval *)data; | 232 | struct compat_timeval ctv; |
235 | ctv.tv_sec = tv->tv_sec; | 233 | struct compat_timespec cts[3]; |
236 | ctv.tv_usec = tv->tv_usec; | 234 | if (level == SOL_SOCKET && type == SCM_TIMESTAMP) { |
237 | data = &ctv; | 235 | struct timeval *tv = (struct timeval *)data; |
238 | len = sizeof(ctv); | 236 | ctv.tv_sec = tv->tv_sec; |
239 | } | 237 | ctv.tv_usec = tv->tv_usec; |
240 | if (level == SOL_SOCKET && | 238 | data = &ctv; |
241 | (type == SCM_TIMESTAMPNS || type == SCM_TIMESTAMPING)) { | 239 | len = sizeof(ctv); |
242 | int count = type == SCM_TIMESTAMPNS ? 1 : 3; | 240 | } |
243 | int i; | 241 | if (level == SOL_SOCKET && |
244 | struct timespec *ts = (struct timespec *)data; | 242 | (type == SCM_TIMESTAMPNS || type == SCM_TIMESTAMPING)) { |
245 | for (i = 0; i < count; i++) { | 243 | int count = type == SCM_TIMESTAMPNS ? 1 : 3; |
246 | cts[i].tv_sec = ts[i].tv_sec; | 244 | int i; |
247 | cts[i].tv_nsec = ts[i].tv_nsec; | 245 | struct timespec *ts = (struct timespec *)data; |
246 | for (i = 0; i < count; i++) { | ||
247 | cts[i].tv_sec = ts[i].tv_sec; | ||
248 | cts[i].tv_nsec = ts[i].tv_nsec; | ||
249 | } | ||
250 | data = &cts; | ||
251 | len = sizeof(cts[0]) * count; | ||
248 | } | 252 | } |
249 | data = &cts; | ||
250 | len = sizeof(cts[0]) * count; | ||
251 | } | 253 | } |
252 | 254 | ||
253 | cmlen = CMSG_COMPAT_LEN(len); | 255 | cmlen = CMSG_COMPAT_LEN(len); |
@@ -454,11 +456,15 @@ static int compat_sock_getsockopt(struct socket *sock, int level, int optname, | |||
454 | 456 | ||
455 | int compat_sock_get_timestamp(struct sock *sk, struct timeval __user *userstamp) | 457 | int compat_sock_get_timestamp(struct sock *sk, struct timeval __user *userstamp) |
456 | { | 458 | { |
457 | struct compat_timeval __user *ctv = | 459 | struct compat_timeval __user *ctv; |
458 | (struct compat_timeval __user *) userstamp; | 460 | int err; |
459 | int err = -ENOENT; | ||
460 | struct timeval tv; | 461 | struct timeval tv; |
461 | 462 | ||
463 | if (COMPAT_USE_64BIT_TIME) | ||
464 | return sock_get_timestamp(sk, userstamp); | ||
465 | |||
466 | ctv = (struct compat_timeval __user *) userstamp; | ||
467 | err = -ENOENT; | ||
462 | if (!sock_flag(sk, SOCK_TIMESTAMP)) | 468 | if (!sock_flag(sk, SOCK_TIMESTAMP)) |
463 | sock_enable_timestamp(sk, SOCK_TIMESTAMP); | 469 | sock_enable_timestamp(sk, SOCK_TIMESTAMP); |
464 | tv = ktime_to_timeval(sk->sk_stamp); | 470 | tv = ktime_to_timeval(sk->sk_stamp); |
@@ -478,11 +484,15 @@ EXPORT_SYMBOL(compat_sock_get_timestamp); | |||
478 | 484 | ||
479 | int compat_sock_get_timestampns(struct sock *sk, struct timespec __user *userstamp) | 485 | int compat_sock_get_timestampns(struct sock *sk, struct timespec __user *userstamp) |
480 | { | 486 | { |
481 | struct compat_timespec __user *ctv = | 487 | struct compat_timespec __user *ctv; |
482 | (struct compat_timespec __user *) userstamp; | 488 | int err; |
483 | int err = -ENOENT; | ||
484 | struct timespec ts; | 489 | struct timespec ts; |
485 | 490 | ||
491 | if (COMPAT_USE_64BIT_TIME) | ||
492 | return sock_get_timestampns (sk, userstamp); | ||
493 | |||
494 | ctv = (struct compat_timespec __user *) userstamp; | ||
495 | err = -ENOENT; | ||
486 | if (!sock_flag(sk, SOCK_TIMESTAMP)) | 496 | if (!sock_flag(sk, SOCK_TIMESTAMP)) |
487 | sock_enable_timestamp(sk, SOCK_TIMESTAMP); | 497 | sock_enable_timestamp(sk, SOCK_TIMESTAMP); |
488 | ts = ktime_to_timespec(sk->sk_stamp); | 498 | ts = ktime_to_timespec(sk->sk_stamp); |
@@ -767,6 +777,11 @@ asmlinkage long compat_sys_recvmmsg(int fd, struct compat_mmsghdr __user *mmsg, | |||
767 | int datagrams; | 777 | int datagrams; |
768 | struct timespec ktspec; | 778 | struct timespec ktspec; |
769 | 779 | ||
780 | if (COMPAT_USE_64BIT_TIME) | ||
781 | return __sys_recvmmsg(fd, (struct mmsghdr __user *)mmsg, vlen, | ||
782 | flags | MSG_CMSG_COMPAT, | ||
783 | (struct timespec *) timeout); | ||
784 | |||
770 | if (timeout == NULL) | 785 | if (timeout == NULL) |
771 | return __sys_recvmmsg(fd, (struct mmsghdr __user *)mmsg, vlen, | 786 | return __sys_recvmmsg(fd, (struct mmsghdr __user *)mmsg, vlen, |
772 | flags | MSG_CMSG_COMPAT, NULL); | 787 | flags | MSG_CMSG_COMPAT, NULL); |
diff --git a/net/core/datagram.c b/net/core/datagram.c index d3cf12f62c8f..e4fbfd6e2bd4 100644 --- a/net/core/datagram.c +++ b/net/core/datagram.c | |||
@@ -37,7 +37,6 @@ | |||
37 | #include <linux/types.h> | 37 | #include <linux/types.h> |
38 | #include <linux/kernel.h> | 38 | #include <linux/kernel.h> |
39 | #include <asm/uaccess.h> | 39 | #include <asm/uaccess.h> |
40 | #include <asm/system.h> | ||
41 | #include <linux/mm.h> | 40 | #include <linux/mm.h> |
42 | #include <linux/interrupt.h> | 41 | #include <linux/interrupt.h> |
43 | #include <linux/errno.h> | 42 | #include <linux/errno.h> |
diff --git a/net/core/dev.c b/net/core/dev.c index 452db7090d18..c25d453b2803 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -73,7 +73,6 @@ | |||
73 | */ | 73 | */ |
74 | 74 | ||
75 | #include <asm/uaccess.h> | 75 | #include <asm/uaccess.h> |
76 | #include <asm/system.h> | ||
77 | #include <linux/bitops.h> | 76 | #include <linux/bitops.h> |
78 | #include <linux/capability.h> | 77 | #include <linux/capability.h> |
79 | #include <linux/cpu.h> | 78 | #include <linux/cpu.h> |
@@ -1597,6 +1596,7 @@ int dev_forward_skb(struct net_device *dev, struct sk_buff *skb) | |||
1597 | kfree_skb(skb); | 1596 | kfree_skb(skb); |
1598 | return NET_RX_DROP; | 1597 | return NET_RX_DROP; |
1599 | } | 1598 | } |
1599 | skb->skb_iif = 0; | ||
1600 | skb_set_dev(skb, dev); | 1600 | skb_set_dev(skb, dev); |
1601 | skb->tstamp.tv64 = 0; | 1601 | skb->tstamp.tv64 = 0; |
1602 | skb->pkt_type = PACKET_HOST; | 1602 | skb->pkt_type = PACKET_HOST; |
@@ -4028,54 +4028,41 @@ static int dev_ifconf(struct net *net, char __user *arg) | |||
4028 | 4028 | ||
4029 | #ifdef CONFIG_PROC_FS | 4029 | #ifdef CONFIG_PROC_FS |
4030 | 4030 | ||
4031 | #define BUCKET_SPACE (32 - NETDEV_HASHBITS) | 4031 | #define BUCKET_SPACE (32 - NETDEV_HASHBITS - 1) |
4032 | |||
4033 | struct dev_iter_state { | ||
4034 | struct seq_net_private p; | ||
4035 | unsigned int pos; /* bucket << BUCKET_SPACE + offset */ | ||
4036 | }; | ||
4037 | 4032 | ||
4038 | #define get_bucket(x) ((x) >> BUCKET_SPACE) | 4033 | #define get_bucket(x) ((x) >> BUCKET_SPACE) |
4039 | #define get_offset(x) ((x) & ((1 << BUCKET_SPACE) - 1)) | 4034 | #define get_offset(x) ((x) & ((1 << BUCKET_SPACE) - 1)) |
4040 | #define set_bucket_offset(b, o) ((b) << BUCKET_SPACE | (o)) | 4035 | #define set_bucket_offset(b, o) ((b) << BUCKET_SPACE | (o)) |
4041 | 4036 | ||
4042 | static inline struct net_device *dev_from_same_bucket(struct seq_file *seq) | 4037 | static inline struct net_device *dev_from_same_bucket(struct seq_file *seq, loff_t *pos) |
4043 | { | 4038 | { |
4044 | struct dev_iter_state *state = seq->private; | ||
4045 | struct net *net = seq_file_net(seq); | 4039 | struct net *net = seq_file_net(seq); |
4046 | struct net_device *dev; | 4040 | struct net_device *dev; |
4047 | struct hlist_node *p; | 4041 | struct hlist_node *p; |
4048 | struct hlist_head *h; | 4042 | struct hlist_head *h; |
4049 | unsigned int count, bucket, offset; | 4043 | unsigned int count = 0, offset = get_offset(*pos); |
4050 | 4044 | ||
4051 | bucket = get_bucket(state->pos); | 4045 | h = &net->dev_name_head[get_bucket(*pos)]; |
4052 | offset = get_offset(state->pos); | ||
4053 | h = &net->dev_name_head[bucket]; | ||
4054 | count = 0; | ||
4055 | hlist_for_each_entry_rcu(dev, p, h, name_hlist) { | 4046 | hlist_for_each_entry_rcu(dev, p, h, name_hlist) { |
4056 | if (count++ == offset) { | 4047 | if (++count == offset) |
4057 | state->pos = set_bucket_offset(bucket, count); | ||
4058 | return dev; | 4048 | return dev; |
4059 | } | ||
4060 | } | 4049 | } |
4061 | 4050 | ||
4062 | return NULL; | 4051 | return NULL; |
4063 | } | 4052 | } |
4064 | 4053 | ||
4065 | static inline struct net_device *dev_from_new_bucket(struct seq_file *seq) | 4054 | static inline struct net_device *dev_from_bucket(struct seq_file *seq, loff_t *pos) |
4066 | { | 4055 | { |
4067 | struct dev_iter_state *state = seq->private; | ||
4068 | struct net_device *dev; | 4056 | struct net_device *dev; |
4069 | unsigned int bucket; | 4057 | unsigned int bucket; |
4070 | 4058 | ||
4071 | bucket = get_bucket(state->pos); | ||
4072 | do { | 4059 | do { |
4073 | dev = dev_from_same_bucket(seq); | 4060 | dev = dev_from_same_bucket(seq, pos); |
4074 | if (dev) | 4061 | if (dev) |
4075 | return dev; | 4062 | return dev; |
4076 | 4063 | ||
4077 | bucket++; | 4064 | bucket = get_bucket(*pos) + 1; |
4078 | state->pos = set_bucket_offset(bucket, 0); | 4065 | *pos = set_bucket_offset(bucket, 1); |
4079 | } while (bucket < NETDEV_HASHENTRIES); | 4066 | } while (bucket < NETDEV_HASHENTRIES); |
4080 | 4067 | ||
4081 | return NULL; | 4068 | return NULL; |
@@ -4088,33 +4075,20 @@ static inline struct net_device *dev_from_new_bucket(struct seq_file *seq) | |||
4088 | void *dev_seq_start(struct seq_file *seq, loff_t *pos) | 4075 | void *dev_seq_start(struct seq_file *seq, loff_t *pos) |
4089 | __acquires(RCU) | 4076 | __acquires(RCU) |
4090 | { | 4077 | { |
4091 | struct dev_iter_state *state = seq->private; | ||
4092 | |||
4093 | rcu_read_lock(); | 4078 | rcu_read_lock(); |
4094 | if (!*pos) | 4079 | if (!*pos) |
4095 | return SEQ_START_TOKEN; | 4080 | return SEQ_START_TOKEN; |
4096 | 4081 | ||
4097 | /* check for end of the hash */ | 4082 | if (get_bucket(*pos) >= NETDEV_HASHENTRIES) |
4098 | if (state->pos == 0 && *pos > 1) | ||
4099 | return NULL; | 4083 | return NULL; |
4100 | 4084 | ||
4101 | return dev_from_new_bucket(seq); | 4085 | return dev_from_bucket(seq, pos); |
4102 | } | 4086 | } |
4103 | 4087 | ||
4104 | void *dev_seq_next(struct seq_file *seq, void *v, loff_t *pos) | 4088 | void *dev_seq_next(struct seq_file *seq, void *v, loff_t *pos) |
4105 | { | 4089 | { |
4106 | struct net_device *dev; | ||
4107 | |||
4108 | ++*pos; | 4090 | ++*pos; |
4109 | 4091 | return dev_from_bucket(seq, pos); | |
4110 | if (v == SEQ_START_TOKEN) | ||
4111 | return dev_from_new_bucket(seq); | ||
4112 | |||
4113 | dev = dev_from_same_bucket(seq); | ||
4114 | if (dev) | ||
4115 | return dev; | ||
4116 | |||
4117 | return dev_from_new_bucket(seq); | ||
4118 | } | 4092 | } |
4119 | 4093 | ||
4120 | void dev_seq_stop(struct seq_file *seq, void *v) | 4094 | void dev_seq_stop(struct seq_file *seq, void *v) |
@@ -4213,13 +4187,7 @@ static const struct seq_operations dev_seq_ops = { | |||
4213 | static int dev_seq_open(struct inode *inode, struct file *file) | 4187 | static int dev_seq_open(struct inode *inode, struct file *file) |
4214 | { | 4188 | { |
4215 | return seq_open_net(inode, file, &dev_seq_ops, | 4189 | return seq_open_net(inode, file, &dev_seq_ops, |
4216 | sizeof(struct dev_iter_state)); | 4190 | sizeof(struct seq_net_private)); |
4217 | } | ||
4218 | |||
4219 | int dev_seq_open_ops(struct inode *inode, struct file *file, | ||
4220 | const struct seq_operations *ops) | ||
4221 | { | ||
4222 | return seq_open_net(inode, file, ops, sizeof(struct dev_iter_state)); | ||
4223 | } | 4191 | } |
4224 | 4192 | ||
4225 | static const struct file_operations dev_seq_fops = { | 4193 | static const struct file_operations dev_seq_fops = { |
diff --git a/net/core/dev_addr_lists.c b/net/core/dev_addr_lists.c index 29c07fef9228..626698f0db8b 100644 --- a/net/core/dev_addr_lists.c +++ b/net/core/dev_addr_lists.c | |||
@@ -696,7 +696,8 @@ static const struct seq_operations dev_mc_seq_ops = { | |||
696 | 696 | ||
697 | static int dev_mc_seq_open(struct inode *inode, struct file *file) | 697 | static int dev_mc_seq_open(struct inode *inode, struct file *file) |
698 | { | 698 | { |
699 | return dev_seq_open_ops(inode, file, &dev_mc_seq_ops); | 699 | return seq_open_net(inode, file, &dev_mc_seq_ops, |
700 | sizeof(struct seq_net_private)); | ||
700 | } | 701 | } |
701 | 702 | ||
702 | static const struct file_operations dev_mc_seq_fops = { | 703 | static const struct file_operations dev_mc_seq_fops = { |
diff --git a/net/core/filter.c b/net/core/filter.c index 5dea45279215..6f755cca4520 100644 --- a/net/core/filter.c +++ b/net/core/filter.c | |||
@@ -33,15 +33,17 @@ | |||
33 | #include <net/sock.h> | 33 | #include <net/sock.h> |
34 | #include <linux/errno.h> | 34 | #include <linux/errno.h> |
35 | #include <linux/timer.h> | 35 | #include <linux/timer.h> |
36 | #include <asm/system.h> | ||
37 | #include <asm/uaccess.h> | 36 | #include <asm/uaccess.h> |
38 | #include <asm/unaligned.h> | 37 | #include <asm/unaligned.h> |
39 | #include <linux/filter.h> | 38 | #include <linux/filter.h> |
40 | #include <linux/reciprocal_div.h> | 39 | #include <linux/reciprocal_div.h> |
41 | #include <linux/ratelimit.h> | 40 | #include <linux/ratelimit.h> |
42 | 41 | ||
43 | /* No hurry in this branch */ | 42 | /* No hurry in this branch |
44 | static void *__load_pointer(const struct sk_buff *skb, int k, unsigned int size) | 43 | * |
44 | * Exported for the bpf jit load helper. | ||
45 | */ | ||
46 | void *bpf_internal_load_pointer_neg_helper(const struct sk_buff *skb, int k, unsigned int size) | ||
45 | { | 47 | { |
46 | u8 *ptr = NULL; | 48 | u8 *ptr = NULL; |
47 | 49 | ||
@@ -60,7 +62,7 @@ static inline void *load_pointer(const struct sk_buff *skb, int k, | |||
60 | { | 62 | { |
61 | if (k >= 0) | 63 | if (k >= 0) |
62 | return skb_header_pointer(skb, k, size, buffer); | 64 | return skb_header_pointer(skb, k, size, buffer); |
63 | return __load_pointer(skb, k, size); | 65 | return bpf_internal_load_pointer_neg_helper(skb, k, size); |
64 | } | 66 | } |
65 | 67 | ||
66 | /** | 68 | /** |
diff --git a/net/core/gen_estimator.c b/net/core/gen_estimator.c index 43b03dd71e85..d9d198aa9fed 100644 --- a/net/core/gen_estimator.c +++ b/net/core/gen_estimator.c | |||
@@ -14,7 +14,6 @@ | |||
14 | */ | 14 | */ |
15 | 15 | ||
16 | #include <asm/uaccess.h> | 16 | #include <asm/uaccess.h> |
17 | #include <asm/system.h> | ||
18 | #include <linux/bitops.h> | 17 | #include <linux/bitops.h> |
19 | #include <linux/module.h> | 18 | #include <linux/module.h> |
20 | #include <linux/types.h> | 19 | #include <linux/types.h> |
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 1a63c6efd2ea..90430b776ece 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
@@ -38,7 +38,6 @@ | |||
38 | #include <linux/pci.h> | 38 | #include <linux/pci.h> |
39 | 39 | ||
40 | #include <asm/uaccess.h> | 40 | #include <asm/uaccess.h> |
41 | #include <asm/system.h> | ||
42 | 41 | ||
43 | #include <linux/inet.h> | 42 | #include <linux/inet.h> |
44 | #include <linux/netdevice.h> | 43 | #include <linux/netdevice.h> |
diff --git a/net/core/scm.c b/net/core/scm.c index ff52ad0a5150..611c5efd4cb0 100644 --- a/net/core/scm.c +++ b/net/core/scm.c | |||
@@ -28,7 +28,6 @@ | |||
28 | #include <linux/nsproxy.h> | 28 | #include <linux/nsproxy.h> |
29 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
30 | 30 | ||
31 | #include <asm/system.h> | ||
32 | #include <asm/uaccess.h> | 31 | #include <asm/uaccess.h> |
33 | 32 | ||
34 | #include <net/protocol.h> | 33 | #include <net/protocol.h> |
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 6eb656acdfe5..baf8d281152c 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
@@ -66,7 +66,6 @@ | |||
66 | #include <net/xfrm.h> | 66 | #include <net/xfrm.h> |
67 | 67 | ||
68 | #include <asm/uaccess.h> | 68 | #include <asm/uaccess.h> |
69 | #include <asm/system.h> | ||
70 | #include <trace/events/skb.h> | 69 | #include <trace/events/skb.h> |
71 | 70 | ||
72 | #include "kmap_skb.h" | 71 | #include "kmap_skb.h" |
@@ -321,12 +320,12 @@ struct sk_buff *__netdev_alloc_skb(struct net_device *dev, | |||
321 | EXPORT_SYMBOL(__netdev_alloc_skb); | 320 | EXPORT_SYMBOL(__netdev_alloc_skb); |
322 | 321 | ||
323 | void skb_add_rx_frag(struct sk_buff *skb, int i, struct page *page, int off, | 322 | void skb_add_rx_frag(struct sk_buff *skb, int i, struct page *page, int off, |
324 | int size) | 323 | int size, unsigned int truesize) |
325 | { | 324 | { |
326 | skb_fill_page_desc(skb, i, page, off, size); | 325 | skb_fill_page_desc(skb, i, page, off, size); |
327 | skb->len += size; | 326 | skb->len += size; |
328 | skb->data_len += size; | 327 | skb->data_len += size; |
329 | skb->truesize += size; | 328 | skb->truesize += truesize; |
330 | } | 329 | } |
331 | EXPORT_SYMBOL(skb_add_rx_frag); | 330 | EXPORT_SYMBOL(skb_add_rx_frag); |
332 | 331 | ||
@@ -3162,6 +3161,8 @@ static void sock_rmem_free(struct sk_buff *skb) | |||
3162 | */ | 3161 | */ |
3163 | int sock_queue_err_skb(struct sock *sk, struct sk_buff *skb) | 3162 | int sock_queue_err_skb(struct sock *sk, struct sk_buff *skb) |
3164 | { | 3163 | { |
3164 | int len = skb->len; | ||
3165 | |||
3165 | if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >= | 3166 | if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >= |
3166 | (unsigned)sk->sk_rcvbuf) | 3167 | (unsigned)sk->sk_rcvbuf) |
3167 | return -ENOMEM; | 3168 | return -ENOMEM; |
@@ -3176,7 +3177,7 @@ int sock_queue_err_skb(struct sock *sk, struct sk_buff *skb) | |||
3176 | 3177 | ||
3177 | skb_queue_tail(&sk->sk_error_queue, skb); | 3178 | skb_queue_tail(&sk->sk_error_queue, skb); |
3178 | if (!sock_flag(sk, SOCK_DEAD)) | 3179 | if (!sock_flag(sk, SOCK_DEAD)) |
3179 | sk->sk_data_ready(sk, skb->len); | 3180 | sk->sk_data_ready(sk, len); |
3180 | return 0; | 3181 | return 0; |
3181 | } | 3182 | } |
3182 | EXPORT_SYMBOL(sock_queue_err_skb); | 3183 | EXPORT_SYMBOL(sock_queue_err_skb); |
diff --git a/net/core/sock.c b/net/core/sock.c index 9be6d0d6c533..b2e14c07d920 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
@@ -115,7 +115,6 @@ | |||
115 | #include <linux/memcontrol.h> | 115 | #include <linux/memcontrol.h> |
116 | 116 | ||
117 | #include <asm/uaccess.h> | 117 | #include <asm/uaccess.h> |
118 | #include <asm/system.h> | ||
119 | 118 | ||
120 | #include <linux/netdevice.h> | 119 | #include <linux/netdevice.h> |
121 | #include <net/protocol.h> | 120 | #include <net/protocol.h> |
diff --git a/net/core/utils.c b/net/core/utils.c index 386e263f6066..dc3c3faff2f4 100644 --- a/net/core/utils.c +++ b/net/core/utils.c | |||
@@ -30,7 +30,6 @@ | |||
30 | #include <net/net_ratelimit.h> | 30 | #include <net/net_ratelimit.h> |
31 | 31 | ||
32 | #include <asm/byteorder.h> | 32 | #include <asm/byteorder.h> |
33 | #include <asm/system.h> | ||
34 | #include <asm/uaccess.h> | 33 | #include <asm/uaccess.h> |
35 | 34 | ||
36 | int net_msg_warn __read_mostly = 1; | 35 | int net_msg_warn __read_mostly = 1; |
diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c index 19acd00a6382..4136987d94da 100644 --- a/net/decnet/af_decnet.c +++ b/net/decnet/af_decnet.c | |||
@@ -119,7 +119,6 @@ Version 0.0.6 2.1.110 07-aug-98 Eduardo Marcelo Serrat | |||
119 | #include <net/sock.h> | 119 | #include <net/sock.h> |
120 | #include <net/tcp_states.h> | 120 | #include <net/tcp_states.h> |
121 | #include <net/flow.h> | 121 | #include <net/flow.h> |
122 | #include <asm/system.h> | ||
123 | #include <asm/ioctls.h> | 122 | #include <asm/ioctls.h> |
124 | #include <linux/capability.h> | 123 | #include <linux/capability.h> |
125 | #include <linux/mm.h> | 124 | #include <linux/mm.h> |
diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c index 74d321a60e7b..c00e3077988c 100644 --- a/net/decnet/dn_dev.c +++ b/net/decnet/dn_dev.c | |||
@@ -42,7 +42,6 @@ | |||
42 | #include <linux/notifier.h> | 42 | #include <linux/notifier.h> |
43 | #include <linux/slab.h> | 43 | #include <linux/slab.h> |
44 | #include <asm/uaccess.h> | 44 | #include <asm/uaccess.h> |
45 | #include <asm/system.h> | ||
46 | #include <net/net_namespace.h> | 45 | #include <net/net_namespace.h> |
47 | #include <net/neighbour.h> | 46 | #include <net/neighbour.h> |
48 | #include <net/dst.h> | 47 | #include <net/dst.h> |
diff --git a/net/decnet/dn_nsp_in.c b/net/decnet/dn_nsp_in.c index 73fa268fe2e8..f6544b2c91b0 100644 --- a/net/decnet/dn_nsp_in.c +++ b/net/decnet/dn_nsp_in.c | |||
@@ -60,7 +60,6 @@ | |||
60 | #include <linux/slab.h> | 60 | #include <linux/slab.h> |
61 | #include <net/sock.h> | 61 | #include <net/sock.h> |
62 | #include <net/tcp_states.h> | 62 | #include <net/tcp_states.h> |
63 | #include <asm/system.h> | ||
64 | #include <linux/fcntl.h> | 63 | #include <linux/fcntl.h> |
65 | #include <linux/mm.h> | 64 | #include <linux/mm.h> |
66 | #include <linux/termios.h> | 65 | #include <linux/termios.h> |
diff --git a/net/decnet/dn_nsp_out.c b/net/decnet/dn_nsp_out.c index bd78836a81eb..e446e85e64a6 100644 --- a/net/decnet/dn_nsp_out.c +++ b/net/decnet/dn_nsp_out.c | |||
@@ -52,7 +52,6 @@ | |||
52 | #include <linux/route.h> | 52 | #include <linux/route.h> |
53 | #include <linux/slab.h> | 53 | #include <linux/slab.h> |
54 | #include <net/sock.h> | 54 | #include <net/sock.h> |
55 | #include <asm/system.h> | ||
56 | #include <linux/fcntl.h> | 55 | #include <linux/fcntl.h> |
57 | #include <linux/mm.h> | 56 | #include <linux/mm.h> |
58 | #include <linux/termios.h> | 57 | #include <linux/termios.h> |
diff --git a/net/econet/af_econet.c b/net/econet/af_econet.c index 7e717cb35ad1..71b5edcee401 100644 --- a/net/econet/af_econet.c +++ b/net/econet/af_econet.c | |||
@@ -47,7 +47,6 @@ | |||
47 | #include <linux/mutex.h> | 47 | #include <linux/mutex.h> |
48 | 48 | ||
49 | #include <linux/uaccess.h> | 49 | #include <linux/uaccess.h> |
50 | #include <asm/system.h> | ||
51 | 50 | ||
52 | static const struct proto_ops econet_ops; | 51 | static const struct proto_ops econet_ops; |
53 | static struct hlist_head econet_sklist; | 52 | static struct hlist_head econet_sklist; |
diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c index a93af86b8474..bf10a311cf1c 100644 --- a/net/ethernet/eth.c +++ b/net/ethernet/eth.c | |||
@@ -59,7 +59,6 @@ | |||
59 | #include <net/ip.h> | 59 | #include <net/ip.h> |
60 | #include <net/dsa.h> | 60 | #include <net/dsa.h> |
61 | #include <asm/uaccess.h> | 61 | #include <asm/uaccess.h> |
62 | #include <asm/system.h> | ||
63 | 62 | ||
64 | __setup("ether=", netdev_boot_setup); | 63 | __setup("ether=", netdev_boot_setup); |
65 | 64 | ||
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index fdf49fd44bb4..10e3751466b5 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c | |||
@@ -91,7 +91,6 @@ | |||
91 | #include <linux/slab.h> | 91 | #include <linux/slab.h> |
92 | 92 | ||
93 | #include <asm/uaccess.h> | 93 | #include <asm/uaccess.h> |
94 | #include <asm/system.h> | ||
95 | 94 | ||
96 | #include <linux/inet.h> | 95 | #include <linux/inet.h> |
97 | #include <linux/igmp.h> | 96 | #include <linux/igmp.h> |
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index 73f46d691abc..18d9b81ecb1a 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c | |||
@@ -113,7 +113,6 @@ | |||
113 | #include <net/ax25.h> | 113 | #include <net/ax25.h> |
114 | #include <net/netrom.h> | 114 | #include <net/netrom.h> |
115 | 115 | ||
116 | #include <asm/system.h> | ||
117 | #include <linux/uaccess.h> | 116 | #include <linux/uaccess.h> |
118 | 117 | ||
119 | #include <linux/netfilter_arp.h> | 118 | #include <linux/netfilter_arp.h> |
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index d4fad5c77447..6e447ff94dfa 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c | |||
@@ -27,7 +27,6 @@ | |||
27 | 27 | ||
28 | 28 | ||
29 | #include <asm/uaccess.h> | 29 | #include <asm/uaccess.h> |
30 | #include <asm/system.h> | ||
31 | #include <linux/bitops.h> | 30 | #include <linux/bitops.h> |
32 | #include <linux/capability.h> | 31 | #include <linux/capability.h> |
33 | #include <linux/module.h> | 32 | #include <linux/module.h> |
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index 76e72bacc217..cbe3a68507cf 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c | |||
@@ -15,7 +15,6 @@ | |||
15 | 15 | ||
16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
17 | #include <asm/uaccess.h> | 17 | #include <asm/uaccess.h> |
18 | #include <asm/system.h> | ||
19 | #include <linux/bitops.h> | 18 | #include <linux/bitops.h> |
20 | #include <linux/capability.h> | 19 | #include <linux/capability.h> |
21 | #include <linux/types.h> | 20 | #include <linux/types.h> |
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c index a8c5c1d6715b..5063fa38ac7b 100644 --- a/net/ipv4/fib_semantics.c +++ b/net/ipv4/fib_semantics.c | |||
@@ -14,7 +14,6 @@ | |||
14 | */ | 14 | */ |
15 | 15 | ||
16 | #include <asm/uaccess.h> | 16 | #include <asm/uaccess.h> |
17 | #include <asm/system.h> | ||
18 | #include <linux/bitops.h> | 17 | #include <linux/bitops.h> |
19 | #include <linux/types.h> | 18 | #include <linux/types.h> |
20 | #include <linux/kernel.h> | 19 | #include <linux/kernel.h> |
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index da9b9cb2282d..bce36f1a37b4 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c | |||
@@ -51,7 +51,6 @@ | |||
51 | #define VERSION "0.409" | 51 | #define VERSION "0.409" |
52 | 52 | ||
53 | #include <asm/uaccess.h> | 53 | #include <asm/uaccess.h> |
54 | #include <asm/system.h> | ||
55 | #include <linux/bitops.h> | 54 | #include <linux/bitops.h> |
56 | #include <linux/types.h> | 55 | #include <linux/types.h> |
57 | #include <linux/kernel.h> | 56 | #include <linux/kernel.h> |
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index 9664d353ccd8..2cb2bf845641 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c | |||
@@ -91,7 +91,6 @@ | |||
91 | #include <linux/errno.h> | 91 | #include <linux/errno.h> |
92 | #include <linux/timer.h> | 92 | #include <linux/timer.h> |
93 | #include <linux/init.h> | 93 | #include <linux/init.h> |
94 | #include <asm/system.h> | ||
95 | #include <asm/uaccess.h> | 94 | #include <asm/uaccess.h> |
96 | #include <net/checksum.h> | 95 | #include <net/checksum.h> |
97 | #include <net/xfrm.h> | 96 | #include <net/xfrm.h> |
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index 450e5d21ed2a..5dfecfd7d5e9 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c | |||
@@ -73,7 +73,6 @@ | |||
73 | #include <linux/module.h> | 73 | #include <linux/module.h> |
74 | #include <linux/slab.h> | 74 | #include <linux/slab.h> |
75 | #include <asm/uaccess.h> | 75 | #include <asm/uaccess.h> |
76 | #include <asm/system.h> | ||
77 | #include <linux/types.h> | 76 | #include <linux/types.h> |
78 | #include <linux/kernel.h> | 77 | #include <linux/kernel.h> |
79 | #include <linux/jiffies.h> | 78 | #include <linux/jiffies.h> |
diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c index f3f1108940f5..26eccc5bab1c 100644 --- a/net/ipv4/ip_input.c +++ b/net/ipv4/ip_input.c | |||
@@ -115,7 +115,6 @@ | |||
115 | 115 | ||
116 | #define pr_fmt(fmt) "IPv4: " fmt | 116 | #define pr_fmt(fmt) "IPv4: " fmt |
117 | 117 | ||
118 | #include <asm/system.h> | ||
119 | #include <linux/module.h> | 118 | #include <linux/module.h> |
120 | #include <linux/types.h> | 119 | #include <linux/types.h> |
121 | #include <linux/kernel.h> | 120 | #include <linux/kernel.h> |
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index ff302bde8890..4910176d24ed 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c | |||
@@ -43,7 +43,6 @@ | |||
43 | */ | 43 | */ |
44 | 44 | ||
45 | #include <asm/uaccess.h> | 45 | #include <asm/uaccess.h> |
46 | #include <asm/system.h> | ||
47 | #include <linux/module.h> | 46 | #include <linux/module.h> |
48 | #include <linux/types.h> | 47 | #include <linux/types.h> |
49 | #include <linux/kernel.h> | 48 | #include <linux/kernel.h> |
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 0518a4fb177b..960fbfc3e976 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c | |||
@@ -26,7 +26,6 @@ | |||
26 | * | 26 | * |
27 | */ | 27 | */ |
28 | 28 | ||
29 | #include <asm/system.h> | ||
30 | #include <asm/uaccess.h> | 29 | #include <asm/uaccess.h> |
31 | #include <linux/types.h> | 30 | #include <linux/types.h> |
32 | #include <linux/capability.h> | 31 | #include <linux/capability.h> |
diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c index ab6b36e6da15..50009c787bcd 100644 --- a/net/ipv4/ping.c +++ b/net/ipv4/ping.c | |||
@@ -20,7 +20,6 @@ | |||
20 | * | 20 | * |
21 | */ | 21 | */ |
22 | 22 | ||
23 | #include <asm/system.h> | ||
24 | #include <linux/uaccess.h> | 23 | #include <linux/uaccess.h> |
25 | #include <linux/types.h> | 24 | #include <linux/types.h> |
26 | #include <linux/fcntl.h> | 25 | #include <linux/fcntl.h> |
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 12ccf880eb88..167ea10b521a 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
@@ -66,7 +66,6 @@ | |||
66 | 66 | ||
67 | #include <linux/module.h> | 67 | #include <linux/module.h> |
68 | #include <asm/uaccess.h> | 68 | #include <asm/uaccess.h> |
69 | #include <asm/system.h> | ||
70 | #include <linux/bitops.h> | 69 | #include <linux/bitops.h> |
71 | #include <linux/types.h> | 70 | #include <linux/types.h> |
72 | #include <linux/kernel.h> | 71 | #include <linux/kernel.h> |
@@ -2042,7 +2041,7 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr, | |||
2042 | if (err < 0) | 2041 | if (err < 0) |
2043 | goto e_err; | 2042 | goto e_err; |
2044 | } | 2043 | } |
2045 | rth = rt_dst_alloc(init_net.loopback_dev, | 2044 | rth = rt_dst_alloc(dev_net(dev)->loopback_dev, |
2046 | IN_DEV_CONF_GET(in_dev, NOPOLICY), false); | 2045 | IN_DEV_CONF_GET(in_dev, NOPOLICY), false); |
2047 | if (!rth) | 2046 | if (!rth) |
2048 | goto e_nobufs; | 2047 | goto e_nobufs; |
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index cfd7edda0a8e..5d54ed30e821 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
@@ -860,7 +860,7 @@ wait_for_memory: | |||
860 | } | 860 | } |
861 | 861 | ||
862 | out: | 862 | out: |
863 | if (copied) | 863 | if (copied && !(flags & MSG_SENDPAGE_NOTLAST)) |
864 | tcp_push(sk, flags, mss_now, tp->nonagle); | 864 | tcp_push(sk, flags, mss_now, tp->nonagle); |
865 | return copied; | 865 | return copied; |
866 | 866 | ||
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index d6f5feeb3eaf..fe141052a1be 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
@@ -79,7 +79,6 @@ | |||
79 | 79 | ||
80 | #define pr_fmt(fmt) "UDP: " fmt | 80 | #define pr_fmt(fmt) "UDP: " fmt |
81 | 81 | ||
82 | #include <asm/system.h> | ||
83 | #include <asm/uaccess.h> | 82 | #include <asm/uaccess.h> |
84 | #include <asm/ioctls.h> | 83 | #include <asm/ioctls.h> |
85 | #include <linux/bootmem.h> | 84 | #include <linux/bootmem.h> |
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 5605f9dca87e..8ed1b930e75f 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c | |||
@@ -60,7 +60,6 @@ | |||
60 | #endif | 60 | #endif |
61 | 61 | ||
62 | #include <asm/uaccess.h> | 62 | #include <asm/uaccess.h> |
63 | #include <asm/system.h> | ||
64 | #include <linux/mroute6.h> | 63 | #include <linux/mroute6.h> |
65 | 64 | ||
66 | MODULE_AUTHOR("Cast of dozens"); | 65 | MODULE_AUTHOR("Cast of dozens"); |
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index af88934e4d79..27ac95a63429 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c | |||
@@ -66,7 +66,6 @@ | |||
66 | #include <net/inet_common.h> | 66 | #include <net/inet_common.h> |
67 | 67 | ||
68 | #include <asm/uaccess.h> | 68 | #include <asm/uaccess.h> |
69 | #include <asm/system.h> | ||
70 | 69 | ||
71 | /* | 70 | /* |
72 | * The ICMP socket(s). This is the most convenient way to flow control | 71 | * The ICMP socket(s). This is the most convenient way to flow control |
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index 5aa3981a3922..8110362e0af5 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c | |||
@@ -16,7 +16,6 @@ | |||
16 | * | 16 | * |
17 | */ | 17 | */ |
18 | 18 | ||
19 | #include <asm/system.h> | ||
20 | #include <asm/uaccess.h> | 19 | #include <asm/uaccess.h> |
21 | #include <linux/types.h> | 20 | #include <linux/types.h> |
22 | #include <linux/sched.h> | 21 | #include <linux/sched.h> |
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index 16c33e308121..b2869cab2092 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c | |||
@@ -2044,7 +2044,7 @@ static int ip6_mc_add_src(struct inet6_dev *idev, const struct in6_addr *pmca, | |||
2044 | if (!delta) | 2044 | if (!delta) |
2045 | pmc->mca_sfcount[sfmode]--; | 2045 | pmc->mca_sfcount[sfmode]--; |
2046 | for (j=0; j<i; j++) | 2046 | for (j=0; j<i; j++) |
2047 | (void) ip6_mc_del1_src(pmc, sfmode, &psfsrc[i]); | 2047 | ip6_mc_del1_src(pmc, sfmode, &psfsrc[j]); |
2048 | } else if (isexclude != (pmc->mca_sfcount[MCAST_EXCLUDE] != 0)) { | 2048 | } else if (isexclude != (pmc->mca_sfcount[MCAST_EXCLUDE] != 0)) { |
2049 | struct ip6_sf_list *psf; | 2049 | struct ip6_sf_list *psf; |
2050 | 2050 | ||
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 24c456e8aa1d..3992e26a6039 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -881,6 +881,16 @@ static struct rt6_info *ip6_pol_route_input(struct net *net, struct fib6_table * | |||
881 | return ip6_pol_route(net, table, fl6->flowi6_iif, fl6, flags); | 881 | return ip6_pol_route(net, table, fl6->flowi6_iif, fl6, flags); |
882 | } | 882 | } |
883 | 883 | ||
884 | static struct dst_entry *ip6_route_input_lookup(struct net *net, | ||
885 | struct net_device *dev, | ||
886 | struct flowi6 *fl6, int flags) | ||
887 | { | ||
888 | if (rt6_need_strict(&fl6->daddr) && dev->type != ARPHRD_PIMREG) | ||
889 | flags |= RT6_LOOKUP_F_IFACE; | ||
890 | |||
891 | return fib6_rule_lookup(net, fl6, flags, ip6_pol_route_input); | ||
892 | } | ||
893 | |||
884 | void ip6_route_input(struct sk_buff *skb) | 894 | void ip6_route_input(struct sk_buff *skb) |
885 | { | 895 | { |
886 | const struct ipv6hdr *iph = ipv6_hdr(skb); | 896 | const struct ipv6hdr *iph = ipv6_hdr(skb); |
@@ -895,10 +905,7 @@ void ip6_route_input(struct sk_buff *skb) | |||
895 | .flowi6_proto = iph->nexthdr, | 905 | .flowi6_proto = iph->nexthdr, |
896 | }; | 906 | }; |
897 | 907 | ||
898 | if (rt6_need_strict(&iph->daddr) && skb->dev->type != ARPHRD_PIMREG) | 908 | skb_dst_set(skb, ip6_route_input_lookup(net, skb->dev, &fl6, flags)); |
899 | flags |= RT6_LOOKUP_F_IFACE; | ||
900 | |||
901 | skb_dst_set(skb, fib6_rule_lookup(net, &fl6, flags, ip6_pol_route_input)); | ||
902 | } | 909 | } |
903 | 910 | ||
904 | static struct rt6_info *ip6_pol_route_output(struct net *net, struct fib6_table *table, | 911 | static struct rt6_info *ip6_pol_route_output(struct net *net, struct fib6_table *table, |
@@ -2474,8 +2481,12 @@ static int rt6_fill_node(struct net *net, | |||
2474 | 2481 | ||
2475 | rcu_read_lock(); | 2482 | rcu_read_lock(); |
2476 | n = dst_get_neighbour_noref(&rt->dst); | 2483 | n = dst_get_neighbour_noref(&rt->dst); |
2477 | if (n) | 2484 | if (n) { |
2478 | NLA_PUT(skb, RTA_GATEWAY, 16, &n->primary_key); | 2485 | if (nla_put(skb, RTA_GATEWAY, 16, &n->primary_key) < 0) { |
2486 | rcu_read_unlock(); | ||
2487 | goto nla_put_failure; | ||
2488 | } | ||
2489 | } | ||
2479 | rcu_read_unlock(); | 2490 | rcu_read_unlock(); |
2480 | 2491 | ||
2481 | if (rt->dst.dev) | 2492 | if (rt->dst.dev) |
@@ -2533,7 +2544,7 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void | |||
2533 | struct sk_buff *skb; | 2544 | struct sk_buff *skb; |
2534 | struct rtmsg *rtm; | 2545 | struct rtmsg *rtm; |
2535 | struct flowi6 fl6; | 2546 | struct flowi6 fl6; |
2536 | int err, iif = 0; | 2547 | int err, iif = 0, oif = 0; |
2537 | 2548 | ||
2538 | err = nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX, rtm_ipv6_policy); | 2549 | err = nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX, rtm_ipv6_policy); |
2539 | if (err < 0) | 2550 | if (err < 0) |
@@ -2560,15 +2571,29 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void | |||
2560 | iif = nla_get_u32(tb[RTA_IIF]); | 2571 | iif = nla_get_u32(tb[RTA_IIF]); |
2561 | 2572 | ||
2562 | if (tb[RTA_OIF]) | 2573 | if (tb[RTA_OIF]) |
2563 | fl6.flowi6_oif = nla_get_u32(tb[RTA_OIF]); | 2574 | oif = nla_get_u32(tb[RTA_OIF]); |
2564 | 2575 | ||
2565 | if (iif) { | 2576 | if (iif) { |
2566 | struct net_device *dev; | 2577 | struct net_device *dev; |
2578 | int flags = 0; | ||
2579 | |||
2567 | dev = __dev_get_by_index(net, iif); | 2580 | dev = __dev_get_by_index(net, iif); |
2568 | if (!dev) { | 2581 | if (!dev) { |
2569 | err = -ENODEV; | 2582 | err = -ENODEV; |
2570 | goto errout; | 2583 | goto errout; |
2571 | } | 2584 | } |
2585 | |||
2586 | fl6.flowi6_iif = iif; | ||
2587 | |||
2588 | if (!ipv6_addr_any(&fl6.saddr)) | ||
2589 | flags |= RT6_LOOKUP_F_HAS_SADDR; | ||
2590 | |||
2591 | rt = (struct rt6_info *)ip6_route_input_lookup(net, dev, &fl6, | ||
2592 | flags); | ||
2593 | } else { | ||
2594 | fl6.flowi6_oif = oif; | ||
2595 | |||
2596 | rt = (struct rt6_info *)ip6_route_output(net, NULL, &fl6); | ||
2572 | } | 2597 | } |
2573 | 2598 | ||
2574 | skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); | 2599 | skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); |
@@ -2583,7 +2608,6 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void | |||
2583 | skb_reset_mac_header(skb); | 2608 | skb_reset_mac_header(skb); |
2584 | skb_reserve(skb, MAX_HEADER + sizeof(struct ipv6hdr)); | 2609 | skb_reserve(skb, MAX_HEADER + sizeof(struct ipv6hdr)); |
2585 | 2610 | ||
2586 | rt = (struct rt6_info*) ip6_route_output(net, NULL, &fl6); | ||
2587 | skb_dst_set(skb, &rt->dst); | 2611 | skb_dst_set(skb, &rt->dst); |
2588 | 2612 | ||
2589 | err = rt6_fill_node(net, skb, rt, &fl6.daddr, &fl6.saddr, iif, | 2613 | err = rt6_fill_node(net, skb, rt, &fl6.daddr, &fl6.saddr, iif, |
diff --git a/net/irda/irlan/irlan_client.c b/net/irda/irlan/irlan_client.c index ba1a3fc39b5c..42cf1390ce9c 100644 --- a/net/irda/irlan/irlan_client.c +++ b/net/irda/irlan/irlan_client.c | |||
@@ -37,7 +37,6 @@ | |||
37 | #include <linux/bitops.h> | 37 | #include <linux/bitops.h> |
38 | #include <net/arp.h> | 38 | #include <net/arp.h> |
39 | 39 | ||
40 | #include <asm/system.h> | ||
41 | #include <asm/byteorder.h> | 40 | #include <asm/byteorder.h> |
42 | 41 | ||
43 | #include <net/irda/irda.h> | 42 | #include <net/irda/irda.h> |
diff --git a/net/irda/irlan/irlan_common.c b/net/irda/irlan/irlan_common.c index 579617cca125..7ac4d1becbfc 100644 --- a/net/irda/irlan/irlan_common.c +++ b/net/irda/irlan/irlan_common.c | |||
@@ -40,7 +40,6 @@ | |||
40 | #include <linux/moduleparam.h> | 40 | #include <linux/moduleparam.h> |
41 | #include <linux/bitops.h> | 41 | #include <linux/bitops.h> |
42 | 42 | ||
43 | #include <asm/system.h> | ||
44 | #include <asm/byteorder.h> | 43 | #include <asm/byteorder.h> |
45 | 44 | ||
46 | #include <net/irda/irda.h> | 45 | #include <net/irda/irda.h> |
diff --git a/net/irda/irlan/irlan_provider.c b/net/irda/irlan/irlan_provider.c index 8b61cf0d8a69..32dcaac70b0c 100644 --- a/net/irda/irlan/irlan_provider.c +++ b/net/irda/irlan/irlan_provider.c | |||
@@ -36,7 +36,6 @@ | |||
36 | #include <linux/bitops.h> | 36 | #include <linux/bitops.h> |
37 | #include <linux/slab.h> | 37 | #include <linux/slab.h> |
38 | 38 | ||
39 | #include <asm/system.h> | ||
40 | #include <asm/byteorder.h> | 39 | #include <asm/byteorder.h> |
41 | 40 | ||
42 | #include <net/irda/irda.h> | 41 | #include <net/irda/irda.h> |
diff --git a/net/irda/timer.c b/net/irda/timer.c index f418cb2ad49c..1d552b3946fc 100644 --- a/net/irda/timer.c +++ b/net/irda/timer.c | |||
@@ -24,7 +24,6 @@ | |||
24 | * | 24 | * |
25 | ********************************************************************/ | 25 | ********************************************************************/ |
26 | 26 | ||
27 | #include <asm/system.h> | ||
28 | #include <linux/delay.h> | 27 | #include <linux/delay.h> |
29 | 28 | ||
30 | #include <net/irda/timer.h> | 29 | #include <net/irda/timer.h> |
diff --git a/net/iucv/iucv.c b/net/iucv/iucv.c index 403be43b793d..3ad1f9db5f8b 100644 --- a/net/iucv/iucv.c +++ b/net/iucv/iucv.c | |||
@@ -1800,7 +1800,7 @@ static void iucv_work_fn(struct work_struct *work) | |||
1800 | * Handles external interrupts coming in from CP. | 1800 | * Handles external interrupts coming in from CP. |
1801 | * Places the interrupt buffer on a queue and schedules iucv_tasklet_fn(). | 1801 | * Places the interrupt buffer on a queue and schedules iucv_tasklet_fn(). |
1802 | */ | 1802 | */ |
1803 | static void iucv_external_interrupt(unsigned int ext_int_code, | 1803 | static void iucv_external_interrupt(struct ext_code ext_code, |
1804 | unsigned int param32, unsigned long param64) | 1804 | unsigned int param32, unsigned long param64) |
1805 | { | 1805 | { |
1806 | struct iucv_irq_data *p; | 1806 | struct iucv_irq_data *p; |
diff --git a/net/lapb/lapb_iface.c b/net/lapb/lapb_iface.c index 8d0324bac01c..ab3d35f23257 100644 --- a/net/lapb/lapb_iface.c +++ b/net/lapb/lapb_iface.c | |||
@@ -32,7 +32,6 @@ | |||
32 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
33 | #include <net/sock.h> | 33 | #include <net/sock.h> |
34 | #include <asm/uaccess.h> | 34 | #include <asm/uaccess.h> |
35 | #include <asm/system.h> | ||
36 | #include <linux/fcntl.h> | 35 | #include <linux/fcntl.h> |
37 | #include <linux/mm.h> | 36 | #include <linux/mm.h> |
38 | #include <linux/interrupt.h> | 37 | #include <linux/interrupt.h> |
diff --git a/net/lapb/lapb_in.c b/net/lapb/lapb_in.c index 2ec1af5c36cc..f4e3c1accab7 100644 --- a/net/lapb/lapb_in.c +++ b/net/lapb/lapb_in.c | |||
@@ -30,7 +30,6 @@ | |||
30 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
31 | #include <net/sock.h> | 31 | #include <net/sock.h> |
32 | #include <asm/uaccess.h> | 32 | #include <asm/uaccess.h> |
33 | #include <asm/system.h> | ||
34 | #include <linux/fcntl.h> | 33 | #include <linux/fcntl.h> |
35 | #include <linux/mm.h> | 34 | #include <linux/mm.h> |
36 | #include <linux/interrupt.h> | 35 | #include <linux/interrupt.h> |
diff --git a/net/lapb/lapb_out.c b/net/lapb/lapb_out.c index c75a79540f9f..baab2760f651 100644 --- a/net/lapb/lapb_out.c +++ b/net/lapb/lapb_out.c | |||
@@ -28,7 +28,6 @@ | |||
28 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
29 | #include <net/sock.h> | 29 | #include <net/sock.h> |
30 | #include <asm/uaccess.h> | 30 | #include <asm/uaccess.h> |
31 | #include <asm/system.h> | ||
32 | #include <linux/fcntl.h> | 31 | #include <linux/fcntl.h> |
33 | #include <linux/mm.h> | 32 | #include <linux/mm.h> |
34 | #include <linux/interrupt.h> | 33 | #include <linux/interrupt.h> |
diff --git a/net/lapb/lapb_subr.c b/net/lapb/lapb_subr.c index 43a2a7fb327b..066225b4e824 100644 --- a/net/lapb/lapb_subr.c +++ b/net/lapb/lapb_subr.c | |||
@@ -27,7 +27,6 @@ | |||
27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
28 | #include <net/sock.h> | 28 | #include <net/sock.h> |
29 | #include <asm/uaccess.h> | 29 | #include <asm/uaccess.h> |
30 | #include <asm/system.h> | ||
31 | #include <linux/fcntl.h> | 30 | #include <linux/fcntl.h> |
32 | #include <linux/mm.h> | 31 | #include <linux/mm.h> |
33 | #include <linux/interrupt.h> | 32 | #include <linux/interrupt.h> |
diff --git a/net/lapb/lapb_timer.c b/net/lapb/lapb_timer.c index af6d14b44e2e..f8cd641dfc82 100644 --- a/net/lapb/lapb_timer.c +++ b/net/lapb/lapb_timer.c | |||
@@ -28,7 +28,6 @@ | |||
28 | #include <linux/skbuff.h> | 28 | #include <linux/skbuff.h> |
29 | #include <net/sock.h> | 29 | #include <net/sock.h> |
30 | #include <asm/uaccess.h> | 30 | #include <asm/uaccess.h> |
31 | #include <asm/system.h> | ||
32 | #include <linux/fcntl.h> | 31 | #include <linux/fcntl.h> |
33 | #include <linux/mm.h> | 32 | #include <linux/mm.h> |
34 | #include <linux/interrupt.h> | 33 | #include <linux/interrupt.h> |
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index cc5b7a6e7e0b..778e5916d7c3 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c | |||
@@ -15,12 +15,6 @@ | |||
15 | #include "rate.h" | 15 | #include "rate.h" |
16 | #include "debugfs.h" | 16 | #include "debugfs.h" |
17 | 17 | ||
18 | int mac80211_open_file_generic(struct inode *inode, struct file *file) | ||
19 | { | ||
20 | file->private_data = inode->i_private; | ||
21 | return 0; | ||
22 | } | ||
23 | |||
24 | #define DEBUGFS_FORMAT_BUFFER_SIZE 100 | 18 | #define DEBUGFS_FORMAT_BUFFER_SIZE 100 |
25 | 19 | ||
26 | int mac80211_format_buffer(char __user *userbuf, size_t count, | 20 | int mac80211_format_buffer(char __user *userbuf, size_t count, |
@@ -50,7 +44,7 @@ static ssize_t name## _read(struct file *file, char __user *userbuf, \ | |||
50 | #define DEBUGFS_READONLY_FILE_OPS(name) \ | 44 | #define DEBUGFS_READONLY_FILE_OPS(name) \ |
51 | static const struct file_operations name## _ops = { \ | 45 | static const struct file_operations name## _ops = { \ |
52 | .read = name## _read, \ | 46 | .read = name## _read, \ |
53 | .open = mac80211_open_file_generic, \ | 47 | .open = simple_open, \ |
54 | .llseek = generic_file_llseek, \ | 48 | .llseek = generic_file_llseek, \ |
55 | }; | 49 | }; |
56 | 50 | ||
@@ -93,7 +87,7 @@ static ssize_t reset_write(struct file *file, const char __user *user_buf, | |||
93 | 87 | ||
94 | static const struct file_operations reset_ops = { | 88 | static const struct file_operations reset_ops = { |
95 | .write = reset_write, | 89 | .write = reset_write, |
96 | .open = mac80211_open_file_generic, | 90 | .open = simple_open, |
97 | .llseek = noop_llseek, | 91 | .llseek = noop_llseek, |
98 | }; | 92 | }; |
99 | 93 | ||
@@ -254,7 +248,7 @@ static ssize_t stats_ ##name## _read(struct file *file, \ | |||
254 | \ | 248 | \ |
255 | static const struct file_operations stats_ ##name## _ops = { \ | 249 | static const struct file_operations stats_ ##name## _ops = { \ |
256 | .read = stats_ ##name## _read, \ | 250 | .read = stats_ ##name## _read, \ |
257 | .open = mac80211_open_file_generic, \ | 251 | .open = simple_open, \ |
258 | .llseek = generic_file_llseek, \ | 252 | .llseek = generic_file_llseek, \ |
259 | }; | 253 | }; |
260 | 254 | ||
diff --git a/net/mac80211/debugfs.h b/net/mac80211/debugfs.h index 7c87529630f5..9be4e6d71d00 100644 --- a/net/mac80211/debugfs.h +++ b/net/mac80211/debugfs.h | |||
@@ -3,7 +3,6 @@ | |||
3 | 3 | ||
4 | #ifdef CONFIG_MAC80211_DEBUGFS | 4 | #ifdef CONFIG_MAC80211_DEBUGFS |
5 | extern void debugfs_hw_add(struct ieee80211_local *local); | 5 | extern void debugfs_hw_add(struct ieee80211_local *local); |
6 | extern int mac80211_open_file_generic(struct inode *inode, struct file *file); | ||
7 | extern int mac80211_format_buffer(char __user *userbuf, size_t count, | 6 | extern int mac80211_format_buffer(char __user *userbuf, size_t count, |
8 | loff_t *ppos, char *fmt, ...); | 7 | loff_t *ppos, char *fmt, ...); |
9 | #else | 8 | #else |
diff --git a/net/mac80211/debugfs_key.c b/net/mac80211/debugfs_key.c index 59edcd95a58d..7932767bb482 100644 --- a/net/mac80211/debugfs_key.c +++ b/net/mac80211/debugfs_key.c | |||
@@ -30,7 +30,7 @@ static ssize_t key_##name##_read(struct file *file, \ | |||
30 | #define KEY_OPS(name) \ | 30 | #define KEY_OPS(name) \ |
31 | static const struct file_operations key_ ##name## _ops = { \ | 31 | static const struct file_operations key_ ##name## _ops = { \ |
32 | .read = key_##name##_read, \ | 32 | .read = key_##name##_read, \ |
33 | .open = mac80211_open_file_generic, \ | 33 | .open = simple_open, \ |
34 | .llseek = generic_file_llseek, \ | 34 | .llseek = generic_file_llseek, \ |
35 | } | 35 | } |
36 | 36 | ||
@@ -45,7 +45,7 @@ static const struct file_operations key_ ##name## _ops = { \ | |||
45 | #define KEY_CONF_OPS(name) \ | 45 | #define KEY_CONF_OPS(name) \ |
46 | static const struct file_operations key_ ##name## _ops = { \ | 46 | static const struct file_operations key_ ##name## _ops = { \ |
47 | .read = key_conf_##name##_read, \ | 47 | .read = key_conf_##name##_read, \ |
48 | .open = mac80211_open_file_generic, \ | 48 | .open = simple_open, \ |
49 | .llseek = generic_file_llseek, \ | 49 | .llseek = generic_file_llseek, \ |
50 | } | 50 | } |
51 | 51 | ||
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index a32eeda04aa3..30f99c344847 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c | |||
@@ -135,7 +135,7 @@ static ssize_t ieee80211_if_read_##name(struct file *file, \ | |||
135 | static const struct file_operations name##_ops = { \ | 135 | static const struct file_operations name##_ops = { \ |
136 | .read = ieee80211_if_read_##name, \ | 136 | .read = ieee80211_if_read_##name, \ |
137 | .write = (_write), \ | 137 | .write = (_write), \ |
138 | .open = mac80211_open_file_generic, \ | 138 | .open = simple_open, \ |
139 | .llseek = generic_file_llseek, \ | 139 | .llseek = generic_file_llseek, \ |
140 | } | 140 | } |
141 | 141 | ||
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index 6d45804d09bc..832b2da5e4cd 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c | |||
@@ -33,7 +33,7 @@ static ssize_t sta_ ##name## _read(struct file *file, \ | |||
33 | #define STA_OPS(name) \ | 33 | #define STA_OPS(name) \ |
34 | static const struct file_operations sta_ ##name## _ops = { \ | 34 | static const struct file_operations sta_ ##name## _ops = { \ |
35 | .read = sta_##name##_read, \ | 35 | .read = sta_##name##_read, \ |
36 | .open = mac80211_open_file_generic, \ | 36 | .open = simple_open, \ |
37 | .llseek = generic_file_llseek, \ | 37 | .llseek = generic_file_llseek, \ |
38 | } | 38 | } |
39 | 39 | ||
@@ -41,7 +41,7 @@ static const struct file_operations sta_ ##name## _ops = { \ | |||
41 | static const struct file_operations sta_ ##name## _ops = { \ | 41 | static const struct file_operations sta_ ##name## _ops = { \ |
42 | .read = sta_##name##_read, \ | 42 | .read = sta_##name##_read, \ |
43 | .write = sta_##name##_write, \ | 43 | .write = sta_##name##_write, \ |
44 | .open = mac80211_open_file_generic, \ | 44 | .open = simple_open, \ |
45 | .llseek = generic_file_llseek, \ | 45 | .llseek = generic_file_llseek, \ |
46 | } | 46 | } |
47 | 47 | ||
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 33fd8d9f714e..cef7c29214a8 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -457,8 +457,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
457 | * fall back to HT20 if we don't use or use | 457 | * fall back to HT20 if we don't use or use |
458 | * the other extension channel | 458 | * the other extension channel |
459 | */ | 459 | */ |
460 | if ((channel_type == NL80211_CHAN_HT40MINUS || | 460 | if (!(channel_type == NL80211_CHAN_HT40MINUS || |
461 | channel_type == NL80211_CHAN_HT40PLUS) && | 461 | channel_type == NL80211_CHAN_HT40PLUS) || |
462 | channel_type != sdata->u.ibss.channel_type) | 462 | channel_type != sdata->u.ibss.channel_type) |
463 | sta_ht_cap_new.cap &= | 463 | sta_ht_cap_new.cap &= |
464 | ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; | 464 | ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index d9798a307f20..db8fae51714c 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -1210,7 +1210,7 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | |||
1210 | struct sk_buff *skb); | 1210 | struct sk_buff *skb); |
1211 | void ieee80211_sta_reset_beacon_monitor(struct ieee80211_sub_if_data *sdata); | 1211 | void ieee80211_sta_reset_beacon_monitor(struct ieee80211_sub_if_data *sdata); |
1212 | void ieee80211_sta_reset_conn_monitor(struct ieee80211_sub_if_data *sdata); | 1212 | void ieee80211_sta_reset_conn_monitor(struct ieee80211_sub_if_data *sdata); |
1213 | void ieee80211_mgd_teardown(struct ieee80211_sub_if_data *sdata); | 1213 | void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata); |
1214 | 1214 | ||
1215 | /* IBSS code */ | 1215 | /* IBSS code */ |
1216 | void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local); | 1216 | void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local); |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 401c01f0731e..c20051b7ffcd 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -486,6 +486,8 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
486 | /* free all potentially still buffered bcast frames */ | 486 | /* free all potentially still buffered bcast frames */ |
487 | local->total_ps_buffered -= skb_queue_len(&sdata->u.ap.ps_bc_buf); | 487 | local->total_ps_buffered -= skb_queue_len(&sdata->u.ap.ps_bc_buf); |
488 | skb_queue_purge(&sdata->u.ap.ps_bc_buf); | 488 | skb_queue_purge(&sdata->u.ap.ps_bc_buf); |
489 | } else if (sdata->vif.type == NL80211_IFTYPE_STATION) { | ||
490 | ieee80211_mgd_stop(sdata); | ||
489 | } | 491 | } |
490 | 492 | ||
491 | if (going_down) | 493 | if (going_down) |
@@ -644,8 +646,6 @@ static void ieee80211_teardown_sdata(struct net_device *dev) | |||
644 | 646 | ||
645 | if (ieee80211_vif_is_mesh(&sdata->vif)) | 647 | if (ieee80211_vif_is_mesh(&sdata->vif)) |
646 | mesh_rmc_free(sdata); | 648 | mesh_rmc_free(sdata); |
647 | else if (sdata->vif.type == NL80211_IFTYPE_STATION) | ||
648 | ieee80211_mgd_teardown(sdata); | ||
649 | 649 | ||
650 | flushed = sta_info_flush(local, sdata); | 650 | flushed = sta_info_flush(local, sdata); |
651 | WARN_ON(flushed); | 651 | WARN_ON(flushed); |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 576fb25456dd..20c680bfc3ae 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -3387,8 +3387,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
3387 | */ | 3387 | */ |
3388 | printk(KERN_DEBUG "%s: waiting for beacon from %pM\n", | 3388 | printk(KERN_DEBUG "%s: waiting for beacon from %pM\n", |
3389 | sdata->name, ifmgd->bssid); | 3389 | sdata->name, ifmgd->bssid); |
3390 | assoc_data->timeout = jiffies + | 3390 | assoc_data->timeout = TU_TO_EXP_TIME(req->bss->beacon_interval); |
3391 | TU_TO_EXP_TIME(req->bss->beacon_interval); | ||
3392 | } else { | 3391 | } else { |
3393 | assoc_data->have_beacon = true; | 3392 | assoc_data->have_beacon = true; |
3394 | assoc_data->sent_assoc = false; | 3393 | assoc_data->sent_assoc = false; |
@@ -3498,7 +3497,7 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata, | |||
3498 | return 0; | 3497 | return 0; |
3499 | } | 3498 | } |
3500 | 3499 | ||
3501 | void ieee80211_mgd_teardown(struct ieee80211_sub_if_data *sdata) | 3500 | void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata) |
3502 | { | 3501 | { |
3503 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 3502 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
3504 | 3503 | ||
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c index b4f7600a3e36..3313c117b322 100644 --- a/net/mac80211/rate.c +++ b/net/mac80211/rate.c | |||
@@ -145,7 +145,7 @@ static ssize_t rcname_read(struct file *file, char __user *userbuf, | |||
145 | 145 | ||
146 | static const struct file_operations rcname_ops = { | 146 | static const struct file_operations rcname_ops = { |
147 | .read = rcname_read, | 147 | .read = rcname_read, |
148 | .open = mac80211_open_file_generic, | 148 | .open = simple_open, |
149 | .llseek = default_llseek, | 149 | .llseek = default_llseek, |
150 | }; | 150 | }; |
151 | #endif | 151 | #endif |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index bcfe8c77c839..d64e285400aa 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -103,7 +103,7 @@ static void | |||
103 | ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | 103 | ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, |
104 | struct sk_buff *skb, | 104 | struct sk_buff *skb, |
105 | struct ieee80211_rate *rate, | 105 | struct ieee80211_rate *rate, |
106 | int rtap_len) | 106 | int rtap_len, bool has_fcs) |
107 | { | 107 | { |
108 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); | 108 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); |
109 | struct ieee80211_radiotap_header *rthdr; | 109 | struct ieee80211_radiotap_header *rthdr; |
@@ -134,7 +134,7 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
134 | } | 134 | } |
135 | 135 | ||
136 | /* IEEE80211_RADIOTAP_FLAGS */ | 136 | /* IEEE80211_RADIOTAP_FLAGS */ |
137 | if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) | 137 | if (has_fcs && (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS)) |
138 | *pos |= IEEE80211_RADIOTAP_F_FCS; | 138 | *pos |= IEEE80211_RADIOTAP_F_FCS; |
139 | if (status->flag & (RX_FLAG_FAILED_FCS_CRC | RX_FLAG_FAILED_PLCP_CRC)) | 139 | if (status->flag & (RX_FLAG_FAILED_FCS_CRC | RX_FLAG_FAILED_PLCP_CRC)) |
140 | *pos |= IEEE80211_RADIOTAP_F_BADFCS; | 140 | *pos |= IEEE80211_RADIOTAP_F_BADFCS; |
@@ -294,7 +294,8 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb, | |||
294 | } | 294 | } |
295 | 295 | ||
296 | /* prepend radiotap information */ | 296 | /* prepend radiotap information */ |
297 | ieee80211_add_rx_radiotap_header(local, skb, rate, needed_headroom); | 297 | ieee80211_add_rx_radiotap_header(local, skb, rate, needed_headroom, |
298 | true); | ||
298 | 299 | ||
299 | skb_reset_mac_header(skb); | 300 | skb_reset_mac_header(skb); |
300 | skb->ip_summed = CHECKSUM_UNNECESSARY; | 301 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
@@ -2571,7 +2572,8 @@ static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx, | |||
2571 | goto out_free_skb; | 2572 | goto out_free_skb; |
2572 | 2573 | ||
2573 | /* prepend radiotap information */ | 2574 | /* prepend radiotap information */ |
2574 | ieee80211_add_rx_radiotap_header(local, skb, rate, needed_headroom); | 2575 | ieee80211_add_rx_radiotap_header(local, skb, rate, needed_headroom, |
2576 | false); | ||
2575 | 2577 | ||
2576 | skb_set_mac_header(skb, 0); | 2578 | skb_set_mac_header(skb, 0); |
2577 | skb->ip_summed = CHECKSUM_UNNECESSARY; | 2579 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 33cd16901378..c70e17677135 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -370,7 +370,7 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local) | |||
370 | */ | 370 | */ |
371 | drv_sw_scan_start(local); | 371 | drv_sw_scan_start(local); |
372 | 372 | ||
373 | local->leave_oper_channel_time = 0; | 373 | local->leave_oper_channel_time = jiffies; |
374 | local->next_scan_state = SCAN_DECISION; | 374 | local->next_scan_state = SCAN_DECISION; |
375 | local->scan_channel_idx = 0; | 375 | local->scan_channel_idx = 0; |
376 | 376 | ||
diff --git a/net/netfilter/ipvs/ip_vs_app.c b/net/netfilter/ipvs/ip_vs_app.c index fe6cb4304d72..52856178c9d7 100644 --- a/net/netfilter/ipvs/ip_vs_app.c +++ b/net/netfilter/ipvs/ip_vs_app.c | |||
@@ -31,7 +31,6 @@ | |||
31 | #include <net/net_namespace.h> | 31 | #include <net/net_namespace.h> |
32 | #include <net/protocol.h> | 32 | #include <net/protocol.h> |
33 | #include <net/tcp.h> | 33 | #include <net/tcp.h> |
34 | #include <asm/system.h> | ||
35 | #include <linux/stat.h> | 34 | #include <linux/stat.h> |
36 | #include <linux/proc_fs.h> | 35 | #include <linux/proc_fs.h> |
37 | #include <linux/seq_file.h> | 36 | #include <linux/seq_file.h> |
diff --git a/net/netfilter/ipvs/ip_vs_proto.c b/net/netfilter/ipvs/ip_vs_proto.c index 85312939695f..f843a8833250 100644 --- a/net/netfilter/ipvs/ip_vs_proto.c +++ b/net/netfilter/ipvs/ip_vs_proto.c | |||
@@ -25,7 +25,6 @@ | |||
25 | #include <net/protocol.h> | 25 | #include <net/protocol.h> |
26 | #include <net/tcp.h> | 26 | #include <net/tcp.h> |
27 | #include <net/udp.h> | 27 | #include <net/udp.h> |
28 | #include <asm/system.h> | ||
29 | #include <linux/stat.h> | 28 | #include <linux/stat.h> |
30 | #include <linux/proc_fs.h> | 29 | #include <linux/proc_fs.h> |
31 | 30 | ||
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 7b48035826ee..3cc4487ac349 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c | |||
@@ -735,6 +735,7 @@ __nf_conntrack_alloc(struct net *net, u16 zone, | |||
735 | 735 | ||
736 | #ifdef CONFIG_NF_CONNTRACK_ZONES | 736 | #ifdef CONFIG_NF_CONNTRACK_ZONES |
737 | out_free: | 737 | out_free: |
738 | atomic_dec(&net->ct.count); | ||
738 | kmem_cache_free(net->ct.nf_conntrack_cachep, ct); | 739 | kmem_cache_free(net->ct.nf_conntrack_cachep, ct); |
739 | return ERR_PTR(-ENOMEM); | 740 | return ERR_PTR(-ENOMEM); |
740 | #endif | 741 | #endif |
@@ -768,8 +769,7 @@ init_conntrack(struct net *net, struct nf_conn *tmpl, | |||
768 | struct nf_conntrack_l3proto *l3proto, | 769 | struct nf_conntrack_l3proto *l3proto, |
769 | struct nf_conntrack_l4proto *l4proto, | 770 | struct nf_conntrack_l4proto *l4proto, |
770 | struct sk_buff *skb, | 771 | struct sk_buff *skb, |
771 | unsigned int dataoff, u32 hash, | 772 | unsigned int dataoff, u32 hash) |
772 | unsigned int *timeouts) | ||
773 | { | 773 | { |
774 | struct nf_conn *ct; | 774 | struct nf_conn *ct; |
775 | struct nf_conn_help *help; | 775 | struct nf_conn_help *help; |
@@ -777,6 +777,8 @@ init_conntrack(struct net *net, struct nf_conn *tmpl, | |||
777 | struct nf_conntrack_ecache *ecache; | 777 | struct nf_conntrack_ecache *ecache; |
778 | struct nf_conntrack_expect *exp; | 778 | struct nf_conntrack_expect *exp; |
779 | u16 zone = tmpl ? nf_ct_zone(tmpl) : NF_CT_DEFAULT_ZONE; | 779 | u16 zone = tmpl ? nf_ct_zone(tmpl) : NF_CT_DEFAULT_ZONE; |
780 | struct nf_conn_timeout *timeout_ext; | ||
781 | unsigned int *timeouts; | ||
780 | 782 | ||
781 | if (!nf_ct_invert_tuple(&repl_tuple, tuple, l3proto, l4proto)) { | 783 | if (!nf_ct_invert_tuple(&repl_tuple, tuple, l3proto, l4proto)) { |
782 | pr_debug("Can't invert tuple.\n"); | 784 | pr_debug("Can't invert tuple.\n"); |
@@ -788,12 +790,21 @@ init_conntrack(struct net *net, struct nf_conn *tmpl, | |||
788 | if (IS_ERR(ct)) | 790 | if (IS_ERR(ct)) |
789 | return (struct nf_conntrack_tuple_hash *)ct; | 791 | return (struct nf_conntrack_tuple_hash *)ct; |
790 | 792 | ||
793 | timeout_ext = tmpl ? nf_ct_timeout_find(tmpl) : NULL; | ||
794 | if (timeout_ext) | ||
795 | timeouts = NF_CT_TIMEOUT_EXT_DATA(timeout_ext); | ||
796 | else | ||
797 | timeouts = l4proto->get_timeouts(net); | ||
798 | |||
791 | if (!l4proto->new(ct, skb, dataoff, timeouts)) { | 799 | if (!l4proto->new(ct, skb, dataoff, timeouts)) { |
792 | nf_conntrack_free(ct); | 800 | nf_conntrack_free(ct); |
793 | pr_debug("init conntrack: can't track with proto module\n"); | 801 | pr_debug("init conntrack: can't track with proto module\n"); |
794 | return NULL; | 802 | return NULL; |
795 | } | 803 | } |
796 | 804 | ||
805 | if (timeout_ext) | ||
806 | nf_ct_timeout_ext_add(ct, timeout_ext->timeout, GFP_ATOMIC); | ||
807 | |||
797 | nf_ct_acct_ext_add(ct, GFP_ATOMIC); | 808 | nf_ct_acct_ext_add(ct, GFP_ATOMIC); |
798 | nf_ct_tstamp_ext_add(ct, GFP_ATOMIC); | 809 | nf_ct_tstamp_ext_add(ct, GFP_ATOMIC); |
799 | 810 | ||
@@ -854,8 +865,7 @@ resolve_normal_ct(struct net *net, struct nf_conn *tmpl, | |||
854 | struct nf_conntrack_l3proto *l3proto, | 865 | struct nf_conntrack_l3proto *l3proto, |
855 | struct nf_conntrack_l4proto *l4proto, | 866 | struct nf_conntrack_l4proto *l4proto, |
856 | int *set_reply, | 867 | int *set_reply, |
857 | enum ip_conntrack_info *ctinfo, | 868 | enum ip_conntrack_info *ctinfo) |
858 | unsigned int *timeouts) | ||
859 | { | 869 | { |
860 | struct nf_conntrack_tuple tuple; | 870 | struct nf_conntrack_tuple tuple; |
861 | struct nf_conntrack_tuple_hash *h; | 871 | struct nf_conntrack_tuple_hash *h; |
@@ -875,7 +885,7 @@ resolve_normal_ct(struct net *net, struct nf_conn *tmpl, | |||
875 | h = __nf_conntrack_find_get(net, zone, &tuple, hash); | 885 | h = __nf_conntrack_find_get(net, zone, &tuple, hash); |
876 | if (!h) { | 886 | if (!h) { |
877 | h = init_conntrack(net, tmpl, &tuple, l3proto, l4proto, | 887 | h = init_conntrack(net, tmpl, &tuple, l3proto, l4proto, |
878 | skb, dataoff, hash, timeouts); | 888 | skb, dataoff, hash); |
879 | if (!h) | 889 | if (!h) |
880 | return NULL; | 890 | return NULL; |
881 | if (IS_ERR(h)) | 891 | if (IS_ERR(h)) |
@@ -964,19 +974,8 @@ nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum, | |||
964 | goto out; | 974 | goto out; |
965 | } | 975 | } |
966 | 976 | ||
967 | /* Decide what timeout policy we want to apply to this flow. */ | ||
968 | if (tmpl) { | ||
969 | timeout_ext = nf_ct_timeout_find(tmpl); | ||
970 | if (timeout_ext) | ||
971 | timeouts = NF_CT_TIMEOUT_EXT_DATA(timeout_ext); | ||
972 | else | ||
973 | timeouts = l4proto->get_timeouts(net); | ||
974 | } else | ||
975 | timeouts = l4proto->get_timeouts(net); | ||
976 | |||
977 | ct = resolve_normal_ct(net, tmpl, skb, dataoff, pf, protonum, | 977 | ct = resolve_normal_ct(net, tmpl, skb, dataoff, pf, protonum, |
978 | l3proto, l4proto, &set_reply, &ctinfo, | 978 | l3proto, l4proto, &set_reply, &ctinfo); |
979 | timeouts); | ||
980 | if (!ct) { | 979 | if (!ct) { |
981 | /* Not valid part of a connection */ | 980 | /* Not valid part of a connection */ |
982 | NF_CT_STAT_INC_ATOMIC(net, invalid); | 981 | NF_CT_STAT_INC_ATOMIC(net, invalid); |
@@ -993,6 +992,13 @@ nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum, | |||
993 | 992 | ||
994 | NF_CT_ASSERT(skb->nfct); | 993 | NF_CT_ASSERT(skb->nfct); |
995 | 994 | ||
995 | /* Decide what timeout policy we want to apply to this flow. */ | ||
996 | timeout_ext = nf_ct_timeout_find(ct); | ||
997 | if (timeout_ext) | ||
998 | timeouts = NF_CT_TIMEOUT_EXT_DATA(timeout_ext); | ||
999 | else | ||
1000 | timeouts = l4proto->get_timeouts(net); | ||
1001 | |||
996 | ret = l4proto->packet(ct, skb, dataoff, ctinfo, pf, hooknum, timeouts); | 1002 | ret = l4proto->packet(ct, skb, dataoff, ctinfo, pf, hooknum, timeouts); |
997 | if (ret <= 0) { | 1003 | if (ret <= 0) { |
998 | /* Invalid: inverse of the return code tells | 1004 | /* Invalid: inverse of the return code tells |
diff --git a/net/netfilter/nf_conntrack_proto.c b/net/netfilter/nf_conntrack_proto.c index 5701c8dd783c..be3da2c8cdc5 100644 --- a/net/netfilter/nf_conntrack_proto.c +++ b/net/netfilter/nf_conntrack_proto.c | |||
@@ -127,6 +127,27 @@ void nf_ct_l3proto_module_put(unsigned short l3proto) | |||
127 | } | 127 | } |
128 | EXPORT_SYMBOL_GPL(nf_ct_l3proto_module_put); | 128 | EXPORT_SYMBOL_GPL(nf_ct_l3proto_module_put); |
129 | 129 | ||
130 | struct nf_conntrack_l4proto * | ||
131 | nf_ct_l4proto_find_get(u_int16_t l3num, u_int8_t l4num) | ||
132 | { | ||
133 | struct nf_conntrack_l4proto *p; | ||
134 | |||
135 | rcu_read_lock(); | ||
136 | p = __nf_ct_l4proto_find(l3num, l4num); | ||
137 | if (!try_module_get(p->me)) | ||
138 | p = &nf_conntrack_l4proto_generic; | ||
139 | rcu_read_unlock(); | ||
140 | |||
141 | return p; | ||
142 | } | ||
143 | EXPORT_SYMBOL_GPL(nf_ct_l4proto_find_get); | ||
144 | |||
145 | void nf_ct_l4proto_put(struct nf_conntrack_l4proto *p) | ||
146 | { | ||
147 | module_put(p->me); | ||
148 | } | ||
149 | EXPORT_SYMBOL_GPL(nf_ct_l4proto_put); | ||
150 | |||
130 | static int kill_l3proto(struct nf_conn *i, void *data) | 151 | static int kill_l3proto(struct nf_conn *i, void *data) |
131 | { | 152 | { |
132 | return nf_ct_l3num(i) == ((struct nf_conntrack_l3proto *)data)->l3proto; | 153 | return nf_ct_l3num(i) == ((struct nf_conntrack_l3proto *)data)->l3proto; |
diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c index 4d70785b953d..e6ddde165612 100644 --- a/net/netfilter/nfnetlink.c +++ b/net/netfilter/nfnetlink.c | |||
@@ -23,7 +23,6 @@ | |||
23 | #include <linux/net.h> | 23 | #include <linux/net.h> |
24 | #include <linux/skbuff.h> | 24 | #include <linux/skbuff.h> |
25 | #include <asm/uaccess.h> | 25 | #include <asm/uaccess.h> |
26 | #include <asm/system.h> | ||
27 | #include <net/sock.h> | 26 | #include <net/sock.h> |
28 | #include <net/netlink.h> | 27 | #include <net/netlink.h> |
29 | #include <linux/init.h> | 28 | #include <linux/init.h> |
diff --git a/net/netfilter/nfnetlink_acct.c b/net/netfilter/nfnetlink_acct.c index 3eb348bfc4fb..d98c868c148b 100644 --- a/net/netfilter/nfnetlink_acct.c +++ b/net/netfilter/nfnetlink_acct.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <linux/module.h> | 10 | #include <linux/module.h> |
11 | #include <linux/kernel.h> | 11 | #include <linux/kernel.h> |
12 | #include <linux/skbuff.h> | 12 | #include <linux/skbuff.h> |
13 | #include <linux/atomic.h> | ||
13 | #include <linux/netlink.h> | 14 | #include <linux/netlink.h> |
14 | #include <linux/rculist.h> | 15 | #include <linux/rculist.h> |
15 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
@@ -17,7 +18,6 @@ | |||
17 | #include <linux/errno.h> | 18 | #include <linux/errno.h> |
18 | #include <net/netlink.h> | 19 | #include <net/netlink.h> |
19 | #include <net/sock.h> | 20 | #include <net/sock.h> |
20 | #include <asm/atomic.h> | ||
21 | 21 | ||
22 | #include <linux/netfilter.h> | 22 | #include <linux/netfilter.h> |
23 | #include <linux/netfilter/nfnetlink.h> | 23 | #include <linux/netfilter/nfnetlink.h> |
diff --git a/net/netfilter/nfnetlink_cttimeout.c b/net/netfilter/nfnetlink_cttimeout.c index fec29a43de4d..2b9e79f5ef05 100644 --- a/net/netfilter/nfnetlink_cttimeout.c +++ b/net/netfilter/nfnetlink_cttimeout.c | |||
@@ -98,11 +98,13 @@ cttimeout_new_timeout(struct sock *ctnl, struct sk_buff *skb, | |||
98 | break; | 98 | break; |
99 | } | 99 | } |
100 | 100 | ||
101 | l4proto = __nf_ct_l4proto_find(l3num, l4num); | 101 | l4proto = nf_ct_l4proto_find_get(l3num, l4num); |
102 | 102 | ||
103 | /* This protocol is not supportted, skip. */ | 103 | /* This protocol is not supportted, skip. */ |
104 | if (l4proto->l4proto != l4num) | 104 | if (l4proto->l4proto != l4num) { |
105 | return -EOPNOTSUPP; | 105 | ret = -EOPNOTSUPP; |
106 | goto err_proto_put; | ||
107 | } | ||
106 | 108 | ||
107 | if (matching) { | 109 | if (matching) { |
108 | if (nlh->nlmsg_flags & NLM_F_REPLACE) { | 110 | if (nlh->nlmsg_flags & NLM_F_REPLACE) { |
@@ -110,20 +112,25 @@ cttimeout_new_timeout(struct sock *ctnl, struct sk_buff *skb, | |||
110 | * different kind, sorry. | 112 | * different kind, sorry. |
111 | */ | 113 | */ |
112 | if (matching->l3num != l3num || | 114 | if (matching->l3num != l3num || |
113 | matching->l4num != l4num) | 115 | matching->l4proto->l4proto != l4num) { |
114 | return -EINVAL; | 116 | ret = -EINVAL; |
117 | goto err_proto_put; | ||
118 | } | ||
115 | 119 | ||
116 | ret = ctnl_timeout_parse_policy(matching, l4proto, | 120 | ret = ctnl_timeout_parse_policy(matching, l4proto, |
117 | cda[CTA_TIMEOUT_DATA]); | 121 | cda[CTA_TIMEOUT_DATA]); |
118 | return ret; | 122 | return ret; |
119 | } | 123 | } |
120 | return -EBUSY; | 124 | ret = -EBUSY; |
125 | goto err_proto_put; | ||
121 | } | 126 | } |
122 | 127 | ||
123 | timeout = kzalloc(sizeof(struct ctnl_timeout) + | 128 | timeout = kzalloc(sizeof(struct ctnl_timeout) + |
124 | l4proto->ctnl_timeout.obj_size, GFP_KERNEL); | 129 | l4proto->ctnl_timeout.obj_size, GFP_KERNEL); |
125 | if (timeout == NULL) | 130 | if (timeout == NULL) { |
126 | return -ENOMEM; | 131 | ret = -ENOMEM; |
132 | goto err_proto_put; | ||
133 | } | ||
127 | 134 | ||
128 | ret = ctnl_timeout_parse_policy(timeout, l4proto, | 135 | ret = ctnl_timeout_parse_policy(timeout, l4proto, |
129 | cda[CTA_TIMEOUT_DATA]); | 136 | cda[CTA_TIMEOUT_DATA]); |
@@ -132,13 +139,15 @@ cttimeout_new_timeout(struct sock *ctnl, struct sk_buff *skb, | |||
132 | 139 | ||
133 | strcpy(timeout->name, nla_data(cda[CTA_TIMEOUT_NAME])); | 140 | strcpy(timeout->name, nla_data(cda[CTA_TIMEOUT_NAME])); |
134 | timeout->l3num = l3num; | 141 | timeout->l3num = l3num; |
135 | timeout->l4num = l4num; | 142 | timeout->l4proto = l4proto; |
136 | atomic_set(&timeout->refcnt, 1); | 143 | atomic_set(&timeout->refcnt, 1); |
137 | list_add_tail_rcu(&timeout->head, &cttimeout_list); | 144 | list_add_tail_rcu(&timeout->head, &cttimeout_list); |
138 | 145 | ||
139 | return 0; | 146 | return 0; |
140 | err: | 147 | err: |
141 | kfree(timeout); | 148 | kfree(timeout); |
149 | err_proto_put: | ||
150 | nf_ct_l4proto_put(l4proto); | ||
142 | return ret; | 151 | return ret; |
143 | } | 152 | } |
144 | 153 | ||
@@ -149,7 +158,7 @@ ctnl_timeout_fill_info(struct sk_buff *skb, u32 pid, u32 seq, u32 type, | |||
149 | struct nlmsghdr *nlh; | 158 | struct nlmsghdr *nlh; |
150 | struct nfgenmsg *nfmsg; | 159 | struct nfgenmsg *nfmsg; |
151 | unsigned int flags = pid ? NLM_F_MULTI : 0; | 160 | unsigned int flags = pid ? NLM_F_MULTI : 0; |
152 | struct nf_conntrack_l4proto *l4proto; | 161 | struct nf_conntrack_l4proto *l4proto = timeout->l4proto; |
153 | 162 | ||
154 | event |= NFNL_SUBSYS_CTNETLINK_TIMEOUT << 8; | 163 | event |= NFNL_SUBSYS_CTNETLINK_TIMEOUT << 8; |
155 | nlh = nlmsg_put(skb, pid, seq, event, sizeof(*nfmsg), flags); | 164 | nlh = nlmsg_put(skb, pid, seq, event, sizeof(*nfmsg), flags); |
@@ -163,20 +172,10 @@ ctnl_timeout_fill_info(struct sk_buff *skb, u32 pid, u32 seq, u32 type, | |||
163 | 172 | ||
164 | NLA_PUT_STRING(skb, CTA_TIMEOUT_NAME, timeout->name); | 173 | NLA_PUT_STRING(skb, CTA_TIMEOUT_NAME, timeout->name); |
165 | NLA_PUT_BE16(skb, CTA_TIMEOUT_L3PROTO, htons(timeout->l3num)); | 174 | NLA_PUT_BE16(skb, CTA_TIMEOUT_L3PROTO, htons(timeout->l3num)); |
166 | NLA_PUT_U8(skb, CTA_TIMEOUT_L4PROTO, timeout->l4num); | 175 | NLA_PUT_U8(skb, CTA_TIMEOUT_L4PROTO, timeout->l4proto->l4proto); |
167 | NLA_PUT_BE32(skb, CTA_TIMEOUT_USE, | 176 | NLA_PUT_BE32(skb, CTA_TIMEOUT_USE, |
168 | htonl(atomic_read(&timeout->refcnt))); | 177 | htonl(atomic_read(&timeout->refcnt))); |
169 | 178 | ||
170 | l4proto = __nf_ct_l4proto_find(timeout->l3num, timeout->l4num); | ||
171 | |||
172 | /* If the timeout object does not match the layer 4 protocol tracker, | ||
173 | * then skip dumping the data part since we don't know how to | ||
174 | * interpret it. This may happen for UPDlite, SCTP and DCCP since | ||
175 | * you can unload the module. | ||
176 | */ | ||
177 | if (timeout->l4num != l4proto->l4proto) | ||
178 | goto out; | ||
179 | |||
180 | if (likely(l4proto->ctnl_timeout.obj_to_nlattr)) { | 179 | if (likely(l4proto->ctnl_timeout.obj_to_nlattr)) { |
181 | struct nlattr *nest_parms; | 180 | struct nlattr *nest_parms; |
182 | int ret; | 181 | int ret; |
@@ -192,7 +191,7 @@ ctnl_timeout_fill_info(struct sk_buff *skb, u32 pid, u32 seq, u32 type, | |||
192 | 191 | ||
193 | nla_nest_end(skb, nest_parms); | 192 | nla_nest_end(skb, nest_parms); |
194 | } | 193 | } |
195 | out: | 194 | |
196 | nlmsg_end(skb, nlh); | 195 | nlmsg_end(skb, nlh); |
197 | return skb->len; | 196 | return skb->len; |
198 | 197 | ||
@@ -293,6 +292,7 @@ static int ctnl_timeout_try_del(struct ctnl_timeout *timeout) | |||
293 | if (atomic_dec_and_test(&timeout->refcnt)) { | 292 | if (atomic_dec_and_test(&timeout->refcnt)) { |
294 | /* We are protected by nfnl mutex. */ | 293 | /* We are protected by nfnl mutex. */ |
295 | list_del_rcu(&timeout->head); | 294 | list_del_rcu(&timeout->head); |
295 | nf_ct_l4proto_put(timeout->l4proto); | ||
296 | kfree_rcu(timeout, rcu_head); | 296 | kfree_rcu(timeout, rcu_head); |
297 | } else { | 297 | } else { |
298 | /* still in use, restore reference counter. */ | 298 | /* still in use, restore reference counter. */ |
@@ -417,6 +417,7 @@ static void __exit cttimeout_exit(void) | |||
417 | /* We are sure that our objects have no clients at this point, | 417 | /* We are sure that our objects have no clients at this point, |
418 | * it's safe to release them all without checking refcnt. | 418 | * it's safe to release them all without checking refcnt. |
419 | */ | 419 | */ |
420 | nf_ct_l4proto_put(cur->l4proto); | ||
420 | kfree_rcu(cur, rcu_head); | 421 | kfree_rcu(cur, rcu_head); |
421 | } | 422 | } |
422 | #ifdef CONFIG_NF_CONNTRACK_TIMEOUT | 423 | #ifdef CONFIG_NF_CONNTRACK_TIMEOUT |
diff --git a/net/netfilter/xt_CT.c b/net/netfilter/xt_CT.c index b873445df444..59530e93fa58 100644 --- a/net/netfilter/xt_CT.c +++ b/net/netfilter/xt_CT.c | |||
@@ -14,8 +14,10 @@ | |||
14 | #include <linux/netfilter/x_tables.h> | 14 | #include <linux/netfilter/x_tables.h> |
15 | #include <linux/netfilter/xt_CT.h> | 15 | #include <linux/netfilter/xt_CT.h> |
16 | #include <net/netfilter/nf_conntrack.h> | 16 | #include <net/netfilter/nf_conntrack.h> |
17 | #include <net/netfilter/nf_conntrack_l4proto.h> | ||
17 | #include <net/netfilter/nf_conntrack_helper.h> | 18 | #include <net/netfilter/nf_conntrack_helper.h> |
18 | #include <net/netfilter/nf_conntrack_ecache.h> | 19 | #include <net/netfilter/nf_conntrack_ecache.h> |
20 | #include <net/netfilter/nf_conntrack_l4proto.h> | ||
19 | #include <net/netfilter/nf_conntrack_timeout.h> | 21 | #include <net/netfilter/nf_conntrack_timeout.h> |
20 | #include <net/netfilter/nf_conntrack_zones.h> | 22 | #include <net/netfilter/nf_conntrack_zones.h> |
21 | 23 | ||
@@ -148,6 +150,17 @@ err1: | |||
148 | return ret; | 150 | return ret; |
149 | } | 151 | } |
150 | 152 | ||
153 | #ifdef CONFIG_NF_CONNTRACK_TIMEOUT | ||
154 | static void __xt_ct_tg_timeout_put(struct ctnl_timeout *timeout) | ||
155 | { | ||
156 | typeof(nf_ct_timeout_put_hook) timeout_put; | ||
157 | |||
158 | timeout_put = rcu_dereference(nf_ct_timeout_put_hook); | ||
159 | if (timeout_put) | ||
160 | timeout_put(timeout); | ||
161 | } | ||
162 | #endif | ||
163 | |||
151 | static int xt_ct_tg_check_v1(const struct xt_tgchk_param *par) | 164 | static int xt_ct_tg_check_v1(const struct xt_tgchk_param *par) |
152 | { | 165 | { |
153 | struct xt_ct_target_info_v1 *info = par->targinfo; | 166 | struct xt_ct_target_info_v1 *info = par->targinfo; |
@@ -156,7 +169,9 @@ static int xt_ct_tg_check_v1(const struct xt_tgchk_param *par) | |||
156 | struct nf_conn *ct; | 169 | struct nf_conn *ct; |
157 | int ret = 0; | 170 | int ret = 0; |
158 | u8 proto; | 171 | u8 proto; |
159 | 172 | #ifdef CONFIG_NF_CONNTRACK_TIMEOUT | |
173 | struct ctnl_timeout *timeout; | ||
174 | #endif | ||
160 | if (info->flags & ~XT_CT_NOTRACK) | 175 | if (info->flags & ~XT_CT_NOTRACK) |
161 | return -EINVAL; | 176 | return -EINVAL; |
162 | 177 | ||
@@ -214,53 +229,61 @@ static int xt_ct_tg_check_v1(const struct xt_tgchk_param *par) | |||
214 | #ifdef CONFIG_NF_CONNTRACK_TIMEOUT | 229 | #ifdef CONFIG_NF_CONNTRACK_TIMEOUT |
215 | if (info->timeout) { | 230 | if (info->timeout) { |
216 | typeof(nf_ct_timeout_find_get_hook) timeout_find_get; | 231 | typeof(nf_ct_timeout_find_get_hook) timeout_find_get; |
217 | struct ctnl_timeout *timeout; | ||
218 | struct nf_conn_timeout *timeout_ext; | 232 | struct nf_conn_timeout *timeout_ext; |
219 | 233 | ||
234 | rcu_read_lock(); | ||
220 | timeout_find_get = | 235 | timeout_find_get = |
221 | rcu_dereference(nf_ct_timeout_find_get_hook); | 236 | rcu_dereference(nf_ct_timeout_find_get_hook); |
222 | 237 | ||
223 | if (timeout_find_get) { | 238 | if (timeout_find_get) { |
224 | const struct ipt_entry *e = par->entryinfo; | 239 | const struct ipt_entry *e = par->entryinfo; |
240 | struct nf_conntrack_l4proto *l4proto; | ||
225 | 241 | ||
226 | if (e->ip.invflags & IPT_INV_PROTO) { | 242 | if (e->ip.invflags & IPT_INV_PROTO) { |
227 | ret = -EINVAL; | 243 | ret = -EINVAL; |
228 | pr_info("You cannot use inversion on " | 244 | pr_info("You cannot use inversion on " |
229 | "L4 protocol\n"); | 245 | "L4 protocol\n"); |
230 | goto err3; | 246 | goto err4; |
231 | } | 247 | } |
232 | timeout = timeout_find_get(info->timeout); | 248 | timeout = timeout_find_get(info->timeout); |
233 | if (timeout == NULL) { | 249 | if (timeout == NULL) { |
234 | ret = -ENOENT; | 250 | ret = -ENOENT; |
235 | pr_info("No such timeout policy \"%s\"\n", | 251 | pr_info("No such timeout policy \"%s\"\n", |
236 | info->timeout); | 252 | info->timeout); |
237 | goto err3; | 253 | goto err4; |
238 | } | 254 | } |
239 | if (timeout->l3num != par->family) { | 255 | if (timeout->l3num != par->family) { |
240 | ret = -EINVAL; | 256 | ret = -EINVAL; |
241 | pr_info("Timeout policy `%s' can only be " | 257 | pr_info("Timeout policy `%s' can only be " |
242 | "used by L3 protocol number %d\n", | 258 | "used by L3 protocol number %d\n", |
243 | info->timeout, timeout->l3num); | 259 | info->timeout, timeout->l3num); |
244 | goto err3; | 260 | goto err5; |
245 | } | 261 | } |
246 | if (timeout->l4num != e->ip.proto) { | 262 | /* Make sure the timeout policy matches any existing |
263 | * protocol tracker, otherwise default to generic. | ||
264 | */ | ||
265 | l4proto = __nf_ct_l4proto_find(par->family, | ||
266 | e->ip.proto); | ||
267 | if (timeout->l4proto->l4proto != l4proto->l4proto) { | ||
247 | ret = -EINVAL; | 268 | ret = -EINVAL; |
248 | pr_info("Timeout policy `%s' can only be " | 269 | pr_info("Timeout policy `%s' can only be " |
249 | "used by L4 protocol number %d\n", | 270 | "used by L4 protocol number %d\n", |
250 | info->timeout, timeout->l4num); | 271 | info->timeout, |
251 | goto err3; | 272 | timeout->l4proto->l4proto); |
273 | goto err5; | ||
252 | } | 274 | } |
253 | timeout_ext = nf_ct_timeout_ext_add(ct, timeout, | 275 | timeout_ext = nf_ct_timeout_ext_add(ct, timeout, |
254 | GFP_KERNEL); | 276 | GFP_ATOMIC); |
255 | if (timeout_ext == NULL) { | 277 | if (timeout_ext == NULL) { |
256 | ret = -ENOMEM; | 278 | ret = -ENOMEM; |
257 | goto err3; | 279 | goto err5; |
258 | } | 280 | } |
259 | } else { | 281 | } else { |
260 | ret = -ENOENT; | 282 | ret = -ENOENT; |
261 | pr_info("Timeout policy base is empty\n"); | 283 | pr_info("Timeout policy base is empty\n"); |
262 | goto err3; | 284 | goto err4; |
263 | } | 285 | } |
286 | rcu_read_unlock(); | ||
264 | } | 287 | } |
265 | #endif | 288 | #endif |
266 | 289 | ||
@@ -270,6 +293,12 @@ out: | |||
270 | info->ct = ct; | 293 | info->ct = ct; |
271 | return 0; | 294 | return 0; |
272 | 295 | ||
296 | #ifdef CONFIG_NF_CONNTRACK_TIMEOUT | ||
297 | err5: | ||
298 | __xt_ct_tg_timeout_put(timeout); | ||
299 | err4: | ||
300 | rcu_read_unlock(); | ||
301 | #endif | ||
273 | err3: | 302 | err3: |
274 | nf_conntrack_free(ct); | 303 | nf_conntrack_free(ct); |
275 | err2: | 304 | err2: |
@@ -311,6 +340,7 @@ static void xt_ct_tg_destroy_v1(const struct xt_tgdtor_param *par) | |||
311 | nf_ct_l3proto_module_put(par->family); | 340 | nf_ct_l3proto_module_put(par->family); |
312 | 341 | ||
313 | #ifdef CONFIG_NF_CONNTRACK_TIMEOUT | 342 | #ifdef CONFIG_NF_CONNTRACK_TIMEOUT |
343 | rcu_read_lock(); | ||
314 | timeout_put = rcu_dereference(nf_ct_timeout_put_hook); | 344 | timeout_put = rcu_dereference(nf_ct_timeout_put_hook); |
315 | 345 | ||
316 | if (timeout_put) { | 346 | if (timeout_put) { |
@@ -318,6 +348,7 @@ static void xt_ct_tg_destroy_v1(const struct xt_tgdtor_param *par) | |||
318 | if (timeout_ext) | 348 | if (timeout_ext) |
319 | timeout_put(timeout_ext->timeout); | 349 | timeout_put(timeout_ext->timeout); |
320 | } | 350 | } |
351 | rcu_read_unlock(); | ||
321 | #endif | 352 | #endif |
322 | } | 353 | } |
323 | nf_ct_put(info->ct); | 354 | nf_ct_put(info->ct); |
diff --git a/net/netfilter/xt_LOG.c b/net/netfilter/xt_LOG.c index f99f8dee238b..ff5f75fddb15 100644 --- a/net/netfilter/xt_LOG.c +++ b/net/netfilter/xt_LOG.c | |||
@@ -480,7 +480,7 @@ ipt_log_packet(u_int8_t pf, | |||
480 | sb_close(m); | 480 | sb_close(m); |
481 | } | 481 | } |
482 | 482 | ||
483 | #if IS_ENABLED(CONFIG_IPV6) | 483 | #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) |
484 | /* One level of recursion won't kill us */ | 484 | /* One level of recursion won't kill us */ |
485 | static void dump_ipv6_packet(struct sbuff *m, | 485 | static void dump_ipv6_packet(struct sbuff *m, |
486 | const struct nf_loginfo *info, | 486 | const struct nf_loginfo *info, |
@@ -824,7 +824,7 @@ log_tg(struct sk_buff *skb, const struct xt_action_param *par) | |||
824 | if (par->family == NFPROTO_IPV4) | 824 | if (par->family == NFPROTO_IPV4) |
825 | ipt_log_packet(NFPROTO_IPV4, par->hooknum, skb, par->in, | 825 | ipt_log_packet(NFPROTO_IPV4, par->hooknum, skb, par->in, |
826 | par->out, &li, loginfo->prefix); | 826 | par->out, &li, loginfo->prefix); |
827 | #if IS_ENABLED(CONFIG_IPV6) | 827 | #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) |
828 | else if (par->family == NFPROTO_IPV6) | 828 | else if (par->family == NFPROTO_IPV6) |
829 | ip6t_log_packet(NFPROTO_IPV6, par->hooknum, skb, par->in, | 829 | ip6t_log_packet(NFPROTO_IPV6, par->hooknum, skb, par->in, |
830 | par->out, &li, loginfo->prefix); | 830 | par->out, &li, loginfo->prefix); |
@@ -864,7 +864,7 @@ static struct xt_target log_tg_regs[] __read_mostly = { | |||
864 | .checkentry = log_tg_check, | 864 | .checkentry = log_tg_check, |
865 | .me = THIS_MODULE, | 865 | .me = THIS_MODULE, |
866 | }, | 866 | }, |
867 | #if IS_ENABLED(CONFIG_IPV6) | 867 | #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) |
868 | { | 868 | { |
869 | .name = "LOG", | 869 | .name = "LOG", |
870 | .family = NFPROTO_IPV6, | 870 | .family = NFPROTO_IPV6, |
@@ -882,7 +882,7 @@ static struct nf_logger ipt_log_logger __read_mostly = { | |||
882 | .me = THIS_MODULE, | 882 | .me = THIS_MODULE, |
883 | }; | 883 | }; |
884 | 884 | ||
885 | #if IS_ENABLED(CONFIG_IPV6) | 885 | #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) |
886 | static struct nf_logger ip6t_log_logger __read_mostly = { | 886 | static struct nf_logger ip6t_log_logger __read_mostly = { |
887 | .name = "ip6t_LOG", | 887 | .name = "ip6t_LOG", |
888 | .logfn = &ip6t_log_packet, | 888 | .logfn = &ip6t_log_packet, |
@@ -899,7 +899,7 @@ static int __init log_tg_init(void) | |||
899 | return ret; | 899 | return ret; |
900 | 900 | ||
901 | nf_log_register(NFPROTO_IPV4, &ipt_log_logger); | 901 | nf_log_register(NFPROTO_IPV4, &ipt_log_logger); |
902 | #if IS_ENABLED(CONFIG_IPV6) | 902 | #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) |
903 | nf_log_register(NFPROTO_IPV6, &ip6t_log_logger); | 903 | nf_log_register(NFPROTO_IPV6, &ip6t_log_logger); |
904 | #endif | 904 | #endif |
905 | return 0; | 905 | return 0; |
@@ -908,7 +908,7 @@ static int __init log_tg_init(void) | |||
908 | static void __exit log_tg_exit(void) | 908 | static void __exit log_tg_exit(void) |
909 | { | 909 | { |
910 | nf_log_unregister(&ipt_log_logger); | 910 | nf_log_unregister(&ipt_log_logger); |
911 | #if IS_ENABLED(CONFIG_IPV6) | 911 | #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) |
912 | nf_log_unregister(&ip6t_log_logger); | 912 | nf_log_unregister(&ip6t_log_logger); |
913 | #endif | 913 | #endif |
914 | xt_unregister_targets(log_tg_regs, ARRAY_SIZE(log_tg_regs)); | 914 | xt_unregister_targets(log_tg_regs, ARRAY_SIZE(log_tg_regs)); |
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 32bb75324e76..faa48f70b7c9 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c | |||
@@ -829,12 +829,19 @@ int netlink_attachskb(struct sock *sk, struct sk_buff *skb, | |||
829 | return 0; | 829 | return 0; |
830 | } | 830 | } |
831 | 831 | ||
832 | int netlink_sendskb(struct sock *sk, struct sk_buff *skb) | 832 | static int __netlink_sendskb(struct sock *sk, struct sk_buff *skb) |
833 | { | 833 | { |
834 | int len = skb->len; | 834 | int len = skb->len; |
835 | 835 | ||
836 | skb_queue_tail(&sk->sk_receive_queue, skb); | 836 | skb_queue_tail(&sk->sk_receive_queue, skb); |
837 | sk->sk_data_ready(sk, len); | 837 | sk->sk_data_ready(sk, len); |
838 | return len; | ||
839 | } | ||
840 | |||
841 | int netlink_sendskb(struct sock *sk, struct sk_buff *skb) | ||
842 | { | ||
843 | int len = __netlink_sendskb(sk, skb); | ||
844 | |||
838 | sock_put(sk); | 845 | sock_put(sk); |
839 | return len; | 846 | return len; |
840 | } | 847 | } |
@@ -957,8 +964,7 @@ static int netlink_broadcast_deliver(struct sock *sk, struct sk_buff *skb) | |||
957 | if (atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf && | 964 | if (atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf && |
958 | !test_bit(0, &nlk->state)) { | 965 | !test_bit(0, &nlk->state)) { |
959 | skb_set_owner_r(skb, sk); | 966 | skb_set_owner_r(skb, sk); |
960 | skb_queue_tail(&sk->sk_receive_queue, skb); | 967 | __netlink_sendskb(sk, skb); |
961 | sk->sk_data_ready(sk, skb->len); | ||
962 | return atomic_read(&sk->sk_rmem_alloc) > (sk->sk_rcvbuf >> 1); | 968 | return atomic_read(&sk->sk_rmem_alloc) > (sk->sk_rcvbuf >> 1); |
963 | } | 969 | } |
964 | return -1; | 970 | return -1; |
@@ -1698,10 +1704,8 @@ static int netlink_dump(struct sock *sk) | |||
1698 | 1704 | ||
1699 | if (sk_filter(sk, skb)) | 1705 | if (sk_filter(sk, skb)) |
1700 | kfree_skb(skb); | 1706 | kfree_skb(skb); |
1701 | else { | 1707 | else |
1702 | skb_queue_tail(&sk->sk_receive_queue, skb); | 1708 | __netlink_sendskb(sk, skb); |
1703 | sk->sk_data_ready(sk, skb->len); | ||
1704 | } | ||
1705 | return 0; | 1709 | return 0; |
1706 | } | 1710 | } |
1707 | 1711 | ||
@@ -1715,10 +1719,8 @@ static int netlink_dump(struct sock *sk) | |||
1715 | 1719 | ||
1716 | if (sk_filter(sk, skb)) | 1720 | if (sk_filter(sk, skb)) |
1717 | kfree_skb(skb); | 1721 | kfree_skb(skb); |
1718 | else { | 1722 | else |
1719 | skb_queue_tail(&sk->sk_receive_queue, skb); | 1723 | __netlink_sendskb(sk, skb); |
1720 | sk->sk_data_ready(sk, skb->len); | ||
1721 | } | ||
1722 | 1724 | ||
1723 | if (cb->done) | 1725 | if (cb->done) |
1724 | cb->done(cb); | 1726 | cb->done(cb); |
diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c index 7dab229bfbcc..06592d8b4a2b 100644 --- a/net/netrom/af_netrom.c +++ b/net/netrom/af_netrom.c | |||
@@ -31,7 +31,6 @@ | |||
31 | #include <net/net_namespace.h> | 31 | #include <net/net_namespace.h> |
32 | #include <net/sock.h> | 32 | #include <net/sock.h> |
33 | #include <asm/uaccess.h> | 33 | #include <asm/uaccess.h> |
34 | #include <asm/system.h> | ||
35 | #include <linux/fcntl.h> | 34 | #include <linux/fcntl.h> |
36 | #include <linux/termios.h> /* For TIOCINQ/OUTQ */ | 35 | #include <linux/termios.h> /* For TIOCINQ/OUTQ */ |
37 | #include <linux/mm.h> | 36 | #include <linux/mm.h> |
diff --git a/net/netrom/nr_dev.c b/net/netrom/nr_dev.c index 64e6dde9749d..1c51d7a58f0b 100644 --- a/net/netrom/nr_dev.c +++ b/net/netrom/nr_dev.c | |||
@@ -21,7 +21,6 @@ | |||
21 | #include <linux/if_ether.h> /* For the statistics structure. */ | 21 | #include <linux/if_ether.h> /* For the statistics structure. */ |
22 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
23 | 23 | ||
24 | #include <asm/system.h> | ||
25 | #include <asm/uaccess.h> | 24 | #include <asm/uaccess.h> |
26 | #include <asm/io.h> | 25 | #include <asm/io.h> |
27 | 26 | ||
diff --git a/net/netrom/nr_in.c b/net/netrom/nr_in.c index 6d4ef6d65b3d..c3073a2ef634 100644 --- a/net/netrom/nr_in.c +++ b/net/netrom/nr_in.c | |||
@@ -24,7 +24,6 @@ | |||
24 | #include <net/sock.h> | 24 | #include <net/sock.h> |
25 | #include <net/tcp_states.h> | 25 | #include <net/tcp_states.h> |
26 | #include <asm/uaccess.h> | 26 | #include <asm/uaccess.h> |
27 | #include <asm/system.h> | ||
28 | #include <linux/fcntl.h> | 27 | #include <linux/fcntl.h> |
29 | #include <linux/mm.h> | 28 | #include <linux/mm.h> |
30 | #include <linux/interrupt.h> | 29 | #include <linux/interrupt.h> |
diff --git a/net/netrom/nr_out.c b/net/netrom/nr_out.c index 607fddb4fdbb..0b4bcb2bf38f 100644 --- a/net/netrom/nr_out.c +++ b/net/netrom/nr_out.c | |||
@@ -23,7 +23,6 @@ | |||
23 | #include <linux/skbuff.h> | 23 | #include <linux/skbuff.h> |
24 | #include <net/sock.h> | 24 | #include <net/sock.h> |
25 | #include <asm/uaccess.h> | 25 | #include <asm/uaccess.h> |
26 | #include <asm/system.h> | ||
27 | #include <linux/fcntl.h> | 26 | #include <linux/fcntl.h> |
28 | #include <linux/mm.h> | 27 | #include <linux/mm.h> |
29 | #include <linux/interrupt.h> | 28 | #include <linux/interrupt.h> |
diff --git a/net/netrom/nr_route.c b/net/netrom/nr_route.c index 2cf330162d7e..70ffff76a967 100644 --- a/net/netrom/nr_route.c +++ b/net/netrom/nr_route.c | |||
@@ -26,7 +26,6 @@ | |||
26 | #include <linux/skbuff.h> | 26 | #include <linux/skbuff.h> |
27 | #include <net/sock.h> | 27 | #include <net/sock.h> |
28 | #include <asm/uaccess.h> | 28 | #include <asm/uaccess.h> |
29 | #include <asm/system.h> | ||
30 | #include <linux/fcntl.h> | 29 | #include <linux/fcntl.h> |
31 | #include <linux/termios.h> /* For TIOCINQ/OUTQ */ | 30 | #include <linux/termios.h> /* For TIOCINQ/OUTQ */ |
32 | #include <linux/mm.h> | 31 | #include <linux/mm.h> |
diff --git a/net/netrom/nr_subr.c b/net/netrom/nr_subr.c index 6a947ae50dbd..ca40e2298f5a 100644 --- a/net/netrom/nr_subr.c +++ b/net/netrom/nr_subr.c | |||
@@ -23,7 +23,6 @@ | |||
23 | #include <net/sock.h> | 23 | #include <net/sock.h> |
24 | #include <net/tcp_states.h> | 24 | #include <net/tcp_states.h> |
25 | #include <asm/uaccess.h> | 25 | #include <asm/uaccess.h> |
26 | #include <asm/system.h> | ||
27 | #include <linux/fcntl.h> | 26 | #include <linux/fcntl.h> |
28 | #include <linux/mm.h> | 27 | #include <linux/mm.h> |
29 | #include <linux/interrupt.h> | 28 | #include <linux/interrupt.h> |
diff --git a/net/netrom/nr_timer.c b/net/netrom/nr_timer.c index 1cb98e88f5e1..ff2c1b142f57 100644 --- a/net/netrom/nr_timer.c +++ b/net/netrom/nr_timer.c | |||
@@ -24,7 +24,6 @@ | |||
24 | #include <net/sock.h> | 24 | #include <net/sock.h> |
25 | #include <net/tcp_states.h> | 25 | #include <net/tcp_states.h> |
26 | #include <asm/uaccess.h> | 26 | #include <asm/uaccess.h> |
27 | #include <asm/system.h> | ||
28 | #include <linux/fcntl.h> | 27 | #include <linux/fcntl.h> |
29 | #include <linux/mm.h> | 28 | #include <linux/mm.h> |
30 | #include <linux/interrupt.h> | 29 | #include <linux/interrupt.h> |
diff --git a/net/nfc/llcp/commands.c b/net/nfc/llcp/commands.c index 7b76eb7192f3..ef10ffcb4b6f 100644 --- a/net/nfc/llcp/commands.c +++ b/net/nfc/llcp/commands.c | |||
@@ -474,7 +474,7 @@ int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock, | |||
474 | 474 | ||
475 | while (remaining_len > 0) { | 475 | while (remaining_len > 0) { |
476 | 476 | ||
477 | frag_len = min_t(u16, local->remote_miu, remaining_len); | 477 | frag_len = min_t(size_t, local->remote_miu, remaining_len); |
478 | 478 | ||
479 | pr_debug("Fragment %zd bytes remaining %zd", | 479 | pr_debug("Fragment %zd bytes remaining %zd", |
480 | frag_len, remaining_len); | 480 | frag_len, remaining_len); |
@@ -497,7 +497,7 @@ int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock, | |||
497 | release_sock(sk); | 497 | release_sock(sk); |
498 | 498 | ||
499 | remaining_len -= frag_len; | 499 | remaining_len -= frag_len; |
500 | msg_ptr += len; | 500 | msg_ptr += frag_len; |
501 | } | 501 | } |
502 | 502 | ||
503 | kfree(msg_data); | 503 | kfree(msg_data); |
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index 2c030505b335..e44e631ea952 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c | |||
@@ -38,7 +38,6 @@ | |||
38 | #include <linux/udp.h> | 38 | #include <linux/udp.h> |
39 | #include <linux/ethtool.h> | 39 | #include <linux/ethtool.h> |
40 | #include <linux/wait.h> | 40 | #include <linux/wait.h> |
41 | #include <asm/system.h> | ||
42 | #include <asm/div64.h> | 41 | #include <asm/div64.h> |
43 | #include <linux/highmem.h> | 42 | #include <linux/highmem.h> |
44 | #include <linux/netfilter_bridge.h> | 43 | #include <linux/netfilter_bridge.h> |
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index ae2d484416dd..4f2c0df79563 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c | |||
@@ -73,7 +73,6 @@ | |||
73 | #include <net/sock.h> | 73 | #include <net/sock.h> |
74 | #include <linux/errno.h> | 74 | #include <linux/errno.h> |
75 | #include <linux/timer.h> | 75 | #include <linux/timer.h> |
76 | #include <asm/system.h> | ||
77 | #include <asm/uaccess.h> | 76 | #include <asm/uaccess.h> |
78 | #include <asm/ioctls.h> | 77 | #include <asm/ioctls.h> |
79 | #include <asm/page.h> | 78 | #include <asm/page.h> |
diff --git a/net/phonet/pep.c b/net/phonet/pep.c index 9f60008740e3..9726fe684ab8 100644 --- a/net/phonet/pep.c +++ b/net/phonet/pep.c | |||
@@ -1130,6 +1130,9 @@ static int pep_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
1130 | int flags = msg->msg_flags; | 1130 | int flags = msg->msg_flags; |
1131 | int err, done; | 1131 | int err, done; |
1132 | 1132 | ||
1133 | if (len > USHRT_MAX) | ||
1134 | return -EMSGSIZE; | ||
1135 | |||
1133 | if ((msg->msg_flags & ~(MSG_DONTWAIT|MSG_EOR|MSG_NOSIGNAL| | 1136 | if ((msg->msg_flags & ~(MSG_DONTWAIT|MSG_EOR|MSG_NOSIGNAL| |
1134 | MSG_CMSG_COMPAT)) || | 1137 | MSG_CMSG_COMPAT)) || |
1135 | !(msg->msg_flags & MSG_EOR)) | 1138 | !(msg->msg_flags & MSG_EOR)) |
diff --git a/net/rfkill/core.c b/net/rfkill/core.c index 354760ebbbd2..f974961754ca 100644 --- a/net/rfkill/core.c +++ b/net/rfkill/core.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/rfkill.h> | 29 | #include <linux/rfkill.h> |
30 | #include <linux/sched.h> | 30 | #include <linux/sched.h> |
31 | #include <linux/spinlock.h> | 31 | #include <linux/spinlock.h> |
32 | #include <linux/device.h> | ||
32 | #include <linux/miscdevice.h> | 33 | #include <linux/miscdevice.h> |
33 | #include <linux/wait.h> | 34 | #include <linux/wait.h> |
34 | #include <linux/poll.h> | 35 | #include <linux/poll.h> |
diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c index f9ea925ad9cb..c4719ce604c2 100644 --- a/net/rose/af_rose.c +++ b/net/rose/af_rose.c | |||
@@ -34,7 +34,6 @@ | |||
34 | #include <linux/if_arp.h> | 34 | #include <linux/if_arp.h> |
35 | #include <linux/skbuff.h> | 35 | #include <linux/skbuff.h> |
36 | #include <net/sock.h> | 36 | #include <net/sock.h> |
37 | #include <asm/system.h> | ||
38 | #include <asm/uaccess.h> | 37 | #include <asm/uaccess.h> |
39 | #include <linux/fcntl.h> | 38 | #include <linux/fcntl.h> |
40 | #include <linux/termios.h> | 39 | #include <linux/termios.h> |
diff --git a/net/rose/rose_dev.c b/net/rose/rose_dev.c index 178ff4f73c85..906cc05bba63 100644 --- a/net/rose/rose_dev.c +++ b/net/rose/rose_dev.c | |||
@@ -21,7 +21,6 @@ | |||
21 | #include <linux/if_ether.h> | 21 | #include <linux/if_ether.h> |
22 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
23 | 23 | ||
24 | #include <asm/system.h> | ||
25 | #include <asm/io.h> | 24 | #include <asm/io.h> |
26 | 25 | ||
27 | #include <linux/inet.h> | 26 | #include <linux/inet.h> |
@@ -96,11 +95,11 @@ static int rose_set_mac_address(struct net_device *dev, void *addr) | |||
96 | struct sockaddr *sa = addr; | 95 | struct sockaddr *sa = addr; |
97 | int err; | 96 | int err; |
98 | 97 | ||
99 | if (!memcpy(dev->dev_addr, sa->sa_data, dev->addr_len)) | 98 | if (!memcmp(dev->dev_addr, sa->sa_data, dev->addr_len)) |
100 | return 0; | 99 | return 0; |
101 | 100 | ||
102 | if (dev->flags & IFF_UP) { | 101 | if (dev->flags & IFF_UP) { |
103 | err = rose_add_loopback_node((rose_address *)dev->dev_addr); | 102 | err = rose_add_loopback_node((rose_address *)sa->sa_data); |
104 | if (err) | 103 | if (err) |
105 | return err; | 104 | return err; |
106 | 105 | ||
diff --git a/net/rose/rose_in.c b/net/rose/rose_in.c index 7f7fcb46b4fa..79c4abcfa6b4 100644 --- a/net/rose/rose_in.c +++ b/net/rose/rose_in.c | |||
@@ -26,7 +26,6 @@ | |||
26 | #include <linux/skbuff.h> | 26 | #include <linux/skbuff.h> |
27 | #include <net/sock.h> | 27 | #include <net/sock.h> |
28 | #include <net/tcp_states.h> | 28 | #include <net/tcp_states.h> |
29 | #include <asm/system.h> | ||
30 | #include <linux/fcntl.h> | 29 | #include <linux/fcntl.h> |
31 | #include <linux/mm.h> | 30 | #include <linux/mm.h> |
32 | #include <linux/interrupt.h> | 31 | #include <linux/interrupt.h> |
diff --git a/net/rose/rose_link.c b/net/rose/rose_link.c index 7a02bd1cc5a0..bc5514211b0c 100644 --- a/net/rose/rose_link.c +++ b/net/rose/rose_link.c | |||
@@ -22,7 +22,6 @@ | |||
22 | #include <linux/netdevice.h> | 22 | #include <linux/netdevice.h> |
23 | #include <linux/skbuff.h> | 23 | #include <linux/skbuff.h> |
24 | #include <net/sock.h> | 24 | #include <net/sock.h> |
25 | #include <asm/system.h> | ||
26 | #include <linux/fcntl.h> | 25 | #include <linux/fcntl.h> |
27 | #include <linux/mm.h> | 26 | #include <linux/mm.h> |
28 | #include <linux/interrupt.h> | 27 | #include <linux/interrupt.h> |
diff --git a/net/rose/rose_out.c b/net/rose/rose_out.c index 4ebf33afbe47..9ad98b524646 100644 --- a/net/rose/rose_out.c +++ b/net/rose/rose_out.c | |||
@@ -21,7 +21,6 @@ | |||
21 | #include <linux/netdevice.h> | 21 | #include <linux/netdevice.h> |
22 | #include <linux/skbuff.h> | 22 | #include <linux/skbuff.h> |
23 | #include <net/sock.h> | 23 | #include <net/sock.h> |
24 | #include <asm/system.h> | ||
25 | #include <linux/fcntl.h> | 24 | #include <linux/fcntl.h> |
26 | #include <linux/mm.h> | 25 | #include <linux/mm.h> |
27 | #include <linux/interrupt.h> | 26 | #include <linux/interrupt.h> |
diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c index cd9b7ee60f3e..40148932c8a4 100644 --- a/net/rose/rose_route.c +++ b/net/rose/rose_route.c | |||
@@ -25,7 +25,6 @@ | |||
25 | #include <linux/skbuff.h> | 25 | #include <linux/skbuff.h> |
26 | #include <net/sock.h> | 26 | #include <net/sock.h> |
27 | #include <net/tcp_states.h> | 27 | #include <net/tcp_states.h> |
28 | #include <asm/system.h> | ||
29 | #include <asm/uaccess.h> | 28 | #include <asm/uaccess.h> |
30 | #include <linux/fcntl.h> | 29 | #include <linux/fcntl.h> |
31 | #include <linux/termios.h> /* For TIOCINQ/OUTQ */ | 30 | #include <linux/termios.h> /* For TIOCINQ/OUTQ */ |
diff --git a/net/rose/rose_subr.c b/net/rose/rose_subr.c index f6c71caa94b9..47f1fdb346b0 100644 --- a/net/rose/rose_subr.c +++ b/net/rose/rose_subr.c | |||
@@ -22,7 +22,6 @@ | |||
22 | #include <linux/skbuff.h> | 22 | #include <linux/skbuff.h> |
23 | #include <net/sock.h> | 23 | #include <net/sock.h> |
24 | #include <net/tcp_states.h> | 24 | #include <net/tcp_states.h> |
25 | #include <asm/system.h> | ||
26 | #include <linux/fcntl.h> | 25 | #include <linux/fcntl.h> |
27 | #include <linux/mm.h> | 26 | #include <linux/mm.h> |
28 | #include <linux/interrupt.h> | 27 | #include <linux/interrupt.h> |
diff --git a/net/rose/rose_timer.c b/net/rose/rose_timer.c index b6c8f38cc26c..bc5469d6d9cb 100644 --- a/net/rose/rose_timer.c +++ b/net/rose/rose_timer.c | |||
@@ -23,7 +23,6 @@ | |||
23 | #include <linux/skbuff.h> | 23 | #include <linux/skbuff.h> |
24 | #include <net/sock.h> | 24 | #include <net/sock.h> |
25 | #include <net/tcp_states.h> | 25 | #include <net/tcp_states.h> |
26 | #include <asm/system.h> | ||
27 | #include <linux/fcntl.h> | 26 | #include <linux/fcntl.h> |
28 | #include <linux/mm.h> | 27 | #include <linux/mm.h> |
29 | #include <linux/interrupt.h> | 28 | #include <linux/interrupt.h> |
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 06b42b7f5a02..92ba71dfe080 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -4133,9 +4133,10 @@ static int sctp_getsockopt_disable_fragments(struct sock *sk, int len, | |||
4133 | static int sctp_getsockopt_events(struct sock *sk, int len, char __user *optval, | 4133 | static int sctp_getsockopt_events(struct sock *sk, int len, char __user *optval, |
4134 | int __user *optlen) | 4134 | int __user *optlen) |
4135 | { | 4135 | { |
4136 | if (len < sizeof(struct sctp_event_subscribe)) | 4136 | if (len <= 0) |
4137 | return -EINVAL; | 4137 | return -EINVAL; |
4138 | len = sizeof(struct sctp_event_subscribe); | 4138 | if (len > sizeof(struct sctp_event_subscribe)) |
4139 | len = sizeof(struct sctp_event_subscribe); | ||
4139 | if (put_user(len, optlen)) | 4140 | if (put_user(len, optlen)) |
4140 | return -EFAULT; | 4141 | return -EFAULT; |
4141 | if (copy_to_user(optval, &sctp_sk(sk)->subscribe, len)) | 4142 | if (copy_to_user(optval, &sctp_sk(sk)->subscribe, len)) |
diff --git a/net/socket.c b/net/socket.c index 12a48d846223..851edcd6b098 100644 --- a/net/socket.c +++ b/net/socket.c | |||
@@ -811,9 +811,9 @@ static ssize_t sock_sendpage(struct file *file, struct page *page, | |||
811 | 811 | ||
812 | sock = file->private_data; | 812 | sock = file->private_data; |
813 | 813 | ||
814 | flags = !(file->f_flags & O_NONBLOCK) ? 0 : MSG_DONTWAIT; | 814 | flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0; |
815 | if (more) | 815 | /* more is a combination of MSG_MORE and MSG_SENDPAGE_NOTLAST */ |
816 | flags |= MSG_MORE; | 816 | flags |= more; |
817 | 817 | ||
818 | return kernel_sendpage(sock, page, offset, size, flags); | 818 | return kernel_sendpage(sock, page, offset, size, flags); |
819 | } | 819 | } |
@@ -2592,7 +2592,7 @@ void socket_seq_show(struct seq_file *seq) | |||
2592 | 2592 | ||
2593 | #ifdef CONFIG_COMPAT | 2593 | #ifdef CONFIG_COMPAT |
2594 | static int do_siocgstamp(struct net *net, struct socket *sock, | 2594 | static int do_siocgstamp(struct net *net, struct socket *sock, |
2595 | unsigned int cmd, struct compat_timeval __user *up) | 2595 | unsigned int cmd, void __user *up) |
2596 | { | 2596 | { |
2597 | mm_segment_t old_fs = get_fs(); | 2597 | mm_segment_t old_fs = get_fs(); |
2598 | struct timeval ktv; | 2598 | struct timeval ktv; |
@@ -2601,15 +2601,14 @@ static int do_siocgstamp(struct net *net, struct socket *sock, | |||
2601 | set_fs(KERNEL_DS); | 2601 | set_fs(KERNEL_DS); |
2602 | err = sock_do_ioctl(net, sock, cmd, (unsigned long)&ktv); | 2602 | err = sock_do_ioctl(net, sock, cmd, (unsigned long)&ktv); |
2603 | set_fs(old_fs); | 2603 | set_fs(old_fs); |
2604 | if (!err) { | 2604 | if (!err) |
2605 | err = put_user(ktv.tv_sec, &up->tv_sec); | 2605 | err = compat_put_timeval(up, &ktv); |
2606 | err |= __put_user(ktv.tv_usec, &up->tv_usec); | 2606 | |
2607 | } | ||
2608 | return err; | 2607 | return err; |
2609 | } | 2608 | } |
2610 | 2609 | ||
2611 | static int do_siocgstampns(struct net *net, struct socket *sock, | 2610 | static int do_siocgstampns(struct net *net, struct socket *sock, |
2612 | unsigned int cmd, struct compat_timespec __user *up) | 2611 | unsigned int cmd, void __user *up) |
2613 | { | 2612 | { |
2614 | mm_segment_t old_fs = get_fs(); | 2613 | mm_segment_t old_fs = get_fs(); |
2615 | struct timespec kts; | 2614 | struct timespec kts; |
@@ -2618,10 +2617,9 @@ static int do_siocgstampns(struct net *net, struct socket *sock, | |||
2618 | set_fs(KERNEL_DS); | 2617 | set_fs(KERNEL_DS); |
2619 | err = sock_do_ioctl(net, sock, cmd, (unsigned long)&kts); | 2618 | err = sock_do_ioctl(net, sock, cmd, (unsigned long)&kts); |
2620 | set_fs(old_fs); | 2619 | set_fs(old_fs); |
2621 | if (!err) { | 2620 | if (!err) |
2622 | err = put_user(kts.tv_sec, &up->tv_sec); | 2621 | err = compat_put_timespec(up, &kts); |
2623 | err |= __put_user(kts.tv_nsec, &up->tv_nsec); | 2622 | |
2624 | } | ||
2625 | return err; | 2623 | return err; |
2626 | } | 2624 | } |
2627 | 2625 | ||
diff --git a/net/sunrpc/Kconfig b/net/sunrpc/Kconfig index ffd243d09188..9fe8857d8d59 100644 --- a/net/sunrpc/Kconfig +++ b/net/sunrpc/Kconfig | |||
@@ -39,3 +39,16 @@ config RPCSEC_GSS_KRB5 | |||
39 | Kerberos support should be installed. | 39 | Kerberos support should be installed. |
40 | 40 | ||
41 | If unsure, say Y. | 41 | If unsure, say Y. |
42 | |||
43 | config SUNRPC_DEBUG | ||
44 | bool "RPC: Enable dprintk debugging" | ||
45 | depends on SUNRPC && SYSCTL | ||
46 | help | ||
47 | This option enables a sysctl-based debugging interface | ||
48 | that is be used by the 'rpcdebug' utility to turn on or off | ||
49 | logging of different aspects of the kernel RPC activity. | ||
50 | |||
51 | Disabling this option will make your kernel slightly smaller, | ||
52 | but makes troubleshooting NFS issues significantly harder. | ||
53 | |||
54 | If unsure, say Y. | ||
diff --git a/net/sunrpc/addr.c b/net/sunrpc/addr.c index ee77742e0ed6..d11418f97f1f 100644 --- a/net/sunrpc/addr.c +++ b/net/sunrpc/addr.c | |||
@@ -156,8 +156,9 @@ static size_t rpc_pton4(const char *buf, const size_t buflen, | |||
156 | } | 156 | } |
157 | 157 | ||
158 | #if IS_ENABLED(CONFIG_IPV6) | 158 | #if IS_ENABLED(CONFIG_IPV6) |
159 | static int rpc_parse_scope_id(const char *buf, const size_t buflen, | 159 | static int rpc_parse_scope_id(struct net *net, const char *buf, |
160 | const char *delim, struct sockaddr_in6 *sin6) | 160 | const size_t buflen, const char *delim, |
161 | struct sockaddr_in6 *sin6) | ||
161 | { | 162 | { |
162 | char *p; | 163 | char *p; |
163 | size_t len; | 164 | size_t len; |
@@ -177,7 +178,7 @@ static int rpc_parse_scope_id(const char *buf, const size_t buflen, | |||
177 | unsigned long scope_id = 0; | 178 | unsigned long scope_id = 0; |
178 | struct net_device *dev; | 179 | struct net_device *dev; |
179 | 180 | ||
180 | dev = dev_get_by_name(&init_net, p); | 181 | dev = dev_get_by_name(net, p); |
181 | if (dev != NULL) { | 182 | if (dev != NULL) { |
182 | scope_id = dev->ifindex; | 183 | scope_id = dev->ifindex; |
183 | dev_put(dev); | 184 | dev_put(dev); |
@@ -197,7 +198,7 @@ static int rpc_parse_scope_id(const char *buf, const size_t buflen, | |||
197 | return 0; | 198 | return 0; |
198 | } | 199 | } |
199 | 200 | ||
200 | static size_t rpc_pton6(const char *buf, const size_t buflen, | 201 | static size_t rpc_pton6(struct net *net, const char *buf, const size_t buflen, |
201 | struct sockaddr *sap, const size_t salen) | 202 | struct sockaddr *sap, const size_t salen) |
202 | { | 203 | { |
203 | struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap; | 204 | struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap; |
@@ -213,14 +214,14 @@ static size_t rpc_pton6(const char *buf, const size_t buflen, | |||
213 | if (in6_pton(buf, buflen, addr, IPV6_SCOPE_DELIMITER, &delim) == 0) | 214 | if (in6_pton(buf, buflen, addr, IPV6_SCOPE_DELIMITER, &delim) == 0) |
214 | return 0; | 215 | return 0; |
215 | 216 | ||
216 | if (!rpc_parse_scope_id(buf, buflen, delim, sin6)) | 217 | if (!rpc_parse_scope_id(net, buf, buflen, delim, sin6)) |
217 | return 0; | 218 | return 0; |
218 | 219 | ||
219 | sin6->sin6_family = AF_INET6; | 220 | sin6->sin6_family = AF_INET6; |
220 | return sizeof(struct sockaddr_in6); | 221 | return sizeof(struct sockaddr_in6); |
221 | } | 222 | } |
222 | #else | 223 | #else |
223 | static size_t rpc_pton6(const char *buf, const size_t buflen, | 224 | static size_t rpc_pton6(struct net *net, const char *buf, const size_t buflen, |
224 | struct sockaddr *sap, const size_t salen) | 225 | struct sockaddr *sap, const size_t salen) |
225 | { | 226 | { |
226 | return 0; | 227 | return 0; |
@@ -229,6 +230,7 @@ static size_t rpc_pton6(const char *buf, const size_t buflen, | |||
229 | 230 | ||
230 | /** | 231 | /** |
231 | * rpc_pton - Construct a sockaddr in @sap | 232 | * rpc_pton - Construct a sockaddr in @sap |
233 | * @net: applicable network namespace | ||
232 | * @buf: C string containing presentation format IP address | 234 | * @buf: C string containing presentation format IP address |
233 | * @buflen: length of presentation address in bytes | 235 | * @buflen: length of presentation address in bytes |
234 | * @sap: buffer into which to plant socket address | 236 | * @sap: buffer into which to plant socket address |
@@ -241,14 +243,14 @@ static size_t rpc_pton6(const char *buf, const size_t buflen, | |||
241 | * socket address, if successful. Returns zero if an error | 243 | * socket address, if successful. Returns zero if an error |
242 | * occurred. | 244 | * occurred. |
243 | */ | 245 | */ |
244 | size_t rpc_pton(const char *buf, const size_t buflen, | 246 | size_t rpc_pton(struct net *net, const char *buf, const size_t buflen, |
245 | struct sockaddr *sap, const size_t salen) | 247 | struct sockaddr *sap, const size_t salen) |
246 | { | 248 | { |
247 | unsigned int i; | 249 | unsigned int i; |
248 | 250 | ||
249 | for (i = 0; i < buflen; i++) | 251 | for (i = 0; i < buflen; i++) |
250 | if (buf[i] == ':') | 252 | if (buf[i] == ':') |
251 | return rpc_pton6(buf, buflen, sap, salen); | 253 | return rpc_pton6(net, buf, buflen, sap, salen); |
252 | return rpc_pton4(buf, buflen, sap, salen); | 254 | return rpc_pton4(buf, buflen, sap, salen); |
253 | } | 255 | } |
254 | EXPORT_SYMBOL_GPL(rpc_pton); | 256 | EXPORT_SYMBOL_GPL(rpc_pton); |
@@ -295,6 +297,7 @@ char *rpc_sockaddr2uaddr(const struct sockaddr *sap, gfp_t gfp_flags) | |||
295 | 297 | ||
296 | /** | 298 | /** |
297 | * rpc_uaddr2sockaddr - convert a universal address to a socket address. | 299 | * rpc_uaddr2sockaddr - convert a universal address to a socket address. |
300 | * @net: applicable network namespace | ||
298 | * @uaddr: C string containing universal address to convert | 301 | * @uaddr: C string containing universal address to convert |
299 | * @uaddr_len: length of universal address string | 302 | * @uaddr_len: length of universal address string |
300 | * @sap: buffer into which to plant socket address | 303 | * @sap: buffer into which to plant socket address |
@@ -306,8 +309,9 @@ char *rpc_sockaddr2uaddr(const struct sockaddr *sap, gfp_t gfp_flags) | |||
306 | * Returns the size of the socket address if successful; otherwise | 309 | * Returns the size of the socket address if successful; otherwise |
307 | * zero is returned. | 310 | * zero is returned. |
308 | */ | 311 | */ |
309 | size_t rpc_uaddr2sockaddr(const char *uaddr, const size_t uaddr_len, | 312 | size_t rpc_uaddr2sockaddr(struct net *net, const char *uaddr, |
310 | struct sockaddr *sap, const size_t salen) | 313 | const size_t uaddr_len, struct sockaddr *sap, |
314 | const size_t salen) | ||
311 | { | 315 | { |
312 | char *c, buf[RPCBIND_MAXUADDRLEN + sizeof('\0')]; | 316 | char *c, buf[RPCBIND_MAXUADDRLEN + sizeof('\0')]; |
313 | unsigned long portlo, porthi; | 317 | unsigned long portlo, porthi; |
@@ -339,7 +343,7 @@ size_t rpc_uaddr2sockaddr(const char *uaddr, const size_t uaddr_len, | |||
339 | port = (unsigned short)((porthi << 8) | portlo); | 343 | port = (unsigned short)((porthi << 8) | portlo); |
340 | 344 | ||
341 | *c = '\0'; | 345 | *c = '\0'; |
342 | if (rpc_pton(buf, strlen(buf), sap, salen) == 0) | 346 | if (rpc_pton(net, buf, strlen(buf), sap, salen) == 0) |
343 | return 0; | 347 | return 0; |
344 | 348 | ||
345 | switch (sap->sa_family) { | 349 | switch (sap->sa_family) { |
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index affa631ac1ab..d3ad81f8da5b 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c | |||
@@ -81,7 +81,7 @@ struct gss_auth { | |||
81 | * mechanism (for example, "krb5") and exists for | 81 | * mechanism (for example, "krb5") and exists for |
82 | * backwards-compatibility with older gssd's. | 82 | * backwards-compatibility with older gssd's. |
83 | */ | 83 | */ |
84 | struct dentry *dentry[2]; | 84 | struct rpc_pipe *pipe[2]; |
85 | }; | 85 | }; |
86 | 86 | ||
87 | /* pipe_version >= 0 if and only if someone has a pipe open. */ | 87 | /* pipe_version >= 0 if and only if someone has a pipe open. */ |
@@ -112,7 +112,7 @@ gss_put_ctx(struct gss_cl_ctx *ctx) | |||
112 | /* gss_cred_set_ctx: | 112 | /* gss_cred_set_ctx: |
113 | * called by gss_upcall_callback and gss_create_upcall in order | 113 | * called by gss_upcall_callback and gss_create_upcall in order |
114 | * to set the gss context. The actual exchange of an old context | 114 | * to set the gss context. The actual exchange of an old context |
115 | * and a new one is protected by the inode->i_lock. | 115 | * and a new one is protected by the pipe->lock. |
116 | */ | 116 | */ |
117 | static void | 117 | static void |
118 | gss_cred_set_ctx(struct rpc_cred *cred, struct gss_cl_ctx *ctx) | 118 | gss_cred_set_ctx(struct rpc_cred *cred, struct gss_cl_ctx *ctx) |
@@ -251,7 +251,7 @@ struct gss_upcall_msg { | |||
251 | struct rpc_pipe_msg msg; | 251 | struct rpc_pipe_msg msg; |
252 | struct list_head list; | 252 | struct list_head list; |
253 | struct gss_auth *auth; | 253 | struct gss_auth *auth; |
254 | struct rpc_inode *inode; | 254 | struct rpc_pipe *pipe; |
255 | struct rpc_wait_queue rpc_waitqueue; | 255 | struct rpc_wait_queue rpc_waitqueue; |
256 | wait_queue_head_t waitqueue; | 256 | wait_queue_head_t waitqueue; |
257 | struct gss_cl_ctx *ctx; | 257 | struct gss_cl_ctx *ctx; |
@@ -294,10 +294,10 @@ gss_release_msg(struct gss_upcall_msg *gss_msg) | |||
294 | } | 294 | } |
295 | 295 | ||
296 | static struct gss_upcall_msg * | 296 | static struct gss_upcall_msg * |
297 | __gss_find_upcall(struct rpc_inode *rpci, uid_t uid) | 297 | __gss_find_upcall(struct rpc_pipe *pipe, uid_t uid) |
298 | { | 298 | { |
299 | struct gss_upcall_msg *pos; | 299 | struct gss_upcall_msg *pos; |
300 | list_for_each_entry(pos, &rpci->in_downcall, list) { | 300 | list_for_each_entry(pos, &pipe->in_downcall, list) { |
301 | if (pos->uid != uid) | 301 | if (pos->uid != uid) |
302 | continue; | 302 | continue; |
303 | atomic_inc(&pos->count); | 303 | atomic_inc(&pos->count); |
@@ -315,18 +315,17 @@ __gss_find_upcall(struct rpc_inode *rpci, uid_t uid) | |||
315 | static inline struct gss_upcall_msg * | 315 | static inline struct gss_upcall_msg * |
316 | gss_add_msg(struct gss_upcall_msg *gss_msg) | 316 | gss_add_msg(struct gss_upcall_msg *gss_msg) |
317 | { | 317 | { |
318 | struct rpc_inode *rpci = gss_msg->inode; | 318 | struct rpc_pipe *pipe = gss_msg->pipe; |
319 | struct inode *inode = &rpci->vfs_inode; | ||
320 | struct gss_upcall_msg *old; | 319 | struct gss_upcall_msg *old; |
321 | 320 | ||
322 | spin_lock(&inode->i_lock); | 321 | spin_lock(&pipe->lock); |
323 | old = __gss_find_upcall(rpci, gss_msg->uid); | 322 | old = __gss_find_upcall(pipe, gss_msg->uid); |
324 | if (old == NULL) { | 323 | if (old == NULL) { |
325 | atomic_inc(&gss_msg->count); | 324 | atomic_inc(&gss_msg->count); |
326 | list_add(&gss_msg->list, &rpci->in_downcall); | 325 | list_add(&gss_msg->list, &pipe->in_downcall); |
327 | } else | 326 | } else |
328 | gss_msg = old; | 327 | gss_msg = old; |
329 | spin_unlock(&inode->i_lock); | 328 | spin_unlock(&pipe->lock); |
330 | return gss_msg; | 329 | return gss_msg; |
331 | } | 330 | } |
332 | 331 | ||
@@ -342,14 +341,14 @@ __gss_unhash_msg(struct gss_upcall_msg *gss_msg) | |||
342 | static void | 341 | static void |
343 | gss_unhash_msg(struct gss_upcall_msg *gss_msg) | 342 | gss_unhash_msg(struct gss_upcall_msg *gss_msg) |
344 | { | 343 | { |
345 | struct inode *inode = &gss_msg->inode->vfs_inode; | 344 | struct rpc_pipe *pipe = gss_msg->pipe; |
346 | 345 | ||
347 | if (list_empty(&gss_msg->list)) | 346 | if (list_empty(&gss_msg->list)) |
348 | return; | 347 | return; |
349 | spin_lock(&inode->i_lock); | 348 | spin_lock(&pipe->lock); |
350 | if (!list_empty(&gss_msg->list)) | 349 | if (!list_empty(&gss_msg->list)) |
351 | __gss_unhash_msg(gss_msg); | 350 | __gss_unhash_msg(gss_msg); |
352 | spin_unlock(&inode->i_lock); | 351 | spin_unlock(&pipe->lock); |
353 | } | 352 | } |
354 | 353 | ||
355 | static void | 354 | static void |
@@ -376,11 +375,11 @@ gss_upcall_callback(struct rpc_task *task) | |||
376 | struct gss_cred *gss_cred = container_of(task->tk_rqstp->rq_cred, | 375 | struct gss_cred *gss_cred = container_of(task->tk_rqstp->rq_cred, |
377 | struct gss_cred, gc_base); | 376 | struct gss_cred, gc_base); |
378 | struct gss_upcall_msg *gss_msg = gss_cred->gc_upcall; | 377 | struct gss_upcall_msg *gss_msg = gss_cred->gc_upcall; |
379 | struct inode *inode = &gss_msg->inode->vfs_inode; | 378 | struct rpc_pipe *pipe = gss_msg->pipe; |
380 | 379 | ||
381 | spin_lock(&inode->i_lock); | 380 | spin_lock(&pipe->lock); |
382 | gss_handle_downcall_result(gss_cred, gss_msg); | 381 | gss_handle_downcall_result(gss_cred, gss_msg); |
383 | spin_unlock(&inode->i_lock); | 382 | spin_unlock(&pipe->lock); |
384 | task->tk_status = gss_msg->msg.errno; | 383 | task->tk_status = gss_msg->msg.errno; |
385 | gss_release_msg(gss_msg); | 384 | gss_release_msg(gss_msg); |
386 | } | 385 | } |
@@ -450,7 +449,7 @@ gss_alloc_msg(struct gss_auth *gss_auth, struct rpc_clnt *clnt, | |||
450 | kfree(gss_msg); | 449 | kfree(gss_msg); |
451 | return ERR_PTR(vers); | 450 | return ERR_PTR(vers); |
452 | } | 451 | } |
453 | gss_msg->inode = RPC_I(gss_auth->dentry[vers]->d_inode); | 452 | gss_msg->pipe = gss_auth->pipe[vers]; |
454 | INIT_LIST_HEAD(&gss_msg->list); | 453 | INIT_LIST_HEAD(&gss_msg->list); |
455 | rpc_init_wait_queue(&gss_msg->rpc_waitqueue, "RPCSEC_GSS upcall waitq"); | 454 | rpc_init_wait_queue(&gss_msg->rpc_waitqueue, "RPCSEC_GSS upcall waitq"); |
456 | init_waitqueue_head(&gss_msg->waitqueue); | 455 | init_waitqueue_head(&gss_msg->waitqueue); |
@@ -474,8 +473,7 @@ gss_setup_upcall(struct rpc_clnt *clnt, struct gss_auth *gss_auth, struct rpc_cr | |||
474 | return gss_new; | 473 | return gss_new; |
475 | gss_msg = gss_add_msg(gss_new); | 474 | gss_msg = gss_add_msg(gss_new); |
476 | if (gss_msg == gss_new) { | 475 | if (gss_msg == gss_new) { |
477 | struct inode *inode = &gss_new->inode->vfs_inode; | 476 | int res = rpc_queue_upcall(gss_new->pipe, &gss_new->msg); |
478 | int res = rpc_queue_upcall(inode, &gss_new->msg); | ||
479 | if (res) { | 477 | if (res) { |
480 | gss_unhash_msg(gss_new); | 478 | gss_unhash_msg(gss_new); |
481 | gss_msg = ERR_PTR(res); | 479 | gss_msg = ERR_PTR(res); |
@@ -506,7 +504,7 @@ gss_refresh_upcall(struct rpc_task *task) | |||
506 | struct gss_cred *gss_cred = container_of(cred, | 504 | struct gss_cred *gss_cred = container_of(cred, |
507 | struct gss_cred, gc_base); | 505 | struct gss_cred, gc_base); |
508 | struct gss_upcall_msg *gss_msg; | 506 | struct gss_upcall_msg *gss_msg; |
509 | struct inode *inode; | 507 | struct rpc_pipe *pipe; |
510 | int err = 0; | 508 | int err = 0; |
511 | 509 | ||
512 | dprintk("RPC: %5u gss_refresh_upcall for uid %u\n", task->tk_pid, | 510 | dprintk("RPC: %5u gss_refresh_upcall for uid %u\n", task->tk_pid, |
@@ -524,8 +522,8 @@ gss_refresh_upcall(struct rpc_task *task) | |||
524 | err = PTR_ERR(gss_msg); | 522 | err = PTR_ERR(gss_msg); |
525 | goto out; | 523 | goto out; |
526 | } | 524 | } |
527 | inode = &gss_msg->inode->vfs_inode; | 525 | pipe = gss_msg->pipe; |
528 | spin_lock(&inode->i_lock); | 526 | spin_lock(&pipe->lock); |
529 | if (gss_cred->gc_upcall != NULL) | 527 | if (gss_cred->gc_upcall != NULL) |
530 | rpc_sleep_on(&gss_cred->gc_upcall->rpc_waitqueue, task, NULL); | 528 | rpc_sleep_on(&gss_cred->gc_upcall->rpc_waitqueue, task, NULL); |
531 | else if (gss_msg->ctx == NULL && gss_msg->msg.errno >= 0) { | 529 | else if (gss_msg->ctx == NULL && gss_msg->msg.errno >= 0) { |
@@ -538,7 +536,7 @@ gss_refresh_upcall(struct rpc_task *task) | |||
538 | gss_handle_downcall_result(gss_cred, gss_msg); | 536 | gss_handle_downcall_result(gss_cred, gss_msg); |
539 | err = gss_msg->msg.errno; | 537 | err = gss_msg->msg.errno; |
540 | } | 538 | } |
541 | spin_unlock(&inode->i_lock); | 539 | spin_unlock(&pipe->lock); |
542 | gss_release_msg(gss_msg); | 540 | gss_release_msg(gss_msg); |
543 | out: | 541 | out: |
544 | dprintk("RPC: %5u gss_refresh_upcall for uid %u result %d\n", | 542 | dprintk("RPC: %5u gss_refresh_upcall for uid %u result %d\n", |
@@ -549,7 +547,7 @@ out: | |||
549 | static inline int | 547 | static inline int |
550 | gss_create_upcall(struct gss_auth *gss_auth, struct gss_cred *gss_cred) | 548 | gss_create_upcall(struct gss_auth *gss_auth, struct gss_cred *gss_cred) |
551 | { | 549 | { |
552 | struct inode *inode; | 550 | struct rpc_pipe *pipe; |
553 | struct rpc_cred *cred = &gss_cred->gc_base; | 551 | struct rpc_cred *cred = &gss_cred->gc_base; |
554 | struct gss_upcall_msg *gss_msg; | 552 | struct gss_upcall_msg *gss_msg; |
555 | DEFINE_WAIT(wait); | 553 | DEFINE_WAIT(wait); |
@@ -573,14 +571,14 @@ retry: | |||
573 | err = PTR_ERR(gss_msg); | 571 | err = PTR_ERR(gss_msg); |
574 | goto out; | 572 | goto out; |
575 | } | 573 | } |
576 | inode = &gss_msg->inode->vfs_inode; | 574 | pipe = gss_msg->pipe; |
577 | for (;;) { | 575 | for (;;) { |
578 | prepare_to_wait(&gss_msg->waitqueue, &wait, TASK_KILLABLE); | 576 | prepare_to_wait(&gss_msg->waitqueue, &wait, TASK_KILLABLE); |
579 | spin_lock(&inode->i_lock); | 577 | spin_lock(&pipe->lock); |
580 | if (gss_msg->ctx != NULL || gss_msg->msg.errno < 0) { | 578 | if (gss_msg->ctx != NULL || gss_msg->msg.errno < 0) { |
581 | break; | 579 | break; |
582 | } | 580 | } |
583 | spin_unlock(&inode->i_lock); | 581 | spin_unlock(&pipe->lock); |
584 | if (fatal_signal_pending(current)) { | 582 | if (fatal_signal_pending(current)) { |
585 | err = -ERESTARTSYS; | 583 | err = -ERESTARTSYS; |
586 | goto out_intr; | 584 | goto out_intr; |
@@ -591,7 +589,7 @@ retry: | |||
591 | gss_cred_set_ctx(cred, gss_msg->ctx); | 589 | gss_cred_set_ctx(cred, gss_msg->ctx); |
592 | else | 590 | else |
593 | err = gss_msg->msg.errno; | 591 | err = gss_msg->msg.errno; |
594 | spin_unlock(&inode->i_lock); | 592 | spin_unlock(&pipe->lock); |
595 | out_intr: | 593 | out_intr: |
596 | finish_wait(&gss_msg->waitqueue, &wait); | 594 | finish_wait(&gss_msg->waitqueue, &wait); |
597 | gss_release_msg(gss_msg); | 595 | gss_release_msg(gss_msg); |
@@ -609,7 +607,7 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen) | |||
609 | const void *p, *end; | 607 | const void *p, *end; |
610 | void *buf; | 608 | void *buf; |
611 | struct gss_upcall_msg *gss_msg; | 609 | struct gss_upcall_msg *gss_msg; |
612 | struct inode *inode = filp->f_path.dentry->d_inode; | 610 | struct rpc_pipe *pipe = RPC_I(filp->f_dentry->d_inode)->pipe; |
613 | struct gss_cl_ctx *ctx; | 611 | struct gss_cl_ctx *ctx; |
614 | uid_t uid; | 612 | uid_t uid; |
615 | ssize_t err = -EFBIG; | 613 | ssize_t err = -EFBIG; |
@@ -639,14 +637,14 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen) | |||
639 | 637 | ||
640 | err = -ENOENT; | 638 | err = -ENOENT; |
641 | /* Find a matching upcall */ | 639 | /* Find a matching upcall */ |
642 | spin_lock(&inode->i_lock); | 640 | spin_lock(&pipe->lock); |
643 | gss_msg = __gss_find_upcall(RPC_I(inode), uid); | 641 | gss_msg = __gss_find_upcall(pipe, uid); |
644 | if (gss_msg == NULL) { | 642 | if (gss_msg == NULL) { |
645 | spin_unlock(&inode->i_lock); | 643 | spin_unlock(&pipe->lock); |
646 | goto err_put_ctx; | 644 | goto err_put_ctx; |
647 | } | 645 | } |
648 | list_del_init(&gss_msg->list); | 646 | list_del_init(&gss_msg->list); |
649 | spin_unlock(&inode->i_lock); | 647 | spin_unlock(&pipe->lock); |
650 | 648 | ||
651 | p = gss_fill_context(p, end, ctx, gss_msg->auth->mech); | 649 | p = gss_fill_context(p, end, ctx, gss_msg->auth->mech); |
652 | if (IS_ERR(p)) { | 650 | if (IS_ERR(p)) { |
@@ -674,9 +672,9 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen) | |||
674 | err = mlen; | 672 | err = mlen; |
675 | 673 | ||
676 | err_release_msg: | 674 | err_release_msg: |
677 | spin_lock(&inode->i_lock); | 675 | spin_lock(&pipe->lock); |
678 | __gss_unhash_msg(gss_msg); | 676 | __gss_unhash_msg(gss_msg); |
679 | spin_unlock(&inode->i_lock); | 677 | spin_unlock(&pipe->lock); |
680 | gss_release_msg(gss_msg); | 678 | gss_release_msg(gss_msg); |
681 | err_put_ctx: | 679 | err_put_ctx: |
682 | gss_put_ctx(ctx); | 680 | gss_put_ctx(ctx); |
@@ -722,23 +720,23 @@ static int gss_pipe_open_v1(struct inode *inode) | |||
722 | static void | 720 | static void |
723 | gss_pipe_release(struct inode *inode) | 721 | gss_pipe_release(struct inode *inode) |
724 | { | 722 | { |
725 | struct rpc_inode *rpci = RPC_I(inode); | 723 | struct rpc_pipe *pipe = RPC_I(inode)->pipe; |
726 | struct gss_upcall_msg *gss_msg; | 724 | struct gss_upcall_msg *gss_msg; |
727 | 725 | ||
728 | restart: | 726 | restart: |
729 | spin_lock(&inode->i_lock); | 727 | spin_lock(&pipe->lock); |
730 | list_for_each_entry(gss_msg, &rpci->in_downcall, list) { | 728 | list_for_each_entry(gss_msg, &pipe->in_downcall, list) { |
731 | 729 | ||
732 | if (!list_empty(&gss_msg->msg.list)) | 730 | if (!list_empty(&gss_msg->msg.list)) |
733 | continue; | 731 | continue; |
734 | gss_msg->msg.errno = -EPIPE; | 732 | gss_msg->msg.errno = -EPIPE; |
735 | atomic_inc(&gss_msg->count); | 733 | atomic_inc(&gss_msg->count); |
736 | __gss_unhash_msg(gss_msg); | 734 | __gss_unhash_msg(gss_msg); |
737 | spin_unlock(&inode->i_lock); | 735 | spin_unlock(&pipe->lock); |
738 | gss_release_msg(gss_msg); | 736 | gss_release_msg(gss_msg); |
739 | goto restart; | 737 | goto restart; |
740 | } | 738 | } |
741 | spin_unlock(&inode->i_lock); | 739 | spin_unlock(&pipe->lock); |
742 | 740 | ||
743 | put_pipe_version(); | 741 | put_pipe_version(); |
744 | } | 742 | } |
@@ -759,6 +757,75 @@ gss_pipe_destroy_msg(struct rpc_pipe_msg *msg) | |||
759 | } | 757 | } |
760 | } | 758 | } |
761 | 759 | ||
760 | static void gss_pipes_dentries_destroy(struct rpc_auth *auth) | ||
761 | { | ||
762 | struct gss_auth *gss_auth; | ||
763 | |||
764 | gss_auth = container_of(auth, struct gss_auth, rpc_auth); | ||
765 | if (gss_auth->pipe[0]->dentry) | ||
766 | rpc_unlink(gss_auth->pipe[0]->dentry); | ||
767 | if (gss_auth->pipe[1]->dentry) | ||
768 | rpc_unlink(gss_auth->pipe[1]->dentry); | ||
769 | } | ||
770 | |||
771 | static int gss_pipes_dentries_create(struct rpc_auth *auth) | ||
772 | { | ||
773 | int err; | ||
774 | struct gss_auth *gss_auth; | ||
775 | struct rpc_clnt *clnt; | ||
776 | |||
777 | gss_auth = container_of(auth, struct gss_auth, rpc_auth); | ||
778 | clnt = gss_auth->client; | ||
779 | |||
780 | gss_auth->pipe[1]->dentry = rpc_mkpipe_dentry(clnt->cl_dentry, | ||
781 | "gssd", | ||
782 | clnt, gss_auth->pipe[1]); | ||
783 | if (IS_ERR(gss_auth->pipe[1]->dentry)) | ||
784 | return PTR_ERR(gss_auth->pipe[1]->dentry); | ||
785 | gss_auth->pipe[0]->dentry = rpc_mkpipe_dentry(clnt->cl_dentry, | ||
786 | gss_auth->mech->gm_name, | ||
787 | clnt, gss_auth->pipe[0]); | ||
788 | if (IS_ERR(gss_auth->pipe[0]->dentry)) { | ||
789 | err = PTR_ERR(gss_auth->pipe[0]->dentry); | ||
790 | goto err_unlink_pipe_1; | ||
791 | } | ||
792 | return 0; | ||
793 | |||
794 | err_unlink_pipe_1: | ||
795 | rpc_unlink(gss_auth->pipe[1]->dentry); | ||
796 | return err; | ||
797 | } | ||
798 | |||
799 | static void gss_pipes_dentries_destroy_net(struct rpc_clnt *clnt, | ||
800 | struct rpc_auth *auth) | ||
801 | { | ||
802 | struct net *net = rpc_net_ns(clnt); | ||
803 | struct super_block *sb; | ||
804 | |||
805 | sb = rpc_get_sb_net(net); | ||
806 | if (sb) { | ||
807 | if (clnt->cl_dentry) | ||
808 | gss_pipes_dentries_destroy(auth); | ||
809 | rpc_put_sb_net(net); | ||
810 | } | ||
811 | } | ||
812 | |||
813 | static int gss_pipes_dentries_create_net(struct rpc_clnt *clnt, | ||
814 | struct rpc_auth *auth) | ||
815 | { | ||
816 | struct net *net = rpc_net_ns(clnt); | ||
817 | struct super_block *sb; | ||
818 | int err = 0; | ||
819 | |||
820 | sb = rpc_get_sb_net(net); | ||
821 | if (sb) { | ||
822 | if (clnt->cl_dentry) | ||
823 | err = gss_pipes_dentries_create(auth); | ||
824 | rpc_put_sb_net(net); | ||
825 | } | ||
826 | return err; | ||
827 | } | ||
828 | |||
762 | /* | 829 | /* |
763 | * NOTE: we have the opportunity to use different | 830 | * NOTE: we have the opportunity to use different |
764 | * parameters based on the input flavor (which must be a pseudoflavor) | 831 | * parameters based on the input flavor (which must be a pseudoflavor) |
@@ -801,32 +868,33 @@ gss_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor) | |||
801 | * that we supported only the old pipe. So we instead create | 868 | * that we supported only the old pipe. So we instead create |
802 | * the new pipe first. | 869 | * the new pipe first. |
803 | */ | 870 | */ |
804 | gss_auth->dentry[1] = rpc_mkpipe(clnt->cl_path.dentry, | 871 | gss_auth->pipe[1] = rpc_mkpipe_data(&gss_upcall_ops_v1, |
805 | "gssd", | 872 | RPC_PIPE_WAIT_FOR_OPEN); |
806 | clnt, &gss_upcall_ops_v1, | 873 | if (IS_ERR(gss_auth->pipe[1])) { |
807 | RPC_PIPE_WAIT_FOR_OPEN); | 874 | err = PTR_ERR(gss_auth->pipe[1]); |
808 | if (IS_ERR(gss_auth->dentry[1])) { | ||
809 | err = PTR_ERR(gss_auth->dentry[1]); | ||
810 | goto err_put_mech; | 875 | goto err_put_mech; |
811 | } | 876 | } |
812 | 877 | ||
813 | gss_auth->dentry[0] = rpc_mkpipe(clnt->cl_path.dentry, | 878 | gss_auth->pipe[0] = rpc_mkpipe_data(&gss_upcall_ops_v0, |
814 | gss_auth->mech->gm_name, | 879 | RPC_PIPE_WAIT_FOR_OPEN); |
815 | clnt, &gss_upcall_ops_v0, | 880 | if (IS_ERR(gss_auth->pipe[0])) { |
816 | RPC_PIPE_WAIT_FOR_OPEN); | 881 | err = PTR_ERR(gss_auth->pipe[0]); |
817 | if (IS_ERR(gss_auth->dentry[0])) { | 882 | goto err_destroy_pipe_1; |
818 | err = PTR_ERR(gss_auth->dentry[0]); | ||
819 | goto err_unlink_pipe_1; | ||
820 | } | 883 | } |
884 | err = gss_pipes_dentries_create_net(clnt, auth); | ||
885 | if (err) | ||
886 | goto err_destroy_pipe_0; | ||
821 | err = rpcauth_init_credcache(auth); | 887 | err = rpcauth_init_credcache(auth); |
822 | if (err) | 888 | if (err) |
823 | goto err_unlink_pipe_0; | 889 | goto err_unlink_pipes; |
824 | 890 | ||
825 | return auth; | 891 | return auth; |
826 | err_unlink_pipe_0: | 892 | err_unlink_pipes: |
827 | rpc_unlink(gss_auth->dentry[0]); | 893 | gss_pipes_dentries_destroy_net(clnt, auth); |
828 | err_unlink_pipe_1: | 894 | err_destroy_pipe_0: |
829 | rpc_unlink(gss_auth->dentry[1]); | 895 | rpc_destroy_pipe_data(gss_auth->pipe[0]); |
896 | err_destroy_pipe_1: | ||
897 | rpc_destroy_pipe_data(gss_auth->pipe[1]); | ||
830 | err_put_mech: | 898 | err_put_mech: |
831 | gss_mech_put(gss_auth->mech); | 899 | gss_mech_put(gss_auth->mech); |
832 | err_free: | 900 | err_free: |
@@ -839,8 +907,9 @@ out_dec: | |||
839 | static void | 907 | static void |
840 | gss_free(struct gss_auth *gss_auth) | 908 | gss_free(struct gss_auth *gss_auth) |
841 | { | 909 | { |
842 | rpc_unlink(gss_auth->dentry[1]); | 910 | gss_pipes_dentries_destroy_net(gss_auth->client, &gss_auth->rpc_auth); |
843 | rpc_unlink(gss_auth->dentry[0]); | 911 | rpc_destroy_pipe_data(gss_auth->pipe[0]); |
912 | rpc_destroy_pipe_data(gss_auth->pipe[1]); | ||
844 | gss_mech_put(gss_auth->mech); | 913 | gss_mech_put(gss_auth->mech); |
845 | 914 | ||
846 | kfree(gss_auth); | 915 | kfree(gss_auth); |
@@ -1547,7 +1616,9 @@ static const struct rpc_authops authgss_ops = { | |||
1547 | .create = gss_create, | 1616 | .create = gss_create, |
1548 | .destroy = gss_destroy, | 1617 | .destroy = gss_destroy, |
1549 | .lookup_cred = gss_lookup_cred, | 1618 | .lookup_cred = gss_lookup_cred, |
1550 | .crcreate = gss_create_cred | 1619 | .crcreate = gss_create_cred, |
1620 | .pipes_create = gss_pipes_dentries_create, | ||
1621 | .pipes_destroy = gss_pipes_dentries_destroy, | ||
1551 | }; | 1622 | }; |
1552 | 1623 | ||
1553 | static const struct rpc_credops gss_credops = { | 1624 | static const struct rpc_credops gss_credops = { |
@@ -1591,6 +1662,21 @@ static const struct rpc_pipe_ops gss_upcall_ops_v1 = { | |||
1591 | .release_pipe = gss_pipe_release, | 1662 | .release_pipe = gss_pipe_release, |
1592 | }; | 1663 | }; |
1593 | 1664 | ||
1665 | static __net_init int rpcsec_gss_init_net(struct net *net) | ||
1666 | { | ||
1667 | return gss_svc_init_net(net); | ||
1668 | } | ||
1669 | |||
1670 | static __net_exit void rpcsec_gss_exit_net(struct net *net) | ||
1671 | { | ||
1672 | gss_svc_shutdown_net(net); | ||
1673 | } | ||
1674 | |||
1675 | static struct pernet_operations rpcsec_gss_net_ops = { | ||
1676 | .init = rpcsec_gss_init_net, | ||
1677 | .exit = rpcsec_gss_exit_net, | ||
1678 | }; | ||
1679 | |||
1594 | /* | 1680 | /* |
1595 | * Initialize RPCSEC_GSS module | 1681 | * Initialize RPCSEC_GSS module |
1596 | */ | 1682 | */ |
@@ -1604,8 +1690,13 @@ static int __init init_rpcsec_gss(void) | |||
1604 | err = gss_svc_init(); | 1690 | err = gss_svc_init(); |
1605 | if (err) | 1691 | if (err) |
1606 | goto out_unregister; | 1692 | goto out_unregister; |
1693 | err = register_pernet_subsys(&rpcsec_gss_net_ops); | ||
1694 | if (err) | ||
1695 | goto out_svc_exit; | ||
1607 | rpc_init_wait_queue(&pipe_version_rpc_waitqueue, "gss pipe version"); | 1696 | rpc_init_wait_queue(&pipe_version_rpc_waitqueue, "gss pipe version"); |
1608 | return 0; | 1697 | return 0; |
1698 | out_svc_exit: | ||
1699 | gss_svc_shutdown(); | ||
1609 | out_unregister: | 1700 | out_unregister: |
1610 | rpcauth_unregister(&authgss_ops); | 1701 | rpcauth_unregister(&authgss_ops); |
1611 | out: | 1702 | out: |
@@ -1614,6 +1705,7 @@ out: | |||
1614 | 1705 | ||
1615 | static void __exit exit_rpcsec_gss(void) | 1706 | static void __exit exit_rpcsec_gss(void) |
1616 | { | 1707 | { |
1708 | unregister_pernet_subsys(&rpcsec_gss_net_ops); | ||
1617 | gss_svc_shutdown(); | 1709 | gss_svc_shutdown(); |
1618 | rpcauth_unregister(&authgss_ops); | 1710 | rpcauth_unregister(&authgss_ops); |
1619 | rcu_barrier(); /* Wait for completion of call_rcu()'s */ | 1711 | rcu_barrier(); /* Wait for completion of call_rcu()'s */ |
diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c index 9576f35ab701..0f43e894bc0a 100644 --- a/net/sunrpc/auth_gss/gss_krb5_crypto.c +++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c | |||
@@ -600,11 +600,14 @@ gss_krb5_cts_crypt(struct crypto_blkcipher *cipher, struct xdr_buf *buf, | |||
600 | u32 ret; | 600 | u32 ret; |
601 | struct scatterlist sg[1]; | 601 | struct scatterlist sg[1]; |
602 | struct blkcipher_desc desc = { .tfm = cipher, .info = iv }; | 602 | struct blkcipher_desc desc = { .tfm = cipher, .info = iv }; |
603 | u8 data[crypto_blkcipher_blocksize(cipher) * 2]; | 603 | u8 data[GSS_KRB5_MAX_BLOCKSIZE * 2]; |
604 | struct page **save_pages; | 604 | struct page **save_pages; |
605 | u32 len = buf->len - offset; | 605 | u32 len = buf->len - offset; |
606 | 606 | ||
607 | BUG_ON(len > crypto_blkcipher_blocksize(cipher) * 2); | 607 | if (len > ARRAY_SIZE(data)) { |
608 | WARN_ON(0); | ||
609 | return -ENOMEM; | ||
610 | } | ||
608 | 611 | ||
609 | /* | 612 | /* |
610 | * For encryption, we want to read from the cleartext | 613 | * For encryption, we want to read from the cleartext |
diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c index 8c67890de427..8eff8c32d1b9 100644 --- a/net/sunrpc/auth_gss/gss_krb5_mech.c +++ b/net/sunrpc/auth_gss/gss_krb5_mech.c | |||
@@ -344,7 +344,7 @@ out_err: | |||
344 | return PTR_ERR(p); | 344 | return PTR_ERR(p); |
345 | } | 345 | } |
346 | 346 | ||
347 | struct crypto_blkcipher * | 347 | static struct crypto_blkcipher * |
348 | context_v2_alloc_cipher(struct krb5_ctx *ctx, const char *cname, u8 *key) | 348 | context_v2_alloc_cipher(struct krb5_ctx *ctx, const char *cname, u8 *key) |
349 | { | 349 | { |
350 | struct crypto_blkcipher *cp; | 350 | struct crypto_blkcipher *cp; |
diff --git a/net/sunrpc/auth_gss/gss_krb5_seal.c b/net/sunrpc/auth_gss/gss_krb5_seal.c index d7941eab7796..62ae3273186c 100644 --- a/net/sunrpc/auth_gss/gss_krb5_seal.c +++ b/net/sunrpc/auth_gss/gss_krb5_seal.c | |||
@@ -159,7 +159,7 @@ gss_get_mic_v1(struct krb5_ctx *ctx, struct xdr_buf *text, | |||
159 | return (ctx->endtime < now) ? GSS_S_CONTEXT_EXPIRED : GSS_S_COMPLETE; | 159 | return (ctx->endtime < now) ? GSS_S_CONTEXT_EXPIRED : GSS_S_COMPLETE; |
160 | } | 160 | } |
161 | 161 | ||
162 | u32 | 162 | static u32 |
163 | gss_get_mic_v2(struct krb5_ctx *ctx, struct xdr_buf *text, | 163 | gss_get_mic_v2(struct krb5_ctx *ctx, struct xdr_buf *text, |
164 | struct xdr_netobj *token) | 164 | struct xdr_netobj *token) |
165 | { | 165 | { |
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c index 8d0f7d3c71c8..1600cfb1618c 100644 --- a/net/sunrpc/auth_gss/svcauth_gss.c +++ b/net/sunrpc/auth_gss/svcauth_gss.c | |||
@@ -48,6 +48,8 @@ | |||
48 | #include <linux/sunrpc/svcauth_gss.h> | 48 | #include <linux/sunrpc/svcauth_gss.h> |
49 | #include <linux/sunrpc/cache.h> | 49 | #include <linux/sunrpc/cache.h> |
50 | 50 | ||
51 | #include "../netns.h" | ||
52 | |||
51 | #ifdef RPC_DEBUG | 53 | #ifdef RPC_DEBUG |
52 | # define RPCDBG_FACILITY RPCDBG_AUTH | 54 | # define RPCDBG_FACILITY RPCDBG_AUTH |
53 | #endif | 55 | #endif |
@@ -75,10 +77,8 @@ struct rsi { | |||
75 | int major_status, minor_status; | 77 | int major_status, minor_status; |
76 | }; | 78 | }; |
77 | 79 | ||
78 | static struct cache_head *rsi_table[RSI_HASHMAX]; | 80 | static struct rsi *rsi_update(struct cache_detail *cd, struct rsi *new, struct rsi *old); |
79 | static struct cache_detail rsi_cache; | 81 | static struct rsi *rsi_lookup(struct cache_detail *cd, struct rsi *item); |
80 | static struct rsi *rsi_update(struct rsi *new, struct rsi *old); | ||
81 | static struct rsi *rsi_lookup(struct rsi *item); | ||
82 | 82 | ||
83 | static void rsi_free(struct rsi *rsii) | 83 | static void rsi_free(struct rsi *rsii) |
84 | { | 84 | { |
@@ -216,7 +216,7 @@ static int rsi_parse(struct cache_detail *cd, | |||
216 | if (dup_to_netobj(&rsii.in_token, buf, len)) | 216 | if (dup_to_netobj(&rsii.in_token, buf, len)) |
217 | goto out; | 217 | goto out; |
218 | 218 | ||
219 | rsip = rsi_lookup(&rsii); | 219 | rsip = rsi_lookup(cd, &rsii); |
220 | if (!rsip) | 220 | if (!rsip) |
221 | goto out; | 221 | goto out; |
222 | 222 | ||
@@ -258,21 +258,20 @@ static int rsi_parse(struct cache_detail *cd, | |||
258 | if (dup_to_netobj(&rsii.out_token, buf, len)) | 258 | if (dup_to_netobj(&rsii.out_token, buf, len)) |
259 | goto out; | 259 | goto out; |
260 | rsii.h.expiry_time = expiry; | 260 | rsii.h.expiry_time = expiry; |
261 | rsip = rsi_update(&rsii, rsip); | 261 | rsip = rsi_update(cd, &rsii, rsip); |
262 | status = 0; | 262 | status = 0; |
263 | out: | 263 | out: |
264 | rsi_free(&rsii); | 264 | rsi_free(&rsii); |
265 | if (rsip) | 265 | if (rsip) |
266 | cache_put(&rsip->h, &rsi_cache); | 266 | cache_put(&rsip->h, cd); |
267 | else | 267 | else |
268 | status = -ENOMEM; | 268 | status = -ENOMEM; |
269 | return status; | 269 | return status; |
270 | } | 270 | } |
271 | 271 | ||
272 | static struct cache_detail rsi_cache = { | 272 | static struct cache_detail rsi_cache_template = { |
273 | .owner = THIS_MODULE, | 273 | .owner = THIS_MODULE, |
274 | .hash_size = RSI_HASHMAX, | 274 | .hash_size = RSI_HASHMAX, |
275 | .hash_table = rsi_table, | ||
276 | .name = "auth.rpcsec.init", | 275 | .name = "auth.rpcsec.init", |
277 | .cache_put = rsi_put, | 276 | .cache_put = rsi_put, |
278 | .cache_upcall = rsi_upcall, | 277 | .cache_upcall = rsi_upcall, |
@@ -283,24 +282,24 @@ static struct cache_detail rsi_cache = { | |||
283 | .alloc = rsi_alloc, | 282 | .alloc = rsi_alloc, |
284 | }; | 283 | }; |
285 | 284 | ||
286 | static struct rsi *rsi_lookup(struct rsi *item) | 285 | static struct rsi *rsi_lookup(struct cache_detail *cd, struct rsi *item) |
287 | { | 286 | { |
288 | struct cache_head *ch; | 287 | struct cache_head *ch; |
289 | int hash = rsi_hash(item); | 288 | int hash = rsi_hash(item); |
290 | 289 | ||
291 | ch = sunrpc_cache_lookup(&rsi_cache, &item->h, hash); | 290 | ch = sunrpc_cache_lookup(cd, &item->h, hash); |
292 | if (ch) | 291 | if (ch) |
293 | return container_of(ch, struct rsi, h); | 292 | return container_of(ch, struct rsi, h); |
294 | else | 293 | else |
295 | return NULL; | 294 | return NULL; |
296 | } | 295 | } |
297 | 296 | ||
298 | static struct rsi *rsi_update(struct rsi *new, struct rsi *old) | 297 | static struct rsi *rsi_update(struct cache_detail *cd, struct rsi *new, struct rsi *old) |
299 | { | 298 | { |
300 | struct cache_head *ch; | 299 | struct cache_head *ch; |
301 | int hash = rsi_hash(new); | 300 | int hash = rsi_hash(new); |
302 | 301 | ||
303 | ch = sunrpc_cache_update(&rsi_cache, &new->h, | 302 | ch = sunrpc_cache_update(cd, &new->h, |
304 | &old->h, hash); | 303 | &old->h, hash); |
305 | if (ch) | 304 | if (ch) |
306 | return container_of(ch, struct rsi, h); | 305 | return container_of(ch, struct rsi, h); |
@@ -339,10 +338,8 @@ struct rsc { | |||
339 | char *client_name; | 338 | char *client_name; |
340 | }; | 339 | }; |
341 | 340 | ||
342 | static struct cache_head *rsc_table[RSC_HASHMAX]; | 341 | static struct rsc *rsc_update(struct cache_detail *cd, struct rsc *new, struct rsc *old); |
343 | static struct cache_detail rsc_cache; | 342 | static struct rsc *rsc_lookup(struct cache_detail *cd, struct rsc *item); |
344 | static struct rsc *rsc_update(struct rsc *new, struct rsc *old); | ||
345 | static struct rsc *rsc_lookup(struct rsc *item); | ||
346 | 343 | ||
347 | static void rsc_free(struct rsc *rsci) | 344 | static void rsc_free(struct rsc *rsci) |
348 | { | 345 | { |
@@ -444,7 +441,7 @@ static int rsc_parse(struct cache_detail *cd, | |||
444 | if (expiry == 0) | 441 | if (expiry == 0) |
445 | goto out; | 442 | goto out; |
446 | 443 | ||
447 | rscp = rsc_lookup(&rsci); | 444 | rscp = rsc_lookup(cd, &rsci); |
448 | if (!rscp) | 445 | if (!rscp) |
449 | goto out; | 446 | goto out; |
450 | 447 | ||
@@ -506,22 +503,21 @@ static int rsc_parse(struct cache_detail *cd, | |||
506 | 503 | ||
507 | } | 504 | } |
508 | rsci.h.expiry_time = expiry; | 505 | rsci.h.expiry_time = expiry; |
509 | rscp = rsc_update(&rsci, rscp); | 506 | rscp = rsc_update(cd, &rsci, rscp); |
510 | status = 0; | 507 | status = 0; |
511 | out: | 508 | out: |
512 | gss_mech_put(gm); | 509 | gss_mech_put(gm); |
513 | rsc_free(&rsci); | 510 | rsc_free(&rsci); |
514 | if (rscp) | 511 | if (rscp) |
515 | cache_put(&rscp->h, &rsc_cache); | 512 | cache_put(&rscp->h, cd); |
516 | else | 513 | else |
517 | status = -ENOMEM; | 514 | status = -ENOMEM; |
518 | return status; | 515 | return status; |
519 | } | 516 | } |
520 | 517 | ||
521 | static struct cache_detail rsc_cache = { | 518 | static struct cache_detail rsc_cache_template = { |
522 | .owner = THIS_MODULE, | 519 | .owner = THIS_MODULE, |
523 | .hash_size = RSC_HASHMAX, | 520 | .hash_size = RSC_HASHMAX, |
524 | .hash_table = rsc_table, | ||
525 | .name = "auth.rpcsec.context", | 521 | .name = "auth.rpcsec.context", |
526 | .cache_put = rsc_put, | 522 | .cache_put = rsc_put, |
527 | .cache_parse = rsc_parse, | 523 | .cache_parse = rsc_parse, |
@@ -531,24 +527,24 @@ static struct cache_detail rsc_cache = { | |||
531 | .alloc = rsc_alloc, | 527 | .alloc = rsc_alloc, |
532 | }; | 528 | }; |
533 | 529 | ||
534 | static struct rsc *rsc_lookup(struct rsc *item) | 530 | static struct rsc *rsc_lookup(struct cache_detail *cd, struct rsc *item) |
535 | { | 531 | { |
536 | struct cache_head *ch; | 532 | struct cache_head *ch; |
537 | int hash = rsc_hash(item); | 533 | int hash = rsc_hash(item); |
538 | 534 | ||
539 | ch = sunrpc_cache_lookup(&rsc_cache, &item->h, hash); | 535 | ch = sunrpc_cache_lookup(cd, &item->h, hash); |
540 | if (ch) | 536 | if (ch) |
541 | return container_of(ch, struct rsc, h); | 537 | return container_of(ch, struct rsc, h); |
542 | else | 538 | else |
543 | return NULL; | 539 | return NULL; |
544 | } | 540 | } |
545 | 541 | ||
546 | static struct rsc *rsc_update(struct rsc *new, struct rsc *old) | 542 | static struct rsc *rsc_update(struct cache_detail *cd, struct rsc *new, struct rsc *old) |
547 | { | 543 | { |
548 | struct cache_head *ch; | 544 | struct cache_head *ch; |
549 | int hash = rsc_hash(new); | 545 | int hash = rsc_hash(new); |
550 | 546 | ||
551 | ch = sunrpc_cache_update(&rsc_cache, &new->h, | 547 | ch = sunrpc_cache_update(cd, &new->h, |
552 | &old->h, hash); | 548 | &old->h, hash); |
553 | if (ch) | 549 | if (ch) |
554 | return container_of(ch, struct rsc, h); | 550 | return container_of(ch, struct rsc, h); |
@@ -558,7 +554,7 @@ static struct rsc *rsc_update(struct rsc *new, struct rsc *old) | |||
558 | 554 | ||
559 | 555 | ||
560 | static struct rsc * | 556 | static struct rsc * |
561 | gss_svc_searchbyctx(struct xdr_netobj *handle) | 557 | gss_svc_searchbyctx(struct cache_detail *cd, struct xdr_netobj *handle) |
562 | { | 558 | { |
563 | struct rsc rsci; | 559 | struct rsc rsci; |
564 | struct rsc *found; | 560 | struct rsc *found; |
@@ -566,11 +562,11 @@ gss_svc_searchbyctx(struct xdr_netobj *handle) | |||
566 | memset(&rsci, 0, sizeof(rsci)); | 562 | memset(&rsci, 0, sizeof(rsci)); |
567 | if (dup_to_netobj(&rsci.handle, handle->data, handle->len)) | 563 | if (dup_to_netobj(&rsci.handle, handle->data, handle->len)) |
568 | return NULL; | 564 | return NULL; |
569 | found = rsc_lookup(&rsci); | 565 | found = rsc_lookup(cd, &rsci); |
570 | rsc_free(&rsci); | 566 | rsc_free(&rsci); |
571 | if (!found) | 567 | if (!found) |
572 | return NULL; | 568 | return NULL; |
573 | if (cache_check(&rsc_cache, &found->h, NULL)) | 569 | if (cache_check(cd, &found->h, NULL)) |
574 | return NULL; | 570 | return NULL; |
575 | return found; | 571 | return found; |
576 | } | 572 | } |
@@ -968,20 +964,20 @@ svcauth_gss_set_client(struct svc_rqst *rqstp) | |||
968 | } | 964 | } |
969 | 965 | ||
970 | static inline int | 966 | static inline int |
971 | gss_write_init_verf(struct svc_rqst *rqstp, struct rsi *rsip) | 967 | gss_write_init_verf(struct cache_detail *cd, struct svc_rqst *rqstp, struct rsi *rsip) |
972 | { | 968 | { |
973 | struct rsc *rsci; | 969 | struct rsc *rsci; |
974 | int rc; | 970 | int rc; |
975 | 971 | ||
976 | if (rsip->major_status != GSS_S_COMPLETE) | 972 | if (rsip->major_status != GSS_S_COMPLETE) |
977 | return gss_write_null_verf(rqstp); | 973 | return gss_write_null_verf(rqstp); |
978 | rsci = gss_svc_searchbyctx(&rsip->out_handle); | 974 | rsci = gss_svc_searchbyctx(cd, &rsip->out_handle); |
979 | if (rsci == NULL) { | 975 | if (rsci == NULL) { |
980 | rsip->major_status = GSS_S_NO_CONTEXT; | 976 | rsip->major_status = GSS_S_NO_CONTEXT; |
981 | return gss_write_null_verf(rqstp); | 977 | return gss_write_null_verf(rqstp); |
982 | } | 978 | } |
983 | rc = gss_write_verf(rqstp, rsci->mechctx, GSS_SEQ_WIN); | 979 | rc = gss_write_verf(rqstp, rsci->mechctx, GSS_SEQ_WIN); |
984 | cache_put(&rsci->h, &rsc_cache); | 980 | cache_put(&rsci->h, cd); |
985 | return rc; | 981 | return rc; |
986 | } | 982 | } |
987 | 983 | ||
@@ -1000,6 +996,7 @@ static int svcauth_gss_handle_init(struct svc_rqst *rqstp, | |||
1000 | struct xdr_netobj tmpobj; | 996 | struct xdr_netobj tmpobj; |
1001 | struct rsi *rsip, rsikey; | 997 | struct rsi *rsip, rsikey; |
1002 | int ret; | 998 | int ret; |
999 | struct sunrpc_net *sn = net_generic(rqstp->rq_xprt->xpt_net, sunrpc_net_id); | ||
1003 | 1000 | ||
1004 | /* Read the verifier; should be NULL: */ | 1001 | /* Read the verifier; should be NULL: */ |
1005 | *authp = rpc_autherr_badverf; | 1002 | *authp = rpc_autherr_badverf; |
@@ -1028,17 +1025,17 @@ static int svcauth_gss_handle_init(struct svc_rqst *rqstp, | |||
1028 | } | 1025 | } |
1029 | 1026 | ||
1030 | /* Perform upcall, or find upcall result: */ | 1027 | /* Perform upcall, or find upcall result: */ |
1031 | rsip = rsi_lookup(&rsikey); | 1028 | rsip = rsi_lookup(sn->rsi_cache, &rsikey); |
1032 | rsi_free(&rsikey); | 1029 | rsi_free(&rsikey); |
1033 | if (!rsip) | 1030 | if (!rsip) |
1034 | return SVC_CLOSE; | 1031 | return SVC_CLOSE; |
1035 | if (cache_check(&rsi_cache, &rsip->h, &rqstp->rq_chandle) < 0) | 1032 | if (cache_check(sn->rsi_cache, &rsip->h, &rqstp->rq_chandle) < 0) |
1036 | /* No upcall result: */ | 1033 | /* No upcall result: */ |
1037 | return SVC_CLOSE; | 1034 | return SVC_CLOSE; |
1038 | 1035 | ||
1039 | ret = SVC_CLOSE; | 1036 | ret = SVC_CLOSE; |
1040 | /* Got an answer to the upcall; use it: */ | 1037 | /* Got an answer to the upcall; use it: */ |
1041 | if (gss_write_init_verf(rqstp, rsip)) | 1038 | if (gss_write_init_verf(sn->rsc_cache, rqstp, rsip)) |
1042 | goto out; | 1039 | goto out; |
1043 | if (resv->iov_len + 4 > PAGE_SIZE) | 1040 | if (resv->iov_len + 4 > PAGE_SIZE) |
1044 | goto out; | 1041 | goto out; |
@@ -1055,7 +1052,7 @@ static int svcauth_gss_handle_init(struct svc_rqst *rqstp, | |||
1055 | 1052 | ||
1056 | ret = SVC_COMPLETE; | 1053 | ret = SVC_COMPLETE; |
1057 | out: | 1054 | out: |
1058 | cache_put(&rsip->h, &rsi_cache); | 1055 | cache_put(&rsip->h, sn->rsi_cache); |
1059 | return ret; | 1056 | return ret; |
1060 | } | 1057 | } |
1061 | 1058 | ||
@@ -1079,6 +1076,7 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp) | |||
1079 | __be32 *rpcstart; | 1076 | __be32 *rpcstart; |
1080 | __be32 *reject_stat = resv->iov_base + resv->iov_len; | 1077 | __be32 *reject_stat = resv->iov_base + resv->iov_len; |
1081 | int ret; | 1078 | int ret; |
1079 | struct sunrpc_net *sn = net_generic(rqstp->rq_xprt->xpt_net, sunrpc_net_id); | ||
1082 | 1080 | ||
1083 | dprintk("RPC: svcauth_gss: argv->iov_len = %zd\n", | 1081 | dprintk("RPC: svcauth_gss: argv->iov_len = %zd\n", |
1084 | argv->iov_len); | 1082 | argv->iov_len); |
@@ -1129,7 +1127,7 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp) | |||
1129 | case RPC_GSS_PROC_DESTROY: | 1127 | case RPC_GSS_PROC_DESTROY: |
1130 | /* Look up the context, and check the verifier: */ | 1128 | /* Look up the context, and check the verifier: */ |
1131 | *authp = rpcsec_gsserr_credproblem; | 1129 | *authp = rpcsec_gsserr_credproblem; |
1132 | rsci = gss_svc_searchbyctx(&gc->gc_ctx); | 1130 | rsci = gss_svc_searchbyctx(sn->rsc_cache, &gc->gc_ctx); |
1133 | if (!rsci) | 1131 | if (!rsci) |
1134 | goto auth_err; | 1132 | goto auth_err; |
1135 | switch (gss_verify_header(rqstp, rsci, rpcstart, gc, authp)) { | 1133 | switch (gss_verify_header(rqstp, rsci, rpcstart, gc, authp)) { |
@@ -1209,7 +1207,7 @@ drop: | |||
1209 | ret = SVC_DROP; | 1207 | ret = SVC_DROP; |
1210 | out: | 1208 | out: |
1211 | if (rsci) | 1209 | if (rsci) |
1212 | cache_put(&rsci->h, &rsc_cache); | 1210 | cache_put(&rsci->h, sn->rsc_cache); |
1213 | return ret; | 1211 | return ret; |
1214 | } | 1212 | } |
1215 | 1213 | ||
@@ -1362,6 +1360,7 @@ svcauth_gss_release(struct svc_rqst *rqstp) | |||
1362 | struct rpc_gss_wire_cred *gc = &gsd->clcred; | 1360 | struct rpc_gss_wire_cred *gc = &gsd->clcred; |
1363 | struct xdr_buf *resbuf = &rqstp->rq_res; | 1361 | struct xdr_buf *resbuf = &rqstp->rq_res; |
1364 | int stat = -EINVAL; | 1362 | int stat = -EINVAL; |
1363 | struct sunrpc_net *sn = net_generic(rqstp->rq_xprt->xpt_net, sunrpc_net_id); | ||
1365 | 1364 | ||
1366 | if (gc->gc_proc != RPC_GSS_PROC_DATA) | 1365 | if (gc->gc_proc != RPC_GSS_PROC_DATA) |
1367 | goto out; | 1366 | goto out; |
@@ -1404,7 +1403,7 @@ out_err: | |||
1404 | put_group_info(rqstp->rq_cred.cr_group_info); | 1403 | put_group_info(rqstp->rq_cred.cr_group_info); |
1405 | rqstp->rq_cred.cr_group_info = NULL; | 1404 | rqstp->rq_cred.cr_group_info = NULL; |
1406 | if (gsd->rsci) | 1405 | if (gsd->rsci) |
1407 | cache_put(&gsd->rsci->h, &rsc_cache); | 1406 | cache_put(&gsd->rsci->h, sn->rsc_cache); |
1408 | gsd->rsci = NULL; | 1407 | gsd->rsci = NULL; |
1409 | 1408 | ||
1410 | return stat; | 1409 | return stat; |
@@ -1429,30 +1428,96 @@ static struct auth_ops svcauthops_gss = { | |||
1429 | .set_client = svcauth_gss_set_client, | 1428 | .set_client = svcauth_gss_set_client, |
1430 | }; | 1429 | }; |
1431 | 1430 | ||
1431 | static int rsi_cache_create_net(struct net *net) | ||
1432 | { | ||
1433 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
1434 | struct cache_detail *cd; | ||
1435 | int err; | ||
1436 | |||
1437 | cd = cache_create_net(&rsi_cache_template, net); | ||
1438 | if (IS_ERR(cd)) | ||
1439 | return PTR_ERR(cd); | ||
1440 | err = cache_register_net(cd, net); | ||
1441 | if (err) { | ||
1442 | cache_destroy_net(cd, net); | ||
1443 | return err; | ||
1444 | } | ||
1445 | sn->rsi_cache = cd; | ||
1446 | return 0; | ||
1447 | } | ||
1448 | |||
1449 | static void rsi_cache_destroy_net(struct net *net) | ||
1450 | { | ||
1451 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
1452 | struct cache_detail *cd = sn->rsi_cache; | ||
1453 | |||
1454 | sn->rsi_cache = NULL; | ||
1455 | cache_purge(cd); | ||
1456 | cache_unregister_net(cd, net); | ||
1457 | cache_destroy_net(cd, net); | ||
1458 | } | ||
1459 | |||
1460 | static int rsc_cache_create_net(struct net *net) | ||
1461 | { | ||
1462 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
1463 | struct cache_detail *cd; | ||
1464 | int err; | ||
1465 | |||
1466 | cd = cache_create_net(&rsc_cache_template, net); | ||
1467 | if (IS_ERR(cd)) | ||
1468 | return PTR_ERR(cd); | ||
1469 | err = cache_register_net(cd, net); | ||
1470 | if (err) { | ||
1471 | cache_destroy_net(cd, net); | ||
1472 | return err; | ||
1473 | } | ||
1474 | sn->rsc_cache = cd; | ||
1475 | return 0; | ||
1476 | } | ||
1477 | |||
1478 | static void rsc_cache_destroy_net(struct net *net) | ||
1479 | { | ||
1480 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
1481 | struct cache_detail *cd = sn->rsc_cache; | ||
1482 | |||
1483 | sn->rsc_cache = NULL; | ||
1484 | cache_purge(cd); | ||
1485 | cache_unregister_net(cd, net); | ||
1486 | cache_destroy_net(cd, net); | ||
1487 | } | ||
1488 | |||
1432 | int | 1489 | int |
1433 | gss_svc_init(void) | 1490 | gss_svc_init_net(struct net *net) |
1434 | { | 1491 | { |
1435 | int rv = svc_auth_register(RPC_AUTH_GSS, &svcauthops_gss); | 1492 | int rv; |
1493 | |||
1494 | rv = rsc_cache_create_net(net); | ||
1436 | if (rv) | 1495 | if (rv) |
1437 | return rv; | 1496 | return rv; |
1438 | rv = cache_register(&rsc_cache); | 1497 | rv = rsi_cache_create_net(net); |
1439 | if (rv) | 1498 | if (rv) |
1440 | goto out1; | 1499 | goto out1; |
1441 | rv = cache_register(&rsi_cache); | ||
1442 | if (rv) | ||
1443 | goto out2; | ||
1444 | return 0; | 1500 | return 0; |
1445 | out2: | ||
1446 | cache_unregister(&rsc_cache); | ||
1447 | out1: | 1501 | out1: |
1448 | svc_auth_unregister(RPC_AUTH_GSS); | 1502 | rsc_cache_destroy_net(net); |
1449 | return rv; | 1503 | return rv; |
1450 | } | 1504 | } |
1451 | 1505 | ||
1452 | void | 1506 | void |
1507 | gss_svc_shutdown_net(struct net *net) | ||
1508 | { | ||
1509 | rsi_cache_destroy_net(net); | ||
1510 | rsc_cache_destroy_net(net); | ||
1511 | } | ||
1512 | |||
1513 | int | ||
1514 | gss_svc_init(void) | ||
1515 | { | ||
1516 | return svc_auth_register(RPC_AUTH_GSS, &svcauthops_gss); | ||
1517 | } | ||
1518 | |||
1519 | void | ||
1453 | gss_svc_shutdown(void) | 1520 | gss_svc_shutdown(void) |
1454 | { | 1521 | { |
1455 | cache_unregister(&rsc_cache); | ||
1456 | cache_unregister(&rsi_cache); | ||
1457 | svc_auth_unregister(RPC_AUTH_GSS); | 1522 | svc_auth_unregister(RPC_AUTH_GSS); |
1458 | } | 1523 | } |
diff --git a/net/sunrpc/backchannel_rqst.c b/net/sunrpc/backchannel_rqst.c index 3ad435a14ada..31def68a0f6e 100644 --- a/net/sunrpc/backchannel_rqst.c +++ b/net/sunrpc/backchannel_rqst.c | |||
@@ -25,6 +25,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||
25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
26 | #include <linux/sunrpc/xprt.h> | 26 | #include <linux/sunrpc/xprt.h> |
27 | #include <linux/export.h> | 27 | #include <linux/export.h> |
28 | #include <linux/sunrpc/bc_xprt.h> | ||
28 | 29 | ||
29 | #ifdef RPC_DEBUG | 30 | #ifdef RPC_DEBUG |
30 | #define RPCDBG_FACILITY RPCDBG_TRANS | 31 | #define RPCDBG_FACILITY RPCDBG_TRANS |
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index 465df9ae1046..de0b0f39d9d8 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c | |||
@@ -344,7 +344,7 @@ static int current_index; | |||
344 | static void do_cache_clean(struct work_struct *work); | 344 | static void do_cache_clean(struct work_struct *work); |
345 | static struct delayed_work cache_cleaner; | 345 | static struct delayed_work cache_cleaner; |
346 | 346 | ||
347 | static void sunrpc_init_cache_detail(struct cache_detail *cd) | 347 | void sunrpc_init_cache_detail(struct cache_detail *cd) |
348 | { | 348 | { |
349 | rwlock_init(&cd->hash_lock); | 349 | rwlock_init(&cd->hash_lock); |
350 | INIT_LIST_HEAD(&cd->queue); | 350 | INIT_LIST_HEAD(&cd->queue); |
@@ -360,8 +360,9 @@ static void sunrpc_init_cache_detail(struct cache_detail *cd) | |||
360 | /* start the cleaning process */ | 360 | /* start the cleaning process */ |
361 | schedule_delayed_work(&cache_cleaner, 0); | 361 | schedule_delayed_work(&cache_cleaner, 0); |
362 | } | 362 | } |
363 | EXPORT_SYMBOL_GPL(sunrpc_init_cache_detail); | ||
363 | 364 | ||
364 | static void sunrpc_destroy_cache_detail(struct cache_detail *cd) | 365 | void sunrpc_destroy_cache_detail(struct cache_detail *cd) |
365 | { | 366 | { |
366 | cache_purge(cd); | 367 | cache_purge(cd); |
367 | spin_lock(&cache_list_lock); | 368 | spin_lock(&cache_list_lock); |
@@ -384,6 +385,7 @@ static void sunrpc_destroy_cache_detail(struct cache_detail *cd) | |||
384 | out: | 385 | out: |
385 | printk(KERN_ERR "nfsd: failed to unregister %s cache\n", cd->name); | 386 | printk(KERN_ERR "nfsd: failed to unregister %s cache\n", cd->name); |
386 | } | 387 | } |
388 | EXPORT_SYMBOL_GPL(sunrpc_destroy_cache_detail); | ||
387 | 389 | ||
388 | /* clean cache tries to find something to clean | 390 | /* clean cache tries to find something to clean |
389 | * and cleans it. | 391 | * and cleans it. |
@@ -828,6 +830,8 @@ static ssize_t cache_do_downcall(char *kaddr, const char __user *buf, | |||
828 | { | 830 | { |
829 | ssize_t ret; | 831 | ssize_t ret; |
830 | 832 | ||
833 | if (count == 0) | ||
834 | return -EINVAL; | ||
831 | if (copy_from_user(kaddr, buf, count)) | 835 | if (copy_from_user(kaddr, buf, count)) |
832 | return -EFAULT; | 836 | return -EFAULT; |
833 | kaddr[count] = '\0'; | 837 | kaddr[count] = '\0'; |
@@ -1643,12 +1647,6 @@ int cache_register_net(struct cache_detail *cd, struct net *net) | |||
1643 | } | 1647 | } |
1644 | EXPORT_SYMBOL_GPL(cache_register_net); | 1648 | EXPORT_SYMBOL_GPL(cache_register_net); |
1645 | 1649 | ||
1646 | int cache_register(struct cache_detail *cd) | ||
1647 | { | ||
1648 | return cache_register_net(cd, &init_net); | ||
1649 | } | ||
1650 | EXPORT_SYMBOL_GPL(cache_register); | ||
1651 | |||
1652 | void cache_unregister_net(struct cache_detail *cd, struct net *net) | 1650 | void cache_unregister_net(struct cache_detail *cd, struct net *net) |
1653 | { | 1651 | { |
1654 | remove_cache_proc_entries(cd, net); | 1652 | remove_cache_proc_entries(cd, net); |
@@ -1656,11 +1654,31 @@ void cache_unregister_net(struct cache_detail *cd, struct net *net) | |||
1656 | } | 1654 | } |
1657 | EXPORT_SYMBOL_GPL(cache_unregister_net); | 1655 | EXPORT_SYMBOL_GPL(cache_unregister_net); |
1658 | 1656 | ||
1659 | void cache_unregister(struct cache_detail *cd) | 1657 | struct cache_detail *cache_create_net(struct cache_detail *tmpl, struct net *net) |
1658 | { | ||
1659 | struct cache_detail *cd; | ||
1660 | |||
1661 | cd = kmemdup(tmpl, sizeof(struct cache_detail), GFP_KERNEL); | ||
1662 | if (cd == NULL) | ||
1663 | return ERR_PTR(-ENOMEM); | ||
1664 | |||
1665 | cd->hash_table = kzalloc(cd->hash_size * sizeof(struct cache_head *), | ||
1666 | GFP_KERNEL); | ||
1667 | if (cd->hash_table == NULL) { | ||
1668 | kfree(cd); | ||
1669 | return ERR_PTR(-ENOMEM); | ||
1670 | } | ||
1671 | cd->net = net; | ||
1672 | return cd; | ||
1673 | } | ||
1674 | EXPORT_SYMBOL_GPL(cache_create_net); | ||
1675 | |||
1676 | void cache_destroy_net(struct cache_detail *cd, struct net *net) | ||
1660 | { | 1677 | { |
1661 | cache_unregister_net(cd, &init_net); | 1678 | kfree(cd->hash_table); |
1679 | kfree(cd); | ||
1662 | } | 1680 | } |
1663 | EXPORT_SYMBOL_GPL(cache_unregister); | 1681 | EXPORT_SYMBOL_GPL(cache_destroy_net); |
1664 | 1682 | ||
1665 | static ssize_t cache_read_pipefs(struct file *filp, char __user *buf, | 1683 | static ssize_t cache_read_pipefs(struct file *filp, char __user *buf, |
1666 | size_t count, loff_t *ppos) | 1684 | size_t count, loff_t *ppos) |
@@ -1787,17 +1805,14 @@ int sunrpc_cache_register_pipefs(struct dentry *parent, | |||
1787 | struct dentry *dir; | 1805 | struct dentry *dir; |
1788 | int ret = 0; | 1806 | int ret = 0; |
1789 | 1807 | ||
1790 | sunrpc_init_cache_detail(cd); | ||
1791 | q.name = name; | 1808 | q.name = name; |
1792 | q.len = strlen(name); | 1809 | q.len = strlen(name); |
1793 | q.hash = full_name_hash(q.name, q.len); | 1810 | q.hash = full_name_hash(q.name, q.len); |
1794 | dir = rpc_create_cache_dir(parent, &q, umode, cd); | 1811 | dir = rpc_create_cache_dir(parent, &q, umode, cd); |
1795 | if (!IS_ERR(dir)) | 1812 | if (!IS_ERR(dir)) |
1796 | cd->u.pipefs.dir = dir; | 1813 | cd->u.pipefs.dir = dir; |
1797 | else { | 1814 | else |
1798 | sunrpc_destroy_cache_detail(cd); | ||
1799 | ret = PTR_ERR(dir); | 1815 | ret = PTR_ERR(dir); |
1800 | } | ||
1801 | return ret; | 1816 | return ret; |
1802 | } | 1817 | } |
1803 | EXPORT_SYMBOL_GPL(sunrpc_cache_register_pipefs); | 1818 | EXPORT_SYMBOL_GPL(sunrpc_cache_register_pipefs); |
@@ -1806,7 +1821,6 @@ void sunrpc_cache_unregister_pipefs(struct cache_detail *cd) | |||
1806 | { | 1821 | { |
1807 | rpc_remove_cache_dir(cd->u.pipefs.dir); | 1822 | rpc_remove_cache_dir(cd->u.pipefs.dir); |
1808 | cd->u.pipefs.dir = NULL; | 1823 | cd->u.pipefs.dir = NULL; |
1809 | sunrpc_destroy_cache_detail(cd); | ||
1810 | } | 1824 | } |
1811 | EXPORT_SYMBOL_GPL(sunrpc_cache_unregister_pipefs); | 1825 | EXPORT_SYMBOL_GPL(sunrpc_cache_unregister_pipefs); |
1812 | 1826 | ||
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index f0268ea7e711..67972462a543 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
@@ -17,7 +17,6 @@ | |||
17 | * Copyright (C) 1995,1996 Olaf Kirch <okir@monad.swb.de> | 17 | * Copyright (C) 1995,1996 Olaf Kirch <okir@monad.swb.de> |
18 | */ | 18 | */ |
19 | 19 | ||
20 | #include <asm/system.h> | ||
21 | 20 | ||
22 | #include <linux/module.h> | 21 | #include <linux/module.h> |
23 | #include <linux/types.h> | 22 | #include <linux/types.h> |
@@ -31,13 +30,16 @@ | |||
31 | #include <linux/in.h> | 30 | #include <linux/in.h> |
32 | #include <linux/in6.h> | 31 | #include <linux/in6.h> |
33 | #include <linux/un.h> | 32 | #include <linux/un.h> |
33 | #include <linux/rcupdate.h> | ||
34 | 34 | ||
35 | #include <linux/sunrpc/clnt.h> | 35 | #include <linux/sunrpc/clnt.h> |
36 | #include <linux/sunrpc/rpc_pipe_fs.h> | 36 | #include <linux/sunrpc/rpc_pipe_fs.h> |
37 | #include <linux/sunrpc/metrics.h> | 37 | #include <linux/sunrpc/metrics.h> |
38 | #include <linux/sunrpc/bc_xprt.h> | 38 | #include <linux/sunrpc/bc_xprt.h> |
39 | #include <trace/events/sunrpc.h> | ||
39 | 40 | ||
40 | #include "sunrpc.h" | 41 | #include "sunrpc.h" |
42 | #include "netns.h" | ||
41 | 43 | ||
42 | #ifdef RPC_DEBUG | 44 | #ifdef RPC_DEBUG |
43 | # define RPCDBG_FACILITY RPCDBG_CALL | 45 | # define RPCDBG_FACILITY RPCDBG_CALL |
@@ -50,8 +52,6 @@ | |||
50 | /* | 52 | /* |
51 | * All RPC clients are linked into this list | 53 | * All RPC clients are linked into this list |
52 | */ | 54 | */ |
53 | static LIST_HEAD(all_clients); | ||
54 | static DEFINE_SPINLOCK(rpc_client_lock); | ||
55 | 55 | ||
56 | static DECLARE_WAIT_QUEUE_HEAD(destroy_wait); | 56 | static DECLARE_WAIT_QUEUE_HEAD(destroy_wait); |
57 | 57 | ||
@@ -81,82 +81,191 @@ static int rpc_ping(struct rpc_clnt *clnt); | |||
81 | 81 | ||
82 | static void rpc_register_client(struct rpc_clnt *clnt) | 82 | static void rpc_register_client(struct rpc_clnt *clnt) |
83 | { | 83 | { |
84 | spin_lock(&rpc_client_lock); | 84 | struct net *net = rpc_net_ns(clnt); |
85 | list_add(&clnt->cl_clients, &all_clients); | 85 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); |
86 | spin_unlock(&rpc_client_lock); | 86 | |
87 | spin_lock(&sn->rpc_client_lock); | ||
88 | list_add(&clnt->cl_clients, &sn->all_clients); | ||
89 | spin_unlock(&sn->rpc_client_lock); | ||
87 | } | 90 | } |
88 | 91 | ||
89 | static void rpc_unregister_client(struct rpc_clnt *clnt) | 92 | static void rpc_unregister_client(struct rpc_clnt *clnt) |
90 | { | 93 | { |
91 | spin_lock(&rpc_client_lock); | 94 | struct net *net = rpc_net_ns(clnt); |
95 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
96 | |||
97 | spin_lock(&sn->rpc_client_lock); | ||
92 | list_del(&clnt->cl_clients); | 98 | list_del(&clnt->cl_clients); |
93 | spin_unlock(&rpc_client_lock); | 99 | spin_unlock(&sn->rpc_client_lock); |
94 | } | 100 | } |
95 | 101 | ||
96 | static int | 102 | static void __rpc_clnt_remove_pipedir(struct rpc_clnt *clnt) |
97 | rpc_setup_pipedir(struct rpc_clnt *clnt, char *dir_name) | 103 | { |
104 | if (clnt->cl_dentry) { | ||
105 | if (clnt->cl_auth && clnt->cl_auth->au_ops->pipes_destroy) | ||
106 | clnt->cl_auth->au_ops->pipes_destroy(clnt->cl_auth); | ||
107 | rpc_remove_client_dir(clnt->cl_dentry); | ||
108 | } | ||
109 | clnt->cl_dentry = NULL; | ||
110 | } | ||
111 | |||
112 | static void rpc_clnt_remove_pipedir(struct rpc_clnt *clnt) | ||
113 | { | ||
114 | struct net *net = rpc_net_ns(clnt); | ||
115 | struct super_block *pipefs_sb; | ||
116 | |||
117 | pipefs_sb = rpc_get_sb_net(net); | ||
118 | if (pipefs_sb) { | ||
119 | __rpc_clnt_remove_pipedir(clnt); | ||
120 | rpc_put_sb_net(net); | ||
121 | } | ||
122 | } | ||
123 | |||
124 | static struct dentry *rpc_setup_pipedir_sb(struct super_block *sb, | ||
125 | struct rpc_clnt *clnt, | ||
126 | const char *dir_name) | ||
98 | { | 127 | { |
99 | static uint32_t clntid; | 128 | static uint32_t clntid; |
100 | struct path path, dir; | ||
101 | char name[15]; | 129 | char name[15]; |
102 | struct qstr q = { | 130 | struct qstr q = { |
103 | .name = name, | 131 | .name = name, |
104 | }; | 132 | }; |
133 | struct dentry *dir, *dentry; | ||
105 | int error; | 134 | int error; |
106 | 135 | ||
107 | clnt->cl_path.mnt = ERR_PTR(-ENOENT); | 136 | dir = rpc_d_lookup_sb(sb, dir_name); |
108 | clnt->cl_path.dentry = ERR_PTR(-ENOENT); | 137 | if (dir == NULL) |
109 | if (dir_name == NULL) | 138 | return dir; |
110 | return 0; | ||
111 | |||
112 | path.mnt = rpc_get_mount(); | ||
113 | if (IS_ERR(path.mnt)) | ||
114 | return PTR_ERR(path.mnt); | ||
115 | error = vfs_path_lookup(path.mnt->mnt_root, path.mnt, dir_name, 0, &dir); | ||
116 | if (error) | ||
117 | goto err; | ||
118 | |||
119 | for (;;) { | 139 | for (;;) { |
120 | q.len = snprintf(name, sizeof(name), "clnt%x", (unsigned int)clntid++); | 140 | q.len = snprintf(name, sizeof(name), "clnt%x", (unsigned int)clntid++); |
121 | name[sizeof(name) - 1] = '\0'; | 141 | name[sizeof(name) - 1] = '\0'; |
122 | q.hash = full_name_hash(q.name, q.len); | 142 | q.hash = full_name_hash(q.name, q.len); |
123 | path.dentry = rpc_create_client_dir(dir.dentry, &q, clnt); | 143 | dentry = rpc_create_client_dir(dir, &q, clnt); |
124 | if (!IS_ERR(path.dentry)) | 144 | if (!IS_ERR(dentry)) |
125 | break; | 145 | break; |
126 | error = PTR_ERR(path.dentry); | 146 | error = PTR_ERR(dentry); |
127 | if (error != -EEXIST) { | 147 | if (error != -EEXIST) { |
128 | printk(KERN_INFO "RPC: Couldn't create pipefs entry" | 148 | printk(KERN_INFO "RPC: Couldn't create pipefs entry" |
129 | " %s/%s, error %d\n", | 149 | " %s/%s, error %d\n", |
130 | dir_name, name, error); | 150 | dir_name, name, error); |
131 | goto err_path_put; | 151 | break; |
132 | } | 152 | } |
133 | } | 153 | } |
134 | path_put(&dir); | 154 | dput(dir); |
135 | clnt->cl_path = path; | 155 | return dentry; |
156 | } | ||
157 | |||
158 | static int | ||
159 | rpc_setup_pipedir(struct rpc_clnt *clnt, const char *dir_name) | ||
160 | { | ||
161 | struct net *net = rpc_net_ns(clnt); | ||
162 | struct super_block *pipefs_sb; | ||
163 | struct dentry *dentry; | ||
164 | |||
165 | clnt->cl_dentry = NULL; | ||
166 | if (dir_name == NULL) | ||
167 | return 0; | ||
168 | pipefs_sb = rpc_get_sb_net(net); | ||
169 | if (!pipefs_sb) | ||
170 | return 0; | ||
171 | dentry = rpc_setup_pipedir_sb(pipefs_sb, clnt, dir_name); | ||
172 | rpc_put_sb_net(net); | ||
173 | if (IS_ERR(dentry)) | ||
174 | return PTR_ERR(dentry); | ||
175 | clnt->cl_dentry = dentry; | ||
136 | return 0; | 176 | return 0; |
137 | err_path_put: | 177 | } |
138 | path_put(&dir); | 178 | |
139 | err: | 179 | static int __rpc_pipefs_event(struct rpc_clnt *clnt, unsigned long event, |
140 | rpc_put_mount(); | 180 | struct super_block *sb) |
181 | { | ||
182 | struct dentry *dentry; | ||
183 | int err = 0; | ||
184 | |||
185 | switch (event) { | ||
186 | case RPC_PIPEFS_MOUNT: | ||
187 | if (clnt->cl_program->pipe_dir_name == NULL) | ||
188 | break; | ||
189 | dentry = rpc_setup_pipedir_sb(sb, clnt, | ||
190 | clnt->cl_program->pipe_dir_name); | ||
191 | BUG_ON(dentry == NULL); | ||
192 | if (IS_ERR(dentry)) | ||
193 | return PTR_ERR(dentry); | ||
194 | clnt->cl_dentry = dentry; | ||
195 | if (clnt->cl_auth->au_ops->pipes_create) { | ||
196 | err = clnt->cl_auth->au_ops->pipes_create(clnt->cl_auth); | ||
197 | if (err) | ||
198 | __rpc_clnt_remove_pipedir(clnt); | ||
199 | } | ||
200 | break; | ||
201 | case RPC_PIPEFS_UMOUNT: | ||
202 | __rpc_clnt_remove_pipedir(clnt); | ||
203 | break; | ||
204 | default: | ||
205 | printk(KERN_ERR "%s: unknown event: %ld\n", __func__, event); | ||
206 | return -ENOTSUPP; | ||
207 | } | ||
208 | return err; | ||
209 | } | ||
210 | |||
211 | static struct rpc_clnt *rpc_get_client_for_event(struct net *net, int event) | ||
212 | { | ||
213 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
214 | struct rpc_clnt *clnt; | ||
215 | |||
216 | spin_lock(&sn->rpc_client_lock); | ||
217 | list_for_each_entry(clnt, &sn->all_clients, cl_clients) { | ||
218 | if (((event == RPC_PIPEFS_MOUNT) && clnt->cl_dentry) || | ||
219 | ((event == RPC_PIPEFS_UMOUNT) && !clnt->cl_dentry)) | ||
220 | continue; | ||
221 | atomic_inc(&clnt->cl_count); | ||
222 | spin_unlock(&sn->rpc_client_lock); | ||
223 | return clnt; | ||
224 | } | ||
225 | spin_unlock(&sn->rpc_client_lock); | ||
226 | return NULL; | ||
227 | } | ||
228 | |||
229 | static int rpc_pipefs_event(struct notifier_block *nb, unsigned long event, | ||
230 | void *ptr) | ||
231 | { | ||
232 | struct super_block *sb = ptr; | ||
233 | struct rpc_clnt *clnt; | ||
234 | int error = 0; | ||
235 | |||
236 | while ((clnt = rpc_get_client_for_event(sb->s_fs_info, event))) { | ||
237 | error = __rpc_pipefs_event(clnt, event, sb); | ||
238 | rpc_release_client(clnt); | ||
239 | if (error) | ||
240 | break; | ||
241 | } | ||
141 | return error; | 242 | return error; |
142 | } | 243 | } |
143 | 244 | ||
245 | static struct notifier_block rpc_clients_block = { | ||
246 | .notifier_call = rpc_pipefs_event, | ||
247 | .priority = SUNRPC_PIPEFS_RPC_PRIO, | ||
248 | }; | ||
249 | |||
250 | int rpc_clients_notifier_register(void) | ||
251 | { | ||
252 | return rpc_pipefs_notifier_register(&rpc_clients_block); | ||
253 | } | ||
254 | |||
255 | void rpc_clients_notifier_unregister(void) | ||
256 | { | ||
257 | return rpc_pipefs_notifier_unregister(&rpc_clients_block); | ||
258 | } | ||
259 | |||
144 | static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, struct rpc_xprt *xprt) | 260 | static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, struct rpc_xprt *xprt) |
145 | { | 261 | { |
146 | struct rpc_program *program = args->program; | 262 | const struct rpc_program *program = args->program; |
147 | struct rpc_version *version; | 263 | const struct rpc_version *version; |
148 | struct rpc_clnt *clnt = NULL; | 264 | struct rpc_clnt *clnt = NULL; |
149 | struct rpc_auth *auth; | 265 | struct rpc_auth *auth; |
150 | int err; | 266 | int err; |
151 | size_t len; | ||
152 | 267 | ||
153 | /* sanity check the name before trying to print it */ | 268 | /* sanity check the name before trying to print it */ |
154 | err = -EINVAL; | ||
155 | len = strlen(args->servername); | ||
156 | if (len > RPC_MAXNETNAMELEN) | ||
157 | goto out_no_rpciod; | ||
158 | len++; | ||
159 | |||
160 | dprintk("RPC: creating %s client for %s (xprt %p)\n", | 269 | dprintk("RPC: creating %s client for %s (xprt %p)\n", |
161 | program->name, args->servername, xprt); | 270 | program->name, args->servername, xprt); |
162 | 271 | ||
@@ -179,17 +288,7 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, stru | |||
179 | goto out_err; | 288 | goto out_err; |
180 | clnt->cl_parent = clnt; | 289 | clnt->cl_parent = clnt; |
181 | 290 | ||
182 | clnt->cl_server = clnt->cl_inline_name; | 291 | rcu_assign_pointer(clnt->cl_xprt, xprt); |
183 | if (len > sizeof(clnt->cl_inline_name)) { | ||
184 | char *buf = kmalloc(len, GFP_KERNEL); | ||
185 | if (buf != NULL) | ||
186 | clnt->cl_server = buf; | ||
187 | else | ||
188 | len = sizeof(clnt->cl_inline_name); | ||
189 | } | ||
190 | strlcpy(clnt->cl_server, args->servername, len); | ||
191 | |||
192 | clnt->cl_xprt = xprt; | ||
193 | clnt->cl_procinfo = version->procs; | 292 | clnt->cl_procinfo = version->procs; |
194 | clnt->cl_maxproc = version->nrprocs; | 293 | clnt->cl_maxproc = version->nrprocs; |
195 | clnt->cl_protname = program->name; | 294 | clnt->cl_protname = program->name; |
@@ -204,7 +303,7 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, stru | |||
204 | INIT_LIST_HEAD(&clnt->cl_tasks); | 303 | INIT_LIST_HEAD(&clnt->cl_tasks); |
205 | spin_lock_init(&clnt->cl_lock); | 304 | spin_lock_init(&clnt->cl_lock); |
206 | 305 | ||
207 | if (!xprt_bound(clnt->cl_xprt)) | 306 | if (!xprt_bound(xprt)) |
208 | clnt->cl_autobind = 1; | 307 | clnt->cl_autobind = 1; |
209 | 308 | ||
210 | clnt->cl_timeout = xprt->timeout; | 309 | clnt->cl_timeout = xprt->timeout; |
@@ -246,17 +345,12 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, stru | |||
246 | return clnt; | 345 | return clnt; |
247 | 346 | ||
248 | out_no_auth: | 347 | out_no_auth: |
249 | if (!IS_ERR(clnt->cl_path.dentry)) { | 348 | rpc_clnt_remove_pipedir(clnt); |
250 | rpc_remove_client_dir(clnt->cl_path.dentry); | ||
251 | rpc_put_mount(); | ||
252 | } | ||
253 | out_no_path: | 349 | out_no_path: |
254 | kfree(clnt->cl_principal); | 350 | kfree(clnt->cl_principal); |
255 | out_no_principal: | 351 | out_no_principal: |
256 | rpc_free_iostats(clnt->cl_metrics); | 352 | rpc_free_iostats(clnt->cl_metrics); |
257 | out_no_stats: | 353 | out_no_stats: |
258 | if (clnt->cl_server != clnt->cl_inline_name) | ||
259 | kfree(clnt->cl_server); | ||
260 | kfree(clnt); | 354 | kfree(clnt); |
261 | out_err: | 355 | out_err: |
262 | xprt_put(xprt); | 356 | xprt_put(xprt); |
@@ -286,6 +380,7 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args) | |||
286 | .srcaddr = args->saddress, | 380 | .srcaddr = args->saddress, |
287 | .dstaddr = args->address, | 381 | .dstaddr = args->address, |
288 | .addrlen = args->addrsize, | 382 | .addrlen = args->addrsize, |
383 | .servername = args->servername, | ||
289 | .bc_xprt = args->bc_xprt, | 384 | .bc_xprt = args->bc_xprt, |
290 | }; | 385 | }; |
291 | char servername[48]; | 386 | char servername[48]; |
@@ -294,7 +389,7 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args) | |||
294 | * If the caller chooses not to specify a hostname, whip | 389 | * If the caller chooses not to specify a hostname, whip |
295 | * up a string representation of the passed-in address. | 390 | * up a string representation of the passed-in address. |
296 | */ | 391 | */ |
297 | if (args->servername == NULL) { | 392 | if (xprtargs.servername == NULL) { |
298 | struct sockaddr_un *sun = | 393 | struct sockaddr_un *sun = |
299 | (struct sockaddr_un *)args->address; | 394 | (struct sockaddr_un *)args->address; |
300 | struct sockaddr_in *sin = | 395 | struct sockaddr_in *sin = |
@@ -321,7 +416,7 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args) | |||
321 | * address family isn't recognized. */ | 416 | * address family isn't recognized. */ |
322 | return ERR_PTR(-EINVAL); | 417 | return ERR_PTR(-EINVAL); |
323 | } | 418 | } |
324 | args->servername = servername; | 419 | xprtargs.servername = servername; |
325 | } | 420 | } |
326 | 421 | ||
327 | xprt = xprt_create_transport(&xprtargs); | 422 | xprt = xprt_create_transport(&xprtargs); |
@@ -374,6 +469,7 @@ struct rpc_clnt * | |||
374 | rpc_clone_client(struct rpc_clnt *clnt) | 469 | rpc_clone_client(struct rpc_clnt *clnt) |
375 | { | 470 | { |
376 | struct rpc_clnt *new; | 471 | struct rpc_clnt *new; |
472 | struct rpc_xprt *xprt; | ||
377 | int err = -ENOMEM; | 473 | int err = -ENOMEM; |
378 | 474 | ||
379 | new = kmemdup(clnt, sizeof(*new), GFP_KERNEL); | 475 | new = kmemdup(clnt, sizeof(*new), GFP_KERNEL); |
@@ -393,18 +489,25 @@ rpc_clone_client(struct rpc_clnt *clnt) | |||
393 | if (new->cl_principal == NULL) | 489 | if (new->cl_principal == NULL) |
394 | goto out_no_principal; | 490 | goto out_no_principal; |
395 | } | 491 | } |
492 | rcu_read_lock(); | ||
493 | xprt = xprt_get(rcu_dereference(clnt->cl_xprt)); | ||
494 | rcu_read_unlock(); | ||
495 | if (xprt == NULL) | ||
496 | goto out_no_transport; | ||
497 | rcu_assign_pointer(new->cl_xprt, xprt); | ||
396 | atomic_set(&new->cl_count, 1); | 498 | atomic_set(&new->cl_count, 1); |
397 | err = rpc_setup_pipedir(new, clnt->cl_program->pipe_dir_name); | 499 | err = rpc_setup_pipedir(new, clnt->cl_program->pipe_dir_name); |
398 | if (err != 0) | 500 | if (err != 0) |
399 | goto out_no_path; | 501 | goto out_no_path; |
400 | if (new->cl_auth) | 502 | if (new->cl_auth) |
401 | atomic_inc(&new->cl_auth->au_count); | 503 | atomic_inc(&new->cl_auth->au_count); |
402 | xprt_get(clnt->cl_xprt); | ||
403 | atomic_inc(&clnt->cl_count); | 504 | atomic_inc(&clnt->cl_count); |
404 | rpc_register_client(new); | 505 | rpc_register_client(new); |
405 | rpciod_up(); | 506 | rpciod_up(); |
406 | return new; | 507 | return new; |
407 | out_no_path: | 508 | out_no_path: |
509 | xprt_put(xprt); | ||
510 | out_no_transport: | ||
408 | kfree(new->cl_principal); | 511 | kfree(new->cl_principal); |
409 | out_no_principal: | 512 | out_no_principal: |
410 | rpc_free_iostats(new->cl_metrics); | 513 | rpc_free_iostats(new->cl_metrics); |
@@ -453,8 +556,9 @@ EXPORT_SYMBOL_GPL(rpc_killall_tasks); | |||
453 | */ | 556 | */ |
454 | void rpc_shutdown_client(struct rpc_clnt *clnt) | 557 | void rpc_shutdown_client(struct rpc_clnt *clnt) |
455 | { | 558 | { |
456 | dprintk("RPC: shutting down %s client for %s\n", | 559 | dprintk_rcu("RPC: shutting down %s client for %s\n", |
457 | clnt->cl_protname, clnt->cl_server); | 560 | clnt->cl_protname, |
561 | rcu_dereference(clnt->cl_xprt)->servername); | ||
458 | 562 | ||
459 | while (!list_empty(&clnt->cl_tasks)) { | 563 | while (!list_empty(&clnt->cl_tasks)) { |
460 | rpc_killall_tasks(clnt); | 564 | rpc_killall_tasks(clnt); |
@@ -472,24 +576,17 @@ EXPORT_SYMBOL_GPL(rpc_shutdown_client); | |||
472 | static void | 576 | static void |
473 | rpc_free_client(struct rpc_clnt *clnt) | 577 | rpc_free_client(struct rpc_clnt *clnt) |
474 | { | 578 | { |
475 | dprintk("RPC: destroying %s client for %s\n", | 579 | dprintk_rcu("RPC: destroying %s client for %s\n", |
476 | clnt->cl_protname, clnt->cl_server); | 580 | clnt->cl_protname, |
477 | if (!IS_ERR(clnt->cl_path.dentry)) { | 581 | rcu_dereference(clnt->cl_xprt)->servername); |
478 | rpc_remove_client_dir(clnt->cl_path.dentry); | 582 | if (clnt->cl_parent != clnt) |
479 | rpc_put_mount(); | ||
480 | } | ||
481 | if (clnt->cl_parent != clnt) { | ||
482 | rpc_release_client(clnt->cl_parent); | 583 | rpc_release_client(clnt->cl_parent); |
483 | goto out_free; | ||
484 | } | ||
485 | if (clnt->cl_server != clnt->cl_inline_name) | ||
486 | kfree(clnt->cl_server); | ||
487 | out_free: | ||
488 | rpc_unregister_client(clnt); | 584 | rpc_unregister_client(clnt); |
585 | rpc_clnt_remove_pipedir(clnt); | ||
489 | rpc_free_iostats(clnt->cl_metrics); | 586 | rpc_free_iostats(clnt->cl_metrics); |
490 | kfree(clnt->cl_principal); | 587 | kfree(clnt->cl_principal); |
491 | clnt->cl_metrics = NULL; | 588 | clnt->cl_metrics = NULL; |
492 | xprt_put(clnt->cl_xprt); | 589 | xprt_put(rcu_dereference_raw(clnt->cl_xprt)); |
493 | rpciod_down(); | 590 | rpciod_down(); |
494 | kfree(clnt); | 591 | kfree(clnt); |
495 | } | 592 | } |
@@ -542,11 +639,11 @@ rpc_release_client(struct rpc_clnt *clnt) | |||
542 | * The Sun NFSv2/v3 ACL protocol can do this. | 639 | * The Sun NFSv2/v3 ACL protocol can do this. |
543 | */ | 640 | */ |
544 | struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *old, | 641 | struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *old, |
545 | struct rpc_program *program, | 642 | const struct rpc_program *program, |
546 | u32 vers) | 643 | u32 vers) |
547 | { | 644 | { |
548 | struct rpc_clnt *clnt; | 645 | struct rpc_clnt *clnt; |
549 | struct rpc_version *version; | 646 | const struct rpc_version *version; |
550 | int err; | 647 | int err; |
551 | 648 | ||
552 | BUG_ON(vers >= program->nrvers || !program->version[vers]); | 649 | BUG_ON(vers >= program->nrvers || !program->version[vers]); |
@@ -778,13 +875,18 @@ EXPORT_SYMBOL_GPL(rpc_call_start); | |||
778 | size_t rpc_peeraddr(struct rpc_clnt *clnt, struct sockaddr *buf, size_t bufsize) | 875 | size_t rpc_peeraddr(struct rpc_clnt *clnt, struct sockaddr *buf, size_t bufsize) |
779 | { | 876 | { |
780 | size_t bytes; | 877 | size_t bytes; |
781 | struct rpc_xprt *xprt = clnt->cl_xprt; | 878 | struct rpc_xprt *xprt; |
782 | 879 | ||
783 | bytes = sizeof(xprt->addr); | 880 | rcu_read_lock(); |
881 | xprt = rcu_dereference(clnt->cl_xprt); | ||
882 | |||
883 | bytes = xprt->addrlen; | ||
784 | if (bytes > bufsize) | 884 | if (bytes > bufsize) |
785 | bytes = bufsize; | 885 | bytes = bufsize; |
786 | memcpy(buf, &clnt->cl_xprt->addr, bytes); | 886 | memcpy(buf, &xprt->addr, bytes); |
787 | return xprt->addrlen; | 887 | rcu_read_unlock(); |
888 | |||
889 | return bytes; | ||
788 | } | 890 | } |
789 | EXPORT_SYMBOL_GPL(rpc_peeraddr); | 891 | EXPORT_SYMBOL_GPL(rpc_peeraddr); |
790 | 892 | ||
@@ -793,11 +895,16 @@ EXPORT_SYMBOL_GPL(rpc_peeraddr); | |||
793 | * @clnt: RPC client structure | 895 | * @clnt: RPC client structure |
794 | * @format: address format | 896 | * @format: address format |
795 | * | 897 | * |
898 | * NB: the lifetime of the memory referenced by the returned pointer is | ||
899 | * the same as the rpc_xprt itself. As long as the caller uses this | ||
900 | * pointer, it must hold the RCU read lock. | ||
796 | */ | 901 | */ |
797 | const char *rpc_peeraddr2str(struct rpc_clnt *clnt, | 902 | const char *rpc_peeraddr2str(struct rpc_clnt *clnt, |
798 | enum rpc_display_format_t format) | 903 | enum rpc_display_format_t format) |
799 | { | 904 | { |
800 | struct rpc_xprt *xprt = clnt->cl_xprt; | 905 | struct rpc_xprt *xprt; |
906 | |||
907 | xprt = rcu_dereference(clnt->cl_xprt); | ||
801 | 908 | ||
802 | if (xprt->address_strings[format] != NULL) | 909 | if (xprt->address_strings[format] != NULL) |
803 | return xprt->address_strings[format]; | 910 | return xprt->address_strings[format]; |
@@ -806,17 +913,203 @@ const char *rpc_peeraddr2str(struct rpc_clnt *clnt, | |||
806 | } | 913 | } |
807 | EXPORT_SYMBOL_GPL(rpc_peeraddr2str); | 914 | EXPORT_SYMBOL_GPL(rpc_peeraddr2str); |
808 | 915 | ||
916 | static const struct sockaddr_in rpc_inaddr_loopback = { | ||
917 | .sin_family = AF_INET, | ||
918 | .sin_addr.s_addr = htonl(INADDR_ANY), | ||
919 | }; | ||
920 | |||
921 | static const struct sockaddr_in6 rpc_in6addr_loopback = { | ||
922 | .sin6_family = AF_INET6, | ||
923 | .sin6_addr = IN6ADDR_ANY_INIT, | ||
924 | }; | ||
925 | |||
926 | /* | ||
927 | * Try a getsockname() on a connected datagram socket. Using a | ||
928 | * connected datagram socket prevents leaving a socket in TIME_WAIT. | ||
929 | * This conserves the ephemeral port number space. | ||
930 | * | ||
931 | * Returns zero and fills in "buf" if successful; otherwise, a | ||
932 | * negative errno is returned. | ||
933 | */ | ||
934 | static int rpc_sockname(struct net *net, struct sockaddr *sap, size_t salen, | ||
935 | struct sockaddr *buf, int buflen) | ||
936 | { | ||
937 | struct socket *sock; | ||
938 | int err; | ||
939 | |||
940 | err = __sock_create(net, sap->sa_family, | ||
941 | SOCK_DGRAM, IPPROTO_UDP, &sock, 1); | ||
942 | if (err < 0) { | ||
943 | dprintk("RPC: can't create UDP socket (%d)\n", err); | ||
944 | goto out; | ||
945 | } | ||
946 | |||
947 | switch (sap->sa_family) { | ||
948 | case AF_INET: | ||
949 | err = kernel_bind(sock, | ||
950 | (struct sockaddr *)&rpc_inaddr_loopback, | ||
951 | sizeof(rpc_inaddr_loopback)); | ||
952 | break; | ||
953 | case AF_INET6: | ||
954 | err = kernel_bind(sock, | ||
955 | (struct sockaddr *)&rpc_in6addr_loopback, | ||
956 | sizeof(rpc_in6addr_loopback)); | ||
957 | break; | ||
958 | default: | ||
959 | err = -EAFNOSUPPORT; | ||
960 | goto out; | ||
961 | } | ||
962 | if (err < 0) { | ||
963 | dprintk("RPC: can't bind UDP socket (%d)\n", err); | ||
964 | goto out_release; | ||
965 | } | ||
966 | |||
967 | err = kernel_connect(sock, sap, salen, 0); | ||
968 | if (err < 0) { | ||
969 | dprintk("RPC: can't connect UDP socket (%d)\n", err); | ||
970 | goto out_release; | ||
971 | } | ||
972 | |||
973 | err = kernel_getsockname(sock, buf, &buflen); | ||
974 | if (err < 0) { | ||
975 | dprintk("RPC: getsockname failed (%d)\n", err); | ||
976 | goto out_release; | ||
977 | } | ||
978 | |||
979 | err = 0; | ||
980 | if (buf->sa_family == AF_INET6) { | ||
981 | struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)buf; | ||
982 | sin6->sin6_scope_id = 0; | ||
983 | } | ||
984 | dprintk("RPC: %s succeeded\n", __func__); | ||
985 | |||
986 | out_release: | ||
987 | sock_release(sock); | ||
988 | out: | ||
989 | return err; | ||
990 | } | ||
991 | |||
992 | /* | ||
993 | * Scraping a connected socket failed, so we don't have a useable | ||
994 | * local address. Fallback: generate an address that will prevent | ||
995 | * the server from calling us back. | ||
996 | * | ||
997 | * Returns zero and fills in "buf" if successful; otherwise, a | ||
998 | * negative errno is returned. | ||
999 | */ | ||
1000 | static int rpc_anyaddr(int family, struct sockaddr *buf, size_t buflen) | ||
1001 | { | ||
1002 | switch (family) { | ||
1003 | case AF_INET: | ||
1004 | if (buflen < sizeof(rpc_inaddr_loopback)) | ||
1005 | return -EINVAL; | ||
1006 | memcpy(buf, &rpc_inaddr_loopback, | ||
1007 | sizeof(rpc_inaddr_loopback)); | ||
1008 | break; | ||
1009 | case AF_INET6: | ||
1010 | if (buflen < sizeof(rpc_in6addr_loopback)) | ||
1011 | return -EINVAL; | ||
1012 | memcpy(buf, &rpc_in6addr_loopback, | ||
1013 | sizeof(rpc_in6addr_loopback)); | ||
1014 | default: | ||
1015 | dprintk("RPC: %s: address family not supported\n", | ||
1016 | __func__); | ||
1017 | return -EAFNOSUPPORT; | ||
1018 | } | ||
1019 | dprintk("RPC: %s: succeeded\n", __func__); | ||
1020 | return 0; | ||
1021 | } | ||
1022 | |||
1023 | /** | ||
1024 | * rpc_localaddr - discover local endpoint address for an RPC client | ||
1025 | * @clnt: RPC client structure | ||
1026 | * @buf: target buffer | ||
1027 | * @buflen: size of target buffer, in bytes | ||
1028 | * | ||
1029 | * Returns zero and fills in "buf" and "buflen" if successful; | ||
1030 | * otherwise, a negative errno is returned. | ||
1031 | * | ||
1032 | * This works even if the underlying transport is not currently connected, | ||
1033 | * or if the upper layer never previously provided a source address. | ||
1034 | * | ||
1035 | * The result of this function call is transient: multiple calls in | ||
1036 | * succession may give different results, depending on how local | ||
1037 | * networking configuration changes over time. | ||
1038 | */ | ||
1039 | int rpc_localaddr(struct rpc_clnt *clnt, struct sockaddr *buf, size_t buflen) | ||
1040 | { | ||
1041 | struct sockaddr_storage address; | ||
1042 | struct sockaddr *sap = (struct sockaddr *)&address; | ||
1043 | struct rpc_xprt *xprt; | ||
1044 | struct net *net; | ||
1045 | size_t salen; | ||
1046 | int err; | ||
1047 | |||
1048 | rcu_read_lock(); | ||
1049 | xprt = rcu_dereference(clnt->cl_xprt); | ||
1050 | salen = xprt->addrlen; | ||
1051 | memcpy(sap, &xprt->addr, salen); | ||
1052 | net = get_net(xprt->xprt_net); | ||
1053 | rcu_read_unlock(); | ||
1054 | |||
1055 | rpc_set_port(sap, 0); | ||
1056 | err = rpc_sockname(net, sap, salen, buf, buflen); | ||
1057 | put_net(net); | ||
1058 | if (err != 0) | ||
1059 | /* Couldn't discover local address, return ANYADDR */ | ||
1060 | return rpc_anyaddr(sap->sa_family, buf, buflen); | ||
1061 | return 0; | ||
1062 | } | ||
1063 | EXPORT_SYMBOL_GPL(rpc_localaddr); | ||
1064 | |||
809 | void | 1065 | void |
810 | rpc_setbufsize(struct rpc_clnt *clnt, unsigned int sndsize, unsigned int rcvsize) | 1066 | rpc_setbufsize(struct rpc_clnt *clnt, unsigned int sndsize, unsigned int rcvsize) |
811 | { | 1067 | { |
812 | struct rpc_xprt *xprt = clnt->cl_xprt; | 1068 | struct rpc_xprt *xprt; |
1069 | |||
1070 | rcu_read_lock(); | ||
1071 | xprt = rcu_dereference(clnt->cl_xprt); | ||
813 | if (xprt->ops->set_buffer_size) | 1072 | if (xprt->ops->set_buffer_size) |
814 | xprt->ops->set_buffer_size(xprt, sndsize, rcvsize); | 1073 | xprt->ops->set_buffer_size(xprt, sndsize, rcvsize); |
1074 | rcu_read_unlock(); | ||
815 | } | 1075 | } |
816 | EXPORT_SYMBOL_GPL(rpc_setbufsize); | 1076 | EXPORT_SYMBOL_GPL(rpc_setbufsize); |
817 | 1077 | ||
818 | /* | 1078 | /** |
819 | * Return size of largest payload RPC client can support, in bytes | 1079 | * rpc_protocol - Get transport protocol number for an RPC client |
1080 | * @clnt: RPC client to query | ||
1081 | * | ||
1082 | */ | ||
1083 | int rpc_protocol(struct rpc_clnt *clnt) | ||
1084 | { | ||
1085 | int protocol; | ||
1086 | |||
1087 | rcu_read_lock(); | ||
1088 | protocol = rcu_dereference(clnt->cl_xprt)->prot; | ||
1089 | rcu_read_unlock(); | ||
1090 | return protocol; | ||
1091 | } | ||
1092 | EXPORT_SYMBOL_GPL(rpc_protocol); | ||
1093 | |||
1094 | /** | ||
1095 | * rpc_net_ns - Get the network namespace for this RPC client | ||
1096 | * @clnt: RPC client to query | ||
1097 | * | ||
1098 | */ | ||
1099 | struct net *rpc_net_ns(struct rpc_clnt *clnt) | ||
1100 | { | ||
1101 | struct net *ret; | ||
1102 | |||
1103 | rcu_read_lock(); | ||
1104 | ret = rcu_dereference(clnt->cl_xprt)->xprt_net; | ||
1105 | rcu_read_unlock(); | ||
1106 | return ret; | ||
1107 | } | ||
1108 | EXPORT_SYMBOL_GPL(rpc_net_ns); | ||
1109 | |||
1110 | /** | ||
1111 | * rpc_max_payload - Get maximum payload size for a transport, in bytes | ||
1112 | * @clnt: RPC client to query | ||
820 | * | 1113 | * |
821 | * For stream transports, this is one RPC record fragment (see RFC | 1114 | * For stream transports, this is one RPC record fragment (see RFC |
822 | * 1831), as we don't support multi-record requests yet. For datagram | 1115 | * 1831), as we don't support multi-record requests yet. For datagram |
@@ -825,7 +1118,12 @@ EXPORT_SYMBOL_GPL(rpc_setbufsize); | |||
825 | */ | 1118 | */ |
826 | size_t rpc_max_payload(struct rpc_clnt *clnt) | 1119 | size_t rpc_max_payload(struct rpc_clnt *clnt) |
827 | { | 1120 | { |
828 | return clnt->cl_xprt->max_payload; | 1121 | size_t ret; |
1122 | |||
1123 | rcu_read_lock(); | ||
1124 | ret = rcu_dereference(clnt->cl_xprt)->max_payload; | ||
1125 | rcu_read_unlock(); | ||
1126 | return ret; | ||
829 | } | 1127 | } |
830 | EXPORT_SYMBOL_GPL(rpc_max_payload); | 1128 | EXPORT_SYMBOL_GPL(rpc_max_payload); |
831 | 1129 | ||
@@ -836,8 +1134,11 @@ EXPORT_SYMBOL_GPL(rpc_max_payload); | |||
836 | */ | 1134 | */ |
837 | void rpc_force_rebind(struct rpc_clnt *clnt) | 1135 | void rpc_force_rebind(struct rpc_clnt *clnt) |
838 | { | 1136 | { |
839 | if (clnt->cl_autobind) | 1137 | if (clnt->cl_autobind) { |
840 | xprt_clear_bound(clnt->cl_xprt); | 1138 | rcu_read_lock(); |
1139 | xprt_clear_bound(rcu_dereference(clnt->cl_xprt)); | ||
1140 | rcu_read_unlock(); | ||
1141 | } | ||
841 | } | 1142 | } |
842 | EXPORT_SYMBOL_GPL(rpc_force_rebind); | 1143 | EXPORT_SYMBOL_GPL(rpc_force_rebind); |
843 | 1144 | ||
@@ -1163,6 +1464,7 @@ call_bind_status(struct rpc_task *task) | |||
1163 | return; | 1464 | return; |
1164 | } | 1465 | } |
1165 | 1466 | ||
1467 | trace_rpc_bind_status(task); | ||
1166 | switch (task->tk_status) { | 1468 | switch (task->tk_status) { |
1167 | case -ENOMEM: | 1469 | case -ENOMEM: |
1168 | dprintk("RPC: %5u rpcbind out of memory\n", task->tk_pid); | 1470 | dprintk("RPC: %5u rpcbind out of memory\n", task->tk_pid); |
@@ -1262,6 +1564,7 @@ call_connect_status(struct rpc_task *task) | |||
1262 | return; | 1564 | return; |
1263 | } | 1565 | } |
1264 | 1566 | ||
1567 | trace_rpc_connect_status(task, status); | ||
1265 | switch (status) { | 1568 | switch (status) { |
1266 | /* if soft mounted, test if we've timed out */ | 1569 | /* if soft mounted, test if we've timed out */ |
1267 | case -ETIMEDOUT: | 1570 | case -ETIMEDOUT: |
@@ -1450,6 +1753,7 @@ call_status(struct rpc_task *task) | |||
1450 | return; | 1753 | return; |
1451 | } | 1754 | } |
1452 | 1755 | ||
1756 | trace_rpc_call_status(task); | ||
1453 | task->tk_status = 0; | 1757 | task->tk_status = 0; |
1454 | switch(status) { | 1758 | switch(status) { |
1455 | case -EHOSTDOWN: | 1759 | case -EHOSTDOWN: |
@@ -1513,8 +1817,11 @@ call_timeout(struct rpc_task *task) | |||
1513 | } | 1817 | } |
1514 | if (RPC_IS_SOFT(task)) { | 1818 | if (RPC_IS_SOFT(task)) { |
1515 | if (clnt->cl_chatty) | 1819 | if (clnt->cl_chatty) |
1820 | rcu_read_lock(); | ||
1516 | printk(KERN_NOTICE "%s: server %s not responding, timed out\n", | 1821 | printk(KERN_NOTICE "%s: server %s not responding, timed out\n", |
1517 | clnt->cl_protname, clnt->cl_server); | 1822 | clnt->cl_protname, |
1823 | rcu_dereference(clnt->cl_xprt)->servername); | ||
1824 | rcu_read_unlock(); | ||
1518 | if (task->tk_flags & RPC_TASK_TIMEOUT) | 1825 | if (task->tk_flags & RPC_TASK_TIMEOUT) |
1519 | rpc_exit(task, -ETIMEDOUT); | 1826 | rpc_exit(task, -ETIMEDOUT); |
1520 | else | 1827 | else |
@@ -1524,9 +1831,13 @@ call_timeout(struct rpc_task *task) | |||
1524 | 1831 | ||
1525 | if (!(task->tk_flags & RPC_CALL_MAJORSEEN)) { | 1832 | if (!(task->tk_flags & RPC_CALL_MAJORSEEN)) { |
1526 | task->tk_flags |= RPC_CALL_MAJORSEEN; | 1833 | task->tk_flags |= RPC_CALL_MAJORSEEN; |
1527 | if (clnt->cl_chatty) | 1834 | if (clnt->cl_chatty) { |
1835 | rcu_read_lock(); | ||
1528 | printk(KERN_NOTICE "%s: server %s not responding, still trying\n", | 1836 | printk(KERN_NOTICE "%s: server %s not responding, still trying\n", |
1529 | clnt->cl_protname, clnt->cl_server); | 1837 | clnt->cl_protname, |
1838 | rcu_dereference(clnt->cl_xprt)->servername); | ||
1839 | rcu_read_unlock(); | ||
1840 | } | ||
1530 | } | 1841 | } |
1531 | rpc_force_rebind(clnt); | 1842 | rpc_force_rebind(clnt); |
1532 | /* | 1843 | /* |
@@ -1555,9 +1866,13 @@ call_decode(struct rpc_task *task) | |||
1555 | dprint_status(task); | 1866 | dprint_status(task); |
1556 | 1867 | ||
1557 | if (task->tk_flags & RPC_CALL_MAJORSEEN) { | 1868 | if (task->tk_flags & RPC_CALL_MAJORSEEN) { |
1558 | if (clnt->cl_chatty) | 1869 | if (clnt->cl_chatty) { |
1870 | rcu_read_lock(); | ||
1559 | printk(KERN_NOTICE "%s: server %s OK\n", | 1871 | printk(KERN_NOTICE "%s: server %s OK\n", |
1560 | clnt->cl_protname, clnt->cl_server); | 1872 | clnt->cl_protname, |
1873 | rcu_dereference(clnt->cl_xprt)->servername); | ||
1874 | rcu_read_unlock(); | ||
1875 | } | ||
1561 | task->tk_flags &= ~RPC_CALL_MAJORSEEN; | 1876 | task->tk_flags &= ~RPC_CALL_MAJORSEEN; |
1562 | } | 1877 | } |
1563 | 1878 | ||
@@ -1635,6 +1950,7 @@ rpc_encode_header(struct rpc_task *task) | |||
1635 | static __be32 * | 1950 | static __be32 * |
1636 | rpc_verify_header(struct rpc_task *task) | 1951 | rpc_verify_header(struct rpc_task *task) |
1637 | { | 1952 | { |
1953 | struct rpc_clnt *clnt = task->tk_client; | ||
1638 | struct kvec *iov = &task->tk_rqstp->rq_rcv_buf.head[0]; | 1954 | struct kvec *iov = &task->tk_rqstp->rq_rcv_buf.head[0]; |
1639 | int len = task->tk_rqstp->rq_rcv_buf.len >> 2; | 1955 | int len = task->tk_rqstp->rq_rcv_buf.len >> 2; |
1640 | __be32 *p = iov->iov_base; | 1956 | __be32 *p = iov->iov_base; |
@@ -1707,8 +2023,11 @@ rpc_verify_header(struct rpc_task *task) | |||
1707 | task->tk_action = call_bind; | 2023 | task->tk_action = call_bind; |
1708 | goto out_retry; | 2024 | goto out_retry; |
1709 | case RPC_AUTH_TOOWEAK: | 2025 | case RPC_AUTH_TOOWEAK: |
2026 | rcu_read_lock(); | ||
1710 | printk(KERN_NOTICE "RPC: server %s requires stronger " | 2027 | printk(KERN_NOTICE "RPC: server %s requires stronger " |
1711 | "authentication.\n", task->tk_client->cl_server); | 2028 | "authentication.\n", |
2029 | rcu_dereference(clnt->cl_xprt)->servername); | ||
2030 | rcu_read_unlock(); | ||
1712 | break; | 2031 | break; |
1713 | default: | 2032 | default: |
1714 | dprintk("RPC: %5u %s: unknown auth error: %x\n", | 2033 | dprintk("RPC: %5u %s: unknown auth error: %x\n", |
@@ -1731,28 +2050,27 @@ rpc_verify_header(struct rpc_task *task) | |||
1731 | case RPC_SUCCESS: | 2050 | case RPC_SUCCESS: |
1732 | return p; | 2051 | return p; |
1733 | case RPC_PROG_UNAVAIL: | 2052 | case RPC_PROG_UNAVAIL: |
1734 | dprintk("RPC: %5u %s: program %u is unsupported by server %s\n", | 2053 | dprintk_rcu("RPC: %5u %s: program %u is unsupported " |
1735 | task->tk_pid, __func__, | 2054 | "by server %s\n", task->tk_pid, __func__, |
1736 | (unsigned int)task->tk_client->cl_prog, | 2055 | (unsigned int)clnt->cl_prog, |
1737 | task->tk_client->cl_server); | 2056 | rcu_dereference(clnt->cl_xprt)->servername); |
1738 | error = -EPFNOSUPPORT; | 2057 | error = -EPFNOSUPPORT; |
1739 | goto out_err; | 2058 | goto out_err; |
1740 | case RPC_PROG_MISMATCH: | 2059 | case RPC_PROG_MISMATCH: |
1741 | dprintk("RPC: %5u %s: program %u, version %u unsupported by " | 2060 | dprintk_rcu("RPC: %5u %s: program %u, version %u unsupported " |
1742 | "server %s\n", task->tk_pid, __func__, | 2061 | "by server %s\n", task->tk_pid, __func__, |
1743 | (unsigned int)task->tk_client->cl_prog, | 2062 | (unsigned int)clnt->cl_prog, |
1744 | (unsigned int)task->tk_client->cl_vers, | 2063 | (unsigned int)clnt->cl_vers, |
1745 | task->tk_client->cl_server); | 2064 | rcu_dereference(clnt->cl_xprt)->servername); |
1746 | error = -EPROTONOSUPPORT; | 2065 | error = -EPROTONOSUPPORT; |
1747 | goto out_err; | 2066 | goto out_err; |
1748 | case RPC_PROC_UNAVAIL: | 2067 | case RPC_PROC_UNAVAIL: |
1749 | dprintk("RPC: %5u %s: proc %s unsupported by program %u, " | 2068 | dprintk_rcu("RPC: %5u %s: proc %s unsupported by program %u, " |
1750 | "version %u on server %s\n", | 2069 | "version %u on server %s\n", |
1751 | task->tk_pid, __func__, | 2070 | task->tk_pid, __func__, |
1752 | rpc_proc_name(task), | 2071 | rpc_proc_name(task), |
1753 | task->tk_client->cl_prog, | 2072 | clnt->cl_prog, clnt->cl_vers, |
1754 | task->tk_client->cl_vers, | 2073 | rcu_dereference(clnt->cl_xprt)->servername); |
1755 | task->tk_client->cl_server); | ||
1756 | error = -EOPNOTSUPP; | 2074 | error = -EOPNOTSUPP; |
1757 | goto out_err; | 2075 | goto out_err; |
1758 | case RPC_GARBAGE_ARGS: | 2076 | case RPC_GARBAGE_ARGS: |
@@ -1766,7 +2084,7 @@ rpc_verify_header(struct rpc_task *task) | |||
1766 | } | 2084 | } |
1767 | 2085 | ||
1768 | out_garbage: | 2086 | out_garbage: |
1769 | task->tk_client->cl_stats->rpcgarbage++; | 2087 | clnt->cl_stats->rpcgarbage++; |
1770 | if (task->tk_garb_retry) { | 2088 | if (task->tk_garb_retry) { |
1771 | task->tk_garb_retry--; | 2089 | task->tk_garb_retry--; |
1772 | dprintk("RPC: %5u %s: retrying\n", | 2090 | dprintk("RPC: %5u %s: retrying\n", |
@@ -1852,14 +2170,15 @@ static void rpc_show_task(const struct rpc_clnt *clnt, | |||
1852 | task->tk_action, rpc_waitq); | 2170 | task->tk_action, rpc_waitq); |
1853 | } | 2171 | } |
1854 | 2172 | ||
1855 | void rpc_show_tasks(void) | 2173 | void rpc_show_tasks(struct net *net) |
1856 | { | 2174 | { |
1857 | struct rpc_clnt *clnt; | 2175 | struct rpc_clnt *clnt; |
1858 | struct rpc_task *task; | 2176 | struct rpc_task *task; |
1859 | int header = 0; | 2177 | int header = 0; |
2178 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
1860 | 2179 | ||
1861 | spin_lock(&rpc_client_lock); | 2180 | spin_lock(&sn->rpc_client_lock); |
1862 | list_for_each_entry(clnt, &all_clients, cl_clients) { | 2181 | list_for_each_entry(clnt, &sn->all_clients, cl_clients) { |
1863 | spin_lock(&clnt->cl_lock); | 2182 | spin_lock(&clnt->cl_lock); |
1864 | list_for_each_entry(task, &clnt->cl_tasks, tk_task) { | 2183 | list_for_each_entry(task, &clnt->cl_tasks, tk_task) { |
1865 | if (!header) { | 2184 | if (!header) { |
@@ -1870,6 +2189,6 @@ void rpc_show_tasks(void) | |||
1870 | } | 2189 | } |
1871 | spin_unlock(&clnt->cl_lock); | 2190 | spin_unlock(&clnt->cl_lock); |
1872 | } | 2191 | } |
1873 | spin_unlock(&rpc_client_lock); | 2192 | spin_unlock(&sn->rpc_client_lock); |
1874 | } | 2193 | } |
1875 | #endif | 2194 | #endif |
diff --git a/net/sunrpc/netns.h b/net/sunrpc/netns.h index d013bf211cae..ce7bd449173d 100644 --- a/net/sunrpc/netns.h +++ b/net/sunrpc/netns.h | |||
@@ -9,6 +9,20 @@ struct cache_detail; | |||
9 | struct sunrpc_net { | 9 | struct sunrpc_net { |
10 | struct proc_dir_entry *proc_net_rpc; | 10 | struct proc_dir_entry *proc_net_rpc; |
11 | struct cache_detail *ip_map_cache; | 11 | struct cache_detail *ip_map_cache; |
12 | struct cache_detail *unix_gid_cache; | ||
13 | struct cache_detail *rsc_cache; | ||
14 | struct cache_detail *rsi_cache; | ||
15 | |||
16 | struct super_block *pipefs_sb; | ||
17 | struct mutex pipefs_sb_lock; | ||
18 | |||
19 | struct list_head all_clients; | ||
20 | spinlock_t rpc_client_lock; | ||
21 | |||
22 | struct rpc_clnt *rpcb_local_clnt; | ||
23 | struct rpc_clnt *rpcb_local_clnt4; | ||
24 | spinlock_t rpcb_clnt_lock; | ||
25 | unsigned int rpcb_users; | ||
12 | }; | 26 | }; |
13 | 27 | ||
14 | extern int sunrpc_net_id; | 28 | extern int sunrpc_net_id; |
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index 63a7a7add21e..0af37fc46818 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c | |||
@@ -16,9 +16,9 @@ | |||
16 | #include <linux/namei.h> | 16 | #include <linux/namei.h> |
17 | #include <linux/fsnotify.h> | 17 | #include <linux/fsnotify.h> |
18 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
19 | #include <linux/rcupdate.h> | ||
19 | 20 | ||
20 | #include <asm/ioctls.h> | 21 | #include <asm/ioctls.h> |
21 | #include <linux/fs.h> | ||
22 | #include <linux/poll.h> | 22 | #include <linux/poll.h> |
23 | #include <linux/wait.h> | 23 | #include <linux/wait.h> |
24 | #include <linux/seq_file.h> | 24 | #include <linux/seq_file.h> |
@@ -27,9 +27,15 @@ | |||
27 | #include <linux/workqueue.h> | 27 | #include <linux/workqueue.h> |
28 | #include <linux/sunrpc/rpc_pipe_fs.h> | 28 | #include <linux/sunrpc/rpc_pipe_fs.h> |
29 | #include <linux/sunrpc/cache.h> | 29 | #include <linux/sunrpc/cache.h> |
30 | #include <linux/nsproxy.h> | ||
31 | #include <linux/notifier.h> | ||
30 | 32 | ||
31 | static struct vfsmount *rpc_mnt __read_mostly; | 33 | #include "netns.h" |
32 | static int rpc_mount_count; | 34 | #include "sunrpc.h" |
35 | |||
36 | #define RPCDBG_FACILITY RPCDBG_DEBUG | ||
37 | |||
38 | #define NET_NAME(net) ((net == &init_net) ? " (init_net)" : "") | ||
33 | 39 | ||
34 | static struct file_system_type rpc_pipe_fs_type; | 40 | static struct file_system_type rpc_pipe_fs_type; |
35 | 41 | ||
@@ -38,7 +44,21 @@ static struct kmem_cache *rpc_inode_cachep __read_mostly; | |||
38 | 44 | ||
39 | #define RPC_UPCALL_TIMEOUT (30*HZ) | 45 | #define RPC_UPCALL_TIMEOUT (30*HZ) |
40 | 46 | ||
41 | static void rpc_purge_list(struct rpc_inode *rpci, struct list_head *head, | 47 | static BLOCKING_NOTIFIER_HEAD(rpc_pipefs_notifier_list); |
48 | |||
49 | int rpc_pipefs_notifier_register(struct notifier_block *nb) | ||
50 | { | ||
51 | return blocking_notifier_chain_cond_register(&rpc_pipefs_notifier_list, nb); | ||
52 | } | ||
53 | EXPORT_SYMBOL_GPL(rpc_pipefs_notifier_register); | ||
54 | |||
55 | void rpc_pipefs_notifier_unregister(struct notifier_block *nb) | ||
56 | { | ||
57 | blocking_notifier_chain_unregister(&rpc_pipefs_notifier_list, nb); | ||
58 | } | ||
59 | EXPORT_SYMBOL_GPL(rpc_pipefs_notifier_unregister); | ||
60 | |||
61 | static void rpc_purge_list(wait_queue_head_t *waitq, struct list_head *head, | ||
42 | void (*destroy_msg)(struct rpc_pipe_msg *), int err) | 62 | void (*destroy_msg)(struct rpc_pipe_msg *), int err) |
43 | { | 63 | { |
44 | struct rpc_pipe_msg *msg; | 64 | struct rpc_pipe_msg *msg; |
@@ -51,30 +71,31 @@ static void rpc_purge_list(struct rpc_inode *rpci, struct list_head *head, | |||
51 | msg->errno = err; | 71 | msg->errno = err; |
52 | destroy_msg(msg); | 72 | destroy_msg(msg); |
53 | } while (!list_empty(head)); | 73 | } while (!list_empty(head)); |
54 | wake_up(&rpci->waitq); | 74 | wake_up(waitq); |
55 | } | 75 | } |
56 | 76 | ||
57 | static void | 77 | static void |
58 | rpc_timeout_upcall_queue(struct work_struct *work) | 78 | rpc_timeout_upcall_queue(struct work_struct *work) |
59 | { | 79 | { |
60 | LIST_HEAD(free_list); | 80 | LIST_HEAD(free_list); |
61 | struct rpc_inode *rpci = | 81 | struct rpc_pipe *pipe = |
62 | container_of(work, struct rpc_inode, queue_timeout.work); | 82 | container_of(work, struct rpc_pipe, queue_timeout.work); |
63 | struct inode *inode = &rpci->vfs_inode; | ||
64 | void (*destroy_msg)(struct rpc_pipe_msg *); | 83 | void (*destroy_msg)(struct rpc_pipe_msg *); |
84 | struct dentry *dentry; | ||
65 | 85 | ||
66 | spin_lock(&inode->i_lock); | 86 | spin_lock(&pipe->lock); |
67 | if (rpci->ops == NULL) { | 87 | destroy_msg = pipe->ops->destroy_msg; |
68 | spin_unlock(&inode->i_lock); | 88 | if (pipe->nreaders == 0) { |
69 | return; | 89 | list_splice_init(&pipe->pipe, &free_list); |
90 | pipe->pipelen = 0; | ||
70 | } | 91 | } |
71 | destroy_msg = rpci->ops->destroy_msg; | 92 | dentry = dget(pipe->dentry); |
72 | if (rpci->nreaders == 0) { | 93 | spin_unlock(&pipe->lock); |
73 | list_splice_init(&rpci->pipe, &free_list); | 94 | if (dentry) { |
74 | rpci->pipelen = 0; | 95 | rpc_purge_list(&RPC_I(dentry->d_inode)->waitq, |
96 | &free_list, destroy_msg, -ETIMEDOUT); | ||
97 | dput(dentry); | ||
75 | } | 98 | } |
76 | spin_unlock(&inode->i_lock); | ||
77 | rpc_purge_list(rpci, &free_list, destroy_msg, -ETIMEDOUT); | ||
78 | } | 99 | } |
79 | 100 | ||
80 | ssize_t rpc_pipe_generic_upcall(struct file *filp, struct rpc_pipe_msg *msg, | 101 | ssize_t rpc_pipe_generic_upcall(struct file *filp, struct rpc_pipe_msg *msg, |
@@ -108,30 +129,31 @@ EXPORT_SYMBOL_GPL(rpc_pipe_generic_upcall); | |||
108 | * initialize the fields of @msg (other than @msg->list) appropriately. | 129 | * initialize the fields of @msg (other than @msg->list) appropriately. |
109 | */ | 130 | */ |
110 | int | 131 | int |
111 | rpc_queue_upcall(struct inode *inode, struct rpc_pipe_msg *msg) | 132 | rpc_queue_upcall(struct rpc_pipe *pipe, struct rpc_pipe_msg *msg) |
112 | { | 133 | { |
113 | struct rpc_inode *rpci = RPC_I(inode); | ||
114 | int res = -EPIPE; | 134 | int res = -EPIPE; |
135 | struct dentry *dentry; | ||
115 | 136 | ||
116 | spin_lock(&inode->i_lock); | 137 | spin_lock(&pipe->lock); |
117 | if (rpci->ops == NULL) | 138 | if (pipe->nreaders) { |
118 | goto out; | 139 | list_add_tail(&msg->list, &pipe->pipe); |
119 | if (rpci->nreaders) { | 140 | pipe->pipelen += msg->len; |
120 | list_add_tail(&msg->list, &rpci->pipe); | ||
121 | rpci->pipelen += msg->len; | ||
122 | res = 0; | 141 | res = 0; |
123 | } else if (rpci->flags & RPC_PIPE_WAIT_FOR_OPEN) { | 142 | } else if (pipe->flags & RPC_PIPE_WAIT_FOR_OPEN) { |
124 | if (list_empty(&rpci->pipe)) | 143 | if (list_empty(&pipe->pipe)) |
125 | queue_delayed_work(rpciod_workqueue, | 144 | queue_delayed_work(rpciod_workqueue, |
126 | &rpci->queue_timeout, | 145 | &pipe->queue_timeout, |
127 | RPC_UPCALL_TIMEOUT); | 146 | RPC_UPCALL_TIMEOUT); |
128 | list_add_tail(&msg->list, &rpci->pipe); | 147 | list_add_tail(&msg->list, &pipe->pipe); |
129 | rpci->pipelen += msg->len; | 148 | pipe->pipelen += msg->len; |
130 | res = 0; | 149 | res = 0; |
131 | } | 150 | } |
132 | out: | 151 | dentry = dget(pipe->dentry); |
133 | spin_unlock(&inode->i_lock); | 152 | spin_unlock(&pipe->lock); |
134 | wake_up(&rpci->waitq); | 153 | if (dentry) { |
154 | wake_up(&RPC_I(dentry->d_inode)->waitq); | ||
155 | dput(dentry); | ||
156 | } | ||
135 | return res; | 157 | return res; |
136 | } | 158 | } |
137 | EXPORT_SYMBOL_GPL(rpc_queue_upcall); | 159 | EXPORT_SYMBOL_GPL(rpc_queue_upcall); |
@@ -145,29 +167,26 @@ rpc_inode_setowner(struct inode *inode, void *private) | |||
145 | static void | 167 | static void |
146 | rpc_close_pipes(struct inode *inode) | 168 | rpc_close_pipes(struct inode *inode) |
147 | { | 169 | { |
148 | struct rpc_inode *rpci = RPC_I(inode); | 170 | struct rpc_pipe *pipe = RPC_I(inode)->pipe; |
149 | const struct rpc_pipe_ops *ops; | ||
150 | int need_release; | 171 | int need_release; |
172 | LIST_HEAD(free_list); | ||
151 | 173 | ||
152 | mutex_lock(&inode->i_mutex); | 174 | mutex_lock(&inode->i_mutex); |
153 | ops = rpci->ops; | 175 | spin_lock(&pipe->lock); |
154 | if (ops != NULL) { | 176 | need_release = pipe->nreaders != 0 || pipe->nwriters != 0; |
155 | LIST_HEAD(free_list); | 177 | pipe->nreaders = 0; |
156 | spin_lock(&inode->i_lock); | 178 | list_splice_init(&pipe->in_upcall, &free_list); |
157 | need_release = rpci->nreaders != 0 || rpci->nwriters != 0; | 179 | list_splice_init(&pipe->pipe, &free_list); |
158 | rpci->nreaders = 0; | 180 | pipe->pipelen = 0; |
159 | list_splice_init(&rpci->in_upcall, &free_list); | 181 | pipe->dentry = NULL; |
160 | list_splice_init(&rpci->pipe, &free_list); | 182 | spin_unlock(&pipe->lock); |
161 | rpci->pipelen = 0; | 183 | rpc_purge_list(&RPC_I(inode)->waitq, &free_list, pipe->ops->destroy_msg, -EPIPE); |
162 | rpci->ops = NULL; | 184 | pipe->nwriters = 0; |
163 | spin_unlock(&inode->i_lock); | 185 | if (need_release && pipe->ops->release_pipe) |
164 | rpc_purge_list(rpci, &free_list, ops->destroy_msg, -EPIPE); | 186 | pipe->ops->release_pipe(inode); |
165 | rpci->nwriters = 0; | 187 | cancel_delayed_work_sync(&pipe->queue_timeout); |
166 | if (need_release && ops->release_pipe) | ||
167 | ops->release_pipe(inode); | ||
168 | cancel_delayed_work_sync(&rpci->queue_timeout); | ||
169 | } | ||
170 | rpc_inode_setowner(inode, NULL); | 188 | rpc_inode_setowner(inode, NULL); |
189 | RPC_I(inode)->pipe = NULL; | ||
171 | mutex_unlock(&inode->i_mutex); | 190 | mutex_unlock(&inode->i_mutex); |
172 | } | 191 | } |
173 | 192 | ||
@@ -197,23 +216,24 @@ rpc_destroy_inode(struct inode *inode) | |||
197 | static int | 216 | static int |
198 | rpc_pipe_open(struct inode *inode, struct file *filp) | 217 | rpc_pipe_open(struct inode *inode, struct file *filp) |
199 | { | 218 | { |
200 | struct rpc_inode *rpci = RPC_I(inode); | 219 | struct rpc_pipe *pipe; |
201 | int first_open; | 220 | int first_open; |
202 | int res = -ENXIO; | 221 | int res = -ENXIO; |
203 | 222 | ||
204 | mutex_lock(&inode->i_mutex); | 223 | mutex_lock(&inode->i_mutex); |
205 | if (rpci->ops == NULL) | 224 | pipe = RPC_I(inode)->pipe; |
225 | if (pipe == NULL) | ||
206 | goto out; | 226 | goto out; |
207 | first_open = rpci->nreaders == 0 && rpci->nwriters == 0; | 227 | first_open = pipe->nreaders == 0 && pipe->nwriters == 0; |
208 | if (first_open && rpci->ops->open_pipe) { | 228 | if (first_open && pipe->ops->open_pipe) { |
209 | res = rpci->ops->open_pipe(inode); | 229 | res = pipe->ops->open_pipe(inode); |
210 | if (res) | 230 | if (res) |
211 | goto out; | 231 | goto out; |
212 | } | 232 | } |
213 | if (filp->f_mode & FMODE_READ) | 233 | if (filp->f_mode & FMODE_READ) |
214 | rpci->nreaders++; | 234 | pipe->nreaders++; |
215 | if (filp->f_mode & FMODE_WRITE) | 235 | if (filp->f_mode & FMODE_WRITE) |
216 | rpci->nwriters++; | 236 | pipe->nwriters++; |
217 | res = 0; | 237 | res = 0; |
218 | out: | 238 | out: |
219 | mutex_unlock(&inode->i_mutex); | 239 | mutex_unlock(&inode->i_mutex); |
@@ -223,38 +243,39 @@ out: | |||
223 | static int | 243 | static int |
224 | rpc_pipe_release(struct inode *inode, struct file *filp) | 244 | rpc_pipe_release(struct inode *inode, struct file *filp) |
225 | { | 245 | { |
226 | struct rpc_inode *rpci = RPC_I(inode); | 246 | struct rpc_pipe *pipe; |
227 | struct rpc_pipe_msg *msg; | 247 | struct rpc_pipe_msg *msg; |
228 | int last_close; | 248 | int last_close; |
229 | 249 | ||
230 | mutex_lock(&inode->i_mutex); | 250 | mutex_lock(&inode->i_mutex); |
231 | if (rpci->ops == NULL) | 251 | pipe = RPC_I(inode)->pipe; |
252 | if (pipe == NULL) | ||
232 | goto out; | 253 | goto out; |
233 | msg = filp->private_data; | 254 | msg = filp->private_data; |
234 | if (msg != NULL) { | 255 | if (msg != NULL) { |
235 | spin_lock(&inode->i_lock); | 256 | spin_lock(&pipe->lock); |
236 | msg->errno = -EAGAIN; | 257 | msg->errno = -EAGAIN; |
237 | list_del_init(&msg->list); | 258 | list_del_init(&msg->list); |
238 | spin_unlock(&inode->i_lock); | 259 | spin_unlock(&pipe->lock); |
239 | rpci->ops->destroy_msg(msg); | 260 | pipe->ops->destroy_msg(msg); |
240 | } | 261 | } |
241 | if (filp->f_mode & FMODE_WRITE) | 262 | if (filp->f_mode & FMODE_WRITE) |
242 | rpci->nwriters --; | 263 | pipe->nwriters --; |
243 | if (filp->f_mode & FMODE_READ) { | 264 | if (filp->f_mode & FMODE_READ) { |
244 | rpci->nreaders --; | 265 | pipe->nreaders --; |
245 | if (rpci->nreaders == 0) { | 266 | if (pipe->nreaders == 0) { |
246 | LIST_HEAD(free_list); | 267 | LIST_HEAD(free_list); |
247 | spin_lock(&inode->i_lock); | 268 | spin_lock(&pipe->lock); |
248 | list_splice_init(&rpci->pipe, &free_list); | 269 | list_splice_init(&pipe->pipe, &free_list); |
249 | rpci->pipelen = 0; | 270 | pipe->pipelen = 0; |
250 | spin_unlock(&inode->i_lock); | 271 | spin_unlock(&pipe->lock); |
251 | rpc_purge_list(rpci, &free_list, | 272 | rpc_purge_list(&RPC_I(inode)->waitq, &free_list, |
252 | rpci->ops->destroy_msg, -EAGAIN); | 273 | pipe->ops->destroy_msg, -EAGAIN); |
253 | } | 274 | } |
254 | } | 275 | } |
255 | last_close = rpci->nwriters == 0 && rpci->nreaders == 0; | 276 | last_close = pipe->nwriters == 0 && pipe->nreaders == 0; |
256 | if (last_close && rpci->ops->release_pipe) | 277 | if (last_close && pipe->ops->release_pipe) |
257 | rpci->ops->release_pipe(inode); | 278 | pipe->ops->release_pipe(inode); |
258 | out: | 279 | out: |
259 | mutex_unlock(&inode->i_mutex); | 280 | mutex_unlock(&inode->i_mutex); |
260 | return 0; | 281 | return 0; |
@@ -264,39 +285,40 @@ static ssize_t | |||
264 | rpc_pipe_read(struct file *filp, char __user *buf, size_t len, loff_t *offset) | 285 | rpc_pipe_read(struct file *filp, char __user *buf, size_t len, loff_t *offset) |
265 | { | 286 | { |
266 | struct inode *inode = filp->f_path.dentry->d_inode; | 287 | struct inode *inode = filp->f_path.dentry->d_inode; |
267 | struct rpc_inode *rpci = RPC_I(inode); | 288 | struct rpc_pipe *pipe; |
268 | struct rpc_pipe_msg *msg; | 289 | struct rpc_pipe_msg *msg; |
269 | int res = 0; | 290 | int res = 0; |
270 | 291 | ||
271 | mutex_lock(&inode->i_mutex); | 292 | mutex_lock(&inode->i_mutex); |
272 | if (rpci->ops == NULL) { | 293 | pipe = RPC_I(inode)->pipe; |
294 | if (pipe == NULL) { | ||
273 | res = -EPIPE; | 295 | res = -EPIPE; |
274 | goto out_unlock; | 296 | goto out_unlock; |
275 | } | 297 | } |
276 | msg = filp->private_data; | 298 | msg = filp->private_data; |
277 | if (msg == NULL) { | 299 | if (msg == NULL) { |
278 | spin_lock(&inode->i_lock); | 300 | spin_lock(&pipe->lock); |
279 | if (!list_empty(&rpci->pipe)) { | 301 | if (!list_empty(&pipe->pipe)) { |
280 | msg = list_entry(rpci->pipe.next, | 302 | msg = list_entry(pipe->pipe.next, |
281 | struct rpc_pipe_msg, | 303 | struct rpc_pipe_msg, |
282 | list); | 304 | list); |
283 | list_move(&msg->list, &rpci->in_upcall); | 305 | list_move(&msg->list, &pipe->in_upcall); |
284 | rpci->pipelen -= msg->len; | 306 | pipe->pipelen -= msg->len; |
285 | filp->private_data = msg; | 307 | filp->private_data = msg; |
286 | msg->copied = 0; | 308 | msg->copied = 0; |
287 | } | 309 | } |
288 | spin_unlock(&inode->i_lock); | 310 | spin_unlock(&pipe->lock); |
289 | if (msg == NULL) | 311 | if (msg == NULL) |
290 | goto out_unlock; | 312 | goto out_unlock; |
291 | } | 313 | } |
292 | /* NOTE: it is up to the callback to update msg->copied */ | 314 | /* NOTE: it is up to the callback to update msg->copied */ |
293 | res = rpci->ops->upcall(filp, msg, buf, len); | 315 | res = pipe->ops->upcall(filp, msg, buf, len); |
294 | if (res < 0 || msg->len == msg->copied) { | 316 | if (res < 0 || msg->len == msg->copied) { |
295 | filp->private_data = NULL; | 317 | filp->private_data = NULL; |
296 | spin_lock(&inode->i_lock); | 318 | spin_lock(&pipe->lock); |
297 | list_del_init(&msg->list); | 319 | list_del_init(&msg->list); |
298 | spin_unlock(&inode->i_lock); | 320 | spin_unlock(&pipe->lock); |
299 | rpci->ops->destroy_msg(msg); | 321 | pipe->ops->destroy_msg(msg); |
300 | } | 322 | } |
301 | out_unlock: | 323 | out_unlock: |
302 | mutex_unlock(&inode->i_mutex); | 324 | mutex_unlock(&inode->i_mutex); |
@@ -307,13 +329,12 @@ static ssize_t | |||
307 | rpc_pipe_write(struct file *filp, const char __user *buf, size_t len, loff_t *offset) | 329 | rpc_pipe_write(struct file *filp, const char __user *buf, size_t len, loff_t *offset) |
308 | { | 330 | { |
309 | struct inode *inode = filp->f_path.dentry->d_inode; | 331 | struct inode *inode = filp->f_path.dentry->d_inode; |
310 | struct rpc_inode *rpci = RPC_I(inode); | ||
311 | int res; | 332 | int res; |
312 | 333 | ||
313 | mutex_lock(&inode->i_mutex); | 334 | mutex_lock(&inode->i_mutex); |
314 | res = -EPIPE; | 335 | res = -EPIPE; |
315 | if (rpci->ops != NULL) | 336 | if (RPC_I(inode)->pipe != NULL) |
316 | res = rpci->ops->downcall(filp, buf, len); | 337 | res = RPC_I(inode)->pipe->ops->downcall(filp, buf, len); |
317 | mutex_unlock(&inode->i_mutex); | 338 | mutex_unlock(&inode->i_mutex); |
318 | return res; | 339 | return res; |
319 | } | 340 | } |
@@ -321,17 +342,18 @@ rpc_pipe_write(struct file *filp, const char __user *buf, size_t len, loff_t *of | |||
321 | static unsigned int | 342 | static unsigned int |
322 | rpc_pipe_poll(struct file *filp, struct poll_table_struct *wait) | 343 | rpc_pipe_poll(struct file *filp, struct poll_table_struct *wait) |
323 | { | 344 | { |
324 | struct rpc_inode *rpci; | 345 | struct inode *inode = filp->f_path.dentry->d_inode; |
325 | unsigned int mask = 0; | 346 | struct rpc_inode *rpci = RPC_I(inode); |
347 | unsigned int mask = POLLOUT | POLLWRNORM; | ||
326 | 348 | ||
327 | rpci = RPC_I(filp->f_path.dentry->d_inode); | ||
328 | poll_wait(filp, &rpci->waitq, wait); | 349 | poll_wait(filp, &rpci->waitq, wait); |
329 | 350 | ||
330 | mask = POLLOUT | POLLWRNORM; | 351 | mutex_lock(&inode->i_mutex); |
331 | if (rpci->ops == NULL) | 352 | if (rpci->pipe == NULL) |
332 | mask |= POLLERR | POLLHUP; | 353 | mask |= POLLERR | POLLHUP; |
333 | if (filp->private_data || !list_empty(&rpci->pipe)) | 354 | else if (filp->private_data || !list_empty(&rpci->pipe->pipe)) |
334 | mask |= POLLIN | POLLRDNORM; | 355 | mask |= POLLIN | POLLRDNORM; |
356 | mutex_unlock(&inode->i_mutex); | ||
335 | return mask; | 357 | return mask; |
336 | } | 358 | } |
337 | 359 | ||
@@ -339,23 +361,26 @@ static long | |||
339 | rpc_pipe_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | 361 | rpc_pipe_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) |
340 | { | 362 | { |
341 | struct inode *inode = filp->f_path.dentry->d_inode; | 363 | struct inode *inode = filp->f_path.dentry->d_inode; |
342 | struct rpc_inode *rpci = RPC_I(inode); | 364 | struct rpc_pipe *pipe; |
343 | int len; | 365 | int len; |
344 | 366 | ||
345 | switch (cmd) { | 367 | switch (cmd) { |
346 | case FIONREAD: | 368 | case FIONREAD: |
347 | spin_lock(&inode->i_lock); | 369 | mutex_lock(&inode->i_mutex); |
348 | if (rpci->ops == NULL) { | 370 | pipe = RPC_I(inode)->pipe; |
349 | spin_unlock(&inode->i_lock); | 371 | if (pipe == NULL) { |
372 | mutex_unlock(&inode->i_mutex); | ||
350 | return -EPIPE; | 373 | return -EPIPE; |
351 | } | 374 | } |
352 | len = rpci->pipelen; | 375 | spin_lock(&pipe->lock); |
376 | len = pipe->pipelen; | ||
353 | if (filp->private_data) { | 377 | if (filp->private_data) { |
354 | struct rpc_pipe_msg *msg; | 378 | struct rpc_pipe_msg *msg; |
355 | msg = filp->private_data; | 379 | msg = filp->private_data; |
356 | len += msg->len - msg->copied; | 380 | len += msg->len - msg->copied; |
357 | } | 381 | } |
358 | spin_unlock(&inode->i_lock); | 382 | spin_unlock(&pipe->lock); |
383 | mutex_unlock(&inode->i_mutex); | ||
359 | return put_user(len, (int __user *)arg); | 384 | return put_user(len, (int __user *)arg); |
360 | default: | 385 | default: |
361 | return -EINVAL; | 386 | return -EINVAL; |
@@ -378,12 +403,15 @@ rpc_show_info(struct seq_file *m, void *v) | |||
378 | { | 403 | { |
379 | struct rpc_clnt *clnt = m->private; | 404 | struct rpc_clnt *clnt = m->private; |
380 | 405 | ||
381 | seq_printf(m, "RPC server: %s\n", clnt->cl_server); | 406 | rcu_read_lock(); |
407 | seq_printf(m, "RPC server: %s\n", | ||
408 | rcu_dereference(clnt->cl_xprt)->servername); | ||
382 | seq_printf(m, "service: %s (%d) version %d\n", clnt->cl_protname, | 409 | seq_printf(m, "service: %s (%d) version %d\n", clnt->cl_protname, |
383 | clnt->cl_prog, clnt->cl_vers); | 410 | clnt->cl_prog, clnt->cl_vers); |
384 | seq_printf(m, "address: %s\n", rpc_peeraddr2str(clnt, RPC_DISPLAY_ADDR)); | 411 | seq_printf(m, "address: %s\n", rpc_peeraddr2str(clnt, RPC_DISPLAY_ADDR)); |
385 | seq_printf(m, "protocol: %s\n", rpc_peeraddr2str(clnt, RPC_DISPLAY_PROTO)); | 412 | seq_printf(m, "protocol: %s\n", rpc_peeraddr2str(clnt, RPC_DISPLAY_PROTO)); |
386 | seq_printf(m, "port: %s\n", rpc_peeraddr2str(clnt, RPC_DISPLAY_PORT)); | 413 | seq_printf(m, "port: %s\n", rpc_peeraddr2str(clnt, RPC_DISPLAY_PORT)); |
414 | rcu_read_unlock(); | ||
387 | return 0; | 415 | return 0; |
388 | } | 416 | } |
389 | 417 | ||
@@ -440,23 +468,6 @@ struct rpc_filelist { | |||
440 | umode_t mode; | 468 | umode_t mode; |
441 | }; | 469 | }; |
442 | 470 | ||
443 | struct vfsmount *rpc_get_mount(void) | ||
444 | { | ||
445 | int err; | ||
446 | |||
447 | err = simple_pin_fs(&rpc_pipe_fs_type, &rpc_mnt, &rpc_mount_count); | ||
448 | if (err != 0) | ||
449 | return ERR_PTR(err); | ||
450 | return rpc_mnt; | ||
451 | } | ||
452 | EXPORT_SYMBOL_GPL(rpc_get_mount); | ||
453 | |||
454 | void rpc_put_mount(void) | ||
455 | { | ||
456 | simple_release_fs(&rpc_mnt, &rpc_mount_count); | ||
457 | } | ||
458 | EXPORT_SYMBOL_GPL(rpc_put_mount); | ||
459 | |||
460 | static int rpc_delete_dentry(const struct dentry *dentry) | 471 | static int rpc_delete_dentry(const struct dentry *dentry) |
461 | { | 472 | { |
462 | return 1; | 473 | return 1; |
@@ -540,12 +551,47 @@ static int __rpc_mkdir(struct inode *dir, struct dentry *dentry, | |||
540 | return 0; | 551 | return 0; |
541 | } | 552 | } |
542 | 553 | ||
543 | static int __rpc_mkpipe(struct inode *dir, struct dentry *dentry, | 554 | static void |
544 | umode_t mode, | 555 | init_pipe(struct rpc_pipe *pipe) |
545 | const struct file_operations *i_fop, | 556 | { |
546 | void *private, | 557 | pipe->nreaders = 0; |
547 | const struct rpc_pipe_ops *ops, | 558 | pipe->nwriters = 0; |
548 | int flags) | 559 | INIT_LIST_HEAD(&pipe->in_upcall); |
560 | INIT_LIST_HEAD(&pipe->in_downcall); | ||
561 | INIT_LIST_HEAD(&pipe->pipe); | ||
562 | pipe->pipelen = 0; | ||
563 | INIT_DELAYED_WORK(&pipe->queue_timeout, | ||
564 | rpc_timeout_upcall_queue); | ||
565 | pipe->ops = NULL; | ||
566 | spin_lock_init(&pipe->lock); | ||
567 | pipe->dentry = NULL; | ||
568 | } | ||
569 | |||
570 | void rpc_destroy_pipe_data(struct rpc_pipe *pipe) | ||
571 | { | ||
572 | kfree(pipe); | ||
573 | } | ||
574 | EXPORT_SYMBOL_GPL(rpc_destroy_pipe_data); | ||
575 | |||
576 | struct rpc_pipe *rpc_mkpipe_data(const struct rpc_pipe_ops *ops, int flags) | ||
577 | { | ||
578 | struct rpc_pipe *pipe; | ||
579 | |||
580 | pipe = kzalloc(sizeof(struct rpc_pipe), GFP_KERNEL); | ||
581 | if (!pipe) | ||
582 | return ERR_PTR(-ENOMEM); | ||
583 | init_pipe(pipe); | ||
584 | pipe->ops = ops; | ||
585 | pipe->flags = flags; | ||
586 | return pipe; | ||
587 | } | ||
588 | EXPORT_SYMBOL_GPL(rpc_mkpipe_data); | ||
589 | |||
590 | static int __rpc_mkpipe_dentry(struct inode *dir, struct dentry *dentry, | ||
591 | umode_t mode, | ||
592 | const struct file_operations *i_fop, | ||
593 | void *private, | ||
594 | struct rpc_pipe *pipe) | ||
549 | { | 595 | { |
550 | struct rpc_inode *rpci; | 596 | struct rpc_inode *rpci; |
551 | int err; | 597 | int err; |
@@ -554,10 +600,8 @@ static int __rpc_mkpipe(struct inode *dir, struct dentry *dentry, | |||
554 | if (err) | 600 | if (err) |
555 | return err; | 601 | return err; |
556 | rpci = RPC_I(dentry->d_inode); | 602 | rpci = RPC_I(dentry->d_inode); |
557 | rpci->nkern_readwriters = 1; | ||
558 | rpci->private = private; | 603 | rpci->private = private; |
559 | rpci->flags = flags; | 604 | rpci->pipe = pipe; |
560 | rpci->ops = ops; | ||
561 | fsnotify_create(dir, dentry); | 605 | fsnotify_create(dir, dentry); |
562 | return 0; | 606 | return 0; |
563 | } | 607 | } |
@@ -573,6 +617,22 @@ static int __rpc_rmdir(struct inode *dir, struct dentry *dentry) | |||
573 | return ret; | 617 | return ret; |
574 | } | 618 | } |
575 | 619 | ||
620 | int rpc_rmdir(struct dentry *dentry) | ||
621 | { | ||
622 | struct dentry *parent; | ||
623 | struct inode *dir; | ||
624 | int error; | ||
625 | |||
626 | parent = dget_parent(dentry); | ||
627 | dir = parent->d_inode; | ||
628 | mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT); | ||
629 | error = __rpc_rmdir(dir, dentry); | ||
630 | mutex_unlock(&dir->i_mutex); | ||
631 | dput(parent); | ||
632 | return error; | ||
633 | } | ||
634 | EXPORT_SYMBOL_GPL(rpc_rmdir); | ||
635 | |||
576 | static int __rpc_unlink(struct inode *dir, struct dentry *dentry) | 636 | static int __rpc_unlink(struct inode *dir, struct dentry *dentry) |
577 | { | 637 | { |
578 | int ret; | 638 | int ret; |
@@ -587,16 +647,12 @@ static int __rpc_unlink(struct inode *dir, struct dentry *dentry) | |||
587 | static int __rpc_rmpipe(struct inode *dir, struct dentry *dentry) | 647 | static int __rpc_rmpipe(struct inode *dir, struct dentry *dentry) |
588 | { | 648 | { |
589 | struct inode *inode = dentry->d_inode; | 649 | struct inode *inode = dentry->d_inode; |
590 | struct rpc_inode *rpci = RPC_I(inode); | ||
591 | 650 | ||
592 | rpci->nkern_readwriters--; | ||
593 | if (rpci->nkern_readwriters != 0) | ||
594 | return 0; | ||
595 | rpc_close_pipes(inode); | 651 | rpc_close_pipes(inode); |
596 | return __rpc_unlink(dir, dentry); | 652 | return __rpc_unlink(dir, dentry); |
597 | } | 653 | } |
598 | 654 | ||
599 | static struct dentry *__rpc_lookup_create(struct dentry *parent, | 655 | static struct dentry *__rpc_lookup_create_exclusive(struct dentry *parent, |
600 | struct qstr *name) | 656 | struct qstr *name) |
601 | { | 657 | { |
602 | struct dentry *dentry; | 658 | struct dentry *dentry; |
@@ -604,27 +660,13 @@ static struct dentry *__rpc_lookup_create(struct dentry *parent, | |||
604 | dentry = d_lookup(parent, name); | 660 | dentry = d_lookup(parent, name); |
605 | if (!dentry) { | 661 | if (!dentry) { |
606 | dentry = d_alloc(parent, name); | 662 | dentry = d_alloc(parent, name); |
607 | if (!dentry) { | 663 | if (!dentry) |
608 | dentry = ERR_PTR(-ENOMEM); | 664 | return ERR_PTR(-ENOMEM); |
609 | goto out_err; | ||
610 | } | ||
611 | } | 665 | } |
612 | if (!dentry->d_inode) | 666 | if (dentry->d_inode == NULL) { |
613 | d_set_d_op(dentry, &rpc_dentry_operations); | 667 | d_set_d_op(dentry, &rpc_dentry_operations); |
614 | out_err: | ||
615 | return dentry; | ||
616 | } | ||
617 | |||
618 | static struct dentry *__rpc_lookup_create_exclusive(struct dentry *parent, | ||
619 | struct qstr *name) | ||
620 | { | ||
621 | struct dentry *dentry; | ||
622 | |||
623 | dentry = __rpc_lookup_create(parent, name); | ||
624 | if (IS_ERR(dentry)) | ||
625 | return dentry; | ||
626 | if (dentry->d_inode == NULL) | ||
627 | return dentry; | 668 | return dentry; |
669 | } | ||
628 | dput(dentry); | 670 | dput(dentry); |
629 | return ERR_PTR(-EEXIST); | 671 | return ERR_PTR(-EEXIST); |
630 | } | 672 | } |
@@ -779,7 +821,7 @@ static int rpc_rmdir_depopulate(struct dentry *dentry, | |||
779 | * @private: private data to associate with the pipe, for the caller's use | 821 | * @private: private data to associate with the pipe, for the caller's use |
780 | * @ops: operations defining the behavior of the pipe: upcall, downcall, | 822 | * @ops: operations defining the behavior of the pipe: upcall, downcall, |
781 | * release_pipe, open_pipe, and destroy_msg. | 823 | * release_pipe, open_pipe, and destroy_msg. |
782 | * @flags: rpc_inode flags | 824 | * @flags: rpc_pipe flags |
783 | * | 825 | * |
784 | * Data is made available for userspace to read by calls to | 826 | * Data is made available for userspace to read by calls to |
785 | * rpc_queue_upcall(). The actual reads will result in calls to | 827 | * rpc_queue_upcall(). The actual reads will result in calls to |
@@ -792,9 +834,8 @@ static int rpc_rmdir_depopulate(struct dentry *dentry, | |||
792 | * The @private argument passed here will be available to all these methods | 834 | * The @private argument passed here will be available to all these methods |
793 | * from the file pointer, via RPC_I(file->f_dentry->d_inode)->private. | 835 | * from the file pointer, via RPC_I(file->f_dentry->d_inode)->private. |
794 | */ | 836 | */ |
795 | struct dentry *rpc_mkpipe(struct dentry *parent, const char *name, | 837 | struct dentry *rpc_mkpipe_dentry(struct dentry *parent, const char *name, |
796 | void *private, const struct rpc_pipe_ops *ops, | 838 | void *private, struct rpc_pipe *pipe) |
797 | int flags) | ||
798 | { | 839 | { |
799 | struct dentry *dentry; | 840 | struct dentry *dentry; |
800 | struct inode *dir = parent->d_inode; | 841 | struct inode *dir = parent->d_inode; |
@@ -802,9 +843,9 @@ struct dentry *rpc_mkpipe(struct dentry *parent, const char *name, | |||
802 | struct qstr q; | 843 | struct qstr q; |
803 | int err; | 844 | int err; |
804 | 845 | ||
805 | if (ops->upcall == NULL) | 846 | if (pipe->ops->upcall == NULL) |
806 | umode &= ~S_IRUGO; | 847 | umode &= ~S_IRUGO; |
807 | if (ops->downcall == NULL) | 848 | if (pipe->ops->downcall == NULL) |
808 | umode &= ~S_IWUGO; | 849 | umode &= ~S_IWUGO; |
809 | 850 | ||
810 | q.name = name; | 851 | q.name = name; |
@@ -812,24 +853,11 @@ struct dentry *rpc_mkpipe(struct dentry *parent, const char *name, | |||
812 | q.hash = full_name_hash(q.name, q.len), | 853 | q.hash = full_name_hash(q.name, q.len), |
813 | 854 | ||
814 | mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT); | 855 | mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT); |
815 | dentry = __rpc_lookup_create(parent, &q); | 856 | dentry = __rpc_lookup_create_exclusive(parent, &q); |
816 | if (IS_ERR(dentry)) | 857 | if (IS_ERR(dentry)) |
817 | goto out; | 858 | goto out; |
818 | if (dentry->d_inode) { | 859 | err = __rpc_mkpipe_dentry(dir, dentry, umode, &rpc_pipe_fops, |
819 | struct rpc_inode *rpci = RPC_I(dentry->d_inode); | 860 | private, pipe); |
820 | if (rpci->private != private || | ||
821 | rpci->ops != ops || | ||
822 | rpci->flags != flags) { | ||
823 | dput (dentry); | ||
824 | err = -EBUSY; | ||
825 | goto out_err; | ||
826 | } | ||
827 | rpci->nkern_readwriters++; | ||
828 | goto out; | ||
829 | } | ||
830 | |||
831 | err = __rpc_mkpipe(dir, dentry, umode, &rpc_pipe_fops, | ||
832 | private, ops, flags); | ||
833 | if (err) | 861 | if (err) |
834 | goto out_err; | 862 | goto out_err; |
835 | out: | 863 | out: |
@@ -842,7 +870,7 @@ out_err: | |||
842 | err); | 870 | err); |
843 | goto out; | 871 | goto out; |
844 | } | 872 | } |
845 | EXPORT_SYMBOL_GPL(rpc_mkpipe); | 873 | EXPORT_SYMBOL_GPL(rpc_mkpipe_dentry); |
846 | 874 | ||
847 | /** | 875 | /** |
848 | * rpc_unlink - remove a pipe | 876 | * rpc_unlink - remove a pipe |
@@ -915,7 +943,7 @@ struct dentry *rpc_create_client_dir(struct dentry *dentry, | |||
915 | 943 | ||
916 | /** | 944 | /** |
917 | * rpc_remove_client_dir - Remove a directory created with rpc_create_client_dir() | 945 | * rpc_remove_client_dir - Remove a directory created with rpc_create_client_dir() |
918 | * @dentry: directory to remove | 946 | * @clnt: rpc client |
919 | */ | 947 | */ |
920 | int rpc_remove_client_dir(struct dentry *dentry) | 948 | int rpc_remove_client_dir(struct dentry *dentry) |
921 | { | 949 | { |
@@ -986,6 +1014,7 @@ enum { | |||
986 | RPCAUTH_statd, | 1014 | RPCAUTH_statd, |
987 | RPCAUTH_nfsd4_cb, | 1015 | RPCAUTH_nfsd4_cb, |
988 | RPCAUTH_cache, | 1016 | RPCAUTH_cache, |
1017 | RPCAUTH_nfsd, | ||
989 | RPCAUTH_RootEOF | 1018 | RPCAUTH_RootEOF |
990 | }; | 1019 | }; |
991 | 1020 | ||
@@ -1018,13 +1047,70 @@ static const struct rpc_filelist files[] = { | |||
1018 | .name = "cache", | 1047 | .name = "cache", |
1019 | .mode = S_IFDIR | S_IRUGO | S_IXUGO, | 1048 | .mode = S_IFDIR | S_IRUGO | S_IXUGO, |
1020 | }, | 1049 | }, |
1050 | [RPCAUTH_nfsd] = { | ||
1051 | .name = "nfsd", | ||
1052 | .mode = S_IFDIR | S_IRUGO | S_IXUGO, | ||
1053 | }, | ||
1021 | }; | 1054 | }; |
1022 | 1055 | ||
1056 | /* | ||
1057 | * This call can be used only in RPC pipefs mount notification hooks. | ||
1058 | */ | ||
1059 | struct dentry *rpc_d_lookup_sb(const struct super_block *sb, | ||
1060 | const unsigned char *dir_name) | ||
1061 | { | ||
1062 | struct qstr dir = { | ||
1063 | .name = dir_name, | ||
1064 | .len = strlen(dir_name), | ||
1065 | .hash = full_name_hash(dir_name, strlen(dir_name)), | ||
1066 | }; | ||
1067 | |||
1068 | return d_lookup(sb->s_root, &dir); | ||
1069 | } | ||
1070 | EXPORT_SYMBOL_GPL(rpc_d_lookup_sb); | ||
1071 | |||
1072 | void rpc_pipefs_init_net(struct net *net) | ||
1073 | { | ||
1074 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
1075 | |||
1076 | mutex_init(&sn->pipefs_sb_lock); | ||
1077 | } | ||
1078 | |||
1079 | /* | ||
1080 | * This call will be used for per network namespace operations calls. | ||
1081 | * Note: Function will be returned with pipefs_sb_lock taken if superblock was | ||
1082 | * found. This lock have to be released by rpc_put_sb_net() when all operations | ||
1083 | * will be completed. | ||
1084 | */ | ||
1085 | struct super_block *rpc_get_sb_net(const struct net *net) | ||
1086 | { | ||
1087 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
1088 | |||
1089 | mutex_lock(&sn->pipefs_sb_lock); | ||
1090 | if (sn->pipefs_sb) | ||
1091 | return sn->pipefs_sb; | ||
1092 | mutex_unlock(&sn->pipefs_sb_lock); | ||
1093 | return NULL; | ||
1094 | } | ||
1095 | EXPORT_SYMBOL_GPL(rpc_get_sb_net); | ||
1096 | |||
1097 | void rpc_put_sb_net(const struct net *net) | ||
1098 | { | ||
1099 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
1100 | |||
1101 | BUG_ON(sn->pipefs_sb == NULL); | ||
1102 | mutex_unlock(&sn->pipefs_sb_lock); | ||
1103 | } | ||
1104 | EXPORT_SYMBOL_GPL(rpc_put_sb_net); | ||
1105 | |||
1023 | static int | 1106 | static int |
1024 | rpc_fill_super(struct super_block *sb, void *data, int silent) | 1107 | rpc_fill_super(struct super_block *sb, void *data, int silent) |
1025 | { | 1108 | { |
1026 | struct inode *inode; | 1109 | struct inode *inode; |
1027 | struct dentry *root; | 1110 | struct dentry *root; |
1111 | struct net *net = data; | ||
1112 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
1113 | int err; | ||
1028 | 1114 | ||
1029 | sb->s_blocksize = PAGE_CACHE_SIZE; | 1115 | sb->s_blocksize = PAGE_CACHE_SIZE; |
1030 | sb->s_blocksize_bits = PAGE_CACHE_SHIFT; | 1116 | sb->s_blocksize_bits = PAGE_CACHE_SHIFT; |
@@ -1033,30 +1119,59 @@ rpc_fill_super(struct super_block *sb, void *data, int silent) | |||
1033 | sb->s_time_gran = 1; | 1119 | sb->s_time_gran = 1; |
1034 | 1120 | ||
1035 | inode = rpc_get_inode(sb, S_IFDIR | 0755); | 1121 | inode = rpc_get_inode(sb, S_IFDIR | 0755); |
1036 | if (!inode) | 1122 | sb->s_root = root = d_make_root(inode); |
1037 | return -ENOMEM; | 1123 | if (!root) |
1038 | sb->s_root = root = d_alloc_root(inode); | ||
1039 | if (!root) { | ||
1040 | iput(inode); | ||
1041 | return -ENOMEM; | 1124 | return -ENOMEM; |
1042 | } | ||
1043 | if (rpc_populate(root, files, RPCAUTH_lockd, RPCAUTH_RootEOF, NULL)) | 1125 | if (rpc_populate(root, files, RPCAUTH_lockd, RPCAUTH_RootEOF, NULL)) |
1044 | return -ENOMEM; | 1126 | return -ENOMEM; |
1127 | dprintk("RPC: sending pipefs MOUNT notification for net %p%s\n", net, | ||
1128 | NET_NAME(net)); | ||
1129 | err = blocking_notifier_call_chain(&rpc_pipefs_notifier_list, | ||
1130 | RPC_PIPEFS_MOUNT, | ||
1131 | sb); | ||
1132 | if (err) | ||
1133 | goto err_depopulate; | ||
1134 | sb->s_fs_info = get_net(net); | ||
1135 | sn->pipefs_sb = sb; | ||
1045 | return 0; | 1136 | return 0; |
1137 | |||
1138 | err_depopulate: | ||
1139 | blocking_notifier_call_chain(&rpc_pipefs_notifier_list, | ||
1140 | RPC_PIPEFS_UMOUNT, | ||
1141 | sb); | ||
1142 | __rpc_depopulate(root, files, RPCAUTH_lockd, RPCAUTH_RootEOF); | ||
1143 | return err; | ||
1046 | } | 1144 | } |
1047 | 1145 | ||
1048 | static struct dentry * | 1146 | static struct dentry * |
1049 | rpc_mount(struct file_system_type *fs_type, | 1147 | rpc_mount(struct file_system_type *fs_type, |
1050 | int flags, const char *dev_name, void *data) | 1148 | int flags, const char *dev_name, void *data) |
1051 | { | 1149 | { |
1052 | return mount_single(fs_type, flags, data, rpc_fill_super); | 1150 | return mount_ns(fs_type, flags, current->nsproxy->net_ns, rpc_fill_super); |
1151 | } | ||
1152 | |||
1153 | static void rpc_kill_sb(struct super_block *sb) | ||
1154 | { | ||
1155 | struct net *net = sb->s_fs_info; | ||
1156 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
1157 | |||
1158 | mutex_lock(&sn->pipefs_sb_lock); | ||
1159 | sn->pipefs_sb = NULL; | ||
1160 | mutex_unlock(&sn->pipefs_sb_lock); | ||
1161 | put_net(net); | ||
1162 | dprintk("RPC: sending pipefs UMOUNT notification for net %p%s\n", net, | ||
1163 | NET_NAME(net)); | ||
1164 | blocking_notifier_call_chain(&rpc_pipefs_notifier_list, | ||
1165 | RPC_PIPEFS_UMOUNT, | ||
1166 | sb); | ||
1167 | kill_litter_super(sb); | ||
1053 | } | 1168 | } |
1054 | 1169 | ||
1055 | static struct file_system_type rpc_pipe_fs_type = { | 1170 | static struct file_system_type rpc_pipe_fs_type = { |
1056 | .owner = THIS_MODULE, | 1171 | .owner = THIS_MODULE, |
1057 | .name = "rpc_pipefs", | 1172 | .name = "rpc_pipefs", |
1058 | .mount = rpc_mount, | 1173 | .mount = rpc_mount, |
1059 | .kill_sb = kill_litter_super, | 1174 | .kill_sb = rpc_kill_sb, |
1060 | }; | 1175 | }; |
1061 | 1176 | ||
1062 | static void | 1177 | static void |
@@ -1066,16 +1181,8 @@ init_once(void *foo) | |||
1066 | 1181 | ||
1067 | inode_init_once(&rpci->vfs_inode); | 1182 | inode_init_once(&rpci->vfs_inode); |
1068 | rpci->private = NULL; | 1183 | rpci->private = NULL; |
1069 | rpci->nreaders = 0; | 1184 | rpci->pipe = NULL; |
1070 | rpci->nwriters = 0; | ||
1071 | INIT_LIST_HEAD(&rpci->in_upcall); | ||
1072 | INIT_LIST_HEAD(&rpci->in_downcall); | ||
1073 | INIT_LIST_HEAD(&rpci->pipe); | ||
1074 | rpci->pipelen = 0; | ||
1075 | init_waitqueue_head(&rpci->waitq); | 1185 | init_waitqueue_head(&rpci->waitq); |
1076 | INIT_DELAYED_WORK(&rpci->queue_timeout, | ||
1077 | rpc_timeout_upcall_queue); | ||
1078 | rpci->ops = NULL; | ||
1079 | } | 1186 | } |
1080 | 1187 | ||
1081 | int register_rpc_pipefs(void) | 1188 | int register_rpc_pipefs(void) |
@@ -1089,17 +1196,24 @@ int register_rpc_pipefs(void) | |||
1089 | init_once); | 1196 | init_once); |
1090 | if (!rpc_inode_cachep) | 1197 | if (!rpc_inode_cachep) |
1091 | return -ENOMEM; | 1198 | return -ENOMEM; |
1199 | err = rpc_clients_notifier_register(); | ||
1200 | if (err) | ||
1201 | goto err_notifier; | ||
1092 | err = register_filesystem(&rpc_pipe_fs_type); | 1202 | err = register_filesystem(&rpc_pipe_fs_type); |
1093 | if (err) { | 1203 | if (err) |
1094 | kmem_cache_destroy(rpc_inode_cachep); | 1204 | goto err_register; |
1095 | return err; | ||
1096 | } | ||
1097 | |||
1098 | return 0; | 1205 | return 0; |
1206 | |||
1207 | err_register: | ||
1208 | rpc_clients_notifier_unregister(); | ||
1209 | err_notifier: | ||
1210 | kmem_cache_destroy(rpc_inode_cachep); | ||
1211 | return err; | ||
1099 | } | 1212 | } |
1100 | 1213 | ||
1101 | void unregister_rpc_pipefs(void) | 1214 | void unregister_rpc_pipefs(void) |
1102 | { | 1215 | { |
1216 | rpc_clients_notifier_unregister(); | ||
1103 | kmem_cache_destroy(rpc_inode_cachep); | 1217 | kmem_cache_destroy(rpc_inode_cachep); |
1104 | unregister_filesystem(&rpc_pipe_fs_type); | 1218 | unregister_filesystem(&rpc_pipe_fs_type); |
1105 | } | 1219 | } |
diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c index 8761bf8e36fc..78ac39fd9fe7 100644 --- a/net/sunrpc/rpcb_clnt.c +++ b/net/sunrpc/rpcb_clnt.c | |||
@@ -23,12 +23,15 @@ | |||
23 | #include <linux/errno.h> | 23 | #include <linux/errno.h> |
24 | #include <linux/mutex.h> | 24 | #include <linux/mutex.h> |
25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
26 | #include <linux/nsproxy.h> | ||
26 | #include <net/ipv6.h> | 27 | #include <net/ipv6.h> |
27 | 28 | ||
28 | #include <linux/sunrpc/clnt.h> | 29 | #include <linux/sunrpc/clnt.h> |
29 | #include <linux/sunrpc/sched.h> | 30 | #include <linux/sunrpc/sched.h> |
30 | #include <linux/sunrpc/xprtsock.h> | 31 | #include <linux/sunrpc/xprtsock.h> |
31 | 32 | ||
33 | #include "netns.h" | ||
34 | |||
32 | #ifdef RPC_DEBUG | 35 | #ifdef RPC_DEBUG |
33 | # define RPCDBG_FACILITY RPCDBG_BIND | 36 | # define RPCDBG_FACILITY RPCDBG_BIND |
34 | #endif | 37 | #endif |
@@ -109,13 +112,7 @@ enum { | |||
109 | 112 | ||
110 | static void rpcb_getport_done(struct rpc_task *, void *); | 113 | static void rpcb_getport_done(struct rpc_task *, void *); |
111 | static void rpcb_map_release(void *data); | 114 | static void rpcb_map_release(void *data); |
112 | static struct rpc_program rpcb_program; | 115 | static const struct rpc_program rpcb_program; |
113 | |||
114 | static struct rpc_clnt * rpcb_local_clnt; | ||
115 | static struct rpc_clnt * rpcb_local_clnt4; | ||
116 | |||
117 | DEFINE_SPINLOCK(rpcb_clnt_lock); | ||
118 | unsigned int rpcb_users; | ||
119 | 116 | ||
120 | struct rpcbind_args { | 117 | struct rpcbind_args { |
121 | struct rpc_xprt * r_xprt; | 118 | struct rpc_xprt * r_xprt; |
@@ -140,8 +137,8 @@ struct rpcb_info { | |||
140 | struct rpc_procinfo * rpc_proc; | 137 | struct rpc_procinfo * rpc_proc; |
141 | }; | 138 | }; |
142 | 139 | ||
143 | static struct rpcb_info rpcb_next_version[]; | 140 | static const struct rpcb_info rpcb_next_version[]; |
144 | static struct rpcb_info rpcb_next_version6[]; | 141 | static const struct rpcb_info rpcb_next_version6[]; |
145 | 142 | ||
146 | static const struct rpc_call_ops rpcb_getport_ops = { | 143 | static const struct rpc_call_ops rpcb_getport_ops = { |
147 | .rpc_call_done = rpcb_getport_done, | 144 | .rpc_call_done = rpcb_getport_done, |
@@ -164,32 +161,34 @@ static void rpcb_map_release(void *data) | |||
164 | kfree(map); | 161 | kfree(map); |
165 | } | 162 | } |
166 | 163 | ||
167 | static int rpcb_get_local(void) | 164 | static int rpcb_get_local(struct net *net) |
168 | { | 165 | { |
169 | int cnt; | 166 | int cnt; |
167 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
170 | 168 | ||
171 | spin_lock(&rpcb_clnt_lock); | 169 | spin_lock(&sn->rpcb_clnt_lock); |
172 | if (rpcb_users) | 170 | if (sn->rpcb_users) |
173 | rpcb_users++; | 171 | sn->rpcb_users++; |
174 | cnt = rpcb_users; | 172 | cnt = sn->rpcb_users; |
175 | spin_unlock(&rpcb_clnt_lock); | 173 | spin_unlock(&sn->rpcb_clnt_lock); |
176 | 174 | ||
177 | return cnt; | 175 | return cnt; |
178 | } | 176 | } |
179 | 177 | ||
180 | void rpcb_put_local(void) | 178 | void rpcb_put_local(struct net *net) |
181 | { | 179 | { |
182 | struct rpc_clnt *clnt = rpcb_local_clnt; | 180 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); |
183 | struct rpc_clnt *clnt4 = rpcb_local_clnt4; | 181 | struct rpc_clnt *clnt = sn->rpcb_local_clnt; |
182 | struct rpc_clnt *clnt4 = sn->rpcb_local_clnt4; | ||
184 | int shutdown; | 183 | int shutdown; |
185 | 184 | ||
186 | spin_lock(&rpcb_clnt_lock); | 185 | spin_lock(&sn->rpcb_clnt_lock); |
187 | if (--rpcb_users == 0) { | 186 | if (--sn->rpcb_users == 0) { |
188 | rpcb_local_clnt = NULL; | 187 | sn->rpcb_local_clnt = NULL; |
189 | rpcb_local_clnt4 = NULL; | 188 | sn->rpcb_local_clnt4 = NULL; |
190 | } | 189 | } |
191 | shutdown = !rpcb_users; | 190 | shutdown = !sn->rpcb_users; |
192 | spin_unlock(&rpcb_clnt_lock); | 191 | spin_unlock(&sn->rpcb_clnt_lock); |
193 | 192 | ||
194 | if (shutdown) { | 193 | if (shutdown) { |
195 | /* | 194 | /* |
@@ -202,30 +201,34 @@ void rpcb_put_local(void) | |||
202 | } | 201 | } |
203 | } | 202 | } |
204 | 203 | ||
205 | static void rpcb_set_local(struct rpc_clnt *clnt, struct rpc_clnt *clnt4) | 204 | static void rpcb_set_local(struct net *net, struct rpc_clnt *clnt, |
205 | struct rpc_clnt *clnt4) | ||
206 | { | 206 | { |
207 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
208 | |||
207 | /* Protected by rpcb_create_local_mutex */ | 209 | /* Protected by rpcb_create_local_mutex */ |
208 | rpcb_local_clnt = clnt; | 210 | sn->rpcb_local_clnt = clnt; |
209 | rpcb_local_clnt4 = clnt4; | 211 | sn->rpcb_local_clnt4 = clnt4; |
210 | smp_wmb(); | 212 | smp_wmb(); |
211 | rpcb_users = 1; | 213 | sn->rpcb_users = 1; |
212 | dprintk("RPC: created new rpcb local clients (rpcb_local_clnt: " | 214 | dprintk("RPC: created new rpcb local clients (rpcb_local_clnt: " |
213 | "%p, rpcb_local_clnt4: %p)\n", rpcb_local_clnt, | 215 | "%p, rpcb_local_clnt4: %p) for net %p%s\n", |
214 | rpcb_local_clnt4); | 216 | sn->rpcb_local_clnt, sn->rpcb_local_clnt4, |
217 | net, (net == &init_net) ? " (init_net)" : ""); | ||
215 | } | 218 | } |
216 | 219 | ||
217 | /* | 220 | /* |
218 | * Returns zero on success, otherwise a negative errno value | 221 | * Returns zero on success, otherwise a negative errno value |
219 | * is returned. | 222 | * is returned. |
220 | */ | 223 | */ |
221 | static int rpcb_create_local_unix(void) | 224 | static int rpcb_create_local_unix(struct net *net) |
222 | { | 225 | { |
223 | static const struct sockaddr_un rpcb_localaddr_rpcbind = { | 226 | static const struct sockaddr_un rpcb_localaddr_rpcbind = { |
224 | .sun_family = AF_LOCAL, | 227 | .sun_family = AF_LOCAL, |
225 | .sun_path = RPCBIND_SOCK_PATHNAME, | 228 | .sun_path = RPCBIND_SOCK_PATHNAME, |
226 | }; | 229 | }; |
227 | struct rpc_create_args args = { | 230 | struct rpc_create_args args = { |
228 | .net = &init_net, | 231 | .net = net, |
229 | .protocol = XPRT_TRANSPORT_LOCAL, | 232 | .protocol = XPRT_TRANSPORT_LOCAL, |
230 | .address = (struct sockaddr *)&rpcb_localaddr_rpcbind, | 233 | .address = (struct sockaddr *)&rpcb_localaddr_rpcbind, |
231 | .addrsize = sizeof(rpcb_localaddr_rpcbind), | 234 | .addrsize = sizeof(rpcb_localaddr_rpcbind), |
@@ -258,7 +261,7 @@ static int rpcb_create_local_unix(void) | |||
258 | clnt4 = NULL; | 261 | clnt4 = NULL; |
259 | } | 262 | } |
260 | 263 | ||
261 | rpcb_set_local(clnt, clnt4); | 264 | rpcb_set_local(net, clnt, clnt4); |
262 | 265 | ||
263 | out: | 266 | out: |
264 | return result; | 267 | return result; |
@@ -268,7 +271,7 @@ out: | |||
268 | * Returns zero on success, otherwise a negative errno value | 271 | * Returns zero on success, otherwise a negative errno value |
269 | * is returned. | 272 | * is returned. |
270 | */ | 273 | */ |
271 | static int rpcb_create_local_net(void) | 274 | static int rpcb_create_local_net(struct net *net) |
272 | { | 275 | { |
273 | static const struct sockaddr_in rpcb_inaddr_loopback = { | 276 | static const struct sockaddr_in rpcb_inaddr_loopback = { |
274 | .sin_family = AF_INET, | 277 | .sin_family = AF_INET, |
@@ -276,7 +279,7 @@ static int rpcb_create_local_net(void) | |||
276 | .sin_port = htons(RPCBIND_PORT), | 279 | .sin_port = htons(RPCBIND_PORT), |
277 | }; | 280 | }; |
278 | struct rpc_create_args args = { | 281 | struct rpc_create_args args = { |
279 | .net = &init_net, | 282 | .net = net, |
280 | .protocol = XPRT_TRANSPORT_TCP, | 283 | .protocol = XPRT_TRANSPORT_TCP, |
281 | .address = (struct sockaddr *)&rpcb_inaddr_loopback, | 284 | .address = (struct sockaddr *)&rpcb_inaddr_loopback, |
282 | .addrsize = sizeof(rpcb_inaddr_loopback), | 285 | .addrsize = sizeof(rpcb_inaddr_loopback), |
@@ -310,7 +313,7 @@ static int rpcb_create_local_net(void) | |||
310 | clnt4 = NULL; | 313 | clnt4 = NULL; |
311 | } | 314 | } |
312 | 315 | ||
313 | rpcb_set_local(clnt, clnt4); | 316 | rpcb_set_local(net, clnt, clnt4); |
314 | 317 | ||
315 | out: | 318 | out: |
316 | return result; | 319 | return result; |
@@ -320,31 +323,32 @@ out: | |||
320 | * Returns zero on success, otherwise a negative errno value | 323 | * Returns zero on success, otherwise a negative errno value |
321 | * is returned. | 324 | * is returned. |
322 | */ | 325 | */ |
323 | int rpcb_create_local(void) | 326 | int rpcb_create_local(struct net *net) |
324 | { | 327 | { |
325 | static DEFINE_MUTEX(rpcb_create_local_mutex); | 328 | static DEFINE_MUTEX(rpcb_create_local_mutex); |
326 | int result = 0; | 329 | int result = 0; |
327 | 330 | ||
328 | if (rpcb_get_local()) | 331 | if (rpcb_get_local(net)) |
329 | return result; | 332 | return result; |
330 | 333 | ||
331 | mutex_lock(&rpcb_create_local_mutex); | 334 | mutex_lock(&rpcb_create_local_mutex); |
332 | if (rpcb_get_local()) | 335 | if (rpcb_get_local(net)) |
333 | goto out; | 336 | goto out; |
334 | 337 | ||
335 | if (rpcb_create_local_unix() != 0) | 338 | if (rpcb_create_local_unix(net) != 0) |
336 | result = rpcb_create_local_net(); | 339 | result = rpcb_create_local_net(net); |
337 | 340 | ||
338 | out: | 341 | out: |
339 | mutex_unlock(&rpcb_create_local_mutex); | 342 | mutex_unlock(&rpcb_create_local_mutex); |
340 | return result; | 343 | return result; |
341 | } | 344 | } |
342 | 345 | ||
343 | static struct rpc_clnt *rpcb_create(char *hostname, struct sockaddr *srvaddr, | 346 | static struct rpc_clnt *rpcb_create(struct net *net, const char *hostname, |
344 | size_t salen, int proto, u32 version) | 347 | struct sockaddr *srvaddr, size_t salen, |
348 | int proto, u32 version) | ||
345 | { | 349 | { |
346 | struct rpc_create_args args = { | 350 | struct rpc_create_args args = { |
347 | .net = &init_net, | 351 | .net = net, |
348 | .protocol = proto, | 352 | .protocol = proto, |
349 | .address = srvaddr, | 353 | .address = srvaddr, |
350 | .addrsize = salen, | 354 | .addrsize = salen, |
@@ -420,7 +424,7 @@ static int rpcb_register_call(struct rpc_clnt *clnt, struct rpc_message *msg) | |||
420 | * IN6ADDR_ANY (ie available for all AF_INET and AF_INET6 | 424 | * IN6ADDR_ANY (ie available for all AF_INET and AF_INET6 |
421 | * addresses). | 425 | * addresses). |
422 | */ | 426 | */ |
423 | int rpcb_register(u32 prog, u32 vers, int prot, unsigned short port) | 427 | int rpcb_register(struct net *net, u32 prog, u32 vers, int prot, unsigned short port) |
424 | { | 428 | { |
425 | struct rpcbind_args map = { | 429 | struct rpcbind_args map = { |
426 | .r_prog = prog, | 430 | .r_prog = prog, |
@@ -431,6 +435,7 @@ int rpcb_register(u32 prog, u32 vers, int prot, unsigned short port) | |||
431 | struct rpc_message msg = { | 435 | struct rpc_message msg = { |
432 | .rpc_argp = &map, | 436 | .rpc_argp = &map, |
433 | }; | 437 | }; |
438 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
434 | 439 | ||
435 | dprintk("RPC: %sregistering (%u, %u, %d, %u) with local " | 440 | dprintk("RPC: %sregistering (%u, %u, %d, %u) with local " |
436 | "rpcbind\n", (port ? "" : "un"), | 441 | "rpcbind\n", (port ? "" : "un"), |
@@ -440,13 +445,14 @@ int rpcb_register(u32 prog, u32 vers, int prot, unsigned short port) | |||
440 | if (port) | 445 | if (port) |
441 | msg.rpc_proc = &rpcb_procedures2[RPCBPROC_SET]; | 446 | msg.rpc_proc = &rpcb_procedures2[RPCBPROC_SET]; |
442 | 447 | ||
443 | return rpcb_register_call(rpcb_local_clnt, &msg); | 448 | return rpcb_register_call(sn->rpcb_local_clnt, &msg); |
444 | } | 449 | } |
445 | 450 | ||
446 | /* | 451 | /* |
447 | * Fill in AF_INET family-specific arguments to register | 452 | * Fill in AF_INET family-specific arguments to register |
448 | */ | 453 | */ |
449 | static int rpcb_register_inet4(const struct sockaddr *sap, | 454 | static int rpcb_register_inet4(struct sunrpc_net *sn, |
455 | const struct sockaddr *sap, | ||
450 | struct rpc_message *msg) | 456 | struct rpc_message *msg) |
451 | { | 457 | { |
452 | const struct sockaddr_in *sin = (const struct sockaddr_in *)sap; | 458 | const struct sockaddr_in *sin = (const struct sockaddr_in *)sap; |
@@ -465,7 +471,7 @@ static int rpcb_register_inet4(const struct sockaddr *sap, | |||
465 | if (port) | 471 | if (port) |
466 | msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET]; | 472 | msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET]; |
467 | 473 | ||
468 | result = rpcb_register_call(rpcb_local_clnt4, msg); | 474 | result = rpcb_register_call(sn->rpcb_local_clnt4, msg); |
469 | kfree(map->r_addr); | 475 | kfree(map->r_addr); |
470 | return result; | 476 | return result; |
471 | } | 477 | } |
@@ -473,7 +479,8 @@ static int rpcb_register_inet4(const struct sockaddr *sap, | |||
473 | /* | 479 | /* |
474 | * Fill in AF_INET6 family-specific arguments to register | 480 | * Fill in AF_INET6 family-specific arguments to register |
475 | */ | 481 | */ |
476 | static int rpcb_register_inet6(const struct sockaddr *sap, | 482 | static int rpcb_register_inet6(struct sunrpc_net *sn, |
483 | const struct sockaddr *sap, | ||
477 | struct rpc_message *msg) | 484 | struct rpc_message *msg) |
478 | { | 485 | { |
479 | const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sap; | 486 | const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sap; |
@@ -492,12 +499,13 @@ static int rpcb_register_inet6(const struct sockaddr *sap, | |||
492 | if (port) | 499 | if (port) |
493 | msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET]; | 500 | msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET]; |
494 | 501 | ||
495 | result = rpcb_register_call(rpcb_local_clnt4, msg); | 502 | result = rpcb_register_call(sn->rpcb_local_clnt4, msg); |
496 | kfree(map->r_addr); | 503 | kfree(map->r_addr); |
497 | return result; | 504 | return result; |
498 | } | 505 | } |
499 | 506 | ||
500 | static int rpcb_unregister_all_protofamilies(struct rpc_message *msg) | 507 | static int rpcb_unregister_all_protofamilies(struct sunrpc_net *sn, |
508 | struct rpc_message *msg) | ||
501 | { | 509 | { |
502 | struct rpcbind_args *map = msg->rpc_argp; | 510 | struct rpcbind_args *map = msg->rpc_argp; |
503 | 511 | ||
@@ -508,7 +516,7 @@ static int rpcb_unregister_all_protofamilies(struct rpc_message *msg) | |||
508 | map->r_addr = ""; | 516 | map->r_addr = ""; |
509 | msg->rpc_proc = &rpcb_procedures4[RPCBPROC_UNSET]; | 517 | msg->rpc_proc = &rpcb_procedures4[RPCBPROC_UNSET]; |
510 | 518 | ||
511 | return rpcb_register_call(rpcb_local_clnt4, msg); | 519 | return rpcb_register_call(sn->rpcb_local_clnt4, msg); |
512 | } | 520 | } |
513 | 521 | ||
514 | /** | 522 | /** |
@@ -554,7 +562,7 @@ static int rpcb_unregister_all_protofamilies(struct rpc_message *msg) | |||
554 | * service on any IPv4 address, but not on IPv6. The latter | 562 | * service on any IPv4 address, but not on IPv6. The latter |
555 | * advertises the service on all IPv4 and IPv6 addresses. | 563 | * advertises the service on all IPv4 and IPv6 addresses. |
556 | */ | 564 | */ |
557 | int rpcb_v4_register(const u32 program, const u32 version, | 565 | int rpcb_v4_register(struct net *net, const u32 program, const u32 version, |
558 | const struct sockaddr *address, const char *netid) | 566 | const struct sockaddr *address, const char *netid) |
559 | { | 567 | { |
560 | struct rpcbind_args map = { | 568 | struct rpcbind_args map = { |
@@ -566,18 +574,19 @@ int rpcb_v4_register(const u32 program, const u32 version, | |||
566 | struct rpc_message msg = { | 574 | struct rpc_message msg = { |
567 | .rpc_argp = &map, | 575 | .rpc_argp = &map, |
568 | }; | 576 | }; |
577 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
569 | 578 | ||
570 | if (rpcb_local_clnt4 == NULL) | 579 | if (sn->rpcb_local_clnt4 == NULL) |
571 | return -EPROTONOSUPPORT; | 580 | return -EPROTONOSUPPORT; |
572 | 581 | ||
573 | if (address == NULL) | 582 | if (address == NULL) |
574 | return rpcb_unregister_all_protofamilies(&msg); | 583 | return rpcb_unregister_all_protofamilies(sn, &msg); |
575 | 584 | ||
576 | switch (address->sa_family) { | 585 | switch (address->sa_family) { |
577 | case AF_INET: | 586 | case AF_INET: |
578 | return rpcb_register_inet4(address, &msg); | 587 | return rpcb_register_inet4(sn, address, &msg); |
579 | case AF_INET6: | 588 | case AF_INET6: |
580 | return rpcb_register_inet6(address, &msg); | 589 | return rpcb_register_inet6(sn, address, &msg); |
581 | } | 590 | } |
582 | 591 | ||
583 | return -EAFNOSUPPORT; | 592 | return -EAFNOSUPPORT; |
@@ -611,9 +620,10 @@ static struct rpc_task *rpcb_call_async(struct rpc_clnt *rpcb_clnt, struct rpcbi | |||
611 | static struct rpc_clnt *rpcb_find_transport_owner(struct rpc_clnt *clnt) | 620 | static struct rpc_clnt *rpcb_find_transport_owner(struct rpc_clnt *clnt) |
612 | { | 621 | { |
613 | struct rpc_clnt *parent = clnt->cl_parent; | 622 | struct rpc_clnt *parent = clnt->cl_parent; |
623 | struct rpc_xprt *xprt = rcu_dereference(clnt->cl_xprt); | ||
614 | 624 | ||
615 | while (parent != clnt) { | 625 | while (parent != clnt) { |
616 | if (parent->cl_xprt != clnt->cl_xprt) | 626 | if (rcu_dereference(parent->cl_xprt) != xprt) |
617 | break; | 627 | break; |
618 | if (clnt->cl_autobind) | 628 | if (clnt->cl_autobind) |
619 | break; | 629 | break; |
@@ -644,12 +654,16 @@ void rpcb_getport_async(struct rpc_task *task) | |||
644 | size_t salen; | 654 | size_t salen; |
645 | int status; | 655 | int status; |
646 | 656 | ||
647 | clnt = rpcb_find_transport_owner(task->tk_client); | 657 | rcu_read_lock(); |
648 | xprt = clnt->cl_xprt; | 658 | do { |
659 | clnt = rpcb_find_transport_owner(task->tk_client); | ||
660 | xprt = xprt_get(rcu_dereference(clnt->cl_xprt)); | ||
661 | } while (xprt == NULL); | ||
662 | rcu_read_unlock(); | ||
649 | 663 | ||
650 | dprintk("RPC: %5u %s(%s, %u, %u, %d)\n", | 664 | dprintk("RPC: %5u %s(%s, %u, %u, %d)\n", |
651 | task->tk_pid, __func__, | 665 | task->tk_pid, __func__, |
652 | clnt->cl_server, clnt->cl_prog, clnt->cl_vers, xprt->prot); | 666 | xprt->servername, clnt->cl_prog, clnt->cl_vers, xprt->prot); |
653 | 667 | ||
654 | /* Put self on the wait queue to ensure we get notified if | 668 | /* Put self on the wait queue to ensure we get notified if |
655 | * some other task is already attempting to bind the port */ | 669 | * some other task is already attempting to bind the port */ |
@@ -658,6 +672,7 @@ void rpcb_getport_async(struct rpc_task *task) | |||
658 | if (xprt_test_and_set_binding(xprt)) { | 672 | if (xprt_test_and_set_binding(xprt)) { |
659 | dprintk("RPC: %5u %s: waiting for another binder\n", | 673 | dprintk("RPC: %5u %s: waiting for another binder\n", |
660 | task->tk_pid, __func__); | 674 | task->tk_pid, __func__); |
675 | xprt_put(xprt); | ||
661 | return; | 676 | return; |
662 | } | 677 | } |
663 | 678 | ||
@@ -699,8 +714,8 @@ void rpcb_getport_async(struct rpc_task *task) | |||
699 | dprintk("RPC: %5u %s: trying rpcbind version %u\n", | 714 | dprintk("RPC: %5u %s: trying rpcbind version %u\n", |
700 | task->tk_pid, __func__, bind_version); | 715 | task->tk_pid, __func__, bind_version); |
701 | 716 | ||
702 | rpcb_clnt = rpcb_create(clnt->cl_server, sap, salen, xprt->prot, | 717 | rpcb_clnt = rpcb_create(xprt->xprt_net, xprt->servername, sap, salen, |
703 | bind_version); | 718 | xprt->prot, bind_version); |
704 | if (IS_ERR(rpcb_clnt)) { | 719 | if (IS_ERR(rpcb_clnt)) { |
705 | status = PTR_ERR(rpcb_clnt); | 720 | status = PTR_ERR(rpcb_clnt); |
706 | dprintk("RPC: %5u %s: rpcb_create failed, error %ld\n", | 721 | dprintk("RPC: %5u %s: rpcb_create failed, error %ld\n", |
@@ -719,13 +734,13 @@ void rpcb_getport_async(struct rpc_task *task) | |||
719 | map->r_vers = clnt->cl_vers; | 734 | map->r_vers = clnt->cl_vers; |
720 | map->r_prot = xprt->prot; | 735 | map->r_prot = xprt->prot; |
721 | map->r_port = 0; | 736 | map->r_port = 0; |
722 | map->r_xprt = xprt_get(xprt); | 737 | map->r_xprt = xprt; |
723 | map->r_status = -EIO; | 738 | map->r_status = -EIO; |
724 | 739 | ||
725 | switch (bind_version) { | 740 | switch (bind_version) { |
726 | case RPCBVERS_4: | 741 | case RPCBVERS_4: |
727 | case RPCBVERS_3: | 742 | case RPCBVERS_3: |
728 | map->r_netid = rpc_peeraddr2str(clnt, RPC_DISPLAY_NETID); | 743 | map->r_netid = xprt->address_strings[RPC_DISPLAY_NETID]; |
729 | map->r_addr = rpc_sockaddr2uaddr(sap, GFP_ATOMIC); | 744 | map->r_addr = rpc_sockaddr2uaddr(sap, GFP_ATOMIC); |
730 | map->r_owner = ""; | 745 | map->r_owner = ""; |
731 | break; | 746 | break; |
@@ -754,6 +769,7 @@ bailout_release_client: | |||
754 | bailout_nofree: | 769 | bailout_nofree: |
755 | rpcb_wake_rpcbind_waiters(xprt, status); | 770 | rpcb_wake_rpcbind_waiters(xprt, status); |
756 | task->tk_status = status; | 771 | task->tk_status = status; |
772 | xprt_put(xprt); | ||
757 | } | 773 | } |
758 | EXPORT_SYMBOL_GPL(rpcb_getport_async); | 774 | EXPORT_SYMBOL_GPL(rpcb_getport_async); |
759 | 775 | ||
@@ -801,11 +817,11 @@ static void rpcb_getport_done(struct rpc_task *child, void *data) | |||
801 | static void rpcb_enc_mapping(struct rpc_rqst *req, struct xdr_stream *xdr, | 817 | static void rpcb_enc_mapping(struct rpc_rqst *req, struct xdr_stream *xdr, |
802 | const struct rpcbind_args *rpcb) | 818 | const struct rpcbind_args *rpcb) |
803 | { | 819 | { |
804 | struct rpc_task *task = req->rq_task; | ||
805 | __be32 *p; | 820 | __be32 *p; |
806 | 821 | ||
807 | dprintk("RPC: %5u encoding PMAP_%s call (%u, %u, %d, %u)\n", | 822 | dprintk("RPC: %5u encoding PMAP_%s call (%u, %u, %d, %u)\n", |
808 | task->tk_pid, task->tk_msg.rpc_proc->p_name, | 823 | req->rq_task->tk_pid, |
824 | req->rq_task->tk_msg.rpc_proc->p_name, | ||
809 | rpcb->r_prog, rpcb->r_vers, rpcb->r_prot, rpcb->r_port); | 825 | rpcb->r_prog, rpcb->r_vers, rpcb->r_prot, rpcb->r_port); |
810 | 826 | ||
811 | p = xdr_reserve_space(xdr, RPCB_mappingargs_sz << 2); | 827 | p = xdr_reserve_space(xdr, RPCB_mappingargs_sz << 2); |
@@ -818,7 +834,6 @@ static void rpcb_enc_mapping(struct rpc_rqst *req, struct xdr_stream *xdr, | |||
818 | static int rpcb_dec_getport(struct rpc_rqst *req, struct xdr_stream *xdr, | 834 | static int rpcb_dec_getport(struct rpc_rqst *req, struct xdr_stream *xdr, |
819 | struct rpcbind_args *rpcb) | 835 | struct rpcbind_args *rpcb) |
820 | { | 836 | { |
821 | struct rpc_task *task = req->rq_task; | ||
822 | unsigned long port; | 837 | unsigned long port; |
823 | __be32 *p; | 838 | __be32 *p; |
824 | 839 | ||
@@ -829,8 +844,8 @@ static int rpcb_dec_getport(struct rpc_rqst *req, struct xdr_stream *xdr, | |||
829 | return -EIO; | 844 | return -EIO; |
830 | 845 | ||
831 | port = be32_to_cpup(p); | 846 | port = be32_to_cpup(p); |
832 | dprintk("RPC: %5u PMAP_%s result: %lu\n", task->tk_pid, | 847 | dprintk("RPC: %5u PMAP_%s result: %lu\n", req->rq_task->tk_pid, |
833 | task->tk_msg.rpc_proc->p_name, port); | 848 | req->rq_task->tk_msg.rpc_proc->p_name, port); |
834 | if (unlikely(port > USHRT_MAX)) | 849 | if (unlikely(port > USHRT_MAX)) |
835 | return -EIO; | 850 | return -EIO; |
836 | 851 | ||
@@ -841,7 +856,6 @@ static int rpcb_dec_getport(struct rpc_rqst *req, struct xdr_stream *xdr, | |||
841 | static int rpcb_dec_set(struct rpc_rqst *req, struct xdr_stream *xdr, | 856 | static int rpcb_dec_set(struct rpc_rqst *req, struct xdr_stream *xdr, |
842 | unsigned int *boolp) | 857 | unsigned int *boolp) |
843 | { | 858 | { |
844 | struct rpc_task *task = req->rq_task; | ||
845 | __be32 *p; | 859 | __be32 *p; |
846 | 860 | ||
847 | p = xdr_inline_decode(xdr, 4); | 861 | p = xdr_inline_decode(xdr, 4); |
@@ -853,7 +867,8 @@ static int rpcb_dec_set(struct rpc_rqst *req, struct xdr_stream *xdr, | |||
853 | *boolp = 1; | 867 | *boolp = 1; |
854 | 868 | ||
855 | dprintk("RPC: %5u RPCB_%s call %s\n", | 869 | dprintk("RPC: %5u RPCB_%s call %s\n", |
856 | task->tk_pid, task->tk_msg.rpc_proc->p_name, | 870 | req->rq_task->tk_pid, |
871 | req->rq_task->tk_msg.rpc_proc->p_name, | ||
857 | (*boolp ? "succeeded" : "failed")); | 872 | (*boolp ? "succeeded" : "failed")); |
858 | return 0; | 873 | return 0; |
859 | } | 874 | } |
@@ -873,11 +888,11 @@ static void encode_rpcb_string(struct xdr_stream *xdr, const char *string, | |||
873 | static void rpcb_enc_getaddr(struct rpc_rqst *req, struct xdr_stream *xdr, | 888 | static void rpcb_enc_getaddr(struct rpc_rqst *req, struct xdr_stream *xdr, |
874 | const struct rpcbind_args *rpcb) | 889 | const struct rpcbind_args *rpcb) |
875 | { | 890 | { |
876 | struct rpc_task *task = req->rq_task; | ||
877 | __be32 *p; | 891 | __be32 *p; |
878 | 892 | ||
879 | dprintk("RPC: %5u encoding RPCB_%s call (%u, %u, '%s', '%s')\n", | 893 | dprintk("RPC: %5u encoding RPCB_%s call (%u, %u, '%s', '%s')\n", |
880 | task->tk_pid, task->tk_msg.rpc_proc->p_name, | 894 | req->rq_task->tk_pid, |
895 | req->rq_task->tk_msg.rpc_proc->p_name, | ||
881 | rpcb->r_prog, rpcb->r_vers, | 896 | rpcb->r_prog, rpcb->r_vers, |
882 | rpcb->r_netid, rpcb->r_addr); | 897 | rpcb->r_netid, rpcb->r_addr); |
883 | 898 | ||
@@ -895,7 +910,6 @@ static int rpcb_dec_getaddr(struct rpc_rqst *req, struct xdr_stream *xdr, | |||
895 | { | 910 | { |
896 | struct sockaddr_storage address; | 911 | struct sockaddr_storage address; |
897 | struct sockaddr *sap = (struct sockaddr *)&address; | 912 | struct sockaddr *sap = (struct sockaddr *)&address; |
898 | struct rpc_task *task = req->rq_task; | ||
899 | __be32 *p; | 913 | __be32 *p; |
900 | u32 len; | 914 | u32 len; |
901 | 915 | ||
@@ -912,7 +926,7 @@ static int rpcb_dec_getaddr(struct rpc_rqst *req, struct xdr_stream *xdr, | |||
912 | */ | 926 | */ |
913 | if (len == 0) { | 927 | if (len == 0) { |
914 | dprintk("RPC: %5u RPCB reply: program not registered\n", | 928 | dprintk("RPC: %5u RPCB reply: program not registered\n", |
915 | task->tk_pid); | 929 | req->rq_task->tk_pid); |
916 | return 0; | 930 | return 0; |
917 | } | 931 | } |
918 | 932 | ||
@@ -922,10 +936,11 @@ static int rpcb_dec_getaddr(struct rpc_rqst *req, struct xdr_stream *xdr, | |||
922 | p = xdr_inline_decode(xdr, len); | 936 | p = xdr_inline_decode(xdr, len); |
923 | if (unlikely(p == NULL)) | 937 | if (unlikely(p == NULL)) |
924 | goto out_fail; | 938 | goto out_fail; |
925 | dprintk("RPC: %5u RPCB_%s reply: %s\n", task->tk_pid, | 939 | dprintk("RPC: %5u RPCB_%s reply: %s\n", req->rq_task->tk_pid, |
926 | task->tk_msg.rpc_proc->p_name, (char *)p); | 940 | req->rq_task->tk_msg.rpc_proc->p_name, (char *)p); |
927 | 941 | ||
928 | if (rpc_uaddr2sockaddr((char *)p, len, sap, sizeof(address)) == 0) | 942 | if (rpc_uaddr2sockaddr(req->rq_xprt->xprt_net, (char *)p, len, |
943 | sap, sizeof(address)) == 0) | ||
929 | goto out_fail; | 944 | goto out_fail; |
930 | rpcb->r_port = rpc_get_port(sap); | 945 | rpcb->r_port = rpc_get_port(sap); |
931 | 946 | ||
@@ -933,7 +948,8 @@ static int rpcb_dec_getaddr(struct rpc_rqst *req, struct xdr_stream *xdr, | |||
933 | 948 | ||
934 | out_fail: | 949 | out_fail: |
935 | dprintk("RPC: %5u malformed RPCB_%s reply\n", | 950 | dprintk("RPC: %5u malformed RPCB_%s reply\n", |
936 | task->tk_pid, task->tk_msg.rpc_proc->p_name); | 951 | req->rq_task->tk_pid, |
952 | req->rq_task->tk_msg.rpc_proc->p_name); | ||
937 | return -EIO; | 953 | return -EIO; |
938 | } | 954 | } |
939 | 955 | ||
@@ -1041,7 +1057,7 @@ static struct rpc_procinfo rpcb_procedures4[] = { | |||
1041 | }, | 1057 | }, |
1042 | }; | 1058 | }; |
1043 | 1059 | ||
1044 | static struct rpcb_info rpcb_next_version[] = { | 1060 | static const struct rpcb_info rpcb_next_version[] = { |
1045 | { | 1061 | { |
1046 | .rpc_vers = RPCBVERS_2, | 1062 | .rpc_vers = RPCBVERS_2, |
1047 | .rpc_proc = &rpcb_procedures2[RPCBPROC_GETPORT], | 1063 | .rpc_proc = &rpcb_procedures2[RPCBPROC_GETPORT], |
@@ -1051,7 +1067,7 @@ static struct rpcb_info rpcb_next_version[] = { | |||
1051 | }, | 1067 | }, |
1052 | }; | 1068 | }; |
1053 | 1069 | ||
1054 | static struct rpcb_info rpcb_next_version6[] = { | 1070 | static const struct rpcb_info rpcb_next_version6[] = { |
1055 | { | 1071 | { |
1056 | .rpc_vers = RPCBVERS_4, | 1072 | .rpc_vers = RPCBVERS_4, |
1057 | .rpc_proc = &rpcb_procedures4[RPCBPROC_GETADDR], | 1073 | .rpc_proc = &rpcb_procedures4[RPCBPROC_GETADDR], |
@@ -1065,25 +1081,25 @@ static struct rpcb_info rpcb_next_version6[] = { | |||
1065 | }, | 1081 | }, |
1066 | }; | 1082 | }; |
1067 | 1083 | ||
1068 | static struct rpc_version rpcb_version2 = { | 1084 | static const struct rpc_version rpcb_version2 = { |
1069 | .number = RPCBVERS_2, | 1085 | .number = RPCBVERS_2, |
1070 | .nrprocs = ARRAY_SIZE(rpcb_procedures2), | 1086 | .nrprocs = ARRAY_SIZE(rpcb_procedures2), |
1071 | .procs = rpcb_procedures2 | 1087 | .procs = rpcb_procedures2 |
1072 | }; | 1088 | }; |
1073 | 1089 | ||
1074 | static struct rpc_version rpcb_version3 = { | 1090 | static const struct rpc_version rpcb_version3 = { |
1075 | .number = RPCBVERS_3, | 1091 | .number = RPCBVERS_3, |
1076 | .nrprocs = ARRAY_SIZE(rpcb_procedures3), | 1092 | .nrprocs = ARRAY_SIZE(rpcb_procedures3), |
1077 | .procs = rpcb_procedures3 | 1093 | .procs = rpcb_procedures3 |
1078 | }; | 1094 | }; |
1079 | 1095 | ||
1080 | static struct rpc_version rpcb_version4 = { | 1096 | static const struct rpc_version rpcb_version4 = { |
1081 | .number = RPCBVERS_4, | 1097 | .number = RPCBVERS_4, |
1082 | .nrprocs = ARRAY_SIZE(rpcb_procedures4), | 1098 | .nrprocs = ARRAY_SIZE(rpcb_procedures4), |
1083 | .procs = rpcb_procedures4 | 1099 | .procs = rpcb_procedures4 |
1084 | }; | 1100 | }; |
1085 | 1101 | ||
1086 | static struct rpc_version *rpcb_version[] = { | 1102 | static const struct rpc_version *rpcb_version[] = { |
1087 | NULL, | 1103 | NULL, |
1088 | NULL, | 1104 | NULL, |
1089 | &rpcb_version2, | 1105 | &rpcb_version2, |
@@ -1093,7 +1109,7 @@ static struct rpc_version *rpcb_version[] = { | |||
1093 | 1109 | ||
1094 | static struct rpc_stat rpcb_stats; | 1110 | static struct rpc_stat rpcb_stats; |
1095 | 1111 | ||
1096 | static struct rpc_program rpcb_program = { | 1112 | static const struct rpc_program rpcb_program = { |
1097 | .name = "rpcbind", | 1113 | .name = "rpcbind", |
1098 | .number = RPCBIND_PROGRAM, | 1114 | .number = RPCBIND_PROGRAM, |
1099 | .nrvers = ARRAY_SIZE(rpcb_version), | 1115 | .nrvers = ARRAY_SIZE(rpcb_version), |
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index 3341d8962786..994cfea2bad6 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c | |||
@@ -28,6 +28,9 @@ | |||
28 | #define RPCDBG_FACILITY RPCDBG_SCHED | 28 | #define RPCDBG_FACILITY RPCDBG_SCHED |
29 | #endif | 29 | #endif |
30 | 30 | ||
31 | #define CREATE_TRACE_POINTS | ||
32 | #include <trace/events/sunrpc.h> | ||
33 | |||
31 | /* | 34 | /* |
32 | * RPC slabs and memory pools | 35 | * RPC slabs and memory pools |
33 | */ | 36 | */ |
@@ -205,9 +208,7 @@ static void __rpc_init_priority_wait_queue(struct rpc_wait_queue *queue, const c | |||
205 | queue->qlen = 0; | 208 | queue->qlen = 0; |
206 | setup_timer(&queue->timer_list.timer, __rpc_queue_timer_fn, (unsigned long)queue); | 209 | setup_timer(&queue->timer_list.timer, __rpc_queue_timer_fn, (unsigned long)queue); |
207 | INIT_LIST_HEAD(&queue->timer_list.list); | 210 | INIT_LIST_HEAD(&queue->timer_list.list); |
208 | #ifdef RPC_DEBUG | 211 | rpc_assign_waitqueue_name(queue, qname); |
209 | queue->name = qname; | ||
210 | #endif | ||
211 | } | 212 | } |
212 | 213 | ||
213 | void rpc_init_priority_wait_queue(struct rpc_wait_queue *queue, const char *qname) | 214 | void rpc_init_priority_wait_queue(struct rpc_wait_queue *queue, const char *qname) |
@@ -251,6 +252,8 @@ static inline void rpc_task_set_debuginfo(struct rpc_task *task) | |||
251 | 252 | ||
252 | static void rpc_set_active(struct rpc_task *task) | 253 | static void rpc_set_active(struct rpc_task *task) |
253 | { | 254 | { |
255 | trace_rpc_task_begin(task->tk_client, task, NULL); | ||
256 | |||
254 | rpc_task_set_debuginfo(task); | 257 | rpc_task_set_debuginfo(task); |
255 | set_bit(RPC_TASK_ACTIVE, &task->tk_runstate); | 258 | set_bit(RPC_TASK_ACTIVE, &task->tk_runstate); |
256 | } | 259 | } |
@@ -267,6 +270,8 @@ static int rpc_complete_task(struct rpc_task *task) | |||
267 | unsigned long flags; | 270 | unsigned long flags; |
268 | int ret; | 271 | int ret; |
269 | 272 | ||
273 | trace_rpc_task_complete(task->tk_client, task, NULL); | ||
274 | |||
270 | spin_lock_irqsave(&wq->lock, flags); | 275 | spin_lock_irqsave(&wq->lock, flags); |
271 | clear_bit(RPC_TASK_ACTIVE, &task->tk_runstate); | 276 | clear_bit(RPC_TASK_ACTIVE, &task->tk_runstate); |
272 | ret = atomic_dec_and_test(&task->tk_count); | 277 | ret = atomic_dec_and_test(&task->tk_count); |
@@ -324,6 +329,8 @@ static void __rpc_sleep_on_priority(struct rpc_wait_queue *q, | |||
324 | dprintk("RPC: %5u sleep_on(queue \"%s\" time %lu)\n", | 329 | dprintk("RPC: %5u sleep_on(queue \"%s\" time %lu)\n", |
325 | task->tk_pid, rpc_qname(q), jiffies); | 330 | task->tk_pid, rpc_qname(q), jiffies); |
326 | 331 | ||
332 | trace_rpc_task_sleep(task->tk_client, task, q); | ||
333 | |||
327 | __rpc_add_wait_queue(q, task, queue_priority); | 334 | __rpc_add_wait_queue(q, task, queue_priority); |
328 | 335 | ||
329 | BUG_ON(task->tk_callback != NULL); | 336 | BUG_ON(task->tk_callback != NULL); |
@@ -378,6 +385,8 @@ static void __rpc_do_wake_up_task(struct rpc_wait_queue *queue, struct rpc_task | |||
378 | return; | 385 | return; |
379 | } | 386 | } |
380 | 387 | ||
388 | trace_rpc_task_wakeup(task->tk_client, task, queue); | ||
389 | |||
381 | __rpc_remove_wait_queue(queue, task); | 390 | __rpc_remove_wait_queue(queue, task); |
382 | 391 | ||
383 | rpc_make_runnable(task); | 392 | rpc_make_runnable(task); |
@@ -422,7 +431,7 @@ EXPORT_SYMBOL_GPL(rpc_wake_up_queued_task); | |||
422 | /* | 431 | /* |
423 | * Wake up the next task on a priority queue. | 432 | * Wake up the next task on a priority queue. |
424 | */ | 433 | */ |
425 | static struct rpc_task * __rpc_wake_up_next_priority(struct rpc_wait_queue *queue) | 434 | static struct rpc_task *__rpc_find_next_queued_priority(struct rpc_wait_queue *queue) |
426 | { | 435 | { |
427 | struct list_head *q; | 436 | struct list_head *q; |
428 | struct rpc_task *task; | 437 | struct rpc_task *task; |
@@ -467,30 +476,54 @@ new_queue: | |||
467 | new_owner: | 476 | new_owner: |
468 | rpc_set_waitqueue_owner(queue, task->tk_owner); | 477 | rpc_set_waitqueue_owner(queue, task->tk_owner); |
469 | out: | 478 | out: |
470 | rpc_wake_up_task_queue_locked(queue, task); | ||
471 | return task; | 479 | return task; |
472 | } | 480 | } |
473 | 481 | ||
482 | static struct rpc_task *__rpc_find_next_queued(struct rpc_wait_queue *queue) | ||
483 | { | ||
484 | if (RPC_IS_PRIORITY(queue)) | ||
485 | return __rpc_find_next_queued_priority(queue); | ||
486 | if (!list_empty(&queue->tasks[0])) | ||
487 | return list_first_entry(&queue->tasks[0], struct rpc_task, u.tk_wait.list); | ||
488 | return NULL; | ||
489 | } | ||
490 | |||
474 | /* | 491 | /* |
475 | * Wake up the next task on the wait queue. | 492 | * Wake up the first task on the wait queue. |
476 | */ | 493 | */ |
477 | struct rpc_task * rpc_wake_up_next(struct rpc_wait_queue *queue) | 494 | struct rpc_task *rpc_wake_up_first(struct rpc_wait_queue *queue, |
495 | bool (*func)(struct rpc_task *, void *), void *data) | ||
478 | { | 496 | { |
479 | struct rpc_task *task = NULL; | 497 | struct rpc_task *task = NULL; |
480 | 498 | ||
481 | dprintk("RPC: wake_up_next(%p \"%s\")\n", | 499 | dprintk("RPC: wake_up_first(%p \"%s\")\n", |
482 | queue, rpc_qname(queue)); | 500 | queue, rpc_qname(queue)); |
483 | spin_lock_bh(&queue->lock); | 501 | spin_lock_bh(&queue->lock); |
484 | if (RPC_IS_PRIORITY(queue)) | 502 | task = __rpc_find_next_queued(queue); |
485 | task = __rpc_wake_up_next_priority(queue); | 503 | if (task != NULL) { |
486 | else { | 504 | if (func(task, data)) |
487 | task_for_first(task, &queue->tasks[0]) | ||
488 | rpc_wake_up_task_queue_locked(queue, task); | 505 | rpc_wake_up_task_queue_locked(queue, task); |
506 | else | ||
507 | task = NULL; | ||
489 | } | 508 | } |
490 | spin_unlock_bh(&queue->lock); | 509 | spin_unlock_bh(&queue->lock); |
491 | 510 | ||
492 | return task; | 511 | return task; |
493 | } | 512 | } |
513 | EXPORT_SYMBOL_GPL(rpc_wake_up_first); | ||
514 | |||
515 | static bool rpc_wake_up_next_func(struct rpc_task *task, void *data) | ||
516 | { | ||
517 | return true; | ||
518 | } | ||
519 | |||
520 | /* | ||
521 | * Wake up the next task on the wait queue. | ||
522 | */ | ||
523 | struct rpc_task *rpc_wake_up_next(struct rpc_wait_queue *queue) | ||
524 | { | ||
525 | return rpc_wake_up_first(queue, rpc_wake_up_next_func, NULL); | ||
526 | } | ||
494 | EXPORT_SYMBOL_GPL(rpc_wake_up_next); | 527 | EXPORT_SYMBOL_GPL(rpc_wake_up_next); |
495 | 528 | ||
496 | /** | 529 | /** |
@@ -501,14 +534,18 @@ EXPORT_SYMBOL_GPL(rpc_wake_up_next); | |||
501 | */ | 534 | */ |
502 | void rpc_wake_up(struct rpc_wait_queue *queue) | 535 | void rpc_wake_up(struct rpc_wait_queue *queue) |
503 | { | 536 | { |
504 | struct rpc_task *task, *next; | ||
505 | struct list_head *head; | 537 | struct list_head *head; |
506 | 538 | ||
507 | spin_lock_bh(&queue->lock); | 539 | spin_lock_bh(&queue->lock); |
508 | head = &queue->tasks[queue->maxpriority]; | 540 | head = &queue->tasks[queue->maxpriority]; |
509 | for (;;) { | 541 | for (;;) { |
510 | list_for_each_entry_safe(task, next, head, u.tk_wait.list) | 542 | while (!list_empty(head)) { |
543 | struct rpc_task *task; | ||
544 | task = list_first_entry(head, | ||
545 | struct rpc_task, | ||
546 | u.tk_wait.list); | ||
511 | rpc_wake_up_task_queue_locked(queue, task); | 547 | rpc_wake_up_task_queue_locked(queue, task); |
548 | } | ||
512 | if (head == &queue->tasks[0]) | 549 | if (head == &queue->tasks[0]) |
513 | break; | 550 | break; |
514 | head--; | 551 | head--; |
@@ -526,13 +563,16 @@ EXPORT_SYMBOL_GPL(rpc_wake_up); | |||
526 | */ | 563 | */ |
527 | void rpc_wake_up_status(struct rpc_wait_queue *queue, int status) | 564 | void rpc_wake_up_status(struct rpc_wait_queue *queue, int status) |
528 | { | 565 | { |
529 | struct rpc_task *task, *next; | ||
530 | struct list_head *head; | 566 | struct list_head *head; |
531 | 567 | ||
532 | spin_lock_bh(&queue->lock); | 568 | spin_lock_bh(&queue->lock); |
533 | head = &queue->tasks[queue->maxpriority]; | 569 | head = &queue->tasks[queue->maxpriority]; |
534 | for (;;) { | 570 | for (;;) { |
535 | list_for_each_entry_safe(task, next, head, u.tk_wait.list) { | 571 | while (!list_empty(head)) { |
572 | struct rpc_task *task; | ||
573 | task = list_first_entry(head, | ||
574 | struct rpc_task, | ||
575 | u.tk_wait.list); | ||
536 | task->tk_status = status; | 576 | task->tk_status = status; |
537 | rpc_wake_up_task_queue_locked(queue, task); | 577 | rpc_wake_up_task_queue_locked(queue, task); |
538 | } | 578 | } |
@@ -677,6 +717,7 @@ static void __rpc_execute(struct rpc_task *task) | |||
677 | if (do_action == NULL) | 717 | if (do_action == NULL) |
678 | break; | 718 | break; |
679 | } | 719 | } |
720 | trace_rpc_task_run_action(task->tk_client, task, task->tk_action); | ||
680 | do_action(task); | 721 | do_action(task); |
681 | 722 | ||
682 | /* | 723 | /* |
diff --git a/net/sunrpc/stats.c b/net/sunrpc/stats.c index 80df89d957ba..bc2068ee795b 100644 --- a/net/sunrpc/stats.c +++ b/net/sunrpc/stats.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/sunrpc/clnt.h> | 22 | #include <linux/sunrpc/clnt.h> |
23 | #include <linux/sunrpc/svcsock.h> | 23 | #include <linux/sunrpc/svcsock.h> |
24 | #include <linux/sunrpc/metrics.h> | 24 | #include <linux/sunrpc/metrics.h> |
25 | #include <linux/rcupdate.h> | ||
25 | 26 | ||
26 | #include "netns.h" | 27 | #include "netns.h" |
27 | 28 | ||
@@ -133,20 +134,19 @@ EXPORT_SYMBOL_GPL(rpc_free_iostats); | |||
133 | /** | 134 | /** |
134 | * rpc_count_iostats - tally up per-task stats | 135 | * rpc_count_iostats - tally up per-task stats |
135 | * @task: completed rpc_task | 136 | * @task: completed rpc_task |
137 | * @stats: array of stat structures | ||
136 | * | 138 | * |
137 | * Relies on the caller for serialization. | 139 | * Relies on the caller for serialization. |
138 | */ | 140 | */ |
139 | void rpc_count_iostats(struct rpc_task *task) | 141 | void rpc_count_iostats(const struct rpc_task *task, struct rpc_iostats *stats) |
140 | { | 142 | { |
141 | struct rpc_rqst *req = task->tk_rqstp; | 143 | struct rpc_rqst *req = task->tk_rqstp; |
142 | struct rpc_iostats *stats; | ||
143 | struct rpc_iostats *op_metrics; | 144 | struct rpc_iostats *op_metrics; |
144 | ktime_t delta; | 145 | ktime_t delta; |
145 | 146 | ||
146 | if (!task->tk_client || !task->tk_client->cl_metrics || !req) | 147 | if (!stats || !req) |
147 | return; | 148 | return; |
148 | 149 | ||
149 | stats = task->tk_client->cl_metrics; | ||
150 | op_metrics = &stats[task->tk_msg.rpc_proc->p_statidx]; | 150 | op_metrics = &stats[task->tk_msg.rpc_proc->p_statidx]; |
151 | 151 | ||
152 | op_metrics->om_ops++; | 152 | op_metrics->om_ops++; |
@@ -164,6 +164,7 @@ void rpc_count_iostats(struct rpc_task *task) | |||
164 | delta = ktime_sub(ktime_get(), task->tk_start); | 164 | delta = ktime_sub(ktime_get(), task->tk_start); |
165 | op_metrics->om_execute = ktime_add(op_metrics->om_execute, delta); | 165 | op_metrics->om_execute = ktime_add(op_metrics->om_execute, delta); |
166 | } | 166 | } |
167 | EXPORT_SYMBOL_GPL(rpc_count_iostats); | ||
167 | 168 | ||
168 | static void _print_name(struct seq_file *seq, unsigned int op, | 169 | static void _print_name(struct seq_file *seq, unsigned int op, |
169 | struct rpc_procinfo *procs) | 170 | struct rpc_procinfo *procs) |
@@ -179,7 +180,7 @@ static void _print_name(struct seq_file *seq, unsigned int op, | |||
179 | void rpc_print_iostats(struct seq_file *seq, struct rpc_clnt *clnt) | 180 | void rpc_print_iostats(struct seq_file *seq, struct rpc_clnt *clnt) |
180 | { | 181 | { |
181 | struct rpc_iostats *stats = clnt->cl_metrics; | 182 | struct rpc_iostats *stats = clnt->cl_metrics; |
182 | struct rpc_xprt *xprt = clnt->cl_xprt; | 183 | struct rpc_xprt *xprt; |
183 | unsigned int op, maxproc = clnt->cl_maxproc; | 184 | unsigned int op, maxproc = clnt->cl_maxproc; |
184 | 185 | ||
185 | if (!stats) | 186 | if (!stats) |
@@ -189,8 +190,11 @@ void rpc_print_iostats(struct seq_file *seq, struct rpc_clnt *clnt) | |||
189 | seq_printf(seq, "p/v: %u/%u (%s)\n", | 190 | seq_printf(seq, "p/v: %u/%u (%s)\n", |
190 | clnt->cl_prog, clnt->cl_vers, clnt->cl_protname); | 191 | clnt->cl_prog, clnt->cl_vers, clnt->cl_protname); |
191 | 192 | ||
193 | rcu_read_lock(); | ||
194 | xprt = rcu_dereference(clnt->cl_xprt); | ||
192 | if (xprt) | 195 | if (xprt) |
193 | xprt->ops->print_stats(xprt, seq); | 196 | xprt->ops->print_stats(xprt, seq); |
197 | rcu_read_unlock(); | ||
194 | 198 | ||
195 | seq_printf(seq, "\tper-op statistics\n"); | 199 | seq_printf(seq, "\tper-op statistics\n"); |
196 | for (op = 0; op < maxproc; op++) { | 200 | for (op = 0; op < maxproc; op++) { |
@@ -213,45 +217,46 @@ EXPORT_SYMBOL_GPL(rpc_print_iostats); | |||
213 | * Register/unregister RPC proc files | 217 | * Register/unregister RPC proc files |
214 | */ | 218 | */ |
215 | static inline struct proc_dir_entry * | 219 | static inline struct proc_dir_entry * |
216 | do_register(const char *name, void *data, const struct file_operations *fops) | 220 | do_register(struct net *net, const char *name, void *data, |
221 | const struct file_operations *fops) | ||
217 | { | 222 | { |
218 | struct sunrpc_net *sn; | 223 | struct sunrpc_net *sn; |
219 | 224 | ||
220 | dprintk("RPC: registering /proc/net/rpc/%s\n", name); | 225 | dprintk("RPC: registering /proc/net/rpc/%s\n", name); |
221 | sn = net_generic(&init_net, sunrpc_net_id); | 226 | sn = net_generic(net, sunrpc_net_id); |
222 | return proc_create_data(name, 0, sn->proc_net_rpc, fops, data); | 227 | return proc_create_data(name, 0, sn->proc_net_rpc, fops, data); |
223 | } | 228 | } |
224 | 229 | ||
225 | struct proc_dir_entry * | 230 | struct proc_dir_entry * |
226 | rpc_proc_register(struct rpc_stat *statp) | 231 | rpc_proc_register(struct net *net, struct rpc_stat *statp) |
227 | { | 232 | { |
228 | return do_register(statp->program->name, statp, &rpc_proc_fops); | 233 | return do_register(net, statp->program->name, statp, &rpc_proc_fops); |
229 | } | 234 | } |
230 | EXPORT_SYMBOL_GPL(rpc_proc_register); | 235 | EXPORT_SYMBOL_GPL(rpc_proc_register); |
231 | 236 | ||
232 | void | 237 | void |
233 | rpc_proc_unregister(const char *name) | 238 | rpc_proc_unregister(struct net *net, const char *name) |
234 | { | 239 | { |
235 | struct sunrpc_net *sn; | 240 | struct sunrpc_net *sn; |
236 | 241 | ||
237 | sn = net_generic(&init_net, sunrpc_net_id); | 242 | sn = net_generic(net, sunrpc_net_id); |
238 | remove_proc_entry(name, sn->proc_net_rpc); | 243 | remove_proc_entry(name, sn->proc_net_rpc); |
239 | } | 244 | } |
240 | EXPORT_SYMBOL_GPL(rpc_proc_unregister); | 245 | EXPORT_SYMBOL_GPL(rpc_proc_unregister); |
241 | 246 | ||
242 | struct proc_dir_entry * | 247 | struct proc_dir_entry * |
243 | svc_proc_register(struct svc_stat *statp, const struct file_operations *fops) | 248 | svc_proc_register(struct net *net, struct svc_stat *statp, const struct file_operations *fops) |
244 | { | 249 | { |
245 | return do_register(statp->program->pg_name, statp, fops); | 250 | return do_register(net, statp->program->pg_name, statp, fops); |
246 | } | 251 | } |
247 | EXPORT_SYMBOL_GPL(svc_proc_register); | 252 | EXPORT_SYMBOL_GPL(svc_proc_register); |
248 | 253 | ||
249 | void | 254 | void |
250 | svc_proc_unregister(const char *name) | 255 | svc_proc_unregister(struct net *net, const char *name) |
251 | { | 256 | { |
252 | struct sunrpc_net *sn; | 257 | struct sunrpc_net *sn; |
253 | 258 | ||
254 | sn = net_generic(&init_net, sunrpc_net_id); | 259 | sn = net_generic(net, sunrpc_net_id); |
255 | remove_proc_entry(name, sn->proc_net_rpc); | 260 | remove_proc_entry(name, sn->proc_net_rpc); |
256 | } | 261 | } |
257 | EXPORT_SYMBOL_GPL(svc_proc_unregister); | 262 | EXPORT_SYMBOL_GPL(svc_proc_unregister); |
diff --git a/net/sunrpc/sunrpc.h b/net/sunrpc/sunrpc.h index 90c292e2738b..14c9f6d1c5ff 100644 --- a/net/sunrpc/sunrpc.h +++ b/net/sunrpc/sunrpc.h | |||
@@ -47,5 +47,7 @@ int svc_send_common(struct socket *sock, struct xdr_buf *xdr, | |||
47 | struct page *headpage, unsigned long headoffset, | 47 | struct page *headpage, unsigned long headoffset, |
48 | struct page *tailpage, unsigned long tailoffset); | 48 | struct page *tailpage, unsigned long tailoffset); |
49 | 49 | ||
50 | int rpc_clients_notifier_register(void); | ||
51 | void rpc_clients_notifier_unregister(void); | ||
50 | #endif /* _NET_SUNRPC_SUNRPC_H */ | 52 | #endif /* _NET_SUNRPC_SUNRPC_H */ |
51 | 53 | ||
diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c index 8ec9778c3f4a..8adfc88e793a 100644 --- a/net/sunrpc/sunrpc_syms.c +++ b/net/sunrpc/sunrpc_syms.c | |||
@@ -25,10 +25,12 @@ | |||
25 | #include "netns.h" | 25 | #include "netns.h" |
26 | 26 | ||
27 | int sunrpc_net_id; | 27 | int sunrpc_net_id; |
28 | EXPORT_SYMBOL_GPL(sunrpc_net_id); | ||
28 | 29 | ||
29 | static __net_init int sunrpc_init_net(struct net *net) | 30 | static __net_init int sunrpc_init_net(struct net *net) |
30 | { | 31 | { |
31 | int err; | 32 | int err; |
33 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
32 | 34 | ||
33 | err = rpc_proc_init(net); | 35 | err = rpc_proc_init(net); |
34 | if (err) | 36 | if (err) |
@@ -38,8 +40,18 @@ static __net_init int sunrpc_init_net(struct net *net) | |||
38 | if (err) | 40 | if (err) |
39 | goto err_ipmap; | 41 | goto err_ipmap; |
40 | 42 | ||
43 | err = unix_gid_cache_create(net); | ||
44 | if (err) | ||
45 | goto err_unixgid; | ||
46 | |||
47 | rpc_pipefs_init_net(net); | ||
48 | INIT_LIST_HEAD(&sn->all_clients); | ||
49 | spin_lock_init(&sn->rpc_client_lock); | ||
50 | spin_lock_init(&sn->rpcb_clnt_lock); | ||
41 | return 0; | 51 | return 0; |
42 | 52 | ||
53 | err_unixgid: | ||
54 | ip_map_cache_destroy(net); | ||
43 | err_ipmap: | 55 | err_ipmap: |
44 | rpc_proc_exit(net); | 56 | rpc_proc_exit(net); |
45 | err_proc: | 57 | err_proc: |
@@ -48,6 +60,7 @@ err_proc: | |||
48 | 60 | ||
49 | static __net_exit void sunrpc_exit_net(struct net *net) | 61 | static __net_exit void sunrpc_exit_net(struct net *net) |
50 | { | 62 | { |
63 | unix_gid_cache_destroy(net); | ||
51 | ip_map_cache_destroy(net); | 64 | ip_map_cache_destroy(net); |
52 | rpc_proc_exit(net); | 65 | rpc_proc_exit(net); |
53 | } | 66 | } |
@@ -59,8 +72,6 @@ static struct pernet_operations sunrpc_net_ops = { | |||
59 | .size = sizeof(struct sunrpc_net), | 72 | .size = sizeof(struct sunrpc_net), |
60 | }; | 73 | }; |
61 | 74 | ||
62 | extern struct cache_detail unix_gid_cache; | ||
63 | |||
64 | static int __init | 75 | static int __init |
65 | init_sunrpc(void) | 76 | init_sunrpc(void) |
66 | { | 77 | { |
@@ -82,7 +93,6 @@ init_sunrpc(void) | |||
82 | #ifdef RPC_DEBUG | 93 | #ifdef RPC_DEBUG |
83 | rpc_register_sysctl(); | 94 | rpc_register_sysctl(); |
84 | #endif | 95 | #endif |
85 | cache_register(&unix_gid_cache); | ||
86 | svc_init_xprt_sock(); /* svc sock transport */ | 96 | svc_init_xprt_sock(); /* svc sock transport */ |
87 | init_socket_xprt(); /* clnt sock transport */ | 97 | init_socket_xprt(); /* clnt sock transport */ |
88 | return 0; | 98 | return 0; |
@@ -105,7 +115,6 @@ cleanup_sunrpc(void) | |||
105 | svc_cleanup_xprt_sock(); | 115 | svc_cleanup_xprt_sock(); |
106 | unregister_rpc_pipefs(); | 116 | unregister_rpc_pipefs(); |
107 | rpc_destroy_mempool(); | 117 | rpc_destroy_mempool(); |
108 | cache_unregister(&unix_gid_cache); | ||
109 | unregister_pernet_subsys(&sunrpc_net_ops); | 118 | unregister_pernet_subsys(&sunrpc_net_ops); |
110 | #ifdef RPC_DEBUG | 119 | #ifdef RPC_DEBUG |
111 | rpc_unregister_sysctl(); | 120 | rpc_unregister_sysctl(); |
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c index e4aabc02368b..4153846984ac 100644 --- a/net/sunrpc/svc.c +++ b/net/sunrpc/svc.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/module.h> | 20 | #include <linux/module.h> |
21 | #include <linux/kthread.h> | 21 | #include <linux/kthread.h> |
22 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
23 | #include <linux/nsproxy.h> | ||
23 | 24 | ||
24 | #include <linux/sunrpc/types.h> | 25 | #include <linux/sunrpc/types.h> |
25 | #include <linux/sunrpc/xdr.h> | 26 | #include <linux/sunrpc/xdr.h> |
@@ -30,7 +31,7 @@ | |||
30 | 31 | ||
31 | #define RPCDBG_FACILITY RPCDBG_SVCDSP | 32 | #define RPCDBG_FACILITY RPCDBG_SVCDSP |
32 | 33 | ||
33 | static void svc_unregister(const struct svc_serv *serv); | 34 | static void svc_unregister(const struct svc_serv *serv, struct net *net); |
34 | 35 | ||
35 | #define svc_serv_is_pooled(serv) ((serv)->sv_function) | 36 | #define svc_serv_is_pooled(serv) ((serv)->sv_function) |
36 | 37 | ||
@@ -368,23 +369,24 @@ svc_pool_for_cpu(struct svc_serv *serv, int cpu) | |||
368 | return &serv->sv_pools[pidx % serv->sv_nrpools]; | 369 | return &serv->sv_pools[pidx % serv->sv_nrpools]; |
369 | } | 370 | } |
370 | 371 | ||
371 | static int svc_rpcb_setup(struct svc_serv *serv) | 372 | int svc_rpcb_setup(struct svc_serv *serv, struct net *net) |
372 | { | 373 | { |
373 | int err; | 374 | int err; |
374 | 375 | ||
375 | err = rpcb_create_local(); | 376 | err = rpcb_create_local(net); |
376 | if (err) | 377 | if (err) |
377 | return err; | 378 | return err; |
378 | 379 | ||
379 | /* Remove any stale portmap registrations */ | 380 | /* Remove any stale portmap registrations */ |
380 | svc_unregister(serv); | 381 | svc_unregister(serv, net); |
381 | return 0; | 382 | return 0; |
382 | } | 383 | } |
384 | EXPORT_SYMBOL_GPL(svc_rpcb_setup); | ||
383 | 385 | ||
384 | void svc_rpcb_cleanup(struct svc_serv *serv) | 386 | void svc_rpcb_cleanup(struct svc_serv *serv, struct net *net) |
385 | { | 387 | { |
386 | svc_unregister(serv); | 388 | svc_unregister(serv, net); |
387 | rpcb_put_local(); | 389 | rpcb_put_local(net); |
388 | } | 390 | } |
389 | EXPORT_SYMBOL_GPL(svc_rpcb_cleanup); | 391 | EXPORT_SYMBOL_GPL(svc_rpcb_cleanup); |
390 | 392 | ||
@@ -410,7 +412,7 @@ static int svc_uses_rpcbind(struct svc_serv *serv) | |||
410 | */ | 412 | */ |
411 | static struct svc_serv * | 413 | static struct svc_serv * |
412 | __svc_create(struct svc_program *prog, unsigned int bufsize, int npools, | 414 | __svc_create(struct svc_program *prog, unsigned int bufsize, int npools, |
413 | void (*shutdown)(struct svc_serv *serv)) | 415 | void (*shutdown)(struct svc_serv *serv, struct net *net)) |
414 | { | 416 | { |
415 | struct svc_serv *serv; | 417 | struct svc_serv *serv; |
416 | unsigned int vers; | 418 | unsigned int vers; |
@@ -470,7 +472,7 @@ __svc_create(struct svc_program *prog, unsigned int bufsize, int npools, | |||
470 | } | 472 | } |
471 | 473 | ||
472 | if (svc_uses_rpcbind(serv)) { | 474 | if (svc_uses_rpcbind(serv)) { |
473 | if (svc_rpcb_setup(serv) < 0) { | 475 | if (svc_rpcb_setup(serv, current->nsproxy->net_ns) < 0) { |
474 | kfree(serv->sv_pools); | 476 | kfree(serv->sv_pools); |
475 | kfree(serv); | 477 | kfree(serv); |
476 | return NULL; | 478 | return NULL; |
@@ -484,7 +486,7 @@ __svc_create(struct svc_program *prog, unsigned int bufsize, int npools, | |||
484 | 486 | ||
485 | struct svc_serv * | 487 | struct svc_serv * |
486 | svc_create(struct svc_program *prog, unsigned int bufsize, | 488 | svc_create(struct svc_program *prog, unsigned int bufsize, |
487 | void (*shutdown)(struct svc_serv *serv)) | 489 | void (*shutdown)(struct svc_serv *serv, struct net *net)) |
488 | { | 490 | { |
489 | return __svc_create(prog, bufsize, /*npools*/1, shutdown); | 491 | return __svc_create(prog, bufsize, /*npools*/1, shutdown); |
490 | } | 492 | } |
@@ -492,7 +494,7 @@ EXPORT_SYMBOL_GPL(svc_create); | |||
492 | 494 | ||
493 | struct svc_serv * | 495 | struct svc_serv * |
494 | svc_create_pooled(struct svc_program *prog, unsigned int bufsize, | 496 | svc_create_pooled(struct svc_program *prog, unsigned int bufsize, |
495 | void (*shutdown)(struct svc_serv *serv), | 497 | void (*shutdown)(struct svc_serv *serv, struct net *net), |
496 | svc_thread_fn func, struct module *mod) | 498 | svc_thread_fn func, struct module *mod) |
497 | { | 499 | { |
498 | struct svc_serv *serv; | 500 | struct svc_serv *serv; |
@@ -509,6 +511,24 @@ svc_create_pooled(struct svc_program *prog, unsigned int bufsize, | |||
509 | } | 511 | } |
510 | EXPORT_SYMBOL_GPL(svc_create_pooled); | 512 | EXPORT_SYMBOL_GPL(svc_create_pooled); |
511 | 513 | ||
514 | void svc_shutdown_net(struct svc_serv *serv, struct net *net) | ||
515 | { | ||
516 | /* | ||
517 | * The set of xprts (contained in the sv_tempsocks and | ||
518 | * sv_permsocks lists) is now constant, since it is modified | ||
519 | * only by accepting new sockets (done by service threads in | ||
520 | * svc_recv) or aging old ones (done by sv_temptimer), or | ||
521 | * configuration changes (excluded by whatever locking the | ||
522 | * caller is using--nfsd_mutex in the case of nfsd). So it's | ||
523 | * safe to traverse those lists and shut everything down: | ||
524 | */ | ||
525 | svc_close_net(serv, net); | ||
526 | |||
527 | if (serv->sv_shutdown) | ||
528 | serv->sv_shutdown(serv, net); | ||
529 | } | ||
530 | EXPORT_SYMBOL_GPL(svc_shutdown_net); | ||
531 | |||
512 | /* | 532 | /* |
513 | * Destroy an RPC service. Should be called with appropriate locking to | 533 | * Destroy an RPC service. Should be called with appropriate locking to |
514 | * protect the sv_nrthreads, sv_permsocks and sv_tempsocks. | 534 | * protect the sv_nrthreads, sv_permsocks and sv_tempsocks. |
@@ -516,6 +536,8 @@ EXPORT_SYMBOL_GPL(svc_create_pooled); | |||
516 | void | 536 | void |
517 | svc_destroy(struct svc_serv *serv) | 537 | svc_destroy(struct svc_serv *serv) |
518 | { | 538 | { |
539 | struct net *net = current->nsproxy->net_ns; | ||
540 | |||
519 | dprintk("svc: svc_destroy(%s, %d)\n", | 541 | dprintk("svc: svc_destroy(%s, %d)\n", |
520 | serv->sv_program->pg_name, | 542 | serv->sv_program->pg_name, |
521 | serv->sv_nrthreads); | 543 | serv->sv_nrthreads); |
@@ -529,19 +551,15 @@ svc_destroy(struct svc_serv *serv) | |||
529 | printk("svc_destroy: no threads for serv=%p!\n", serv); | 551 | printk("svc_destroy: no threads for serv=%p!\n", serv); |
530 | 552 | ||
531 | del_timer_sync(&serv->sv_temptimer); | 553 | del_timer_sync(&serv->sv_temptimer); |
554 | |||
555 | svc_shutdown_net(serv, net); | ||
556 | |||
532 | /* | 557 | /* |
533 | * The set of xprts (contained in the sv_tempsocks and | 558 | * The last user is gone and thus all sockets have to be destroyed to |
534 | * sv_permsocks lists) is now constant, since it is modified | 559 | * the point. Check this. |
535 | * only by accepting new sockets (done by service threads in | ||
536 | * svc_recv) or aging old ones (done by sv_temptimer), or | ||
537 | * configuration changes (excluded by whatever locking the | ||
538 | * caller is using--nfsd_mutex in the case of nfsd). So it's | ||
539 | * safe to traverse those lists and shut everything down: | ||
540 | */ | 560 | */ |
541 | svc_close_all(serv); | 561 | BUG_ON(!list_empty(&serv->sv_permsocks)); |
542 | 562 | BUG_ON(!list_empty(&serv->sv_tempsocks)); | |
543 | if (serv->sv_shutdown) | ||
544 | serv->sv_shutdown(serv); | ||
545 | 563 | ||
546 | cache_clean_deferred(serv); | 564 | cache_clean_deferred(serv); |
547 | 565 | ||
@@ -795,7 +813,8 @@ EXPORT_SYMBOL_GPL(svc_exit_thread); | |||
795 | * Returns zero on success; a negative errno value is returned | 813 | * Returns zero on success; a negative errno value is returned |
796 | * if any error occurs. | 814 | * if any error occurs. |
797 | */ | 815 | */ |
798 | static int __svc_rpcb_register4(const u32 program, const u32 version, | 816 | static int __svc_rpcb_register4(struct net *net, const u32 program, |
817 | const u32 version, | ||
799 | const unsigned short protocol, | 818 | const unsigned short protocol, |
800 | const unsigned short port) | 819 | const unsigned short port) |
801 | { | 820 | { |
@@ -818,7 +837,7 @@ static int __svc_rpcb_register4(const u32 program, const u32 version, | |||
818 | return -ENOPROTOOPT; | 837 | return -ENOPROTOOPT; |
819 | } | 838 | } |
820 | 839 | ||
821 | error = rpcb_v4_register(program, version, | 840 | error = rpcb_v4_register(net, program, version, |
822 | (const struct sockaddr *)&sin, netid); | 841 | (const struct sockaddr *)&sin, netid); |
823 | 842 | ||
824 | /* | 843 | /* |
@@ -826,7 +845,7 @@ static int __svc_rpcb_register4(const u32 program, const u32 version, | |||
826 | * registration request with the legacy rpcbind v2 protocol. | 845 | * registration request with the legacy rpcbind v2 protocol. |
827 | */ | 846 | */ |
828 | if (error == -EPROTONOSUPPORT) | 847 | if (error == -EPROTONOSUPPORT) |
829 | error = rpcb_register(program, version, protocol, port); | 848 | error = rpcb_register(net, program, version, protocol, port); |
830 | 849 | ||
831 | return error; | 850 | return error; |
832 | } | 851 | } |
@@ -842,7 +861,8 @@ static int __svc_rpcb_register4(const u32 program, const u32 version, | |||
842 | * Returns zero on success; a negative errno value is returned | 861 | * Returns zero on success; a negative errno value is returned |
843 | * if any error occurs. | 862 | * if any error occurs. |
844 | */ | 863 | */ |
845 | static int __svc_rpcb_register6(const u32 program, const u32 version, | 864 | static int __svc_rpcb_register6(struct net *net, const u32 program, |
865 | const u32 version, | ||
846 | const unsigned short protocol, | 866 | const unsigned short protocol, |
847 | const unsigned short port) | 867 | const unsigned short port) |
848 | { | 868 | { |
@@ -865,7 +885,7 @@ static int __svc_rpcb_register6(const u32 program, const u32 version, | |||
865 | return -ENOPROTOOPT; | 885 | return -ENOPROTOOPT; |
866 | } | 886 | } |
867 | 887 | ||
868 | error = rpcb_v4_register(program, version, | 888 | error = rpcb_v4_register(net, program, version, |
869 | (const struct sockaddr *)&sin6, netid); | 889 | (const struct sockaddr *)&sin6, netid); |
870 | 890 | ||
871 | /* | 891 | /* |
@@ -885,7 +905,7 @@ static int __svc_rpcb_register6(const u32 program, const u32 version, | |||
885 | * Returns zero on success; a negative errno value is returned | 905 | * Returns zero on success; a negative errno value is returned |
886 | * if any error occurs. | 906 | * if any error occurs. |
887 | */ | 907 | */ |
888 | static int __svc_register(const char *progname, | 908 | static int __svc_register(struct net *net, const char *progname, |
889 | const u32 program, const u32 version, | 909 | const u32 program, const u32 version, |
890 | const int family, | 910 | const int family, |
891 | const unsigned short protocol, | 911 | const unsigned short protocol, |
@@ -895,12 +915,12 @@ static int __svc_register(const char *progname, | |||
895 | 915 | ||
896 | switch (family) { | 916 | switch (family) { |
897 | case PF_INET: | 917 | case PF_INET: |
898 | error = __svc_rpcb_register4(program, version, | 918 | error = __svc_rpcb_register4(net, program, version, |
899 | protocol, port); | 919 | protocol, port); |
900 | break; | 920 | break; |
901 | #if IS_ENABLED(CONFIG_IPV6) | 921 | #if IS_ENABLED(CONFIG_IPV6) |
902 | case PF_INET6: | 922 | case PF_INET6: |
903 | error = __svc_rpcb_register6(program, version, | 923 | error = __svc_rpcb_register6(net, program, version, |
904 | protocol, port); | 924 | protocol, port); |
905 | #endif | 925 | #endif |
906 | } | 926 | } |
@@ -914,14 +934,16 @@ static int __svc_register(const char *progname, | |||
914 | /** | 934 | /** |
915 | * svc_register - register an RPC service with the local portmapper | 935 | * svc_register - register an RPC service with the local portmapper |
916 | * @serv: svc_serv struct for the service to register | 936 | * @serv: svc_serv struct for the service to register |
937 | * @net: net namespace for the service to register | ||
917 | * @family: protocol family of service's listener socket | 938 | * @family: protocol family of service's listener socket |
918 | * @proto: transport protocol number to advertise | 939 | * @proto: transport protocol number to advertise |
919 | * @port: port to advertise | 940 | * @port: port to advertise |
920 | * | 941 | * |
921 | * Service is registered for any address in the passed-in protocol family | 942 | * Service is registered for any address in the passed-in protocol family |
922 | */ | 943 | */ |
923 | int svc_register(const struct svc_serv *serv, const int family, | 944 | int svc_register(const struct svc_serv *serv, struct net *net, |
924 | const unsigned short proto, const unsigned short port) | 945 | const int family, const unsigned short proto, |
946 | const unsigned short port) | ||
925 | { | 947 | { |
926 | struct svc_program *progp; | 948 | struct svc_program *progp; |
927 | unsigned int i; | 949 | unsigned int i; |
@@ -946,7 +968,7 @@ int svc_register(const struct svc_serv *serv, const int family, | |||
946 | if (progp->pg_vers[i]->vs_hidden) | 968 | if (progp->pg_vers[i]->vs_hidden) |
947 | continue; | 969 | continue; |
948 | 970 | ||
949 | error = __svc_register(progp->pg_name, progp->pg_prog, | 971 | error = __svc_register(net, progp->pg_name, progp->pg_prog, |
950 | i, family, proto, port); | 972 | i, family, proto, port); |
951 | if (error < 0) | 973 | if (error < 0) |
952 | break; | 974 | break; |
@@ -963,19 +985,19 @@ int svc_register(const struct svc_serv *serv, const int family, | |||
963 | * any "inet6" entries anyway. So a PMAP_UNSET should be sufficient | 985 | * any "inet6" entries anyway. So a PMAP_UNSET should be sufficient |
964 | * in this case to clear all existing entries for [program, version]. | 986 | * in this case to clear all existing entries for [program, version]. |
965 | */ | 987 | */ |
966 | static void __svc_unregister(const u32 program, const u32 version, | 988 | static void __svc_unregister(struct net *net, const u32 program, const u32 version, |
967 | const char *progname) | 989 | const char *progname) |
968 | { | 990 | { |
969 | int error; | 991 | int error; |
970 | 992 | ||
971 | error = rpcb_v4_register(program, version, NULL, ""); | 993 | error = rpcb_v4_register(net, program, version, NULL, ""); |
972 | 994 | ||
973 | /* | 995 | /* |
974 | * User space didn't support rpcbind v4, so retry this | 996 | * User space didn't support rpcbind v4, so retry this |
975 | * request with the legacy rpcbind v2 protocol. | 997 | * request with the legacy rpcbind v2 protocol. |
976 | */ | 998 | */ |
977 | if (error == -EPROTONOSUPPORT) | 999 | if (error == -EPROTONOSUPPORT) |
978 | error = rpcb_register(program, version, 0, 0); | 1000 | error = rpcb_register(net, program, version, 0, 0); |
979 | 1001 | ||
980 | dprintk("svc: %s(%sv%u), error %d\n", | 1002 | dprintk("svc: %s(%sv%u), error %d\n", |
981 | __func__, progname, version, error); | 1003 | __func__, progname, version, error); |
@@ -989,7 +1011,7 @@ static void __svc_unregister(const u32 program, const u32 version, | |||
989 | * The result of unregistration is reported via dprintk for those who want | 1011 | * The result of unregistration is reported via dprintk for those who want |
990 | * verification of the result, but is otherwise not important. | 1012 | * verification of the result, but is otherwise not important. |
991 | */ | 1013 | */ |
992 | static void svc_unregister(const struct svc_serv *serv) | 1014 | static void svc_unregister(const struct svc_serv *serv, struct net *net) |
993 | { | 1015 | { |
994 | struct svc_program *progp; | 1016 | struct svc_program *progp; |
995 | unsigned long flags; | 1017 | unsigned long flags; |
@@ -1006,7 +1028,7 @@ static void svc_unregister(const struct svc_serv *serv) | |||
1006 | 1028 | ||
1007 | dprintk("svc: attempting to unregister %sv%u\n", | 1029 | dprintk("svc: attempting to unregister %sv%u\n", |
1008 | progp->pg_name, i); | 1030 | progp->pg_name, i); |
1009 | __svc_unregister(progp->pg_prog, i, progp->pg_name); | 1031 | __svc_unregister(net, progp->pg_prog, i, progp->pg_name); |
1010 | } | 1032 | } |
1011 | } | 1033 | } |
1012 | 1034 | ||
diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c index 74cb0d8e9ca1..4bda09d7e1a4 100644 --- a/net/sunrpc/svc_xprt.c +++ b/net/sunrpc/svc_xprt.c | |||
@@ -922,48 +922,65 @@ void svc_close_xprt(struct svc_xprt *xprt) | |||
922 | } | 922 | } |
923 | EXPORT_SYMBOL_GPL(svc_close_xprt); | 923 | EXPORT_SYMBOL_GPL(svc_close_xprt); |
924 | 924 | ||
925 | static void svc_close_list(struct list_head *xprt_list) | 925 | static void svc_close_list(struct list_head *xprt_list, struct net *net) |
926 | { | 926 | { |
927 | struct svc_xprt *xprt; | 927 | struct svc_xprt *xprt; |
928 | 928 | ||
929 | list_for_each_entry(xprt, xprt_list, xpt_list) { | 929 | list_for_each_entry(xprt, xprt_list, xpt_list) { |
930 | if (xprt->xpt_net != net) | ||
931 | continue; | ||
930 | set_bit(XPT_CLOSE, &xprt->xpt_flags); | 932 | set_bit(XPT_CLOSE, &xprt->xpt_flags); |
931 | set_bit(XPT_BUSY, &xprt->xpt_flags); | 933 | set_bit(XPT_BUSY, &xprt->xpt_flags); |
932 | } | 934 | } |
933 | } | 935 | } |
934 | 936 | ||
935 | void svc_close_all(struct svc_serv *serv) | 937 | static void svc_clear_pools(struct svc_serv *serv, struct net *net) |
936 | { | 938 | { |
937 | struct svc_pool *pool; | 939 | struct svc_pool *pool; |
938 | struct svc_xprt *xprt; | 940 | struct svc_xprt *xprt; |
939 | struct svc_xprt *tmp; | 941 | struct svc_xprt *tmp; |
940 | int i; | 942 | int i; |
941 | 943 | ||
942 | svc_close_list(&serv->sv_tempsocks); | ||
943 | svc_close_list(&serv->sv_permsocks); | ||
944 | |||
945 | for (i = 0; i < serv->sv_nrpools; i++) { | 944 | for (i = 0; i < serv->sv_nrpools; i++) { |
946 | pool = &serv->sv_pools[i]; | 945 | pool = &serv->sv_pools[i]; |
947 | 946 | ||
948 | spin_lock_bh(&pool->sp_lock); | 947 | spin_lock_bh(&pool->sp_lock); |
949 | while (!list_empty(&pool->sp_sockets)) { | 948 | list_for_each_entry_safe(xprt, tmp, &pool->sp_sockets, xpt_ready) { |
950 | xprt = list_first_entry(&pool->sp_sockets, struct svc_xprt, xpt_ready); | 949 | if (xprt->xpt_net != net) |
950 | continue; | ||
951 | list_del_init(&xprt->xpt_ready); | 951 | list_del_init(&xprt->xpt_ready); |
952 | } | 952 | } |
953 | spin_unlock_bh(&pool->sp_lock); | 953 | spin_unlock_bh(&pool->sp_lock); |
954 | } | 954 | } |
955 | } | ||
956 | |||
957 | static void svc_clear_list(struct list_head *xprt_list, struct net *net) | ||
958 | { | ||
959 | struct svc_xprt *xprt; | ||
960 | struct svc_xprt *tmp; | ||
961 | |||
962 | list_for_each_entry_safe(xprt, tmp, xprt_list, xpt_list) { | ||
963 | if (xprt->xpt_net != net) | ||
964 | continue; | ||
965 | svc_delete_xprt(xprt); | ||
966 | } | ||
967 | list_for_each_entry(xprt, xprt_list, xpt_list) | ||
968 | BUG_ON(xprt->xpt_net == net); | ||
969 | } | ||
970 | |||
971 | void svc_close_net(struct svc_serv *serv, struct net *net) | ||
972 | { | ||
973 | svc_close_list(&serv->sv_tempsocks, net); | ||
974 | svc_close_list(&serv->sv_permsocks, net); | ||
975 | |||
976 | svc_clear_pools(serv, net); | ||
955 | /* | 977 | /* |
956 | * At this point the sp_sockets lists will stay empty, since | 978 | * At this point the sp_sockets lists will stay empty, since |
957 | * svc_enqueue will not add new entries without taking the | 979 | * svc_enqueue will not add new entries without taking the |
958 | * sp_lock and checking XPT_BUSY. | 980 | * sp_lock and checking XPT_BUSY. |
959 | */ | 981 | */ |
960 | list_for_each_entry_safe(xprt, tmp, &serv->sv_tempsocks, xpt_list) | 982 | svc_clear_list(&serv->sv_tempsocks, net); |
961 | svc_delete_xprt(xprt); | 983 | svc_clear_list(&serv->sv_permsocks, net); |
962 | list_for_each_entry_safe(xprt, tmp, &serv->sv_permsocks, xpt_list) | ||
963 | svc_delete_xprt(xprt); | ||
964 | |||
965 | BUG_ON(!list_empty(&serv->sv_permsocks)); | ||
966 | BUG_ON(!list_empty(&serv->sv_tempsocks)); | ||
967 | } | 984 | } |
968 | 985 | ||
969 | /* | 986 | /* |
@@ -1089,6 +1106,7 @@ static struct svc_deferred_req *svc_deferred_dequeue(struct svc_xprt *xprt) | |||
1089 | * svc_find_xprt - find an RPC transport instance | 1106 | * svc_find_xprt - find an RPC transport instance |
1090 | * @serv: pointer to svc_serv to search | 1107 | * @serv: pointer to svc_serv to search |
1091 | * @xcl_name: C string containing transport's class name | 1108 | * @xcl_name: C string containing transport's class name |
1109 | * @net: owner net pointer | ||
1092 | * @af: Address family of transport's local address | 1110 | * @af: Address family of transport's local address |
1093 | * @port: transport's IP port number | 1111 | * @port: transport's IP port number |
1094 | * | 1112 | * |
@@ -1101,7 +1119,8 @@ static struct svc_deferred_req *svc_deferred_dequeue(struct svc_xprt *xprt) | |||
1101 | * service's list that has a matching class name. | 1119 | * service's list that has a matching class name. |
1102 | */ | 1120 | */ |
1103 | struct svc_xprt *svc_find_xprt(struct svc_serv *serv, const char *xcl_name, | 1121 | struct svc_xprt *svc_find_xprt(struct svc_serv *serv, const char *xcl_name, |
1104 | const sa_family_t af, const unsigned short port) | 1122 | struct net *net, const sa_family_t af, |
1123 | const unsigned short port) | ||
1105 | { | 1124 | { |
1106 | struct svc_xprt *xprt; | 1125 | struct svc_xprt *xprt; |
1107 | struct svc_xprt *found = NULL; | 1126 | struct svc_xprt *found = NULL; |
@@ -1112,6 +1131,8 @@ struct svc_xprt *svc_find_xprt(struct svc_serv *serv, const char *xcl_name, | |||
1112 | 1131 | ||
1113 | spin_lock_bh(&serv->sv_lock); | 1132 | spin_lock_bh(&serv->sv_lock); |
1114 | list_for_each_entry(xprt, &serv->sv_permsocks, xpt_list) { | 1133 | list_for_each_entry(xprt, &serv->sv_permsocks, xpt_list) { |
1134 | if (xprt->xpt_net != net) | ||
1135 | continue; | ||
1115 | if (strcmp(xprt->xpt_class->xcl_name, xcl_name)) | 1136 | if (strcmp(xprt->xpt_class->xcl_name, xcl_name)) |
1116 | continue; | 1137 | continue; |
1117 | if (af != AF_UNSPEC && af != xprt->xpt_local.ss_family) | 1138 | if (af != AF_UNSPEC && af != xprt->xpt_local.ss_family) |
diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c index 01153ead1dba..521d8f7dc833 100644 --- a/net/sunrpc/svcauth_unix.c +++ b/net/sunrpc/svcauth_unix.c | |||
@@ -211,7 +211,7 @@ static int ip_map_parse(struct cache_detail *cd, | |||
211 | len = qword_get(&mesg, buf, mlen); | 211 | len = qword_get(&mesg, buf, mlen); |
212 | if (len <= 0) return -EINVAL; | 212 | if (len <= 0) return -EINVAL; |
213 | 213 | ||
214 | if (rpc_pton(buf, len, &address.sa, sizeof(address)) == 0) | 214 | if (rpc_pton(cd->net, buf, len, &address.sa, sizeof(address)) == 0) |
215 | return -EINVAL; | 215 | return -EINVAL; |
216 | switch (address.sa.sa_family) { | 216 | switch (address.sa.sa_family) { |
217 | case AF_INET: | 217 | case AF_INET: |
@@ -436,7 +436,6 @@ struct unix_gid { | |||
436 | uid_t uid; | 436 | uid_t uid; |
437 | struct group_info *gi; | 437 | struct group_info *gi; |
438 | }; | 438 | }; |
439 | static struct cache_head *gid_table[GID_HASHMAX]; | ||
440 | 439 | ||
441 | static void unix_gid_put(struct kref *kref) | 440 | static void unix_gid_put(struct kref *kref) |
442 | { | 441 | { |
@@ -494,8 +493,7 @@ static int unix_gid_upcall(struct cache_detail *cd, struct cache_head *h) | |||
494 | return sunrpc_cache_pipe_upcall(cd, h, unix_gid_request); | 493 | return sunrpc_cache_pipe_upcall(cd, h, unix_gid_request); |
495 | } | 494 | } |
496 | 495 | ||
497 | static struct unix_gid *unix_gid_lookup(uid_t uid); | 496 | static struct unix_gid *unix_gid_lookup(struct cache_detail *cd, uid_t uid); |
498 | extern struct cache_detail unix_gid_cache; | ||
499 | 497 | ||
500 | static int unix_gid_parse(struct cache_detail *cd, | 498 | static int unix_gid_parse(struct cache_detail *cd, |
501 | char *mesg, int mlen) | 499 | char *mesg, int mlen) |
@@ -509,7 +507,7 @@ static int unix_gid_parse(struct cache_detail *cd, | |||
509 | time_t expiry; | 507 | time_t expiry; |
510 | struct unix_gid ug, *ugp; | 508 | struct unix_gid ug, *ugp; |
511 | 509 | ||
512 | if (mlen <= 0 || mesg[mlen-1] != '\n') | 510 | if (mesg[mlen - 1] != '\n') |
513 | return -EINVAL; | 511 | return -EINVAL; |
514 | mesg[mlen-1] = 0; | 512 | mesg[mlen-1] = 0; |
515 | 513 | ||
@@ -539,19 +537,19 @@ static int unix_gid_parse(struct cache_detail *cd, | |||
539 | GROUP_AT(ug.gi, i) = gid; | 537 | GROUP_AT(ug.gi, i) = gid; |
540 | } | 538 | } |
541 | 539 | ||
542 | ugp = unix_gid_lookup(uid); | 540 | ugp = unix_gid_lookup(cd, uid); |
543 | if (ugp) { | 541 | if (ugp) { |
544 | struct cache_head *ch; | 542 | struct cache_head *ch; |
545 | ug.h.flags = 0; | 543 | ug.h.flags = 0; |
546 | ug.h.expiry_time = expiry; | 544 | ug.h.expiry_time = expiry; |
547 | ch = sunrpc_cache_update(&unix_gid_cache, | 545 | ch = sunrpc_cache_update(cd, |
548 | &ug.h, &ugp->h, | 546 | &ug.h, &ugp->h, |
549 | hash_long(uid, GID_HASHBITS)); | 547 | hash_long(uid, GID_HASHBITS)); |
550 | if (!ch) | 548 | if (!ch) |
551 | err = -ENOMEM; | 549 | err = -ENOMEM; |
552 | else { | 550 | else { |
553 | err = 0; | 551 | err = 0; |
554 | cache_put(ch, &unix_gid_cache); | 552 | cache_put(ch, cd); |
555 | } | 553 | } |
556 | } else | 554 | } else |
557 | err = -ENOMEM; | 555 | err = -ENOMEM; |
@@ -587,10 +585,9 @@ static int unix_gid_show(struct seq_file *m, | |||
587 | return 0; | 585 | return 0; |
588 | } | 586 | } |
589 | 587 | ||
590 | struct cache_detail unix_gid_cache = { | 588 | static struct cache_detail unix_gid_cache_template = { |
591 | .owner = THIS_MODULE, | 589 | .owner = THIS_MODULE, |
592 | .hash_size = GID_HASHMAX, | 590 | .hash_size = GID_HASHMAX, |
593 | .hash_table = gid_table, | ||
594 | .name = "auth.unix.gid", | 591 | .name = "auth.unix.gid", |
595 | .cache_put = unix_gid_put, | 592 | .cache_put = unix_gid_put, |
596 | .cache_upcall = unix_gid_upcall, | 593 | .cache_upcall = unix_gid_upcall, |
@@ -602,14 +599,42 @@ struct cache_detail unix_gid_cache = { | |||
602 | .alloc = unix_gid_alloc, | 599 | .alloc = unix_gid_alloc, |
603 | }; | 600 | }; |
604 | 601 | ||
605 | static struct unix_gid *unix_gid_lookup(uid_t uid) | 602 | int unix_gid_cache_create(struct net *net) |
603 | { | ||
604 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
605 | struct cache_detail *cd; | ||
606 | int err; | ||
607 | |||
608 | cd = cache_create_net(&unix_gid_cache_template, net); | ||
609 | if (IS_ERR(cd)) | ||
610 | return PTR_ERR(cd); | ||
611 | err = cache_register_net(cd, net); | ||
612 | if (err) { | ||
613 | cache_destroy_net(cd, net); | ||
614 | return err; | ||
615 | } | ||
616 | sn->unix_gid_cache = cd; | ||
617 | return 0; | ||
618 | } | ||
619 | |||
620 | void unix_gid_cache_destroy(struct net *net) | ||
621 | { | ||
622 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
623 | struct cache_detail *cd = sn->unix_gid_cache; | ||
624 | |||
625 | sn->unix_gid_cache = NULL; | ||
626 | cache_purge(cd); | ||
627 | cache_unregister_net(cd, net); | ||
628 | cache_destroy_net(cd, net); | ||
629 | } | ||
630 | |||
631 | static struct unix_gid *unix_gid_lookup(struct cache_detail *cd, uid_t uid) | ||
606 | { | 632 | { |
607 | struct unix_gid ug; | 633 | struct unix_gid ug; |
608 | struct cache_head *ch; | 634 | struct cache_head *ch; |
609 | 635 | ||
610 | ug.uid = uid; | 636 | ug.uid = uid; |
611 | ch = sunrpc_cache_lookup(&unix_gid_cache, &ug.h, | 637 | ch = sunrpc_cache_lookup(cd, &ug.h, hash_long(uid, GID_HASHBITS)); |
612 | hash_long(uid, GID_HASHBITS)); | ||
613 | if (ch) | 638 | if (ch) |
614 | return container_of(ch, struct unix_gid, h); | 639 | return container_of(ch, struct unix_gid, h); |
615 | else | 640 | else |
@@ -621,11 +646,13 @@ static struct group_info *unix_gid_find(uid_t uid, struct svc_rqst *rqstp) | |||
621 | struct unix_gid *ug; | 646 | struct unix_gid *ug; |
622 | struct group_info *gi; | 647 | struct group_info *gi; |
623 | int ret; | 648 | int ret; |
649 | struct sunrpc_net *sn = net_generic(rqstp->rq_xprt->xpt_net, | ||
650 | sunrpc_net_id); | ||
624 | 651 | ||
625 | ug = unix_gid_lookup(uid); | 652 | ug = unix_gid_lookup(sn->unix_gid_cache, uid); |
626 | if (!ug) | 653 | if (!ug) |
627 | return ERR_PTR(-EAGAIN); | 654 | return ERR_PTR(-EAGAIN); |
628 | ret = cache_check(&unix_gid_cache, &ug->h, &rqstp->rq_chandle); | 655 | ret = cache_check(sn->unix_gid_cache, &ug->h, &rqstp->rq_chandle); |
629 | switch (ret) { | 656 | switch (ret) { |
630 | case -ENOENT: | 657 | case -ENOENT: |
631 | return ERR_PTR(-ENOENT); | 658 | return ERR_PTR(-ENOENT); |
@@ -633,7 +660,7 @@ static struct group_info *unix_gid_find(uid_t uid, struct svc_rqst *rqstp) | |||
633 | return ERR_PTR(-ESHUTDOWN); | 660 | return ERR_PTR(-ESHUTDOWN); |
634 | case 0: | 661 | case 0: |
635 | gi = get_group_info(ug->gi); | 662 | gi = get_group_info(ug->gi); |
636 | cache_put(&ug->h, &unix_gid_cache); | 663 | cache_put(&ug->h, sn->unix_gid_cache); |
637 | return gi; | 664 | return gi; |
638 | default: | 665 | default: |
639 | return ERR_PTR(-EAGAIN); | 666 | return ERR_PTR(-EAGAIN); |
@@ -849,56 +876,45 @@ struct auth_ops svcauth_unix = { | |||
849 | .set_client = svcauth_unix_set_client, | 876 | .set_client = svcauth_unix_set_client, |
850 | }; | 877 | }; |
851 | 878 | ||
879 | static struct cache_detail ip_map_cache_template = { | ||
880 | .owner = THIS_MODULE, | ||
881 | .hash_size = IP_HASHMAX, | ||
882 | .name = "auth.unix.ip", | ||
883 | .cache_put = ip_map_put, | ||
884 | .cache_upcall = ip_map_upcall, | ||
885 | .cache_parse = ip_map_parse, | ||
886 | .cache_show = ip_map_show, | ||
887 | .match = ip_map_match, | ||
888 | .init = ip_map_init, | ||
889 | .update = update, | ||
890 | .alloc = ip_map_alloc, | ||
891 | }; | ||
892 | |||
852 | int ip_map_cache_create(struct net *net) | 893 | int ip_map_cache_create(struct net *net) |
853 | { | 894 | { |
854 | int err = -ENOMEM; | ||
855 | struct cache_detail *cd; | ||
856 | struct cache_head **tbl; | ||
857 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | 895 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); |
896 | struct cache_detail *cd; | ||
897 | int err; | ||
858 | 898 | ||
859 | cd = kzalloc(sizeof(struct cache_detail), GFP_KERNEL); | 899 | cd = cache_create_net(&ip_map_cache_template, net); |
860 | if (cd == NULL) | 900 | if (IS_ERR(cd)) |
861 | goto err_cd; | 901 | return PTR_ERR(cd); |
862 | |||
863 | tbl = kzalloc(IP_HASHMAX * sizeof(struct cache_head *), GFP_KERNEL); | ||
864 | if (tbl == NULL) | ||
865 | goto err_tbl; | ||
866 | |||
867 | cd->owner = THIS_MODULE, | ||
868 | cd->hash_size = IP_HASHMAX, | ||
869 | cd->hash_table = tbl, | ||
870 | cd->name = "auth.unix.ip", | ||
871 | cd->cache_put = ip_map_put, | ||
872 | cd->cache_upcall = ip_map_upcall, | ||
873 | cd->cache_parse = ip_map_parse, | ||
874 | cd->cache_show = ip_map_show, | ||
875 | cd->match = ip_map_match, | ||
876 | cd->init = ip_map_init, | ||
877 | cd->update = update, | ||
878 | cd->alloc = ip_map_alloc, | ||
879 | |||
880 | err = cache_register_net(cd, net); | 902 | err = cache_register_net(cd, net); |
881 | if (err) | 903 | if (err) { |
882 | goto err_reg; | 904 | cache_destroy_net(cd, net); |
883 | 905 | return err; | |
906 | } | ||
884 | sn->ip_map_cache = cd; | 907 | sn->ip_map_cache = cd; |
885 | return 0; | 908 | return 0; |
886 | |||
887 | err_reg: | ||
888 | kfree(tbl); | ||
889 | err_tbl: | ||
890 | kfree(cd); | ||
891 | err_cd: | ||
892 | return err; | ||
893 | } | 909 | } |
894 | 910 | ||
895 | void ip_map_cache_destroy(struct net *net) | 911 | void ip_map_cache_destroy(struct net *net) |
896 | { | 912 | { |
897 | struct sunrpc_net *sn; | 913 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); |
914 | struct cache_detail *cd = sn->ip_map_cache; | ||
898 | 915 | ||
899 | sn = net_generic(net, sunrpc_net_id); | 916 | sn->ip_map_cache = NULL; |
900 | cache_purge(sn->ip_map_cache); | 917 | cache_purge(cd); |
901 | cache_unregister_net(sn->ip_map_cache, net); | 918 | cache_unregister_net(cd, net); |
902 | kfree(sn->ip_map_cache->hash_table); | 919 | cache_destroy_net(cd, net); |
903 | kfree(sn->ip_map_cache); | ||
904 | } | 920 | } |
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index 464570906f80..824d32fb3121 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c | |||
@@ -396,7 +396,7 @@ static int svc_partial_recvfrom(struct svc_rqst *rqstp, | |||
396 | int buflen, unsigned int base) | 396 | int buflen, unsigned int base) |
397 | { | 397 | { |
398 | size_t save_iovlen; | 398 | size_t save_iovlen; |
399 | void __user *save_iovbase; | 399 | void *save_iovbase; |
400 | unsigned int i; | 400 | unsigned int i; |
401 | int ret; | 401 | int ret; |
402 | 402 | ||
@@ -1381,8 +1381,6 @@ void svc_sock_update_bufs(struct svc_serv *serv) | |||
1381 | spin_lock_bh(&serv->sv_lock); | 1381 | spin_lock_bh(&serv->sv_lock); |
1382 | list_for_each_entry(svsk, &serv->sv_permsocks, sk_xprt.xpt_list) | 1382 | list_for_each_entry(svsk, &serv->sv_permsocks, sk_xprt.xpt_list) |
1383 | set_bit(XPT_CHNGBUF, &svsk->sk_xprt.xpt_flags); | 1383 | set_bit(XPT_CHNGBUF, &svsk->sk_xprt.xpt_flags); |
1384 | list_for_each_entry(svsk, &serv->sv_tempsocks, sk_xprt.xpt_list) | ||
1385 | set_bit(XPT_CHNGBUF, &svsk->sk_xprt.xpt_flags); | ||
1386 | spin_unlock_bh(&serv->sv_lock); | 1384 | spin_unlock_bh(&serv->sv_lock); |
1387 | } | 1385 | } |
1388 | EXPORT_SYMBOL_GPL(svc_sock_update_bufs); | 1386 | EXPORT_SYMBOL_GPL(svc_sock_update_bufs); |
@@ -1409,7 +1407,8 @@ static struct svc_sock *svc_setup_socket(struct svc_serv *serv, | |||
1409 | 1407 | ||
1410 | /* Register socket with portmapper */ | 1408 | /* Register socket with portmapper */ |
1411 | if (*errp >= 0 && pmap_register) | 1409 | if (*errp >= 0 && pmap_register) |
1412 | *errp = svc_register(serv, inet->sk_family, inet->sk_protocol, | 1410 | *errp = svc_register(serv, sock_net(sock->sk), inet->sk_family, |
1411 | inet->sk_protocol, | ||
1413 | ntohs(inet_sk(inet)->inet_sport)); | 1412 | ntohs(inet_sk(inet)->inet_sport)); |
1414 | 1413 | ||
1415 | if (*errp < 0) { | 1414 | if (*errp < 0) { |
diff --git a/net/sunrpc/sysctl.c b/net/sunrpc/sysctl.c index e65dcc613339..af7d339add9d 100644 --- a/net/sunrpc/sysctl.c +++ b/net/sunrpc/sysctl.c | |||
@@ -20,6 +20,8 @@ | |||
20 | #include <linux/sunrpc/stats.h> | 20 | #include <linux/sunrpc/stats.h> |
21 | #include <linux/sunrpc/svc_xprt.h> | 21 | #include <linux/sunrpc/svc_xprt.h> |
22 | 22 | ||
23 | #include "netns.h" | ||
24 | |||
23 | /* | 25 | /* |
24 | * Declare the debug flags here | 26 | * Declare the debug flags here |
25 | */ | 27 | */ |
@@ -110,7 +112,7 @@ proc_dodebug(ctl_table *table, int write, | |||
110 | *(unsigned int *) table->data = value; | 112 | *(unsigned int *) table->data = value; |
111 | /* Display the RPC tasks on writing to rpc_debug */ | 113 | /* Display the RPC tasks on writing to rpc_debug */ |
112 | if (strcmp(table->procname, "rpc_debug") == 0) | 114 | if (strcmp(table->procname, "rpc_debug") == 0) |
113 | rpc_show_tasks(); | 115 | rpc_show_tasks(&init_net); |
114 | } else { | 116 | } else { |
115 | if (!access_ok(VERIFY_WRITE, buffer, left)) | 117 | if (!access_ok(VERIFY_WRITE, buffer, left)) |
116 | return -EFAULT; | 118 | return -EFAULT; |
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index c64c0ef519b5..0cbcd1ab49ab 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c | |||
@@ -66,6 +66,7 @@ static void xprt_init(struct rpc_xprt *xprt, struct net *net); | |||
66 | static void xprt_request_init(struct rpc_task *, struct rpc_xprt *); | 66 | static void xprt_request_init(struct rpc_task *, struct rpc_xprt *); |
67 | static void xprt_connect_status(struct rpc_task *task); | 67 | static void xprt_connect_status(struct rpc_task *task); |
68 | static int __xprt_get_cong(struct rpc_xprt *, struct rpc_task *); | 68 | static int __xprt_get_cong(struct rpc_xprt *, struct rpc_task *); |
69 | static void xprt_destroy(struct rpc_xprt *xprt); | ||
69 | 70 | ||
70 | static DEFINE_SPINLOCK(xprt_list_lock); | 71 | static DEFINE_SPINLOCK(xprt_list_lock); |
71 | static LIST_HEAD(xprt_list); | 72 | static LIST_HEAD(xprt_list); |
@@ -292,54 +293,57 @@ static inline int xprt_lock_write(struct rpc_xprt *xprt, struct rpc_task *task) | |||
292 | return retval; | 293 | return retval; |
293 | } | 294 | } |
294 | 295 | ||
295 | static void __xprt_lock_write_next(struct rpc_xprt *xprt) | 296 | static bool __xprt_lock_write_func(struct rpc_task *task, void *data) |
296 | { | 297 | { |
297 | struct rpc_task *task; | 298 | struct rpc_xprt *xprt = data; |
298 | struct rpc_rqst *req; | 299 | struct rpc_rqst *req; |
299 | 300 | ||
300 | if (test_and_set_bit(XPRT_LOCKED, &xprt->state)) | ||
301 | return; | ||
302 | |||
303 | task = rpc_wake_up_next(&xprt->sending); | ||
304 | if (task == NULL) | ||
305 | goto out_unlock; | ||
306 | |||
307 | req = task->tk_rqstp; | 301 | req = task->tk_rqstp; |
308 | xprt->snd_task = task; | 302 | xprt->snd_task = task; |
309 | if (req) { | 303 | if (req) { |
310 | req->rq_bytes_sent = 0; | 304 | req->rq_bytes_sent = 0; |
311 | req->rq_ntrans++; | 305 | req->rq_ntrans++; |
312 | } | 306 | } |
313 | return; | 307 | return true; |
308 | } | ||
314 | 309 | ||
315 | out_unlock: | 310 | static void __xprt_lock_write_next(struct rpc_xprt *xprt) |
311 | { | ||
312 | if (test_and_set_bit(XPRT_LOCKED, &xprt->state)) | ||
313 | return; | ||
314 | |||
315 | if (rpc_wake_up_first(&xprt->sending, __xprt_lock_write_func, xprt)) | ||
316 | return; | ||
316 | xprt_clear_locked(xprt); | 317 | xprt_clear_locked(xprt); |
317 | } | 318 | } |
318 | 319 | ||
319 | static void __xprt_lock_write_next_cong(struct rpc_xprt *xprt) | 320 | static bool __xprt_lock_write_cong_func(struct rpc_task *task, void *data) |
320 | { | 321 | { |
321 | struct rpc_task *task; | 322 | struct rpc_xprt *xprt = data; |
322 | struct rpc_rqst *req; | 323 | struct rpc_rqst *req; |
323 | 324 | ||
324 | if (test_and_set_bit(XPRT_LOCKED, &xprt->state)) | ||
325 | return; | ||
326 | if (RPCXPRT_CONGESTED(xprt)) | ||
327 | goto out_unlock; | ||
328 | task = rpc_wake_up_next(&xprt->sending); | ||
329 | if (task == NULL) | ||
330 | goto out_unlock; | ||
331 | |||
332 | req = task->tk_rqstp; | 325 | req = task->tk_rqstp; |
333 | if (req == NULL) { | 326 | if (req == NULL) { |
334 | xprt->snd_task = task; | 327 | xprt->snd_task = task; |
335 | return; | 328 | return true; |
336 | } | 329 | } |
337 | if (__xprt_get_cong(xprt, task)) { | 330 | if (__xprt_get_cong(xprt, task)) { |
338 | xprt->snd_task = task; | 331 | xprt->snd_task = task; |
339 | req->rq_bytes_sent = 0; | 332 | req->rq_bytes_sent = 0; |
340 | req->rq_ntrans++; | 333 | req->rq_ntrans++; |
341 | return; | 334 | return true; |
342 | } | 335 | } |
336 | return false; | ||
337 | } | ||
338 | |||
339 | static void __xprt_lock_write_next_cong(struct rpc_xprt *xprt) | ||
340 | { | ||
341 | if (test_and_set_bit(XPRT_LOCKED, &xprt->state)) | ||
342 | return; | ||
343 | if (RPCXPRT_CONGESTED(xprt)) | ||
344 | goto out_unlock; | ||
345 | if (rpc_wake_up_first(&xprt->sending, __xprt_lock_write_cong_func, xprt)) | ||
346 | return; | ||
343 | out_unlock: | 347 | out_unlock: |
344 | xprt_clear_locked(xprt); | 348 | xprt_clear_locked(xprt); |
345 | } | 349 | } |
@@ -712,9 +716,7 @@ void xprt_connect(struct rpc_task *task) | |||
712 | if (xprt_connected(xprt)) | 716 | if (xprt_connected(xprt)) |
713 | xprt_release_write(xprt, task); | 717 | xprt_release_write(xprt, task); |
714 | else { | 718 | else { |
715 | if (task->tk_rqstp) | 719 | task->tk_rqstp->rq_bytes_sent = 0; |
716 | task->tk_rqstp->rq_bytes_sent = 0; | ||
717 | |||
718 | task->tk_timeout = task->tk_rqstp->rq_timeout; | 720 | task->tk_timeout = task->tk_rqstp->rq_timeout; |
719 | rpc_sleep_on(&xprt->pending, task, xprt_connect_status); | 721 | rpc_sleep_on(&xprt->pending, task, xprt_connect_status); |
720 | 722 | ||
@@ -750,7 +752,7 @@ static void xprt_connect_status(struct rpc_task *task) | |||
750 | default: | 752 | default: |
751 | dprintk("RPC: %5u xprt_connect_status: error %d connecting to " | 753 | dprintk("RPC: %5u xprt_connect_status: error %d connecting to " |
752 | "server %s\n", task->tk_pid, -task->tk_status, | 754 | "server %s\n", task->tk_pid, -task->tk_status, |
753 | task->tk_client->cl_server); | 755 | xprt->servername); |
754 | xprt_release_write(xprt, task); | 756 | xprt_release_write(xprt, task); |
755 | task->tk_status = -EIO; | 757 | task->tk_status = -EIO; |
756 | } | 758 | } |
@@ -884,7 +886,7 @@ void xprt_transmit(struct rpc_task *task) | |||
884 | { | 886 | { |
885 | struct rpc_rqst *req = task->tk_rqstp; | 887 | struct rpc_rqst *req = task->tk_rqstp; |
886 | struct rpc_xprt *xprt = req->rq_xprt; | 888 | struct rpc_xprt *xprt = req->rq_xprt; |
887 | int status; | 889 | int status, numreqs; |
888 | 890 | ||
889 | dprintk("RPC: %5u xprt_transmit(%u)\n", task->tk_pid, req->rq_slen); | 891 | dprintk("RPC: %5u xprt_transmit(%u)\n", task->tk_pid, req->rq_slen); |
890 | 892 | ||
@@ -921,9 +923,14 @@ void xprt_transmit(struct rpc_task *task) | |||
921 | 923 | ||
922 | xprt->ops->set_retrans_timeout(task); | 924 | xprt->ops->set_retrans_timeout(task); |
923 | 925 | ||
926 | numreqs = atomic_read(&xprt->num_reqs); | ||
927 | if (numreqs > xprt->stat.max_slots) | ||
928 | xprt->stat.max_slots = numreqs; | ||
924 | xprt->stat.sends++; | 929 | xprt->stat.sends++; |
925 | xprt->stat.req_u += xprt->stat.sends - xprt->stat.recvs; | 930 | xprt->stat.req_u += xprt->stat.sends - xprt->stat.recvs; |
926 | xprt->stat.bklog_u += xprt->backlog.qlen; | 931 | xprt->stat.bklog_u += xprt->backlog.qlen; |
932 | xprt->stat.sending_u += xprt->sending.qlen; | ||
933 | xprt->stat.pending_u += xprt->pending.qlen; | ||
927 | 934 | ||
928 | /* Don't race with disconnect */ | 935 | /* Don't race with disconnect */ |
929 | if (!xprt_connected(xprt)) | 936 | if (!xprt_connected(xprt)) |
@@ -1131,7 +1138,10 @@ void xprt_release(struct rpc_task *task) | |||
1131 | return; | 1138 | return; |
1132 | 1139 | ||
1133 | xprt = req->rq_xprt; | 1140 | xprt = req->rq_xprt; |
1134 | rpc_count_iostats(task); | 1141 | if (task->tk_ops->rpc_count_stats != NULL) |
1142 | task->tk_ops->rpc_count_stats(task, task->tk_calldata); | ||
1143 | else if (task->tk_client) | ||
1144 | rpc_count_iostats(task, task->tk_client->cl_metrics); | ||
1135 | spin_lock_bh(&xprt->transport_lock); | 1145 | spin_lock_bh(&xprt->transport_lock); |
1136 | xprt->ops->release_xprt(xprt, task); | 1146 | xprt->ops->release_xprt(xprt, task); |
1137 | if (xprt->ops->release_request) | 1147 | if (xprt->ops->release_request) |
@@ -1220,6 +1230,17 @@ found: | |||
1220 | (unsigned long)xprt); | 1230 | (unsigned long)xprt); |
1221 | else | 1231 | else |
1222 | init_timer(&xprt->timer); | 1232 | init_timer(&xprt->timer); |
1233 | |||
1234 | if (strlen(args->servername) > RPC_MAXNETNAMELEN) { | ||
1235 | xprt_destroy(xprt); | ||
1236 | return ERR_PTR(-EINVAL); | ||
1237 | } | ||
1238 | xprt->servername = kstrdup(args->servername, GFP_KERNEL); | ||
1239 | if (xprt->servername == NULL) { | ||
1240 | xprt_destroy(xprt); | ||
1241 | return ERR_PTR(-ENOMEM); | ||
1242 | } | ||
1243 | |||
1223 | dprintk("RPC: created transport %p with %u slots\n", xprt, | 1244 | dprintk("RPC: created transport %p with %u slots\n", xprt, |
1224 | xprt->max_reqs); | 1245 | xprt->max_reqs); |
1225 | out: | 1246 | out: |
@@ -1242,6 +1263,7 @@ static void xprt_destroy(struct rpc_xprt *xprt) | |||
1242 | rpc_destroy_wait_queue(&xprt->sending); | 1263 | rpc_destroy_wait_queue(&xprt->sending); |
1243 | rpc_destroy_wait_queue(&xprt->backlog); | 1264 | rpc_destroy_wait_queue(&xprt->backlog); |
1244 | cancel_work_sync(&xprt->task_cleanup); | 1265 | cancel_work_sync(&xprt->task_cleanup); |
1266 | kfree(xprt->servername); | ||
1245 | /* | 1267 | /* |
1246 | * Tear down transport state and free the rpc_xprt | 1268 | * Tear down transport state and free the rpc_xprt |
1247 | */ | 1269 | */ |
diff --git a/net/sunrpc/xprtrdma/rpc_rdma.c b/net/sunrpc/xprtrdma/rpc_rdma.c index 1776e5731dcf..558fbab574f0 100644 --- a/net/sunrpc/xprtrdma/rpc_rdma.c +++ b/net/sunrpc/xprtrdma/rpc_rdma.c | |||
@@ -771,13 +771,18 @@ repost: | |||
771 | 771 | ||
772 | /* get request object */ | 772 | /* get request object */ |
773 | req = rpcr_to_rdmar(rqst); | 773 | req = rpcr_to_rdmar(rqst); |
774 | if (req->rl_reply) { | ||
775 | spin_unlock(&xprt->transport_lock); | ||
776 | dprintk("RPC: %s: duplicate reply 0x%p to RPC " | ||
777 | "request 0x%p: xid 0x%08x\n", __func__, rep, req, | ||
778 | headerp->rm_xid); | ||
779 | goto repost; | ||
780 | } | ||
774 | 781 | ||
775 | dprintk("RPC: %s: reply 0x%p completes request 0x%p\n" | 782 | dprintk("RPC: %s: reply 0x%p completes request 0x%p\n" |
776 | " RPC request 0x%p xid 0x%08x\n", | 783 | " RPC request 0x%p xid 0x%08x\n", |
777 | __func__, rep, req, rqst, headerp->rm_xid); | 784 | __func__, rep, req, rqst, headerp->rm_xid); |
778 | 785 | ||
779 | BUG_ON(!req || req->rl_reply); | ||
780 | |||
781 | /* from here on, the reply is no longer an orphan */ | 786 | /* from here on, the reply is no longer an orphan */ |
782 | req->rl_reply = rep; | 787 | req->rl_reply = rep; |
783 | 788 | ||
diff --git a/net/sunrpc/xprtrdma/svc_rdma.c b/net/sunrpc/xprtrdma/svc_rdma.c index 09af4fab1a45..8343737e85f4 100644 --- a/net/sunrpc/xprtrdma/svc_rdma.c +++ b/net/sunrpc/xprtrdma/svc_rdma.c | |||
@@ -47,6 +47,7 @@ | |||
47 | #include <linux/sunrpc/clnt.h> | 47 | #include <linux/sunrpc/clnt.h> |
48 | #include <linux/sunrpc/sched.h> | 48 | #include <linux/sunrpc/sched.h> |
49 | #include <linux/sunrpc/svc_rdma.h> | 49 | #include <linux/sunrpc/svc_rdma.h> |
50 | #include "xprt_rdma.h" | ||
50 | 51 | ||
51 | #define RPCDBG_FACILITY RPCDBG_SVCXPRT | 52 | #define RPCDBG_FACILITY RPCDBG_SVCXPRT |
52 | 53 | ||
diff --git a/net/sunrpc/xprtrdma/svc_rdma_marshal.c b/net/sunrpc/xprtrdma/svc_rdma_marshal.c index 9530ef2d40dc..8d2edddf48cf 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_marshal.c +++ b/net/sunrpc/xprtrdma/svc_rdma_marshal.c | |||
@@ -60,21 +60,11 @@ static u32 *decode_read_list(u32 *va, u32 *vaend) | |||
60 | struct rpcrdma_read_chunk *ch = (struct rpcrdma_read_chunk *)va; | 60 | struct rpcrdma_read_chunk *ch = (struct rpcrdma_read_chunk *)va; |
61 | 61 | ||
62 | while (ch->rc_discrim != xdr_zero) { | 62 | while (ch->rc_discrim != xdr_zero) { |
63 | u64 ch_offset; | ||
64 | |||
65 | if (((unsigned long)ch + sizeof(struct rpcrdma_read_chunk)) > | 63 | if (((unsigned long)ch + sizeof(struct rpcrdma_read_chunk)) > |
66 | (unsigned long)vaend) { | 64 | (unsigned long)vaend) { |
67 | dprintk("svcrdma: vaend=%p, ch=%p\n", vaend, ch); | 65 | dprintk("svcrdma: vaend=%p, ch=%p\n", vaend, ch); |
68 | return NULL; | 66 | return NULL; |
69 | } | 67 | } |
70 | |||
71 | ch->rc_discrim = ntohl(ch->rc_discrim); | ||
72 | ch->rc_position = ntohl(ch->rc_position); | ||
73 | ch->rc_target.rs_handle = ntohl(ch->rc_target.rs_handle); | ||
74 | ch->rc_target.rs_length = ntohl(ch->rc_target.rs_length); | ||
75 | va = (u32 *)&ch->rc_target.rs_offset; | ||
76 | xdr_decode_hyper(va, &ch_offset); | ||
77 | put_unaligned(ch_offset, (u64 *)va); | ||
78 | ch++; | 68 | ch++; |
79 | } | 69 | } |
80 | return (u32 *)&ch->rc_position; | 70 | return (u32 *)&ch->rc_position; |
@@ -91,7 +81,7 @@ void svc_rdma_rcl_chunk_counts(struct rpcrdma_read_chunk *ch, | |||
91 | *byte_count = 0; | 81 | *byte_count = 0; |
92 | *ch_count = 0; | 82 | *ch_count = 0; |
93 | for (; ch->rc_discrim != 0; ch++) { | 83 | for (; ch->rc_discrim != 0; ch++) { |
94 | *byte_count = *byte_count + ch->rc_target.rs_length; | 84 | *byte_count = *byte_count + ntohl(ch->rc_target.rs_length); |
95 | *ch_count = *ch_count + 1; | 85 | *ch_count = *ch_count + 1; |
96 | } | 86 | } |
97 | } | 87 | } |
@@ -108,7 +98,8 @@ void svc_rdma_rcl_chunk_counts(struct rpcrdma_read_chunk *ch, | |||
108 | */ | 98 | */ |
109 | static u32 *decode_write_list(u32 *va, u32 *vaend) | 99 | static u32 *decode_write_list(u32 *va, u32 *vaend) |
110 | { | 100 | { |
111 | int ch_no; | 101 | int nchunks; |
102 | |||
112 | struct rpcrdma_write_array *ary = | 103 | struct rpcrdma_write_array *ary = |
113 | (struct rpcrdma_write_array *)va; | 104 | (struct rpcrdma_write_array *)va; |
114 | 105 | ||
@@ -121,37 +112,24 @@ static u32 *decode_write_list(u32 *va, u32 *vaend) | |||
121 | dprintk("svcrdma: ary=%p, vaend=%p\n", ary, vaend); | 112 | dprintk("svcrdma: ary=%p, vaend=%p\n", ary, vaend); |
122 | return NULL; | 113 | return NULL; |
123 | } | 114 | } |
124 | ary->wc_discrim = ntohl(ary->wc_discrim); | 115 | nchunks = ntohl(ary->wc_nchunks); |
125 | ary->wc_nchunks = ntohl(ary->wc_nchunks); | ||
126 | if (((unsigned long)&ary->wc_array[0] + | 116 | if (((unsigned long)&ary->wc_array[0] + |
127 | (sizeof(struct rpcrdma_write_chunk) * ary->wc_nchunks)) > | 117 | (sizeof(struct rpcrdma_write_chunk) * nchunks)) > |
128 | (unsigned long)vaend) { | 118 | (unsigned long)vaend) { |
129 | dprintk("svcrdma: ary=%p, wc_nchunks=%d, vaend=%p\n", | 119 | dprintk("svcrdma: ary=%p, wc_nchunks=%d, vaend=%p\n", |
130 | ary, ary->wc_nchunks, vaend); | 120 | ary, nchunks, vaend); |
131 | return NULL; | 121 | return NULL; |
132 | } | 122 | } |
133 | for (ch_no = 0; ch_no < ary->wc_nchunks; ch_no++) { | ||
134 | u64 ch_offset; | ||
135 | |||
136 | ary->wc_array[ch_no].wc_target.rs_handle = | ||
137 | ntohl(ary->wc_array[ch_no].wc_target.rs_handle); | ||
138 | ary->wc_array[ch_no].wc_target.rs_length = | ||
139 | ntohl(ary->wc_array[ch_no].wc_target.rs_length); | ||
140 | va = (u32 *)&ary->wc_array[ch_no].wc_target.rs_offset; | ||
141 | xdr_decode_hyper(va, &ch_offset); | ||
142 | put_unaligned(ch_offset, (u64 *)va); | ||
143 | } | ||
144 | |||
145 | /* | 123 | /* |
146 | * rs_length is the 2nd 4B field in wc_target and taking its | 124 | * rs_length is the 2nd 4B field in wc_target and taking its |
147 | * address skips the list terminator | 125 | * address skips the list terminator |
148 | */ | 126 | */ |
149 | return (u32 *)&ary->wc_array[ch_no].wc_target.rs_length; | 127 | return (u32 *)&ary->wc_array[nchunks].wc_target.rs_length; |
150 | } | 128 | } |
151 | 129 | ||
152 | static u32 *decode_reply_array(u32 *va, u32 *vaend) | 130 | static u32 *decode_reply_array(u32 *va, u32 *vaend) |
153 | { | 131 | { |
154 | int ch_no; | 132 | int nchunks; |
155 | struct rpcrdma_write_array *ary = | 133 | struct rpcrdma_write_array *ary = |
156 | (struct rpcrdma_write_array *)va; | 134 | (struct rpcrdma_write_array *)va; |
157 | 135 | ||
@@ -164,28 +142,15 @@ static u32 *decode_reply_array(u32 *va, u32 *vaend) | |||
164 | dprintk("svcrdma: ary=%p, vaend=%p\n", ary, vaend); | 142 | dprintk("svcrdma: ary=%p, vaend=%p\n", ary, vaend); |
165 | return NULL; | 143 | return NULL; |
166 | } | 144 | } |
167 | ary->wc_discrim = ntohl(ary->wc_discrim); | 145 | nchunks = ntohl(ary->wc_nchunks); |
168 | ary->wc_nchunks = ntohl(ary->wc_nchunks); | ||
169 | if (((unsigned long)&ary->wc_array[0] + | 146 | if (((unsigned long)&ary->wc_array[0] + |
170 | (sizeof(struct rpcrdma_write_chunk) * ary->wc_nchunks)) > | 147 | (sizeof(struct rpcrdma_write_chunk) * nchunks)) > |
171 | (unsigned long)vaend) { | 148 | (unsigned long)vaend) { |
172 | dprintk("svcrdma: ary=%p, wc_nchunks=%d, vaend=%p\n", | 149 | dprintk("svcrdma: ary=%p, wc_nchunks=%d, vaend=%p\n", |
173 | ary, ary->wc_nchunks, vaend); | 150 | ary, nchunks, vaend); |
174 | return NULL; | 151 | return NULL; |
175 | } | 152 | } |
176 | for (ch_no = 0; ch_no < ary->wc_nchunks; ch_no++) { | 153 | return (u32 *)&ary->wc_array[nchunks]; |
177 | u64 ch_offset; | ||
178 | |||
179 | ary->wc_array[ch_no].wc_target.rs_handle = | ||
180 | ntohl(ary->wc_array[ch_no].wc_target.rs_handle); | ||
181 | ary->wc_array[ch_no].wc_target.rs_length = | ||
182 | ntohl(ary->wc_array[ch_no].wc_target.rs_length); | ||
183 | va = (u32 *)&ary->wc_array[ch_no].wc_target.rs_offset; | ||
184 | xdr_decode_hyper(va, &ch_offset); | ||
185 | put_unaligned(ch_offset, (u64 *)va); | ||
186 | } | ||
187 | |||
188 | return (u32 *)&ary->wc_array[ch_no]; | ||
189 | } | 154 | } |
190 | 155 | ||
191 | int svc_rdma_xdr_decode_req(struct rpcrdma_msg **rdma_req, | 156 | int svc_rdma_xdr_decode_req(struct rpcrdma_msg **rdma_req, |
@@ -386,13 +351,14 @@ void svc_rdma_xdr_encode_reply_array(struct rpcrdma_write_array *ary, | |||
386 | 351 | ||
387 | void svc_rdma_xdr_encode_array_chunk(struct rpcrdma_write_array *ary, | 352 | void svc_rdma_xdr_encode_array_chunk(struct rpcrdma_write_array *ary, |
388 | int chunk_no, | 353 | int chunk_no, |
389 | u32 rs_handle, u64 rs_offset, | 354 | __be32 rs_handle, |
355 | __be64 rs_offset, | ||
390 | u32 write_len) | 356 | u32 write_len) |
391 | { | 357 | { |
392 | struct rpcrdma_segment *seg = &ary->wc_array[chunk_no].wc_target; | 358 | struct rpcrdma_segment *seg = &ary->wc_array[chunk_no].wc_target; |
393 | seg->rs_handle = htonl(rs_handle); | 359 | seg->rs_handle = rs_handle; |
360 | seg->rs_offset = rs_offset; | ||
394 | seg->rs_length = htonl(write_len); | 361 | seg->rs_length = htonl(write_len); |
395 | xdr_encode_hyper((u32 *) &seg->rs_offset, rs_offset); | ||
396 | } | 362 | } |
397 | 363 | ||
398 | void svc_rdma_xdr_encode_reply_header(struct svcxprt_rdma *xprt, | 364 | void svc_rdma_xdr_encode_reply_header(struct svcxprt_rdma *xprt, |
diff --git a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c index df67211c4baf..41cb63b623df 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c +++ b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c | |||
@@ -147,7 +147,7 @@ static int map_read_chunks(struct svcxprt_rdma *xprt, | |||
147 | page_off = 0; | 147 | page_off = 0; |
148 | ch = (struct rpcrdma_read_chunk *)&rmsgp->rm_body.rm_chunks[0]; | 148 | ch = (struct rpcrdma_read_chunk *)&rmsgp->rm_body.rm_chunks[0]; |
149 | ch_no = 0; | 149 | ch_no = 0; |
150 | ch_bytes = ch->rc_target.rs_length; | 150 | ch_bytes = ntohl(ch->rc_target.rs_length); |
151 | head->arg.head[0] = rqstp->rq_arg.head[0]; | 151 | head->arg.head[0] = rqstp->rq_arg.head[0]; |
152 | head->arg.tail[0] = rqstp->rq_arg.tail[0]; | 152 | head->arg.tail[0] = rqstp->rq_arg.tail[0]; |
153 | head->arg.pages = &head->pages[head->count]; | 153 | head->arg.pages = &head->pages[head->count]; |
@@ -183,7 +183,7 @@ static int map_read_chunks(struct svcxprt_rdma *xprt, | |||
183 | ch_no++; | 183 | ch_no++; |
184 | ch++; | 184 | ch++; |
185 | chl_map->ch[ch_no].start = sge_no; | 185 | chl_map->ch[ch_no].start = sge_no; |
186 | ch_bytes = ch->rc_target.rs_length; | 186 | ch_bytes = ntohl(ch->rc_target.rs_length); |
187 | /* If bytes remaining account for next chunk */ | 187 | /* If bytes remaining account for next chunk */ |
188 | if (byte_count) { | 188 | if (byte_count) { |
189 | head->arg.page_len += ch_bytes; | 189 | head->arg.page_len += ch_bytes; |
@@ -281,11 +281,12 @@ static int fast_reg_read_chunks(struct svcxprt_rdma *xprt, | |||
281 | offset = 0; | 281 | offset = 0; |
282 | ch = (struct rpcrdma_read_chunk *)&rmsgp->rm_body.rm_chunks[0]; | 282 | ch = (struct rpcrdma_read_chunk *)&rmsgp->rm_body.rm_chunks[0]; |
283 | for (ch_no = 0; ch_no < ch_count; ch_no++) { | 283 | for (ch_no = 0; ch_no < ch_count; ch_no++) { |
284 | int len = ntohl(ch->rc_target.rs_length); | ||
284 | rpl_map->sge[ch_no].iov_base = frmr->kva + offset; | 285 | rpl_map->sge[ch_no].iov_base = frmr->kva + offset; |
285 | rpl_map->sge[ch_no].iov_len = ch->rc_target.rs_length; | 286 | rpl_map->sge[ch_no].iov_len = len; |
286 | chl_map->ch[ch_no].count = 1; | 287 | chl_map->ch[ch_no].count = 1; |
287 | chl_map->ch[ch_no].start = ch_no; | 288 | chl_map->ch[ch_no].start = ch_no; |
288 | offset += ch->rc_target.rs_length; | 289 | offset += len; |
289 | ch++; | 290 | ch++; |
290 | } | 291 | } |
291 | 292 | ||
@@ -316,7 +317,7 @@ static int rdma_set_ctxt_sge(struct svcxprt_rdma *xprt, | |||
316 | for (i = 0; i < count; i++) { | 317 | for (i = 0; i < count; i++) { |
317 | ctxt->sge[i].length = 0; /* in case map fails */ | 318 | ctxt->sge[i].length = 0; /* in case map fails */ |
318 | if (!frmr) { | 319 | if (!frmr) { |
319 | BUG_ON(0 == virt_to_page(vec[i].iov_base)); | 320 | BUG_ON(!virt_to_page(vec[i].iov_base)); |
320 | off = (unsigned long)vec[i].iov_base & ~PAGE_MASK; | 321 | off = (unsigned long)vec[i].iov_base & ~PAGE_MASK; |
321 | ctxt->sge[i].addr = | 322 | ctxt->sge[i].addr = |
322 | ib_dma_map_page(xprt->sc_cm_id->device, | 323 | ib_dma_map_page(xprt->sc_cm_id->device, |
@@ -426,6 +427,7 @@ static int rdma_read_xdr(struct svcxprt_rdma *xprt, | |||
426 | 427 | ||
427 | for (ch = (struct rpcrdma_read_chunk *)&rmsgp->rm_body.rm_chunks[0]; | 428 | for (ch = (struct rpcrdma_read_chunk *)&rmsgp->rm_body.rm_chunks[0]; |
428 | ch->rc_discrim != 0; ch++, ch_no++) { | 429 | ch->rc_discrim != 0; ch++, ch_no++) { |
430 | u64 rs_offset; | ||
429 | next_sge: | 431 | next_sge: |
430 | ctxt = svc_rdma_get_context(xprt); | 432 | ctxt = svc_rdma_get_context(xprt); |
431 | ctxt->direction = DMA_FROM_DEVICE; | 433 | ctxt->direction = DMA_FROM_DEVICE; |
@@ -440,10 +442,10 @@ next_sge: | |||
440 | read_wr.opcode = IB_WR_RDMA_READ; | 442 | read_wr.opcode = IB_WR_RDMA_READ; |
441 | ctxt->wr_op = read_wr.opcode; | 443 | ctxt->wr_op = read_wr.opcode; |
442 | read_wr.send_flags = IB_SEND_SIGNALED; | 444 | read_wr.send_flags = IB_SEND_SIGNALED; |
443 | read_wr.wr.rdma.rkey = ch->rc_target.rs_handle; | 445 | read_wr.wr.rdma.rkey = ntohl(ch->rc_target.rs_handle); |
444 | read_wr.wr.rdma.remote_addr = | 446 | xdr_decode_hyper((__be32 *)&ch->rc_target.rs_offset, |
445 | get_unaligned(&(ch->rc_target.rs_offset)) + | 447 | &rs_offset); |
446 | sgl_offset; | 448 | read_wr.wr.rdma.remote_addr = rs_offset + sgl_offset; |
447 | read_wr.sg_list = ctxt->sge; | 449 | read_wr.sg_list = ctxt->sge; |
448 | read_wr.num_sge = | 450 | read_wr.num_sge = |
449 | rdma_read_max_sge(xprt, chl_map->ch[ch_no].count); | 451 | rdma_read_max_sge(xprt, chl_map->ch[ch_no].count); |
diff --git a/net/sunrpc/xprtrdma/svc_rdma_sendto.c b/net/sunrpc/xprtrdma/svc_rdma_sendto.c index 249a835b703f..42eb7ba0b903 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_sendto.c +++ b/net/sunrpc/xprtrdma/svc_rdma_sendto.c | |||
@@ -409,21 +409,21 @@ static int send_write_chunks(struct svcxprt_rdma *xprt, | |||
409 | u64 rs_offset; | 409 | u64 rs_offset; |
410 | 410 | ||
411 | arg_ch = &arg_ary->wc_array[chunk_no].wc_target; | 411 | arg_ch = &arg_ary->wc_array[chunk_no].wc_target; |
412 | write_len = min(xfer_len, arg_ch->rs_length); | 412 | write_len = min(xfer_len, ntohl(arg_ch->rs_length)); |
413 | 413 | ||
414 | /* Prepare the response chunk given the length actually | 414 | /* Prepare the response chunk given the length actually |
415 | * written */ | 415 | * written */ |
416 | rs_offset = get_unaligned(&(arg_ch->rs_offset)); | 416 | xdr_decode_hyper((__be32 *)&arg_ch->rs_offset, &rs_offset); |
417 | svc_rdma_xdr_encode_array_chunk(res_ary, chunk_no, | 417 | svc_rdma_xdr_encode_array_chunk(res_ary, chunk_no, |
418 | arg_ch->rs_handle, | 418 | arg_ch->rs_handle, |
419 | rs_offset, | 419 | arg_ch->rs_offset, |
420 | write_len); | 420 | write_len); |
421 | chunk_off = 0; | 421 | chunk_off = 0; |
422 | while (write_len) { | 422 | while (write_len) { |
423 | int this_write; | 423 | int this_write; |
424 | this_write = min(write_len, max_write); | 424 | this_write = min(write_len, max_write); |
425 | ret = send_write(xprt, rqstp, | 425 | ret = send_write(xprt, rqstp, |
426 | arg_ch->rs_handle, | 426 | ntohl(arg_ch->rs_handle), |
427 | rs_offset + chunk_off, | 427 | rs_offset + chunk_off, |
428 | xdr_off, | 428 | xdr_off, |
429 | this_write, | 429 | this_write, |
@@ -457,6 +457,7 @@ static int send_reply_chunks(struct svcxprt_rdma *xprt, | |||
457 | u32 xdr_off; | 457 | u32 xdr_off; |
458 | int chunk_no; | 458 | int chunk_no; |
459 | int chunk_off; | 459 | int chunk_off; |
460 | int nchunks; | ||
460 | struct rpcrdma_segment *ch; | 461 | struct rpcrdma_segment *ch; |
461 | struct rpcrdma_write_array *arg_ary; | 462 | struct rpcrdma_write_array *arg_ary; |
462 | struct rpcrdma_write_array *res_ary; | 463 | struct rpcrdma_write_array *res_ary; |
@@ -476,26 +477,27 @@ static int send_reply_chunks(struct svcxprt_rdma *xprt, | |||
476 | max_write = xprt->sc_max_sge * PAGE_SIZE; | 477 | max_write = xprt->sc_max_sge * PAGE_SIZE; |
477 | 478 | ||
478 | /* xdr offset starts at RPC message */ | 479 | /* xdr offset starts at RPC message */ |
480 | nchunks = ntohl(arg_ary->wc_nchunks); | ||
479 | for (xdr_off = 0, chunk_no = 0; | 481 | for (xdr_off = 0, chunk_no = 0; |
480 | xfer_len && chunk_no < arg_ary->wc_nchunks; | 482 | xfer_len && chunk_no < nchunks; |
481 | chunk_no++) { | 483 | chunk_no++) { |
482 | u64 rs_offset; | 484 | u64 rs_offset; |
483 | ch = &arg_ary->wc_array[chunk_no].wc_target; | 485 | ch = &arg_ary->wc_array[chunk_no].wc_target; |
484 | write_len = min(xfer_len, ch->rs_length); | 486 | write_len = min(xfer_len, htonl(ch->rs_length)); |
485 | 487 | ||
486 | /* Prepare the reply chunk given the length actually | 488 | /* Prepare the reply chunk given the length actually |
487 | * written */ | 489 | * written */ |
488 | rs_offset = get_unaligned(&(ch->rs_offset)); | 490 | xdr_decode_hyper((__be32 *)&ch->rs_offset, &rs_offset); |
489 | svc_rdma_xdr_encode_array_chunk(res_ary, chunk_no, | 491 | svc_rdma_xdr_encode_array_chunk(res_ary, chunk_no, |
490 | ch->rs_handle, rs_offset, | 492 | ch->rs_handle, ch->rs_offset, |
491 | write_len); | 493 | write_len); |
492 | chunk_off = 0; | 494 | chunk_off = 0; |
493 | while (write_len) { | 495 | while (write_len) { |
494 | int this_write; | 496 | int this_write; |
495 | 497 | ||
496 | this_write = min(write_len, max_write); | 498 | this_write = min(write_len, max_write); |
497 | ret = send_write(xprt, rqstp, | 499 | ret = send_write(xprt, rqstp, |
498 | ch->rs_handle, | 500 | ntohl(ch->rs_handle), |
499 | rs_offset + chunk_off, | 501 | rs_offset + chunk_off, |
500 | xdr_off, | 502 | xdr_off, |
501 | this_write, | 503 | this_write, |
diff --git a/net/sunrpc/xprtrdma/svc_rdma_transport.c b/net/sunrpc/xprtrdma/svc_rdma_transport.c index 894cb42db91d..73b428bef598 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_transport.c +++ b/net/sunrpc/xprtrdma/svc_rdma_transport.c | |||
@@ -51,6 +51,7 @@ | |||
51 | #include <rdma/rdma_cm.h> | 51 | #include <rdma/rdma_cm.h> |
52 | #include <linux/sunrpc/svc_rdma.h> | 52 | #include <linux/sunrpc/svc_rdma.h> |
53 | #include <linux/export.h> | 53 | #include <linux/export.h> |
54 | #include "xprt_rdma.h" | ||
54 | 55 | ||
55 | #define RPCDBG_FACILITY RPCDBG_SVCXPRT | 56 | #define RPCDBG_FACILITY RPCDBG_SVCXPRT |
56 | 57 | ||
@@ -90,12 +91,6 @@ struct svc_xprt_class svc_rdma_class = { | |||
90 | .xcl_max_payload = RPCSVC_MAXPAYLOAD_TCP, | 91 | .xcl_max_payload = RPCSVC_MAXPAYLOAD_TCP, |
91 | }; | 92 | }; |
92 | 93 | ||
93 | /* WR context cache. Created in svc_rdma.c */ | ||
94 | extern struct kmem_cache *svc_rdma_ctxt_cachep; | ||
95 | |||
96 | /* Workqueue created in svc_rdma.c */ | ||
97 | extern struct workqueue_struct *svc_rdma_wq; | ||
98 | |||
99 | struct svc_rdma_op_ctxt *svc_rdma_get_context(struct svcxprt_rdma *xprt) | 94 | struct svc_rdma_op_ctxt *svc_rdma_get_context(struct svcxprt_rdma *xprt) |
100 | { | 95 | { |
101 | struct svc_rdma_op_ctxt *ctxt; | 96 | struct svc_rdma_op_ctxt *ctxt; |
@@ -150,9 +145,6 @@ void svc_rdma_put_context(struct svc_rdma_op_ctxt *ctxt, int free_pages) | |||
150 | atomic_dec(&xprt->sc_ctxt_used); | 145 | atomic_dec(&xprt->sc_ctxt_used); |
151 | } | 146 | } |
152 | 147 | ||
153 | /* Temporary NFS request map cache. Created in svc_rdma.c */ | ||
154 | extern struct kmem_cache *svc_rdma_map_cachep; | ||
155 | |||
156 | /* | 148 | /* |
157 | * Temporary NFS req mappings are shared across all transport | 149 | * Temporary NFS req mappings are shared across all transport |
158 | * instances. These are short lived and should be bounded by the number | 150 | * instances. These are short lived and should be bounded by the number |
diff --git a/net/sunrpc/xprtrdma/verbs.c b/net/sunrpc/xprtrdma/verbs.c index 28236bab57f9..745973b729af 100644 --- a/net/sunrpc/xprtrdma/verbs.c +++ b/net/sunrpc/xprtrdma/verbs.c | |||
@@ -1490,6 +1490,9 @@ rpcrdma_register_frmr_external(struct rpcrdma_mr_seg *seg, | |||
1490 | u8 key; | 1490 | u8 key; |
1491 | int len, pageoff; | 1491 | int len, pageoff; |
1492 | int i, rc; | 1492 | int i, rc; |
1493 | int seg_len; | ||
1494 | u64 pa; | ||
1495 | int page_no; | ||
1493 | 1496 | ||
1494 | pageoff = offset_in_page(seg1->mr_offset); | 1497 | pageoff = offset_in_page(seg1->mr_offset); |
1495 | seg1->mr_offset -= pageoff; /* start of page */ | 1498 | seg1->mr_offset -= pageoff; /* start of page */ |
@@ -1497,11 +1500,15 @@ rpcrdma_register_frmr_external(struct rpcrdma_mr_seg *seg, | |||
1497 | len = -pageoff; | 1500 | len = -pageoff; |
1498 | if (*nsegs > RPCRDMA_MAX_DATA_SEGS) | 1501 | if (*nsegs > RPCRDMA_MAX_DATA_SEGS) |
1499 | *nsegs = RPCRDMA_MAX_DATA_SEGS; | 1502 | *nsegs = RPCRDMA_MAX_DATA_SEGS; |
1500 | for (i = 0; i < *nsegs;) { | 1503 | for (page_no = i = 0; i < *nsegs;) { |
1501 | rpcrdma_map_one(ia, seg, writing); | 1504 | rpcrdma_map_one(ia, seg, writing); |
1502 | seg1->mr_chunk.rl_mw->r.frmr.fr_pgl->page_list[i] = seg->mr_dma; | 1505 | pa = seg->mr_dma; |
1506 | for (seg_len = seg->mr_len; seg_len > 0; seg_len -= PAGE_SIZE) { | ||
1507 | seg1->mr_chunk.rl_mw->r.frmr.fr_pgl-> | ||
1508 | page_list[page_no++] = pa; | ||
1509 | pa += PAGE_SIZE; | ||
1510 | } | ||
1503 | len += seg->mr_len; | 1511 | len += seg->mr_len; |
1504 | BUG_ON(seg->mr_len > PAGE_SIZE); | ||
1505 | ++seg; | 1512 | ++seg; |
1506 | ++i; | 1513 | ++i; |
1507 | /* Check for holes */ | 1514 | /* Check for holes */ |
@@ -1540,9 +1547,9 @@ rpcrdma_register_frmr_external(struct rpcrdma_mr_seg *seg, | |||
1540 | frmr_wr.send_flags = IB_SEND_SIGNALED; | 1547 | frmr_wr.send_flags = IB_SEND_SIGNALED; |
1541 | frmr_wr.wr.fast_reg.iova_start = seg1->mr_dma; | 1548 | frmr_wr.wr.fast_reg.iova_start = seg1->mr_dma; |
1542 | frmr_wr.wr.fast_reg.page_list = seg1->mr_chunk.rl_mw->r.frmr.fr_pgl; | 1549 | frmr_wr.wr.fast_reg.page_list = seg1->mr_chunk.rl_mw->r.frmr.fr_pgl; |
1543 | frmr_wr.wr.fast_reg.page_list_len = i; | 1550 | frmr_wr.wr.fast_reg.page_list_len = page_no; |
1544 | frmr_wr.wr.fast_reg.page_shift = PAGE_SHIFT; | 1551 | frmr_wr.wr.fast_reg.page_shift = PAGE_SHIFT; |
1545 | frmr_wr.wr.fast_reg.length = i << PAGE_SHIFT; | 1552 | frmr_wr.wr.fast_reg.length = page_no << PAGE_SHIFT; |
1546 | BUG_ON(frmr_wr.wr.fast_reg.length < len); | 1553 | BUG_ON(frmr_wr.wr.fast_reg.length < len); |
1547 | frmr_wr.wr.fast_reg.access_flags = (writing ? | 1554 | frmr_wr.wr.fast_reg.access_flags = (writing ? |
1548 | IB_ACCESS_REMOTE_WRITE | IB_ACCESS_LOCAL_WRITE : | 1555 | IB_ACCESS_REMOTE_WRITE | IB_ACCESS_LOCAL_WRITE : |
diff --git a/net/sunrpc/xprtrdma/xprt_rdma.h b/net/sunrpc/xprtrdma/xprt_rdma.h index 08c5d5a128fc..9a66c95b5837 100644 --- a/net/sunrpc/xprtrdma/xprt_rdma.h +++ b/net/sunrpc/xprtrdma/xprt_rdma.h | |||
@@ -343,4 +343,11 @@ void rpcrdma_reply_handler(struct rpcrdma_rep *); | |||
343 | */ | 343 | */ |
344 | int rpcrdma_marshal_req(struct rpc_rqst *); | 344 | int rpcrdma_marshal_req(struct rpc_rqst *); |
345 | 345 | ||
346 | /* Temporary NFS request map cache. Created in svc_rdma.c */ | ||
347 | extern struct kmem_cache *svc_rdma_map_cachep; | ||
348 | /* WR context cache. Created in svc_rdma.c */ | ||
349 | extern struct kmem_cache *svc_rdma_ctxt_cachep; | ||
350 | /* Workqueue created in svc_rdma.c */ | ||
351 | extern struct workqueue_struct *svc_rdma_wq; | ||
352 | |||
346 | #endif /* _LINUX_SUNRPC_XPRT_RDMA_H */ | 353 | #endif /* _LINUX_SUNRPC_XPRT_RDMA_H */ |
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 55472c48825e..890b03f8d877 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c | |||
@@ -53,12 +53,12 @@ static void xs_close(struct rpc_xprt *xprt); | |||
53 | /* | 53 | /* |
54 | * xprtsock tunables | 54 | * xprtsock tunables |
55 | */ | 55 | */ |
56 | unsigned int xprt_udp_slot_table_entries = RPC_DEF_SLOT_TABLE; | 56 | static unsigned int xprt_udp_slot_table_entries = RPC_DEF_SLOT_TABLE; |
57 | unsigned int xprt_tcp_slot_table_entries = RPC_MIN_SLOT_TABLE; | 57 | static unsigned int xprt_tcp_slot_table_entries = RPC_MIN_SLOT_TABLE; |
58 | unsigned int xprt_max_tcp_slot_table_entries = RPC_MAX_SLOT_TABLE; | 58 | static unsigned int xprt_max_tcp_slot_table_entries = RPC_MAX_SLOT_TABLE; |
59 | 59 | ||
60 | unsigned int xprt_min_resvport = RPC_DEF_MIN_RESVPORT; | 60 | static unsigned int xprt_min_resvport = RPC_DEF_MIN_RESVPORT; |
61 | unsigned int xprt_max_resvport = RPC_DEF_MAX_RESVPORT; | 61 | static unsigned int xprt_max_resvport = RPC_DEF_MAX_RESVPORT; |
62 | 62 | ||
63 | #define XS_TCP_LINGER_TO (15U * HZ) | 63 | #define XS_TCP_LINGER_TO (15U * HZ) |
64 | static unsigned int xs_tcp_fin_timeout __read_mostly = XS_TCP_LINGER_TO; | 64 | static unsigned int xs_tcp_fin_timeout __read_mostly = XS_TCP_LINGER_TO; |
@@ -2227,7 +2227,7 @@ static void xs_local_print_stats(struct rpc_xprt *xprt, struct seq_file *seq) | |||
2227 | idle_time = (long)(jiffies - xprt->last_used) / HZ; | 2227 | idle_time = (long)(jiffies - xprt->last_used) / HZ; |
2228 | 2228 | ||
2229 | seq_printf(seq, "\txprt:\tlocal %lu %lu %lu %ld %lu %lu %lu " | 2229 | seq_printf(seq, "\txprt:\tlocal %lu %lu %lu %ld %lu %lu %lu " |
2230 | "%llu %llu\n", | 2230 | "%llu %llu %lu %llu %llu\n", |
2231 | xprt->stat.bind_count, | 2231 | xprt->stat.bind_count, |
2232 | xprt->stat.connect_count, | 2232 | xprt->stat.connect_count, |
2233 | xprt->stat.connect_time, | 2233 | xprt->stat.connect_time, |
@@ -2236,7 +2236,10 @@ static void xs_local_print_stats(struct rpc_xprt *xprt, struct seq_file *seq) | |||
2236 | xprt->stat.recvs, | 2236 | xprt->stat.recvs, |
2237 | xprt->stat.bad_xids, | 2237 | xprt->stat.bad_xids, |
2238 | xprt->stat.req_u, | 2238 | xprt->stat.req_u, |
2239 | xprt->stat.bklog_u); | 2239 | xprt->stat.bklog_u, |
2240 | xprt->stat.max_slots, | ||
2241 | xprt->stat.sending_u, | ||
2242 | xprt->stat.pending_u); | ||
2240 | } | 2243 | } |
2241 | 2244 | ||
2242 | /** | 2245 | /** |
@@ -2249,14 +2252,18 @@ static void xs_udp_print_stats(struct rpc_xprt *xprt, struct seq_file *seq) | |||
2249 | { | 2252 | { |
2250 | struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); | 2253 | struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); |
2251 | 2254 | ||
2252 | seq_printf(seq, "\txprt:\tudp %u %lu %lu %lu %lu %Lu %Lu\n", | 2255 | seq_printf(seq, "\txprt:\tudp %u %lu %lu %lu %lu %llu %llu " |
2256 | "%lu %llu %llu\n", | ||
2253 | transport->srcport, | 2257 | transport->srcport, |
2254 | xprt->stat.bind_count, | 2258 | xprt->stat.bind_count, |
2255 | xprt->stat.sends, | 2259 | xprt->stat.sends, |
2256 | xprt->stat.recvs, | 2260 | xprt->stat.recvs, |
2257 | xprt->stat.bad_xids, | 2261 | xprt->stat.bad_xids, |
2258 | xprt->stat.req_u, | 2262 | xprt->stat.req_u, |
2259 | xprt->stat.bklog_u); | 2263 | xprt->stat.bklog_u, |
2264 | xprt->stat.max_slots, | ||
2265 | xprt->stat.sending_u, | ||
2266 | xprt->stat.pending_u); | ||
2260 | } | 2267 | } |
2261 | 2268 | ||
2262 | /** | 2269 | /** |
@@ -2273,7 +2280,8 @@ static void xs_tcp_print_stats(struct rpc_xprt *xprt, struct seq_file *seq) | |||
2273 | if (xprt_connected(xprt)) | 2280 | if (xprt_connected(xprt)) |
2274 | idle_time = (long)(jiffies - xprt->last_used) / HZ; | 2281 | idle_time = (long)(jiffies - xprt->last_used) / HZ; |
2275 | 2282 | ||
2276 | seq_printf(seq, "\txprt:\ttcp %u %lu %lu %lu %ld %lu %lu %lu %Lu %Lu\n", | 2283 | seq_printf(seq, "\txprt:\ttcp %u %lu %lu %lu %ld %lu %lu %lu " |
2284 | "%llu %llu %lu %llu %llu\n", | ||
2277 | transport->srcport, | 2285 | transport->srcport, |
2278 | xprt->stat.bind_count, | 2286 | xprt->stat.bind_count, |
2279 | xprt->stat.connect_count, | 2287 | xprt->stat.connect_count, |
@@ -2283,7 +2291,10 @@ static void xs_tcp_print_stats(struct rpc_xprt *xprt, struct seq_file *seq) | |||
2283 | xprt->stat.recvs, | 2291 | xprt->stat.recvs, |
2284 | xprt->stat.bad_xids, | 2292 | xprt->stat.bad_xids, |
2285 | xprt->stat.req_u, | 2293 | xprt->stat.req_u, |
2286 | xprt->stat.bklog_u); | 2294 | xprt->stat.bklog_u, |
2295 | xprt->stat.max_slots, | ||
2296 | xprt->stat.sending_u, | ||
2297 | xprt->stat.pending_u); | ||
2287 | } | 2298 | } |
2288 | 2299 | ||
2289 | /* | 2300 | /* |
@@ -2464,6 +2475,7 @@ static struct rpc_xprt_ops xs_tcp_ops = { | |||
2464 | static struct rpc_xprt_ops bc_tcp_ops = { | 2475 | static struct rpc_xprt_ops bc_tcp_ops = { |
2465 | .reserve_xprt = xprt_reserve_xprt, | 2476 | .reserve_xprt = xprt_reserve_xprt, |
2466 | .release_xprt = xprt_release_xprt, | 2477 | .release_xprt = xprt_release_xprt, |
2478 | .rpcbind = xs_local_rpcbind, | ||
2467 | .buf_alloc = bc_malloc, | 2479 | .buf_alloc = bc_malloc, |
2468 | .buf_free = bc_free, | 2480 | .buf_free = bc_free, |
2469 | .send_request = bc_send_request, | 2481 | .send_request = bc_send_request, |
diff --git a/net/sysctl_net.c b/net/sysctl_net.c index e75813904f26..c3e65aebecc0 100644 --- a/net/sysctl_net.c +++ b/net/sysctl_net.c | |||
@@ -74,15 +74,13 @@ static struct ctl_table_root net_sysctl_ro_root = { | |||
74 | 74 | ||
75 | static int __net_init sysctl_net_init(struct net *net) | 75 | static int __net_init sysctl_net_init(struct net *net) |
76 | { | 76 | { |
77 | setup_sysctl_set(&net->sysctls, | 77 | setup_sysctl_set(&net->sysctls, &net_sysctl_root, is_seen); |
78 | &net_sysctl_ro_root.default_set, | ||
79 | is_seen); | ||
80 | return 0; | 78 | return 0; |
81 | } | 79 | } |
82 | 80 | ||
83 | static void __net_exit sysctl_net_exit(struct net *net) | 81 | static void __net_exit sysctl_net_exit(struct net *net) |
84 | { | 82 | { |
85 | WARN_ON(!list_empty(&net->sysctls.list)); | 83 | retire_sysctl_set(&net->sysctls); |
86 | } | 84 | } |
87 | 85 | ||
88 | static struct pernet_operations sysctl_pernet_ops = { | 86 | static struct pernet_operations sysctl_pernet_ops = { |
@@ -90,36 +88,32 @@ static struct pernet_operations sysctl_pernet_ops = { | |||
90 | .exit = sysctl_net_exit, | 88 | .exit = sysctl_net_exit, |
91 | }; | 89 | }; |
92 | 90 | ||
93 | static __init int sysctl_init(void) | 91 | static __init int net_sysctl_init(void) |
94 | { | 92 | { |
95 | int ret; | 93 | int ret; |
96 | ret = register_pernet_subsys(&sysctl_pernet_ops); | 94 | ret = register_pernet_subsys(&sysctl_pernet_ops); |
97 | if (ret) | 95 | if (ret) |
98 | goto out; | 96 | goto out; |
99 | register_sysctl_root(&net_sysctl_root); | 97 | setup_sysctl_set(&net_sysctl_ro_root.default_set, &net_sysctl_ro_root, NULL); |
100 | setup_sysctl_set(&net_sysctl_ro_root.default_set, NULL, NULL); | ||
101 | register_sysctl_root(&net_sysctl_ro_root); | 98 | register_sysctl_root(&net_sysctl_ro_root); |
99 | register_sysctl_root(&net_sysctl_root); | ||
102 | out: | 100 | out: |
103 | return ret; | 101 | return ret; |
104 | } | 102 | } |
105 | subsys_initcall(sysctl_init); | 103 | subsys_initcall(net_sysctl_init); |
106 | 104 | ||
107 | struct ctl_table_header *register_net_sysctl_table(struct net *net, | 105 | struct ctl_table_header *register_net_sysctl_table(struct net *net, |
108 | const struct ctl_path *path, struct ctl_table *table) | 106 | const struct ctl_path *path, struct ctl_table *table) |
109 | { | 107 | { |
110 | struct nsproxy namespaces; | 108 | return __register_sysctl_paths(&net->sysctls, path, table); |
111 | namespaces = *current->nsproxy; | ||
112 | namespaces.net_ns = net; | ||
113 | return __register_sysctl_paths(&net_sysctl_root, | ||
114 | &namespaces, path, table); | ||
115 | } | 109 | } |
116 | EXPORT_SYMBOL_GPL(register_net_sysctl_table); | 110 | EXPORT_SYMBOL_GPL(register_net_sysctl_table); |
117 | 111 | ||
118 | struct ctl_table_header *register_net_sysctl_rotable(const | 112 | struct ctl_table_header *register_net_sysctl_rotable(const |
119 | struct ctl_path *path, struct ctl_table *table) | 113 | struct ctl_path *path, struct ctl_table *table) |
120 | { | 114 | { |
121 | return __register_sysctl_paths(&net_sysctl_ro_root, | 115 | return __register_sysctl_paths(&net_sysctl_ro_root.default_set, |
122 | &init_nsproxy, path, table); | 116 | path, table); |
123 | } | 117 | } |
124 | EXPORT_SYMBOL_GPL(register_net_sysctl_rotable); | 118 | EXPORT_SYMBOL_GPL(register_net_sysctl_rotable); |
125 | 119 | ||
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 8ee85aa79fa7..d510353ef431 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c | |||
@@ -293,7 +293,7 @@ static struct sock *unix_find_socket_byinode(struct inode *i) | |||
293 | spin_lock(&unix_table_lock); | 293 | spin_lock(&unix_table_lock); |
294 | sk_for_each(s, node, | 294 | sk_for_each(s, node, |
295 | &unix_socket_table[i->i_ino & (UNIX_HASH_SIZE - 1)]) { | 295 | &unix_socket_table[i->i_ino & (UNIX_HASH_SIZE - 1)]) { |
296 | struct dentry *dentry = unix_sk(s)->dentry; | 296 | struct dentry *dentry = unix_sk(s)->path.dentry; |
297 | 297 | ||
298 | if (dentry && dentry->d_inode == i) { | 298 | if (dentry && dentry->d_inode == i) { |
299 | sock_hold(s); | 299 | sock_hold(s); |
@@ -377,8 +377,7 @@ static void unix_sock_destructor(struct sock *sk) | |||
377 | static int unix_release_sock(struct sock *sk, int embrion) | 377 | static int unix_release_sock(struct sock *sk, int embrion) |
378 | { | 378 | { |
379 | struct unix_sock *u = unix_sk(sk); | 379 | struct unix_sock *u = unix_sk(sk); |
380 | struct dentry *dentry; | 380 | struct path path; |
381 | struct vfsmount *mnt; | ||
382 | struct sock *skpair; | 381 | struct sock *skpair; |
383 | struct sk_buff *skb; | 382 | struct sk_buff *skb; |
384 | int state; | 383 | int state; |
@@ -389,10 +388,9 @@ static int unix_release_sock(struct sock *sk, int embrion) | |||
389 | unix_state_lock(sk); | 388 | unix_state_lock(sk); |
390 | sock_orphan(sk); | 389 | sock_orphan(sk); |
391 | sk->sk_shutdown = SHUTDOWN_MASK; | 390 | sk->sk_shutdown = SHUTDOWN_MASK; |
392 | dentry = u->dentry; | 391 | path = u->path; |
393 | u->dentry = NULL; | 392 | u->path.dentry = NULL; |
394 | mnt = u->mnt; | 393 | u->path.mnt = NULL; |
395 | u->mnt = NULL; | ||
396 | state = sk->sk_state; | 394 | state = sk->sk_state; |
397 | sk->sk_state = TCP_CLOSE; | 395 | sk->sk_state = TCP_CLOSE; |
398 | unix_state_unlock(sk); | 396 | unix_state_unlock(sk); |
@@ -425,10 +423,8 @@ static int unix_release_sock(struct sock *sk, int embrion) | |||
425 | kfree_skb(skb); | 423 | kfree_skb(skb); |
426 | } | 424 | } |
427 | 425 | ||
428 | if (dentry) { | 426 | if (path.dentry) |
429 | dput(dentry); | 427 | path_put(&path); |
430 | mntput(mnt); | ||
431 | } | ||
432 | 428 | ||
433 | sock_put(sk); | 429 | sock_put(sk); |
434 | 430 | ||
@@ -641,8 +637,8 @@ static struct sock *unix_create1(struct net *net, struct socket *sock) | |||
641 | sk->sk_max_ack_backlog = net->unx.sysctl_max_dgram_qlen; | 637 | sk->sk_max_ack_backlog = net->unx.sysctl_max_dgram_qlen; |
642 | sk->sk_destruct = unix_sock_destructor; | 638 | sk->sk_destruct = unix_sock_destructor; |
643 | u = unix_sk(sk); | 639 | u = unix_sk(sk); |
644 | u->dentry = NULL; | 640 | u->path.dentry = NULL; |
645 | u->mnt = NULL; | 641 | u->path.mnt = NULL; |
646 | spin_lock_init(&u->lock); | 642 | spin_lock_init(&u->lock); |
647 | atomic_long_set(&u->inflight, 0); | 643 | atomic_long_set(&u->inflight, 0); |
648 | INIT_LIST_HEAD(&u->link); | 644 | INIT_LIST_HEAD(&u->link); |
@@ -788,7 +784,7 @@ static struct sock *unix_find_other(struct net *net, | |||
788 | goto put_fail; | 784 | goto put_fail; |
789 | 785 | ||
790 | if (u->sk_type == type) | 786 | if (u->sk_type == type) |
791 | touch_atime(path.mnt, path.dentry); | 787 | touch_atime(&path); |
792 | 788 | ||
793 | path_put(&path); | 789 | path_put(&path); |
794 | 790 | ||
@@ -802,9 +798,9 @@ static struct sock *unix_find_other(struct net *net, | |||
802 | u = unix_find_socket_byname(net, sunname, len, type, hash); | 798 | u = unix_find_socket_byname(net, sunname, len, type, hash); |
803 | if (u) { | 799 | if (u) { |
804 | struct dentry *dentry; | 800 | struct dentry *dentry; |
805 | dentry = unix_sk(u)->dentry; | 801 | dentry = unix_sk(u)->path.dentry; |
806 | if (dentry) | 802 | if (dentry) |
807 | touch_atime(unix_sk(u)->mnt, dentry); | 803 | touch_atime(&unix_sk(u)->path); |
808 | } else | 804 | } else |
809 | goto fail; | 805 | goto fail; |
810 | } | 806 | } |
@@ -910,8 +906,7 @@ out_mknod_drop_write: | |||
910 | list = &unix_socket_table[addr->hash]; | 906 | list = &unix_socket_table[addr->hash]; |
911 | } else { | 907 | } else { |
912 | list = &unix_socket_table[dentry->d_inode->i_ino & (UNIX_HASH_SIZE-1)]; | 908 | list = &unix_socket_table[dentry->d_inode->i_ino & (UNIX_HASH_SIZE-1)]; |
913 | u->dentry = path.dentry; | 909 | u->path = path; |
914 | u->mnt = path.mnt; | ||
915 | } | 910 | } |
916 | 911 | ||
917 | err = 0; | 912 | err = 0; |
@@ -1193,9 +1188,9 @@ restart: | |||
1193 | atomic_inc(&otheru->addr->refcnt); | 1188 | atomic_inc(&otheru->addr->refcnt); |
1194 | newu->addr = otheru->addr; | 1189 | newu->addr = otheru->addr; |
1195 | } | 1190 | } |
1196 | if (otheru->dentry) { | 1191 | if (otheru->path.dentry) { |
1197 | newu->dentry = dget(otheru->dentry); | 1192 | path_get(&otheru->path); |
1198 | newu->mnt = mntget(otheru->mnt); | 1193 | newu->path = otheru->path; |
1199 | } | 1194 | } |
1200 | 1195 | ||
1201 | /* Set credentials */ | 1196 | /* Set credentials */ |
@@ -2211,7 +2206,7 @@ static unsigned int unix_dgram_poll(struct file *file, struct socket *sock, | |||
2211 | } | 2206 | } |
2212 | 2207 | ||
2213 | /* No write status requested, avoid expensive OUT tests. */ | 2208 | /* No write status requested, avoid expensive OUT tests. */ |
2214 | if (wait && !(wait->key & (POLLWRBAND | POLLWRNORM | POLLOUT))) | 2209 | if (!(poll_requested_events(wait) & (POLLWRBAND|POLLWRNORM|POLLOUT))) |
2215 | return mask; | 2210 | return mask; |
2216 | 2211 | ||
2217 | writable = unix_writable(sk); | 2212 | writable = unix_writable(sk); |
diff --git a/net/unix/diag.c b/net/unix/diag.c index 4195555aea65..f0486ae9ebe6 100644 --- a/net/unix/diag.c +++ b/net/unix/diag.c | |||
@@ -29,7 +29,7 @@ rtattr_failure: | |||
29 | 29 | ||
30 | static int sk_diag_dump_vfs(struct sock *sk, struct sk_buff *nlskb) | 30 | static int sk_diag_dump_vfs(struct sock *sk, struct sk_buff *nlskb) |
31 | { | 31 | { |
32 | struct dentry *dentry = unix_sk(sk)->dentry; | 32 | struct dentry *dentry = unix_sk(sk)->path.dentry; |
33 | struct unix_diag_vfs *uv; | 33 | struct unix_diag_vfs *uv; |
34 | 34 | ||
35 | if (dentry) { | 35 | if (dentry) { |
diff --git a/net/wireless/debugfs.c b/net/wireless/debugfs.c index 39765bcfb472..920cabe0461b 100644 --- a/net/wireless/debugfs.c +++ b/net/wireless/debugfs.c | |||
@@ -13,12 +13,6 @@ | |||
13 | #include "core.h" | 13 | #include "core.h" |
14 | #include "debugfs.h" | 14 | #include "debugfs.h" |
15 | 15 | ||
16 | static int cfg80211_open_file_generic(struct inode *inode, struct file *file) | ||
17 | { | ||
18 | file->private_data = inode->i_private; | ||
19 | return 0; | ||
20 | } | ||
21 | |||
22 | #define DEBUGFS_READONLY_FILE(name, buflen, fmt, value...) \ | 16 | #define DEBUGFS_READONLY_FILE(name, buflen, fmt, value...) \ |
23 | static ssize_t name## _read(struct file *file, char __user *userbuf, \ | 17 | static ssize_t name## _read(struct file *file, char __user *userbuf, \ |
24 | size_t count, loff_t *ppos) \ | 18 | size_t count, loff_t *ppos) \ |
@@ -33,7 +27,7 @@ static ssize_t name## _read(struct file *file, char __user *userbuf, \ | |||
33 | \ | 27 | \ |
34 | static const struct file_operations name## _ops = { \ | 28 | static const struct file_operations name## _ops = { \ |
35 | .read = name## _read, \ | 29 | .read = name## _read, \ |
36 | .open = cfg80211_open_file_generic, \ | 30 | .open = simple_open, \ |
37 | .llseek = generic_file_llseek, \ | 31 | .llseek = generic_file_llseek, \ |
38 | }; | 32 | }; |
39 | 33 | ||
@@ -102,7 +96,7 @@ static ssize_t ht40allow_map_read(struct file *file, | |||
102 | 96 | ||
103 | static const struct file_operations ht40allow_map_ops = { | 97 | static const struct file_operations ht40allow_map_ops = { |
104 | .read = ht40allow_map_read, | 98 | .read = ht40allow_map_read, |
105 | .open = cfg80211_open_file_generic, | 99 | .open = simple_open, |
106 | .llseek = default_llseek, | 100 | .llseek = default_llseek, |
107 | }; | 101 | }; |
108 | 102 | ||
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index e49da2797022..f432c57af05d 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -1294,6 +1294,11 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) | |||
1294 | goto bad_res; | 1294 | goto bad_res; |
1295 | } | 1295 | } |
1296 | 1296 | ||
1297 | if (!netif_running(netdev)) { | ||
1298 | result = -ENETDOWN; | ||
1299 | goto bad_res; | ||
1300 | } | ||
1301 | |||
1297 | nla_for_each_nested(nl_txq_params, | 1302 | nla_for_each_nested(nl_txq_params, |
1298 | info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS], | 1303 | info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS], |
1299 | rem_txq_params) { | 1304 | rem_txq_params) { |
@@ -6384,7 +6389,7 @@ static struct genl_ops nl80211_ops[] = { | |||
6384 | .doit = nl80211_get_key, | 6389 | .doit = nl80211_get_key, |
6385 | .policy = nl80211_policy, | 6390 | .policy = nl80211_policy, |
6386 | .flags = GENL_ADMIN_PERM, | 6391 | .flags = GENL_ADMIN_PERM, |
6387 | .internal_flags = NL80211_FLAG_NEED_NETDEV | | 6392 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | |
6388 | NL80211_FLAG_NEED_RTNL, | 6393 | NL80211_FLAG_NEED_RTNL, |
6389 | }, | 6394 | }, |
6390 | { | 6395 | { |
@@ -6416,7 +6421,7 @@ static struct genl_ops nl80211_ops[] = { | |||
6416 | .policy = nl80211_policy, | 6421 | .policy = nl80211_policy, |
6417 | .flags = GENL_ADMIN_PERM, | 6422 | .flags = GENL_ADMIN_PERM, |
6418 | .doit = nl80211_set_beacon, | 6423 | .doit = nl80211_set_beacon, |
6419 | .internal_flags = NL80211_FLAG_NEED_NETDEV | | 6424 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | |
6420 | NL80211_FLAG_NEED_RTNL, | 6425 | NL80211_FLAG_NEED_RTNL, |
6421 | }, | 6426 | }, |
6422 | { | 6427 | { |
@@ -6424,7 +6429,7 @@ static struct genl_ops nl80211_ops[] = { | |||
6424 | .policy = nl80211_policy, | 6429 | .policy = nl80211_policy, |
6425 | .flags = GENL_ADMIN_PERM, | 6430 | .flags = GENL_ADMIN_PERM, |
6426 | .doit = nl80211_start_ap, | 6431 | .doit = nl80211_start_ap, |
6427 | .internal_flags = NL80211_FLAG_NEED_NETDEV | | 6432 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | |
6428 | NL80211_FLAG_NEED_RTNL, | 6433 | NL80211_FLAG_NEED_RTNL, |
6429 | }, | 6434 | }, |
6430 | { | 6435 | { |
@@ -6432,7 +6437,7 @@ static struct genl_ops nl80211_ops[] = { | |||
6432 | .policy = nl80211_policy, | 6437 | .policy = nl80211_policy, |
6433 | .flags = GENL_ADMIN_PERM, | 6438 | .flags = GENL_ADMIN_PERM, |
6434 | .doit = nl80211_stop_ap, | 6439 | .doit = nl80211_stop_ap, |
6435 | .internal_flags = NL80211_FLAG_NEED_NETDEV | | 6440 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | |
6436 | NL80211_FLAG_NEED_RTNL, | 6441 | NL80211_FLAG_NEED_RTNL, |
6437 | }, | 6442 | }, |
6438 | { | 6443 | { |
@@ -6448,7 +6453,7 @@ static struct genl_ops nl80211_ops[] = { | |||
6448 | .doit = nl80211_set_station, | 6453 | .doit = nl80211_set_station, |
6449 | .policy = nl80211_policy, | 6454 | .policy = nl80211_policy, |
6450 | .flags = GENL_ADMIN_PERM, | 6455 | .flags = GENL_ADMIN_PERM, |
6451 | .internal_flags = NL80211_FLAG_NEED_NETDEV | | 6456 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | |
6452 | NL80211_FLAG_NEED_RTNL, | 6457 | NL80211_FLAG_NEED_RTNL, |
6453 | }, | 6458 | }, |
6454 | { | 6459 | { |
@@ -6464,7 +6469,7 @@ static struct genl_ops nl80211_ops[] = { | |||
6464 | .doit = nl80211_del_station, | 6469 | .doit = nl80211_del_station, |
6465 | .policy = nl80211_policy, | 6470 | .policy = nl80211_policy, |
6466 | .flags = GENL_ADMIN_PERM, | 6471 | .flags = GENL_ADMIN_PERM, |
6467 | .internal_flags = NL80211_FLAG_NEED_NETDEV | | 6472 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | |
6468 | NL80211_FLAG_NEED_RTNL, | 6473 | NL80211_FLAG_NEED_RTNL, |
6469 | }, | 6474 | }, |
6470 | { | 6475 | { |
@@ -6497,7 +6502,7 @@ static struct genl_ops nl80211_ops[] = { | |||
6497 | .doit = nl80211_del_mpath, | 6502 | .doit = nl80211_del_mpath, |
6498 | .policy = nl80211_policy, | 6503 | .policy = nl80211_policy, |
6499 | .flags = GENL_ADMIN_PERM, | 6504 | .flags = GENL_ADMIN_PERM, |
6500 | .internal_flags = NL80211_FLAG_NEED_NETDEV | | 6505 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | |
6501 | NL80211_FLAG_NEED_RTNL, | 6506 | NL80211_FLAG_NEED_RTNL, |
6502 | }, | 6507 | }, |
6503 | { | 6508 | { |
@@ -6505,7 +6510,7 @@ static struct genl_ops nl80211_ops[] = { | |||
6505 | .doit = nl80211_set_bss, | 6510 | .doit = nl80211_set_bss, |
6506 | .policy = nl80211_policy, | 6511 | .policy = nl80211_policy, |
6507 | .flags = GENL_ADMIN_PERM, | 6512 | .flags = GENL_ADMIN_PERM, |
6508 | .internal_flags = NL80211_FLAG_NEED_NETDEV | | 6513 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | |
6509 | NL80211_FLAG_NEED_RTNL, | 6514 | NL80211_FLAG_NEED_RTNL, |
6510 | }, | 6515 | }, |
6511 | { | 6516 | { |
@@ -6531,7 +6536,7 @@ static struct genl_ops nl80211_ops[] = { | |||
6531 | .doit = nl80211_get_mesh_config, | 6536 | .doit = nl80211_get_mesh_config, |
6532 | .policy = nl80211_policy, | 6537 | .policy = nl80211_policy, |
6533 | /* can be retrieved by unprivileged users */ | 6538 | /* can be retrieved by unprivileged users */ |
6534 | .internal_flags = NL80211_FLAG_NEED_NETDEV | | 6539 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | |
6535 | NL80211_FLAG_NEED_RTNL, | 6540 | NL80211_FLAG_NEED_RTNL, |
6536 | }, | 6541 | }, |
6537 | { | 6542 | { |
@@ -6664,7 +6669,7 @@ static struct genl_ops nl80211_ops[] = { | |||
6664 | .doit = nl80211_setdel_pmksa, | 6669 | .doit = nl80211_setdel_pmksa, |
6665 | .policy = nl80211_policy, | 6670 | .policy = nl80211_policy, |
6666 | .flags = GENL_ADMIN_PERM, | 6671 | .flags = GENL_ADMIN_PERM, |
6667 | .internal_flags = NL80211_FLAG_NEED_NETDEV | | 6672 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | |
6668 | NL80211_FLAG_NEED_RTNL, | 6673 | NL80211_FLAG_NEED_RTNL, |
6669 | }, | 6674 | }, |
6670 | { | 6675 | { |
@@ -6672,7 +6677,7 @@ static struct genl_ops nl80211_ops[] = { | |||
6672 | .doit = nl80211_setdel_pmksa, | 6677 | .doit = nl80211_setdel_pmksa, |
6673 | .policy = nl80211_policy, | 6678 | .policy = nl80211_policy, |
6674 | .flags = GENL_ADMIN_PERM, | 6679 | .flags = GENL_ADMIN_PERM, |
6675 | .internal_flags = NL80211_FLAG_NEED_NETDEV | | 6680 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | |
6676 | NL80211_FLAG_NEED_RTNL, | 6681 | NL80211_FLAG_NEED_RTNL, |
6677 | }, | 6682 | }, |
6678 | { | 6683 | { |
@@ -6680,7 +6685,7 @@ static struct genl_ops nl80211_ops[] = { | |||
6680 | .doit = nl80211_flush_pmksa, | 6685 | .doit = nl80211_flush_pmksa, |
6681 | .policy = nl80211_policy, | 6686 | .policy = nl80211_policy, |
6682 | .flags = GENL_ADMIN_PERM, | 6687 | .flags = GENL_ADMIN_PERM, |
6683 | .internal_flags = NL80211_FLAG_NEED_NETDEV | | 6688 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | |
6684 | NL80211_FLAG_NEED_RTNL, | 6689 | NL80211_FLAG_NEED_RTNL, |
6685 | }, | 6690 | }, |
6686 | { | 6691 | { |
@@ -6840,7 +6845,7 @@ static struct genl_ops nl80211_ops[] = { | |||
6840 | .doit = nl80211_probe_client, | 6845 | .doit = nl80211_probe_client, |
6841 | .policy = nl80211_policy, | 6846 | .policy = nl80211_policy, |
6842 | .flags = GENL_ADMIN_PERM, | 6847 | .flags = GENL_ADMIN_PERM, |
6843 | .internal_flags = NL80211_FLAG_NEED_NETDEV | | 6848 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | |
6844 | NL80211_FLAG_NEED_RTNL, | 6849 | NL80211_FLAG_NEED_RTNL, |
6845 | }, | 6850 | }, |
6846 | { | 6851 | { |
diff --git a/net/wireless/util.c b/net/wireless/util.c index 1b7a08df933c..957f25621617 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c | |||
@@ -989,7 +989,7 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev, | |||
989 | if (rdev->wiphy.software_iftypes & BIT(iftype)) | 989 | if (rdev->wiphy.software_iftypes & BIT(iftype)) |
990 | continue; | 990 | continue; |
991 | for (j = 0; j < c->n_limits; j++) { | 991 | for (j = 0; j < c->n_limits; j++) { |
992 | if (!(limits[j].types & iftype)) | 992 | if (!(limits[j].types & BIT(iftype))) |
993 | continue; | 993 | continue; |
994 | if (limits[j].max < num[iftype]) | 994 | if (limits[j].max < num[iftype]) |
995 | goto cont; | 995 | goto cont; |
diff --git a/net/wireless/wext-core.c b/net/wireless/wext-core.c index 0af7f54e4f61..af648e08e61b 100644 --- a/net/wireless/wext-core.c +++ b/net/wireless/wext-core.c | |||
@@ -780,8 +780,10 @@ static int ioctl_standard_iw_point(struct iw_point *iwp, unsigned int cmd, | |||
780 | if (cmd == SIOCSIWENCODEEXT) { | 780 | if (cmd == SIOCSIWENCODEEXT) { |
781 | struct iw_encode_ext *ee = (void *) extra; | 781 | struct iw_encode_ext *ee = (void *) extra; |
782 | 782 | ||
783 | if (iwp->length < sizeof(*ee) + ee->key_len) | 783 | if (iwp->length < sizeof(*ee) + ee->key_len) { |
784 | return -EFAULT; | 784 | err = -EFAULT; |
785 | goto out; | ||
786 | } | ||
785 | } | 787 | } |
786 | } | 788 | } |
787 | 789 | ||