diff options
Diffstat (limited to 'net/sunrpc')
-rw-r--r-- | net/sunrpc/cache.c | 66 | ||||
-rw-r--r-- | net/sunrpc/svcauth_unix.c | 1 | ||||
-rw-r--r-- | net/sunrpc/svcsock.c | 84 | ||||
-rw-r--r-- | net/sunrpc/xprtrdma/svc_rdma_transport.c | 4 |
4 files changed, 100 insertions, 55 deletions
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index 45cdaff9b361..ade8a7e99cd3 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c | |||
@@ -103,7 +103,7 @@ struct cache_head *sunrpc_cache_lookup(struct cache_detail *detail, | |||
103 | EXPORT_SYMBOL_GPL(sunrpc_cache_lookup); | 103 | EXPORT_SYMBOL_GPL(sunrpc_cache_lookup); |
104 | 104 | ||
105 | 105 | ||
106 | static void queue_loose(struct cache_detail *detail, struct cache_head *ch); | 106 | static void cache_dequeue(struct cache_detail *detail, struct cache_head *ch); |
107 | 107 | ||
108 | static int cache_fresh_locked(struct cache_head *head, time_t expiry) | 108 | static int cache_fresh_locked(struct cache_head *head, time_t expiry) |
109 | { | 109 | { |
@@ -119,7 +119,7 @@ static void cache_fresh_unlocked(struct cache_head *head, | |||
119 | cache_revisit_request(head); | 119 | cache_revisit_request(head); |
120 | if (test_and_clear_bit(CACHE_PENDING, &head->flags)) { | 120 | if (test_and_clear_bit(CACHE_PENDING, &head->flags)) { |
121 | cache_revisit_request(head); | 121 | cache_revisit_request(head); |
122 | queue_loose(detail, head); | 122 | cache_dequeue(detail, head); |
123 | } | 123 | } |
124 | } | 124 | } |
125 | 125 | ||
@@ -184,6 +184,22 @@ static int cache_make_upcall(struct cache_detail *cd, struct cache_head *h) | |||
184 | return cd->cache_upcall(cd, h); | 184 | return cd->cache_upcall(cd, h); |
185 | } | 185 | } |
186 | 186 | ||
187 | static inline int cache_is_valid(struct cache_detail *detail, struct cache_head *h) | ||
188 | { | ||
189 | if (!test_bit(CACHE_VALID, &h->flags) || | ||
190 | h->expiry_time < get_seconds()) | ||
191 | return -EAGAIN; | ||
192 | else if (detail->flush_time > h->last_refresh) | ||
193 | return -EAGAIN; | ||
194 | else { | ||
195 | /* entry is valid */ | ||
196 | if (test_bit(CACHE_NEGATIVE, &h->flags)) | ||
197 | return -ENOENT; | ||
198 | else | ||
199 | return 0; | ||
200 | } | ||
201 | } | ||
202 | |||
187 | /* | 203 | /* |
188 | * This is the generic cache management routine for all | 204 | * This is the generic cache management routine for all |
189 | * the authentication caches. | 205 | * the authentication caches. |
@@ -192,8 +208,10 @@ static int cache_make_upcall(struct cache_detail *cd, struct cache_head *h) | |||
192 | * | 208 | * |
193 | * | 209 | * |
194 | * Returns 0 if the cache_head can be used, or cache_puts it and returns | 210 | * Returns 0 if the cache_head can be used, or cache_puts it and returns |
195 | * -EAGAIN if upcall is pending, | 211 | * -EAGAIN if upcall is pending and request has been queued |
196 | * -ETIMEDOUT if upcall failed and should be retried, | 212 | * -ETIMEDOUT if upcall failed or request could not be queue or |
213 | * upcall completed but item is still invalid (implying that | ||
214 | * the cache item has been replaced with a newer one). | ||
197 | * -ENOENT if cache entry was negative | 215 | * -ENOENT if cache entry was negative |
198 | */ | 216 | */ |
199 | int cache_check(struct cache_detail *detail, | 217 | int cache_check(struct cache_detail *detail, |
@@ -203,17 +221,7 @@ int cache_check(struct cache_detail *detail, | |||
203 | long refresh_age, age; | 221 | long refresh_age, age; |
204 | 222 | ||
205 | /* First decide return status as best we can */ | 223 | /* First decide return status as best we can */ |
206 | if (!test_bit(CACHE_VALID, &h->flags) || | 224 | rv = cache_is_valid(detail, h); |
207 | h->expiry_time < get_seconds()) | ||
208 | rv = -EAGAIN; | ||
209 | else if (detail->flush_time > h->last_refresh) | ||
210 | rv = -EAGAIN; | ||
211 | else { | ||
212 | /* entry is valid */ | ||
213 | if (test_bit(CACHE_NEGATIVE, &h->flags)) | ||
214 | rv = -ENOENT; | ||
215 | else rv = 0; | ||
216 | } | ||
217 | 225 | ||
218 | /* now see if we want to start an upcall */ | 226 | /* now see if we want to start an upcall */ |
219 | refresh_age = (h->expiry_time - h->last_refresh); | 227 | refresh_age = (h->expiry_time - h->last_refresh); |
@@ -229,6 +237,7 @@ int cache_check(struct cache_detail *detail, | |||
229 | switch (cache_make_upcall(detail, h)) { | 237 | switch (cache_make_upcall(detail, h)) { |
230 | case -EINVAL: | 238 | case -EINVAL: |
231 | clear_bit(CACHE_PENDING, &h->flags); | 239 | clear_bit(CACHE_PENDING, &h->flags); |
240 | cache_revisit_request(h); | ||
232 | if (rv == -EAGAIN) { | 241 | if (rv == -EAGAIN) { |
233 | set_bit(CACHE_NEGATIVE, &h->flags); | 242 | set_bit(CACHE_NEGATIVE, &h->flags); |
234 | cache_fresh_unlocked(h, detail, | 243 | cache_fresh_unlocked(h, detail, |
@@ -245,10 +254,14 @@ int cache_check(struct cache_detail *detail, | |||
245 | } | 254 | } |
246 | } | 255 | } |
247 | 256 | ||
248 | if (rv == -EAGAIN) | 257 | if (rv == -EAGAIN) { |
249 | if (cache_defer_req(rqstp, h) != 0) | 258 | if (cache_defer_req(rqstp, h) == 0) { |
250 | rv = -ETIMEDOUT; | 259 | /* Request is not deferred */ |
251 | 260 | rv = cache_is_valid(detail, h); | |
261 | if (rv == -EAGAIN) | ||
262 | rv = -ETIMEDOUT; | ||
263 | } | ||
264 | } | ||
252 | if (rv) | 265 | if (rv) |
253 | cache_put(h, detail); | 266 | cache_put(h, detail); |
254 | return rv; | 267 | return rv; |
@@ -396,7 +409,7 @@ static int cache_clean(void) | |||
396 | ) | 409 | ) |
397 | continue; | 410 | continue; |
398 | if (test_and_clear_bit(CACHE_PENDING, &ch->flags)) | 411 | if (test_and_clear_bit(CACHE_PENDING, &ch->flags)) |
399 | queue_loose(current_detail, ch); | 412 | cache_dequeue(current_detail, ch); |
400 | 413 | ||
401 | if (atomic_read(&ch->ref.refcount) == 1) | 414 | if (atomic_read(&ch->ref.refcount) == 1) |
402 | break; | 415 | break; |
@@ -412,8 +425,10 @@ static int cache_clean(void) | |||
412 | if (!ch) | 425 | if (!ch) |
413 | current_index ++; | 426 | current_index ++; |
414 | spin_unlock(&cache_list_lock); | 427 | spin_unlock(&cache_list_lock); |
415 | if (ch) | 428 | if (ch) { |
429 | cache_revisit_request(ch); | ||
416 | cache_put(ch, d); | 430 | cache_put(ch, d); |
431 | } | ||
417 | } else | 432 | } else |
418 | spin_unlock(&cache_list_lock); | 433 | spin_unlock(&cache_list_lock); |
419 | 434 | ||
@@ -496,11 +511,11 @@ static int cache_defer_req(struct cache_req *req, struct cache_head *item) | |||
496 | * or continue and drop the oldest below | 511 | * or continue and drop the oldest below |
497 | */ | 512 | */ |
498 | if (net_random()&1) | 513 | if (net_random()&1) |
499 | return -ETIMEDOUT; | 514 | return 0; |
500 | } | 515 | } |
501 | dreq = req->defer(req); | 516 | dreq = req->defer(req); |
502 | if (dreq == NULL) | 517 | if (dreq == NULL) |
503 | return -ETIMEDOUT; | 518 | return 0; |
504 | 519 | ||
505 | dreq->item = item; | 520 | dreq->item = item; |
506 | 521 | ||
@@ -530,8 +545,9 @@ static int cache_defer_req(struct cache_req *req, struct cache_head *item) | |||
530 | if (!test_bit(CACHE_PENDING, &item->flags)) { | 545 | if (!test_bit(CACHE_PENDING, &item->flags)) { |
531 | /* must have just been validated... */ | 546 | /* must have just been validated... */ |
532 | cache_revisit_request(item); | 547 | cache_revisit_request(item); |
548 | return 0; | ||
533 | } | 549 | } |
534 | return 0; | 550 | return 1; |
535 | } | 551 | } |
536 | 552 | ||
537 | static void cache_revisit_request(struct cache_head *item) | 553 | static void cache_revisit_request(struct cache_head *item) |
@@ -887,7 +903,7 @@ static int cache_release(struct inode *inode, struct file *filp, | |||
887 | 903 | ||
888 | 904 | ||
889 | 905 | ||
890 | static void queue_loose(struct cache_detail *detail, struct cache_head *ch) | 906 | static void cache_dequeue(struct cache_detail *detail, struct cache_head *ch) |
891 | { | 907 | { |
892 | struct cache_queue *cq; | 908 | struct cache_queue *cq; |
893 | spin_lock(&queue_lock); | 909 | spin_lock(&queue_lock); |
diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c index 6caffa34ac01..117f68a8aa40 100644 --- a/net/sunrpc/svcauth_unix.c +++ b/net/sunrpc/svcauth_unix.c | |||
@@ -668,6 +668,7 @@ static int unix_gid_find(uid_t uid, struct group_info **gip, | |||
668 | case 0: | 668 | case 0: |
669 | *gip = ug->gi; | 669 | *gip = ug->gi; |
670 | get_group_info(*gip); | 670 | get_group_info(*gip); |
671 | cache_put(&ug->h, &unix_gid_cache); | ||
671 | return 0; | 672 | return 0; |
672 | default: | 673 | default: |
673 | return -EAGAIN; | 674 | return -EAGAIN; |
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index 23128ee191ae..99a826dcc32e 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c | |||
@@ -432,29 +432,49 @@ static void svc_tcp_write_space(struct sock *sk) | |||
432 | } | 432 | } |
433 | 433 | ||
434 | /* | 434 | /* |
435 | * See net/ipv6/ip_sockglue.c : ip_cmsg_recv_pktinfo | ||
436 | */ | ||
437 | static int svc_udp_get_dest_address4(struct svc_rqst *rqstp, | ||
438 | struct cmsghdr *cmh) | ||
439 | { | ||
440 | struct in_pktinfo *pki = CMSG_DATA(cmh); | ||
441 | if (cmh->cmsg_type != IP_PKTINFO) | ||
442 | return 0; | ||
443 | rqstp->rq_daddr.addr.s_addr = pki->ipi_spec_dst.s_addr; | ||
444 | return 1; | ||
445 | } | ||
446 | |||
447 | /* | ||
448 | * See net/ipv6/datagram.c : datagram_recv_ctl | ||
449 | */ | ||
450 | static int svc_udp_get_dest_address6(struct svc_rqst *rqstp, | ||
451 | struct cmsghdr *cmh) | ||
452 | { | ||
453 | struct in6_pktinfo *pki = CMSG_DATA(cmh); | ||
454 | if (cmh->cmsg_type != IPV6_PKTINFO) | ||
455 | return 0; | ||
456 | ipv6_addr_copy(&rqstp->rq_daddr.addr6, &pki->ipi6_addr); | ||
457 | return 1; | ||
458 | } | ||
459 | |||
460 | /* | ||
435 | * Copy the UDP datagram's destination address to the rqstp structure. | 461 | * Copy the UDP datagram's destination address to the rqstp structure. |
436 | * The 'destination' address in this case is the address to which the | 462 | * The 'destination' address in this case is the address to which the |
437 | * peer sent the datagram, i.e. our local address. For multihomed | 463 | * peer sent the datagram, i.e. our local address. For multihomed |
438 | * hosts, this can change from msg to msg. Note that only the IP | 464 | * hosts, this can change from msg to msg. Note that only the IP |
439 | * address changes, the port number should remain the same. | 465 | * address changes, the port number should remain the same. |
440 | */ | 466 | */ |
441 | static void svc_udp_get_dest_address(struct svc_rqst *rqstp, | 467 | static int svc_udp_get_dest_address(struct svc_rqst *rqstp, |
442 | struct cmsghdr *cmh) | 468 | struct cmsghdr *cmh) |
443 | { | 469 | { |
444 | struct svc_sock *svsk = | 470 | switch (cmh->cmsg_level) { |
445 | container_of(rqstp->rq_xprt, struct svc_sock, sk_xprt); | 471 | case SOL_IP: |
446 | switch (svsk->sk_sk->sk_family) { | 472 | return svc_udp_get_dest_address4(rqstp, cmh); |
447 | case AF_INET: { | 473 | case SOL_IPV6: |
448 | struct in_pktinfo *pki = CMSG_DATA(cmh); | 474 | return svc_udp_get_dest_address6(rqstp, cmh); |
449 | rqstp->rq_daddr.addr.s_addr = pki->ipi_spec_dst.s_addr; | ||
450 | break; | ||
451 | } | ||
452 | case AF_INET6: { | ||
453 | struct in6_pktinfo *pki = CMSG_DATA(cmh); | ||
454 | ipv6_addr_copy(&rqstp->rq_daddr.addr6, &pki->ipi6_addr); | ||
455 | break; | ||
456 | } | ||
457 | } | 475 | } |
476 | |||
477 | return 0; | ||
458 | } | 478 | } |
459 | 479 | ||
460 | /* | 480 | /* |
@@ -531,16 +551,15 @@ static int svc_udp_recvfrom(struct svc_rqst *rqstp) | |||
531 | 551 | ||
532 | rqstp->rq_prot = IPPROTO_UDP; | 552 | rqstp->rq_prot = IPPROTO_UDP; |
533 | 553 | ||
534 | if (cmh->cmsg_level != IPPROTO_IP || | 554 | if (!svc_udp_get_dest_address(rqstp, cmh)) { |
535 | cmh->cmsg_type != IP_PKTINFO) { | ||
536 | if (net_ratelimit()) | 555 | if (net_ratelimit()) |
537 | printk("rpcsvc: received unknown control message:" | 556 | printk(KERN_WARNING |
538 | "%d/%d\n", | 557 | "svc: received unknown control message %d/%d; " |
539 | cmh->cmsg_level, cmh->cmsg_type); | 558 | "dropping RPC reply datagram\n", |
559 | cmh->cmsg_level, cmh->cmsg_type); | ||
540 | skb_free_datagram(svsk->sk_sk, skb); | 560 | skb_free_datagram(svsk->sk_sk, skb); |
541 | return 0; | 561 | return 0; |
542 | } | 562 | } |
543 | svc_udp_get_dest_address(rqstp, cmh); | ||
544 | 563 | ||
545 | if (skb_is_nonlinear(skb)) { | 564 | if (skb_is_nonlinear(skb)) { |
546 | /* we have to copy */ | 565 | /* we have to copy */ |
@@ -651,8 +670,7 @@ static struct svc_xprt_class svc_udp_class = { | |||
651 | 670 | ||
652 | static void svc_udp_init(struct svc_sock *svsk, struct svc_serv *serv) | 671 | static void svc_udp_init(struct svc_sock *svsk, struct svc_serv *serv) |
653 | { | 672 | { |
654 | int one = 1; | 673 | int err, level, optname, one = 1; |
655 | mm_segment_t oldfs; | ||
656 | 674 | ||
657 | svc_xprt_init(&svc_udp_class, &svsk->sk_xprt, serv); | 675 | svc_xprt_init(&svc_udp_class, &svsk->sk_xprt, serv); |
658 | clear_bit(XPT_CACHE_AUTH, &svsk->sk_xprt.xpt_flags); | 676 | clear_bit(XPT_CACHE_AUTH, &svsk->sk_xprt.xpt_flags); |
@@ -671,12 +689,22 @@ static void svc_udp_init(struct svc_sock *svsk, struct svc_serv *serv) | |||
671 | set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags); | 689 | set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags); |
672 | set_bit(XPT_CHNGBUF, &svsk->sk_xprt.xpt_flags); | 690 | set_bit(XPT_CHNGBUF, &svsk->sk_xprt.xpt_flags); |
673 | 691 | ||
674 | oldfs = get_fs(); | ||
675 | set_fs(KERNEL_DS); | ||
676 | /* make sure we get destination address info */ | 692 | /* make sure we get destination address info */ |
677 | svsk->sk_sock->ops->setsockopt(svsk->sk_sock, IPPROTO_IP, IP_PKTINFO, | 693 | switch (svsk->sk_sk->sk_family) { |
678 | (char __user *)&one, sizeof(one)); | 694 | case AF_INET: |
679 | set_fs(oldfs); | 695 | level = SOL_IP; |
696 | optname = IP_PKTINFO; | ||
697 | break; | ||
698 | case AF_INET6: | ||
699 | level = SOL_IPV6; | ||
700 | optname = IPV6_RECVPKTINFO; | ||
701 | break; | ||
702 | default: | ||
703 | BUG(); | ||
704 | } | ||
705 | err = kernel_setsockopt(svsk->sk_sock, level, optname, | ||
706 | (char *)&one, sizeof(one)); | ||
707 | dprintk("svc: kernel_setsockopt returned %d\n", err); | ||
680 | } | 708 | } |
681 | 709 | ||
682 | /* | 710 | /* |
diff --git a/net/sunrpc/xprtrdma/svc_rdma_transport.c b/net/sunrpc/xprtrdma/svc_rdma_transport.c index 5151f9f6c573..0cf5e8c27a10 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_transport.c +++ b/net/sunrpc/xprtrdma/svc_rdma_transport.c | |||
@@ -730,12 +730,12 @@ static struct svc_rdma_fastreg_mr *rdma_alloc_frmr(struct svcxprt_rdma *xprt) | |||
730 | goto err; | 730 | goto err; |
731 | 731 | ||
732 | mr = ib_alloc_fast_reg_mr(xprt->sc_pd, RPCSVC_MAXPAGES); | 732 | mr = ib_alloc_fast_reg_mr(xprt->sc_pd, RPCSVC_MAXPAGES); |
733 | if (!mr) | 733 | if (IS_ERR(mr)) |
734 | goto err_free_frmr; | 734 | goto err_free_frmr; |
735 | 735 | ||
736 | pl = ib_alloc_fast_reg_page_list(xprt->sc_cm_id->device, | 736 | pl = ib_alloc_fast_reg_page_list(xprt->sc_cm_id->device, |
737 | RPCSVC_MAXPAGES); | 737 | RPCSVC_MAXPAGES); |
738 | if (!pl) | 738 | if (IS_ERR(pl)) |
739 | goto err_free_mr; | 739 | goto err_free_mr; |
740 | 740 | ||
741 | frmr->mr = mr; | 741 | frmr->mr = mr; |