nfs_clvfsops.c revision 1.1.1.2 1 1.1 dholland /* $NetBSD: nfs_clvfsops.c,v 1.1.1.2 2016/11/18 07:49:11 pgoyette Exp $ */
2 1.1 dholland /*-
3 1.1 dholland * Copyright (c) 1989, 1993, 1995
4 1.1 dholland * The Regents of the University of California. All rights reserved.
5 1.1 dholland *
6 1.1 dholland * This code is derived from software contributed to Berkeley by
7 1.1 dholland * Rick Macklem at The University of Guelph.
8 1.1 dholland *
9 1.1 dholland * Redistribution and use in source and binary forms, with or without
10 1.1 dholland * modification, are permitted provided that the following conditions
11 1.1 dholland * are met:
12 1.1 dholland * 1. Redistributions of source code must retain the above copyright
13 1.1 dholland * notice, this list of conditions and the following disclaimer.
14 1.1 dholland * 2. Redistributions in binary form must reproduce the above copyright
15 1.1 dholland * notice, this list of conditions and the following disclaimer in the
16 1.1 dholland * documentation and/or other materials provided with the distribution.
17 1.1 dholland * 4. Neither the name of the University nor the names of its contributors
18 1.1 dholland * may be used to endorse or promote products derived from this software
19 1.1 dholland * without specific prior written permission.
20 1.1 dholland *
21 1.1 dholland * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 1.1 dholland * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 1.1 dholland * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 1.1 dholland * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 1.1 dholland * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 1.1 dholland * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 1.1 dholland * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 1.1 dholland * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 1.1 dholland * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 1.1 dholland * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 1.1 dholland * SUCH DAMAGE.
32 1.1 dholland *
33 1.1 dholland * from nfs_vfsops.c 8.12 (Berkeley) 5/20/95
34 1.1 dholland */
35 1.1 dholland
36 1.1 dholland #include <sys/cdefs.h>
37 1.1.1.2 pgoyette /* __FBSDID("FreeBSD: head/sys/fs/nfsclient/nfs_clvfsops.c 304026 2016-08-12 22:44:59Z rmacklem "); */
38 1.1 dholland __RCSID("$NetBSD: nfs_clvfsops.c,v 1.1.1.2 2016/11/18 07:49:11 pgoyette Exp $");
39 1.1 dholland
40 1.1 dholland
41 1.1 dholland #include "opt_bootp.h"
42 1.1 dholland #include "opt_nfsroot.h"
43 1.1 dholland
44 1.1 dholland #include <sys/param.h>
45 1.1 dholland #include <sys/systm.h>
46 1.1 dholland #include <sys/kernel.h>
47 1.1 dholland #include <sys/bio.h>
48 1.1 dholland #include <sys/buf.h>
49 1.1 dholland #include <sys/clock.h>
50 1.1 dholland #include <sys/jail.h>
51 1.1 dholland #include <sys/limits.h>
52 1.1 dholland #include <sys/lock.h>
53 1.1 dholland #include <sys/malloc.h>
54 1.1 dholland #include <sys/mbuf.h>
55 1.1 dholland #include <sys/module.h>
56 1.1 dholland #include <sys/mount.h>
57 1.1 dholland #include <sys/proc.h>
58 1.1 dholland #include <sys/socket.h>
59 1.1 dholland #include <sys/socketvar.h>
60 1.1 dholland #include <sys/sockio.h>
61 1.1 dholland #include <sys/sysctl.h>
62 1.1 dholland #include <sys/vnode.h>
63 1.1 dholland #include <sys/signalvar.h>
64 1.1 dholland
65 1.1 dholland #include <vm/vm.h>
66 1.1 dholland #include <vm/vm_extern.h>
67 1.1 dholland #include <vm/uma.h>
68 1.1 dholland
69 1.1 dholland #include <net/if.h>
70 1.1 dholland #include <net/route.h>
71 1.1 dholland #include <netinet/in.h>
72 1.1 dholland
73 1.1 dholland #include <fs/nfs/nfsport.h>
74 1.1 dholland #include <fs/nfsclient/nfsnode.h>
75 1.1 dholland #include <fs/nfsclient/nfsmount.h>
76 1.1 dholland #include <fs/nfsclient/nfs.h>
77 1.1 dholland #include <nfs/nfsdiskless.h>
78 1.1 dholland
79 1.1 dholland FEATURE(nfscl, "NFSv4 client");
80 1.1 dholland
81 1.1 dholland extern int nfscl_ticks;
82 1.1 dholland extern struct timeval nfsboottime;
83 1.1 dholland extern int nfsrv_useacl;
84 1.1 dholland extern int nfscl_debuglevel;
85 1.1 dholland extern enum nfsiod_state ncl_iodwant[NFS_MAXASYNCDAEMON];
86 1.1 dholland extern struct nfsmount *ncl_iodmount[NFS_MAXASYNCDAEMON];
87 1.1 dholland extern struct mtx ncl_iod_mutex;
88 1.1 dholland NFSCLSTATEMUTEX;
89 1.1 dholland
90 1.1.1.2 pgoyette MALLOC_DEFINE(M_NEWNFSREQ, "newnfsclient_req", "NFS request header");
91 1.1.1.2 pgoyette MALLOC_DEFINE(M_NEWNFSMNT, "newnfsmnt", "NFS mount struct");
92 1.1 dholland
93 1.1 dholland SYSCTL_DECL(_vfs_nfs);
94 1.1 dholland static int nfs_ip_paranoia = 1;
95 1.1 dholland SYSCTL_INT(_vfs_nfs, OID_AUTO, nfs_ip_paranoia, CTLFLAG_RW,
96 1.1 dholland &nfs_ip_paranoia, 0, "");
97 1.1 dholland static int nfs_tprintf_initial_delay = NFS_TPRINTF_INITIAL_DELAY;
98 1.1 dholland SYSCTL_INT(_vfs_nfs, NFS_TPRINTF_INITIAL_DELAY,
99 1.1 dholland downdelayinitial, CTLFLAG_RW, &nfs_tprintf_initial_delay, 0, "");
100 1.1 dholland /* how long between console messages "nfs server foo not responding" */
101 1.1 dholland static int nfs_tprintf_delay = NFS_TPRINTF_DELAY;
102 1.1 dholland SYSCTL_INT(_vfs_nfs, NFS_TPRINTF_DELAY,
103 1.1 dholland downdelayinterval, CTLFLAG_RW, &nfs_tprintf_delay, 0, "");
104 1.1.1.2 pgoyette #ifdef NFS_DEBUG
105 1.1.1.2 pgoyette int nfs_debug;
106 1.1.1.2 pgoyette SYSCTL_INT(_vfs_nfs, OID_AUTO, debug, CTLFLAG_RW, &nfs_debug, 0,
107 1.1.1.2 pgoyette "Toggle debug flag");
108 1.1.1.2 pgoyette #endif
109 1.1 dholland
110 1.1 dholland static int nfs_mountroot(struct mount *);
111 1.1 dholland static void nfs_sec_name(char *, int *);
112 1.1 dholland static void nfs_decode_args(struct mount *mp, struct nfsmount *nmp,
113 1.1 dholland struct nfs_args *argp, const char *, struct ucred *,
114 1.1 dholland struct thread *);
115 1.1 dholland static int mountnfs(struct nfs_args *, struct mount *,
116 1.1 dholland struct sockaddr *, char *, u_char *, int, u_char *, int,
117 1.1 dholland u_char *, int, struct vnode **, struct ucred *,
118 1.1 dholland struct thread *, int, int, int);
119 1.1 dholland static void nfs_getnlminfo(struct vnode *, uint8_t *, size_t *,
120 1.1 dholland struct sockaddr_storage *, int *, off_t *,
121 1.1 dholland struct timeval *);
122 1.1 dholland static vfs_mount_t nfs_mount;
123 1.1 dholland static vfs_cmount_t nfs_cmount;
124 1.1 dholland static vfs_unmount_t nfs_unmount;
125 1.1 dholland static vfs_root_t nfs_root;
126 1.1 dholland static vfs_statfs_t nfs_statfs;
127 1.1 dholland static vfs_sync_t nfs_sync;
128 1.1 dholland static vfs_sysctl_t nfs_sysctl;
129 1.1 dholland static vfs_purge_t nfs_purge;
130 1.1 dholland
131 1.1 dholland /*
132 1.1 dholland * nfs vfs operations.
133 1.1 dholland */
134 1.1 dholland static struct vfsops nfs_vfsops = {
135 1.1 dholland .vfs_init = ncl_init,
136 1.1 dholland .vfs_mount = nfs_mount,
137 1.1 dholland .vfs_cmount = nfs_cmount,
138 1.1 dholland .vfs_root = nfs_root,
139 1.1 dholland .vfs_statfs = nfs_statfs,
140 1.1 dholland .vfs_sync = nfs_sync,
141 1.1 dholland .vfs_uninit = ncl_uninit,
142 1.1 dholland .vfs_unmount = nfs_unmount,
143 1.1 dholland .vfs_sysctl = nfs_sysctl,
144 1.1 dholland .vfs_purge = nfs_purge,
145 1.1 dholland };
146 1.1 dholland VFS_SET(nfs_vfsops, nfs, VFCF_NETWORK | VFCF_SBDRY);
147 1.1 dholland
148 1.1 dholland /* So that loader and kldload(2) can find us, wherever we are.. */
149 1.1 dholland MODULE_VERSION(nfs, 1);
150 1.1 dholland MODULE_DEPEND(nfs, nfscommon, 1, 1, 1);
151 1.1 dholland MODULE_DEPEND(nfs, krpc, 1, 1, 1);
152 1.1 dholland MODULE_DEPEND(nfs, nfssvc, 1, 1, 1);
153 1.1 dholland MODULE_DEPEND(nfs, nfslock, 1, 1, 1);
154 1.1 dholland
155 1.1 dholland /*
156 1.1 dholland * This structure is now defined in sys/nfs/nfs_diskless.c so that it
157 1.1 dholland * can be shared by both NFS clients. It is declared here so that it
158 1.1 dholland * will be defined for kernels built without NFS_ROOT, although it
159 1.1 dholland * isn't used in that case.
160 1.1 dholland */
161 1.1.1.2 pgoyette #if !defined(NFS_ROOT)
162 1.1 dholland struct nfs_diskless nfs_diskless = { { { 0 } } };
163 1.1 dholland struct nfsv3_diskless nfsv3_diskless = { { { 0 } } };
164 1.1 dholland int nfs_diskless_valid = 0;
165 1.1 dholland #endif
166 1.1 dholland
167 1.1 dholland SYSCTL_INT(_vfs_nfs, OID_AUTO, diskless_valid, CTLFLAG_RD,
168 1.1 dholland &nfs_diskless_valid, 0,
169 1.1 dholland "Has the diskless struct been filled correctly");
170 1.1 dholland
171 1.1 dholland SYSCTL_STRING(_vfs_nfs, OID_AUTO, diskless_rootpath, CTLFLAG_RD,
172 1.1 dholland nfsv3_diskless.root_hostnam, 0, "Path to nfs root");
173 1.1 dholland
174 1.1 dholland SYSCTL_OPAQUE(_vfs_nfs, OID_AUTO, diskless_rootaddr, CTLFLAG_RD,
175 1.1 dholland &nfsv3_diskless.root_saddr, sizeof(nfsv3_diskless.root_saddr),
176 1.1 dholland "%Ssockaddr_in", "Diskless root nfs address");
177 1.1 dholland
178 1.1 dholland
179 1.1 dholland void newnfsargs_ntoh(struct nfs_args *);
180 1.1 dholland static int nfs_mountdiskless(char *,
181 1.1 dholland struct sockaddr_in *, struct nfs_args *,
182 1.1 dholland struct thread *, struct vnode **, struct mount *);
183 1.1 dholland static void nfs_convert_diskless(void);
184 1.1 dholland static void nfs_convert_oargs(struct nfs_args *args,
185 1.1 dholland struct onfs_args *oargs);
186 1.1 dholland
187 1.1 dholland int
188 1.1 dholland newnfs_iosize(struct nfsmount *nmp)
189 1.1 dholland {
190 1.1 dholland int iosize, maxio;
191 1.1 dholland
192 1.1 dholland /* First, set the upper limit for iosize */
193 1.1 dholland if (nmp->nm_flag & NFSMNT_NFSV4) {
194 1.1 dholland maxio = NFS_MAXBSIZE;
195 1.1 dholland } else if (nmp->nm_flag & NFSMNT_NFSV3) {
196 1.1 dholland if (nmp->nm_sotype == SOCK_DGRAM)
197 1.1 dholland maxio = NFS_MAXDGRAMDATA;
198 1.1 dholland else
199 1.1 dholland maxio = NFS_MAXBSIZE;
200 1.1 dholland } else {
201 1.1 dholland maxio = NFS_V2MAXDATA;
202 1.1 dholland }
203 1.1 dholland if (nmp->nm_rsize > maxio || nmp->nm_rsize == 0)
204 1.1 dholland nmp->nm_rsize = maxio;
205 1.1.1.2 pgoyette if (nmp->nm_rsize > NFS_MAXBSIZE)
206 1.1.1.2 pgoyette nmp->nm_rsize = NFS_MAXBSIZE;
207 1.1 dholland if (nmp->nm_readdirsize > maxio || nmp->nm_readdirsize == 0)
208 1.1 dholland nmp->nm_readdirsize = maxio;
209 1.1 dholland if (nmp->nm_readdirsize > nmp->nm_rsize)
210 1.1 dholland nmp->nm_readdirsize = nmp->nm_rsize;
211 1.1 dholland if (nmp->nm_wsize > maxio || nmp->nm_wsize == 0)
212 1.1 dholland nmp->nm_wsize = maxio;
213 1.1.1.2 pgoyette if (nmp->nm_wsize > NFS_MAXBSIZE)
214 1.1.1.2 pgoyette nmp->nm_wsize = NFS_MAXBSIZE;
215 1.1 dholland
216 1.1 dholland /*
217 1.1 dholland * Calculate the size used for io buffers. Use the larger
218 1.1 dholland * of the two sizes to minimise nfs requests but make sure
219 1.1 dholland * that it is at least one VM page to avoid wasting buffer
220 1.1.1.2 pgoyette * space. It must also be at least NFS_DIRBLKSIZ, since
221 1.1.1.2 pgoyette * that is the buffer size used for directories.
222 1.1 dholland */
223 1.1 dholland iosize = imax(nmp->nm_rsize, nmp->nm_wsize);
224 1.1 dholland iosize = imax(iosize, PAGE_SIZE);
225 1.1.1.2 pgoyette iosize = imax(iosize, NFS_DIRBLKSIZ);
226 1.1 dholland nmp->nm_mountp->mnt_stat.f_iosize = iosize;
227 1.1 dholland return (iosize);
228 1.1 dholland }
229 1.1 dholland
230 1.1 dholland static void
231 1.1 dholland nfs_convert_oargs(struct nfs_args *args, struct onfs_args *oargs)
232 1.1 dholland {
233 1.1 dholland
234 1.1 dholland args->version = NFS_ARGSVERSION;
235 1.1 dholland args->addr = oargs->addr;
236 1.1 dholland args->addrlen = oargs->addrlen;
237 1.1 dholland args->sotype = oargs->sotype;
238 1.1 dholland args->proto = oargs->proto;
239 1.1 dholland args->fh = oargs->fh;
240 1.1 dholland args->fhsize = oargs->fhsize;
241 1.1 dholland args->flags = oargs->flags;
242 1.1 dholland args->wsize = oargs->wsize;
243 1.1 dholland args->rsize = oargs->rsize;
244 1.1 dholland args->readdirsize = oargs->readdirsize;
245 1.1 dholland args->timeo = oargs->timeo;
246 1.1 dholland args->retrans = oargs->retrans;
247 1.1 dholland args->readahead = oargs->readahead;
248 1.1 dholland args->hostname = oargs->hostname;
249 1.1 dholland }
250 1.1 dholland
251 1.1 dholland static void
252 1.1 dholland nfs_convert_diskless(void)
253 1.1 dholland {
254 1.1 dholland
255 1.1 dholland bcopy(&nfs_diskless.myif, &nfsv3_diskless.myif,
256 1.1 dholland sizeof(struct ifaliasreq));
257 1.1 dholland bcopy(&nfs_diskless.mygateway, &nfsv3_diskless.mygateway,
258 1.1 dholland sizeof(struct sockaddr_in));
259 1.1 dholland nfs_convert_oargs(&nfsv3_diskless.root_args,&nfs_diskless.root_args);
260 1.1 dholland if (nfsv3_diskless.root_args.flags & NFSMNT_NFSV3) {
261 1.1 dholland nfsv3_diskless.root_fhsize = NFSX_MYFH;
262 1.1 dholland bcopy(nfs_diskless.root_fh, nfsv3_diskless.root_fh, NFSX_MYFH);
263 1.1 dholland } else {
264 1.1 dholland nfsv3_diskless.root_fhsize = NFSX_V2FH;
265 1.1 dholland bcopy(nfs_diskless.root_fh, nfsv3_diskless.root_fh, NFSX_V2FH);
266 1.1 dholland }
267 1.1 dholland bcopy(&nfs_diskless.root_saddr,&nfsv3_diskless.root_saddr,
268 1.1 dholland sizeof(struct sockaddr_in));
269 1.1 dholland bcopy(nfs_diskless.root_hostnam, nfsv3_diskless.root_hostnam, MNAMELEN);
270 1.1 dholland nfsv3_diskless.root_time = nfs_diskless.root_time;
271 1.1 dholland bcopy(nfs_diskless.my_hostnam, nfsv3_diskless.my_hostnam,
272 1.1 dholland MAXHOSTNAMELEN);
273 1.1 dholland nfs_diskless_valid = 3;
274 1.1 dholland }
275 1.1 dholland
276 1.1 dholland /*
277 1.1 dholland * nfs statfs call
278 1.1 dholland */
279 1.1 dholland static int
280 1.1 dholland nfs_statfs(struct mount *mp, struct statfs *sbp)
281 1.1 dholland {
282 1.1 dholland struct vnode *vp;
283 1.1 dholland struct thread *td;
284 1.1 dholland struct nfsmount *nmp = VFSTONFS(mp);
285 1.1 dholland struct nfsvattr nfsva;
286 1.1 dholland struct nfsfsinfo fs;
287 1.1 dholland struct nfsstatfs sb;
288 1.1 dholland int error = 0, attrflag, gotfsinfo = 0, ret;
289 1.1 dholland struct nfsnode *np;
290 1.1 dholland
291 1.1 dholland td = curthread;
292 1.1 dholland
293 1.1 dholland error = vfs_busy(mp, MBF_NOWAIT);
294 1.1 dholland if (error)
295 1.1 dholland return (error);
296 1.1 dholland error = ncl_nget(mp, nmp->nm_fh, nmp->nm_fhsize, &np, LK_EXCLUSIVE);
297 1.1 dholland if (error) {
298 1.1 dholland vfs_unbusy(mp);
299 1.1 dholland return (error);
300 1.1 dholland }
301 1.1 dholland vp = NFSTOV(np);
302 1.1 dholland mtx_lock(&nmp->nm_mtx);
303 1.1 dholland if (NFSHASNFSV3(nmp) && !NFSHASGOTFSINFO(nmp)) {
304 1.1 dholland mtx_unlock(&nmp->nm_mtx);
305 1.1 dholland error = nfsrpc_fsinfo(vp, &fs, td->td_ucred, td, &nfsva,
306 1.1 dholland &attrflag, NULL);
307 1.1 dholland if (!error)
308 1.1 dholland gotfsinfo = 1;
309 1.1 dholland } else
310 1.1 dholland mtx_unlock(&nmp->nm_mtx);
311 1.1 dholland if (!error)
312 1.1 dholland error = nfsrpc_statfs(vp, &sb, &fs, td->td_ucred, td, &nfsva,
313 1.1 dholland &attrflag, NULL);
314 1.1 dholland if (error != 0)
315 1.1 dholland NFSCL_DEBUG(2, "statfs=%d\n", error);
316 1.1 dholland if (attrflag == 0) {
317 1.1 dholland ret = nfsrpc_getattrnovp(nmp, nmp->nm_fh, nmp->nm_fhsize, 1,
318 1.1 dholland td->td_ucred, td, &nfsva, NULL, NULL);
319 1.1 dholland if (ret) {
320 1.1 dholland /*
321 1.1 dholland * Just set default values to get things going.
322 1.1 dholland */
323 1.1 dholland NFSBZERO((caddr_t)&nfsva, sizeof (struct nfsvattr));
324 1.1 dholland nfsva.na_vattr.va_type = VDIR;
325 1.1 dholland nfsva.na_vattr.va_mode = 0777;
326 1.1 dholland nfsva.na_vattr.va_nlink = 100;
327 1.1 dholland nfsva.na_vattr.va_uid = (uid_t)0;
328 1.1 dholland nfsva.na_vattr.va_gid = (gid_t)0;
329 1.1 dholland nfsva.na_vattr.va_fileid = 2;
330 1.1 dholland nfsva.na_vattr.va_gen = 1;
331 1.1 dholland nfsva.na_vattr.va_blocksize = NFS_FABLKSIZE;
332 1.1 dholland nfsva.na_vattr.va_size = 512 * 1024;
333 1.1 dholland }
334 1.1 dholland }
335 1.1 dholland (void) nfscl_loadattrcache(&vp, &nfsva, NULL, NULL, 0, 1);
336 1.1 dholland if (!error) {
337 1.1 dholland mtx_lock(&nmp->nm_mtx);
338 1.1 dholland if (gotfsinfo || (nmp->nm_flag & NFSMNT_NFSV4))
339 1.1 dholland nfscl_loadfsinfo(nmp, &fs);
340 1.1 dholland nfscl_loadsbinfo(nmp, &sb, sbp);
341 1.1 dholland sbp->f_iosize = newnfs_iosize(nmp);
342 1.1 dholland mtx_unlock(&nmp->nm_mtx);
343 1.1 dholland if (sbp != &mp->mnt_stat) {
344 1.1 dholland bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
345 1.1 dholland bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
346 1.1 dholland }
347 1.1 dholland strncpy(&sbp->f_fstypename[0], mp->mnt_vfc->vfc_name, MFSNAMELEN);
348 1.1 dholland } else if (NFS_ISV4(vp)) {
349 1.1 dholland error = nfscl_maperr(td, error, (uid_t)0, (gid_t)0);
350 1.1 dholland }
351 1.1 dholland vput(vp);
352 1.1 dholland vfs_unbusy(mp);
353 1.1 dholland return (error);
354 1.1 dholland }
355 1.1 dholland
356 1.1 dholland /*
357 1.1 dholland * nfs version 3 fsinfo rpc call
358 1.1 dholland */
359 1.1 dholland int
360 1.1 dholland ncl_fsinfo(struct nfsmount *nmp, struct vnode *vp, struct ucred *cred,
361 1.1 dholland struct thread *td)
362 1.1 dholland {
363 1.1 dholland struct nfsfsinfo fs;
364 1.1 dholland struct nfsvattr nfsva;
365 1.1 dholland int error, attrflag;
366 1.1 dholland
367 1.1 dholland error = nfsrpc_fsinfo(vp, &fs, cred, td, &nfsva, &attrflag, NULL);
368 1.1 dholland if (!error) {
369 1.1 dholland if (attrflag)
370 1.1 dholland (void) nfscl_loadattrcache(&vp, &nfsva, NULL, NULL, 0,
371 1.1 dholland 1);
372 1.1 dholland mtx_lock(&nmp->nm_mtx);
373 1.1 dholland nfscl_loadfsinfo(nmp, &fs);
374 1.1 dholland mtx_unlock(&nmp->nm_mtx);
375 1.1 dholland }
376 1.1 dholland return (error);
377 1.1 dholland }
378 1.1 dholland
379 1.1 dholland /*
380 1.1 dholland * Mount a remote root fs via. nfs. This depends on the info in the
381 1.1 dholland * nfs_diskless structure that has been filled in properly by some primary
382 1.1 dholland * bootstrap.
383 1.1 dholland * It goes something like this:
384 1.1 dholland * - do enough of "ifconfig" by calling ifioctl() so that the system
385 1.1 dholland * can talk to the server
386 1.1 dholland * - If nfs_diskless.mygateway is filled in, use that address as
387 1.1 dholland * a default gateway.
388 1.1 dholland * - build the rootfs mount point and call mountnfs() to do the rest.
389 1.1 dholland *
390 1.1 dholland * It is assumed to be safe to read, modify, and write the nfsv3_diskless
391 1.1 dholland * structure, as well as other global NFS client variables here, as
392 1.1 dholland * nfs_mountroot() will be called once in the boot before any other NFS
393 1.1 dholland * client activity occurs.
394 1.1 dholland */
395 1.1 dholland static int
396 1.1 dholland nfs_mountroot(struct mount *mp)
397 1.1 dholland {
398 1.1 dholland struct thread *td = curthread;
399 1.1 dholland struct nfsv3_diskless *nd = &nfsv3_diskless;
400 1.1 dholland struct socket *so;
401 1.1 dholland struct vnode *vp;
402 1.1 dholland struct ifreq ir;
403 1.1 dholland int error;
404 1.1 dholland u_long l;
405 1.1 dholland char buf[128];
406 1.1 dholland char *cp;
407 1.1 dholland
408 1.1 dholland #if defined(BOOTP_NFSROOT) && defined(BOOTP)
409 1.1 dholland bootpc_init(); /* use bootp to get nfs_diskless filled in */
410 1.1 dholland #elif defined(NFS_ROOT)
411 1.1 dholland nfs_setup_diskless();
412 1.1 dholland #endif
413 1.1 dholland
414 1.1 dholland if (nfs_diskless_valid == 0)
415 1.1 dholland return (-1);
416 1.1 dholland if (nfs_diskless_valid == 1)
417 1.1 dholland nfs_convert_diskless();
418 1.1 dholland
419 1.1 dholland /*
420 1.1 dholland * XXX splnet, so networks will receive...
421 1.1 dholland */
422 1.1 dholland splnet();
423 1.1 dholland
424 1.1 dholland /*
425 1.1 dholland * Do enough of ifconfig(8) so that the critical net interface can
426 1.1 dholland * talk to the server.
427 1.1 dholland */
428 1.1 dholland error = socreate(nd->myif.ifra_addr.sa_family, &so, nd->root_args.sotype, 0,
429 1.1 dholland td->td_ucred, td);
430 1.1 dholland if (error)
431 1.1 dholland panic("nfs_mountroot: socreate(%04x): %d",
432 1.1 dholland nd->myif.ifra_addr.sa_family, error);
433 1.1 dholland
434 1.1 dholland #if 0 /* XXX Bad idea */
435 1.1 dholland /*
436 1.1 dholland * We might not have been told the right interface, so we pass
437 1.1 dholland * over the first ten interfaces of the same kind, until we get
438 1.1 dholland * one of them configured.
439 1.1 dholland */
440 1.1 dholland
441 1.1 dholland for (i = strlen(nd->myif.ifra_name) - 1;
442 1.1 dholland nd->myif.ifra_name[i] >= '0' &&
443 1.1 dholland nd->myif.ifra_name[i] <= '9';
444 1.1 dholland nd->myif.ifra_name[i] ++) {
445 1.1 dholland error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, td);
446 1.1 dholland if(!error)
447 1.1 dholland break;
448 1.1 dholland }
449 1.1 dholland #endif
450 1.1 dholland error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, td);
451 1.1 dholland if (error)
452 1.1 dholland panic("nfs_mountroot: SIOCAIFADDR: %d", error);
453 1.1.1.2 pgoyette if ((cp = kern_getenv("boot.netif.mtu")) != NULL) {
454 1.1 dholland ir.ifr_mtu = strtol(cp, NULL, 10);
455 1.1 dholland bcopy(nd->myif.ifra_name, ir.ifr_name, IFNAMSIZ);
456 1.1 dholland freeenv(cp);
457 1.1 dholland error = ifioctl(so, SIOCSIFMTU, (caddr_t)&ir, td);
458 1.1 dholland if (error)
459 1.1 dholland printf("nfs_mountroot: SIOCSIFMTU: %d", error);
460 1.1 dholland }
461 1.1 dholland soclose(so);
462 1.1 dholland
463 1.1 dholland /*
464 1.1 dholland * If the gateway field is filled in, set it as the default route.
465 1.1 dholland * Note that pxeboot will set a default route of 0 if the route
466 1.1 dholland * is not set by the DHCP server. Check also for a value of 0
467 1.1 dholland * to avoid panicking inappropriately in that situation.
468 1.1 dholland */
469 1.1 dholland if (nd->mygateway.sin_len != 0 &&
470 1.1 dholland nd->mygateway.sin_addr.s_addr != 0) {
471 1.1 dholland struct sockaddr_in mask, sin;
472 1.1 dholland
473 1.1 dholland bzero((caddr_t)&mask, sizeof(mask));
474 1.1 dholland sin = mask;
475 1.1 dholland sin.sin_family = AF_INET;
476 1.1 dholland sin.sin_len = sizeof(sin);
477 1.1 dholland /* XXX MRT use table 0 for this sort of thing */
478 1.1 dholland CURVNET_SET(TD_TO_VNET(td));
479 1.1 dholland error = rtrequest_fib(RTM_ADD, (struct sockaddr *)&sin,
480 1.1 dholland (struct sockaddr *)&nd->mygateway,
481 1.1 dholland (struct sockaddr *)&mask,
482 1.1 dholland RTF_UP | RTF_GATEWAY, NULL, RT_DEFAULT_FIB);
483 1.1 dholland CURVNET_RESTORE();
484 1.1 dholland if (error)
485 1.1 dholland panic("nfs_mountroot: RTM_ADD: %d", error);
486 1.1 dholland }
487 1.1 dholland
488 1.1 dholland /*
489 1.1 dholland * Create the rootfs mount point.
490 1.1 dholland */
491 1.1 dholland nd->root_args.fh = nd->root_fh;
492 1.1 dholland nd->root_args.fhsize = nd->root_fhsize;
493 1.1 dholland l = ntohl(nd->root_saddr.sin_addr.s_addr);
494 1.1 dholland snprintf(buf, sizeof(buf), "%ld.%ld.%ld.%ld:%s",
495 1.1 dholland (l >> 24) & 0xff, (l >> 16) & 0xff,
496 1.1 dholland (l >> 8) & 0xff, (l >> 0) & 0xff, nd->root_hostnam);
497 1.1 dholland printf("NFS ROOT: %s\n", buf);
498 1.1 dholland nd->root_args.hostname = buf;
499 1.1 dholland if ((error = nfs_mountdiskless(buf,
500 1.1 dholland &nd->root_saddr, &nd->root_args, td, &vp, mp)) != 0) {
501 1.1 dholland return (error);
502 1.1 dholland }
503 1.1 dholland
504 1.1 dholland /*
505 1.1 dholland * This is not really an nfs issue, but it is much easier to
506 1.1 dholland * set hostname here and then let the "/etc/rc.xxx" files
507 1.1 dholland * mount the right /var based upon its preset value.
508 1.1 dholland */
509 1.1 dholland mtx_lock(&prison0.pr_mtx);
510 1.1 dholland strlcpy(prison0.pr_hostname, nd->my_hostnam,
511 1.1 dholland sizeof(prison0.pr_hostname));
512 1.1 dholland mtx_unlock(&prison0.pr_mtx);
513 1.1 dholland inittodr(ntohl(nd->root_time));
514 1.1 dholland return (0);
515 1.1 dholland }
516 1.1 dholland
517 1.1 dholland /*
518 1.1 dholland * Internal version of mount system call for diskless setup.
519 1.1 dholland */
520 1.1 dholland static int
521 1.1 dholland nfs_mountdiskless(char *path,
522 1.1 dholland struct sockaddr_in *sin, struct nfs_args *args, struct thread *td,
523 1.1 dholland struct vnode **vpp, struct mount *mp)
524 1.1 dholland {
525 1.1 dholland struct sockaddr *nam;
526 1.1 dholland int dirlen, error;
527 1.1 dholland char *dirpath;
528 1.1 dholland
529 1.1 dholland /*
530 1.1 dholland * Find the directory path in "path", which also has the server's
531 1.1 dholland * name/ip address in it.
532 1.1 dholland */
533 1.1 dholland dirpath = strchr(path, ':');
534 1.1 dholland if (dirpath != NULL)
535 1.1 dholland dirlen = strlen(++dirpath);
536 1.1 dholland else
537 1.1 dholland dirlen = 0;
538 1.1 dholland nam = sodupsockaddr((struct sockaddr *)sin, M_WAITOK);
539 1.1 dholland if ((error = mountnfs(args, mp, nam, path, NULL, 0, dirpath, dirlen,
540 1.1 dholland NULL, 0, vpp, td->td_ucred, td, NFS_DEFAULT_NAMETIMEO,
541 1.1 dholland NFS_DEFAULT_NEGNAMETIMEO, 0)) != 0) {
542 1.1 dholland printf("nfs_mountroot: mount %s on /: %d\n", path, error);
543 1.1 dholland return (error);
544 1.1 dholland }
545 1.1 dholland return (0);
546 1.1 dholland }
547 1.1 dholland
548 1.1 dholland static void
549 1.1 dholland nfs_sec_name(char *sec, int *flagsp)
550 1.1 dholland {
551 1.1 dholland if (!strcmp(sec, "krb5"))
552 1.1 dholland *flagsp |= NFSMNT_KERB;
553 1.1 dholland else if (!strcmp(sec, "krb5i"))
554 1.1 dholland *flagsp |= (NFSMNT_KERB | NFSMNT_INTEGRITY);
555 1.1 dholland else if (!strcmp(sec, "krb5p"))
556 1.1 dholland *flagsp |= (NFSMNT_KERB | NFSMNT_PRIVACY);
557 1.1 dholland }
558 1.1 dholland
559 1.1 dholland static void
560 1.1 dholland nfs_decode_args(struct mount *mp, struct nfsmount *nmp, struct nfs_args *argp,
561 1.1 dholland const char *hostname, struct ucred *cred, struct thread *td)
562 1.1 dholland {
563 1.1 dholland int s;
564 1.1 dholland int adjsock;
565 1.1 dholland char *p;
566 1.1 dholland
567 1.1 dholland s = splnet();
568 1.1 dholland
569 1.1 dholland /*
570 1.1 dholland * Set read-only flag if requested; otherwise, clear it if this is
571 1.1 dholland * an update. If this is not an update, then either the read-only
572 1.1 dholland * flag is already clear, or this is a root mount and it was set
573 1.1 dholland * intentionally at some previous point.
574 1.1 dholland */
575 1.1 dholland if (vfs_getopt(mp->mnt_optnew, "ro", NULL, NULL) == 0) {
576 1.1 dholland MNT_ILOCK(mp);
577 1.1 dholland mp->mnt_flag |= MNT_RDONLY;
578 1.1 dholland MNT_IUNLOCK(mp);
579 1.1 dholland } else if (mp->mnt_flag & MNT_UPDATE) {
580 1.1 dholland MNT_ILOCK(mp);
581 1.1 dholland mp->mnt_flag &= ~MNT_RDONLY;
582 1.1 dholland MNT_IUNLOCK(mp);
583 1.1 dholland }
584 1.1 dholland
585 1.1 dholland /*
586 1.1 dholland * Silently clear NFSMNT_NOCONN if it's a TCP mount, it makes
587 1.1 dholland * no sense in that context. Also, set up appropriate retransmit
588 1.1 dholland * and soft timeout behavior.
589 1.1 dholland */
590 1.1 dholland if (argp->sotype == SOCK_STREAM) {
591 1.1 dholland nmp->nm_flag &= ~NFSMNT_NOCONN;
592 1.1 dholland nmp->nm_timeo = NFS_MAXTIMEO;
593 1.1 dholland if ((argp->flags & NFSMNT_NFSV4) != 0)
594 1.1 dholland nmp->nm_retry = INT_MAX;
595 1.1 dholland else
596 1.1 dholland nmp->nm_retry = NFS_RETRANS_TCP;
597 1.1 dholland }
598 1.1 dholland
599 1.1 dholland /* Also clear RDIRPLUS if NFSv2, it crashes some servers */
600 1.1 dholland if ((argp->flags & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0) {
601 1.1 dholland argp->flags &= ~NFSMNT_RDIRPLUS;
602 1.1 dholland nmp->nm_flag &= ~NFSMNT_RDIRPLUS;
603 1.1 dholland }
604 1.1 dholland
605 1.1 dholland /* Re-bind if rsrvd port requested and wasn't on one */
606 1.1 dholland adjsock = !(nmp->nm_flag & NFSMNT_RESVPORT)
607 1.1 dholland && (argp->flags & NFSMNT_RESVPORT);
608 1.1 dholland /* Also re-bind if we're switching to/from a connected UDP socket */
609 1.1 dholland adjsock |= ((nmp->nm_flag & NFSMNT_NOCONN) !=
610 1.1 dholland (argp->flags & NFSMNT_NOCONN));
611 1.1 dholland
612 1.1 dholland /* Update flags atomically. Don't change the lock bits. */
613 1.1 dholland nmp->nm_flag = argp->flags | nmp->nm_flag;
614 1.1 dholland splx(s);
615 1.1 dholland
616 1.1 dholland if ((argp->flags & NFSMNT_TIMEO) && argp->timeo > 0) {
617 1.1 dholland nmp->nm_timeo = (argp->timeo * NFS_HZ + 5) / 10;
618 1.1 dholland if (nmp->nm_timeo < NFS_MINTIMEO)
619 1.1 dholland nmp->nm_timeo = NFS_MINTIMEO;
620 1.1 dholland else if (nmp->nm_timeo > NFS_MAXTIMEO)
621 1.1 dholland nmp->nm_timeo = NFS_MAXTIMEO;
622 1.1 dholland }
623 1.1 dholland
624 1.1 dholland if ((argp->flags & NFSMNT_RETRANS) && argp->retrans > 1) {
625 1.1 dholland nmp->nm_retry = argp->retrans;
626 1.1 dholland if (nmp->nm_retry > NFS_MAXREXMIT)
627 1.1 dholland nmp->nm_retry = NFS_MAXREXMIT;
628 1.1 dholland }
629 1.1 dholland
630 1.1 dholland if ((argp->flags & NFSMNT_WSIZE) && argp->wsize > 0) {
631 1.1 dholland nmp->nm_wsize = argp->wsize;
632 1.1.1.2 pgoyette /*
633 1.1.1.2 pgoyette * Clip at the power of 2 below the size. There is an
634 1.1.1.2 pgoyette * issue (not isolated) that causes intermittent page
635 1.1.1.2 pgoyette * faults if this is not done.
636 1.1.1.2 pgoyette */
637 1.1.1.2 pgoyette if (nmp->nm_wsize > NFS_FABLKSIZE)
638 1.1.1.2 pgoyette nmp->nm_wsize = 1 << (fls(nmp->nm_wsize) - 1);
639 1.1.1.2 pgoyette else
640 1.1 dholland nmp->nm_wsize = NFS_FABLKSIZE;
641 1.1 dholland }
642 1.1 dholland
643 1.1 dholland if ((argp->flags & NFSMNT_RSIZE) && argp->rsize > 0) {
644 1.1 dholland nmp->nm_rsize = argp->rsize;
645 1.1.1.2 pgoyette /*
646 1.1.1.2 pgoyette * Clip at the power of 2 below the size. There is an
647 1.1.1.2 pgoyette * issue (not isolated) that causes intermittent page
648 1.1.1.2 pgoyette * faults if this is not done.
649 1.1.1.2 pgoyette */
650 1.1.1.2 pgoyette if (nmp->nm_rsize > NFS_FABLKSIZE)
651 1.1.1.2 pgoyette nmp->nm_rsize = 1 << (fls(nmp->nm_rsize) - 1);
652 1.1.1.2 pgoyette else
653 1.1 dholland nmp->nm_rsize = NFS_FABLKSIZE;
654 1.1 dholland }
655 1.1 dholland
656 1.1 dholland if ((argp->flags & NFSMNT_READDIRSIZE) && argp->readdirsize > 0) {
657 1.1 dholland nmp->nm_readdirsize = argp->readdirsize;
658 1.1 dholland }
659 1.1 dholland
660 1.1 dholland if ((argp->flags & NFSMNT_ACREGMIN) && argp->acregmin >= 0)
661 1.1 dholland nmp->nm_acregmin = argp->acregmin;
662 1.1 dholland else
663 1.1 dholland nmp->nm_acregmin = NFS_MINATTRTIMO;
664 1.1 dholland if ((argp->flags & NFSMNT_ACREGMAX) && argp->acregmax >= 0)
665 1.1 dholland nmp->nm_acregmax = argp->acregmax;
666 1.1 dholland else
667 1.1 dholland nmp->nm_acregmax = NFS_MAXATTRTIMO;
668 1.1 dholland if ((argp->flags & NFSMNT_ACDIRMIN) && argp->acdirmin >= 0)
669 1.1 dholland nmp->nm_acdirmin = argp->acdirmin;
670 1.1 dholland else
671 1.1 dholland nmp->nm_acdirmin = NFS_MINDIRATTRTIMO;
672 1.1 dholland if ((argp->flags & NFSMNT_ACDIRMAX) && argp->acdirmax >= 0)
673 1.1 dholland nmp->nm_acdirmax = argp->acdirmax;
674 1.1 dholland else
675 1.1 dholland nmp->nm_acdirmax = NFS_MAXDIRATTRTIMO;
676 1.1 dholland if (nmp->nm_acdirmin > nmp->nm_acdirmax)
677 1.1 dholland nmp->nm_acdirmin = nmp->nm_acdirmax;
678 1.1 dholland if (nmp->nm_acregmin > nmp->nm_acregmax)
679 1.1 dholland nmp->nm_acregmin = nmp->nm_acregmax;
680 1.1 dholland
681 1.1 dholland if ((argp->flags & NFSMNT_READAHEAD) && argp->readahead >= 0) {
682 1.1 dholland if (argp->readahead <= NFS_MAXRAHEAD)
683 1.1 dholland nmp->nm_readahead = argp->readahead;
684 1.1 dholland else
685 1.1 dholland nmp->nm_readahead = NFS_MAXRAHEAD;
686 1.1 dholland }
687 1.1 dholland if ((argp->flags & NFSMNT_WCOMMITSIZE) && argp->wcommitsize >= 0) {
688 1.1 dholland if (argp->wcommitsize < nmp->nm_wsize)
689 1.1 dholland nmp->nm_wcommitsize = nmp->nm_wsize;
690 1.1 dholland else
691 1.1 dholland nmp->nm_wcommitsize = argp->wcommitsize;
692 1.1 dholland }
693 1.1 dholland
694 1.1 dholland adjsock |= ((nmp->nm_sotype != argp->sotype) ||
695 1.1 dholland (nmp->nm_soproto != argp->proto));
696 1.1 dholland
697 1.1 dholland if (nmp->nm_client != NULL && adjsock) {
698 1.1 dholland int haslock = 0, error = 0;
699 1.1 dholland
700 1.1 dholland if (nmp->nm_sotype == SOCK_STREAM) {
701 1.1 dholland error = newnfs_sndlock(&nmp->nm_sockreq.nr_lock);
702 1.1 dholland if (!error)
703 1.1 dholland haslock = 1;
704 1.1 dholland }
705 1.1 dholland if (!error) {
706 1.1 dholland newnfs_disconnect(&nmp->nm_sockreq);
707 1.1 dholland if (haslock)
708 1.1 dholland newnfs_sndunlock(&nmp->nm_sockreq.nr_lock);
709 1.1 dholland nmp->nm_sotype = argp->sotype;
710 1.1 dholland nmp->nm_soproto = argp->proto;
711 1.1 dholland if (nmp->nm_sotype == SOCK_DGRAM)
712 1.1 dholland while (newnfs_connect(nmp, &nmp->nm_sockreq,
713 1.1 dholland cred, td, 0)) {
714 1.1 dholland printf("newnfs_args: retrying connect\n");
715 1.1.1.2 pgoyette (void) nfs_catnap(PSOCK, 0, "nfscon");
716 1.1 dholland }
717 1.1 dholland }
718 1.1 dholland } else {
719 1.1 dholland nmp->nm_sotype = argp->sotype;
720 1.1 dholland nmp->nm_soproto = argp->proto;
721 1.1 dholland }
722 1.1 dholland
723 1.1 dholland if (hostname != NULL) {
724 1.1 dholland strlcpy(nmp->nm_hostname, hostname,
725 1.1 dholland sizeof(nmp->nm_hostname));
726 1.1 dholland p = strchr(nmp->nm_hostname, ':');
727 1.1 dholland if (p != NULL)
728 1.1 dholland *p = '\0';
729 1.1 dholland }
730 1.1 dholland }
731 1.1 dholland
732 1.1 dholland static const char *nfs_opts[] = { "from", "nfs_args",
733 1.1.1.2 pgoyette "noac", "noatime", "noexec", "suiddir", "nosuid", "nosymfollow", "union",
734 1.1 dholland "noclusterr", "noclusterw", "multilabel", "acls", "force", "update",
735 1.1 dholland "async", "noconn", "nolockd", "conn", "lockd", "intr", "rdirplus",
736 1.1 dholland "readdirsize", "soft", "hard", "mntudp", "tcp", "udp", "wsize", "rsize",
737 1.1.1.2 pgoyette "retrans", "actimeo", "acregmin", "acregmax", "acdirmin", "acdirmax",
738 1.1.1.2 pgoyette "resvport", "readahead", "hostname", "timeo", "timeout", "addr", "fh",
739 1.1.1.2 pgoyette "nfsv3", "sec", "principal", "nfsv4", "gssname", "allgssname", "dirpath",
740 1.1.1.2 pgoyette "minorversion", "nametimeo", "negnametimeo", "nocto", "noncontigwr",
741 1.1.1.2 pgoyette "pnfs", "wcommitsize",
742 1.1 dholland NULL };
743 1.1 dholland
744 1.1 dholland /*
745 1.1.1.2 pgoyette * Parse the "from" mountarg, passed by the generic mount(8) program
746 1.1.1.2 pgoyette * or the mountroot code. This is used when rerooting into NFS.
747 1.1.1.2 pgoyette *
748 1.1.1.2 pgoyette * Note that the "hostname" is actually a "hostname:/share/path" string.
749 1.1.1.2 pgoyette */
750 1.1.1.2 pgoyette static int
751 1.1.1.2 pgoyette nfs_mount_parse_from(struct vfsoptlist *opts, char **hostnamep,
752 1.1.1.2 pgoyette struct sockaddr_in **sinp, char *dirpath, size_t dirpathsize, int *dirlenp)
753 1.1.1.2 pgoyette {
754 1.1.1.2 pgoyette char nam[MNAMELEN + 1];
755 1.1.1.2 pgoyette char *delimp, *hostp, *spec;
756 1.1.1.2 pgoyette int error, have_bracket = 0, offset, rv, speclen;
757 1.1.1.2 pgoyette struct sockaddr_in *sin;
758 1.1.1.2 pgoyette size_t len;
759 1.1.1.2 pgoyette
760 1.1.1.2 pgoyette error = vfs_getopt(opts, "from", (void **)&spec, &speclen);
761 1.1.1.2 pgoyette if (error != 0)
762 1.1.1.2 pgoyette return (error);
763 1.1.1.2 pgoyette
764 1.1.1.2 pgoyette /*
765 1.1.1.2 pgoyette * This part comes from sbin/mount_nfs/mount_nfs.c:getnfsargs().
766 1.1.1.2 pgoyette */
767 1.1.1.2 pgoyette if (*spec == '[' && (delimp = strchr(spec + 1, ']')) != NULL &&
768 1.1.1.2 pgoyette *(delimp + 1) == ':') {
769 1.1.1.2 pgoyette hostp = spec + 1;
770 1.1.1.2 pgoyette spec = delimp + 2;
771 1.1.1.2 pgoyette have_bracket = 1;
772 1.1.1.2 pgoyette } else if ((delimp = strrchr(spec, ':')) != NULL) {
773 1.1.1.2 pgoyette hostp = spec;
774 1.1.1.2 pgoyette spec = delimp + 1;
775 1.1.1.2 pgoyette } else if ((delimp = strrchr(spec, '@')) != NULL) {
776 1.1.1.2 pgoyette printf("%s: path@server syntax is deprecated, "
777 1.1.1.2 pgoyette "use server:path\n", __func__);
778 1.1.1.2 pgoyette hostp = delimp + 1;
779 1.1.1.2 pgoyette } else {
780 1.1.1.2 pgoyette printf("%s: no <host>:<dirpath> nfs-name\n", __func__);
781 1.1.1.2 pgoyette return (EINVAL);
782 1.1.1.2 pgoyette }
783 1.1.1.2 pgoyette *delimp = '\0';
784 1.1.1.2 pgoyette
785 1.1.1.2 pgoyette /*
786 1.1.1.2 pgoyette * If there has been a trailing slash at mounttime it seems
787 1.1.1.2 pgoyette * that some mountd implementations fail to remove the mount
788 1.1.1.2 pgoyette * entries from their mountlist while unmounting.
789 1.1.1.2 pgoyette */
790 1.1.1.2 pgoyette for (speclen = strlen(spec);
791 1.1.1.2 pgoyette speclen > 1 && spec[speclen - 1] == '/';
792 1.1.1.2 pgoyette speclen--)
793 1.1.1.2 pgoyette spec[speclen - 1] = '\0';
794 1.1.1.2 pgoyette if (strlen(hostp) + strlen(spec) + 1 > MNAMELEN) {
795 1.1.1.2 pgoyette printf("%s: %s:%s: name too long", __func__, hostp, spec);
796 1.1.1.2 pgoyette return (EINVAL);
797 1.1.1.2 pgoyette }
798 1.1.1.2 pgoyette /* Make both '@' and ':' notations equal */
799 1.1.1.2 pgoyette if (*hostp != '\0') {
800 1.1.1.2 pgoyette len = strlen(hostp);
801 1.1.1.2 pgoyette offset = 0;
802 1.1.1.2 pgoyette if (have_bracket)
803 1.1.1.2 pgoyette nam[offset++] = '[';
804 1.1.1.2 pgoyette memmove(nam + offset, hostp, len);
805 1.1.1.2 pgoyette if (have_bracket)
806 1.1.1.2 pgoyette nam[len + offset++] = ']';
807 1.1.1.2 pgoyette nam[len + offset++] = ':';
808 1.1.1.2 pgoyette memmove(nam + len + offset, spec, speclen);
809 1.1.1.2 pgoyette nam[len + speclen + offset] = '\0';
810 1.1.1.2 pgoyette } else
811 1.1.1.2 pgoyette nam[0] = '\0';
812 1.1.1.2 pgoyette
813 1.1.1.2 pgoyette /*
814 1.1.1.2 pgoyette * XXX: IPv6
815 1.1.1.2 pgoyette */
816 1.1.1.2 pgoyette sin = malloc(sizeof(*sin), M_SONAME, M_WAITOK);
817 1.1.1.2 pgoyette rv = inet_pton(AF_INET, hostp, &sin->sin_addr);
818 1.1.1.2 pgoyette if (rv != 1) {
819 1.1.1.2 pgoyette printf("%s: cannot parse '%s', inet_pton() returned %d\n",
820 1.1.1.2 pgoyette __func__, hostp, rv);
821 1.1.1.2 pgoyette free(sin, M_SONAME);
822 1.1.1.2 pgoyette return (EINVAL);
823 1.1.1.2 pgoyette }
824 1.1.1.2 pgoyette
825 1.1.1.2 pgoyette sin->sin_len = sizeof(*sin);
826 1.1.1.2 pgoyette sin->sin_family = AF_INET;
827 1.1.1.2 pgoyette /*
828 1.1.1.2 pgoyette * XXX: hardcoded port number.
829 1.1.1.2 pgoyette */
830 1.1.1.2 pgoyette sin->sin_port = htons(2049);
831 1.1.1.2 pgoyette
832 1.1.1.2 pgoyette *hostnamep = strdup(nam, M_NEWNFSMNT);
833 1.1.1.2 pgoyette *sinp = sin;
834 1.1.1.2 pgoyette strlcpy(dirpath, spec, dirpathsize);
835 1.1.1.2 pgoyette *dirlenp = strlen(dirpath);
836 1.1.1.2 pgoyette
837 1.1.1.2 pgoyette return (0);
838 1.1.1.2 pgoyette }
839 1.1.1.2 pgoyette
840 1.1.1.2 pgoyette /*
841 1.1 dholland * VFS Operations.
842 1.1 dholland *
843 1.1 dholland * mount system call
844 1.1 dholland * It seems a bit dumb to copyinstr() the host and path here and then
845 1.1 dholland * bcopy() them in mountnfs(), but I wanted to detect errors before
846 1.1.1.2 pgoyette * doing the getsockaddr() call because getsockaddr() allocates an mbuf and
847 1.1 dholland * an error after that means that I have to release the mbuf.
848 1.1 dholland */
849 1.1 dholland /* ARGSUSED */
850 1.1 dholland static int
851 1.1 dholland nfs_mount(struct mount *mp)
852 1.1 dholland {
853 1.1 dholland struct nfs_args args = {
854 1.1 dholland .version = NFS_ARGSVERSION,
855 1.1 dholland .addr = NULL,
856 1.1 dholland .addrlen = sizeof (struct sockaddr_in),
857 1.1 dholland .sotype = SOCK_STREAM,
858 1.1 dholland .proto = 0,
859 1.1 dholland .fh = NULL,
860 1.1 dholland .fhsize = 0,
861 1.1 dholland .flags = NFSMNT_RESVPORT,
862 1.1 dholland .wsize = NFS_WSIZE,
863 1.1 dholland .rsize = NFS_RSIZE,
864 1.1 dholland .readdirsize = NFS_READDIRSIZE,
865 1.1 dholland .timeo = 10,
866 1.1 dholland .retrans = NFS_RETRANS,
867 1.1 dholland .readahead = NFS_DEFRAHEAD,
868 1.1 dholland .wcommitsize = 0, /* was: NQ_DEFLEASE */
869 1.1 dholland .hostname = NULL,
870 1.1 dholland .acregmin = NFS_MINATTRTIMO,
871 1.1 dholland .acregmax = NFS_MAXATTRTIMO,
872 1.1 dholland .acdirmin = NFS_MINDIRATTRTIMO,
873 1.1 dholland .acdirmax = NFS_MAXDIRATTRTIMO,
874 1.1 dholland };
875 1.1 dholland int error = 0, ret, len;
876 1.1 dholland struct sockaddr *nam = NULL;
877 1.1 dholland struct vnode *vp;
878 1.1 dholland struct thread *td;
879 1.1 dholland char hst[MNAMELEN];
880 1.1 dholland u_char nfh[NFSX_FHMAX], krbname[100], dirpath[100], srvkrbname[100];
881 1.1.1.2 pgoyette char *cp, *opt, *name, *secname;
882 1.1 dholland int nametimeo = NFS_DEFAULT_NAMETIMEO;
883 1.1 dholland int negnametimeo = NFS_DEFAULT_NEGNAMETIMEO;
884 1.1 dholland int minvers = 0;
885 1.1.1.2 pgoyette int dirlen, has_nfs_args_opt, has_nfs_from_opt,
886 1.1.1.2 pgoyette krbnamelen, srvkrbnamelen;
887 1.1 dholland size_t hstlen;
888 1.1 dholland
889 1.1 dholland has_nfs_args_opt = 0;
890 1.1.1.2 pgoyette has_nfs_from_opt = 0;
891 1.1 dholland if (vfs_filteropt(mp->mnt_optnew, nfs_opts)) {
892 1.1 dholland error = EINVAL;
893 1.1 dholland goto out;
894 1.1 dholland }
895 1.1 dholland
896 1.1 dholland td = curthread;
897 1.1.1.2 pgoyette if ((mp->mnt_flag & (MNT_ROOTFS | MNT_UPDATE)) == MNT_ROOTFS &&
898 1.1.1.2 pgoyette nfs_diskless_valid != 0) {
899 1.1 dholland error = nfs_mountroot(mp);
900 1.1 dholland goto out;
901 1.1 dholland }
902 1.1 dholland
903 1.1 dholland nfscl_init();
904 1.1 dholland
905 1.1 dholland /*
906 1.1 dholland * The old mount_nfs program passed the struct nfs_args
907 1.1 dholland * from userspace to kernel. The new mount_nfs program
908 1.1 dholland * passes string options via nmount() from userspace to kernel
909 1.1 dholland * and we populate the struct nfs_args in the kernel.
910 1.1 dholland */
911 1.1 dholland if (vfs_getopt(mp->mnt_optnew, "nfs_args", NULL, NULL) == 0) {
912 1.1 dholland error = vfs_copyopt(mp->mnt_optnew, "nfs_args", &args,
913 1.1 dholland sizeof(args));
914 1.1 dholland if (error != 0)
915 1.1 dholland goto out;
916 1.1 dholland
917 1.1 dholland if (args.version != NFS_ARGSVERSION) {
918 1.1 dholland error = EPROGMISMATCH;
919 1.1 dholland goto out;
920 1.1 dholland }
921 1.1 dholland has_nfs_args_opt = 1;
922 1.1 dholland }
923 1.1 dholland
924 1.1 dholland /* Handle the new style options. */
925 1.1.1.2 pgoyette if (vfs_getopt(mp->mnt_optnew, "noac", NULL, NULL) == 0) {
926 1.1.1.2 pgoyette args.acdirmin = args.acdirmax =
927 1.1.1.2 pgoyette args.acregmin = args.acregmax = 0;
928 1.1.1.2 pgoyette args.flags |= NFSMNT_ACDIRMIN | NFSMNT_ACDIRMAX |
929 1.1.1.2 pgoyette NFSMNT_ACREGMIN | NFSMNT_ACREGMAX;
930 1.1.1.2 pgoyette }
931 1.1 dholland if (vfs_getopt(mp->mnt_optnew, "noconn", NULL, NULL) == 0)
932 1.1 dholland args.flags |= NFSMNT_NOCONN;
933 1.1 dholland if (vfs_getopt(mp->mnt_optnew, "conn", NULL, NULL) == 0)
934 1.1.1.2 pgoyette args.flags &= ~NFSMNT_NOCONN;
935 1.1 dholland if (vfs_getopt(mp->mnt_optnew, "nolockd", NULL, NULL) == 0)
936 1.1 dholland args.flags |= NFSMNT_NOLOCKD;
937 1.1 dholland if (vfs_getopt(mp->mnt_optnew, "lockd", NULL, NULL) == 0)
938 1.1 dholland args.flags &= ~NFSMNT_NOLOCKD;
939 1.1 dholland if (vfs_getopt(mp->mnt_optnew, "intr", NULL, NULL) == 0)
940 1.1 dholland args.flags |= NFSMNT_INT;
941 1.1 dholland if (vfs_getopt(mp->mnt_optnew, "rdirplus", NULL, NULL) == 0)
942 1.1 dholland args.flags |= NFSMNT_RDIRPLUS;
943 1.1 dholland if (vfs_getopt(mp->mnt_optnew, "resvport", NULL, NULL) == 0)
944 1.1 dholland args.flags |= NFSMNT_RESVPORT;
945 1.1 dholland if (vfs_getopt(mp->mnt_optnew, "noresvport", NULL, NULL) == 0)
946 1.1 dholland args.flags &= ~NFSMNT_RESVPORT;
947 1.1 dholland if (vfs_getopt(mp->mnt_optnew, "soft", NULL, NULL) == 0)
948 1.1 dholland args.flags |= NFSMNT_SOFT;
949 1.1 dholland if (vfs_getopt(mp->mnt_optnew, "hard", NULL, NULL) == 0)
950 1.1 dholland args.flags &= ~NFSMNT_SOFT;
951 1.1 dholland if (vfs_getopt(mp->mnt_optnew, "mntudp", NULL, NULL) == 0)
952 1.1 dholland args.sotype = SOCK_DGRAM;
953 1.1 dholland if (vfs_getopt(mp->mnt_optnew, "udp", NULL, NULL) == 0)
954 1.1 dholland args.sotype = SOCK_DGRAM;
955 1.1 dholland if (vfs_getopt(mp->mnt_optnew, "tcp", NULL, NULL) == 0)
956 1.1 dholland args.sotype = SOCK_STREAM;
957 1.1 dholland if (vfs_getopt(mp->mnt_optnew, "nfsv3", NULL, NULL) == 0)
958 1.1 dholland args.flags |= NFSMNT_NFSV3;
959 1.1 dholland if (vfs_getopt(mp->mnt_optnew, "nfsv4", NULL, NULL) == 0) {
960 1.1 dholland args.flags |= NFSMNT_NFSV4;
961 1.1 dholland args.sotype = SOCK_STREAM;
962 1.1 dholland }
963 1.1 dholland if (vfs_getopt(mp->mnt_optnew, "allgssname", NULL, NULL) == 0)
964 1.1 dholland args.flags |= NFSMNT_ALLGSSNAME;
965 1.1 dholland if (vfs_getopt(mp->mnt_optnew, "nocto", NULL, NULL) == 0)
966 1.1 dholland args.flags |= NFSMNT_NOCTO;
967 1.1.1.2 pgoyette if (vfs_getopt(mp->mnt_optnew, "noncontigwr", NULL, NULL) == 0)
968 1.1.1.2 pgoyette args.flags |= NFSMNT_NONCONTIGWR;
969 1.1 dholland if (vfs_getopt(mp->mnt_optnew, "pnfs", NULL, NULL) == 0)
970 1.1 dholland args.flags |= NFSMNT_PNFS;
971 1.1 dholland if (vfs_getopt(mp->mnt_optnew, "readdirsize", (void **)&opt, NULL) == 0) {
972 1.1 dholland if (opt == NULL) {
973 1.1 dholland vfs_mount_error(mp, "illegal readdirsize");
974 1.1 dholland error = EINVAL;
975 1.1 dholland goto out;
976 1.1 dholland }
977 1.1 dholland ret = sscanf(opt, "%d", &args.readdirsize);
978 1.1 dholland if (ret != 1 || args.readdirsize <= 0) {
979 1.1 dholland vfs_mount_error(mp, "illegal readdirsize: %s",
980 1.1 dholland opt);
981 1.1 dholland error = EINVAL;
982 1.1 dholland goto out;
983 1.1 dholland }
984 1.1 dholland args.flags |= NFSMNT_READDIRSIZE;
985 1.1 dholland }
986 1.1 dholland if (vfs_getopt(mp->mnt_optnew, "readahead", (void **)&opt, NULL) == 0) {
987 1.1 dholland if (opt == NULL) {
988 1.1 dholland vfs_mount_error(mp, "illegal readahead");
989 1.1 dholland error = EINVAL;
990 1.1 dholland goto out;
991 1.1 dholland }
992 1.1 dholland ret = sscanf(opt, "%d", &args.readahead);
993 1.1 dholland if (ret != 1 || args.readahead <= 0) {
994 1.1 dholland vfs_mount_error(mp, "illegal readahead: %s",
995 1.1 dholland opt);
996 1.1 dholland error = EINVAL;
997 1.1 dholland goto out;
998 1.1 dholland }
999 1.1 dholland args.flags |= NFSMNT_READAHEAD;
1000 1.1 dholland }
1001 1.1 dholland if (vfs_getopt(mp->mnt_optnew, "wsize", (void **)&opt, NULL) == 0) {
1002 1.1 dholland if (opt == NULL) {
1003 1.1 dholland vfs_mount_error(mp, "illegal wsize");
1004 1.1 dholland error = EINVAL;
1005 1.1 dholland goto out;
1006 1.1 dholland }
1007 1.1 dholland ret = sscanf(opt, "%d", &args.wsize);
1008 1.1 dholland if (ret != 1 || args.wsize <= 0) {
1009 1.1 dholland vfs_mount_error(mp, "illegal wsize: %s",
1010 1.1 dholland opt);
1011 1.1 dholland error = EINVAL;
1012 1.1 dholland goto out;
1013 1.1 dholland }
1014 1.1 dholland args.flags |= NFSMNT_WSIZE;
1015 1.1 dholland }
1016 1.1 dholland if (vfs_getopt(mp->mnt_optnew, "rsize", (void **)&opt, NULL) == 0) {
1017 1.1 dholland if (opt == NULL) {
1018 1.1 dholland vfs_mount_error(mp, "illegal rsize");
1019 1.1 dholland error = EINVAL;
1020 1.1 dholland goto out;
1021 1.1 dholland }
1022 1.1 dholland ret = sscanf(opt, "%d", &args.rsize);
1023 1.1 dholland if (ret != 1 || args.rsize <= 0) {
1024 1.1 dholland vfs_mount_error(mp, "illegal wsize: %s",
1025 1.1 dholland opt);
1026 1.1 dholland error = EINVAL;
1027 1.1 dholland goto out;
1028 1.1 dholland }
1029 1.1 dholland args.flags |= NFSMNT_RSIZE;
1030 1.1 dholland }
1031 1.1 dholland if (vfs_getopt(mp->mnt_optnew, "retrans", (void **)&opt, NULL) == 0) {
1032 1.1 dholland if (opt == NULL) {
1033 1.1 dholland vfs_mount_error(mp, "illegal retrans");
1034 1.1 dholland error = EINVAL;
1035 1.1 dholland goto out;
1036 1.1 dholland }
1037 1.1 dholland ret = sscanf(opt, "%d", &args.retrans);
1038 1.1 dholland if (ret != 1 || args.retrans <= 0) {
1039 1.1 dholland vfs_mount_error(mp, "illegal retrans: %s",
1040 1.1 dholland opt);
1041 1.1 dholland error = EINVAL;
1042 1.1 dholland goto out;
1043 1.1 dholland }
1044 1.1 dholland args.flags |= NFSMNT_RETRANS;
1045 1.1 dholland }
1046 1.1.1.2 pgoyette if (vfs_getopt(mp->mnt_optnew, "actimeo", (void **)&opt, NULL) == 0) {
1047 1.1.1.2 pgoyette ret = sscanf(opt, "%d", &args.acregmin);
1048 1.1.1.2 pgoyette if (ret != 1 || args.acregmin < 0) {
1049 1.1.1.2 pgoyette vfs_mount_error(mp, "illegal actimeo: %s",
1050 1.1.1.2 pgoyette opt);
1051 1.1.1.2 pgoyette error = EINVAL;
1052 1.1.1.2 pgoyette goto out;
1053 1.1.1.2 pgoyette }
1054 1.1.1.2 pgoyette args.acdirmin = args.acdirmax = args.acregmax = args.acregmin;
1055 1.1.1.2 pgoyette args.flags |= NFSMNT_ACDIRMIN | NFSMNT_ACDIRMAX |
1056 1.1.1.2 pgoyette NFSMNT_ACREGMIN | NFSMNT_ACREGMAX;
1057 1.1.1.2 pgoyette }
1058 1.1 dholland if (vfs_getopt(mp->mnt_optnew, "acregmin", (void **)&opt, NULL) == 0) {
1059 1.1 dholland ret = sscanf(opt, "%d", &args.acregmin);
1060 1.1 dholland if (ret != 1 || args.acregmin < 0) {
1061 1.1 dholland vfs_mount_error(mp, "illegal acregmin: %s",
1062 1.1 dholland opt);
1063 1.1 dholland error = EINVAL;
1064 1.1 dholland goto out;
1065 1.1 dholland }
1066 1.1 dholland args.flags |= NFSMNT_ACREGMIN;
1067 1.1 dholland }
1068 1.1 dholland if (vfs_getopt(mp->mnt_optnew, "acregmax", (void **)&opt, NULL) == 0) {
1069 1.1 dholland ret = sscanf(opt, "%d", &args.acregmax);
1070 1.1 dholland if (ret != 1 || args.acregmax < 0) {
1071 1.1 dholland vfs_mount_error(mp, "illegal acregmax: %s",
1072 1.1 dholland opt);
1073 1.1 dholland error = EINVAL;
1074 1.1 dholland goto out;
1075 1.1 dholland }
1076 1.1 dholland args.flags |= NFSMNT_ACREGMAX;
1077 1.1 dholland }
1078 1.1 dholland if (vfs_getopt(mp->mnt_optnew, "acdirmin", (void **)&opt, NULL) == 0) {
1079 1.1 dholland ret = sscanf(opt, "%d", &args.acdirmin);
1080 1.1 dholland if (ret != 1 || args.acdirmin < 0) {
1081 1.1 dholland vfs_mount_error(mp, "illegal acdirmin: %s",
1082 1.1 dholland opt);
1083 1.1 dholland error = EINVAL;
1084 1.1 dholland goto out;
1085 1.1 dholland }
1086 1.1 dholland args.flags |= NFSMNT_ACDIRMIN;
1087 1.1 dholland }
1088 1.1 dholland if (vfs_getopt(mp->mnt_optnew, "acdirmax", (void **)&opt, NULL) == 0) {
1089 1.1 dholland ret = sscanf(opt, "%d", &args.acdirmax);
1090 1.1 dholland if (ret != 1 || args.acdirmax < 0) {
1091 1.1 dholland vfs_mount_error(mp, "illegal acdirmax: %s",
1092 1.1 dholland opt);
1093 1.1 dholland error = EINVAL;
1094 1.1 dholland goto out;
1095 1.1 dholland }
1096 1.1 dholland args.flags |= NFSMNT_ACDIRMAX;
1097 1.1 dholland }
1098 1.1 dholland if (vfs_getopt(mp->mnt_optnew, "wcommitsize", (void **)&opt, NULL) == 0) {
1099 1.1 dholland ret = sscanf(opt, "%d", &args.wcommitsize);
1100 1.1 dholland if (ret != 1 || args.wcommitsize < 0) {
1101 1.1 dholland vfs_mount_error(mp, "illegal wcommitsize: %s", opt);
1102 1.1 dholland error = EINVAL;
1103 1.1 dholland goto out;
1104 1.1 dholland }
1105 1.1 dholland args.flags |= NFSMNT_WCOMMITSIZE;
1106 1.1 dholland }
1107 1.1.1.2 pgoyette if (vfs_getopt(mp->mnt_optnew, "timeo", (void **)&opt, NULL) == 0) {
1108 1.1.1.2 pgoyette ret = sscanf(opt, "%d", &args.timeo);
1109 1.1.1.2 pgoyette if (ret != 1 || args.timeo <= 0) {
1110 1.1.1.2 pgoyette vfs_mount_error(mp, "illegal timeo: %s",
1111 1.1.1.2 pgoyette opt);
1112 1.1.1.2 pgoyette error = EINVAL;
1113 1.1.1.2 pgoyette goto out;
1114 1.1.1.2 pgoyette }
1115 1.1.1.2 pgoyette args.flags |= NFSMNT_TIMEO;
1116 1.1.1.2 pgoyette }
1117 1.1 dholland if (vfs_getopt(mp->mnt_optnew, "timeout", (void **)&opt, NULL) == 0) {
1118 1.1 dholland ret = sscanf(opt, "%d", &args.timeo);
1119 1.1 dholland if (ret != 1 || args.timeo <= 0) {
1120 1.1 dholland vfs_mount_error(mp, "illegal timeout: %s",
1121 1.1 dholland opt);
1122 1.1 dholland error = EINVAL;
1123 1.1 dholland goto out;
1124 1.1 dholland }
1125 1.1 dholland args.flags |= NFSMNT_TIMEO;
1126 1.1 dholland }
1127 1.1 dholland if (vfs_getopt(mp->mnt_optnew, "nametimeo", (void **)&opt, NULL) == 0) {
1128 1.1 dholland ret = sscanf(opt, "%d", &nametimeo);
1129 1.1 dholland if (ret != 1 || nametimeo < 0) {
1130 1.1 dholland vfs_mount_error(mp, "illegal nametimeo: %s", opt);
1131 1.1 dholland error = EINVAL;
1132 1.1 dholland goto out;
1133 1.1 dholland }
1134 1.1 dholland }
1135 1.1 dholland if (vfs_getopt(mp->mnt_optnew, "negnametimeo", (void **)&opt, NULL)
1136 1.1 dholland == 0) {
1137 1.1 dholland ret = sscanf(opt, "%d", &negnametimeo);
1138 1.1 dholland if (ret != 1 || negnametimeo < 0) {
1139 1.1 dholland vfs_mount_error(mp, "illegal negnametimeo: %s",
1140 1.1 dholland opt);
1141 1.1 dholland error = EINVAL;
1142 1.1 dholland goto out;
1143 1.1 dholland }
1144 1.1 dholland }
1145 1.1 dholland if (vfs_getopt(mp->mnt_optnew, "minorversion", (void **)&opt, NULL) ==
1146 1.1 dholland 0) {
1147 1.1 dholland ret = sscanf(opt, "%d", &minvers);
1148 1.1 dholland if (ret != 1 || minvers < 0 || minvers > 1 ||
1149 1.1 dholland (args.flags & NFSMNT_NFSV4) == 0) {
1150 1.1 dholland vfs_mount_error(mp, "illegal minorversion: %s", opt);
1151 1.1 dholland error = EINVAL;
1152 1.1 dholland goto out;
1153 1.1 dholland }
1154 1.1 dholland }
1155 1.1 dholland if (vfs_getopt(mp->mnt_optnew, "sec",
1156 1.1 dholland (void **) &secname, NULL) == 0)
1157 1.1 dholland nfs_sec_name(secname, &args.flags);
1158 1.1 dholland
1159 1.1 dholland if (mp->mnt_flag & MNT_UPDATE) {
1160 1.1 dholland struct nfsmount *nmp = VFSTONFS(mp);
1161 1.1 dholland
1162 1.1 dholland if (nmp == NULL) {
1163 1.1 dholland error = EIO;
1164 1.1 dholland goto out;
1165 1.1 dholland }
1166 1.1 dholland
1167 1.1 dholland /*
1168 1.1 dholland * If a change from TCP->UDP is done and there are thread(s)
1169 1.1.1.2 pgoyette * that have I/O RPC(s) in progress with a transfer size
1170 1.1 dholland * greater than NFS_MAXDGRAMDATA, those thread(s) will be
1171 1.1 dholland * hung, retrying the RPC(s) forever. Usually these threads
1172 1.1 dholland * will be seen doing an uninterruptible sleep on wait channel
1173 1.1.1.2 pgoyette * "nfsreq".
1174 1.1 dholland */
1175 1.1 dholland if (args.sotype == SOCK_DGRAM && nmp->nm_sotype == SOCK_STREAM)
1176 1.1 dholland tprintf(td->td_proc, LOG_WARNING,
1177 1.1 dholland "Warning: mount -u that changes TCP->UDP can result in hung threads\n");
1178 1.1 dholland
1179 1.1 dholland /*
1180 1.1 dholland * When doing an update, we can't change version,
1181 1.1 dholland * security, switch lockd strategies or change cookie
1182 1.1 dholland * translation
1183 1.1 dholland */
1184 1.1 dholland args.flags = (args.flags &
1185 1.1 dholland ~(NFSMNT_NFSV3 |
1186 1.1 dholland NFSMNT_NFSV4 |
1187 1.1 dholland NFSMNT_KERB |
1188 1.1 dholland NFSMNT_INTEGRITY |
1189 1.1 dholland NFSMNT_PRIVACY |
1190 1.1 dholland NFSMNT_NOLOCKD /*|NFSMNT_XLATECOOKIE*/)) |
1191 1.1 dholland (nmp->nm_flag &
1192 1.1 dholland (NFSMNT_NFSV3 |
1193 1.1 dholland NFSMNT_NFSV4 |
1194 1.1 dholland NFSMNT_KERB |
1195 1.1 dholland NFSMNT_INTEGRITY |
1196 1.1 dholland NFSMNT_PRIVACY |
1197 1.1 dholland NFSMNT_NOLOCKD /*|NFSMNT_XLATECOOKIE*/));
1198 1.1 dholland nfs_decode_args(mp, nmp, &args, NULL, td->td_ucred, td);
1199 1.1 dholland goto out;
1200 1.1 dholland }
1201 1.1 dholland
1202 1.1 dholland /*
1203 1.1 dholland * Make the nfs_ip_paranoia sysctl serve as the default connection
1204 1.1 dholland * or no-connection mode for those protocols that support
1205 1.1 dholland * no-connection mode (the flag will be cleared later for protocols
1206 1.1 dholland * that do not support no-connection mode). This will allow a client
1207 1.1 dholland * to receive replies from a different IP then the request was
1208 1.1 dholland * sent to. Note: default value for nfs_ip_paranoia is 1 (paranoid),
1209 1.1 dholland * not 0.
1210 1.1 dholland */
1211 1.1 dholland if (nfs_ip_paranoia == 0)
1212 1.1 dholland args.flags |= NFSMNT_NOCONN;
1213 1.1 dholland
1214 1.1 dholland if (has_nfs_args_opt != 0) {
1215 1.1 dholland /*
1216 1.1 dholland * In the 'nfs_args' case, the pointers in the args
1217 1.1 dholland * structure are in userland - we copy them in here.
1218 1.1 dholland */
1219 1.1 dholland if (args.fhsize < 0 || args.fhsize > NFSX_V3FHMAX) {
1220 1.1 dholland vfs_mount_error(mp, "Bad file handle");
1221 1.1 dholland error = EINVAL;
1222 1.1 dholland goto out;
1223 1.1 dholland }
1224 1.1 dholland error = copyin((caddr_t)args.fh, (caddr_t)nfh,
1225 1.1 dholland args.fhsize);
1226 1.1 dholland if (error != 0)
1227 1.1 dholland goto out;
1228 1.1 dholland error = copyinstr(args.hostname, hst, MNAMELEN - 1, &hstlen);
1229 1.1 dholland if (error != 0)
1230 1.1 dholland goto out;
1231 1.1 dholland bzero(&hst[hstlen], MNAMELEN - hstlen);
1232 1.1 dholland args.hostname = hst;
1233 1.1.1.2 pgoyette /* getsockaddr() call must be after above copyin() calls */
1234 1.1 dholland error = getsockaddr(&nam, (caddr_t)args.addr,
1235 1.1 dholland args.addrlen);
1236 1.1 dholland if (error != 0)
1237 1.1 dholland goto out;
1238 1.1.1.2 pgoyette } else if (nfs_mount_parse_from(mp->mnt_optnew,
1239 1.1.1.2 pgoyette &args.hostname, (struct sockaddr_in **)&nam, dirpath,
1240 1.1.1.2 pgoyette sizeof(dirpath), &dirlen) == 0) {
1241 1.1.1.2 pgoyette has_nfs_from_opt = 1;
1242 1.1.1.2 pgoyette bcopy(args.hostname, hst, MNAMELEN);
1243 1.1.1.2 pgoyette hst[MNAMELEN - 1] = '\0';
1244 1.1.1.2 pgoyette
1245 1.1.1.2 pgoyette /*
1246 1.1.1.2 pgoyette * This only works with NFSv4 for now.
1247 1.1.1.2 pgoyette */
1248 1.1.1.2 pgoyette args.fhsize = 0;
1249 1.1.1.2 pgoyette args.flags |= NFSMNT_NFSV4;
1250 1.1.1.2 pgoyette args.sotype = SOCK_STREAM;
1251 1.1 dholland } else {
1252 1.1 dholland if (vfs_getopt(mp->mnt_optnew, "fh", (void **)&args.fh,
1253 1.1 dholland &args.fhsize) == 0) {
1254 1.1 dholland if (args.fhsize < 0 || args.fhsize > NFSX_FHMAX) {
1255 1.1 dholland vfs_mount_error(mp, "Bad file handle");
1256 1.1 dholland error = EINVAL;
1257 1.1 dholland goto out;
1258 1.1 dholland }
1259 1.1 dholland bcopy(args.fh, nfh, args.fhsize);
1260 1.1 dholland } else {
1261 1.1 dholland args.fhsize = 0;
1262 1.1 dholland }
1263 1.1 dholland (void) vfs_getopt(mp->mnt_optnew, "hostname",
1264 1.1 dholland (void **)&args.hostname, &len);
1265 1.1 dholland if (args.hostname == NULL) {
1266 1.1 dholland vfs_mount_error(mp, "Invalid hostname");
1267 1.1 dholland error = EINVAL;
1268 1.1 dholland goto out;
1269 1.1 dholland }
1270 1.1 dholland bcopy(args.hostname, hst, MNAMELEN);
1271 1.1 dholland hst[MNAMELEN - 1] = '\0';
1272 1.1 dholland }
1273 1.1 dholland
1274 1.1 dholland if (vfs_getopt(mp->mnt_optnew, "principal", (void **)&name, NULL) == 0)
1275 1.1 dholland strlcpy(srvkrbname, name, sizeof (srvkrbname));
1276 1.1.1.2 pgoyette else {
1277 1.1 dholland snprintf(srvkrbname, sizeof (srvkrbname), "nfs@%s", hst);
1278 1.1.1.2 pgoyette cp = strchr(srvkrbname, ':');
1279 1.1.1.2 pgoyette if (cp != NULL)
1280 1.1.1.2 pgoyette *cp = '\0';
1281 1.1.1.2 pgoyette }
1282 1.1 dholland srvkrbnamelen = strlen(srvkrbname);
1283 1.1 dholland
1284 1.1 dholland if (vfs_getopt(mp->mnt_optnew, "gssname", (void **)&name, NULL) == 0)
1285 1.1 dholland strlcpy(krbname, name, sizeof (krbname));
1286 1.1 dholland else
1287 1.1 dholland krbname[0] = '\0';
1288 1.1 dholland krbnamelen = strlen(krbname);
1289 1.1 dholland
1290 1.1.1.2 pgoyette if (has_nfs_from_opt == 0) {
1291 1.1.1.2 pgoyette if (vfs_getopt(mp->mnt_optnew,
1292 1.1.1.2 pgoyette "dirpath", (void **)&name, NULL) == 0)
1293 1.1.1.2 pgoyette strlcpy(dirpath, name, sizeof (dirpath));
1294 1.1.1.2 pgoyette else
1295 1.1.1.2 pgoyette dirpath[0] = '\0';
1296 1.1.1.2 pgoyette dirlen = strlen(dirpath);
1297 1.1.1.2 pgoyette }
1298 1.1 dholland
1299 1.1.1.2 pgoyette if (has_nfs_args_opt == 0 && has_nfs_from_opt == 0) {
1300 1.1 dholland if (vfs_getopt(mp->mnt_optnew, "addr",
1301 1.1 dholland (void **)&args.addr, &args.addrlen) == 0) {
1302 1.1 dholland if (args.addrlen > SOCK_MAXADDRLEN) {
1303 1.1 dholland error = ENAMETOOLONG;
1304 1.1 dholland goto out;
1305 1.1 dholland }
1306 1.1 dholland nam = malloc(args.addrlen, M_SONAME, M_WAITOK);
1307 1.1 dholland bcopy(args.addr, nam, args.addrlen);
1308 1.1 dholland nam->sa_len = args.addrlen;
1309 1.1 dholland } else {
1310 1.1 dholland vfs_mount_error(mp, "No server address");
1311 1.1 dholland error = EINVAL;
1312 1.1 dholland goto out;
1313 1.1 dholland }
1314 1.1 dholland }
1315 1.1 dholland
1316 1.1 dholland args.fh = nfh;
1317 1.1 dholland error = mountnfs(&args, mp, nam, hst, krbname, krbnamelen, dirpath,
1318 1.1 dholland dirlen, srvkrbname, srvkrbnamelen, &vp, td->td_ucred, td,
1319 1.1 dholland nametimeo, negnametimeo, minvers);
1320 1.1 dholland out:
1321 1.1 dholland if (!error) {
1322 1.1 dholland MNT_ILOCK(mp);
1323 1.1.1.2 pgoyette mp->mnt_kern_flag |= MNTK_LOOKUP_SHARED | MNTK_NO_IOPF |
1324 1.1.1.2 pgoyette MNTK_USES_BCACHE;
1325 1.1 dholland MNT_IUNLOCK(mp);
1326 1.1 dholland }
1327 1.1 dholland return (error);
1328 1.1 dholland }
1329 1.1 dholland
1330 1.1 dholland
1331 1.1 dholland /*
1332 1.1 dholland * VFS Operations.
1333 1.1 dholland *
1334 1.1 dholland * mount system call
1335 1.1 dholland * It seems a bit dumb to copyinstr() the host and path here and then
1336 1.1 dholland * bcopy() them in mountnfs(), but I wanted to detect errors before
1337 1.1.1.2 pgoyette * doing the getsockaddr() call because getsockaddr() allocates an mbuf and
1338 1.1 dholland * an error after that means that I have to release the mbuf.
1339 1.1 dholland */
1340 1.1 dholland /* ARGSUSED */
1341 1.1 dholland static int
1342 1.1 dholland nfs_cmount(struct mntarg *ma, void *data, uint64_t flags)
1343 1.1 dholland {
1344 1.1 dholland int error;
1345 1.1 dholland struct nfs_args args;
1346 1.1 dholland
1347 1.1 dholland error = copyin(data, &args, sizeof (struct nfs_args));
1348 1.1 dholland if (error)
1349 1.1 dholland return error;
1350 1.1 dholland
1351 1.1 dholland ma = mount_arg(ma, "nfs_args", &args, sizeof args);
1352 1.1 dholland
1353 1.1 dholland error = kernel_mount(ma, flags);
1354 1.1 dholland return (error);
1355 1.1 dholland }
1356 1.1 dholland
1357 1.1 dholland /*
1358 1.1 dholland * Common code for mount and mountroot
1359 1.1 dholland */
1360 1.1 dholland static int
1361 1.1 dholland mountnfs(struct nfs_args *argp, struct mount *mp, struct sockaddr *nam,
1362 1.1 dholland char *hst, u_char *krbname, int krbnamelen, u_char *dirpath, int dirlen,
1363 1.1 dholland u_char *srvkrbname, int srvkrbnamelen, struct vnode **vpp,
1364 1.1 dholland struct ucred *cred, struct thread *td, int nametimeo, int negnametimeo,
1365 1.1 dholland int minvers)
1366 1.1 dholland {
1367 1.1 dholland struct nfsmount *nmp;
1368 1.1 dholland struct nfsnode *np;
1369 1.1 dholland int error, trycnt, ret;
1370 1.1 dholland struct nfsvattr nfsva;
1371 1.1 dholland struct nfsclclient *clp;
1372 1.1 dholland struct nfsclds *dsp, *tdsp;
1373 1.1 dholland uint32_t lease;
1374 1.1 dholland static u_int64_t clval = 0;
1375 1.1 dholland
1376 1.1 dholland NFSCL_DEBUG(3, "in mnt\n");
1377 1.1 dholland clp = NULL;
1378 1.1 dholland if (mp->mnt_flag & MNT_UPDATE) {
1379 1.1 dholland nmp = VFSTONFS(mp);
1380 1.1 dholland printf("%s: MNT_UPDATE is no longer handled here\n", __func__);
1381 1.1 dholland FREE(nam, M_SONAME);
1382 1.1 dholland return (0);
1383 1.1 dholland } else {
1384 1.1 dholland MALLOC(nmp, struct nfsmount *, sizeof (struct nfsmount) +
1385 1.1 dholland krbnamelen + dirlen + srvkrbnamelen + 2,
1386 1.1 dholland M_NEWNFSMNT, M_WAITOK | M_ZERO);
1387 1.1 dholland TAILQ_INIT(&nmp->nm_bufq);
1388 1.1 dholland if (clval == 0)
1389 1.1 dholland clval = (u_int64_t)nfsboottime.tv_sec;
1390 1.1 dholland nmp->nm_clval = clval++;
1391 1.1 dholland nmp->nm_krbnamelen = krbnamelen;
1392 1.1 dholland nmp->nm_dirpathlen = dirlen;
1393 1.1 dholland nmp->nm_srvkrbnamelen = srvkrbnamelen;
1394 1.1 dholland if (td->td_ucred->cr_uid != (uid_t)0) {
1395 1.1 dholland /*
1396 1.1 dholland * nm_uid is used to get KerberosV credentials for
1397 1.1 dholland * the nfsv4 state handling operations if there is
1398 1.1 dholland * no host based principal set. Use the uid of
1399 1.1 dholland * this user if not root, since they are doing the
1400 1.1 dholland * mount. I don't think setting this for root will
1401 1.1 dholland * work, since root normally does not have user
1402 1.1 dholland * credentials in a credentials cache.
1403 1.1 dholland */
1404 1.1 dholland nmp->nm_uid = td->td_ucred->cr_uid;
1405 1.1 dholland } else {
1406 1.1 dholland /*
1407 1.1 dholland * Just set to -1, so it won't be used.
1408 1.1 dholland */
1409 1.1 dholland nmp->nm_uid = (uid_t)-1;
1410 1.1 dholland }
1411 1.1 dholland
1412 1.1 dholland /* Copy and null terminate all the names */
1413 1.1 dholland if (nmp->nm_krbnamelen > 0) {
1414 1.1 dholland bcopy(krbname, nmp->nm_krbname, nmp->nm_krbnamelen);
1415 1.1 dholland nmp->nm_name[nmp->nm_krbnamelen] = '\0';
1416 1.1 dholland }
1417 1.1 dholland if (nmp->nm_dirpathlen > 0) {
1418 1.1 dholland bcopy(dirpath, NFSMNT_DIRPATH(nmp),
1419 1.1 dholland nmp->nm_dirpathlen);
1420 1.1 dholland nmp->nm_name[nmp->nm_krbnamelen + nmp->nm_dirpathlen
1421 1.1 dholland + 1] = '\0';
1422 1.1 dholland }
1423 1.1 dholland if (nmp->nm_srvkrbnamelen > 0) {
1424 1.1 dholland bcopy(srvkrbname, NFSMNT_SRVKRBNAME(nmp),
1425 1.1 dholland nmp->nm_srvkrbnamelen);
1426 1.1 dholland nmp->nm_name[nmp->nm_krbnamelen + nmp->nm_dirpathlen
1427 1.1 dholland + nmp->nm_srvkrbnamelen + 2] = '\0';
1428 1.1 dholland }
1429 1.1 dholland nmp->nm_sockreq.nr_cred = crhold(cred);
1430 1.1 dholland mtx_init(&nmp->nm_sockreq.nr_mtx, "nfssock", NULL, MTX_DEF);
1431 1.1 dholland mp->mnt_data = nmp;
1432 1.1 dholland nmp->nm_getinfo = nfs_getnlminfo;
1433 1.1 dholland nmp->nm_vinvalbuf = ncl_vinvalbuf;
1434 1.1 dholland }
1435 1.1 dholland vfs_getnewfsid(mp);
1436 1.1 dholland nmp->nm_mountp = mp;
1437 1.1 dholland mtx_init(&nmp->nm_mtx, "NFSmount lock", NULL, MTX_DEF | MTX_DUPOK);
1438 1.1 dholland
1439 1.1 dholland /*
1440 1.1 dholland * Since nfs_decode_args() might optionally set them, these
1441 1.1 dholland * need to be set to defaults before the call, so that the
1442 1.1 dholland * optional settings aren't overwritten.
1443 1.1 dholland */
1444 1.1 dholland nmp->nm_nametimeo = nametimeo;
1445 1.1 dholland nmp->nm_negnametimeo = negnametimeo;
1446 1.1 dholland nmp->nm_timeo = NFS_TIMEO;
1447 1.1 dholland nmp->nm_retry = NFS_RETRANS;
1448 1.1 dholland nmp->nm_readahead = NFS_DEFRAHEAD;
1449 1.1.1.2 pgoyette
1450 1.1.1.2 pgoyette /* This is empirical approximation of sqrt(hibufspace) * 256. */
1451 1.1.1.2 pgoyette nmp->nm_wcommitsize = NFS_MAXBSIZE / 256;
1452 1.1.1.2 pgoyette while ((long)nmp->nm_wcommitsize * nmp->nm_wcommitsize < hibufspace)
1453 1.1.1.2 pgoyette nmp->nm_wcommitsize *= 2;
1454 1.1.1.2 pgoyette nmp->nm_wcommitsize *= 256;
1455 1.1.1.2 pgoyette
1456 1.1 dholland if ((argp->flags & NFSMNT_NFSV4) != 0)
1457 1.1 dholland nmp->nm_minorvers = minvers;
1458 1.1 dholland else
1459 1.1 dholland nmp->nm_minorvers = 0;
1460 1.1 dholland
1461 1.1 dholland nfs_decode_args(mp, nmp, argp, hst, cred, td);
1462 1.1 dholland
1463 1.1 dholland /*
1464 1.1 dholland * V2 can only handle 32 bit filesizes. A 4GB-1 limit may be too
1465 1.1 dholland * high, depending on whether we end up with negative offsets in
1466 1.1 dholland * the client or server somewhere. 2GB-1 may be safer.
1467 1.1 dholland *
1468 1.1 dholland * For V3, ncl_fsinfo will adjust this as necessary. Assume maximum
1469 1.1 dholland * that we can handle until we find out otherwise.
1470 1.1 dholland */
1471 1.1 dholland if ((argp->flags & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0)
1472 1.1 dholland nmp->nm_maxfilesize = 0xffffffffLL;
1473 1.1 dholland else
1474 1.1 dholland nmp->nm_maxfilesize = OFF_MAX;
1475 1.1 dholland
1476 1.1 dholland if ((argp->flags & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0) {
1477 1.1 dholland nmp->nm_wsize = NFS_WSIZE;
1478 1.1 dholland nmp->nm_rsize = NFS_RSIZE;
1479 1.1 dholland nmp->nm_readdirsize = NFS_READDIRSIZE;
1480 1.1 dholland }
1481 1.1 dholland nmp->nm_numgrps = NFS_MAXGRPS;
1482 1.1 dholland nmp->nm_tprintf_delay = nfs_tprintf_delay;
1483 1.1 dholland if (nmp->nm_tprintf_delay < 0)
1484 1.1 dholland nmp->nm_tprintf_delay = 0;
1485 1.1 dholland nmp->nm_tprintf_initial_delay = nfs_tprintf_initial_delay;
1486 1.1 dholland if (nmp->nm_tprintf_initial_delay < 0)
1487 1.1 dholland nmp->nm_tprintf_initial_delay = 0;
1488 1.1 dholland nmp->nm_fhsize = argp->fhsize;
1489 1.1 dholland if (nmp->nm_fhsize > 0)
1490 1.1 dholland bcopy((caddr_t)argp->fh, (caddr_t)nmp->nm_fh, argp->fhsize);
1491 1.1 dholland bcopy(hst, mp->mnt_stat.f_mntfromname, MNAMELEN);
1492 1.1 dholland nmp->nm_nam = nam;
1493 1.1 dholland /* Set up the sockets and per-host congestion */
1494 1.1 dholland nmp->nm_sotype = argp->sotype;
1495 1.1 dholland nmp->nm_soproto = argp->proto;
1496 1.1 dholland nmp->nm_sockreq.nr_prog = NFS_PROG;
1497 1.1 dholland if ((argp->flags & NFSMNT_NFSV4))
1498 1.1 dholland nmp->nm_sockreq.nr_vers = NFS_VER4;
1499 1.1 dholland else if ((argp->flags & NFSMNT_NFSV3))
1500 1.1 dholland nmp->nm_sockreq.nr_vers = NFS_VER3;
1501 1.1 dholland else
1502 1.1 dholland nmp->nm_sockreq.nr_vers = NFS_VER2;
1503 1.1 dholland
1504 1.1 dholland
1505 1.1 dholland if ((error = newnfs_connect(nmp, &nmp->nm_sockreq, cred, td, 0)))
1506 1.1 dholland goto bad;
1507 1.1 dholland /* For NFSv4.1, get the clientid now. */
1508 1.1 dholland if (nmp->nm_minorvers > 0) {
1509 1.1 dholland NFSCL_DEBUG(3, "at getcl\n");
1510 1.1 dholland error = nfscl_getcl(mp, cred, td, 0, &clp);
1511 1.1 dholland NFSCL_DEBUG(3, "aft getcl=%d\n", error);
1512 1.1 dholland if (error != 0)
1513 1.1 dholland goto bad;
1514 1.1 dholland }
1515 1.1 dholland
1516 1.1 dholland if (nmp->nm_fhsize == 0 && (nmp->nm_flag & NFSMNT_NFSV4) &&
1517 1.1 dholland nmp->nm_dirpathlen > 0) {
1518 1.1 dholland NFSCL_DEBUG(3, "in dirp\n");
1519 1.1 dholland /*
1520 1.1 dholland * If the fhsize on the mount point == 0 for V4, the mount
1521 1.1 dholland * path needs to be looked up.
1522 1.1 dholland */
1523 1.1 dholland trycnt = 3;
1524 1.1 dholland do {
1525 1.1 dholland error = nfsrpc_getdirpath(nmp, NFSMNT_DIRPATH(nmp),
1526 1.1 dholland cred, td);
1527 1.1 dholland NFSCL_DEBUG(3, "aft dirp=%d\n", error);
1528 1.1 dholland if (error)
1529 1.1 dholland (void) nfs_catnap(PZERO, error, "nfsgetdirp");
1530 1.1 dholland } while (error && --trycnt > 0);
1531 1.1 dholland if (error) {
1532 1.1 dholland error = nfscl_maperr(td, error, (uid_t)0, (gid_t)0);
1533 1.1 dholland goto bad;
1534 1.1 dholland }
1535 1.1 dholland }
1536 1.1 dholland
1537 1.1 dholland /*
1538 1.1 dholland * A reference count is needed on the nfsnode representing the
1539 1.1 dholland * remote root. If this object is not persistent, then backward
1540 1.1 dholland * traversals of the mount point (i.e. "..") will not work if
1541 1.1 dholland * the nfsnode gets flushed out of the cache. Ufs does not have
1542 1.1 dholland * this problem, because one can identify root inodes by their
1543 1.1 dholland * number == ROOTINO (2).
1544 1.1 dholland */
1545 1.1 dholland if (nmp->nm_fhsize > 0) {
1546 1.1 dholland /*
1547 1.1 dholland * Set f_iosize to NFS_DIRBLKSIZ so that bo_bsize gets set
1548 1.1 dholland * non-zero for the root vnode. f_iosize will be set correctly
1549 1.1 dholland * by nfs_statfs() before any I/O occurs.
1550 1.1 dholland */
1551 1.1 dholland mp->mnt_stat.f_iosize = NFS_DIRBLKSIZ;
1552 1.1 dholland error = ncl_nget(mp, nmp->nm_fh, nmp->nm_fhsize, &np,
1553 1.1 dholland LK_EXCLUSIVE);
1554 1.1 dholland if (error)
1555 1.1 dholland goto bad;
1556 1.1 dholland *vpp = NFSTOV(np);
1557 1.1 dholland
1558 1.1 dholland /*
1559 1.1 dholland * Get file attributes and transfer parameters for the
1560 1.1 dholland * mountpoint. This has the side effect of filling in
1561 1.1 dholland * (*vpp)->v_type with the correct value.
1562 1.1 dholland */
1563 1.1 dholland ret = nfsrpc_getattrnovp(nmp, nmp->nm_fh, nmp->nm_fhsize, 1,
1564 1.1 dholland cred, td, &nfsva, NULL, &lease);
1565 1.1 dholland if (ret) {
1566 1.1 dholland /*
1567 1.1 dholland * Just set default values to get things going.
1568 1.1 dholland */
1569 1.1 dholland NFSBZERO((caddr_t)&nfsva, sizeof (struct nfsvattr));
1570 1.1 dholland nfsva.na_vattr.va_type = VDIR;
1571 1.1 dholland nfsva.na_vattr.va_mode = 0777;
1572 1.1 dholland nfsva.na_vattr.va_nlink = 100;
1573 1.1 dholland nfsva.na_vattr.va_uid = (uid_t)0;
1574 1.1 dholland nfsva.na_vattr.va_gid = (gid_t)0;
1575 1.1 dholland nfsva.na_vattr.va_fileid = 2;
1576 1.1 dholland nfsva.na_vattr.va_gen = 1;
1577 1.1 dholland nfsva.na_vattr.va_blocksize = NFS_FABLKSIZE;
1578 1.1 dholland nfsva.na_vattr.va_size = 512 * 1024;
1579 1.1 dholland lease = 60;
1580 1.1 dholland }
1581 1.1 dholland (void) nfscl_loadattrcache(vpp, &nfsva, NULL, NULL, 0, 1);
1582 1.1 dholland if (nmp->nm_minorvers > 0) {
1583 1.1 dholland NFSCL_DEBUG(3, "lease=%d\n", (int)lease);
1584 1.1 dholland NFSLOCKCLSTATE();
1585 1.1 dholland clp->nfsc_renew = NFSCL_RENEW(lease);
1586 1.1 dholland clp->nfsc_expire = NFSD_MONOSEC + clp->nfsc_renew;
1587 1.1 dholland clp->nfsc_clientidrev++;
1588 1.1 dholland if (clp->nfsc_clientidrev == 0)
1589 1.1 dholland clp->nfsc_clientidrev++;
1590 1.1 dholland NFSUNLOCKCLSTATE();
1591 1.1 dholland /*
1592 1.1 dholland * Mount will succeed, so the renew thread can be
1593 1.1 dholland * started now.
1594 1.1 dholland */
1595 1.1 dholland nfscl_start_renewthread(clp);
1596 1.1 dholland nfscl_clientrelease(clp);
1597 1.1 dholland }
1598 1.1 dholland if (argp->flags & NFSMNT_NFSV3)
1599 1.1 dholland ncl_fsinfo(nmp, *vpp, cred, td);
1600 1.1 dholland
1601 1.1 dholland /* Mark if the mount point supports NFSv4 ACLs. */
1602 1.1 dholland if ((argp->flags & NFSMNT_NFSV4) != 0 && nfsrv_useacl != 0 &&
1603 1.1 dholland ret == 0 &&
1604 1.1 dholland NFSISSET_ATTRBIT(&nfsva.na_suppattr, NFSATTRBIT_ACL)) {
1605 1.1 dholland MNT_ILOCK(mp);
1606 1.1 dholland mp->mnt_flag |= MNT_NFS4ACLS;
1607 1.1 dholland MNT_IUNLOCK(mp);
1608 1.1 dholland }
1609 1.1 dholland
1610 1.1 dholland /*
1611 1.1 dholland * Lose the lock but keep the ref.
1612 1.1 dholland */
1613 1.1 dholland NFSVOPUNLOCK(*vpp, 0);
1614 1.1 dholland return (0);
1615 1.1 dholland }
1616 1.1 dholland error = EIO;
1617 1.1 dholland
1618 1.1 dholland bad:
1619 1.1 dholland if (clp != NULL)
1620 1.1 dholland nfscl_clientrelease(clp);
1621 1.1 dholland newnfs_disconnect(&nmp->nm_sockreq);
1622 1.1 dholland crfree(nmp->nm_sockreq.nr_cred);
1623 1.1 dholland if (nmp->nm_sockreq.nr_auth != NULL)
1624 1.1 dholland AUTH_DESTROY(nmp->nm_sockreq.nr_auth);
1625 1.1 dholland mtx_destroy(&nmp->nm_sockreq.nr_mtx);
1626 1.1 dholland mtx_destroy(&nmp->nm_mtx);
1627 1.1 dholland if (nmp->nm_clp != NULL) {
1628 1.1 dholland NFSLOCKCLSTATE();
1629 1.1 dholland LIST_REMOVE(nmp->nm_clp, nfsc_list);
1630 1.1 dholland NFSUNLOCKCLSTATE();
1631 1.1 dholland free(nmp->nm_clp, M_NFSCLCLIENT);
1632 1.1 dholland }
1633 1.1 dholland TAILQ_FOREACH_SAFE(dsp, &nmp->nm_sess, nfsclds_list, tdsp)
1634 1.1 dholland nfscl_freenfsclds(dsp);
1635 1.1 dholland FREE(nmp, M_NEWNFSMNT);
1636 1.1 dholland FREE(nam, M_SONAME);
1637 1.1 dholland return (error);
1638 1.1 dholland }
1639 1.1 dholland
1640 1.1 dholland /*
1641 1.1 dholland * unmount system call
1642 1.1 dholland */
1643 1.1 dholland static int
1644 1.1 dholland nfs_unmount(struct mount *mp, int mntflags)
1645 1.1 dholland {
1646 1.1 dholland struct thread *td;
1647 1.1 dholland struct nfsmount *nmp;
1648 1.1 dholland int error, flags = 0, i, trycnt = 0;
1649 1.1 dholland struct nfsclds *dsp, *tdsp;
1650 1.1 dholland
1651 1.1 dholland td = curthread;
1652 1.1 dholland
1653 1.1 dholland if (mntflags & MNT_FORCE)
1654 1.1 dholland flags |= FORCECLOSE;
1655 1.1 dholland nmp = VFSTONFS(mp);
1656 1.1 dholland /*
1657 1.1 dholland * Goes something like this..
1658 1.1 dholland * - Call vflush() to clear out vnodes for this filesystem
1659 1.1 dholland * - Close the socket
1660 1.1 dholland * - Free up the data structures
1661 1.1 dholland */
1662 1.1 dholland /* In the forced case, cancel any outstanding requests. */
1663 1.1 dholland if (mntflags & MNT_FORCE) {
1664 1.1 dholland error = newnfs_nmcancelreqs(nmp);
1665 1.1 dholland if (error)
1666 1.1 dholland goto out;
1667 1.1 dholland /* For a forced close, get rid of the renew thread now */
1668 1.1 dholland nfscl_umount(nmp, td);
1669 1.1 dholland }
1670 1.1 dholland /* We hold 1 extra ref on the root vnode; see comment in mountnfs(). */
1671 1.1 dholland do {
1672 1.1 dholland error = vflush(mp, 1, flags, td);
1673 1.1 dholland if ((mntflags & MNT_FORCE) && error != 0 && ++trycnt < 30)
1674 1.1 dholland (void) nfs_catnap(PSOCK, error, "newndm");
1675 1.1 dholland } while ((mntflags & MNT_FORCE) && error != 0 && trycnt < 30);
1676 1.1 dholland if (error)
1677 1.1 dholland goto out;
1678 1.1 dholland
1679 1.1 dholland /*
1680 1.1 dholland * We are now committed to the unmount.
1681 1.1 dholland */
1682 1.1 dholland if ((mntflags & MNT_FORCE) == 0)
1683 1.1 dholland nfscl_umount(nmp, td);
1684 1.1 dholland /* Make sure no nfsiods are assigned to this mount. */
1685 1.1 dholland mtx_lock(&ncl_iod_mutex);
1686 1.1 dholland for (i = 0; i < NFS_MAXASYNCDAEMON; i++)
1687 1.1 dholland if (ncl_iodmount[i] == nmp) {
1688 1.1 dholland ncl_iodwant[i] = NFSIOD_AVAILABLE;
1689 1.1 dholland ncl_iodmount[i] = NULL;
1690 1.1 dholland }
1691 1.1 dholland mtx_unlock(&ncl_iod_mutex);
1692 1.1 dholland newnfs_disconnect(&nmp->nm_sockreq);
1693 1.1 dholland crfree(nmp->nm_sockreq.nr_cred);
1694 1.1 dholland FREE(nmp->nm_nam, M_SONAME);
1695 1.1 dholland if (nmp->nm_sockreq.nr_auth != NULL)
1696 1.1 dholland AUTH_DESTROY(nmp->nm_sockreq.nr_auth);
1697 1.1 dholland mtx_destroy(&nmp->nm_sockreq.nr_mtx);
1698 1.1 dholland mtx_destroy(&nmp->nm_mtx);
1699 1.1 dholland TAILQ_FOREACH_SAFE(dsp, &nmp->nm_sess, nfsclds_list, tdsp)
1700 1.1 dholland nfscl_freenfsclds(dsp);
1701 1.1 dholland FREE(nmp, M_NEWNFSMNT);
1702 1.1 dholland out:
1703 1.1 dholland return (error);
1704 1.1 dholland }
1705 1.1 dholland
1706 1.1 dholland /*
1707 1.1 dholland * Return root of a filesystem
1708 1.1 dholland */
1709 1.1 dholland static int
1710 1.1 dholland nfs_root(struct mount *mp, int flags, struct vnode **vpp)
1711 1.1 dholland {
1712 1.1 dholland struct vnode *vp;
1713 1.1 dholland struct nfsmount *nmp;
1714 1.1 dholland struct nfsnode *np;
1715 1.1 dholland int error;
1716 1.1 dholland
1717 1.1 dholland nmp = VFSTONFS(mp);
1718 1.1 dholland error = ncl_nget(mp, nmp->nm_fh, nmp->nm_fhsize, &np, flags);
1719 1.1 dholland if (error)
1720 1.1 dholland return error;
1721 1.1 dholland vp = NFSTOV(np);
1722 1.1 dholland /*
1723 1.1 dholland * Get transfer parameters and attributes for root vnode once.
1724 1.1 dholland */
1725 1.1 dholland mtx_lock(&nmp->nm_mtx);
1726 1.1 dholland if (NFSHASNFSV3(nmp) && !NFSHASGOTFSINFO(nmp)) {
1727 1.1 dholland mtx_unlock(&nmp->nm_mtx);
1728 1.1 dholland ncl_fsinfo(nmp, vp, curthread->td_ucred, curthread);
1729 1.1 dholland } else
1730 1.1 dholland mtx_unlock(&nmp->nm_mtx);
1731 1.1 dholland if (vp->v_type == VNON)
1732 1.1 dholland vp->v_type = VDIR;
1733 1.1 dholland vp->v_vflag |= VV_ROOT;
1734 1.1 dholland *vpp = vp;
1735 1.1 dholland return (0);
1736 1.1 dholland }
1737 1.1 dholland
1738 1.1 dholland /*
1739 1.1 dholland * Flush out the buffer cache
1740 1.1 dholland */
1741 1.1 dholland /* ARGSUSED */
1742 1.1 dholland static int
1743 1.1 dholland nfs_sync(struct mount *mp, int waitfor)
1744 1.1 dholland {
1745 1.1 dholland struct vnode *vp, *mvp;
1746 1.1 dholland struct thread *td;
1747 1.1 dholland int error, allerror = 0;
1748 1.1 dholland
1749 1.1 dholland td = curthread;
1750 1.1 dholland
1751 1.1 dholland MNT_ILOCK(mp);
1752 1.1 dholland /*
1753 1.1 dholland * If a forced dismount is in progress, return from here so that
1754 1.1 dholland * the umount(2) syscall doesn't get stuck in VFS_SYNC() before
1755 1.1 dholland * calling VFS_UNMOUNT().
1756 1.1 dholland */
1757 1.1 dholland if ((mp->mnt_kern_flag & MNTK_UNMOUNTF) != 0) {
1758 1.1 dholland MNT_IUNLOCK(mp);
1759 1.1 dholland return (EBADF);
1760 1.1 dholland }
1761 1.1 dholland MNT_IUNLOCK(mp);
1762 1.1 dholland
1763 1.1 dholland /*
1764 1.1 dholland * Force stale buffer cache information to be flushed.
1765 1.1 dholland */
1766 1.1 dholland loop:
1767 1.1 dholland MNT_VNODE_FOREACH_ALL(vp, mp, mvp) {
1768 1.1 dholland /* XXX Racy bv_cnt check. */
1769 1.1 dholland if (NFSVOPISLOCKED(vp) || vp->v_bufobj.bo_dirty.bv_cnt == 0 ||
1770 1.1 dholland waitfor == MNT_LAZY) {
1771 1.1 dholland VI_UNLOCK(vp);
1772 1.1 dholland continue;
1773 1.1 dholland }
1774 1.1 dholland if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, td)) {
1775 1.1 dholland MNT_VNODE_FOREACH_ALL_ABORT(mp, mvp);
1776 1.1 dholland goto loop;
1777 1.1 dholland }
1778 1.1 dholland error = VOP_FSYNC(vp, waitfor, td);
1779 1.1 dholland if (error)
1780 1.1 dholland allerror = error;
1781 1.1 dholland NFSVOPUNLOCK(vp, 0);
1782 1.1 dholland vrele(vp);
1783 1.1 dholland }
1784 1.1 dholland return (allerror);
1785 1.1 dholland }
1786 1.1 dholland
1787 1.1 dholland static int
1788 1.1 dholland nfs_sysctl(struct mount *mp, fsctlop_t op, struct sysctl_req *req)
1789 1.1 dholland {
1790 1.1 dholland struct nfsmount *nmp = VFSTONFS(mp);
1791 1.1 dholland struct vfsquery vq;
1792 1.1 dholland int error;
1793 1.1 dholland
1794 1.1 dholland bzero(&vq, sizeof(vq));
1795 1.1 dholland switch (op) {
1796 1.1 dholland #if 0
1797 1.1 dholland case VFS_CTL_NOLOCKS:
1798 1.1 dholland val = (nmp->nm_flag & NFSMNT_NOLOCKS) ? 1 : 0;
1799 1.1 dholland if (req->oldptr != NULL) {
1800 1.1 dholland error = SYSCTL_OUT(req, &val, sizeof(val));
1801 1.1 dholland if (error)
1802 1.1 dholland return (error);
1803 1.1 dholland }
1804 1.1 dholland if (req->newptr != NULL) {
1805 1.1 dholland error = SYSCTL_IN(req, &val, sizeof(val));
1806 1.1 dholland if (error)
1807 1.1 dholland return (error);
1808 1.1 dholland if (val)
1809 1.1 dholland nmp->nm_flag |= NFSMNT_NOLOCKS;
1810 1.1 dholland else
1811 1.1 dholland nmp->nm_flag &= ~NFSMNT_NOLOCKS;
1812 1.1 dholland }
1813 1.1 dholland break;
1814 1.1 dholland #endif
1815 1.1 dholland case VFS_CTL_QUERY:
1816 1.1 dholland mtx_lock(&nmp->nm_mtx);
1817 1.1 dholland if (nmp->nm_state & NFSSTA_TIMEO)
1818 1.1 dholland vq.vq_flags |= VQ_NOTRESP;
1819 1.1 dholland mtx_unlock(&nmp->nm_mtx);
1820 1.1 dholland #if 0
1821 1.1 dholland if (!(nmp->nm_flag & NFSMNT_NOLOCKS) &&
1822 1.1 dholland (nmp->nm_state & NFSSTA_LOCKTIMEO))
1823 1.1 dholland vq.vq_flags |= VQ_NOTRESPLOCK;
1824 1.1 dholland #endif
1825 1.1 dholland error = SYSCTL_OUT(req, &vq, sizeof(vq));
1826 1.1 dholland break;
1827 1.1 dholland case VFS_CTL_TIMEO:
1828 1.1 dholland if (req->oldptr != NULL) {
1829 1.1 dholland error = SYSCTL_OUT(req, &nmp->nm_tprintf_initial_delay,
1830 1.1 dholland sizeof(nmp->nm_tprintf_initial_delay));
1831 1.1 dholland if (error)
1832 1.1 dholland return (error);
1833 1.1 dholland }
1834 1.1 dholland if (req->newptr != NULL) {
1835 1.1 dholland error = vfs_suser(mp, req->td);
1836 1.1 dholland if (error)
1837 1.1 dholland return (error);
1838 1.1 dholland error = SYSCTL_IN(req, &nmp->nm_tprintf_initial_delay,
1839 1.1 dholland sizeof(nmp->nm_tprintf_initial_delay));
1840 1.1 dholland if (error)
1841 1.1 dholland return (error);
1842 1.1 dholland if (nmp->nm_tprintf_initial_delay < 0)
1843 1.1 dholland nmp->nm_tprintf_initial_delay = 0;
1844 1.1 dholland }
1845 1.1 dholland break;
1846 1.1 dholland default:
1847 1.1 dholland return (ENOTSUP);
1848 1.1 dholland }
1849 1.1 dholland return (0);
1850 1.1 dholland }
1851 1.1 dholland
1852 1.1 dholland /*
1853 1.1 dholland * Purge any RPCs in progress, so that they will all return errors.
1854 1.1 dholland * This allows dounmount() to continue as far as VFS_UNMOUNT() for a
1855 1.1 dholland * forced dismount.
1856 1.1 dholland */
1857 1.1 dholland static void
1858 1.1 dholland nfs_purge(struct mount *mp)
1859 1.1 dholland {
1860 1.1 dholland struct nfsmount *nmp = VFSTONFS(mp);
1861 1.1 dholland
1862 1.1 dholland newnfs_nmcancelreqs(nmp);
1863 1.1 dholland }
1864 1.1 dholland
1865 1.1 dholland /*
1866 1.1 dholland * Extract the information needed by the nlm from the nfs vnode.
1867 1.1 dholland */
1868 1.1 dholland static void
1869 1.1 dholland nfs_getnlminfo(struct vnode *vp, uint8_t *fhp, size_t *fhlenp,
1870 1.1 dholland struct sockaddr_storage *sp, int *is_v3p, off_t *sizep,
1871 1.1 dholland struct timeval *timeop)
1872 1.1 dholland {
1873 1.1 dholland struct nfsmount *nmp;
1874 1.1 dholland struct nfsnode *np = VTONFS(vp);
1875 1.1 dholland
1876 1.1 dholland nmp = VFSTONFS(vp->v_mount);
1877 1.1 dholland if (fhlenp != NULL)
1878 1.1 dholland *fhlenp = (size_t)np->n_fhp->nfh_len;
1879 1.1 dholland if (fhp != NULL)
1880 1.1 dholland bcopy(np->n_fhp->nfh_fh, fhp, np->n_fhp->nfh_len);
1881 1.1 dholland if (sp != NULL)
1882 1.1 dholland bcopy(nmp->nm_nam, sp, min(nmp->nm_nam->sa_len, sizeof(*sp)));
1883 1.1 dholland if (is_v3p != NULL)
1884 1.1 dholland *is_v3p = NFS_ISV3(vp);
1885 1.1 dholland if (sizep != NULL)
1886 1.1 dholland *sizep = np->n_size;
1887 1.1 dholland if (timeop != NULL) {
1888 1.1 dholland timeop->tv_sec = nmp->nm_timeo / NFS_HZ;
1889 1.1 dholland timeop->tv_usec = (nmp->nm_timeo % NFS_HZ) * (1000000 / NFS_HZ);
1890 1.1 dholland }
1891 1.1 dholland }
1892 1.1 dholland
1893 1.1 dholland /*
1894 1.1 dholland * This function prints out an option name, based on the conditional
1895 1.1 dholland * argument.
1896 1.1 dholland */
1897 1.1 dholland static __inline void nfscl_printopt(struct nfsmount *nmp, int testval,
1898 1.1 dholland char *opt, char **buf, size_t *blen)
1899 1.1 dholland {
1900 1.1 dholland int len;
1901 1.1 dholland
1902 1.1 dholland if (testval != 0 && *blen > strlen(opt)) {
1903 1.1 dholland len = snprintf(*buf, *blen, "%s", opt);
1904 1.1 dholland if (len != strlen(opt))
1905 1.1 dholland printf("EEK!!\n");
1906 1.1 dholland *buf += len;
1907 1.1 dholland *blen -= len;
1908 1.1 dholland }
1909 1.1 dholland }
1910 1.1 dholland
1911 1.1 dholland /*
1912 1.1 dholland * This function printf out an options integer value.
1913 1.1 dholland */
1914 1.1 dholland static __inline void nfscl_printoptval(struct nfsmount *nmp, int optval,
1915 1.1 dholland char *opt, char **buf, size_t *blen)
1916 1.1 dholland {
1917 1.1 dholland int len;
1918 1.1 dholland
1919 1.1 dholland if (*blen > strlen(opt) + 1) {
1920 1.1 dholland /* Could result in truncated output string. */
1921 1.1 dholland len = snprintf(*buf, *blen, "%s=%d", opt, optval);
1922 1.1 dholland if (len < *blen) {
1923 1.1 dholland *buf += len;
1924 1.1 dholland *blen -= len;
1925 1.1 dholland }
1926 1.1 dholland }
1927 1.1 dholland }
1928 1.1 dholland
1929 1.1 dholland /*
1930 1.1 dholland * Load the option flags and values into the buffer.
1931 1.1 dholland */
1932 1.1 dholland void nfscl_retopts(struct nfsmount *nmp, char *buffer, size_t buflen)
1933 1.1 dholland {
1934 1.1 dholland char *buf;
1935 1.1 dholland size_t blen;
1936 1.1 dholland
1937 1.1 dholland buf = buffer;
1938 1.1 dholland blen = buflen;
1939 1.1 dholland nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NFSV4) != 0, "nfsv4", &buf,
1940 1.1 dholland &blen);
1941 1.1 dholland if ((nmp->nm_flag & NFSMNT_NFSV4) != 0) {
1942 1.1 dholland nfscl_printoptval(nmp, nmp->nm_minorvers, ",minorversion", &buf,
1943 1.1 dholland &blen);
1944 1.1 dholland nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_PNFS) != 0, ",pnfs",
1945 1.1 dholland &buf, &blen);
1946 1.1 dholland }
1947 1.1 dholland nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NFSV3) != 0, "nfsv3", &buf,
1948 1.1 dholland &blen);
1949 1.1 dholland nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0,
1950 1.1 dholland "nfsv2", &buf, &blen);
1951 1.1 dholland nfscl_printopt(nmp, nmp->nm_sotype == SOCK_STREAM, ",tcp", &buf, &blen);
1952 1.1 dholland nfscl_printopt(nmp, nmp->nm_sotype != SOCK_STREAM, ",udp", &buf, &blen);
1953 1.1 dholland nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_RESVPORT) != 0, ",resvport",
1954 1.1 dholland &buf, &blen);
1955 1.1 dholland nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NOCONN) != 0, ",noconn",
1956 1.1 dholland &buf, &blen);
1957 1.1 dholland nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_SOFT) == 0, ",hard", &buf,
1958 1.1 dholland &blen);
1959 1.1 dholland nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_SOFT) != 0, ",soft", &buf,
1960 1.1 dholland &blen);
1961 1.1 dholland nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_INT) != 0, ",intr", &buf,
1962 1.1 dholland &blen);
1963 1.1 dholland nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NOCTO) == 0, ",cto", &buf,
1964 1.1 dholland &blen);
1965 1.1 dholland nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NOCTO) != 0, ",nocto", &buf,
1966 1.1 dholland &blen);
1967 1.1.1.2 pgoyette nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NONCONTIGWR) != 0,
1968 1.1.1.2 pgoyette ",noncontigwr", &buf, &blen);
1969 1.1 dholland nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_NOLOCKD | NFSMNT_NFSV4)) ==
1970 1.1 dholland 0, ",lockd", &buf, &blen);
1971 1.1 dholland nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_NOLOCKD | NFSMNT_NFSV4)) ==
1972 1.1 dholland NFSMNT_NOLOCKD, ",nolockd", &buf, &blen);
1973 1.1 dholland nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_RDIRPLUS) != 0, ",rdirplus",
1974 1.1 dholland &buf, &blen);
1975 1.1 dholland nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_KERB) == 0, ",sec=sys",
1976 1.1 dholland &buf, &blen);
1977 1.1 dholland nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_KERB | NFSMNT_INTEGRITY |
1978 1.1 dholland NFSMNT_PRIVACY)) == NFSMNT_KERB, ",sec=krb5", &buf, &blen);
1979 1.1 dholland nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_KERB | NFSMNT_INTEGRITY |
1980 1.1 dholland NFSMNT_PRIVACY)) == (NFSMNT_KERB | NFSMNT_INTEGRITY), ",sec=krb5i",
1981 1.1 dholland &buf, &blen);
1982 1.1 dholland nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_KERB | NFSMNT_INTEGRITY |
1983 1.1 dholland NFSMNT_PRIVACY)) == (NFSMNT_KERB | NFSMNT_PRIVACY), ",sec=krb5p",
1984 1.1 dholland &buf, &blen);
1985 1.1 dholland nfscl_printoptval(nmp, nmp->nm_acdirmin, ",acdirmin", &buf, &blen);
1986 1.1 dholland nfscl_printoptval(nmp, nmp->nm_acdirmax, ",acdirmax", &buf, &blen);
1987 1.1 dholland nfscl_printoptval(nmp, nmp->nm_acregmin, ",acregmin", &buf, &blen);
1988 1.1 dholland nfscl_printoptval(nmp, nmp->nm_acregmax, ",acregmax", &buf, &blen);
1989 1.1 dholland nfscl_printoptval(nmp, nmp->nm_nametimeo, ",nametimeo", &buf, &blen);
1990 1.1 dholland nfscl_printoptval(nmp, nmp->nm_negnametimeo, ",negnametimeo", &buf,
1991 1.1 dholland &blen);
1992 1.1 dholland nfscl_printoptval(nmp, nmp->nm_rsize, ",rsize", &buf, &blen);
1993 1.1 dholland nfscl_printoptval(nmp, nmp->nm_wsize, ",wsize", &buf, &blen);
1994 1.1 dholland nfscl_printoptval(nmp, nmp->nm_readdirsize, ",readdirsize", &buf,
1995 1.1 dholland &blen);
1996 1.1 dholland nfscl_printoptval(nmp, nmp->nm_readahead, ",readahead", &buf, &blen);
1997 1.1 dholland nfscl_printoptval(nmp, nmp->nm_wcommitsize, ",wcommitsize", &buf,
1998 1.1 dholland &blen);
1999 1.1 dholland nfscl_printoptval(nmp, nmp->nm_timeo, ",timeout", &buf, &blen);
2000 1.1 dholland nfscl_printoptval(nmp, nmp->nm_retry, ",retrans", &buf, &blen);
2001 1.1 dholland }
2002 1.1 dholland
2003