diff options
author | Takuma Umeya <tumeya@redhat.com> | 2010-12-15 00:09:01 -0500 |
---|---|---|
committer | J. Bruce Fields <bfields@redhat.com> | 2011-01-04 19:43:01 -0500 |
commit | 6f3d772fb8a039de8f21d725f5e38c252b4c0efd (patch) | |
tree | a62c900be0d2766223f0e5630cebaaf2ffee0efb /fs/nfsd/nfs4state.c | |
parent | 3c726023402a2f3b28f49b9d90ebf9e71151157d (diff) |
nfs4: set source address when callback is generated
when callback is generated in NFSv4 server, it doesn't set the source
address. When an alias IP is utilized on NFSv4 server and suppose the
client is accessing via that alias IP (e.g. eth0:0), the client invokes
the callback to the IP address that is set on the original device (e.g.
eth0). This behavior results in timeout of xprt.
The patch sets the IP address that the client should invoke callback to.
Signed-off-by: Takuma Umeya <tumeya@redhat.com>
[bfields@redhat.com: Simplify gen_callback arguments, use helper function]
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'fs/nfsd/nfs4state.c')
-rw-r--r-- | fs/nfsd/nfs4state.c | 22 |
1 files changed, 19 insertions, 3 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 87d4c48b6069..b583e4e800ab 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
@@ -1163,10 +1163,26 @@ find_unconfirmed_client_by_str(const char *dname, unsigned int hashval) | |||
1163 | return NULL; | 1163 | return NULL; |
1164 | } | 1164 | } |
1165 | 1165 | ||
1166 | static void rpc_svcaddr2sockaddr(struct sockaddr *sa, unsigned short family, union svc_addr_u *svcaddr) | ||
1167 | { | ||
1168 | switch (family) { | ||
1169 | case AF_INET: | ||
1170 | ((struct sockaddr_in *)sa)->sin_family = AF_INET; | ||
1171 | ((struct sockaddr_in *)sa)->sin_addr = svcaddr->addr; | ||
1172 | return; | ||
1173 | case AF_INET6: | ||
1174 | ((struct sockaddr_in6 *)sa)->sin6_family = AF_INET6; | ||
1175 | ((struct sockaddr_in6 *)sa)->sin6_addr = svcaddr->addr6; | ||
1176 | return; | ||
1177 | } | ||
1178 | } | ||
1179 | |||
1166 | static void | 1180 | static void |
1167 | gen_callback(struct nfs4_client *clp, struct nfsd4_setclientid *se, u32 scopeid) | 1181 | gen_callback(struct nfs4_client *clp, struct nfsd4_setclientid *se, struct svc_rqst *rqstp) |
1168 | { | 1182 | { |
1169 | struct nfs4_cb_conn *conn = &clp->cl_cb_conn; | 1183 | struct nfs4_cb_conn *conn = &clp->cl_cb_conn; |
1184 | struct sockaddr *sa = svc_addr(rqstp); | ||
1185 | u32 scopeid = rpc_get_scope_id(sa); | ||
1170 | unsigned short expected_family; | 1186 | unsigned short expected_family; |
1171 | 1187 | ||
1172 | /* Currently, we only support tcp and tcp6 for the callback channel */ | 1188 | /* Currently, we only support tcp and tcp6 for the callback channel */ |
@@ -1192,6 +1208,7 @@ gen_callback(struct nfs4_client *clp, struct nfsd4_setclientid *se, u32 scopeid) | |||
1192 | 1208 | ||
1193 | conn->cb_prog = se->se_callback_prog; | 1209 | conn->cb_prog = se->se_callback_prog; |
1194 | conn->cb_ident = se->se_callback_ident; | 1210 | conn->cb_ident = se->se_callback_ident; |
1211 | rpc_svcaddr2sockaddr((struct sockaddr *)&conn->cb_saddr, expected_family, &rqstp->rq_daddr); | ||
1195 | return; | 1212 | return; |
1196 | out_err: | 1213 | out_err: |
1197 | conn->cb_addr.ss_family = AF_UNSPEC; | 1214 | conn->cb_addr.ss_family = AF_UNSPEC; |
@@ -1768,7 +1785,6 @@ __be32 | |||
1768 | nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | 1785 | nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, |
1769 | struct nfsd4_setclientid *setclid) | 1786 | struct nfsd4_setclientid *setclid) |
1770 | { | 1787 | { |
1771 | struct sockaddr *sa = svc_addr(rqstp); | ||
1772 | struct xdr_netobj clname = { | 1788 | struct xdr_netobj clname = { |
1773 | .len = setclid->se_namelen, | 1789 | .len = setclid->se_namelen, |
1774 | .data = setclid->se_name, | 1790 | .data = setclid->se_name, |
@@ -1871,7 +1887,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
1871 | * for consistent minorversion use throughout: | 1887 | * for consistent minorversion use throughout: |
1872 | */ | 1888 | */ |
1873 | new->cl_minorversion = 0; | 1889 | new->cl_minorversion = 0; |
1874 | gen_callback(new, setclid, rpc_get_scope_id(sa)); | 1890 | gen_callback(new, setclid, rqstp); |
1875 | add_to_unconfirmed(new, strhashval); | 1891 | add_to_unconfirmed(new, strhashval); |
1876 | setclid->se_clientid.cl_boot = new->cl_clientid.cl_boot; | 1892 | setclid->se_clientid.cl_boot = new->cl_clientid.cl_boot; |
1877 | setclid->se_clientid.cl_id = new->cl_clientid.cl_id; | 1893 | setclid->se_clientid.cl_id = new->cl_clientid.cl_id; |