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