diff options
author | Chuck Lever <chuck.lever@oracle.com> | 2008-04-14 12:27:30 -0400 |
---|---|---|
committer | J. Bruce Fields <bfields@citi.umich.edu> | 2008-04-23 16:13:43 -0400 |
commit | c0401ea008fb7c785a93428752d69dccafb127ec (patch) | |
tree | c24c8c6e8871ecba8906098c0360bf3980fedf73 | |
parent | b7872fe86db78cc96c85a13338ea6e3fe1aef610 (diff) |
SUNRPC: Update RPC server's TCP record marker decoder
Clean up: Update the RPC server's TCP record marker decoder to match the
constructs used by the RPC client's TCP socket transport.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
-rw-r--r-- | include/linux/sunrpc/svcsock.h | 4 | ||||
-rw-r--r-- | net/sunrpc/svcsock.c | 24 |
2 files changed, 14 insertions, 14 deletions
diff --git a/include/linux/sunrpc/svcsock.h b/include/linux/sunrpc/svcsock.h index 206f092ad4c7..8cff696dedf5 100644 --- a/include/linux/sunrpc/svcsock.h +++ b/include/linux/sunrpc/svcsock.h | |||
@@ -26,8 +26,8 @@ struct svc_sock { | |||
26 | void (*sk_owspace)(struct sock *); | 26 | void (*sk_owspace)(struct sock *); |
27 | 27 | ||
28 | /* private TCP part */ | 28 | /* private TCP part */ |
29 | int sk_reclen; /* length of record */ | 29 | u32 sk_reclen; /* length of record */ |
30 | int sk_tcplen; /* current read length */ | 30 | u32 sk_tcplen; /* current read length */ |
31 | }; | 31 | }; |
32 | 32 | ||
33 | /* | 33 | /* |
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index 8b1bda3ea5c1..3e65719f1ef6 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c | |||
@@ -46,6 +46,7 @@ | |||
46 | #include <linux/sunrpc/types.h> | 46 | #include <linux/sunrpc/types.h> |
47 | #include <linux/sunrpc/clnt.h> | 47 | #include <linux/sunrpc/clnt.h> |
48 | #include <linux/sunrpc/xdr.h> | 48 | #include <linux/sunrpc/xdr.h> |
49 | #include <linux/sunrpc/msg_prot.h> | ||
49 | #include <linux/sunrpc/svcsock.h> | 50 | #include <linux/sunrpc/svcsock.h> |
50 | #include <linux/sunrpc/stats.h> | 51 | #include <linux/sunrpc/stats.h> |
51 | 52 | ||
@@ -823,8 +824,8 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp) | |||
823 | * 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 |
824 | * possible up to the complete record length. | 825 | * possible up to the complete record length. |
825 | */ | 826 | */ |
826 | if (svsk->sk_tcplen < 4) { | 827 | if (svsk->sk_tcplen < sizeof(rpc_fraghdr)) { |
827 | unsigned long want = 4 - svsk->sk_tcplen; | 828 | int want = sizeof(rpc_fraghdr) - svsk->sk_tcplen; |
828 | struct kvec iov; | 829 | struct kvec iov; |
829 | 830 | ||
830 | iov.iov_base = ((char *) &svsk->sk_reclen) + svsk->sk_tcplen; | 831 | iov.iov_base = ((char *) &svsk->sk_reclen) + svsk->sk_tcplen; |
@@ -834,32 +835,31 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp) | |||
834 | svsk->sk_tcplen += len; | 835 | svsk->sk_tcplen += len; |
835 | 836 | ||
836 | if (len < want) { | 837 | if (len < want) { |
837 | dprintk("svc: short recvfrom while reading record length (%d of %lu)\n", | 838 | dprintk("svc: short recvfrom while reading record " |
838 | len, want); | 839 | "length (%d of %d)\n", len, want); |
839 | svc_xprt_received(&svsk->sk_xprt); | 840 | svc_xprt_received(&svsk->sk_xprt); |
840 | return -EAGAIN; /* record header not complete */ | 841 | return -EAGAIN; /* record header not complete */ |
841 | } | 842 | } |
842 | 843 | ||
843 | svsk->sk_reclen = ntohl(svsk->sk_reclen); | 844 | svsk->sk_reclen = ntohl(svsk->sk_reclen); |
844 | if (!(svsk->sk_reclen & 0x80000000)) { | 845 | if (!(svsk->sk_reclen & RPC_LAST_STREAM_FRAGMENT)) { |
845 | /* FIXME: technically, a record can be fragmented, | 846 | /* FIXME: technically, a record can be fragmented, |
846 | * and non-terminal fragments will not have the top | 847 | * and non-terminal fragments will not have the top |
847 | * bit set in the fragment length header. | 848 | * bit set in the fragment length header. |
848 | * But apparently no known nfs clients send fragmented | 849 | * But apparently no known nfs clients send fragmented |
849 | * records. */ | 850 | * records. */ |
850 | if (net_ratelimit()) | 851 | if (net_ratelimit()) |
851 | printk(KERN_NOTICE "RPC: bad TCP reclen 0x%08lx" | 852 | printk(KERN_NOTICE "RPC: multiple fragments " |
852 | " (non-terminal)\n", | 853 | "per record not supported\n"); |
853 | (unsigned long) svsk->sk_reclen); | ||
854 | goto err_delete; | 854 | goto err_delete; |
855 | } | 855 | } |
856 | svsk->sk_reclen &= 0x7fffffff; | 856 | svsk->sk_reclen &= RPC_FRAGMENT_SIZE_MASK; |
857 | dprintk("svc: TCP record, %d bytes\n", svsk->sk_reclen); | 857 | dprintk("svc: TCP record, %d bytes\n", svsk->sk_reclen); |
858 | if (svsk->sk_reclen > serv->sv_max_mesg) { | 858 | if (svsk->sk_reclen > serv->sv_max_mesg) { |
859 | if (net_ratelimit()) | 859 | if (net_ratelimit()) |
860 | printk(KERN_NOTICE "RPC: bad TCP reclen 0x%08lx" | 860 | printk(KERN_NOTICE "RPC: " |
861 | " (large)\n", | 861 | "fragment too large: 0x%08lx\n", |
862 | (unsigned long) svsk->sk_reclen); | 862 | (unsigned long)svsk->sk_reclen); |
863 | goto err_delete; | 863 | goto err_delete; |
864 | } | 864 | } |
865 | } | 865 | } |