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