diff options
Diffstat (limited to 'net/sunrpc/svcsock.c')
-rw-r--r-- | net/sunrpc/svcsock.c | 29 |
1 files changed, 15 insertions, 14 deletions
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index c475977de05..3e65719f1ef 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <net/checksum.h> | 38 | #include <net/checksum.h> |
39 | #include <net/ip.h> | 39 | #include <net/ip.h> |
40 | #include <net/ipv6.h> | 40 | #include <net/ipv6.h> |
41 | #include <net/tcp.h> | ||
41 | #include <net/tcp_states.h> | 42 | #include <net/tcp_states.h> |
42 | #include <asm/uaccess.h> | 43 | #include <asm/uaccess.h> |
43 | #include <asm/ioctls.h> | 44 | #include <asm/ioctls.h> |
@@ -45,6 +46,7 @@ | |||
45 | #include <linux/sunrpc/types.h> | 46 | #include <linux/sunrpc/types.h> |
46 | #include <linux/sunrpc/clnt.h> | 47 | #include <linux/sunrpc/clnt.h> |
47 | #include <linux/sunrpc/xdr.h> | 48 | #include <linux/sunrpc/xdr.h> |
49 | #include <linux/sunrpc/msg_prot.h> | ||
48 | #include <linux/sunrpc/svcsock.h> | 50 | #include <linux/sunrpc/svcsock.h> |
49 | #include <linux/sunrpc/stats.h> | 51 | #include <linux/sunrpc/stats.h> |
50 | 52 | ||
@@ -822,8 +824,8 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp) | |||
822 | * the next four bytes. Otherwise try to gobble up as much as | 824 | * the next four bytes. Otherwise try to gobble up as much as |
823 | * possible up to the complete record length. | 825 | * possible up to the complete record length. |
824 | */ | 826 | */ |
825 | if (svsk->sk_tcplen < 4) { | 827 | if (svsk->sk_tcplen < sizeof(rpc_fraghdr)) { |
826 | unsigned long want = 4 - svsk->sk_tcplen; | 828 | int want = sizeof(rpc_fraghdr) - svsk->sk_tcplen; |
827 | struct kvec iov; | 829 | struct kvec iov; |
828 | 830 | ||
829 | iov.iov_base = ((char *) &svsk->sk_reclen) + svsk->sk_tcplen; | 831 | iov.iov_base = ((char *) &svsk->sk_reclen) + svsk->sk_tcplen; |
@@ -833,32 +835,31 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp) | |||
833 | svsk->sk_tcplen += len; | 835 | svsk->sk_tcplen += len; |
834 | 836 | ||
835 | if (len < want) { | 837 | if (len < want) { |
836 | dprintk("svc: short recvfrom while reading record length (%d of %lu)\n", | 838 | dprintk("svc: short recvfrom while reading record " |
837 | len, want); | 839 | "length (%d of %d)\n", len, want); |
838 | svc_xprt_received(&svsk->sk_xprt); | 840 | svc_xprt_received(&svsk->sk_xprt); |
839 | return -EAGAIN; /* record header not complete */ | 841 | return -EAGAIN; /* record header not complete */ |
840 | } | 842 | } |
841 | 843 | ||
842 | svsk->sk_reclen = ntohl(svsk->sk_reclen); | 844 | svsk->sk_reclen = ntohl(svsk->sk_reclen); |
843 | if (!(svsk->sk_reclen & 0x80000000)) { | 845 | if (!(svsk->sk_reclen & RPC_LAST_STREAM_FRAGMENT)) { |
844 | /* FIXME: technically, a record can be fragmented, | 846 | /* FIXME: technically, a record can be fragmented, |
845 | * and non-terminal fragments will not have the top | 847 | * and non-terminal fragments will not have the top |
846 | * bit set in the fragment length header. | 848 | * bit set in the fragment length header. |
847 | * But apparently no known nfs clients send fragmented | 849 | * But apparently no known nfs clients send fragmented |
848 | * records. */ | 850 | * records. */ |
849 | if (net_ratelimit()) | 851 | if (net_ratelimit()) |
850 | printk(KERN_NOTICE "RPC: bad TCP reclen 0x%08lx" | 852 | printk(KERN_NOTICE "RPC: multiple fragments " |
851 | " (non-terminal)\n", | 853 | "per record not supported\n"); |
852 | (unsigned long) svsk->sk_reclen); | ||
853 | goto err_delete; | 854 | goto err_delete; |
854 | } | 855 | } |
855 | svsk->sk_reclen &= 0x7fffffff; | 856 | svsk->sk_reclen &= RPC_FRAGMENT_SIZE_MASK; |
856 | dprintk("svc: TCP record, %d bytes\n", svsk->sk_reclen); | 857 | dprintk("svc: TCP record, %d bytes\n", svsk->sk_reclen); |
857 | if (svsk->sk_reclen > serv->sv_max_mesg) { | 858 | if (svsk->sk_reclen > serv->sv_max_mesg) { |
858 | if (net_ratelimit()) | 859 | if (net_ratelimit()) |
859 | printk(KERN_NOTICE "RPC: bad TCP reclen 0x%08lx" | 860 | printk(KERN_NOTICE "RPC: " |
860 | " (large)\n", | 861 | "fragment too large: 0x%08lx\n", |
861 | (unsigned long) svsk->sk_reclen); | 862 | (unsigned long)svsk->sk_reclen); |
862 | goto err_delete; | 863 | goto err_delete; |
863 | } | 864 | } |
864 | } | 865 | } |
@@ -1045,7 +1046,6 @@ void svc_cleanup_xprt_sock(void) | |||
1045 | static void svc_tcp_init(struct svc_sock *svsk, struct svc_serv *serv) | 1046 | static void svc_tcp_init(struct svc_sock *svsk, struct svc_serv *serv) |
1046 | { | 1047 | { |
1047 | struct sock *sk = svsk->sk_sk; | 1048 | struct sock *sk = svsk->sk_sk; |
1048 | struct tcp_sock *tp = tcp_sk(sk); | ||
1049 | 1049 | ||
1050 | svc_xprt_init(&svc_tcp_class, &svsk->sk_xprt, serv); | 1050 | svc_xprt_init(&svc_tcp_class, &svsk->sk_xprt, serv); |
1051 | set_bit(XPT_CACHE_AUTH, &svsk->sk_xprt.xpt_flags); | 1051 | set_bit(XPT_CACHE_AUTH, &svsk->sk_xprt.xpt_flags); |
@@ -1063,7 +1063,7 @@ static void svc_tcp_init(struct svc_sock *svsk, struct svc_serv *serv) | |||
1063 | svsk->sk_reclen = 0; | 1063 | svsk->sk_reclen = 0; |
1064 | svsk->sk_tcplen = 0; | 1064 | svsk->sk_tcplen = 0; |
1065 | 1065 | ||
1066 | tp->nonagle = 1; /* disable Nagle's algorithm */ | 1066 | tcp_sk(sk)->nonagle |= TCP_NAGLE_OFF; |
1067 | 1067 | ||
1068 | /* initialise setting must have enough space to | 1068 | /* initialise setting must have enough space to |
1069 | * receive and respond to one request. | 1069 | * receive and respond to one request. |
@@ -1101,6 +1101,7 @@ void svc_sock_update_bufs(struct svc_serv *serv) | |||
1101 | } | 1101 | } |
1102 | spin_unlock_bh(&serv->sv_lock); | 1102 | spin_unlock_bh(&serv->sv_lock); |
1103 | } | 1103 | } |
1104 | EXPORT_SYMBOL(svc_sock_update_bufs); | ||
1104 | 1105 | ||
1105 | /* | 1106 | /* |
1106 | * Initialize socket for RPC use and create svc_sock struct | 1107 | * Initialize socket for RPC use and create svc_sock struct |