aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTom Tucker <tom@opengridcomputing.com>2007-12-30 22:08:12 -0500
committerJ. Bruce Fields <bfields@citi.umich.edu>2008-02-01 16:42:12 -0500
commit9dbc240f199c16c3c0859c255ad52a663d8ee51d (patch)
tree0e81dd425c36590e65accfe9654d905632783c7f
parent8c7b0172a1db8120d25ecb4eff69664c52ee7639 (diff)
svc: Move the sockaddr information to svc_xprt
This patch moves the transport sockaddr to the svc_xprt structure. Convenience functions are added to set and get the local and remote addresses of a transport from the transport provider as well as determine the length of a sockaddr. A transport is responsible for setting the xpt_local and xpt_remote addresses in the svc_xprt structure as part of transport creation and xpo_accept processing. This cannot be done in a generic way and in fact varies between TCP, UDP and RDMA. A set of xpo_ functions (e.g. getlocalname, getremotename) could have been added but this would have resulted in additional caching and copying of the addresses around. Note that the xpt_local address should also be set on listening endpoints; for TCP/RDMA this is done as part of endpoint creation. For connected transports like TCP and RDMA, the addresses never change and can be set once and copied into the rqstp structure for each request. For UDP, however, the local and remote addresses may change for each request. In this case, the address information is obtained from the UDP recvmsg info and copied into the rqstp structure from there. A svc_xprt_local_port function was also added that returns the local port given a transport. This is used by svc_create_xprt when returning the port associated with a newly created transport, and later when creating a generic find transport service to check if a service is already listening on a given port. Signed-off-by: Tom Tucker <tom@opengridcomputing.com> Acked-by: Neil Brown <neilb@suse.de> Reviewed-by: Chuck Lever <chuck.lever@oracle.com> Reviewed-by: Greg Banks <gnb@sgi.com> Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
-rw-r--r--include/linux/sunrpc/svc_xprt.h51
-rw-r--r--include/linux/sunrpc/svcsock.h4
-rw-r--r--net/sunrpc/svc_xprt.c31
-rw-r--r--net/sunrpc/svcsock.c56
4 files changed, 110 insertions, 32 deletions
diff --git a/include/linux/sunrpc/svc_xprt.h b/include/linux/sunrpc/svc_xprt.h
index 6a8445b9dfd9..09de12b63c1d 100644
--- a/include/linux/sunrpc/svc_xprt.h
+++ b/include/linux/sunrpc/svc_xprt.h
@@ -61,6 +61,10 @@ struct svc_xprt {
61 void *xpt_auth_cache;/* auth cache */ 61 void *xpt_auth_cache;/* auth cache */
62 struct list_head xpt_deferred; /* deferred requests that need 62 struct list_head xpt_deferred; /* deferred requests that need
63 * to be revisted */ 63 * to be revisted */
64 struct sockaddr_storage xpt_local; /* local address */
65 size_t xpt_locallen; /* length of address */
66 struct sockaddr_storage xpt_remote; /* remote peer's address */
67 size_t xpt_remotelen; /* length of address */
64}; 68};
65 69
66int svc_reg_xprt_class(struct svc_xprt_class *); 70int svc_reg_xprt_class(struct svc_xprt_class *);
@@ -70,9 +74,56 @@ void svc_xprt_init(struct svc_xprt_class *, struct svc_xprt *,
70int svc_create_xprt(struct svc_serv *, char *, unsigned short, int); 74int svc_create_xprt(struct svc_serv *, char *, unsigned short, int);
71void svc_xprt_received(struct svc_xprt *); 75void svc_xprt_received(struct svc_xprt *);
72void svc_xprt_put(struct svc_xprt *xprt); 76void svc_xprt_put(struct svc_xprt *xprt);
77void svc_xprt_copy_addrs(struct svc_rqst *rqstp, struct svc_xprt *xprt);
73static inline void svc_xprt_get(struct svc_xprt *xprt) 78static inline void svc_xprt_get(struct svc_xprt *xprt)
74{ 79{
75 kref_get(&xprt->xpt_ref); 80 kref_get(&xprt->xpt_ref);
76} 81}
82static inline void svc_xprt_set_local(struct svc_xprt *xprt,
83 struct sockaddr *sa, int salen)
84{
85 memcpy(&xprt->xpt_local, sa, salen);
86 xprt->xpt_locallen = salen;
87}
88static inline void svc_xprt_set_remote(struct svc_xprt *xprt,
89 struct sockaddr *sa, int salen)
90{
91 memcpy(&xprt->xpt_remote, sa, salen);
92 xprt->xpt_remotelen = salen;
93}
94static inline unsigned short svc_addr_port(struct sockaddr *sa)
95{
96 unsigned short ret = 0;
97 switch (sa->sa_family) {
98 case AF_INET:
99 ret = ntohs(((struct sockaddr_in *)sa)->sin_port);
100 break;
101 case AF_INET6:
102 ret = ntohs(((struct sockaddr_in6 *)sa)->sin6_port);
103 break;
104 }
105 return ret;
106}
107
108static inline size_t svc_addr_len(struct sockaddr *sa)
109{
110 switch (sa->sa_family) {
111 case AF_INET:
112 return sizeof(struct sockaddr_in);
113 case AF_INET6:
114 return sizeof(struct sockaddr_in6);
115 }
116 return -EAFNOSUPPORT;
117}
118
119static inline unsigned short svc_xprt_local_port(struct svc_xprt *xprt)
120{
121 return svc_addr_port((struct sockaddr *)&xprt->xpt_local);
122}
123
124static inline unsigned short svc_xprt_remote_port(struct svc_xprt *xprt)
125{
126 return svc_addr_port((struct sockaddr *)&xprt->xpt_remote);
127}
77 128
78#endif /* SUNRPC_SVC_XPRT_H */ 129#endif /* SUNRPC_SVC_XPRT_H */
diff --git a/include/linux/sunrpc/svcsock.h b/include/linux/sunrpc/svcsock.h
index 96a229e6b9c9..206f092ad4c7 100644
--- a/include/linux/sunrpc/svcsock.h
+++ b/include/linux/sunrpc/svcsock.h
@@ -28,10 +28,6 @@ struct svc_sock {
28 /* private TCP part */ 28 /* private TCP part */
29 int sk_reclen; /* length of record */ 29 int sk_reclen; /* length of record */
30 int sk_tcplen; /* current read length */ 30 int sk_tcplen; /* current read length */
31
32 struct sockaddr_storage sk_local; /* local address */
33 struct sockaddr_storage sk_remote; /* remote peer's address */
34 int sk_remotelen; /* length of address */
35}; 31};
36 32
37/* 33/*
diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c
index 023aeb0ecfa9..eb650af50c49 100644
--- a/net/sunrpc/svc_xprt.c
+++ b/net/sunrpc/svc_xprt.c
@@ -125,7 +125,6 @@ int svc_create_xprt(struct svc_serv *serv, char *xprt_name, unsigned short port,
125 spin_unlock(&svc_xprt_class_lock); 125 spin_unlock(&svc_xprt_class_lock);
126 if (try_module_get(xcl->xcl_owner)) { 126 if (try_module_get(xcl->xcl_owner)) {
127 struct svc_xprt *newxprt; 127 struct svc_xprt *newxprt;
128 ret = 0;
129 newxprt = xcl->xcl_ops->xpo_create 128 newxprt = xcl->xcl_ops->xpo_create
130 (serv, 129 (serv,
131 (struct sockaddr *)&sin, sizeof(sin), 130 (struct sockaddr *)&sin, sizeof(sin),
@@ -133,7 +132,8 @@ int svc_create_xprt(struct svc_serv *serv, char *xprt_name, unsigned short port,
133 if (IS_ERR(newxprt)) { 132 if (IS_ERR(newxprt)) {
134 module_put(xcl->xcl_owner); 133 module_put(xcl->xcl_owner);
135 ret = PTR_ERR(newxprt); 134 ret = PTR_ERR(newxprt);
136 } 135 } else
136 ret = svc_xprt_local_port(newxprt);
137 } 137 }
138 goto out; 138 goto out;
139 } 139 }
@@ -144,3 +144,30 @@ int svc_create_xprt(struct svc_serv *serv, char *xprt_name, unsigned short port,
144 return ret; 144 return ret;
145} 145}
146EXPORT_SYMBOL_GPL(svc_create_xprt); 146EXPORT_SYMBOL_GPL(svc_create_xprt);
147
148/*
149 * Copy the local and remote xprt addresses to the rqstp structure
150 */
151void svc_xprt_copy_addrs(struct svc_rqst *rqstp, struct svc_xprt *xprt)
152{
153 struct sockaddr *sin;
154
155 memcpy(&rqstp->rq_addr, &xprt->xpt_remote, xprt->xpt_remotelen);
156 rqstp->rq_addrlen = xprt->xpt_remotelen;
157
158 /*
159 * Destination address in request is needed for binding the
160 * source address in RPC replies/callbacks later.
161 */
162 sin = (struct sockaddr *)&xprt->xpt_local;
163 switch (sin->sa_family) {
164 case AF_INET:
165 rqstp->rq_daddr.addr = ((struct sockaddr_in *)sin)->sin_addr;
166 break;
167 case AF_INET6:
168 rqstp->rq_daddr.addr6 = ((struct sockaddr_in6 *)sin)->sin6_addr;
169 break;
170 }
171}
172EXPORT_SYMBOL_GPL(svc_xprt_copy_addrs);
173
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index 9d0a9e6c0e10..9564d2e9520e 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -623,33 +623,13 @@ svc_recvfrom(struct svc_rqst *rqstp, struct kvec *iov, int nr, int buflen)
623 struct msghdr msg = { 623 struct msghdr msg = {
624 .msg_flags = MSG_DONTWAIT, 624 .msg_flags = MSG_DONTWAIT,
625 }; 625 };
626 struct sockaddr *sin;
627 int len; 626 int len;
628 627
629 len = kernel_recvmsg(svsk->sk_sock, &msg, iov, nr, buflen, 628 len = kernel_recvmsg(svsk->sk_sock, &msg, iov, nr, buflen,
630 msg.msg_flags); 629 msg.msg_flags);
631 630
632 /* sock_recvmsg doesn't fill in the name/namelen, so we must..
633 */
634 memcpy(&rqstp->rq_addr, &svsk->sk_remote, svsk->sk_remotelen);
635 rqstp->rq_addrlen = svsk->sk_remotelen;
636
637 /* Destination address in request is needed for binding the
638 * source address in RPC callbacks later.
639 */
640 sin = (struct sockaddr *)&svsk->sk_local;
641 switch (sin->sa_family) {
642 case AF_INET:
643 rqstp->rq_daddr.addr = ((struct sockaddr_in *)sin)->sin_addr;
644 break;
645 case AF_INET6:
646 rqstp->rq_daddr.addr6 = ((struct sockaddr_in6 *)sin)->sin6_addr;
647 break;
648 }
649
650 dprintk("svc: socket %p recvfrom(%p, %Zu) = %d\n", 631 dprintk("svc: socket %p recvfrom(%p, %Zu) = %d\n",
651 svsk, iov[0].iov_base, iov[0].iov_len, len); 632 svsk, iov[0].iov_base, iov[0].iov_len, len);
652
653 return len; 633 return len;
654} 634}
655 635
@@ -719,8 +699,15 @@ svc_write_space(struct sock *sk)
719 } 699 }
720} 700}
721 701
722static inline void svc_udp_get_dest_address(struct svc_rqst *rqstp, 702/*
723 struct cmsghdr *cmh) 703 * Copy the UDP datagram's destination address to the rqstp structure.
704 * The 'destination' address in this case is the address to which the
705 * peer sent the datagram, i.e. our local address. For multihomed
706 * hosts, this can change from msg to msg. Note that only the IP
707 * address changes, the port number should remain the same.
708 */
709static void svc_udp_get_dest_address(struct svc_rqst *rqstp,
710 struct cmsghdr *cmh)
724{ 711{
725 switch (rqstp->rq_sock->sk_sk->sk_family) { 712 switch (rqstp->rq_sock->sk_sk->sk_family) {
726 case AF_INET: { 713 case AF_INET: {
@@ -787,7 +774,10 @@ svc_udp_recvfrom(struct svc_rqst *rqstp)
787 svc_xprt_received(&svsk->sk_xprt); 774 svc_xprt_received(&svsk->sk_xprt);
788 return -EAGAIN; 775 return -EAGAIN;
789 } 776 }
790 rqstp->rq_addrlen = sizeof(rqstp->rq_addr); 777 len = svc_addr_len(svc_addr(rqstp));
778 if (len < 0)
779 return len;
780 rqstp->rq_addrlen = len;
791 if (skb->tstamp.tv64 == 0) { 781 if (skb->tstamp.tv64 == 0) {
792 skb->tstamp = ktime_get_real(); 782 skb->tstamp = ktime_get_real();
793 /* Don't enable netstamp, sunrpc doesn't 783 /* Don't enable netstamp, sunrpc doesn't
@@ -1097,14 +1087,13 @@ static struct svc_xprt *svc_tcp_accept(struct svc_xprt *xprt)
1097 if (!(newsvsk = svc_setup_socket(serv, newsock, &err, 1087 if (!(newsvsk = svc_setup_socket(serv, newsock, &err,
1098 (SVC_SOCK_ANONYMOUS | SVC_SOCK_TEMPORARY)))) 1088 (SVC_SOCK_ANONYMOUS | SVC_SOCK_TEMPORARY))))
1099 goto failed; 1089 goto failed;
1100 memcpy(&newsvsk->sk_remote, sin, slen); 1090 svc_xprt_set_remote(&newsvsk->sk_xprt, sin, slen);
1101 newsvsk->sk_remotelen = slen;
1102 err = kernel_getsockname(newsock, sin, &slen); 1091 err = kernel_getsockname(newsock, sin, &slen);
1103 if (unlikely(err < 0)) { 1092 if (unlikely(err < 0)) {
1104 dprintk("svc_tcp_accept: kernel_getsockname error %d\n", -err); 1093 dprintk("svc_tcp_accept: kernel_getsockname error %d\n", -err);
1105 slen = offsetof(struct sockaddr, sa_data); 1094 slen = offsetof(struct sockaddr, sa_data);
1106 } 1095 }
1107 memcpy(&newsvsk->sk_local, sin, slen); 1096 svc_xprt_set_local(&newsvsk->sk_xprt, sin, slen);
1108 1097
1109 if (serv->sv_stats) 1098 if (serv->sv_stats)
1110 serv->sv_stats->nettcpconn++; 1099 serv->sv_stats->nettcpconn++;
@@ -1245,6 +1234,7 @@ svc_tcp_recvfrom(struct svc_rqst *rqstp)
1245 svsk->sk_reclen = 0; 1234 svsk->sk_reclen = 0;
1246 svsk->sk_tcplen = 0; 1235 svsk->sk_tcplen = 0;
1247 1236
1237 svc_xprt_copy_addrs(rqstp, &svsk->sk_xprt);
1248 svc_xprt_received(&svsk->sk_xprt); 1238 svc_xprt_received(&svsk->sk_xprt);
1249 if (serv->sv_stats) 1239 if (serv->sv_stats)
1250 serv->sv_stats->nettcpcnt++; 1240 serv->sv_stats->nettcpcnt++;
@@ -1805,6 +1795,11 @@ int svc_addsock(struct svc_serv *serv,
1805 else { 1795 else {
1806 svsk = svc_setup_socket(serv, so, &err, SVC_SOCK_DEFAULTS); 1796 svsk = svc_setup_socket(serv, so, &err, SVC_SOCK_DEFAULTS);
1807 if (svsk) { 1797 if (svsk) {
1798 struct sockaddr_storage addr;
1799 struct sockaddr *sin = (struct sockaddr *)&addr;
1800 int salen;
1801 if (kernel_getsockname(svsk->sk_sock, sin, &salen) == 0)
1802 svc_xprt_set_local(&svsk->sk_xprt, sin, salen);
1808 svc_xprt_received(&svsk->sk_xprt); 1803 svc_xprt_received(&svsk->sk_xprt);
1809 err = 0; 1804 err = 0;
1810 } 1805 }
@@ -1831,6 +1826,9 @@ static struct svc_xprt *svc_create_socket(struct svc_serv *serv,
1831 int error; 1826 int error;
1832 int type; 1827 int type;
1833 char buf[RPC_MAX_ADDRBUFLEN]; 1828 char buf[RPC_MAX_ADDRBUFLEN];
1829 struct sockaddr_storage addr;
1830 struct sockaddr *newsin = (struct sockaddr *)&addr;
1831 int newlen;
1834 1832
1835 dprintk("svc: svc_create_socket(%s, %d, %s)\n", 1833 dprintk("svc: svc_create_socket(%s, %d, %s)\n",
1836 serv->sv_program->pg_name, protocol, 1834 serv->sv_program->pg_name, protocol,
@@ -1855,12 +1853,18 @@ static struct svc_xprt *svc_create_socket(struct svc_serv *serv,
1855 if (error < 0) 1853 if (error < 0)
1856 goto bummer; 1854 goto bummer;
1857 1855
1856 newlen = len;
1857 error = kernel_getsockname(sock, newsin, &newlen);
1858 if (error < 0)
1859 goto bummer;
1860
1858 if (protocol == IPPROTO_TCP) { 1861 if (protocol == IPPROTO_TCP) {
1859 if ((error = kernel_listen(sock, 64)) < 0) 1862 if ((error = kernel_listen(sock, 64)) < 0)
1860 goto bummer; 1863 goto bummer;
1861 } 1864 }
1862 1865
1863 if ((svsk = svc_setup_socket(serv, sock, &error, flags)) != NULL) { 1866 if ((svsk = svc_setup_socket(serv, sock, &error, flags)) != NULL) {
1867 svc_xprt_set_local(&svsk->sk_xprt, newsin, newlen);
1864 svc_xprt_received(&svsk->sk_xprt); 1868 svc_xprt_received(&svsk->sk_xprt);
1865 return (struct svc_xprt *)svsk; 1869 return (struct svc_xprt *)svsk;
1866 } 1870 }