1 /* $FreeBSD: releng/5.2/sys/nfs4client/nfs4_socket.c 122698 2003-11-14 20:54:10Z alfred $ */
2 /* $Id: nfs_socket.c,v 1.12 2003/11/05 14:59:01 rees Exp $ */
3
4 /*
5 * copyright (c) 2003
6 * the regents of the university of michigan
7 * all rights reserved
8 *
9 * permission is granted to use, copy, create derivative works and redistribute
10 * this software and such derivative works for any purpose, so long as the name
11 * of the university of michigan is not used in any advertising or publicity
12 * pertaining to the use or distribution of this software without specific,
13 * written prior authorization. if the above copyright notice or any other
14 * identification of the university of michigan is included in any copy of any
15 * portion of this software, then the disclaimer below must also be included.
16 *
17 * this software is provided as is, without representation from the university
18 * of michigan as to its fitness for any purpose, and without warranty by the
19 * university of michigan of any kind, either express or implied, including
20 * without limitation the implied warranties of merchantability and fitness for
21 * a particular purpose. the regents of the university of michigan shall not be
22 * liable for any damages, including special, indirect, incidental, or
23 * consequential damages, with respect to any claim arising out of or in
24 * connection with the use of the software, even if it has been or is hereafter
25 * advised of the possibility of such damages.
26 */
27
28 /*
29 * Copyright (c) 1989, 1991, 1993, 1995
30 * The Regents of the University of California. All rights reserved.
31 *
32 * This code is derived from software contributed to Berkeley by
33 * Rick Macklem at The University of Guelph.
34 *
35 * Redistribution and use in source and binary forms, with or without
36 * modification, are permitted provided that the following conditions
37 * are met:
38 * 1. Redistributions of source code must retain the above copyright
39 * notice, this list of conditions and the following disclaimer.
40 * 2. Redistributions in binary form must reproduce the above copyright
41 * notice, this list of conditions and the following disclaimer in the
42 * documentation and/or other materials provided with the distribution.
43 * 3. All advertising materials mentioning features or use of this software
44 * must display the following acknowledgement:
45 * This product includes software developed by the University of
46 * California, Berkeley and its contributors.
47 * 4. Neither the name of the University nor the names of its contributors
48 * may be used to endorse or promote products derived from this software
49 * without specific prior written permission.
50 *
51 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
52 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
53 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
54 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
55 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
56 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
57 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
59 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
60 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
61 * SUCH DAMAGE.
62 *
63 * @(#)nfs_socket.c 8.5 (Berkeley) 3/30/95
64 */
65
66 #include <sys/cdefs.h>
67 __FBSDID("$FreeBSD: releng/5.2/sys/nfs4client/nfs4_socket.c 122698 2003-11-14 20:54:10Z alfred $");
68
69 /*
70 * Socket operations for use by nfs
71 */
72
73 #include "opt_inet6.h"
74
75 #include <sys/param.h>
76 #include <sys/systm.h>
77 #include <sys/kernel.h>
78 #include <sys/lock.h>
79 #include <sys/malloc.h>
80 #include <sys/mbuf.h>
81 #include <sys/mount.h>
82 #include <sys/mutex.h>
83 #include <sys/proc.h>
84 #include <sys/protosw.h>
85 #include <sys/signalvar.h>
86 #include <sys/socket.h>
87 #include <sys/socketvar.h>
88 #include <sys/syslog.h>
89 #include <sys/vnode.h>
90
91 #include <netinet/in.h>
92 #include <netinet/tcp.h>
93
94 #include <rpc/rpcclnt.h>
95
96 #include <nfs/rpcv2.h>
97 #include <nfs/nfsproto.h>
98 #include <nfsclient/nfs.h>
99 #include <nfs4client/nfs4.h>
100 #include <nfs/xdr_subs.h>
101 #include <nfsclient/nfsm_subs.h>
102 #include <nfsclient/nfsmount.h>
103
104 #ifdef NFS4_USE_RPCCLNT
105 #include <rpc/rpcclnt.h>
106 #include <rpc/rpcm_subs.h>
107 #endif
108
109 #ifdef NFS4_USE_RPCCLNT
110 static struct rpc_program nfs_program = {
111 NFS_PROG, NFS_VER4, "NFSv4"
112 };
113 #endif
114
115
116 int
117 nfs4_connect(struct nfsmount *nmp)
118 {
119 struct rpcclnt * rpc = &nmp->nm_rpcclnt;
120 struct rpc_auth * auth;
121 int flag = 0;
122 int error;
123
124 /* XXX hack! */
125 #ifdef __OpenBSD__
126 struct proc * td = curproc;
127 #else
128 struct thread * td = curthread;
129 #endif
130
131 MALLOC(auth, struct rpc_auth *, sizeof(struct rpc_auth), M_TEMP, M_WAITOK);
132 auth->auth_type = RPCAUTH_UNIX;
133
134 /* translate nfs flags -> rpcclnt flags */
135 if (nmp->nm_flag & NFSMNT_SOFT)
136 flag |= RPCCLNT_SOFT;
137
138 if (nmp->nm_flag & NFSMNT_INT)
139 flag |= RPCCLNT_INT;
140
141 if (nmp->nm_flag & NFSMNT_NOCONN)
142 flag |= RPCCLNT_NOCONN;
143
144 if (nmp->nm_flag & NFSMNT_DUMBTIMR)
145 flag |= RPCCLNT_DUMBTIMR;
146
147 /* rpc->rc_servername = nmp->nm_mountp->mnt_stat.f_mntfromname; */
148
149 error = rpcclnt_setup(rpc, &nfs_program, nmp->nm_nam, nmp->nm_sotype,
150 nmp->nm_soproto, auth,
151 /* XXX: check nmp->nm_flag to make sure these are set */
152 (nmp->nm_rsize > nmp->nm_readdirsize) ? nmp->nm_rsize : nmp->nm_readdirsize,
153 nmp->nm_wsize, flag);
154
155 /* set deadthresh, timeo, retry */
156 rpc->rc_deadthresh = nmp->nm_deadthresh;
157 rpc->rc_timeo = nmp->nm_timeo;
158 rpc->rc_retry = nmp->nm_retry;
159
160
161 if (error)
162 return error;
163
164 return rpcclnt_connect(rpc, td);
165 }
166
167 /*
168 * NFS disconnect. Clean up and unlink.
169 */
170 void
171 nfs4_disconnect(struct nfsmount *nmp)
172 {
173 rpcclnt_disconnect(&nmp->nm_rpcclnt);
174 }
175
176 void
177 nfs4_safedisconnect(struct nfsmount *nmp)
178 {
179 rpcclnt_safedisconnect(&nmp->nm_rpcclnt);
180 }
181
182 /*
183 * nfs_request - goes something like this
184 * - fill in request struct
185 * - links it into list
186 * - calls nfs_send() for first transmit
187 * - calls nfs_receive() to get reply
188 * - break down rpc header and return with nfs reply pointed to
189 * by mrep or error
190 * nb: always frees up mreq mbuf list
191 */
192 /* XXX overloaded before */
193 #define NQ_TRYLATERDEL 15 /* Initial try later delay (sec) */
194
195 int
196 nfs4_request(struct vnode *vp, struct mbuf *mrest, int procnum,
197 struct thread *td, struct ucred *cred, struct mbuf **mrp,
198 struct mbuf **mdp, caddr_t *dposp)
199 {
200 int error;
201 u_int32_t *tl;
202 struct nfsmount * nmp = VFSTONFS(vp->v_mount);
203 struct rpcclnt * clnt = &nmp->nm_rpcclnt;
204 struct mbuf *md, *mrep;
205 caddr_t dpos;
206 struct rpc_reply reply;
207
208 if ((error = rpcclnt_request(clnt, mrest, procnum, td, cred,
209 &reply)) != 0) {
210 goto out;
211 }
212
213 /* XXX: don't free mrest if an error occured, to allow caller to retry*/
214 m_freem(mrest);
215 mrep = reply.mrep;
216 md = reply.result_md;
217 dpos = reply.result_dpos;
218
219 tl = nfsm_dissect(u_int32_t *, NFSX_UNSIGNED);
220 if (*tl != 0) {
221 error = fxdr_unsigned(int, *tl);
222
223 #if 0
224 if ((nmp->nm_flag & NFSMNT_NFSV3) &&
225 error == NFSERR_TRYLATER) {
226 m_freem(mrep);
227 error = 0;
228 waituntil = time_second + trylater_delay;
229 while (time_second < waituntil)
230 (void) tsleep(&lbolt, PSOCK, "nqnfstry", 0);
231 trylater_delay *= nfs_backoff[trylater_cnt];
232 if (trylater_cnt < NFS_NBACKOFF - 1)
233 trylater_cnt++;
234 goto tryagain;
235 }
236 #endif
237
238 /*
239 ** If the File Handle was stale, invalidate the
240 ** lookup cache, just in case.
241 **/
242 if (error == ESTALE)
243 cache_purge(vp);
244 goto out;
245 }
246
247 *mrp = mrep;
248 *mdp = md;
249 *dposp = dpos;
250 return (0);
251 nfsmout:
252 out:
253 m_freem(reply.mrep);
254 *mrp = NULL;
255 *mdp = NULL;
256 return (error);
257 }
258
259
260 int
261 nfs4_request_mnt(struct nfsmount *nmp, struct mbuf *mrest, int procnum,
262 struct thread *td, struct ucred *cred, struct mbuf **mrp,
263 struct mbuf **mdp, caddr_t *dposp)
264 {
265 int error;
266 u_int32_t *tl;
267 struct rpcclnt * clnt = &nmp->nm_rpcclnt;
268 struct mbuf *md, *mrep;
269 caddr_t dpos;
270 struct rpc_reply reply;
271
272 if ((error = rpcclnt_request(clnt, mrest, procnum, td, cred,
273 &reply)) != 0) {
274 goto out;
275 }
276
277 /* XXX: don't free mrest if an error occured, to allow caller to retry*/
278 m_freem(mrest);
279 mrep = reply.mrep;
280 md = reply.result_md;
281 dpos = reply.result_dpos;
282
283 tl = nfsm_dissect(u_int32_t *, NFSX_UNSIGNED);
284 if (*tl != 0) {
285 error = fxdr_unsigned(int, *tl);
286 #if 0
287 if ((nmp->nm_flag & NFSMNT_NFSV3) &&
288 error == NFSERR_TRYLATER) {
289 m_freem(mrep);
290 error = 0;
291 waituntil = time_second + trylater_delay;
292 while (time_second < waituntil)
293 (void) tsleep(&lbolt, PSOCK, "nqnfstry", 0);
294 trylater_delay *= nfs_backoff[trylater_cnt];
295 if (trylater_cnt < NFS_NBACKOFF - 1)
296 trylater_cnt++;
297 goto tryagain;
298 }
299 #endif
300 goto out;
301 }
302
303 *mrp = mrep;
304 *mdp = md;
305 *dposp = dpos;
306 return (0);
307 nfsmout:
308 out:
309 m_freem(reply.mrep);
310 *mrp = NULL;
311 *mdp = NULL;
312 return (error);
313 }
314
315
316 /*
317 * Mark all of an nfs mount's outstanding requests with R_SOFTTERM and
318 * wait for all requests to complete. This is used by forced unmounts
319 * to terminate any outstanding RPCs.
320 */
321 int
322 nfs4_nmcancelreqs(nmp)
323 struct nfsmount *nmp;
324 {
325 return rpcclnt_cancelreqs(&nmp->nm_rpcclnt);
326 }
327
328 /*
329 * Test for a termination condition pending on the process.
330 * This is used for NFSMNT_INT mounts.
331 */
332 int
333 nfs4_sigintr(struct nfsmount *nmp, struct nfsreq *rep, struct thread *td)
334 {
335 if (rep != NULL) {
336 printf("nfs_sigintr: attempting to use nfsreq != NULL\n");
337 return EINTR;
338 }
339 return rpcclnt_sigintr(&nmp->nm_rpcclnt, NULL, td);
340 }
Cache object: 05ed695b2619464054bea8a393773bb9
|