diff options
Diffstat (limited to 'net')
35 files changed, 927 insertions, 335 deletions
diff --git a/net/9p/client.c b/net/9p/client.c index ba93bdab2701..ee8fd6bd4035 100644 --- a/net/9p/client.c +++ b/net/9p/client.c | |||
@@ -987,6 +987,7 @@ struct p9_client *p9_client_create(const char *dev_name, char *options) | |||
987 | { | 987 | { |
988 | int err; | 988 | int err; |
989 | struct p9_client *clnt; | 989 | struct p9_client *clnt; |
990 | char *client_id; | ||
990 | 991 | ||
991 | err = 0; | 992 | err = 0; |
992 | clnt = kmalloc(sizeof(struct p9_client), GFP_KERNEL); | 993 | clnt = kmalloc(sizeof(struct p9_client), GFP_KERNEL); |
@@ -995,6 +996,10 @@ struct p9_client *p9_client_create(const char *dev_name, char *options) | |||
995 | 996 | ||
996 | clnt->trans_mod = NULL; | 997 | clnt->trans_mod = NULL; |
997 | clnt->trans = NULL; | 998 | clnt->trans = NULL; |
999 | |||
1000 | client_id = utsname()->nodename; | ||
1001 | memcpy(clnt->name, client_id, strlen(client_id) + 1); | ||
1002 | |||
998 | spin_lock_init(&clnt->lock); | 1003 | spin_lock_init(&clnt->lock); |
999 | INIT_LIST_HEAD(&clnt->fidlist); | 1004 | INIT_LIST_HEAD(&clnt->fidlist); |
1000 | 1005 | ||
diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c index e1c26b101830..990afab2be1b 100644 --- a/net/9p/trans_virtio.c +++ b/net/9p/trans_virtio.c | |||
@@ -577,6 +577,10 @@ static int p9_virtio_probe(struct virtio_device *vdev) | |||
577 | mutex_lock(&virtio_9p_lock); | 577 | mutex_lock(&virtio_9p_lock); |
578 | list_add_tail(&chan->chan_list, &virtio_chan_list); | 578 | list_add_tail(&chan->chan_list, &virtio_chan_list); |
579 | mutex_unlock(&virtio_9p_lock); | 579 | mutex_unlock(&virtio_9p_lock); |
580 | |||
581 | /* Let udev rules use the new mount_tag attribute. */ | ||
582 | kobject_uevent(&(vdev->dev.kobj), KOBJ_CHANGE); | ||
583 | |||
580 | return 0; | 584 | return 0; |
581 | 585 | ||
582 | out_free_tag: | 586 | out_free_tag: |
@@ -654,6 +658,7 @@ static void p9_virtio_remove(struct virtio_device *vdev) | |||
654 | list_del(&chan->chan_list); | 658 | list_del(&chan->chan_list); |
655 | mutex_unlock(&virtio_9p_lock); | 659 | mutex_unlock(&virtio_9p_lock); |
656 | sysfs_remove_file(&(vdev->dev.kobj), &dev_attr_mount_tag.attr); | 660 | sysfs_remove_file(&(vdev->dev.kobj), &dev_attr_mount_tag.attr); |
661 | kobject_uevent(&(vdev->dev.kobj), KOBJ_CHANGE); | ||
657 | kfree(chan->tag); | 662 | kfree(chan->tag); |
658 | kfree(chan->vc_wq); | 663 | kfree(chan->vc_wq); |
659 | kfree(chan); | 664 | kfree(chan); |
diff --git a/net/Kconfig b/net/Kconfig index ee0213667272..b50dacc072f0 100644 --- a/net/Kconfig +++ b/net/Kconfig | |||
@@ -228,7 +228,7 @@ config RPS | |||
228 | 228 | ||
229 | config RFS_ACCEL | 229 | config RFS_ACCEL |
230 | boolean | 230 | boolean |
231 | depends on RPS && GENERIC_HARDIRQS | 231 | depends on RPS |
232 | select CPU_RMAP | 232 | select CPU_RMAP |
233 | default y | 233 | default y |
234 | 234 | ||
diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 3be308e14302..4a5df7b1cc9f 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c | |||
@@ -290,7 +290,7 @@ int ceph_msgr_init(void) | |||
290 | if (ceph_msgr_slab_init()) | 290 | if (ceph_msgr_slab_init()) |
291 | return -ENOMEM; | 291 | return -ENOMEM; |
292 | 292 | ||
293 | ceph_msgr_wq = alloc_workqueue("ceph-msgr", WQ_NON_REENTRANT, 0); | 293 | ceph_msgr_wq = alloc_workqueue("ceph-msgr", 0, 0); |
294 | if (ceph_msgr_wq) | 294 | if (ceph_msgr_wq) |
295 | return 0; | 295 | return 0; |
296 | 296 | ||
diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index dd47889adc4a..1606f740d6ae 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c | |||
@@ -503,7 +503,9 @@ void osd_req_op_extent_init(struct ceph_osd_request *osd_req, | |||
503 | struct ceph_osd_req_op *op = _osd_req_op_init(osd_req, which, opcode); | 503 | struct ceph_osd_req_op *op = _osd_req_op_init(osd_req, which, opcode); |
504 | size_t payload_len = 0; | 504 | size_t payload_len = 0; |
505 | 505 | ||
506 | BUG_ON(opcode != CEPH_OSD_OP_READ && opcode != CEPH_OSD_OP_WRITE); | 506 | BUG_ON(opcode != CEPH_OSD_OP_READ && opcode != CEPH_OSD_OP_WRITE && |
507 | opcode != CEPH_OSD_OP_DELETE && opcode != CEPH_OSD_OP_ZERO && | ||
508 | opcode != CEPH_OSD_OP_TRUNCATE); | ||
507 | 509 | ||
508 | op->extent.offset = offset; | 510 | op->extent.offset = offset; |
509 | op->extent.length = length; | 511 | op->extent.length = length; |
@@ -631,6 +633,9 @@ static u64 osd_req_encode_op(struct ceph_osd_request *req, | |||
631 | break; | 633 | break; |
632 | case CEPH_OSD_OP_READ: | 634 | case CEPH_OSD_OP_READ: |
633 | case CEPH_OSD_OP_WRITE: | 635 | case CEPH_OSD_OP_WRITE: |
636 | case CEPH_OSD_OP_ZERO: | ||
637 | case CEPH_OSD_OP_DELETE: | ||
638 | case CEPH_OSD_OP_TRUNCATE: | ||
634 | if (src->op == CEPH_OSD_OP_WRITE) | 639 | if (src->op == CEPH_OSD_OP_WRITE) |
635 | request_data_len = src->extent.length; | 640 | request_data_len = src->extent.length; |
636 | dst->extent.offset = cpu_to_le64(src->extent.offset); | 641 | dst->extent.offset = cpu_to_le64(src->extent.offset); |
@@ -715,7 +720,9 @@ struct ceph_osd_request *ceph_osdc_new_request(struct ceph_osd_client *osdc, | |||
715 | u64 object_base; | 720 | u64 object_base; |
716 | int r; | 721 | int r; |
717 | 722 | ||
718 | BUG_ON(opcode != CEPH_OSD_OP_READ && opcode != CEPH_OSD_OP_WRITE); | 723 | BUG_ON(opcode != CEPH_OSD_OP_READ && opcode != CEPH_OSD_OP_WRITE && |
724 | opcode != CEPH_OSD_OP_DELETE && opcode != CEPH_OSD_OP_ZERO && | ||
725 | opcode != CEPH_OSD_OP_TRUNCATE); | ||
719 | 726 | ||
720 | req = ceph_osdc_alloc_request(osdc, snapc, num_ops, use_mempool, | 727 | req = ceph_osdc_alloc_request(osdc, snapc, num_ops, use_mempool, |
721 | GFP_NOFS); | 728 | GFP_NOFS); |
@@ -1488,14 +1495,14 @@ static void handle_reply(struct ceph_osd_client *osdc, struct ceph_msg *msg, | |||
1488 | dout("handle_reply %p tid %llu req %p result %d\n", msg, tid, | 1495 | dout("handle_reply %p tid %llu req %p result %d\n", msg, tid, |
1489 | req, result); | 1496 | req, result); |
1490 | 1497 | ||
1491 | ceph_decode_need(&p, end, 4, bad); | 1498 | ceph_decode_need(&p, end, 4, bad_put); |
1492 | numops = ceph_decode_32(&p); | 1499 | numops = ceph_decode_32(&p); |
1493 | if (numops > CEPH_OSD_MAX_OP) | 1500 | if (numops > CEPH_OSD_MAX_OP) |
1494 | goto bad_put; | 1501 | goto bad_put; |
1495 | if (numops != req->r_num_ops) | 1502 | if (numops != req->r_num_ops) |
1496 | goto bad_put; | 1503 | goto bad_put; |
1497 | payload_len = 0; | 1504 | payload_len = 0; |
1498 | ceph_decode_need(&p, end, numops * sizeof(struct ceph_osd_op), bad); | 1505 | ceph_decode_need(&p, end, numops * sizeof(struct ceph_osd_op), bad_put); |
1499 | for (i = 0; i < numops; i++) { | 1506 | for (i = 0; i < numops; i++) { |
1500 | struct ceph_osd_op *op = p; | 1507 | struct ceph_osd_op *op = p; |
1501 | int len; | 1508 | int len; |
@@ -1513,7 +1520,7 @@ static void handle_reply(struct ceph_osd_client *osdc, struct ceph_msg *msg, | |||
1513 | goto bad_put; | 1520 | goto bad_put; |
1514 | } | 1521 | } |
1515 | 1522 | ||
1516 | ceph_decode_need(&p, end, 4 + numops * 4, bad); | 1523 | ceph_decode_need(&p, end, 4 + numops * 4, bad_put); |
1517 | retry_attempt = ceph_decode_32(&p); | 1524 | retry_attempt = ceph_decode_32(&p); |
1518 | for (i = 0; i < numops; i++) | 1525 | for (i = 0; i < numops; i++) |
1519 | req->r_reply_op_result[i] = ceph_decode_32(&p); | 1526 | req->r_reply_op_result[i] = ceph_decode_32(&p); |
@@ -1786,6 +1793,8 @@ void ceph_osdc_handle_map(struct ceph_osd_client *osdc, struct ceph_msg *msg) | |||
1786 | nr_maps--; | 1793 | nr_maps--; |
1787 | } | 1794 | } |
1788 | 1795 | ||
1796 | if (!osdc->osdmap) | ||
1797 | goto bad; | ||
1789 | done: | 1798 | done: |
1790 | downgrade_write(&osdc->map_sem); | 1799 | downgrade_write(&osdc->map_sem); |
1791 | ceph_monc_got_osdmap(&osdc->client->monc, osdc->osdmap->epoch); | 1800 | ceph_monc_got_osdmap(&osdc->client->monc, osdc->osdmap->epoch); |
@@ -2129,6 +2138,8 @@ int ceph_osdc_start_request(struct ceph_osd_client *osdc, | |||
2129 | dout("osdc_start_request failed map, " | 2138 | dout("osdc_start_request failed map, " |
2130 | " will retry %lld\n", req->r_tid); | 2139 | " will retry %lld\n", req->r_tid); |
2131 | rc = 0; | 2140 | rc = 0; |
2141 | } else { | ||
2142 | __unregister_request(osdc, req); | ||
2132 | } | 2143 | } |
2133 | goto out_unlock; | 2144 | goto out_unlock; |
2134 | } | 2145 | } |
@@ -2253,12 +2264,10 @@ int ceph_osdc_init(struct ceph_osd_client *osdc, struct ceph_client *client) | |||
2253 | if (err < 0) | 2264 | if (err < 0) |
2254 | goto out_msgpool; | 2265 | goto out_msgpool; |
2255 | 2266 | ||
2267 | err = -ENOMEM; | ||
2256 | osdc->notify_wq = create_singlethread_workqueue("ceph-watch-notify"); | 2268 | osdc->notify_wq = create_singlethread_workqueue("ceph-watch-notify"); |
2257 | if (IS_ERR(osdc->notify_wq)) { | 2269 | if (!osdc->notify_wq) |
2258 | err = PTR_ERR(osdc->notify_wq); | ||
2259 | osdc->notify_wq = NULL; | ||
2260 | goto out_msgpool; | 2270 | goto out_msgpool; |
2261 | } | ||
2262 | return 0; | 2271 | return 0; |
2263 | 2272 | ||
2264 | out_msgpool: | 2273 | out_msgpool: |
diff --git a/net/ceph/osdmap.c b/net/ceph/osdmap.c index 603ddd92db19..dbd9a4792427 100644 --- a/net/ceph/osdmap.c +++ b/net/ceph/osdmap.c | |||
@@ -1129,7 +1129,7 @@ static int *calc_pg_raw(struct ceph_osdmap *osdmap, struct ceph_pg pgid, | |||
1129 | 1129 | ||
1130 | /* pg_temp? */ | 1130 | /* pg_temp? */ |
1131 | pgid.seed = ceph_stable_mod(pgid.seed, pool->pg_num, | 1131 | pgid.seed = ceph_stable_mod(pgid.seed, pool->pg_num, |
1132 | pool->pgp_num_mask); | 1132 | pool->pg_num_mask); |
1133 | pg = __lookup_pg_mapping(&osdmap->pg_temp, pgid); | 1133 | pg = __lookup_pg_mapping(&osdmap->pg_temp, pgid); |
1134 | if (pg) { | 1134 | if (pg) { |
1135 | *num = pg->len; | 1135 | *num = pg->len; |
diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c index 0ff42f029ace..1929af87b260 100644 --- a/net/core/flow_dissector.c +++ b/net/core/flow_dissector.c | |||
@@ -352,7 +352,7 @@ u16 __netdev_pick_tx(struct net_device *dev, struct sk_buff *skb) | |||
352 | 352 | ||
353 | if (queue_index != new_index && sk && | 353 | if (queue_index != new_index && sk && |
354 | rcu_access_pointer(sk->sk_dst_cache)) | 354 | rcu_access_pointer(sk->sk_dst_cache)) |
355 | sk_tx_queue_set(sk, queue_index); | 355 | sk_tx_queue_set(sk, new_index); |
356 | 356 | ||
357 | queue_index = new_index; | 357 | queue_index = new_index; |
358 | } | 358 | } |
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index 3f40ea9de814..d954b56b4e47 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c | |||
@@ -1196,6 +1196,13 @@ static void remove_queue_kobjects(struct net_device *net) | |||
1196 | #endif | 1196 | #endif |
1197 | } | 1197 | } |
1198 | 1198 | ||
1199 | static bool net_current_may_mount(void) | ||
1200 | { | ||
1201 | struct net *net = current->nsproxy->net_ns; | ||
1202 | |||
1203 | return ns_capable(net->user_ns, CAP_SYS_ADMIN); | ||
1204 | } | ||
1205 | |||
1199 | static void *net_grab_current_ns(void) | 1206 | static void *net_grab_current_ns(void) |
1200 | { | 1207 | { |
1201 | struct net *ns = current->nsproxy->net_ns; | 1208 | struct net *ns = current->nsproxy->net_ns; |
@@ -1218,6 +1225,7 @@ static const void *net_netlink_ns(struct sock *sk) | |||
1218 | 1225 | ||
1219 | struct kobj_ns_type_operations net_ns_type_operations = { | 1226 | struct kobj_ns_type_operations net_ns_type_operations = { |
1220 | .type = KOBJ_NS_TYPE_NET, | 1227 | .type = KOBJ_NS_TYPE_NET, |
1228 | .current_may_mount = net_current_may_mount, | ||
1221 | .grab_current_ns = net_grab_current_ns, | 1229 | .grab_current_ns = net_grab_current_ns, |
1222 | .netlink_ns = net_netlink_ns, | 1230 | .netlink_ns = net_netlink_ns, |
1223 | .initial_ns = net_initial_ns, | 1231 | .initial_ns = net_initial_ns, |
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index f97652036754..81d3a9a08453 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c | |||
@@ -651,7 +651,7 @@ static int netns_install(struct nsproxy *nsproxy, void *ns) | |||
651 | struct net *net = ns; | 651 | struct net *net = ns; |
652 | 652 | ||
653 | if (!ns_capable(net->user_ns, CAP_SYS_ADMIN) || | 653 | if (!ns_capable(net->user_ns, CAP_SYS_ADMIN) || |
654 | !nsown_capable(CAP_SYS_ADMIN)) | 654 | !ns_capable(current_user_ns(), CAP_SYS_ADMIN)) |
655 | return -EPERM; | 655 | return -EPERM; |
656 | 656 | ||
657 | put_net(nsproxy->net_ns); | 657 | put_net(nsproxy->net_ns); |
diff --git a/net/core/scm.c b/net/core/scm.c index b4da80b1cc07..b442e7e25e60 100644 --- a/net/core/scm.c +++ b/net/core/scm.c | |||
@@ -56,9 +56,9 @@ static __inline__ int scm_check_creds(struct ucred *creds) | |||
56 | if ((creds->pid == task_tgid_vnr(current) || | 56 | if ((creds->pid == task_tgid_vnr(current) || |
57 | ns_capable(task_active_pid_ns(current)->user_ns, CAP_SYS_ADMIN)) && | 57 | ns_capable(task_active_pid_ns(current)->user_ns, CAP_SYS_ADMIN)) && |
58 | ((uid_eq(uid, cred->uid) || uid_eq(uid, cred->euid) || | 58 | ((uid_eq(uid, cred->uid) || uid_eq(uid, cred->euid) || |
59 | uid_eq(uid, cred->suid)) || nsown_capable(CAP_SETUID)) && | 59 | uid_eq(uid, cred->suid)) || ns_capable(cred->user_ns, CAP_SETUID)) && |
60 | ((gid_eq(gid, cred->gid) || gid_eq(gid, cred->egid) || | 60 | ((gid_eq(gid, cred->gid) || gid_eq(gid, cred->egid) || |
61 | gid_eq(gid, cred->sgid)) || nsown_capable(CAP_SETGID))) { | 61 | gid_eq(gid, cred->sgid)) || ns_capable(cred->user_ns, CAP_SETGID))) { |
62 | return 0; | 62 | return 0; |
63 | } | 63 | } |
64 | return -EPERM; | 64 | return -EPERM; |
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 1969e16d936d..25a89eaa669d 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -3162,16 +3162,14 @@ static inline bool tcp_may_raise_cwnd(const struct sock *sk, const int flag) | |||
3162 | 3162 | ||
3163 | /* If reordering is high then always grow cwnd whenever data is | 3163 | /* If reordering is high then always grow cwnd whenever data is |
3164 | * delivered regardless of its ordering. Otherwise stay conservative | 3164 | * delivered regardless of its ordering. Otherwise stay conservative |
3165 | * and only grow cwnd on in-order delivery in Open state, and retain | 3165 | * and only grow cwnd on in-order delivery (RFC5681). A stretched ACK w/ |
3166 | * cwnd in Disordered state (RFC5681). A stretched ACK with | ||
3167 | * new SACK or ECE mark may first advance cwnd here and later reduce | 3166 | * new SACK or ECE mark may first advance cwnd here and later reduce |
3168 | * cwnd in tcp_fastretrans_alert() based on more states. | 3167 | * cwnd in tcp_fastretrans_alert() based on more states. |
3169 | */ | 3168 | */ |
3170 | if (tcp_sk(sk)->reordering > sysctl_tcp_reordering) | 3169 | if (tcp_sk(sk)->reordering > sysctl_tcp_reordering) |
3171 | return flag & FLAG_FORWARD_PROGRESS; | 3170 | return flag & FLAG_FORWARD_PROGRESS; |
3172 | 3171 | ||
3173 | return inet_csk(sk)->icsk_ca_state == TCP_CA_Open && | 3172 | return flag & FLAG_DATA_ACKED; |
3174 | flag & FLAG_DATA_ACKED; | ||
3175 | } | 3173 | } |
3176 | 3174 | ||
3177 | /* Check that window update is acceptable. | 3175 | /* Check that window update is acceptable. |
@@ -4141,6 +4139,7 @@ static void tcp_data_queue_ofo(struct sock *sk, struct sk_buff *skb) | |||
4141 | if (!tcp_try_coalesce(sk, skb1, skb, &fragstolen)) { | 4139 | if (!tcp_try_coalesce(sk, skb1, skb, &fragstolen)) { |
4142 | __skb_queue_after(&tp->out_of_order_queue, skb1, skb); | 4140 | __skb_queue_after(&tp->out_of_order_queue, skb1, skb); |
4143 | } else { | 4141 | } else { |
4142 | tcp_grow_window(sk, skb); | ||
4144 | kfree_skb_partial(skb, fragstolen); | 4143 | kfree_skb_partial(skb, fragstolen); |
4145 | skb = NULL; | 4144 | skb = NULL; |
4146 | } | 4145 | } |
@@ -4216,8 +4215,10 @@ add_sack: | |||
4216 | if (tcp_is_sack(tp)) | 4215 | if (tcp_is_sack(tp)) |
4217 | tcp_sack_new_ofo_skb(sk, seq, end_seq); | 4216 | tcp_sack_new_ofo_skb(sk, seq, end_seq); |
4218 | end: | 4217 | end: |
4219 | if (skb) | 4218 | if (skb) { |
4219 | tcp_grow_window(sk, skb); | ||
4220 | skb_set_owner_r(skb, sk); | 4220 | skb_set_owner_r(skb, sk); |
4221 | } | ||
4221 | } | 4222 | } |
4222 | 4223 | ||
4223 | static int __must_check tcp_queue_rcv(struct sock *sk, struct sk_buff *skb, int hdrlen, | 4224 | static int __must_check tcp_queue_rcv(struct sock *sk, struct sk_buff *skb, int hdrlen, |
diff --git a/net/ipv4/tcp_memcontrol.c b/net/ipv4/tcp_memcontrol.c index 8a57d79b0b16..559d4ae6ebf4 100644 --- a/net/ipv4/tcp_memcontrol.c +++ b/net/ipv4/tcp_memcontrol.c | |||
@@ -87,8 +87,8 @@ static int tcp_update_limit(struct mem_cgroup *memcg, u64 val) | |||
87 | if (!cg_proto) | 87 | if (!cg_proto) |
88 | return -EINVAL; | 88 | return -EINVAL; |
89 | 89 | ||
90 | if (val > RESOURCE_MAX) | 90 | if (val > RES_COUNTER_MAX) |
91 | val = RESOURCE_MAX; | 91 | val = RES_COUNTER_MAX; |
92 | 92 | ||
93 | tcp = tcp_from_cgproto(cg_proto); | 93 | tcp = tcp_from_cgproto(cg_proto); |
94 | 94 | ||
@@ -101,9 +101,9 @@ static int tcp_update_limit(struct mem_cgroup *memcg, u64 val) | |||
101 | tcp->tcp_prot_mem[i] = min_t(long, val >> PAGE_SHIFT, | 101 | tcp->tcp_prot_mem[i] = min_t(long, val >> PAGE_SHIFT, |
102 | net->ipv4.sysctl_tcp_mem[i]); | 102 | net->ipv4.sysctl_tcp_mem[i]); |
103 | 103 | ||
104 | if (val == RESOURCE_MAX) | 104 | if (val == RES_COUNTER_MAX) |
105 | clear_bit(MEMCG_SOCK_ACTIVE, &cg_proto->flags); | 105 | clear_bit(MEMCG_SOCK_ACTIVE, &cg_proto->flags); |
106 | else if (val != RESOURCE_MAX) { | 106 | else if (val != RES_COUNTER_MAX) { |
107 | /* | 107 | /* |
108 | * The active bit needs to be written after the static_key | 108 | * The active bit needs to be written after the static_key |
109 | * update. This is what guarantees that the socket activation | 109 | * update. This is what guarantees that the socket activation |
@@ -187,7 +187,7 @@ static u64 tcp_cgroup_read(struct cgroup_subsys_state *css, struct cftype *cft) | |||
187 | 187 | ||
188 | switch (cft->private) { | 188 | switch (cft->private) { |
189 | case RES_LIMIT: | 189 | case RES_LIMIT: |
190 | val = tcp_read_stat(memcg, RES_LIMIT, RESOURCE_MAX); | 190 | val = tcp_read_stat(memcg, RES_LIMIT, RES_COUNTER_MAX); |
191 | break; | 191 | break; |
192 | case RES_USAGE: | 192 | case RES_USAGE: |
193 | val = tcp_read_usage(memcg); | 193 | val = tcp_read_usage(memcg); |
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 136fe55c1a47..7c96100b021e 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c | |||
@@ -915,6 +915,9 @@ static int __init inet6_init(void) | |||
915 | err = ip6_route_init(); | 915 | err = ip6_route_init(); |
916 | if (err) | 916 | if (err) |
917 | goto ip6_route_fail; | 917 | goto ip6_route_fail; |
918 | err = ndisc_late_init(); | ||
919 | if (err) | ||
920 | goto ndisc_late_fail; | ||
918 | err = ip6_flowlabel_init(); | 921 | err = ip6_flowlabel_init(); |
919 | if (err) | 922 | if (err) |
920 | goto ip6_flowlabel_fail; | 923 | goto ip6_flowlabel_fail; |
@@ -981,6 +984,8 @@ ipv6_exthdrs_fail: | |||
981 | addrconf_fail: | 984 | addrconf_fail: |
982 | ip6_flowlabel_cleanup(); | 985 | ip6_flowlabel_cleanup(); |
983 | ip6_flowlabel_fail: | 986 | ip6_flowlabel_fail: |
987 | ndisc_late_cleanup(); | ||
988 | ndisc_late_fail: | ||
984 | ip6_route_cleanup(); | 989 | ip6_route_cleanup(); |
985 | ip6_route_fail: | 990 | ip6_route_fail: |
986 | #ifdef CONFIG_PROC_FS | 991 | #ifdef CONFIG_PROC_FS |
@@ -1043,6 +1048,7 @@ static void __exit inet6_exit(void) | |||
1043 | ipv6_exthdrs_exit(); | 1048 | ipv6_exthdrs_exit(); |
1044 | addrconf_cleanup(); | 1049 | addrconf_cleanup(); |
1045 | ip6_flowlabel_cleanup(); | 1050 | ip6_flowlabel_cleanup(); |
1051 | ndisc_late_cleanup(); | ||
1046 | ip6_route_cleanup(); | 1052 | ip6_route_cleanup(); |
1047 | #ifdef CONFIG_PROC_FS | 1053 | #ifdef CONFIG_PROC_FS |
1048 | 1054 | ||
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c index 07a7d65a7cb6..8d67900aa003 100644 --- a/net/ipv6/exthdrs.c +++ b/net/ipv6/exthdrs.c | |||
@@ -162,12 +162,6 @@ static bool ip6_parse_tlv(const struct tlvtype_proc *procs, struct sk_buff *skb) | |||
162 | off += optlen; | 162 | off += optlen; |
163 | len -= optlen; | 163 | len -= optlen; |
164 | } | 164 | } |
165 | /* This case will not be caught by above check since its padding | ||
166 | * length is smaller than 7: | ||
167 | * 1 byte NH + 1 byte Length + 6 bytes Padding | ||
168 | */ | ||
169 | if ((padlen == 6) && ((off - skb_network_header_len(skb)) == 8)) | ||
170 | goto bad; | ||
171 | 165 | ||
172 | if (len == 0) | 166 | if (len == 0) |
173 | return true; | 167 | return true; |
diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c index a6c58ce43d34..e27591635f92 100644 --- a/net/ipv6/fib6_rules.c +++ b/net/ipv6/fib6_rules.c | |||
@@ -138,8 +138,8 @@ static bool fib6_rule_suppress(struct fib_rule *rule, struct fib_lookup_arg *arg | |||
138 | return false; | 138 | return false; |
139 | 139 | ||
140 | suppress_route: | 140 | suppress_route: |
141 | ip6_rt_put(rt); | 141 | ip6_rt_put(rt); |
142 | return true; | 142 | return true; |
143 | } | 143 | } |
144 | 144 | ||
145 | static int fib6_rule_match(struct fib_rule *rule, struct flowi *fl, int flags) | 145 | static int fib6_rule_match(struct fib_rule *rule, struct flowi *fl, int flags) |
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index 73db48eba1c4..5bec666aba61 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c | |||
@@ -825,9 +825,9 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nl_info *info) | |||
825 | fn = fib6_add_1(root, &rt->rt6i_dst.addr, rt->rt6i_dst.plen, | 825 | fn = fib6_add_1(root, &rt->rt6i_dst.addr, rt->rt6i_dst.plen, |
826 | offsetof(struct rt6_info, rt6i_dst), allow_create, | 826 | offsetof(struct rt6_info, rt6i_dst), allow_create, |
827 | replace_required); | 827 | replace_required); |
828 | |||
829 | if (IS_ERR(fn)) { | 828 | if (IS_ERR(fn)) { |
830 | err = PTR_ERR(fn); | 829 | err = PTR_ERR(fn); |
830 | fn = NULL; | ||
831 | goto out; | 831 | goto out; |
832 | } | 832 | } |
833 | 833 | ||
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 12179457b2cd..f8a55ff1971b 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c | |||
@@ -1727,24 +1727,28 @@ int __init ndisc_init(void) | |||
1727 | if (err) | 1727 | if (err) |
1728 | goto out_unregister_pernet; | 1728 | goto out_unregister_pernet; |
1729 | #endif | 1729 | #endif |
1730 | err = register_netdevice_notifier(&ndisc_netdev_notifier); | ||
1731 | if (err) | ||
1732 | goto out_unregister_sysctl; | ||
1733 | out: | 1730 | out: |
1734 | return err; | 1731 | return err; |
1735 | 1732 | ||
1736 | out_unregister_sysctl: | ||
1737 | #ifdef CONFIG_SYSCTL | 1733 | #ifdef CONFIG_SYSCTL |
1738 | neigh_sysctl_unregister(&nd_tbl.parms); | ||
1739 | out_unregister_pernet: | 1734 | out_unregister_pernet: |
1740 | #endif | ||
1741 | unregister_pernet_subsys(&ndisc_net_ops); | 1735 | unregister_pernet_subsys(&ndisc_net_ops); |
1742 | goto out; | 1736 | goto out; |
1737 | #endif | ||
1743 | } | 1738 | } |
1744 | 1739 | ||
1745 | void ndisc_cleanup(void) | 1740 | int __init ndisc_late_init(void) |
1741 | { | ||
1742 | return register_netdevice_notifier(&ndisc_netdev_notifier); | ||
1743 | } | ||
1744 | |||
1745 | void ndisc_late_cleanup(void) | ||
1746 | { | 1746 | { |
1747 | unregister_netdevice_notifier(&ndisc_netdev_notifier); | 1747 | unregister_netdevice_notifier(&ndisc_netdev_notifier); |
1748 | } | ||
1749 | |||
1750 | void ndisc_cleanup(void) | ||
1751 | { | ||
1748 | #ifdef CONFIG_SYSCTL | 1752 | #ifdef CONFIG_SYSCTL |
1749 | neigh_sysctl_unregister(&nd_tbl.parms); | 1753 | neigh_sysctl_unregister(&nd_tbl.parms); |
1750 | #endif | 1754 | #endif |
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index a17dda1bbee0..8df7f64c6db3 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c | |||
@@ -168,16 +168,43 @@ int netlink_remove_tap(struct netlink_tap *nt) | |||
168 | } | 168 | } |
169 | EXPORT_SYMBOL_GPL(netlink_remove_tap); | 169 | EXPORT_SYMBOL_GPL(netlink_remove_tap); |
170 | 170 | ||
171 | static bool netlink_filter_tap(const struct sk_buff *skb) | ||
172 | { | ||
173 | struct sock *sk = skb->sk; | ||
174 | bool pass = false; | ||
175 | |||
176 | /* We take the more conservative approach and | ||
177 | * whitelist socket protocols that may pass. | ||
178 | */ | ||
179 | switch (sk->sk_protocol) { | ||
180 | case NETLINK_ROUTE: | ||
181 | case NETLINK_USERSOCK: | ||
182 | case NETLINK_SOCK_DIAG: | ||
183 | case NETLINK_NFLOG: | ||
184 | case NETLINK_XFRM: | ||
185 | case NETLINK_FIB_LOOKUP: | ||
186 | case NETLINK_NETFILTER: | ||
187 | case NETLINK_GENERIC: | ||
188 | pass = true; | ||
189 | break; | ||
190 | } | ||
191 | |||
192 | return pass; | ||
193 | } | ||
194 | |||
171 | static int __netlink_deliver_tap_skb(struct sk_buff *skb, | 195 | static int __netlink_deliver_tap_skb(struct sk_buff *skb, |
172 | struct net_device *dev) | 196 | struct net_device *dev) |
173 | { | 197 | { |
174 | struct sk_buff *nskb; | 198 | struct sk_buff *nskb; |
199 | struct sock *sk = skb->sk; | ||
175 | int ret = -ENOMEM; | 200 | int ret = -ENOMEM; |
176 | 201 | ||
177 | dev_hold(dev); | 202 | dev_hold(dev); |
178 | nskb = skb_clone(skb, GFP_ATOMIC); | 203 | nskb = skb_clone(skb, GFP_ATOMIC); |
179 | if (nskb) { | 204 | if (nskb) { |
180 | nskb->dev = dev; | 205 | nskb->dev = dev; |
206 | nskb->protocol = htons((u16) sk->sk_protocol); | ||
207 | |||
181 | ret = dev_queue_xmit(nskb); | 208 | ret = dev_queue_xmit(nskb); |
182 | if (unlikely(ret > 0)) | 209 | if (unlikely(ret > 0)) |
183 | ret = net_xmit_errno(ret); | 210 | ret = net_xmit_errno(ret); |
@@ -192,6 +219,9 @@ static void __netlink_deliver_tap(struct sk_buff *skb) | |||
192 | int ret; | 219 | int ret; |
193 | struct netlink_tap *tmp; | 220 | struct netlink_tap *tmp; |
194 | 221 | ||
222 | if (!netlink_filter_tap(skb)) | ||
223 | return; | ||
224 | |||
195 | list_for_each_entry_rcu(tmp, &netlink_tap_all, list) { | 225 | list_for_each_entry_rcu(tmp, &netlink_tap_all, list) { |
196 | ret = __netlink_deliver_tap_skb(skb, tmp->dev); | 226 | ret = __netlink_deliver_tap_skb(skb, tmp->dev); |
197 | if (unlikely(ret)) | 227 | if (unlikely(ret)) |
diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c index fb36f8565161..410db90db73d 100644 --- a/net/openvswitch/flow.c +++ b/net/openvswitch/flow.c | |||
@@ -1178,6 +1178,7 @@ static int __parse_flow_nlattrs(const struct nlattr *attr, | |||
1178 | if (type > OVS_KEY_ATTR_MAX) { | 1178 | if (type > OVS_KEY_ATTR_MAX) { |
1179 | OVS_NLERR("Unknown key attribute (type=%d, max=%d).\n", | 1179 | OVS_NLERR("Unknown key attribute (type=%d, max=%d).\n", |
1180 | type, OVS_KEY_ATTR_MAX); | 1180 | type, OVS_KEY_ATTR_MAX); |
1181 | return -EINVAL; | ||
1181 | } | 1182 | } |
1182 | 1183 | ||
1183 | if (attrs & (1 << type)) { | 1184 | if (attrs & (1 << type)) { |
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c index c2178b15ca6e..863846cc5513 100644 --- a/net/sched/sch_htb.c +++ b/net/sched/sch_htb.c | |||
@@ -1495,7 +1495,7 @@ static int htb_change_class(struct Qdisc *sch, u32 classid, | |||
1495 | psched_ratecfg_precompute(&cl->ceil, &hopt->ceil); | 1495 | psched_ratecfg_precompute(&cl->ceil, &hopt->ceil); |
1496 | 1496 | ||
1497 | cl->buffer = PSCHED_TICKS2NS(hopt->buffer); | 1497 | cl->buffer = PSCHED_TICKS2NS(hopt->buffer); |
1498 | cl->cbuffer = PSCHED_TICKS2NS(hopt->buffer); | 1498 | cl->cbuffer = PSCHED_TICKS2NS(hopt->cbuffer); |
1499 | 1499 | ||
1500 | sch_tree_unlock(sch); | 1500 | sch_tree_unlock(sch); |
1501 | 1501 | ||
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index d5d5882a2891..911b71b26b0e 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -806,6 +806,9 @@ static int sctp_send_asconf_del_ip(struct sock *sk, | |||
806 | goto skip_mkasconf; | 806 | goto skip_mkasconf; |
807 | } | 807 | } |
808 | 808 | ||
809 | if (laddr == NULL) | ||
810 | return -EINVAL; | ||
811 | |||
809 | /* We do not need RCU protection throughout this loop | 812 | /* We do not need RCU protection throughout this loop |
810 | * because this is done under a socket lock from the | 813 | * because this is done under a socket lock from the |
811 | * setsockopt call. | 814 | * setsockopt call. |
@@ -6176,7 +6179,7 @@ unsigned int sctp_poll(struct file *file, struct socket *sock, poll_table *wait) | |||
6176 | /* Is there any exceptional events? */ | 6179 | /* Is there any exceptional events? */ |
6177 | if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue)) | 6180 | if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue)) |
6178 | mask |= POLLERR | | 6181 | mask |= POLLERR | |
6179 | sock_flag(sk, SOCK_SELECT_ERR_QUEUE) ? POLLPRI : 0; | 6182 | (sock_flag(sk, SOCK_SELECT_ERR_QUEUE) ? POLLPRI : 0); |
6180 | if (sk->sk_shutdown & RCV_SHUTDOWN) | 6183 | if (sk->sk_shutdown & RCV_SHUTDOWN) |
6181 | mask |= POLLRDHUP | POLLIN | POLLRDNORM; | 6184 | mask |= POLLRDHUP | POLLIN | POLLRDNORM; |
6182 | if (sk->sk_shutdown == SHUTDOWN_MASK) | 6185 | if (sk->sk_shutdown == SHUTDOWN_MASK) |
diff --git a/net/socket.c b/net/socket.c index b2d7c629eeb9..ebed4b68f768 100644 --- a/net/socket.c +++ b/net/socket.c | |||
@@ -854,11 +854,6 @@ int kernel_recvmsg(struct socket *sock, struct msghdr *msg, | |||
854 | } | 854 | } |
855 | EXPORT_SYMBOL(kernel_recvmsg); | 855 | EXPORT_SYMBOL(kernel_recvmsg); |
856 | 856 | ||
857 | static void sock_aio_dtor(struct kiocb *iocb) | ||
858 | { | ||
859 | kfree(iocb->private); | ||
860 | } | ||
861 | |||
862 | static ssize_t sock_sendpage(struct file *file, struct page *page, | 857 | static ssize_t sock_sendpage(struct file *file, struct page *page, |
863 | int offset, size_t size, loff_t *ppos, int more) | 858 | int offset, size_t size, loff_t *ppos, int more) |
864 | { | 859 | { |
@@ -889,12 +884,8 @@ static ssize_t sock_splice_read(struct file *file, loff_t *ppos, | |||
889 | static struct sock_iocb *alloc_sock_iocb(struct kiocb *iocb, | 884 | static struct sock_iocb *alloc_sock_iocb(struct kiocb *iocb, |
890 | struct sock_iocb *siocb) | 885 | struct sock_iocb *siocb) |
891 | { | 886 | { |
892 | if (!is_sync_kiocb(iocb)) { | 887 | if (!is_sync_kiocb(iocb)) |
893 | siocb = kmalloc(sizeof(*siocb), GFP_KERNEL); | 888 | BUG(); |
894 | if (!siocb) | ||
895 | return NULL; | ||
896 | iocb->ki_dtor = sock_aio_dtor; | ||
897 | } | ||
898 | 889 | ||
899 | siocb->kiocb = iocb; | 890 | siocb->kiocb = iocb; |
900 | iocb->private = siocb; | 891 | iocb->private = siocb; |
@@ -931,7 +922,7 @@ static ssize_t sock_aio_read(struct kiocb *iocb, const struct iovec *iov, | |||
931 | if (pos != 0) | 922 | if (pos != 0) |
932 | return -ESPIPE; | 923 | return -ESPIPE; |
933 | 924 | ||
934 | if (iocb->ki_left == 0) /* Match SYS5 behaviour */ | 925 | if (iocb->ki_nbytes == 0) /* Match SYS5 behaviour */ |
935 | return 0; | 926 | return 0; |
936 | 927 | ||
937 | 928 | ||
@@ -3072,12 +3063,12 @@ static int compat_sioc_ifmap(struct net *net, unsigned int cmd, | |||
3072 | 3063 | ||
3073 | uifmap32 = &uifr32->ifr_ifru.ifru_map; | 3064 | uifmap32 = &uifr32->ifr_ifru.ifru_map; |
3074 | err = copy_from_user(&ifr, uifr32, sizeof(ifr.ifr_name)); | 3065 | err = copy_from_user(&ifr, uifr32, sizeof(ifr.ifr_name)); |
3075 | err |= __get_user(ifr.ifr_map.mem_start, &uifmap32->mem_start); | 3066 | err |= get_user(ifr.ifr_map.mem_start, &uifmap32->mem_start); |
3076 | err |= __get_user(ifr.ifr_map.mem_end, &uifmap32->mem_end); | 3067 | err |= get_user(ifr.ifr_map.mem_end, &uifmap32->mem_end); |
3077 | err |= __get_user(ifr.ifr_map.base_addr, &uifmap32->base_addr); | 3068 | err |= get_user(ifr.ifr_map.base_addr, &uifmap32->base_addr); |
3078 | err |= __get_user(ifr.ifr_map.irq, &uifmap32->irq); | 3069 | err |= get_user(ifr.ifr_map.irq, &uifmap32->irq); |
3079 | err |= __get_user(ifr.ifr_map.dma, &uifmap32->dma); | 3070 | err |= get_user(ifr.ifr_map.dma, &uifmap32->dma); |
3080 | err |= __get_user(ifr.ifr_map.port, &uifmap32->port); | 3071 | err |= get_user(ifr.ifr_map.port, &uifmap32->port); |
3081 | if (err) | 3072 | if (err) |
3082 | return -EFAULT; | 3073 | return -EFAULT; |
3083 | 3074 | ||
@@ -3088,12 +3079,12 @@ static int compat_sioc_ifmap(struct net *net, unsigned int cmd, | |||
3088 | 3079 | ||
3089 | if (cmd == SIOCGIFMAP && !err) { | 3080 | if (cmd == SIOCGIFMAP && !err) { |
3090 | err = copy_to_user(uifr32, &ifr, sizeof(ifr.ifr_name)); | 3081 | err = copy_to_user(uifr32, &ifr, sizeof(ifr.ifr_name)); |
3091 | err |= __put_user(ifr.ifr_map.mem_start, &uifmap32->mem_start); | 3082 | err |= put_user(ifr.ifr_map.mem_start, &uifmap32->mem_start); |
3092 | err |= __put_user(ifr.ifr_map.mem_end, &uifmap32->mem_end); | 3083 | err |= put_user(ifr.ifr_map.mem_end, &uifmap32->mem_end); |
3093 | err |= __put_user(ifr.ifr_map.base_addr, &uifmap32->base_addr); | 3084 | err |= put_user(ifr.ifr_map.base_addr, &uifmap32->base_addr); |
3094 | err |= __put_user(ifr.ifr_map.irq, &uifmap32->irq); | 3085 | err |= put_user(ifr.ifr_map.irq, &uifmap32->irq); |
3095 | err |= __put_user(ifr.ifr_map.dma, &uifmap32->dma); | 3086 | err |= put_user(ifr.ifr_map.dma, &uifmap32->dma); |
3096 | err |= __put_user(ifr.ifr_map.port, &uifmap32->port); | 3087 | err |= put_user(ifr.ifr_map.port, &uifmap32->port); |
3097 | if (err) | 3088 | if (err) |
3098 | err = -EFAULT; | 3089 | err = -EFAULT; |
3099 | } | 3090 | } |
@@ -3167,25 +3158,25 @@ static int routing_ioctl(struct net *net, struct socket *sock, | |||
3167 | struct in6_rtmsg32 __user *ur6 = argp; | 3158 | struct in6_rtmsg32 __user *ur6 = argp; |
3168 | ret = copy_from_user(&r6.rtmsg_dst, &(ur6->rtmsg_dst), | 3159 | ret = copy_from_user(&r6.rtmsg_dst, &(ur6->rtmsg_dst), |
3169 | 3 * sizeof(struct in6_addr)); | 3160 | 3 * sizeof(struct in6_addr)); |
3170 | ret |= __get_user(r6.rtmsg_type, &(ur6->rtmsg_type)); | 3161 | ret |= get_user(r6.rtmsg_type, &(ur6->rtmsg_type)); |
3171 | ret |= __get_user(r6.rtmsg_dst_len, &(ur6->rtmsg_dst_len)); | 3162 | ret |= get_user(r6.rtmsg_dst_len, &(ur6->rtmsg_dst_len)); |
3172 | ret |= __get_user(r6.rtmsg_src_len, &(ur6->rtmsg_src_len)); | 3163 | ret |= get_user(r6.rtmsg_src_len, &(ur6->rtmsg_src_len)); |
3173 | ret |= __get_user(r6.rtmsg_metric, &(ur6->rtmsg_metric)); | 3164 | ret |= get_user(r6.rtmsg_metric, &(ur6->rtmsg_metric)); |
3174 | ret |= __get_user(r6.rtmsg_info, &(ur6->rtmsg_info)); | 3165 | ret |= get_user(r6.rtmsg_info, &(ur6->rtmsg_info)); |
3175 | ret |= __get_user(r6.rtmsg_flags, &(ur6->rtmsg_flags)); | 3166 | ret |= get_user(r6.rtmsg_flags, &(ur6->rtmsg_flags)); |
3176 | ret |= __get_user(r6.rtmsg_ifindex, &(ur6->rtmsg_ifindex)); | 3167 | ret |= get_user(r6.rtmsg_ifindex, &(ur6->rtmsg_ifindex)); |
3177 | 3168 | ||
3178 | r = (void *) &r6; | 3169 | r = (void *) &r6; |
3179 | } else { /* ipv4 */ | 3170 | } else { /* ipv4 */ |
3180 | struct rtentry32 __user *ur4 = argp; | 3171 | struct rtentry32 __user *ur4 = argp; |
3181 | ret = copy_from_user(&r4.rt_dst, &(ur4->rt_dst), | 3172 | ret = copy_from_user(&r4.rt_dst, &(ur4->rt_dst), |
3182 | 3 * sizeof(struct sockaddr)); | 3173 | 3 * sizeof(struct sockaddr)); |
3183 | ret |= __get_user(r4.rt_flags, &(ur4->rt_flags)); | 3174 | ret |= get_user(r4.rt_flags, &(ur4->rt_flags)); |
3184 | ret |= __get_user(r4.rt_metric, &(ur4->rt_metric)); | 3175 | ret |= get_user(r4.rt_metric, &(ur4->rt_metric)); |
3185 | ret |= __get_user(r4.rt_mtu, &(ur4->rt_mtu)); | 3176 | ret |= get_user(r4.rt_mtu, &(ur4->rt_mtu)); |
3186 | ret |= __get_user(r4.rt_window, &(ur4->rt_window)); | 3177 | ret |= get_user(r4.rt_window, &(ur4->rt_window)); |
3187 | ret |= __get_user(r4.rt_irtt, &(ur4->rt_irtt)); | 3178 | ret |= get_user(r4.rt_irtt, &(ur4->rt_irtt)); |
3188 | ret |= __get_user(rtdev, &(ur4->rt_dev)); | 3179 | ret |= get_user(rtdev, &(ur4->rt_dev)); |
3189 | if (rtdev) { | 3180 | if (rtdev) { |
3190 | ret |= copy_from_user(devname, compat_ptr(rtdev), 15); | 3181 | ret |= copy_from_user(devname, compat_ptr(rtdev), 15); |
3191 | r4.rt_dev = (char __user __force *)devname; | 3182 | r4.rt_dev = (char __user __force *)devname; |
diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c index ed2fdd210c0b..5285ead196c0 100644 --- a/net/sunrpc/auth.c +++ b/net/sunrpc/auth.c | |||
@@ -250,11 +250,11 @@ rpcauth_list_flavors(rpc_authflavor_t *array, int size) | |||
250 | EXPORT_SYMBOL_GPL(rpcauth_list_flavors); | 250 | EXPORT_SYMBOL_GPL(rpcauth_list_flavors); |
251 | 251 | ||
252 | struct rpc_auth * | 252 | struct rpc_auth * |
253 | rpcauth_create(rpc_authflavor_t pseudoflavor, struct rpc_clnt *clnt) | 253 | rpcauth_create(struct rpc_auth_create_args *args, struct rpc_clnt *clnt) |
254 | { | 254 | { |
255 | struct rpc_auth *auth; | 255 | struct rpc_auth *auth; |
256 | const struct rpc_authops *ops; | 256 | const struct rpc_authops *ops; |
257 | u32 flavor = pseudoflavor_to_flavor(pseudoflavor); | 257 | u32 flavor = pseudoflavor_to_flavor(args->pseudoflavor); |
258 | 258 | ||
259 | auth = ERR_PTR(-EINVAL); | 259 | auth = ERR_PTR(-EINVAL); |
260 | if (flavor >= RPC_AUTH_MAXFLAVOR) | 260 | if (flavor >= RPC_AUTH_MAXFLAVOR) |
@@ -269,7 +269,7 @@ rpcauth_create(rpc_authflavor_t pseudoflavor, struct rpc_clnt *clnt) | |||
269 | goto out; | 269 | goto out; |
270 | } | 270 | } |
271 | spin_unlock(&rpc_authflavor_lock); | 271 | spin_unlock(&rpc_authflavor_lock); |
272 | auth = ops->create(clnt, pseudoflavor); | 272 | auth = ops->create(args, clnt); |
273 | module_put(ops->owner); | 273 | module_put(ops->owner); |
274 | if (IS_ERR(auth)) | 274 | if (IS_ERR(auth)) |
275 | return auth; | 275 | return auth; |
@@ -343,6 +343,27 @@ out_nocache: | |||
343 | EXPORT_SYMBOL_GPL(rpcauth_init_credcache); | 343 | EXPORT_SYMBOL_GPL(rpcauth_init_credcache); |
344 | 344 | ||
345 | /* | 345 | /* |
346 | * Setup a credential key lifetime timeout notification | ||
347 | */ | ||
348 | int | ||
349 | rpcauth_key_timeout_notify(struct rpc_auth *auth, struct rpc_cred *cred) | ||
350 | { | ||
351 | if (!cred->cr_auth->au_ops->key_timeout) | ||
352 | return 0; | ||
353 | return cred->cr_auth->au_ops->key_timeout(auth, cred); | ||
354 | } | ||
355 | EXPORT_SYMBOL_GPL(rpcauth_key_timeout_notify); | ||
356 | |||
357 | bool | ||
358 | rpcauth_cred_key_to_expire(struct rpc_cred *cred) | ||
359 | { | ||
360 | if (!cred->cr_ops->crkey_to_expire) | ||
361 | return false; | ||
362 | return cred->cr_ops->crkey_to_expire(cred); | ||
363 | } | ||
364 | EXPORT_SYMBOL_GPL(rpcauth_cred_key_to_expire); | ||
365 | |||
366 | /* | ||
346 | * Destroy a list of credentials | 367 | * Destroy a list of credentials |
347 | */ | 368 | */ |
348 | static inline | 369 | static inline |
@@ -413,12 +434,13 @@ EXPORT_SYMBOL_GPL(rpcauth_destroy_credcache); | |||
413 | /* | 434 | /* |
414 | * Remove stale credentials. Avoid sleeping inside the loop. | 435 | * Remove stale credentials. Avoid sleeping inside the loop. |
415 | */ | 436 | */ |
416 | static int | 437 | static long |
417 | rpcauth_prune_expired(struct list_head *free, int nr_to_scan) | 438 | rpcauth_prune_expired(struct list_head *free, int nr_to_scan) |
418 | { | 439 | { |
419 | spinlock_t *cache_lock; | 440 | spinlock_t *cache_lock; |
420 | struct rpc_cred *cred, *next; | 441 | struct rpc_cred *cred, *next; |
421 | unsigned long expired = jiffies - RPC_AUTH_EXPIRY_MORATORIUM; | 442 | unsigned long expired = jiffies - RPC_AUTH_EXPIRY_MORATORIUM; |
443 | long freed = 0; | ||
422 | 444 | ||
423 | list_for_each_entry_safe(cred, next, &cred_unused, cr_lru) { | 445 | list_for_each_entry_safe(cred, next, &cred_unused, cr_lru) { |
424 | 446 | ||
@@ -430,10 +452,11 @@ rpcauth_prune_expired(struct list_head *free, int nr_to_scan) | |||
430 | */ | 452 | */ |
431 | if (time_in_range(cred->cr_expire, expired, jiffies) && | 453 | if (time_in_range(cred->cr_expire, expired, jiffies) && |
432 | test_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags) != 0) | 454 | test_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags) != 0) |
433 | return 0; | 455 | break; |
434 | 456 | ||
435 | list_del_init(&cred->cr_lru); | 457 | list_del_init(&cred->cr_lru); |
436 | number_cred_unused--; | 458 | number_cred_unused--; |
459 | freed++; | ||
437 | if (atomic_read(&cred->cr_count) != 0) | 460 | if (atomic_read(&cred->cr_count) != 0) |
438 | continue; | 461 | continue; |
439 | 462 | ||
@@ -446,29 +469,39 @@ rpcauth_prune_expired(struct list_head *free, int nr_to_scan) | |||
446 | } | 469 | } |
447 | spin_unlock(cache_lock); | 470 | spin_unlock(cache_lock); |
448 | } | 471 | } |
449 | return (number_cred_unused / 100) * sysctl_vfs_cache_pressure; | 472 | return freed; |
450 | } | 473 | } |
451 | 474 | ||
452 | /* | 475 | /* |
453 | * Run memory cache shrinker. | 476 | * Run memory cache shrinker. |
454 | */ | 477 | */ |
455 | static int | 478 | static unsigned long |
456 | rpcauth_cache_shrinker(struct shrinker *shrink, struct shrink_control *sc) | 479 | rpcauth_cache_shrink_scan(struct shrinker *shrink, struct shrink_control *sc) |
480 | |||
457 | { | 481 | { |
458 | LIST_HEAD(free); | 482 | LIST_HEAD(free); |
459 | int res; | 483 | unsigned long freed; |
460 | int nr_to_scan = sc->nr_to_scan; | ||
461 | gfp_t gfp_mask = sc->gfp_mask; | ||
462 | 484 | ||
463 | if ((gfp_mask & GFP_KERNEL) != GFP_KERNEL) | 485 | if ((sc->gfp_mask & GFP_KERNEL) != GFP_KERNEL) |
464 | return (nr_to_scan == 0) ? 0 : -1; | 486 | return SHRINK_STOP; |
487 | |||
488 | /* nothing left, don't come back */ | ||
465 | if (list_empty(&cred_unused)) | 489 | if (list_empty(&cred_unused)) |
466 | return 0; | 490 | return SHRINK_STOP; |
491 | |||
467 | spin_lock(&rpc_credcache_lock); | 492 | spin_lock(&rpc_credcache_lock); |
468 | res = rpcauth_prune_expired(&free, nr_to_scan); | 493 | freed = rpcauth_prune_expired(&free, sc->nr_to_scan); |
469 | spin_unlock(&rpc_credcache_lock); | 494 | spin_unlock(&rpc_credcache_lock); |
470 | rpcauth_destroy_credlist(&free); | 495 | rpcauth_destroy_credlist(&free); |
471 | return res; | 496 | |
497 | return freed; | ||
498 | } | ||
499 | |||
500 | static unsigned long | ||
501 | rpcauth_cache_shrink_count(struct shrinker *shrink, struct shrink_control *sc) | ||
502 | |||
503 | { | ||
504 | return (number_cred_unused / 100) * sysctl_vfs_cache_pressure; | ||
472 | } | 505 | } |
473 | 506 | ||
474 | /* | 507 | /* |
@@ -784,7 +817,8 @@ rpcauth_uptodatecred(struct rpc_task *task) | |||
784 | } | 817 | } |
785 | 818 | ||
786 | static struct shrinker rpc_cred_shrinker = { | 819 | static struct shrinker rpc_cred_shrinker = { |
787 | .shrink = rpcauth_cache_shrinker, | 820 | .count_objects = rpcauth_cache_shrink_count, |
821 | .scan_objects = rpcauth_cache_shrink_scan, | ||
788 | .seeks = DEFAULT_SEEKS, | 822 | .seeks = DEFAULT_SEEKS, |
789 | }; | 823 | }; |
790 | 824 | ||
diff --git a/net/sunrpc/auth_generic.c b/net/sunrpc/auth_generic.c index b6badafc6494..ed04869b2d4f 100644 --- a/net/sunrpc/auth_generic.c +++ b/net/sunrpc/auth_generic.c | |||
@@ -89,6 +89,7 @@ generic_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags) | |||
89 | gcred->acred.uid = acred->uid; | 89 | gcred->acred.uid = acred->uid; |
90 | gcred->acred.gid = acred->gid; | 90 | gcred->acred.gid = acred->gid; |
91 | gcred->acred.group_info = acred->group_info; | 91 | gcred->acred.group_info = acred->group_info; |
92 | gcred->acred.ac_flags = 0; | ||
92 | if (gcred->acred.group_info != NULL) | 93 | if (gcred->acred.group_info != NULL) |
93 | get_group_info(gcred->acred.group_info); | 94 | get_group_info(gcred->acred.group_info); |
94 | gcred->acred.machine_cred = acred->machine_cred; | 95 | gcred->acred.machine_cred = acred->machine_cred; |
@@ -182,11 +183,78 @@ void rpc_destroy_generic_auth(void) | |||
182 | rpcauth_destroy_credcache(&generic_auth); | 183 | rpcauth_destroy_credcache(&generic_auth); |
183 | } | 184 | } |
184 | 185 | ||
186 | /* | ||
187 | * Test the the current time (now) against the underlying credential key expiry | ||
188 | * minus a timeout and setup notification. | ||
189 | * | ||
190 | * The normal case: | ||
191 | * If 'now' is before the key expiry minus RPC_KEY_EXPIRE_TIMEO, set | ||
192 | * the RPC_CRED_NOTIFY_TIMEOUT flag to setup the underlying credential | ||
193 | * rpc_credops crmatch routine to notify this generic cred when it's key | ||
194 | * expiration is within RPC_KEY_EXPIRE_TIMEO, and return 0. | ||
195 | * | ||
196 | * The error case: | ||
197 | * If the underlying cred lookup fails, return -EACCES. | ||
198 | * | ||
199 | * The 'almost' error case: | ||
200 | * If 'now' is within key expiry minus RPC_KEY_EXPIRE_TIMEO, but not within | ||
201 | * key expiry minus RPC_KEY_EXPIRE_FAIL, set the RPC_CRED_EXPIRE_SOON bit | ||
202 | * on the acred ac_flags and return 0. | ||
203 | */ | ||
204 | static int | ||
205 | generic_key_timeout(struct rpc_auth *auth, struct rpc_cred *cred) | ||
206 | { | ||
207 | struct auth_cred *acred = &container_of(cred, struct generic_cred, | ||
208 | gc_base)->acred; | ||
209 | struct rpc_cred *tcred; | ||
210 | int ret = 0; | ||
211 | |||
212 | |||
213 | /* Fast track for non crkey_timeout (no key) underlying credentials */ | ||
214 | if (test_bit(RPC_CRED_NO_CRKEY_TIMEOUT, &acred->ac_flags)) | ||
215 | return 0; | ||
216 | |||
217 | /* Fast track for the normal case */ | ||
218 | if (test_bit(RPC_CRED_NOTIFY_TIMEOUT, &acred->ac_flags)) | ||
219 | return 0; | ||
220 | |||
221 | /* lookup_cred either returns a valid referenced rpc_cred, or PTR_ERR */ | ||
222 | tcred = auth->au_ops->lookup_cred(auth, acred, 0); | ||
223 | if (IS_ERR(tcred)) | ||
224 | return -EACCES; | ||
225 | |||
226 | if (!tcred->cr_ops->crkey_timeout) { | ||
227 | set_bit(RPC_CRED_NO_CRKEY_TIMEOUT, &acred->ac_flags); | ||
228 | ret = 0; | ||
229 | goto out_put; | ||
230 | } | ||
231 | |||
232 | /* Test for the almost error case */ | ||
233 | ret = tcred->cr_ops->crkey_timeout(tcred); | ||
234 | if (ret != 0) { | ||
235 | set_bit(RPC_CRED_KEY_EXPIRE_SOON, &acred->ac_flags); | ||
236 | ret = 0; | ||
237 | } else { | ||
238 | /* In case underlying cred key has been reset */ | ||
239 | if (test_and_clear_bit(RPC_CRED_KEY_EXPIRE_SOON, | ||
240 | &acred->ac_flags)) | ||
241 | dprintk("RPC: UID %d Credential key reset\n", | ||
242 | from_kuid(&init_user_ns, tcred->cr_uid)); | ||
243 | /* set up fasttrack for the normal case */ | ||
244 | set_bit(RPC_CRED_NOTIFY_TIMEOUT, &acred->ac_flags); | ||
245 | } | ||
246 | |||
247 | out_put: | ||
248 | put_rpccred(tcred); | ||
249 | return ret; | ||
250 | } | ||
251 | |||
185 | static const struct rpc_authops generic_auth_ops = { | 252 | static const struct rpc_authops generic_auth_ops = { |
186 | .owner = THIS_MODULE, | 253 | .owner = THIS_MODULE, |
187 | .au_name = "Generic", | 254 | .au_name = "Generic", |
188 | .lookup_cred = generic_lookup_cred, | 255 | .lookup_cred = generic_lookup_cred, |
189 | .crcreate = generic_create_cred, | 256 | .crcreate = generic_create_cred, |
257 | .key_timeout = generic_key_timeout, | ||
190 | }; | 258 | }; |
191 | 259 | ||
192 | static struct rpc_auth generic_auth = { | 260 | static struct rpc_auth generic_auth = { |
@@ -194,9 +262,23 @@ static struct rpc_auth generic_auth = { | |||
194 | .au_count = ATOMIC_INIT(0), | 262 | .au_count = ATOMIC_INIT(0), |
195 | }; | 263 | }; |
196 | 264 | ||
265 | static bool generic_key_to_expire(struct rpc_cred *cred) | ||
266 | { | ||
267 | struct auth_cred *acred = &container_of(cred, struct generic_cred, | ||
268 | gc_base)->acred; | ||
269 | bool ret; | ||
270 | |||
271 | get_rpccred(cred); | ||
272 | ret = test_bit(RPC_CRED_KEY_EXPIRE_SOON, &acred->ac_flags); | ||
273 | put_rpccred(cred); | ||
274 | |||
275 | return ret; | ||
276 | } | ||
277 | |||
197 | static const struct rpc_credops generic_credops = { | 278 | static const struct rpc_credops generic_credops = { |
198 | .cr_name = "Generic cred", | 279 | .cr_name = "Generic cred", |
199 | .crdestroy = generic_destroy_cred, | 280 | .crdestroy = generic_destroy_cred, |
200 | .crbind = generic_bind_cred, | 281 | .crbind = generic_bind_cred, |
201 | .crmatch = generic_match, | 282 | .crmatch = generic_match, |
283 | .crkey_to_expire = generic_key_to_expire, | ||
202 | }; | 284 | }; |
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index fc2f78d6a9b4..fcac5d141717 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c | |||
@@ -51,6 +51,7 @@ | |||
51 | #include <linux/sunrpc/rpc_pipe_fs.h> | 51 | #include <linux/sunrpc/rpc_pipe_fs.h> |
52 | #include <linux/sunrpc/gss_api.h> | 52 | #include <linux/sunrpc/gss_api.h> |
53 | #include <asm/uaccess.h> | 53 | #include <asm/uaccess.h> |
54 | #include <linux/hashtable.h> | ||
54 | 55 | ||
55 | #include "../netns.h" | 56 | #include "../netns.h" |
56 | 57 | ||
@@ -62,6 +63,9 @@ static const struct rpc_credops gss_nullops; | |||
62 | #define GSS_RETRY_EXPIRED 5 | 63 | #define GSS_RETRY_EXPIRED 5 |
63 | static unsigned int gss_expired_cred_retry_delay = GSS_RETRY_EXPIRED; | 64 | static unsigned int gss_expired_cred_retry_delay = GSS_RETRY_EXPIRED; |
64 | 65 | ||
66 | #define GSS_KEY_EXPIRE_TIMEO 240 | ||
67 | static unsigned int gss_key_expire_timeo = GSS_KEY_EXPIRE_TIMEO; | ||
68 | |||
65 | #ifdef RPC_DEBUG | 69 | #ifdef RPC_DEBUG |
66 | # define RPCDBG_FACILITY RPCDBG_AUTH | 70 | # define RPCDBG_FACILITY RPCDBG_AUTH |
67 | #endif | 71 | #endif |
@@ -71,19 +75,33 @@ static unsigned int gss_expired_cred_retry_delay = GSS_RETRY_EXPIRED; | |||
71 | * using integrity (two 4-byte integers): */ | 75 | * using integrity (two 4-byte integers): */ |
72 | #define GSS_VERF_SLACK 100 | 76 | #define GSS_VERF_SLACK 100 |
73 | 77 | ||
78 | static DEFINE_HASHTABLE(gss_auth_hash_table, 4); | ||
79 | static DEFINE_SPINLOCK(gss_auth_hash_lock); | ||
80 | |||
81 | struct gss_pipe { | ||
82 | struct rpc_pipe_dir_object pdo; | ||
83 | struct rpc_pipe *pipe; | ||
84 | struct rpc_clnt *clnt; | ||
85 | const char *name; | ||
86 | struct kref kref; | ||
87 | }; | ||
88 | |||
74 | struct gss_auth { | 89 | struct gss_auth { |
75 | struct kref kref; | 90 | struct kref kref; |
91 | struct hlist_node hash; | ||
76 | struct rpc_auth rpc_auth; | 92 | struct rpc_auth rpc_auth; |
77 | struct gss_api_mech *mech; | 93 | struct gss_api_mech *mech; |
78 | enum rpc_gss_svc service; | 94 | enum rpc_gss_svc service; |
79 | struct rpc_clnt *client; | 95 | struct rpc_clnt *client; |
96 | struct net *net; | ||
80 | /* | 97 | /* |
81 | * There are two upcall pipes; dentry[1], named "gssd", is used | 98 | * There are two upcall pipes; dentry[1], named "gssd", is used |
82 | * for the new text-based upcall; dentry[0] is named after the | 99 | * for the new text-based upcall; dentry[0] is named after the |
83 | * mechanism (for example, "krb5") and exists for | 100 | * mechanism (for example, "krb5") and exists for |
84 | * backwards-compatibility with older gssd's. | 101 | * backwards-compatibility with older gssd's. |
85 | */ | 102 | */ |
86 | struct rpc_pipe *pipe[2]; | 103 | struct gss_pipe *gss_pipe[2]; |
104 | const char *target_name; | ||
87 | }; | 105 | }; |
88 | 106 | ||
89 | /* pipe_version >= 0 if and only if someone has a pipe open. */ | 107 | /* pipe_version >= 0 if and only if someone has a pipe open. */ |
@@ -294,7 +312,7 @@ static void put_pipe_version(struct net *net) | |||
294 | static void | 312 | static void |
295 | gss_release_msg(struct gss_upcall_msg *gss_msg) | 313 | gss_release_msg(struct gss_upcall_msg *gss_msg) |
296 | { | 314 | { |
297 | struct net *net = rpc_net_ns(gss_msg->auth->client); | 315 | struct net *net = gss_msg->auth->net; |
298 | if (!atomic_dec_and_test(&gss_msg->count)) | 316 | if (!atomic_dec_and_test(&gss_msg->count)) |
299 | return; | 317 | return; |
300 | put_pipe_version(net); | 318 | put_pipe_version(net); |
@@ -406,8 +424,8 @@ static void gss_encode_v0_msg(struct gss_upcall_msg *gss_msg) | |||
406 | } | 424 | } |
407 | 425 | ||
408 | static void gss_encode_v1_msg(struct gss_upcall_msg *gss_msg, | 426 | static void gss_encode_v1_msg(struct gss_upcall_msg *gss_msg, |
409 | struct rpc_clnt *clnt, | 427 | const char *service_name, |
410 | const char *service_name) | 428 | const char *target_name) |
411 | { | 429 | { |
412 | struct gss_api_mech *mech = gss_msg->auth->mech; | 430 | struct gss_api_mech *mech = gss_msg->auth->mech; |
413 | char *p = gss_msg->databuf; | 431 | char *p = gss_msg->databuf; |
@@ -417,8 +435,8 @@ static void gss_encode_v1_msg(struct gss_upcall_msg *gss_msg, | |||
417 | mech->gm_name, | 435 | mech->gm_name, |
418 | from_kuid(&init_user_ns, gss_msg->uid)); | 436 | from_kuid(&init_user_ns, gss_msg->uid)); |
419 | p += gss_msg->msg.len; | 437 | p += gss_msg->msg.len; |
420 | if (clnt->cl_principal) { | 438 | if (target_name) { |
421 | len = sprintf(p, "target=%s ", clnt->cl_principal); | 439 | len = sprintf(p, "target=%s ", target_name); |
422 | p += len; | 440 | p += len; |
423 | gss_msg->msg.len += len; | 441 | gss_msg->msg.len += len; |
424 | } | 442 | } |
@@ -439,21 +457,8 @@ static void gss_encode_v1_msg(struct gss_upcall_msg *gss_msg, | |||
439 | BUG_ON(gss_msg->msg.len > UPCALL_BUF_LEN); | 457 | BUG_ON(gss_msg->msg.len > UPCALL_BUF_LEN); |
440 | } | 458 | } |
441 | 459 | ||
442 | static void gss_encode_msg(struct gss_upcall_msg *gss_msg, | ||
443 | struct rpc_clnt *clnt, | ||
444 | const char *service_name) | ||
445 | { | ||
446 | struct net *net = rpc_net_ns(clnt); | ||
447 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
448 | |||
449 | if (sn->pipe_version == 0) | ||
450 | gss_encode_v0_msg(gss_msg); | ||
451 | else /* pipe_version == 1 */ | ||
452 | gss_encode_v1_msg(gss_msg, clnt, service_name); | ||
453 | } | ||
454 | |||
455 | static struct gss_upcall_msg * | 460 | static struct gss_upcall_msg * |
456 | gss_alloc_msg(struct gss_auth *gss_auth, struct rpc_clnt *clnt, | 461 | gss_alloc_msg(struct gss_auth *gss_auth, |
457 | kuid_t uid, const char *service_name) | 462 | kuid_t uid, const char *service_name) |
458 | { | 463 | { |
459 | struct gss_upcall_msg *gss_msg; | 464 | struct gss_upcall_msg *gss_msg; |
@@ -462,31 +467,36 @@ gss_alloc_msg(struct gss_auth *gss_auth, struct rpc_clnt *clnt, | |||
462 | gss_msg = kzalloc(sizeof(*gss_msg), GFP_NOFS); | 467 | gss_msg = kzalloc(sizeof(*gss_msg), GFP_NOFS); |
463 | if (gss_msg == NULL) | 468 | if (gss_msg == NULL) |
464 | return ERR_PTR(-ENOMEM); | 469 | return ERR_PTR(-ENOMEM); |
465 | vers = get_pipe_version(rpc_net_ns(clnt)); | 470 | vers = get_pipe_version(gss_auth->net); |
466 | if (vers < 0) { | 471 | if (vers < 0) { |
467 | kfree(gss_msg); | 472 | kfree(gss_msg); |
468 | return ERR_PTR(vers); | 473 | return ERR_PTR(vers); |
469 | } | 474 | } |
470 | gss_msg->pipe = gss_auth->pipe[vers]; | 475 | gss_msg->pipe = gss_auth->gss_pipe[vers]->pipe; |
471 | INIT_LIST_HEAD(&gss_msg->list); | 476 | INIT_LIST_HEAD(&gss_msg->list); |
472 | rpc_init_wait_queue(&gss_msg->rpc_waitqueue, "RPCSEC_GSS upcall waitq"); | 477 | rpc_init_wait_queue(&gss_msg->rpc_waitqueue, "RPCSEC_GSS upcall waitq"); |
473 | init_waitqueue_head(&gss_msg->waitqueue); | 478 | init_waitqueue_head(&gss_msg->waitqueue); |
474 | atomic_set(&gss_msg->count, 1); | 479 | atomic_set(&gss_msg->count, 1); |
475 | gss_msg->uid = uid; | 480 | gss_msg->uid = uid; |
476 | gss_msg->auth = gss_auth; | 481 | gss_msg->auth = gss_auth; |
477 | gss_encode_msg(gss_msg, clnt, service_name); | 482 | switch (vers) { |
483 | case 0: | ||
484 | gss_encode_v0_msg(gss_msg); | ||
485 | default: | ||
486 | gss_encode_v1_msg(gss_msg, service_name, gss_auth->target_name); | ||
487 | }; | ||
478 | return gss_msg; | 488 | return gss_msg; |
479 | } | 489 | } |
480 | 490 | ||
481 | static struct gss_upcall_msg * | 491 | static struct gss_upcall_msg * |
482 | gss_setup_upcall(struct rpc_clnt *clnt, struct gss_auth *gss_auth, struct rpc_cred *cred) | 492 | gss_setup_upcall(struct gss_auth *gss_auth, struct rpc_cred *cred) |
483 | { | 493 | { |
484 | struct gss_cred *gss_cred = container_of(cred, | 494 | struct gss_cred *gss_cred = container_of(cred, |
485 | struct gss_cred, gc_base); | 495 | struct gss_cred, gc_base); |
486 | struct gss_upcall_msg *gss_new, *gss_msg; | 496 | struct gss_upcall_msg *gss_new, *gss_msg; |
487 | kuid_t uid = cred->cr_uid; | 497 | kuid_t uid = cred->cr_uid; |
488 | 498 | ||
489 | gss_new = gss_alloc_msg(gss_auth, clnt, uid, gss_cred->gc_principal); | 499 | gss_new = gss_alloc_msg(gss_auth, uid, gss_cred->gc_principal); |
490 | if (IS_ERR(gss_new)) | 500 | if (IS_ERR(gss_new)) |
491 | return gss_new; | 501 | return gss_new; |
492 | gss_msg = gss_add_msg(gss_new); | 502 | gss_msg = gss_add_msg(gss_new); |
@@ -527,7 +537,7 @@ gss_refresh_upcall(struct rpc_task *task) | |||
527 | 537 | ||
528 | dprintk("RPC: %5u %s for uid %u\n", | 538 | dprintk("RPC: %5u %s for uid %u\n", |
529 | task->tk_pid, __func__, from_kuid(&init_user_ns, cred->cr_uid)); | 539 | task->tk_pid, __func__, from_kuid(&init_user_ns, cred->cr_uid)); |
530 | gss_msg = gss_setup_upcall(task->tk_client, gss_auth, cred); | 540 | gss_msg = gss_setup_upcall(gss_auth, cred); |
531 | if (PTR_ERR(gss_msg) == -EAGAIN) { | 541 | if (PTR_ERR(gss_msg) == -EAGAIN) { |
532 | /* XXX: warning on the first, under the assumption we | 542 | /* XXX: warning on the first, under the assumption we |
533 | * shouldn't normally hit this case on a refresh. */ | 543 | * shouldn't normally hit this case on a refresh. */ |
@@ -566,7 +576,7 @@ out: | |||
566 | static inline int | 576 | static inline int |
567 | gss_create_upcall(struct gss_auth *gss_auth, struct gss_cred *gss_cred) | 577 | gss_create_upcall(struct gss_auth *gss_auth, struct gss_cred *gss_cred) |
568 | { | 578 | { |
569 | struct net *net = rpc_net_ns(gss_auth->client); | 579 | struct net *net = gss_auth->net; |
570 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | 580 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); |
571 | struct rpc_pipe *pipe; | 581 | struct rpc_pipe *pipe; |
572 | struct rpc_cred *cred = &gss_cred->gc_base; | 582 | struct rpc_cred *cred = &gss_cred->gc_base; |
@@ -583,7 +593,7 @@ retry: | |||
583 | timeout = 15 * HZ; | 593 | timeout = 15 * HZ; |
584 | if (!sn->gssd_running) | 594 | if (!sn->gssd_running) |
585 | timeout = HZ >> 2; | 595 | timeout = HZ >> 2; |
586 | gss_msg = gss_setup_upcall(gss_auth->client, gss_auth, cred); | 596 | gss_msg = gss_setup_upcall(gss_auth, cred); |
587 | if (PTR_ERR(gss_msg) == -EAGAIN) { | 597 | if (PTR_ERR(gss_msg) == -EAGAIN) { |
588 | err = wait_event_interruptible_timeout(pipe_version_waitqueue, | 598 | err = wait_event_interruptible_timeout(pipe_version_waitqueue, |
589 | sn->pipe_version >= 0, timeout); | 599 | sn->pipe_version >= 0, timeout); |
@@ -797,83 +807,153 @@ gss_pipe_destroy_msg(struct rpc_pipe_msg *msg) | |||
797 | } | 807 | } |
798 | } | 808 | } |
799 | 809 | ||
800 | static void gss_pipes_dentries_destroy(struct rpc_auth *auth) | 810 | static void gss_pipe_dentry_destroy(struct dentry *dir, |
811 | struct rpc_pipe_dir_object *pdo) | ||
801 | { | 812 | { |
802 | struct gss_auth *gss_auth; | 813 | struct gss_pipe *gss_pipe = pdo->pdo_data; |
814 | struct rpc_pipe *pipe = gss_pipe->pipe; | ||
803 | 815 | ||
804 | gss_auth = container_of(auth, struct gss_auth, rpc_auth); | 816 | if (pipe->dentry != NULL) { |
805 | if (gss_auth->pipe[0]->dentry) | 817 | rpc_unlink(pipe->dentry); |
806 | rpc_unlink(gss_auth->pipe[0]->dentry); | 818 | pipe->dentry = NULL; |
807 | if (gss_auth->pipe[1]->dentry) | 819 | } |
808 | rpc_unlink(gss_auth->pipe[1]->dentry); | ||
809 | } | 820 | } |
810 | 821 | ||
811 | static int gss_pipes_dentries_create(struct rpc_auth *auth) | 822 | static int gss_pipe_dentry_create(struct dentry *dir, |
823 | struct rpc_pipe_dir_object *pdo) | ||
812 | { | 824 | { |
813 | int err; | 825 | struct gss_pipe *p = pdo->pdo_data; |
814 | struct gss_auth *gss_auth; | 826 | struct dentry *dentry; |
815 | struct rpc_clnt *clnt; | ||
816 | 827 | ||
817 | gss_auth = container_of(auth, struct gss_auth, rpc_auth); | 828 | dentry = rpc_mkpipe_dentry(dir, p->name, p->clnt, p->pipe); |
818 | clnt = gss_auth->client; | 829 | if (IS_ERR(dentry)) |
819 | 830 | return PTR_ERR(dentry); | |
820 | gss_auth->pipe[1]->dentry = rpc_mkpipe_dentry(clnt->cl_dentry, | 831 | p->pipe->dentry = dentry; |
821 | "gssd", | ||
822 | clnt, gss_auth->pipe[1]); | ||
823 | if (IS_ERR(gss_auth->pipe[1]->dentry)) | ||
824 | return PTR_ERR(gss_auth->pipe[1]->dentry); | ||
825 | gss_auth->pipe[0]->dentry = rpc_mkpipe_dentry(clnt->cl_dentry, | ||
826 | gss_auth->mech->gm_name, | ||
827 | clnt, gss_auth->pipe[0]); | ||
828 | if (IS_ERR(gss_auth->pipe[0]->dentry)) { | ||
829 | err = PTR_ERR(gss_auth->pipe[0]->dentry); | ||
830 | goto err_unlink_pipe_1; | ||
831 | } | ||
832 | return 0; | 832 | return 0; |
833 | } | ||
833 | 834 | ||
834 | err_unlink_pipe_1: | 835 | static const struct rpc_pipe_dir_object_ops gss_pipe_dir_object_ops = { |
835 | rpc_unlink(gss_auth->pipe[1]->dentry); | 836 | .create = gss_pipe_dentry_create, |
836 | return err; | 837 | .destroy = gss_pipe_dentry_destroy, |
838 | }; | ||
839 | |||
840 | static struct gss_pipe *gss_pipe_alloc(struct rpc_clnt *clnt, | ||
841 | const char *name, | ||
842 | const struct rpc_pipe_ops *upcall_ops) | ||
843 | { | ||
844 | struct gss_pipe *p; | ||
845 | int err = -ENOMEM; | ||
846 | |||
847 | p = kmalloc(sizeof(*p), GFP_KERNEL); | ||
848 | if (p == NULL) | ||
849 | goto err; | ||
850 | p->pipe = rpc_mkpipe_data(upcall_ops, RPC_PIPE_WAIT_FOR_OPEN); | ||
851 | if (IS_ERR(p->pipe)) { | ||
852 | err = PTR_ERR(p->pipe); | ||
853 | goto err_free_gss_pipe; | ||
854 | } | ||
855 | p->name = name; | ||
856 | p->clnt = clnt; | ||
857 | kref_init(&p->kref); | ||
858 | rpc_init_pipe_dir_object(&p->pdo, | ||
859 | &gss_pipe_dir_object_ops, | ||
860 | p); | ||
861 | return p; | ||
862 | err_free_gss_pipe: | ||
863 | kfree(p); | ||
864 | err: | ||
865 | return ERR_PTR(err); | ||
866 | } | ||
867 | |||
868 | struct gss_alloc_pdo { | ||
869 | struct rpc_clnt *clnt; | ||
870 | const char *name; | ||
871 | const struct rpc_pipe_ops *upcall_ops; | ||
872 | }; | ||
873 | |||
874 | static int gss_pipe_match_pdo(struct rpc_pipe_dir_object *pdo, void *data) | ||
875 | { | ||
876 | struct gss_pipe *gss_pipe; | ||
877 | struct gss_alloc_pdo *args = data; | ||
878 | |||
879 | if (pdo->pdo_ops != &gss_pipe_dir_object_ops) | ||
880 | return 0; | ||
881 | gss_pipe = container_of(pdo, struct gss_pipe, pdo); | ||
882 | if (strcmp(gss_pipe->name, args->name) != 0) | ||
883 | return 0; | ||
884 | if (!kref_get_unless_zero(&gss_pipe->kref)) | ||
885 | return 0; | ||
886 | return 1; | ||
837 | } | 887 | } |
838 | 888 | ||
839 | static void gss_pipes_dentries_destroy_net(struct rpc_clnt *clnt, | 889 | static struct rpc_pipe_dir_object *gss_pipe_alloc_pdo(void *data) |
840 | struct rpc_auth *auth) | 890 | { |
891 | struct gss_pipe *gss_pipe; | ||
892 | struct gss_alloc_pdo *args = data; | ||
893 | |||
894 | gss_pipe = gss_pipe_alloc(args->clnt, args->name, args->upcall_ops); | ||
895 | if (!IS_ERR(gss_pipe)) | ||
896 | return &gss_pipe->pdo; | ||
897 | return NULL; | ||
898 | } | ||
899 | |||
900 | static struct gss_pipe *gss_pipe_get(struct rpc_clnt *clnt, | ||
901 | const char *name, | ||
902 | const struct rpc_pipe_ops *upcall_ops) | ||
841 | { | 903 | { |
842 | struct net *net = rpc_net_ns(clnt); | 904 | struct net *net = rpc_net_ns(clnt); |
843 | struct super_block *sb; | 905 | struct rpc_pipe_dir_object *pdo; |
906 | struct gss_alloc_pdo args = { | ||
907 | .clnt = clnt, | ||
908 | .name = name, | ||
909 | .upcall_ops = upcall_ops, | ||
910 | }; | ||
844 | 911 | ||
845 | sb = rpc_get_sb_net(net); | 912 | pdo = rpc_find_or_alloc_pipe_dir_object(net, |
846 | if (sb) { | 913 | &clnt->cl_pipedir_objects, |
847 | if (clnt->cl_dentry) | 914 | gss_pipe_match_pdo, |
848 | gss_pipes_dentries_destroy(auth); | 915 | gss_pipe_alloc_pdo, |
849 | rpc_put_sb_net(net); | 916 | &args); |
850 | } | 917 | if (pdo != NULL) |
918 | return container_of(pdo, struct gss_pipe, pdo); | ||
919 | return ERR_PTR(-ENOMEM); | ||
851 | } | 920 | } |
852 | 921 | ||
853 | static int gss_pipes_dentries_create_net(struct rpc_clnt *clnt, | 922 | static void __gss_pipe_free(struct gss_pipe *p) |
854 | struct rpc_auth *auth) | ||
855 | { | 923 | { |
924 | struct rpc_clnt *clnt = p->clnt; | ||
856 | struct net *net = rpc_net_ns(clnt); | 925 | struct net *net = rpc_net_ns(clnt); |
857 | struct super_block *sb; | ||
858 | int err = 0; | ||
859 | 926 | ||
860 | sb = rpc_get_sb_net(net); | 927 | rpc_remove_pipe_dir_object(net, |
861 | if (sb) { | 928 | &clnt->cl_pipedir_objects, |
862 | if (clnt->cl_dentry) | 929 | &p->pdo); |
863 | err = gss_pipes_dentries_create(auth); | 930 | rpc_destroy_pipe_data(p->pipe); |
864 | rpc_put_sb_net(net); | 931 | kfree(p); |
865 | } | 932 | } |
866 | return err; | 933 | |
934 | static void __gss_pipe_release(struct kref *kref) | ||
935 | { | ||
936 | struct gss_pipe *p = container_of(kref, struct gss_pipe, kref); | ||
937 | |||
938 | __gss_pipe_free(p); | ||
939 | } | ||
940 | |||
941 | static void gss_pipe_free(struct gss_pipe *p) | ||
942 | { | ||
943 | if (p != NULL) | ||
944 | kref_put(&p->kref, __gss_pipe_release); | ||
867 | } | 945 | } |
868 | 946 | ||
869 | /* | 947 | /* |
870 | * NOTE: we have the opportunity to use different | 948 | * NOTE: we have the opportunity to use different |
871 | * parameters based on the input flavor (which must be a pseudoflavor) | 949 | * parameters based on the input flavor (which must be a pseudoflavor) |
872 | */ | 950 | */ |
873 | static struct rpc_auth * | 951 | static struct gss_auth * |
874 | gss_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor) | 952 | gss_create_new(struct rpc_auth_create_args *args, struct rpc_clnt *clnt) |
875 | { | 953 | { |
954 | rpc_authflavor_t flavor = args->pseudoflavor; | ||
876 | struct gss_auth *gss_auth; | 955 | struct gss_auth *gss_auth; |
956 | struct gss_pipe *gss_pipe; | ||
877 | struct rpc_auth * auth; | 957 | struct rpc_auth * auth; |
878 | int err = -ENOMEM; /* XXX? */ | 958 | int err = -ENOMEM; /* XXX? */ |
879 | 959 | ||
@@ -883,12 +963,20 @@ gss_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor) | |||
883 | return ERR_PTR(err); | 963 | return ERR_PTR(err); |
884 | if (!(gss_auth = kmalloc(sizeof(*gss_auth), GFP_KERNEL))) | 964 | if (!(gss_auth = kmalloc(sizeof(*gss_auth), GFP_KERNEL))) |
885 | goto out_dec; | 965 | goto out_dec; |
966 | INIT_HLIST_NODE(&gss_auth->hash); | ||
967 | gss_auth->target_name = NULL; | ||
968 | if (args->target_name) { | ||
969 | gss_auth->target_name = kstrdup(args->target_name, GFP_KERNEL); | ||
970 | if (gss_auth->target_name == NULL) | ||
971 | goto err_free; | ||
972 | } | ||
886 | gss_auth->client = clnt; | 973 | gss_auth->client = clnt; |
974 | gss_auth->net = get_net(rpc_net_ns(clnt)); | ||
887 | err = -EINVAL; | 975 | err = -EINVAL; |
888 | gss_auth->mech = gss_mech_get_by_pseudoflavor(flavor); | 976 | gss_auth->mech = gss_mech_get_by_pseudoflavor(flavor); |
889 | if (!gss_auth->mech) { | 977 | if (!gss_auth->mech) { |
890 | dprintk("RPC: Pseudoflavor %d not found!\n", flavor); | 978 | dprintk("RPC: Pseudoflavor %d not found!\n", flavor); |
891 | goto err_free; | 979 | goto err_put_net; |
892 | } | 980 | } |
893 | gss_auth->service = gss_pseudoflavor_to_service(gss_auth->mech, flavor); | 981 | gss_auth->service = gss_pseudoflavor_to_service(gss_auth->mech, flavor); |
894 | if (gss_auth->service == 0) | 982 | if (gss_auth->service == 0) |
@@ -901,42 +989,41 @@ gss_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor) | |||
901 | atomic_set(&auth->au_count, 1); | 989 | atomic_set(&auth->au_count, 1); |
902 | kref_init(&gss_auth->kref); | 990 | kref_init(&gss_auth->kref); |
903 | 991 | ||
992 | err = rpcauth_init_credcache(auth); | ||
993 | if (err) | ||
994 | goto err_put_mech; | ||
904 | /* | 995 | /* |
905 | * Note: if we created the old pipe first, then someone who | 996 | * Note: if we created the old pipe first, then someone who |
906 | * examined the directory at the right moment might conclude | 997 | * examined the directory at the right moment might conclude |
907 | * that we supported only the old pipe. So we instead create | 998 | * that we supported only the old pipe. So we instead create |
908 | * the new pipe first. | 999 | * the new pipe first. |
909 | */ | 1000 | */ |
910 | gss_auth->pipe[1] = rpc_mkpipe_data(&gss_upcall_ops_v1, | 1001 | gss_pipe = gss_pipe_get(clnt, "gssd", &gss_upcall_ops_v1); |
911 | RPC_PIPE_WAIT_FOR_OPEN); | 1002 | if (IS_ERR(gss_pipe)) { |
912 | if (IS_ERR(gss_auth->pipe[1])) { | 1003 | err = PTR_ERR(gss_pipe); |
913 | err = PTR_ERR(gss_auth->pipe[1]); | 1004 | goto err_destroy_credcache; |
914 | goto err_put_mech; | ||
915 | } | 1005 | } |
1006 | gss_auth->gss_pipe[1] = gss_pipe; | ||
916 | 1007 | ||
917 | gss_auth->pipe[0] = rpc_mkpipe_data(&gss_upcall_ops_v0, | 1008 | gss_pipe = gss_pipe_get(clnt, gss_auth->mech->gm_name, |
918 | RPC_PIPE_WAIT_FOR_OPEN); | 1009 | &gss_upcall_ops_v0); |
919 | if (IS_ERR(gss_auth->pipe[0])) { | 1010 | if (IS_ERR(gss_pipe)) { |
920 | err = PTR_ERR(gss_auth->pipe[0]); | 1011 | err = PTR_ERR(gss_pipe); |
921 | goto err_destroy_pipe_1; | 1012 | goto err_destroy_pipe_1; |
922 | } | 1013 | } |
923 | err = gss_pipes_dentries_create_net(clnt, auth); | 1014 | gss_auth->gss_pipe[0] = gss_pipe; |
924 | if (err) | ||
925 | goto err_destroy_pipe_0; | ||
926 | err = rpcauth_init_credcache(auth); | ||
927 | if (err) | ||
928 | goto err_unlink_pipes; | ||
929 | 1015 | ||
930 | return auth; | 1016 | return gss_auth; |
931 | err_unlink_pipes: | ||
932 | gss_pipes_dentries_destroy_net(clnt, auth); | ||
933 | err_destroy_pipe_0: | ||
934 | rpc_destroy_pipe_data(gss_auth->pipe[0]); | ||
935 | err_destroy_pipe_1: | 1017 | err_destroy_pipe_1: |
936 | rpc_destroy_pipe_data(gss_auth->pipe[1]); | 1018 | gss_pipe_free(gss_auth->gss_pipe[1]); |
1019 | err_destroy_credcache: | ||
1020 | rpcauth_destroy_credcache(auth); | ||
937 | err_put_mech: | 1021 | err_put_mech: |
938 | gss_mech_put(gss_auth->mech); | 1022 | gss_mech_put(gss_auth->mech); |
1023 | err_put_net: | ||
1024 | put_net(gss_auth->net); | ||
939 | err_free: | 1025 | err_free: |
1026 | kfree(gss_auth->target_name); | ||
940 | kfree(gss_auth); | 1027 | kfree(gss_auth); |
941 | out_dec: | 1028 | out_dec: |
942 | module_put(THIS_MODULE); | 1029 | module_put(THIS_MODULE); |
@@ -946,10 +1033,11 @@ out_dec: | |||
946 | static void | 1033 | static void |
947 | gss_free(struct gss_auth *gss_auth) | 1034 | gss_free(struct gss_auth *gss_auth) |
948 | { | 1035 | { |
949 | gss_pipes_dentries_destroy_net(gss_auth->client, &gss_auth->rpc_auth); | 1036 | gss_pipe_free(gss_auth->gss_pipe[0]); |
950 | rpc_destroy_pipe_data(gss_auth->pipe[0]); | 1037 | gss_pipe_free(gss_auth->gss_pipe[1]); |
951 | rpc_destroy_pipe_data(gss_auth->pipe[1]); | ||
952 | gss_mech_put(gss_auth->mech); | 1038 | gss_mech_put(gss_auth->mech); |
1039 | put_net(gss_auth->net); | ||
1040 | kfree(gss_auth->target_name); | ||
953 | 1041 | ||
954 | kfree(gss_auth); | 1042 | kfree(gss_auth); |
955 | module_put(THIS_MODULE); | 1043 | module_put(THIS_MODULE); |
@@ -966,17 +1054,101 @@ gss_free_callback(struct kref *kref) | |||
966 | static void | 1054 | static void |
967 | gss_destroy(struct rpc_auth *auth) | 1055 | gss_destroy(struct rpc_auth *auth) |
968 | { | 1056 | { |
969 | struct gss_auth *gss_auth; | 1057 | struct gss_auth *gss_auth = container_of(auth, |
1058 | struct gss_auth, rpc_auth); | ||
970 | 1059 | ||
971 | dprintk("RPC: destroying GSS authenticator %p flavor %d\n", | 1060 | dprintk("RPC: destroying GSS authenticator %p flavor %d\n", |
972 | auth, auth->au_flavor); | 1061 | auth, auth->au_flavor); |
973 | 1062 | ||
1063 | if (hash_hashed(&gss_auth->hash)) { | ||
1064 | spin_lock(&gss_auth_hash_lock); | ||
1065 | hash_del(&gss_auth->hash); | ||
1066 | spin_unlock(&gss_auth_hash_lock); | ||
1067 | } | ||
1068 | |||
1069 | gss_pipe_free(gss_auth->gss_pipe[0]); | ||
1070 | gss_auth->gss_pipe[0] = NULL; | ||
1071 | gss_pipe_free(gss_auth->gss_pipe[1]); | ||
1072 | gss_auth->gss_pipe[1] = NULL; | ||
974 | rpcauth_destroy_credcache(auth); | 1073 | rpcauth_destroy_credcache(auth); |
975 | 1074 | ||
976 | gss_auth = container_of(auth, struct gss_auth, rpc_auth); | ||
977 | kref_put(&gss_auth->kref, gss_free_callback); | 1075 | kref_put(&gss_auth->kref, gss_free_callback); |
978 | } | 1076 | } |
979 | 1077 | ||
1078 | static struct gss_auth * | ||
1079 | gss_auth_find_or_add_hashed(struct rpc_auth_create_args *args, | ||
1080 | struct rpc_clnt *clnt, | ||
1081 | struct gss_auth *new) | ||
1082 | { | ||
1083 | struct gss_auth *gss_auth; | ||
1084 | unsigned long hashval = (unsigned long)clnt; | ||
1085 | |||
1086 | spin_lock(&gss_auth_hash_lock); | ||
1087 | hash_for_each_possible(gss_auth_hash_table, | ||
1088 | gss_auth, | ||
1089 | hash, | ||
1090 | hashval) { | ||
1091 | if (gss_auth->rpc_auth.au_flavor != args->pseudoflavor) | ||
1092 | continue; | ||
1093 | if (gss_auth->target_name != args->target_name) { | ||
1094 | if (gss_auth->target_name == NULL) | ||
1095 | continue; | ||
1096 | if (args->target_name == NULL) | ||
1097 | continue; | ||
1098 | if (strcmp(gss_auth->target_name, args->target_name)) | ||
1099 | continue; | ||
1100 | } | ||
1101 | if (!atomic_inc_not_zero(&gss_auth->rpc_auth.au_count)) | ||
1102 | continue; | ||
1103 | goto out; | ||
1104 | } | ||
1105 | if (new) | ||
1106 | hash_add(gss_auth_hash_table, &new->hash, hashval); | ||
1107 | gss_auth = new; | ||
1108 | out: | ||
1109 | spin_unlock(&gss_auth_hash_lock); | ||
1110 | return gss_auth; | ||
1111 | } | ||
1112 | |||
1113 | static struct gss_auth * | ||
1114 | gss_create_hashed(struct rpc_auth_create_args *args, struct rpc_clnt *clnt) | ||
1115 | { | ||
1116 | struct gss_auth *gss_auth; | ||
1117 | struct gss_auth *new; | ||
1118 | |||
1119 | gss_auth = gss_auth_find_or_add_hashed(args, clnt, NULL); | ||
1120 | if (gss_auth != NULL) | ||
1121 | goto out; | ||
1122 | new = gss_create_new(args, clnt); | ||
1123 | if (IS_ERR(new)) | ||
1124 | return new; | ||
1125 | gss_auth = gss_auth_find_or_add_hashed(args, clnt, new); | ||
1126 | if (gss_auth != new) | ||
1127 | gss_destroy(&new->rpc_auth); | ||
1128 | out: | ||
1129 | return gss_auth; | ||
1130 | } | ||
1131 | |||
1132 | static struct rpc_auth * | ||
1133 | gss_create(struct rpc_auth_create_args *args, struct rpc_clnt *clnt) | ||
1134 | { | ||
1135 | struct gss_auth *gss_auth; | ||
1136 | struct rpc_xprt *xprt = rcu_access_pointer(clnt->cl_xprt); | ||
1137 | |||
1138 | while (clnt != clnt->cl_parent) { | ||
1139 | struct rpc_clnt *parent = clnt->cl_parent; | ||
1140 | /* Find the original parent for this transport */ | ||
1141 | if (rcu_access_pointer(parent->cl_xprt) != xprt) | ||
1142 | break; | ||
1143 | clnt = parent; | ||
1144 | } | ||
1145 | |||
1146 | gss_auth = gss_create_hashed(args, clnt); | ||
1147 | if (IS_ERR(gss_auth)) | ||
1148 | return ERR_CAST(gss_auth); | ||
1149 | return &gss_auth->rpc_auth; | ||
1150 | } | ||
1151 | |||
980 | /* | 1152 | /* |
981 | * gss_destroying_context will cause the RPCSEC_GSS to send a NULL RPC call | 1153 | * gss_destroying_context will cause the RPCSEC_GSS to send a NULL RPC call |
982 | * to the server with the GSS control procedure field set to | 1154 | * to the server with the GSS control procedure field set to |
@@ -1126,10 +1298,32 @@ gss_cred_init(struct rpc_auth *auth, struct rpc_cred *cred) | |||
1126 | return err; | 1298 | return err; |
1127 | } | 1299 | } |
1128 | 1300 | ||
1301 | /* | ||
1302 | * Returns -EACCES if GSS context is NULL or will expire within the | ||
1303 | * timeout (miliseconds) | ||
1304 | */ | ||
1305 | static int | ||
1306 | gss_key_timeout(struct rpc_cred *rc) | ||
1307 | { | ||
1308 | struct gss_cred *gss_cred = container_of(rc, struct gss_cred, gc_base); | ||
1309 | unsigned long now = jiffies; | ||
1310 | unsigned long expire; | ||
1311 | |||
1312 | if (gss_cred->gc_ctx == NULL) | ||
1313 | return -EACCES; | ||
1314 | |||
1315 | expire = gss_cred->gc_ctx->gc_expiry - (gss_key_expire_timeo * HZ); | ||
1316 | |||
1317 | if (time_after(now, expire)) | ||
1318 | return -EACCES; | ||
1319 | return 0; | ||
1320 | } | ||
1321 | |||
1129 | static int | 1322 | static int |
1130 | gss_match(struct auth_cred *acred, struct rpc_cred *rc, int flags) | 1323 | gss_match(struct auth_cred *acred, struct rpc_cred *rc, int flags) |
1131 | { | 1324 | { |
1132 | struct gss_cred *gss_cred = container_of(rc, struct gss_cred, gc_base); | 1325 | struct gss_cred *gss_cred = container_of(rc, struct gss_cred, gc_base); |
1326 | int ret; | ||
1133 | 1327 | ||
1134 | if (test_bit(RPCAUTH_CRED_NEW, &rc->cr_flags)) | 1328 | if (test_bit(RPCAUTH_CRED_NEW, &rc->cr_flags)) |
1135 | goto out; | 1329 | goto out; |
@@ -1142,11 +1336,26 @@ out: | |||
1142 | if (acred->principal != NULL) { | 1336 | if (acred->principal != NULL) { |
1143 | if (gss_cred->gc_principal == NULL) | 1337 | if (gss_cred->gc_principal == NULL) |
1144 | return 0; | 1338 | return 0; |
1145 | return strcmp(acred->principal, gss_cred->gc_principal) == 0; | 1339 | ret = strcmp(acred->principal, gss_cred->gc_principal) == 0; |
1340 | goto check_expire; | ||
1146 | } | 1341 | } |
1147 | if (gss_cred->gc_principal != NULL) | 1342 | if (gss_cred->gc_principal != NULL) |
1148 | return 0; | 1343 | return 0; |
1149 | return uid_eq(rc->cr_uid, acred->uid); | 1344 | ret = uid_eq(rc->cr_uid, acred->uid); |
1345 | |||
1346 | check_expire: | ||
1347 | if (ret == 0) | ||
1348 | return ret; | ||
1349 | |||
1350 | /* Notify acred users of GSS context expiration timeout */ | ||
1351 | if (test_bit(RPC_CRED_NOTIFY_TIMEOUT, &acred->ac_flags) && | ||
1352 | (gss_key_timeout(rc) != 0)) { | ||
1353 | /* test will now be done from generic cred */ | ||
1354 | test_and_clear_bit(RPC_CRED_NOTIFY_TIMEOUT, &acred->ac_flags); | ||
1355 | /* tell NFS layer that key will expire soon */ | ||
1356 | set_bit(RPC_CRED_KEY_EXPIRE_SOON, &acred->ac_flags); | ||
1357 | } | ||
1358 | return ret; | ||
1150 | } | 1359 | } |
1151 | 1360 | ||
1152 | /* | 1361 | /* |
@@ -1292,6 +1501,7 @@ gss_validate(struct rpc_task *task, __be32 *p) | |||
1292 | struct xdr_netobj mic; | 1501 | struct xdr_netobj mic; |
1293 | u32 flav,len; | 1502 | u32 flav,len; |
1294 | u32 maj_stat; | 1503 | u32 maj_stat; |
1504 | __be32 *ret = ERR_PTR(-EIO); | ||
1295 | 1505 | ||
1296 | dprintk("RPC: %5u %s\n", task->tk_pid, __func__); | 1506 | dprintk("RPC: %5u %s\n", task->tk_pid, __func__); |
1297 | 1507 | ||
@@ -1307,6 +1517,7 @@ gss_validate(struct rpc_task *task, __be32 *p) | |||
1307 | mic.data = (u8 *)p; | 1517 | mic.data = (u8 *)p; |
1308 | mic.len = len; | 1518 | mic.len = len; |
1309 | 1519 | ||
1520 | ret = ERR_PTR(-EACCES); | ||
1310 | maj_stat = gss_verify_mic(ctx->gc_gss_ctx, &verf_buf, &mic); | 1521 | maj_stat = gss_verify_mic(ctx->gc_gss_ctx, &verf_buf, &mic); |
1311 | if (maj_stat == GSS_S_CONTEXT_EXPIRED) | 1522 | if (maj_stat == GSS_S_CONTEXT_EXPIRED) |
1312 | clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags); | 1523 | clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags); |
@@ -1324,8 +1535,9 @@ gss_validate(struct rpc_task *task, __be32 *p) | |||
1324 | return p + XDR_QUADLEN(len); | 1535 | return p + XDR_QUADLEN(len); |
1325 | out_bad: | 1536 | out_bad: |
1326 | gss_put_ctx(ctx); | 1537 | gss_put_ctx(ctx); |
1327 | dprintk("RPC: %5u %s failed.\n", task->tk_pid, __func__); | 1538 | dprintk("RPC: %5u %s failed ret %ld.\n", task->tk_pid, __func__, |
1328 | return NULL; | 1539 | PTR_ERR(ret)); |
1540 | return ret; | ||
1329 | } | 1541 | } |
1330 | 1542 | ||
1331 | static void gss_wrap_req_encode(kxdreproc_t encode, struct rpc_rqst *rqstp, | 1543 | static void gss_wrap_req_encode(kxdreproc_t encode, struct rpc_rqst *rqstp, |
@@ -1657,8 +1869,6 @@ static const struct rpc_authops authgss_ops = { | |||
1657 | .destroy = gss_destroy, | 1869 | .destroy = gss_destroy, |
1658 | .lookup_cred = gss_lookup_cred, | 1870 | .lookup_cred = gss_lookup_cred, |
1659 | .crcreate = gss_create_cred, | 1871 | .crcreate = gss_create_cred, |
1660 | .pipes_create = gss_pipes_dentries_create, | ||
1661 | .pipes_destroy = gss_pipes_dentries_destroy, | ||
1662 | .list_pseudoflavors = gss_mech_list_pseudoflavors, | 1872 | .list_pseudoflavors = gss_mech_list_pseudoflavors, |
1663 | .info2flavor = gss_mech_info2flavor, | 1873 | .info2flavor = gss_mech_info2flavor, |
1664 | .flavor2info = gss_mech_flavor2info, | 1874 | .flavor2info = gss_mech_flavor2info, |
@@ -1675,6 +1885,7 @@ static const struct rpc_credops gss_credops = { | |||
1675 | .crvalidate = gss_validate, | 1885 | .crvalidate = gss_validate, |
1676 | .crwrap_req = gss_wrap_req, | 1886 | .crwrap_req = gss_wrap_req, |
1677 | .crunwrap_resp = gss_unwrap_resp, | 1887 | .crunwrap_resp = gss_unwrap_resp, |
1888 | .crkey_timeout = gss_key_timeout, | ||
1678 | }; | 1889 | }; |
1679 | 1890 | ||
1680 | static const struct rpc_credops gss_nullops = { | 1891 | static const struct rpc_credops gss_nullops = { |
@@ -1762,5 +1973,12 @@ module_param_named(expired_cred_retry_delay, | |||
1762 | MODULE_PARM_DESC(expired_cred_retry_delay, "Timeout (in seconds) until " | 1973 | MODULE_PARM_DESC(expired_cred_retry_delay, "Timeout (in seconds) until " |
1763 | "the RPC engine retries an expired credential"); | 1974 | "the RPC engine retries an expired credential"); |
1764 | 1975 | ||
1976 | module_param_named(key_expire_timeo, | ||
1977 | gss_key_expire_timeo, | ||
1978 | uint, 0644); | ||
1979 | MODULE_PARM_DESC(key_expire_timeo, "Time (in seconds) at the end of a " | ||
1980 | "credential keys lifetime where the NFS layer cleans up " | ||
1981 | "prior to key expiration"); | ||
1982 | |||
1765 | module_init(init_rpcsec_gss) | 1983 | module_init(init_rpcsec_gss) |
1766 | module_exit(exit_rpcsec_gss) | 1984 | module_exit(exit_rpcsec_gss) |
diff --git a/net/sunrpc/auth_gss/gss_rpc_upcall.c b/net/sunrpc/auth_gss/gss_rpc_upcall.c index af7ffd447fee..f1eb0d16666c 100644 --- a/net/sunrpc/auth_gss/gss_rpc_upcall.c +++ b/net/sunrpc/auth_gss/gss_rpc_upcall.c | |||
@@ -213,6 +213,26 @@ static int gssp_call(struct net *net, struct rpc_message *msg) | |||
213 | return status; | 213 | return status; |
214 | } | 214 | } |
215 | 215 | ||
216 | static void gssp_free_receive_pages(struct gssx_arg_accept_sec_context *arg) | ||
217 | { | ||
218 | int i; | ||
219 | |||
220 | for (i = 0; i < arg->npages && arg->pages[i]; i++) | ||
221 | __free_page(arg->pages[i]); | ||
222 | } | ||
223 | |||
224 | static int gssp_alloc_receive_pages(struct gssx_arg_accept_sec_context *arg) | ||
225 | { | ||
226 | arg->npages = DIV_ROUND_UP(NGROUPS_MAX * 4, PAGE_SIZE); | ||
227 | arg->pages = kzalloc(arg->npages * sizeof(struct page *), GFP_KERNEL); | ||
228 | /* | ||
229 | * XXX: actual pages are allocated by xdr layer in | ||
230 | * xdr_partial_copy_from_skb. | ||
231 | */ | ||
232 | if (!arg->pages) | ||
233 | return -ENOMEM; | ||
234 | return 0; | ||
235 | } | ||
216 | 236 | ||
217 | /* | 237 | /* |
218 | * Public functions | 238 | * Public functions |
@@ -261,10 +281,16 @@ int gssp_accept_sec_context_upcall(struct net *net, | |||
261 | arg.context_handle = &ctxh; | 281 | arg.context_handle = &ctxh; |
262 | res.output_token->len = GSSX_max_output_token_sz; | 282 | res.output_token->len = GSSX_max_output_token_sz; |
263 | 283 | ||
284 | ret = gssp_alloc_receive_pages(&arg); | ||
285 | if (ret) | ||
286 | return ret; | ||
287 | |||
264 | /* use nfs/ for targ_name ? */ | 288 | /* use nfs/ for targ_name ? */ |
265 | 289 | ||
266 | ret = gssp_call(net, &msg); | 290 | ret = gssp_call(net, &msg); |
267 | 291 | ||
292 | gssp_free_receive_pages(&arg); | ||
293 | |||
268 | /* we need to fetch all data even in case of error so | 294 | /* we need to fetch all data even in case of error so |
269 | * that we can free special strctures is they have been allocated */ | 295 | * that we can free special strctures is they have been allocated */ |
270 | data->major_status = res.status.major_status; | 296 | data->major_status = res.status.major_status; |
diff --git a/net/sunrpc/auth_gss/gss_rpc_xdr.c b/net/sunrpc/auth_gss/gss_rpc_xdr.c index 3c85d1c8a028..f0f78c5f1c7d 100644 --- a/net/sunrpc/auth_gss/gss_rpc_xdr.c +++ b/net/sunrpc/auth_gss/gss_rpc_xdr.c | |||
@@ -166,14 +166,15 @@ static int dummy_dec_opt_array(struct xdr_stream *xdr, | |||
166 | return 0; | 166 | return 0; |
167 | } | 167 | } |
168 | 168 | ||
169 | static int get_s32(void **p, void *max, s32 *res) | 169 | static int get_host_u32(struct xdr_stream *xdr, u32 *res) |
170 | { | 170 | { |
171 | void *base = *p; | 171 | __be32 *p; |
172 | void *next = (void *)((char *)base + sizeof(s32)); | 172 | |
173 | if (unlikely(next > max || next < base)) | 173 | p = xdr_inline_decode(xdr, 4); |
174 | if (!p) | ||
174 | return -EINVAL; | 175 | return -EINVAL; |
175 | memcpy(res, base, sizeof(s32)); | 176 | /* Contents of linux creds are all host-endian: */ |
176 | *p = next; | 177 | memcpy(res, p, sizeof(u32)); |
177 | return 0; | 178 | return 0; |
178 | } | 179 | } |
179 | 180 | ||
@@ -182,9 +183,9 @@ static int gssx_dec_linux_creds(struct xdr_stream *xdr, | |||
182 | { | 183 | { |
183 | u32 length; | 184 | u32 length; |
184 | __be32 *p; | 185 | __be32 *p; |
185 | void *q, *end; | 186 | u32 tmp; |
186 | s32 tmp; | 187 | u32 N; |
187 | int N, i, err; | 188 | int i, err; |
188 | 189 | ||
189 | p = xdr_inline_decode(xdr, 4); | 190 | p = xdr_inline_decode(xdr, 4); |
190 | if (unlikely(p == NULL)) | 191 | if (unlikely(p == NULL)) |
@@ -192,33 +193,28 @@ static int gssx_dec_linux_creds(struct xdr_stream *xdr, | |||
192 | 193 | ||
193 | length = be32_to_cpup(p); | 194 | length = be32_to_cpup(p); |
194 | 195 | ||
195 | /* FIXME: we do not want to use the scratch buffer for this one | 196 | if (length > (3 + NGROUPS_MAX) * sizeof(u32)) |
196 | * may need to use functions that allows us to access an io vector | ||
197 | * directly */ | ||
198 | p = xdr_inline_decode(xdr, length); | ||
199 | if (unlikely(p == NULL)) | ||
200 | return -ENOSPC; | 197 | return -ENOSPC; |
201 | 198 | ||
202 | q = p; | ||
203 | end = q + length; | ||
204 | |||
205 | /* uid */ | 199 | /* uid */ |
206 | err = get_s32(&q, end, &tmp); | 200 | err = get_host_u32(xdr, &tmp); |
207 | if (err) | 201 | if (err) |
208 | return err; | 202 | return err; |
209 | creds->cr_uid = make_kuid(&init_user_ns, tmp); | 203 | creds->cr_uid = make_kuid(&init_user_ns, tmp); |
210 | 204 | ||
211 | /* gid */ | 205 | /* gid */ |
212 | err = get_s32(&q, end, &tmp); | 206 | err = get_host_u32(xdr, &tmp); |
213 | if (err) | 207 | if (err) |
214 | return err; | 208 | return err; |
215 | creds->cr_gid = make_kgid(&init_user_ns, tmp); | 209 | creds->cr_gid = make_kgid(&init_user_ns, tmp); |
216 | 210 | ||
217 | /* number of additional gid's */ | 211 | /* number of additional gid's */ |
218 | err = get_s32(&q, end, &tmp); | 212 | err = get_host_u32(xdr, &tmp); |
219 | if (err) | 213 | if (err) |
220 | return err; | 214 | return err; |
221 | N = tmp; | 215 | N = tmp; |
216 | if ((3 + N) * sizeof(u32) != length) | ||
217 | return -EINVAL; | ||
222 | creds->cr_group_info = groups_alloc(N); | 218 | creds->cr_group_info = groups_alloc(N); |
223 | if (creds->cr_group_info == NULL) | 219 | if (creds->cr_group_info == NULL) |
224 | return -ENOMEM; | 220 | return -ENOMEM; |
@@ -226,7 +222,7 @@ static int gssx_dec_linux_creds(struct xdr_stream *xdr, | |||
226 | /* gid's */ | 222 | /* gid's */ |
227 | for (i = 0; i < N; i++) { | 223 | for (i = 0; i < N; i++) { |
228 | kgid_t kgid; | 224 | kgid_t kgid; |
229 | err = get_s32(&q, end, &tmp); | 225 | err = get_host_u32(xdr, &tmp); |
230 | if (err) | 226 | if (err) |
231 | goto out_free_groups; | 227 | goto out_free_groups; |
232 | err = -EINVAL; | 228 | err = -EINVAL; |
@@ -784,6 +780,9 @@ void gssx_enc_accept_sec_context(struct rpc_rqst *req, | |||
784 | /* arg->options */ | 780 | /* arg->options */ |
785 | err = dummy_enc_opt_array(xdr, &arg->options); | 781 | err = dummy_enc_opt_array(xdr, &arg->options); |
786 | 782 | ||
783 | xdr_inline_pages(&req->rq_rcv_buf, | ||
784 | PAGE_SIZE/2 /* pretty arbitrary */, | ||
785 | arg->pages, 0 /* page base */, arg->npages * PAGE_SIZE); | ||
787 | done: | 786 | done: |
788 | if (err) | 787 | if (err) |
789 | dprintk("RPC: gssx_enc_accept_sec_context: %d\n", err); | 788 | dprintk("RPC: gssx_enc_accept_sec_context: %d\n", err); |
diff --git a/net/sunrpc/auth_gss/gss_rpc_xdr.h b/net/sunrpc/auth_gss/gss_rpc_xdr.h index 1c98b27d870c..685a688f3d8a 100644 --- a/net/sunrpc/auth_gss/gss_rpc_xdr.h +++ b/net/sunrpc/auth_gss/gss_rpc_xdr.h | |||
@@ -147,6 +147,8 @@ struct gssx_arg_accept_sec_context { | |||
147 | struct gssx_cb *input_cb; | 147 | struct gssx_cb *input_cb; |
148 | u32 ret_deleg_cred; | 148 | u32 ret_deleg_cred; |
149 | struct gssx_option_array options; | 149 | struct gssx_option_array options; |
150 | struct page **pages; | ||
151 | unsigned int npages; | ||
150 | }; | 152 | }; |
151 | 153 | ||
152 | struct gssx_res_accept_sec_context { | 154 | struct gssx_res_accept_sec_context { |
@@ -240,7 +242,8 @@ int gssx_dec_accept_sec_context(struct rpc_rqst *rqstp, | |||
240 | 2 * GSSX_max_princ_sz + \ | 242 | 2 * GSSX_max_princ_sz + \ |
241 | 8 + 8 + 4 + 4 + 4) | 243 | 8 + 8 + 4 + 4 + 4) |
242 | #define GSSX_max_output_token_sz 1024 | 244 | #define GSSX_max_output_token_sz 1024 |
243 | #define GSSX_max_creds_sz (4 + 4 + 4 + NGROUPS_MAX * 4) | 245 | /* grouplist not included; we allocate separate pages for that: */ |
246 | #define GSSX_max_creds_sz (4 + 4 + 4 /* + NGROUPS_MAX*4 */) | ||
244 | #define GSSX_RES_accept_sec_context_sz (GSSX_default_status_sz + \ | 247 | #define GSSX_RES_accept_sec_context_sz (GSSX_default_status_sz + \ |
245 | GSSX_default_ctx_sz + \ | 248 | GSSX_default_ctx_sz + \ |
246 | GSSX_max_output_token_sz + \ | 249 | GSSX_max_output_token_sz + \ |
diff --git a/net/sunrpc/auth_null.c b/net/sunrpc/auth_null.c index a5c36c01707b..f0ebe07978a2 100644 --- a/net/sunrpc/auth_null.c +++ b/net/sunrpc/auth_null.c | |||
@@ -18,7 +18,7 @@ static struct rpc_auth null_auth; | |||
18 | static struct rpc_cred null_cred; | 18 | static struct rpc_cred null_cred; |
19 | 19 | ||
20 | static struct rpc_auth * | 20 | static struct rpc_auth * |
21 | nul_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor) | 21 | nul_create(struct rpc_auth_create_args *args, struct rpc_clnt *clnt) |
22 | { | 22 | { |
23 | atomic_inc(&null_auth.au_count); | 23 | atomic_inc(&null_auth.au_count); |
24 | return &null_auth; | 24 | return &null_auth; |
@@ -88,13 +88,13 @@ nul_validate(struct rpc_task *task, __be32 *p) | |||
88 | flavor = ntohl(*p++); | 88 | flavor = ntohl(*p++); |
89 | if (flavor != RPC_AUTH_NULL) { | 89 | if (flavor != RPC_AUTH_NULL) { |
90 | printk("RPC: bad verf flavor: %u\n", flavor); | 90 | printk("RPC: bad verf flavor: %u\n", flavor); |
91 | return NULL; | 91 | return ERR_PTR(-EIO); |
92 | } | 92 | } |
93 | 93 | ||
94 | size = ntohl(*p++); | 94 | size = ntohl(*p++); |
95 | if (size != 0) { | 95 | if (size != 0) { |
96 | printk("RPC: bad verf size: %u\n", size); | 96 | printk("RPC: bad verf size: %u\n", size); |
97 | return NULL; | 97 | return ERR_PTR(-EIO); |
98 | } | 98 | } |
99 | 99 | ||
100 | return p; | 100 | return p; |
diff --git a/net/sunrpc/auth_unix.c b/net/sunrpc/auth_unix.c index dc37021fc3e5..d5d692366294 100644 --- a/net/sunrpc/auth_unix.c +++ b/net/sunrpc/auth_unix.c | |||
@@ -33,7 +33,7 @@ static struct rpc_auth unix_auth; | |||
33 | static const struct rpc_credops unix_credops; | 33 | static const struct rpc_credops unix_credops; |
34 | 34 | ||
35 | static struct rpc_auth * | 35 | static struct rpc_auth * |
36 | unx_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor) | 36 | unx_create(struct rpc_auth_create_args *args, struct rpc_clnt *clnt) |
37 | { | 37 | { |
38 | dprintk("RPC: creating UNIX authenticator for client %p\n", | 38 | dprintk("RPC: creating UNIX authenticator for client %p\n", |
39 | clnt); | 39 | clnt); |
@@ -192,13 +192,13 @@ unx_validate(struct rpc_task *task, __be32 *p) | |||
192 | flavor != RPC_AUTH_UNIX && | 192 | flavor != RPC_AUTH_UNIX && |
193 | flavor != RPC_AUTH_SHORT) { | 193 | flavor != RPC_AUTH_SHORT) { |
194 | printk("RPC: bad verf flavor: %u\n", flavor); | 194 | printk("RPC: bad verf flavor: %u\n", flavor); |
195 | return NULL; | 195 | return ERR_PTR(-EIO); |
196 | } | 196 | } |
197 | 197 | ||
198 | size = ntohl(*p++); | 198 | size = ntohl(*p++); |
199 | if (size > RPC_MAX_AUTH_SIZE) { | 199 | if (size > RPC_MAX_AUTH_SIZE) { |
200 | printk("RPC: giant verf size: %u\n", size); | 200 | printk("RPC: giant verf size: %u\n", size); |
201 | return NULL; | 201 | return ERR_PTR(-EIO); |
202 | } | 202 | } |
203 | task->tk_rqstp->rq_cred->cr_auth->au_rslack = (size >> 2) + 2; | 203 | task->tk_rqstp->rq_cred->cr_auth->au_rslack = (size >> 2) + 2; |
204 | p += (size >> 2); | 204 | p += (size >> 2); |
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index ecbc4e3d83ad..77479606a971 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
@@ -102,12 +102,7 @@ static void rpc_unregister_client(struct rpc_clnt *clnt) | |||
102 | 102 | ||
103 | static void __rpc_clnt_remove_pipedir(struct rpc_clnt *clnt) | 103 | static void __rpc_clnt_remove_pipedir(struct rpc_clnt *clnt) |
104 | { | 104 | { |
105 | if (clnt->cl_dentry) { | 105 | rpc_remove_client_dir(clnt); |
106 | if (clnt->cl_auth && clnt->cl_auth->au_ops->pipes_destroy) | ||
107 | clnt->cl_auth->au_ops->pipes_destroy(clnt->cl_auth); | ||
108 | rpc_remove_client_dir(clnt->cl_dentry); | ||
109 | } | ||
110 | clnt->cl_dentry = NULL; | ||
111 | } | 106 | } |
112 | 107 | ||
113 | static void rpc_clnt_remove_pipedir(struct rpc_clnt *clnt) | 108 | static void rpc_clnt_remove_pipedir(struct rpc_clnt *clnt) |
@@ -123,10 +118,10 @@ static void rpc_clnt_remove_pipedir(struct rpc_clnt *clnt) | |||
123 | } | 118 | } |
124 | 119 | ||
125 | static struct dentry *rpc_setup_pipedir_sb(struct super_block *sb, | 120 | static struct dentry *rpc_setup_pipedir_sb(struct super_block *sb, |
126 | struct rpc_clnt *clnt, | 121 | struct rpc_clnt *clnt) |
127 | const char *dir_name) | ||
128 | { | 122 | { |
129 | static uint32_t clntid; | 123 | static uint32_t clntid; |
124 | const char *dir_name = clnt->cl_program->pipe_dir_name; | ||
130 | char name[15]; | 125 | char name[15]; |
131 | struct dentry *dir, *dentry; | 126 | struct dentry *dir, *dentry; |
132 | 127 | ||
@@ -153,28 +148,35 @@ static struct dentry *rpc_setup_pipedir_sb(struct super_block *sb, | |||
153 | } | 148 | } |
154 | 149 | ||
155 | static int | 150 | static int |
156 | rpc_setup_pipedir(struct rpc_clnt *clnt, const char *dir_name, | 151 | rpc_setup_pipedir(struct super_block *pipefs_sb, struct rpc_clnt *clnt) |
157 | struct super_block *pipefs_sb) | ||
158 | { | 152 | { |
159 | struct dentry *dentry; | 153 | struct dentry *dentry; |
160 | 154 | ||
161 | clnt->cl_dentry = NULL; | 155 | if (clnt->cl_program->pipe_dir_name != NULL) { |
162 | if (dir_name == NULL) | 156 | dentry = rpc_setup_pipedir_sb(pipefs_sb, clnt); |
163 | return 0; | 157 | if (IS_ERR(dentry)) |
164 | dentry = rpc_setup_pipedir_sb(pipefs_sb, clnt, dir_name); | 158 | return PTR_ERR(dentry); |
165 | if (IS_ERR(dentry)) | 159 | } |
166 | return PTR_ERR(dentry); | ||
167 | clnt->cl_dentry = dentry; | ||
168 | return 0; | 160 | return 0; |
169 | } | 161 | } |
170 | 162 | ||
171 | static inline int rpc_clnt_skip_event(struct rpc_clnt *clnt, unsigned long event) | 163 | static int rpc_clnt_skip_event(struct rpc_clnt *clnt, unsigned long event) |
172 | { | 164 | { |
173 | if (((event == RPC_PIPEFS_MOUNT) && clnt->cl_dentry) || | 165 | if (clnt->cl_program->pipe_dir_name == NULL) |
174 | ((event == RPC_PIPEFS_UMOUNT) && !clnt->cl_dentry)) | ||
175 | return 1; | ||
176 | if ((event == RPC_PIPEFS_MOUNT) && atomic_read(&clnt->cl_count) == 0) | ||
177 | return 1; | 166 | return 1; |
167 | |||
168 | switch (event) { | ||
169 | case RPC_PIPEFS_MOUNT: | ||
170 | if (clnt->cl_pipedir_objects.pdh_dentry != NULL) | ||
171 | return 1; | ||
172 | if (atomic_read(&clnt->cl_count) == 0) | ||
173 | return 1; | ||
174 | break; | ||
175 | case RPC_PIPEFS_UMOUNT: | ||
176 | if (clnt->cl_pipedir_objects.pdh_dentry == NULL) | ||
177 | return 1; | ||
178 | break; | ||
179 | } | ||
178 | return 0; | 180 | return 0; |
179 | } | 181 | } |
180 | 182 | ||
@@ -186,18 +188,11 @@ static int __rpc_clnt_handle_event(struct rpc_clnt *clnt, unsigned long event, | |||
186 | 188 | ||
187 | switch (event) { | 189 | switch (event) { |
188 | case RPC_PIPEFS_MOUNT: | 190 | case RPC_PIPEFS_MOUNT: |
189 | dentry = rpc_setup_pipedir_sb(sb, clnt, | 191 | dentry = rpc_setup_pipedir_sb(sb, clnt); |
190 | clnt->cl_program->pipe_dir_name); | ||
191 | if (!dentry) | 192 | if (!dentry) |
192 | return -ENOENT; | 193 | return -ENOENT; |
193 | if (IS_ERR(dentry)) | 194 | if (IS_ERR(dentry)) |
194 | return PTR_ERR(dentry); | 195 | return PTR_ERR(dentry); |
195 | clnt->cl_dentry = dentry; | ||
196 | if (clnt->cl_auth->au_ops->pipes_create) { | ||
197 | err = clnt->cl_auth->au_ops->pipes_create(clnt->cl_auth); | ||
198 | if (err) | ||
199 | __rpc_clnt_remove_pipedir(clnt); | ||
200 | } | ||
201 | break; | 196 | break; |
202 | case RPC_PIPEFS_UMOUNT: | 197 | case RPC_PIPEFS_UMOUNT: |
203 | __rpc_clnt_remove_pipedir(clnt); | 198 | __rpc_clnt_remove_pipedir(clnt); |
@@ -230,8 +225,6 @@ static struct rpc_clnt *rpc_get_client_for_event(struct net *net, int event) | |||
230 | 225 | ||
231 | spin_lock(&sn->rpc_client_lock); | 226 | spin_lock(&sn->rpc_client_lock); |
232 | list_for_each_entry(clnt, &sn->all_clients, cl_clients) { | 227 | list_for_each_entry(clnt, &sn->all_clients, cl_clients) { |
233 | if (clnt->cl_program->pipe_dir_name == NULL) | ||
234 | continue; | ||
235 | if (rpc_clnt_skip_event(clnt, event)) | 228 | if (rpc_clnt_skip_event(clnt, event)) |
236 | continue; | 229 | continue; |
237 | spin_unlock(&sn->rpc_client_lock); | 230 | spin_unlock(&sn->rpc_client_lock); |
@@ -282,7 +275,10 @@ static void rpc_clnt_set_nodename(struct rpc_clnt *clnt, const char *nodename) | |||
282 | static int rpc_client_register(const struct rpc_create_args *args, | 275 | static int rpc_client_register(const struct rpc_create_args *args, |
283 | struct rpc_clnt *clnt) | 276 | struct rpc_clnt *clnt) |
284 | { | 277 | { |
285 | const struct rpc_program *program = args->program; | 278 | struct rpc_auth_create_args auth_args = { |
279 | .pseudoflavor = args->authflavor, | ||
280 | .target_name = args->client_name, | ||
281 | }; | ||
286 | struct rpc_auth *auth; | 282 | struct rpc_auth *auth; |
287 | struct net *net = rpc_net_ns(clnt); | 283 | struct net *net = rpc_net_ns(clnt); |
288 | struct super_block *pipefs_sb; | 284 | struct super_block *pipefs_sb; |
@@ -290,7 +286,7 @@ static int rpc_client_register(const struct rpc_create_args *args, | |||
290 | 286 | ||
291 | pipefs_sb = rpc_get_sb_net(net); | 287 | pipefs_sb = rpc_get_sb_net(net); |
292 | if (pipefs_sb) { | 288 | if (pipefs_sb) { |
293 | err = rpc_setup_pipedir(clnt, program->pipe_dir_name, pipefs_sb); | 289 | err = rpc_setup_pipedir(pipefs_sb, clnt); |
294 | if (err) | 290 | if (err) |
295 | goto out; | 291 | goto out; |
296 | } | 292 | } |
@@ -299,7 +295,7 @@ static int rpc_client_register(const struct rpc_create_args *args, | |||
299 | if (pipefs_sb) | 295 | if (pipefs_sb) |
300 | rpc_put_sb_net(net); | 296 | rpc_put_sb_net(net); |
301 | 297 | ||
302 | auth = rpcauth_create(args->authflavor, clnt); | 298 | auth = rpcauth_create(&auth_args, clnt); |
303 | if (IS_ERR(auth)) { | 299 | if (IS_ERR(auth)) { |
304 | dprintk("RPC: Couldn't create auth handle (flavor %u)\n", | 300 | dprintk("RPC: Couldn't create auth handle (flavor %u)\n", |
305 | args->authflavor); | 301 | args->authflavor); |
@@ -317,7 +313,27 @@ out: | |||
317 | return err; | 313 | return err; |
318 | } | 314 | } |
319 | 315 | ||
320 | static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, struct rpc_xprt *xprt) | 316 | static DEFINE_IDA(rpc_clids); |
317 | |||
318 | static int rpc_alloc_clid(struct rpc_clnt *clnt) | ||
319 | { | ||
320 | int clid; | ||
321 | |||
322 | clid = ida_simple_get(&rpc_clids, 0, 0, GFP_KERNEL); | ||
323 | if (clid < 0) | ||
324 | return clid; | ||
325 | clnt->cl_clid = clid; | ||
326 | return 0; | ||
327 | } | ||
328 | |||
329 | static void rpc_free_clid(struct rpc_clnt *clnt) | ||
330 | { | ||
331 | ida_simple_remove(&rpc_clids, clnt->cl_clid); | ||
332 | } | ||
333 | |||
334 | static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, | ||
335 | struct rpc_xprt *xprt, | ||
336 | struct rpc_clnt *parent) | ||
321 | { | 337 | { |
322 | const struct rpc_program *program = args->program; | 338 | const struct rpc_program *program = args->program; |
323 | const struct rpc_version *version; | 339 | const struct rpc_version *version; |
@@ -343,16 +359,20 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, stru | |||
343 | clnt = kzalloc(sizeof(*clnt), GFP_KERNEL); | 359 | clnt = kzalloc(sizeof(*clnt), GFP_KERNEL); |
344 | if (!clnt) | 360 | if (!clnt) |
345 | goto out_err; | 361 | goto out_err; |
346 | clnt->cl_parent = clnt; | 362 | clnt->cl_parent = parent ? : clnt; |
363 | |||
364 | err = rpc_alloc_clid(clnt); | ||
365 | if (err) | ||
366 | goto out_no_clid; | ||
347 | 367 | ||
348 | rcu_assign_pointer(clnt->cl_xprt, xprt); | 368 | rcu_assign_pointer(clnt->cl_xprt, xprt); |
349 | clnt->cl_procinfo = version->procs; | 369 | clnt->cl_procinfo = version->procs; |
350 | clnt->cl_maxproc = version->nrprocs; | 370 | clnt->cl_maxproc = version->nrprocs; |
351 | clnt->cl_protname = program->name; | ||
352 | clnt->cl_prog = args->prognumber ? : program->number; | 371 | clnt->cl_prog = args->prognumber ? : program->number; |
353 | clnt->cl_vers = version->number; | 372 | clnt->cl_vers = version->number; |
354 | clnt->cl_stats = program->stats; | 373 | clnt->cl_stats = program->stats; |
355 | clnt->cl_metrics = rpc_alloc_iostats(clnt); | 374 | clnt->cl_metrics = rpc_alloc_iostats(clnt); |
375 | rpc_init_pipe_dir_head(&clnt->cl_pipedir_objects); | ||
356 | err = -ENOMEM; | 376 | err = -ENOMEM; |
357 | if (clnt->cl_metrics == NULL) | 377 | if (clnt->cl_metrics == NULL) |
358 | goto out_no_stats; | 378 | goto out_no_stats; |
@@ -372,12 +392,6 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, stru | |||
372 | 392 | ||
373 | clnt->cl_rtt = &clnt->cl_rtt_default; | 393 | clnt->cl_rtt = &clnt->cl_rtt_default; |
374 | rpc_init_rtt(&clnt->cl_rtt_default, clnt->cl_timeout->to_initval); | 394 | rpc_init_rtt(&clnt->cl_rtt_default, clnt->cl_timeout->to_initval); |
375 | clnt->cl_principal = NULL; | ||
376 | if (args->client_name) { | ||
377 | clnt->cl_principal = kstrdup(args->client_name, GFP_KERNEL); | ||
378 | if (!clnt->cl_principal) | ||
379 | goto out_no_principal; | ||
380 | } | ||
381 | 395 | ||
382 | atomic_set(&clnt->cl_count, 1); | 396 | atomic_set(&clnt->cl_count, 1); |
383 | 397 | ||
@@ -387,13 +401,15 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, stru | |||
387 | err = rpc_client_register(args, clnt); | 401 | err = rpc_client_register(args, clnt); |
388 | if (err) | 402 | if (err) |
389 | goto out_no_path; | 403 | goto out_no_path; |
404 | if (parent) | ||
405 | atomic_inc(&parent->cl_count); | ||
390 | return clnt; | 406 | return clnt; |
391 | 407 | ||
392 | out_no_path: | 408 | out_no_path: |
393 | kfree(clnt->cl_principal); | ||
394 | out_no_principal: | ||
395 | rpc_free_iostats(clnt->cl_metrics); | 409 | rpc_free_iostats(clnt->cl_metrics); |
396 | out_no_stats: | 410 | out_no_stats: |
411 | rpc_free_clid(clnt); | ||
412 | out_no_clid: | ||
397 | kfree(clnt); | 413 | kfree(clnt); |
398 | out_err: | 414 | out_err: |
399 | rpciod_down(); | 415 | rpciod_down(); |
@@ -479,7 +495,7 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args) | |||
479 | if (args->flags & RPC_CLNT_CREATE_NONPRIVPORT) | 495 | if (args->flags & RPC_CLNT_CREATE_NONPRIVPORT) |
480 | xprt->resvport = 0; | 496 | xprt->resvport = 0; |
481 | 497 | ||
482 | clnt = rpc_new_client(args, xprt); | 498 | clnt = rpc_new_client(args, xprt, NULL); |
483 | if (IS_ERR(clnt)) | 499 | if (IS_ERR(clnt)) |
484 | return clnt; | 500 | return clnt; |
485 | 501 | ||
@@ -526,15 +542,12 @@ static struct rpc_clnt *__rpc_clone_client(struct rpc_create_args *args, | |||
526 | goto out_err; | 542 | goto out_err; |
527 | args->servername = xprt->servername; | 543 | args->servername = xprt->servername; |
528 | 544 | ||
529 | new = rpc_new_client(args, xprt); | 545 | new = rpc_new_client(args, xprt, clnt); |
530 | if (IS_ERR(new)) { | 546 | if (IS_ERR(new)) { |
531 | err = PTR_ERR(new); | 547 | err = PTR_ERR(new); |
532 | goto out_err; | 548 | goto out_err; |
533 | } | 549 | } |
534 | 550 | ||
535 | atomic_inc(&clnt->cl_count); | ||
536 | new->cl_parent = clnt; | ||
537 | |||
538 | /* Turn off autobind on clones */ | 551 | /* Turn off autobind on clones */ |
539 | new->cl_autobind = 0; | 552 | new->cl_autobind = 0; |
540 | new->cl_softrtry = clnt->cl_softrtry; | 553 | new->cl_softrtry = clnt->cl_softrtry; |
@@ -561,7 +574,6 @@ struct rpc_clnt *rpc_clone_client(struct rpc_clnt *clnt) | |||
561 | .prognumber = clnt->cl_prog, | 574 | .prognumber = clnt->cl_prog, |
562 | .version = clnt->cl_vers, | 575 | .version = clnt->cl_vers, |
563 | .authflavor = clnt->cl_auth->au_flavor, | 576 | .authflavor = clnt->cl_auth->au_flavor, |
564 | .client_name = clnt->cl_principal, | ||
565 | }; | 577 | }; |
566 | return __rpc_clone_client(&args, clnt); | 578 | return __rpc_clone_client(&args, clnt); |
567 | } | 579 | } |
@@ -583,7 +595,6 @@ rpc_clone_client_set_auth(struct rpc_clnt *clnt, rpc_authflavor_t flavor) | |||
583 | .prognumber = clnt->cl_prog, | 595 | .prognumber = clnt->cl_prog, |
584 | .version = clnt->cl_vers, | 596 | .version = clnt->cl_vers, |
585 | .authflavor = flavor, | 597 | .authflavor = flavor, |
586 | .client_name = clnt->cl_principal, | ||
587 | }; | 598 | }; |
588 | return __rpc_clone_client(&args, clnt); | 599 | return __rpc_clone_client(&args, clnt); |
589 | } | 600 | } |
@@ -629,7 +640,7 @@ void rpc_shutdown_client(struct rpc_clnt *clnt) | |||
629 | might_sleep(); | 640 | might_sleep(); |
630 | 641 | ||
631 | dprintk_rcu("RPC: shutting down %s client for %s\n", | 642 | dprintk_rcu("RPC: shutting down %s client for %s\n", |
632 | clnt->cl_protname, | 643 | clnt->cl_program->name, |
633 | rcu_dereference(clnt->cl_xprt)->servername); | 644 | rcu_dereference(clnt->cl_xprt)->servername); |
634 | 645 | ||
635 | while (!list_empty(&clnt->cl_tasks)) { | 646 | while (!list_empty(&clnt->cl_tasks)) { |
@@ -649,17 +660,17 @@ static void | |||
649 | rpc_free_client(struct rpc_clnt *clnt) | 660 | rpc_free_client(struct rpc_clnt *clnt) |
650 | { | 661 | { |
651 | dprintk_rcu("RPC: destroying %s client for %s\n", | 662 | dprintk_rcu("RPC: destroying %s client for %s\n", |
652 | clnt->cl_protname, | 663 | clnt->cl_program->name, |
653 | rcu_dereference(clnt->cl_xprt)->servername); | 664 | rcu_dereference(clnt->cl_xprt)->servername); |
654 | if (clnt->cl_parent != clnt) | 665 | if (clnt->cl_parent != clnt) |
655 | rpc_release_client(clnt->cl_parent); | 666 | rpc_release_client(clnt->cl_parent); |
656 | rpc_clnt_remove_pipedir(clnt); | 667 | rpc_clnt_remove_pipedir(clnt); |
657 | rpc_unregister_client(clnt); | 668 | rpc_unregister_client(clnt); |
658 | rpc_free_iostats(clnt->cl_metrics); | 669 | rpc_free_iostats(clnt->cl_metrics); |
659 | kfree(clnt->cl_principal); | ||
660 | clnt->cl_metrics = NULL; | 670 | clnt->cl_metrics = NULL; |
661 | xprt_put(rcu_dereference_raw(clnt->cl_xprt)); | 671 | xprt_put(rcu_dereference_raw(clnt->cl_xprt)); |
662 | rpciod_down(); | 672 | rpciod_down(); |
673 | rpc_free_clid(clnt); | ||
663 | kfree(clnt); | 674 | kfree(clnt); |
664 | } | 675 | } |
665 | 676 | ||
@@ -720,7 +731,6 @@ struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *old, | |||
720 | .prognumber = program->number, | 731 | .prognumber = program->number, |
721 | .version = vers, | 732 | .version = vers, |
722 | .authflavor = old->cl_auth->au_flavor, | 733 | .authflavor = old->cl_auth->au_flavor, |
723 | .client_name = old->cl_principal, | ||
724 | }; | 734 | }; |
725 | struct rpc_clnt *clnt; | 735 | struct rpc_clnt *clnt; |
726 | int err; | 736 | int err; |
@@ -1299,7 +1309,7 @@ call_start(struct rpc_task *task) | |||
1299 | struct rpc_clnt *clnt = task->tk_client; | 1309 | struct rpc_clnt *clnt = task->tk_client; |
1300 | 1310 | ||
1301 | dprintk("RPC: %5u call_start %s%d proc %s (%s)\n", task->tk_pid, | 1311 | dprintk("RPC: %5u call_start %s%d proc %s (%s)\n", task->tk_pid, |
1302 | clnt->cl_protname, clnt->cl_vers, | 1312 | clnt->cl_program->name, clnt->cl_vers, |
1303 | rpc_proc_name(task), | 1313 | rpc_proc_name(task), |
1304 | (RPC_IS_ASYNC(task) ? "async" : "sync")); | 1314 | (RPC_IS_ASYNC(task) ? "async" : "sync")); |
1305 | 1315 | ||
@@ -1423,9 +1433,9 @@ call_refreshresult(struct rpc_task *task) | |||
1423 | return; | 1433 | return; |
1424 | case -ETIMEDOUT: | 1434 | case -ETIMEDOUT: |
1425 | rpc_delay(task, 3*HZ); | 1435 | rpc_delay(task, 3*HZ); |
1426 | case -EKEYEXPIRED: | ||
1427 | case -EAGAIN: | 1436 | case -EAGAIN: |
1428 | status = -EACCES; | 1437 | status = -EACCES; |
1438 | case -EKEYEXPIRED: | ||
1429 | if (!task->tk_cred_retry) | 1439 | if (!task->tk_cred_retry) |
1430 | break; | 1440 | break; |
1431 | task->tk_cred_retry--; | 1441 | task->tk_cred_retry--; |
@@ -1912,7 +1922,7 @@ call_status(struct rpc_task *task) | |||
1912 | default: | 1922 | default: |
1913 | if (clnt->cl_chatty) | 1923 | if (clnt->cl_chatty) |
1914 | printk("%s: RPC call returned error %d\n", | 1924 | printk("%s: RPC call returned error %d\n", |
1915 | clnt->cl_protname, -status); | 1925 | clnt->cl_program->name, -status); |
1916 | rpc_exit(task, status); | 1926 | rpc_exit(task, status); |
1917 | } | 1927 | } |
1918 | } | 1928 | } |
@@ -1943,7 +1953,7 @@ call_timeout(struct rpc_task *task) | |||
1943 | if (clnt->cl_chatty) { | 1953 | if (clnt->cl_chatty) { |
1944 | rcu_read_lock(); | 1954 | rcu_read_lock(); |
1945 | printk(KERN_NOTICE "%s: server %s not responding, timed out\n", | 1955 | printk(KERN_NOTICE "%s: server %s not responding, timed out\n", |
1946 | clnt->cl_protname, | 1956 | clnt->cl_program->name, |
1947 | rcu_dereference(clnt->cl_xprt)->servername); | 1957 | rcu_dereference(clnt->cl_xprt)->servername); |
1948 | rcu_read_unlock(); | 1958 | rcu_read_unlock(); |
1949 | } | 1959 | } |
@@ -1959,7 +1969,7 @@ call_timeout(struct rpc_task *task) | |||
1959 | if (clnt->cl_chatty) { | 1969 | if (clnt->cl_chatty) { |
1960 | rcu_read_lock(); | 1970 | rcu_read_lock(); |
1961 | printk(KERN_NOTICE "%s: server %s not responding, still trying\n", | 1971 | printk(KERN_NOTICE "%s: server %s not responding, still trying\n", |
1962 | clnt->cl_protname, | 1972 | clnt->cl_program->name, |
1963 | rcu_dereference(clnt->cl_xprt)->servername); | 1973 | rcu_dereference(clnt->cl_xprt)->servername); |
1964 | rcu_read_unlock(); | 1974 | rcu_read_unlock(); |
1965 | } | 1975 | } |
@@ -1994,7 +2004,7 @@ call_decode(struct rpc_task *task) | |||
1994 | if (clnt->cl_chatty) { | 2004 | if (clnt->cl_chatty) { |
1995 | rcu_read_lock(); | 2005 | rcu_read_lock(); |
1996 | printk(KERN_NOTICE "%s: server %s OK\n", | 2006 | printk(KERN_NOTICE "%s: server %s OK\n", |
1997 | clnt->cl_protname, | 2007 | clnt->cl_program->name, |
1998 | rcu_dereference(clnt->cl_xprt)->servername); | 2008 | rcu_dereference(clnt->cl_xprt)->servername); |
1999 | rcu_read_unlock(); | 2009 | rcu_read_unlock(); |
2000 | } | 2010 | } |
@@ -2019,7 +2029,7 @@ call_decode(struct rpc_task *task) | |||
2019 | goto out_retry; | 2029 | goto out_retry; |
2020 | } | 2030 | } |
2021 | dprintk("RPC: %s: too small RPC reply size (%d bytes)\n", | 2031 | dprintk("RPC: %s: too small RPC reply size (%d bytes)\n", |
2022 | clnt->cl_protname, task->tk_status); | 2032 | clnt->cl_program->name, task->tk_status); |
2023 | task->tk_action = call_timeout; | 2033 | task->tk_action = call_timeout; |
2024 | goto out_retry; | 2034 | goto out_retry; |
2025 | } | 2035 | } |
@@ -2091,7 +2101,8 @@ rpc_verify_header(struct rpc_task *task) | |||
2091 | dprintk("RPC: %5u %s: XDR representation not a multiple of" | 2101 | dprintk("RPC: %5u %s: XDR representation not a multiple of" |
2092 | " 4 bytes: 0x%x\n", task->tk_pid, __func__, | 2102 | " 4 bytes: 0x%x\n", task->tk_pid, __func__, |
2093 | task->tk_rqstp->rq_rcv_buf.len); | 2103 | task->tk_rqstp->rq_rcv_buf.len); |
2094 | goto out_eio; | 2104 | error = -EIO; |
2105 | goto out_err; | ||
2095 | } | 2106 | } |
2096 | if ((len -= 3) < 0) | 2107 | if ((len -= 3) < 0) |
2097 | goto out_overflow; | 2108 | goto out_overflow; |
@@ -2100,6 +2111,7 @@ rpc_verify_header(struct rpc_task *task) | |||
2100 | if ((n = ntohl(*p++)) != RPC_REPLY) { | 2111 | if ((n = ntohl(*p++)) != RPC_REPLY) { |
2101 | dprintk("RPC: %5u %s: not an RPC reply: %x\n", | 2112 | dprintk("RPC: %5u %s: not an RPC reply: %x\n", |
2102 | task->tk_pid, __func__, n); | 2113 | task->tk_pid, __func__, n); |
2114 | error = -EIO; | ||
2103 | goto out_garbage; | 2115 | goto out_garbage; |
2104 | } | 2116 | } |
2105 | 2117 | ||
@@ -2118,7 +2130,8 @@ rpc_verify_header(struct rpc_task *task) | |||
2118 | dprintk("RPC: %5u %s: RPC call rejected, " | 2130 | dprintk("RPC: %5u %s: RPC call rejected, " |
2119 | "unknown error: %x\n", | 2131 | "unknown error: %x\n", |
2120 | task->tk_pid, __func__, n); | 2132 | task->tk_pid, __func__, n); |
2121 | goto out_eio; | 2133 | error = -EIO; |
2134 | goto out_err; | ||
2122 | } | 2135 | } |
2123 | if (--len < 0) | 2136 | if (--len < 0) |
2124 | goto out_overflow; | 2137 | goto out_overflow; |
@@ -2163,9 +2176,11 @@ rpc_verify_header(struct rpc_task *task) | |||
2163 | task->tk_pid, __func__, n); | 2176 | task->tk_pid, __func__, n); |
2164 | goto out_err; | 2177 | goto out_err; |
2165 | } | 2178 | } |
2166 | if (!(p = rpcauth_checkverf(task, p))) { | 2179 | p = rpcauth_checkverf(task, p); |
2167 | dprintk("RPC: %5u %s: auth check failed\n", | 2180 | if (IS_ERR(p)) { |
2168 | task->tk_pid, __func__); | 2181 | error = PTR_ERR(p); |
2182 | dprintk("RPC: %5u %s: auth check failed with %d\n", | ||
2183 | task->tk_pid, __func__, error); | ||
2169 | goto out_garbage; /* bad verifier, retry */ | 2184 | goto out_garbage; /* bad verifier, retry */ |
2170 | } | 2185 | } |
2171 | len = p - (__be32 *)iov->iov_base - 1; | 2186 | len = p - (__be32 *)iov->iov_base - 1; |
@@ -2218,8 +2233,6 @@ out_garbage: | |||
2218 | out_retry: | 2233 | out_retry: |
2219 | return ERR_PTR(-EAGAIN); | 2234 | return ERR_PTR(-EAGAIN); |
2220 | } | 2235 | } |
2221 | out_eio: | ||
2222 | error = -EIO; | ||
2223 | out_err: | 2236 | out_err: |
2224 | rpc_exit(task, error); | 2237 | rpc_exit(task, error); |
2225 | dprintk("RPC: %5u %s: call failed with error %d\n", task->tk_pid, | 2238 | dprintk("RPC: %5u %s: call failed with error %d\n", task->tk_pid, |
@@ -2291,7 +2304,7 @@ static void rpc_show_task(const struct rpc_clnt *clnt, | |||
2291 | printk(KERN_INFO "%5u %04x %6d %8p %8p %8ld %8p %sv%u %s a:%ps q:%s\n", | 2304 | printk(KERN_INFO "%5u %04x %6d %8p %8p %8ld %8p %sv%u %s a:%ps q:%s\n", |
2292 | task->tk_pid, task->tk_flags, task->tk_status, | 2305 | task->tk_pid, task->tk_flags, task->tk_status, |
2293 | clnt, task->tk_rqstp, task->tk_timeout, task->tk_ops, | 2306 | clnt, task->tk_rqstp, task->tk_timeout, task->tk_ops, |
2294 | clnt->cl_protname, clnt->cl_vers, rpc_proc_name(task), | 2307 | clnt->cl_program->name, clnt->cl_vers, rpc_proc_name(task), |
2295 | task->tk_action, rpc_waitq); | 2308 | task->tk_action, rpc_waitq); |
2296 | } | 2309 | } |
2297 | 2310 | ||
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index 406859cc68aa..f94567b45bb3 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c | |||
@@ -409,7 +409,7 @@ rpc_show_info(struct seq_file *m, void *v) | |||
409 | rcu_read_lock(); | 409 | rcu_read_lock(); |
410 | seq_printf(m, "RPC server: %s\n", | 410 | seq_printf(m, "RPC server: %s\n", |
411 | rcu_dereference(clnt->cl_xprt)->servername); | 411 | rcu_dereference(clnt->cl_xprt)->servername); |
412 | seq_printf(m, "service: %s (%d) version %d\n", clnt->cl_protname, | 412 | seq_printf(m, "service: %s (%d) version %d\n", clnt->cl_program->name, |
413 | clnt->cl_prog, clnt->cl_vers); | 413 | clnt->cl_prog, clnt->cl_vers); |
414 | seq_printf(m, "address: %s\n", rpc_peeraddr2str(clnt, RPC_DISPLAY_ADDR)); | 414 | seq_printf(m, "address: %s\n", rpc_peeraddr2str(clnt, RPC_DISPLAY_ADDR)); |
415 | seq_printf(m, "protocol: %s\n", rpc_peeraddr2str(clnt, RPC_DISPLAY_PROTO)); | 415 | seq_printf(m, "protocol: %s\n", rpc_peeraddr2str(clnt, RPC_DISPLAY_PROTO)); |
@@ -480,23 +480,6 @@ static const struct dentry_operations rpc_dentry_operations = { | |||
480 | .d_delete = rpc_delete_dentry, | 480 | .d_delete = rpc_delete_dentry, |
481 | }; | 481 | }; |
482 | 482 | ||
483 | /* | ||
484 | * Lookup the data. This is trivial - if the dentry didn't already | ||
485 | * exist, we know it is negative. | ||
486 | */ | ||
487 | static struct dentry * | ||
488 | rpc_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) | ||
489 | { | ||
490 | if (dentry->d_name.len > NAME_MAX) | ||
491 | return ERR_PTR(-ENAMETOOLONG); | ||
492 | d_add(dentry, NULL); | ||
493 | return NULL; | ||
494 | } | ||
495 | |||
496 | static const struct inode_operations rpc_dir_inode_operations = { | ||
497 | .lookup = rpc_lookup, | ||
498 | }; | ||
499 | |||
500 | static struct inode * | 483 | static struct inode * |
501 | rpc_get_inode(struct super_block *sb, umode_t mode) | 484 | rpc_get_inode(struct super_block *sb, umode_t mode) |
502 | { | 485 | { |
@@ -509,7 +492,7 @@ rpc_get_inode(struct super_block *sb, umode_t mode) | |||
509 | switch (mode & S_IFMT) { | 492 | switch (mode & S_IFMT) { |
510 | case S_IFDIR: | 493 | case S_IFDIR: |
511 | inode->i_fop = &simple_dir_operations; | 494 | inode->i_fop = &simple_dir_operations; |
512 | inode->i_op = &rpc_dir_inode_operations; | 495 | inode->i_op = &simple_dir_inode_operations; |
513 | inc_nlink(inode); | 496 | inc_nlink(inode); |
514 | default: | 497 | default: |
515 | break; | 498 | break; |
@@ -901,6 +884,159 @@ rpc_unlink(struct dentry *dentry) | |||
901 | } | 884 | } |
902 | EXPORT_SYMBOL_GPL(rpc_unlink); | 885 | EXPORT_SYMBOL_GPL(rpc_unlink); |
903 | 886 | ||
887 | /** | ||
888 | * rpc_init_pipe_dir_head - initialise a struct rpc_pipe_dir_head | ||
889 | * @pdh: pointer to struct rpc_pipe_dir_head | ||
890 | */ | ||
891 | void rpc_init_pipe_dir_head(struct rpc_pipe_dir_head *pdh) | ||
892 | { | ||
893 | INIT_LIST_HEAD(&pdh->pdh_entries); | ||
894 | pdh->pdh_dentry = NULL; | ||
895 | } | ||
896 | EXPORT_SYMBOL_GPL(rpc_init_pipe_dir_head); | ||
897 | |||
898 | /** | ||
899 | * rpc_init_pipe_dir_object - initialise a struct rpc_pipe_dir_object | ||
900 | * @pdo: pointer to struct rpc_pipe_dir_object | ||
901 | * @pdo_ops: pointer to const struct rpc_pipe_dir_object_ops | ||
902 | * @pdo_data: pointer to caller-defined data | ||
903 | */ | ||
904 | void rpc_init_pipe_dir_object(struct rpc_pipe_dir_object *pdo, | ||
905 | const struct rpc_pipe_dir_object_ops *pdo_ops, | ||
906 | void *pdo_data) | ||
907 | { | ||
908 | INIT_LIST_HEAD(&pdo->pdo_head); | ||
909 | pdo->pdo_ops = pdo_ops; | ||
910 | pdo->pdo_data = pdo_data; | ||
911 | } | ||
912 | EXPORT_SYMBOL_GPL(rpc_init_pipe_dir_object); | ||
913 | |||
914 | static int | ||
915 | rpc_add_pipe_dir_object_locked(struct net *net, | ||
916 | struct rpc_pipe_dir_head *pdh, | ||
917 | struct rpc_pipe_dir_object *pdo) | ||
918 | { | ||
919 | int ret = 0; | ||
920 | |||
921 | if (pdh->pdh_dentry) | ||
922 | ret = pdo->pdo_ops->create(pdh->pdh_dentry, pdo); | ||
923 | if (ret == 0) | ||
924 | list_add_tail(&pdo->pdo_head, &pdh->pdh_entries); | ||
925 | return ret; | ||
926 | } | ||
927 | |||
928 | static void | ||
929 | rpc_remove_pipe_dir_object_locked(struct net *net, | ||
930 | struct rpc_pipe_dir_head *pdh, | ||
931 | struct rpc_pipe_dir_object *pdo) | ||
932 | { | ||
933 | if (pdh->pdh_dentry) | ||
934 | pdo->pdo_ops->destroy(pdh->pdh_dentry, pdo); | ||
935 | list_del_init(&pdo->pdo_head); | ||
936 | } | ||
937 | |||
938 | /** | ||
939 | * rpc_add_pipe_dir_object - associate a rpc_pipe_dir_object to a directory | ||
940 | * @net: pointer to struct net | ||
941 | * @pdh: pointer to struct rpc_pipe_dir_head | ||
942 | * @pdo: pointer to struct rpc_pipe_dir_object | ||
943 | * | ||
944 | */ | ||
945 | int | ||
946 | rpc_add_pipe_dir_object(struct net *net, | ||
947 | struct rpc_pipe_dir_head *pdh, | ||
948 | struct rpc_pipe_dir_object *pdo) | ||
949 | { | ||
950 | int ret = 0; | ||
951 | |||
952 | if (list_empty(&pdo->pdo_head)) { | ||
953 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
954 | |||
955 | mutex_lock(&sn->pipefs_sb_lock); | ||
956 | ret = rpc_add_pipe_dir_object_locked(net, pdh, pdo); | ||
957 | mutex_unlock(&sn->pipefs_sb_lock); | ||
958 | } | ||
959 | return ret; | ||
960 | } | ||
961 | EXPORT_SYMBOL_GPL(rpc_add_pipe_dir_object); | ||
962 | |||
963 | /** | ||
964 | * rpc_remove_pipe_dir_object - remove a rpc_pipe_dir_object from a directory | ||
965 | * @net: pointer to struct net | ||
966 | * @pdh: pointer to struct rpc_pipe_dir_head | ||
967 | * @pdo: pointer to struct rpc_pipe_dir_object | ||
968 | * | ||
969 | */ | ||
970 | void | ||
971 | rpc_remove_pipe_dir_object(struct net *net, | ||
972 | struct rpc_pipe_dir_head *pdh, | ||
973 | struct rpc_pipe_dir_object *pdo) | ||
974 | { | ||
975 | if (!list_empty(&pdo->pdo_head)) { | ||
976 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
977 | |||
978 | mutex_lock(&sn->pipefs_sb_lock); | ||
979 | rpc_remove_pipe_dir_object_locked(net, pdh, pdo); | ||
980 | mutex_unlock(&sn->pipefs_sb_lock); | ||
981 | } | ||
982 | } | ||
983 | EXPORT_SYMBOL_GPL(rpc_remove_pipe_dir_object); | ||
984 | |||
985 | /** | ||
986 | * rpc_find_or_alloc_pipe_dir_object | ||
987 | * @net: pointer to struct net | ||
988 | * @pdh: pointer to struct rpc_pipe_dir_head | ||
989 | * @match: match struct rpc_pipe_dir_object to data | ||
990 | * @alloc: allocate a new struct rpc_pipe_dir_object | ||
991 | * @data: user defined data for match() and alloc() | ||
992 | * | ||
993 | */ | ||
994 | struct rpc_pipe_dir_object * | ||
995 | rpc_find_or_alloc_pipe_dir_object(struct net *net, | ||
996 | struct rpc_pipe_dir_head *pdh, | ||
997 | int (*match)(struct rpc_pipe_dir_object *, void *), | ||
998 | struct rpc_pipe_dir_object *(*alloc)(void *), | ||
999 | void *data) | ||
1000 | { | ||
1001 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
1002 | struct rpc_pipe_dir_object *pdo; | ||
1003 | |||
1004 | mutex_lock(&sn->pipefs_sb_lock); | ||
1005 | list_for_each_entry(pdo, &pdh->pdh_entries, pdo_head) { | ||
1006 | if (!match(pdo, data)) | ||
1007 | continue; | ||
1008 | goto out; | ||
1009 | } | ||
1010 | pdo = alloc(data); | ||
1011 | if (!pdo) | ||
1012 | goto out; | ||
1013 | rpc_add_pipe_dir_object_locked(net, pdh, pdo); | ||
1014 | out: | ||
1015 | mutex_unlock(&sn->pipefs_sb_lock); | ||
1016 | return pdo; | ||
1017 | } | ||
1018 | EXPORT_SYMBOL_GPL(rpc_find_or_alloc_pipe_dir_object); | ||
1019 | |||
1020 | static void | ||
1021 | rpc_create_pipe_dir_objects(struct rpc_pipe_dir_head *pdh) | ||
1022 | { | ||
1023 | struct rpc_pipe_dir_object *pdo; | ||
1024 | struct dentry *dir = pdh->pdh_dentry; | ||
1025 | |||
1026 | list_for_each_entry(pdo, &pdh->pdh_entries, pdo_head) | ||
1027 | pdo->pdo_ops->create(dir, pdo); | ||
1028 | } | ||
1029 | |||
1030 | static void | ||
1031 | rpc_destroy_pipe_dir_objects(struct rpc_pipe_dir_head *pdh) | ||
1032 | { | ||
1033 | struct rpc_pipe_dir_object *pdo; | ||
1034 | struct dentry *dir = pdh->pdh_dentry; | ||
1035 | |||
1036 | list_for_each_entry(pdo, &pdh->pdh_entries, pdo_head) | ||
1037 | pdo->pdo_ops->destroy(dir, pdo); | ||
1038 | } | ||
1039 | |||
904 | enum { | 1040 | enum { |
905 | RPCAUTH_info, | 1041 | RPCAUTH_info, |
906 | RPCAUTH_EOF | 1042 | RPCAUTH_EOF |
@@ -941,16 +1077,29 @@ struct dentry *rpc_create_client_dir(struct dentry *dentry, | |||
941 | const char *name, | 1077 | const char *name, |
942 | struct rpc_clnt *rpc_client) | 1078 | struct rpc_clnt *rpc_client) |
943 | { | 1079 | { |
944 | return rpc_mkdir_populate(dentry, name, S_IRUGO | S_IXUGO, NULL, | 1080 | struct dentry *ret; |
1081 | |||
1082 | ret = rpc_mkdir_populate(dentry, name, S_IRUGO | S_IXUGO, NULL, | ||
945 | rpc_clntdir_populate, rpc_client); | 1083 | rpc_clntdir_populate, rpc_client); |
1084 | if (!IS_ERR(ret)) { | ||
1085 | rpc_client->cl_pipedir_objects.pdh_dentry = ret; | ||
1086 | rpc_create_pipe_dir_objects(&rpc_client->cl_pipedir_objects); | ||
1087 | } | ||
1088 | return ret; | ||
946 | } | 1089 | } |
947 | 1090 | ||
948 | /** | 1091 | /** |
949 | * rpc_remove_client_dir - Remove a directory created with rpc_create_client_dir() | 1092 | * rpc_remove_client_dir - Remove a directory created with rpc_create_client_dir() |
950 | * @dentry: dentry for the pipe | 1093 | * @rpc_client: rpc_client for the pipe |
951 | */ | 1094 | */ |
952 | int rpc_remove_client_dir(struct dentry *dentry) | 1095 | int rpc_remove_client_dir(struct rpc_clnt *rpc_client) |
953 | { | 1096 | { |
1097 | struct dentry *dentry = rpc_client->cl_pipedir_objects.pdh_dentry; | ||
1098 | |||
1099 | if (dentry == NULL) | ||
1100 | return 0; | ||
1101 | rpc_destroy_pipe_dir_objects(&rpc_client->cl_pipedir_objects); | ||
1102 | rpc_client->cl_pipedir_objects.pdh_dentry = NULL; | ||
954 | return rpc_rmdir_depopulate(dentry, rpc_clntdir_depopulate); | 1103 | return rpc_rmdir_depopulate(dentry, rpc_clntdir_depopulate); |
955 | } | 1104 | } |
956 | 1105 | ||
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index 93a7a4e94d80..ff3cc4bf4b24 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c | |||
@@ -258,7 +258,7 @@ static int rpc_wait_bit_killable(void *word) | |||
258 | return 0; | 258 | return 0; |
259 | } | 259 | } |
260 | 260 | ||
261 | #ifdef RPC_DEBUG | 261 | #if defined(RPC_DEBUG) || defined(RPC_TRACEPOINTS) |
262 | static void rpc_task_set_debuginfo(struct rpc_task *task) | 262 | static void rpc_task_set_debuginfo(struct rpc_task *task) |
263 | { | 263 | { |
264 | static atomic_t rpc_pid; | 264 | static atomic_t rpc_pid; |
diff --git a/net/sunrpc/stats.c b/net/sunrpc/stats.c index 21b75cb08c03..54530490944e 100644 --- a/net/sunrpc/stats.c +++ b/net/sunrpc/stats.c | |||
@@ -188,7 +188,7 @@ void rpc_print_iostats(struct seq_file *seq, struct rpc_clnt *clnt) | |||
188 | 188 | ||
189 | seq_printf(seq, "\tRPC iostats version: %s ", RPC_IOSTATS_VERS); | 189 | seq_printf(seq, "\tRPC iostats version: %s ", RPC_IOSTATS_VERS); |
190 | seq_printf(seq, "p/v: %u/%u (%s)\n", | 190 | seq_printf(seq, "p/v: %u/%u (%s)\n", |
191 | clnt->cl_prog, clnt->cl_vers, clnt->cl_protname); | 191 | clnt->cl_prog, clnt->cl_vers, clnt->cl_program->name); |
192 | 192 | ||
193 | rcu_read_lock(); | 193 | rcu_read_lock(); |
194 | xprt = rcu_dereference(clnt->cl_xprt); | 194 | xprt = rcu_dereference(clnt->cl_xprt); |
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index d6656d7768f4..ee03d35677d9 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c | |||
@@ -47,6 +47,8 @@ | |||
47 | #include <net/udp.h> | 47 | #include <net/udp.h> |
48 | #include <net/tcp.h> | 48 | #include <net/tcp.h> |
49 | 49 | ||
50 | #include <trace/events/sunrpc.h> | ||
51 | |||
50 | #include "sunrpc.h" | 52 | #include "sunrpc.h" |
51 | 53 | ||
52 | static void xs_close(struct rpc_xprt *xprt); | 54 | static void xs_close(struct rpc_xprt *xprt); |
@@ -665,8 +667,10 @@ static void xs_tcp_shutdown(struct rpc_xprt *xprt) | |||
665 | struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); | 667 | struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); |
666 | struct socket *sock = transport->sock; | 668 | struct socket *sock = transport->sock; |
667 | 669 | ||
668 | if (sock != NULL) | 670 | if (sock != NULL) { |
669 | kernel_sock_shutdown(sock, SHUT_WR); | 671 | kernel_sock_shutdown(sock, SHUT_WR); |
672 | trace_rpc_socket_shutdown(xprt, sock); | ||
673 | } | ||
670 | } | 674 | } |
671 | 675 | ||
672 | /** | 676 | /** |
@@ -811,6 +815,7 @@ static void xs_reset_transport(struct sock_xprt *transport) | |||
811 | 815 | ||
812 | sk->sk_no_check = 0; | 816 | sk->sk_no_check = 0; |
813 | 817 | ||
818 | trace_rpc_socket_close(&transport->xprt, sock); | ||
814 | sock_release(sock); | 819 | sock_release(sock); |
815 | } | 820 | } |
816 | 821 | ||
@@ -1492,6 +1497,7 @@ static void xs_tcp_state_change(struct sock *sk) | |||
1492 | sock_flag(sk, SOCK_ZAPPED), | 1497 | sock_flag(sk, SOCK_ZAPPED), |
1493 | sk->sk_shutdown); | 1498 | sk->sk_shutdown); |
1494 | 1499 | ||
1500 | trace_rpc_socket_state_change(xprt, sk->sk_socket); | ||
1495 | switch (sk->sk_state) { | 1501 | switch (sk->sk_state) { |
1496 | case TCP_ESTABLISHED: | 1502 | case TCP_ESTABLISHED: |
1497 | spin_lock(&xprt->transport_lock); | 1503 | spin_lock(&xprt->transport_lock); |
@@ -1896,6 +1902,7 @@ static int xs_local_setup_socket(struct sock_xprt *transport) | |||
1896 | xprt, xprt->address_strings[RPC_DISPLAY_ADDR]); | 1902 | xprt, xprt->address_strings[RPC_DISPLAY_ADDR]); |
1897 | 1903 | ||
1898 | status = xs_local_finish_connecting(xprt, sock); | 1904 | status = xs_local_finish_connecting(xprt, sock); |
1905 | trace_rpc_socket_connect(xprt, sock, status); | ||
1899 | switch (status) { | 1906 | switch (status) { |
1900 | case 0: | 1907 | case 0: |
1901 | dprintk("RPC: xprt %p connected to %s\n", | 1908 | dprintk("RPC: xprt %p connected to %s\n", |
@@ -2039,6 +2046,7 @@ static void xs_udp_setup_socket(struct work_struct *work) | |||
2039 | xprt->address_strings[RPC_DISPLAY_PORT]); | 2046 | xprt->address_strings[RPC_DISPLAY_PORT]); |
2040 | 2047 | ||
2041 | xs_udp_finish_connecting(xprt, sock); | 2048 | xs_udp_finish_connecting(xprt, sock); |
2049 | trace_rpc_socket_connect(xprt, sock, 0); | ||
2042 | status = 0; | 2050 | status = 0; |
2043 | out: | 2051 | out: |
2044 | xprt_clear_connecting(xprt); | 2052 | xprt_clear_connecting(xprt); |
@@ -2064,6 +2072,8 @@ static void xs_abort_connection(struct sock_xprt *transport) | |||
2064 | memset(&any, 0, sizeof(any)); | 2072 | memset(&any, 0, sizeof(any)); |
2065 | any.sa_family = AF_UNSPEC; | 2073 | any.sa_family = AF_UNSPEC; |
2066 | result = kernel_connect(transport->sock, &any, sizeof(any), 0); | 2074 | result = kernel_connect(transport->sock, &any, sizeof(any), 0); |
2075 | trace_rpc_socket_reset_connection(&transport->xprt, | ||
2076 | transport->sock, result); | ||
2067 | if (!result) | 2077 | if (!result) |
2068 | xs_sock_reset_connection_flags(&transport->xprt); | 2078 | xs_sock_reset_connection_flags(&transport->xprt); |
2069 | dprintk("RPC: AF_UNSPEC connect return code %d\n", result); | 2079 | dprintk("RPC: AF_UNSPEC connect return code %d\n", result); |
@@ -2194,6 +2204,7 @@ static void xs_tcp_setup_socket(struct work_struct *work) | |||
2194 | xprt->address_strings[RPC_DISPLAY_PORT]); | 2204 | xprt->address_strings[RPC_DISPLAY_PORT]); |
2195 | 2205 | ||
2196 | status = xs_tcp_finish_connecting(xprt, sock); | 2206 | status = xs_tcp_finish_connecting(xprt, sock); |
2207 | trace_rpc_socket_connect(xprt, sock, status); | ||
2197 | dprintk("RPC: %p connect status %d connected %d sock state %d\n", | 2208 | dprintk("RPC: %p connect status %d connected %d sock state %d\n", |
2198 | xprt, -status, xprt_connected(xprt), | 2209 | xprt, -status, xprt_connected(xprt), |
2199 | sock->sk->sk_state); | 2210 | sock->sk->sk_state); |