2 * SPDX-License-Identifier: BSD-3-Clause
4 * Copyright (c) 1989, 1993
5 * The Regents of the University of California. All rights reserved.
7 * This code is derived from software contributed to Berkeley by
8 * Rick Macklem at The University of Guelph.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 #include <sys/cdefs.h>
37 __FBSDID("$FreeBSD$");
40 * Socket operations for use by the nfs server.
44 #include <fs/nfs/nfsport.h>
46 extern struct nfsstatsv1 nfsstatsv1;
47 extern struct nfsrvfh nfs_pubfh, nfs_rootfh;
48 extern int nfs_pubfhset, nfs_rootfhset;
49 extern struct nfsv4lock nfsv4rootfs_lock;
50 extern struct nfsrv_stablefirst nfsrv_stablefirst;
51 extern struct nfsclienthashhead *nfsclienthash;
52 extern int nfsrv_clienthashsize;
53 extern int nfsrc_floodlevel, nfsrc_tcpsavedreplies;
54 extern int nfsd_debuglevel;
55 extern int nfsrv_layouthighwater;
56 extern volatile int nfsrv_layoutcnt;
60 int (*nfsrv3_procs0[NFS_V3NPROCS])(struct nfsrv_descript *,
61 int, vnode_t , struct nfsexstuff *) = {
62 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
65 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
71 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
72 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
73 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
76 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
77 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
86 int (*nfsrv3_procs1[NFS_V3NPROCS])(struct nfsrv_descript *,
87 int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *) = {
88 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
89 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
90 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
92 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
93 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
94 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
95 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
96 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
100 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
101 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
102 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
103 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
104 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
105 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
106 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
107 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
108 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
109 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
112 int (*nfsrv3_procs2[NFS_V3NPROCS])(struct nfsrv_descript *,
113 int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *) = {
114 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
115 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
116 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
117 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
118 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
119 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
120 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
121 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
122 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
123 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
124 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
125 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
126 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
127 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
130 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
131 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
132 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
133 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
134 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
135 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
138 int (*nfsrv4_ops0[NFSV41_NOPS])(struct nfsrv_descript *,
139 int, vnode_t , struct nfsexstuff *) = {
140 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
141 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
142 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
146 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
151 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
155 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
156 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
158 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
159 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
161 nfsrvd_opendowngrade,
162 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
163 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
164 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
169 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
171 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
172 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
176 nfsrvd_setclientidcfrm,
179 nfsrvd_releaselckown,
183 nfsrvd_createsession,
184 nfsrvd_destroysession,
197 nfsrvd_destroyclientid,
198 nfsrvd_reclaimcomplete,
201 int (*nfsrv4_ops1[NFSV41_NOPS])(struct nfsrv_descript *,
202 int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *) = {
203 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
204 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
205 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
206 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
207 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
208 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
210 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
211 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
212 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
213 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
214 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
215 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
216 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
217 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
220 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
223 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
224 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
225 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
226 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
227 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
228 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
229 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
230 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
231 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
232 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
233 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
234 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
235 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
236 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
237 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
238 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
239 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
240 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
241 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
242 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
243 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
244 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
245 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
246 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
247 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
248 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
249 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
250 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
251 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
252 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
253 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
254 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
255 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
256 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
257 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
258 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
259 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
260 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
261 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
264 int (*nfsrv4_ops2[NFSV41_NOPS])(struct nfsrv_descript *,
265 int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *) = {
266 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
267 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
268 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
269 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
270 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
271 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
272 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
273 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
274 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
275 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
276 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
278 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
279 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
280 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
281 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
282 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
283 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
284 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
285 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
286 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
287 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
288 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
289 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
290 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
291 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
292 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
293 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
294 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
296 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
297 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
298 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
299 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
300 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
301 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
302 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
303 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
304 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
305 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
306 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
307 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
308 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
309 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
310 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
311 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
312 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
313 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
314 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
315 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
316 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
317 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
318 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
319 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
320 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
321 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
322 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
323 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
324 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
326 #endif /* !APPLEKEXT */
329 * Static array that defines which nfs rpc's are nonidempotent
331 static int nfsrv_nonidempotent[NFS_V3NPROCS] = {
357 * This static array indicates whether or not the RPC modifies the
360 int nfsrv_writerpc[NFS_NPROCS] = { 0, 0, 1, 0, 0, 0, 0,
361 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
362 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
364 /* local functions */
365 static void nfsrvd_compound(struct nfsrv_descript *nd, int isdgram,
366 u_char *tag, int taglen, u_int32_t minorvers);
370 * This static array indicates which server procedures require the extra
371 * arguments to return the current file handle for V2, 3.
373 static int nfs_retfh[NFS_V3NPROCS] = { 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1,
374 1, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0 };
376 extern struct nfsv4_opflag nfsv4_opflag[NFSV41_NOPS];
378 static int nfsv3to4op[NFS_V3NPROCS] = {
403 static struct mtx nfsrvd_statmtx;
404 MTX_SYSINIT(nfsst, &nfsrvd_statmtx, "NFSstat", MTX_DEF);
407 nfsrvd_statstart(int op, struct bintime *now)
409 if (op > (NFSV42_NOPS + NFSV4OP_FAKENOPS)) {
410 printf("%s: op %d invalid\n", __func__, op);
414 mtx_lock(&nfsrvd_statmtx);
415 if (nfsstatsv1.srvstartcnt == nfsstatsv1.srvdonecnt) {
417 nfsstatsv1.busyfrom = *now;
419 binuptime(&nfsstatsv1.busyfrom);
422 nfsstatsv1.srvrpccnt[op]++;
423 nfsstatsv1.srvstartcnt++;
424 mtx_unlock(&nfsrvd_statmtx);
429 nfsrvd_statend(int op, uint64_t bytes, struct bintime *now,
430 struct bintime *then)
432 struct bintime dt, lnow;
434 if (op > (NFSV42_NOPS + NFSV4OP_FAKENOPS)) {
435 printf("%s: op %d invalid\n", __func__, op);
444 mtx_lock(&nfsrvd_statmtx);
446 nfsstatsv1.srvbytes[op] += bytes;
447 nfsstatsv1.srvops[op]++;
451 bintime_sub(&dt, then);
452 bintime_add(&nfsstatsv1.srvduration[op], &dt);
456 bintime_sub(&dt, &nfsstatsv1.busyfrom);
457 bintime_add(&nfsstatsv1.busytime, &dt);
458 nfsstatsv1.busyfrom = *now;
460 nfsstatsv1.srvdonecnt++;
462 mtx_unlock(&nfsrvd_statmtx);
466 * Do an RPC. Basically, get the file handles translated to vnode pointers
467 * and then call the appropriate server routine. The server routines are
468 * split into groups, based on whether they use a file handle or file
469 * handle plus name or ...
470 * The NFS V4 Compound RPC is performed separately by nfsrvd_compound().
473 nfsrvd_dorpc(struct nfsrv_descript *nd, int isdgram, u_char *tag, int taglen,
476 int error = 0, lktype;
480 struct nfsexstuff nes;
483 * Get a locked vnode for the first file handle
485 if (!(nd->nd_flag & ND_NFSV4)) {
486 KASSERT(nd->nd_repstat == 0, ("nfsrvd_dorpc"));
488 * For NFSv3, if the malloc/mget allocation is near limits,
489 * return NFSERR_DELAY.
491 if ((nd->nd_flag & ND_NFSV3) && nfsrv_mallocmget_limit()) {
492 nd->nd_repstat = NFSERR_DELAY;
495 error = nfsrv_mtofh(nd, &fh);
497 if (error != EBADRPC)
498 printf("nfs dorpc err1=%d\n", error);
499 nd->nd_repstat = NFSERR_GARBAGE;
502 if (nd->nd_procnum == NFSPROC_READ ||
503 nd->nd_procnum == NFSPROC_WRITE ||
504 nd->nd_procnum == NFSPROC_READDIR ||
505 nd->nd_procnum == NFSPROC_READDIRPLUS ||
506 nd->nd_procnum == NFSPROC_READLINK ||
507 nd->nd_procnum == NFSPROC_GETATTR ||
508 nd->nd_procnum == NFSPROC_ACCESS ||
509 nd->nd_procnum == NFSPROC_FSSTAT ||
510 nd->nd_procnum == NFSPROC_FSINFO)
513 lktype = LK_EXCLUSIVE;
514 if (nd->nd_flag & ND_PUBLOOKUP)
515 nfsd_fhtovp(nd, &nfs_pubfh, lktype, &vp, &nes,
516 &mp, nfsrv_writerpc[nd->nd_procnum]);
518 nfsd_fhtovp(nd, &fh, lktype, &vp, &nes,
519 &mp, nfsrv_writerpc[nd->nd_procnum]);
520 if (nd->nd_repstat == NFSERR_PROGNOTV4)
526 * For V2 and 3, set the ND_SAVEREPLY flag for the recent request
527 * cache, as required.
528 * For V4, nfsrvd_compound() does this.
530 if (!(nd->nd_flag & ND_NFSV4) && nfsrv_nonidempotent[nd->nd_procnum])
531 nd->nd_flag |= ND_SAVEREPLY;
535 * If nd_repstat is non-zero, just fill in the reply status
536 * to complete the RPC reply for V2. Otherwise, you must do
539 if (nd->nd_repstat && (nd->nd_flag & ND_NFSV2)) {
540 *nd->nd_errp = nfsd_errmap(nd);
541 nfsrvd_statstart(nfsv3to4op[nd->nd_procnum], /*now*/ NULL);
542 nfsrvd_statend(nfsv3to4op[nd->nd_procnum], /*bytes*/ 0,
543 /*now*/ NULL, /*then*/ NULL);
544 if (mp != NULL && nfsrv_writerpc[nd->nd_procnum] != 0)
545 vn_finished_write(mp);
550 * Now the procedure can be performed. For V4, nfsrvd_compound()
551 * works through the sub-rpcs, otherwise just call the procedure.
552 * The procedures are in three groups with different arguments.
553 * The group is indicated by the value in nfs_retfh[].
555 if (nd->nd_flag & ND_NFSV4) {
556 nfsrvd_compound(nd, isdgram, tag, taglen, minorvers);
558 struct bintime start_time;
560 binuptime(&start_time);
561 nfsrvd_statstart(nfsv3to4op[nd->nd_procnum], &start_time);
563 if (nfs_retfh[nd->nd_procnum] == 1) {
566 error = (*(nfsrv3_procs1[nd->nd_procnum]))(nd, isdgram,
567 vp, NULL, (fhandle_t *)fh.nfsrvfh_data, &nes);
568 } else if (nfs_retfh[nd->nd_procnum] == 2) {
569 error = (*(nfsrv3_procs2[nd->nd_procnum]))(nd, isdgram,
570 vp, NULL, &nes, NULL);
572 error = (*(nfsrv3_procs0[nd->nd_procnum]))(nd, isdgram,
575 if (mp != NULL && nfsrv_writerpc[nd->nd_procnum] != 0)
576 vn_finished_write(mp);
578 nfsrvd_statend(nfsv3to4op[nd->nd_procnum], /*bytes*/ 0,
579 /*now*/ NULL, /*then*/ &start_time);
582 if (error != EBADRPC)
583 printf("nfs dorpc err2=%d\n", error);
584 nd->nd_repstat = NFSERR_GARBAGE;
586 *nd->nd_errp = nfsd_errmap(nd);
589 * Don't cache certain reply status values.
591 if (nd->nd_repstat && (nd->nd_flag & ND_SAVEREPLY) &&
592 (nd->nd_repstat == NFSERR_GARBAGE ||
593 nd->nd_repstat == NFSERR_BADXDR ||
594 nd->nd_repstat == NFSERR_MOVED ||
595 nd->nd_repstat == NFSERR_DELAY ||
596 nd->nd_repstat == NFSERR_BADSEQID ||
597 nd->nd_repstat == NFSERR_RESOURCE ||
598 nd->nd_repstat == NFSERR_SERVERFAULT ||
599 nd->nd_repstat == NFSERR_STALECLIENTID ||
600 nd->nd_repstat == NFSERR_STALESTATEID ||
601 nd->nd_repstat == NFSERR_OLDSTATEID ||
602 nd->nd_repstat == NFSERR_BADSTATEID ||
603 nd->nd_repstat == NFSERR_GRACE ||
604 nd->nd_repstat == NFSERR_NOGRACE))
605 nd->nd_flag &= ~ND_SAVEREPLY;
612 * Breaks down a compound RPC request and calls the server routines for
614 * Some suboperations are performed directly here to simplify file handle<-->
615 * vnode pointer handling.
618 nfsrvd_compound(struct nfsrv_descript *nd, int isdgram, u_char *tag,
619 int taglen, u_int32_t minorvers)
621 int i, lktype, op, op0 = 0, statsinprog = 0;
623 struct nfsclient *clp, *nclp;
624 int numops, error = 0, igotlock;
625 u_int32_t retops = 0, *retopsp = NULL, *repp;
626 vnode_t vp, nvp, savevp;
628 mount_t new_mp, temp_mp = NULL;
629 struct ucred *credanon;
630 struct nfsexstuff nes, vpnes, savevpnes;
631 fsid_t cur_fsid, save_fsid;
632 static u_int64_t compref = 0;
633 struct bintime start_time;
638 NFSVNO_EXINIT(&vpnes);
639 NFSVNO_EXINIT(&savevpnes);
641 * Put the seq# of the current compound RPC in nfsrv_descript.
642 * (This is used by nfsrv_checkgetattr(), to see if the write
643 * delegation was created by the same compound RPC as the one
644 * with that Getattr in it.)
645 * Don't worry about the 64bit number wrapping around. It ain't
646 * gonna happen before this server gets shut down/rebooted.
648 nd->nd_compref = compref++;
651 * Check for and optionally get a lock on the root. This lock means that
652 * no nfsd will be fiddling with the V4 file system and state stuff. It
653 * is required when the V4 root is being changed, the stable storage
654 * restart file is being updated, or callbacks are being done.
655 * When any of the nfsd are processing an NFSv4 compound RPC, they must
656 * either hold a reference count (nfs_usecnt) or the lock. When
657 * nfsrv_unlock() is called to release the lock, it can optionally
658 * also get a reference count, which saves the need for a call to
659 * nfsrv_getref() after nfsrv_unlock().
662 * First, check to see if we need to wait for an update lock.
665 NFSLOCKV4ROOTMUTEX();
666 if (nfsrv_stablefirst.nsf_flags & NFSNSF_NEEDLOCK)
667 igotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL,
668 NFSV4ROOTLOCKMUTEXPTR, NULL);
670 igotlock = nfsv4_lock(&nfsv4rootfs_lock, 0, NULL,
671 NFSV4ROOTLOCKMUTEXPTR, NULL);
672 NFSUNLOCKV4ROOTMUTEX();
675 * If I got the lock, I can update the stable storage file.
676 * Done when the grace period is over or a client has long
679 nfsrv_stablefirst.nsf_flags &= ~NFSNSF_NEEDLOCK;
680 if ((nfsrv_stablefirst.nsf_flags &
681 (NFSNSF_GRACEOVER | NFSNSF_UPDATEDONE)) == NFSNSF_GRACEOVER)
682 nfsrv_updatestable(p);
685 * If at least one client has long since expired, search
686 * the client list for them, write a REVOKE record on the
687 * stable storage file and then remove them from the client
690 if (nfsrv_stablefirst.nsf_flags & NFSNSF_EXPIREDCLIENT) {
691 nfsrv_stablefirst.nsf_flags &= ~NFSNSF_EXPIREDCLIENT;
692 for (i = 0; i < nfsrv_clienthashsize; i++) {
693 LIST_FOREACH_SAFE(clp, &nfsclienthash[i], lc_hash,
695 if (clp->lc_flags & LCL_EXPIREIT) {
696 if (!LIST_EMPTY(&clp->lc_open) ||
697 !LIST_EMPTY(&clp->lc_deleg))
698 nfsrv_writestable(clp->lc_id,
699 clp->lc_idlen, NFSNST_REVOKE, p);
700 nfsrv_cleanclient(clp, p);
701 nfsrv_freedeleglist(&clp->lc_deleg);
702 nfsrv_freedeleglist(&clp->lc_olddeleg);
703 LIST_REMOVE(clp, lc_hash);
704 nfsrv_zapclient(clp, p);
709 NFSLOCKV4ROOTMUTEX();
710 nfsv4_unlock(&nfsv4rootfs_lock, 1);
711 NFSUNLOCKV4ROOTMUTEX();
714 * If we didn't get the lock, we need to get a refcnt,
715 * which also checks for and waits for the lock.
717 NFSLOCKV4ROOTMUTEX();
718 nfsv4_getref(&nfsv4rootfs_lock, NULL,
719 NFSV4ROOTLOCKMUTEXPTR, NULL);
720 NFSUNLOCKV4ROOTMUTEX();
724 * If flagged, search for open owners that haven't had any opens
727 if (nfsrv_stablefirst.nsf_flags & NFSNSF_NOOPENS) {
728 nfsrv_throwawayopens(p);
731 /* Do a CBLAYOUTRECALL callback if over the high water mark. */
732 if (nfsrv_layoutcnt > nfsrv_layouthighwater)
733 nfsrv_recalloldlayout(p);
736 save_fsid.val[0] = save_fsid.val[1] = 0;
737 cur_fsid.val[0] = cur_fsid.val[1] = 0;
739 /* If taglen < 0, there was a parsing error in nfsd_getminorvers(). */
745 (void) nfsm_strtom(nd, tag, taglen);
746 NFSM_BUILD(retopsp, u_int32_t *, NFSX_UNSIGNED);
747 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
748 if (minorvers != NFSV4_MINORVERSION && minorvers != NFSV41_MINORVERSION)
749 nd->nd_repstat = NFSERR_MINORVERMISMATCH;
753 numops = fxdr_unsigned(int, *tl);
755 * Loop around doing the sub ops.
756 * vp - is an unlocked vnode pointer for the CFH
757 * savevp - is an unlocked vnode pointer for the SAVEDFH
758 * (at some future date, it might turn out to be more appropriate
759 * to keep the file handles instead of vnode pointers?)
760 * savevpnes and vpnes - are the export flags for the above.
762 for (i = 0; i < numops; i++) {
763 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
764 NFSM_BUILD(repp, u_int32_t *, 2 * NFSX_UNSIGNED);
766 op = fxdr_unsigned(int, *tl);
767 NFSD_DEBUG(4, "op=%d\n", op);
768 if (op < NFSV4OP_ACCESS ||
769 (op >= NFSV4OP_NOPS && (nd->nd_flag & ND_NFSV41) == 0) ||
770 (op >= NFSV41_NOPS && (nd->nd_flag & ND_NFSV41) != 0)) {
771 nd->nd_repstat = NFSERR_OPILLEGAL;
772 *repp++ = txdr_unsigned(NFSV4OP_OPILLEGAL);
773 *repp = nfsd_errmap(nd);
780 binuptime(&start_time);
781 nfsrvd_statstart(op, &start_time);
787 nd->nd_flag |= ND_LASTOP;
790 * Check for a referral on the current FH and, if so, return
791 * NFSERR_MOVED for all ops that allow it, except Getattr.
793 if (vp != NULL && op != NFSV4OP_GETATTR &&
794 nfsv4root_getreferral(vp, NULL, 0) != NULL &&
795 nfsrv_errmoved(op)) {
796 nd->nd_repstat = NFSERR_MOVED;
797 *repp = nfsd_errmap(nd);
803 * For NFSv4.1, check for a Sequence Operation being first
804 * or one of the other allowed operations by itself.
806 if ((nd->nd_flag & ND_NFSV41) != 0) {
807 if (i != 0 && op == NFSV4OP_SEQUENCE)
808 nd->nd_repstat = NFSERR_SEQUENCEPOS;
809 else if (i == 0 && op != NFSV4OP_SEQUENCE &&
810 op != NFSV4OP_EXCHANGEID &&
811 op != NFSV4OP_CREATESESSION &&
812 op != NFSV4OP_BINDCONNTOSESS &&
813 op != NFSV4OP_DESTROYCLIENTID &&
814 op != NFSV4OP_DESTROYSESSION)
815 nd->nd_repstat = NFSERR_OPNOTINSESS;
816 else if (i != 0 && op0 != NFSV4OP_SEQUENCE)
817 nd->nd_repstat = NFSERR_NOTONLYOP;
818 if (nd->nd_repstat != 0) {
819 *repp = nfsd_errmap(nd);
827 * If over flood level, reply NFSERR_RESOURCE, if at the first
828 * Op. (Since a client recovery from NFSERR_RESOURCE can get
829 * really nasty for certain Op sequences, I'll play it safe
830 * and only return the error at the beginning.) The cache
831 * will still function over flood level, but uses lots of
833 * If nfsrv_mallocmget_limit() returns True, the system is near
834 * to its limit for memory that malloc()/mget() can allocate.
836 if (i == 0 && (nd->nd_rp == NULL ||
837 nd->nd_rp->rc_refcnt == 0) &&
838 (nfsrv_mallocmget_limit() ||
839 nfsrc_tcpsavedreplies > nfsrc_floodlevel)) {
840 if (nfsrc_tcpsavedreplies > nfsrc_floodlevel)
841 printf("nfsd server cache flooded, try "
842 "increasing vfs.nfsd.tcphighwater\n");
843 nd->nd_repstat = NFSERR_RESOURCE;
844 *repp = nfsd_errmap(nd);
845 if (op == NFSV4OP_SETATTR) {
847 * Setattr replies require a bitmap.
848 * even for errors like these.
850 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
856 if (nfsv4_opflag[op].savereply)
857 nd->nd_flag |= ND_SAVEREPLY;
860 error = nfsrv_mtofh(nd, &fh);
864 nfsd_fhtovp(nd, &fh, LK_SHARED, &nvp, &nes,
866 /* For now, allow this for non-export FHs */
867 if (!nd->nd_repstat) {
871 cur_fsid = vp->v_mount->mnt_stat.f_fsid;
876 case NFSV4OP_PUTPUBFH:
878 nfsd_fhtovp(nd, &nfs_pubfh, LK_SHARED, &nvp,
881 nd->nd_repstat = NFSERR_NOFILEHANDLE;
882 if (!nd->nd_repstat) {
886 cur_fsid = vp->v_mount->mnt_stat.f_fsid;
891 case NFSV4OP_PUTROOTFH:
893 nfsd_fhtovp(nd, &nfs_rootfh, LK_SHARED, &nvp,
895 if (!nd->nd_repstat) {
899 cur_fsid = vp->v_mount->mnt_stat.f_fsid;
904 nd->nd_repstat = NFSERR_NOFILEHANDLE;
907 if (vp && NFSVNO_EXPORTED(&vpnes)) {
909 /* If vp == savevp, a no-op */
916 save_fsid = cur_fsid;
918 if ((nd->nd_flag & ND_CURSTATEID) != 0) {
919 nd->nd_savedcurstateid =
921 nd->nd_flag |= ND_SAVEDCURSTATEID;
924 nd->nd_repstat = NFSERR_NOFILEHANDLE;
927 case NFSV4OP_RESTOREFH:
930 /* If vp == savevp, a no-op */
936 cur_fsid = save_fsid;
938 if ((nd->nd_flag & ND_SAVEDCURSTATEID) != 0) {
940 nd->nd_savedcurstateid;
941 nd->nd_flag |= ND_CURSTATEID;
944 nd->nd_repstat = NFSERR_RESTOREFH;
949 * Allow a Lookup, Getattr, GetFH, Secinfo on an
950 * non-exported directory if
951 * nfs_rootfhset. Do I need to allow any other Ops?
952 * (You can only have a non-exported vpnes if
953 * nfs_rootfhset is true. See nfsd_fhtovp())
954 * Allow AUTH_SYS to be used for file systems
955 * exported GSS only for certain Ops, to allow
956 * clients to do mounts more easily.
958 if (nfsv4_opflag[op].needscfh && vp) {
959 if (!NFSVNO_EXPORTED(&vpnes) &&
960 op != NFSV4OP_LOOKUP &&
961 op != NFSV4OP_GETATTR &&
962 op != NFSV4OP_GETFH &&
963 op != NFSV4OP_ACCESS &&
964 op != NFSV4OP_READLINK &&
965 op != NFSV4OP_SECINFO)
966 nd->nd_repstat = NFSERR_NOFILEHANDLE;
967 else if (nfsvno_testexp(nd, &vpnes) &&
968 op != NFSV4OP_LOOKUP &&
969 op != NFSV4OP_GETFH &&
970 op != NFSV4OP_GETATTR &&
971 op != NFSV4OP_SECINFO)
972 nd->nd_repstat = NFSERR_WRONGSEC;
973 if (nd->nd_repstat) {
974 if (op == NFSV4OP_SETATTR) {
976 * Setattr reply requires a bitmap
977 * even for errors like these.
979 NFSM_BUILD(tl, u_int32_t *,
986 if (nfsv4_opflag[op].retfh == 1) {
988 nd->nd_repstat = NFSERR_NOFILEHANDLE;
992 if (nfsv4_opflag[op].modifyfs)
993 vn_start_write(vp, &temp_mp, V_WAIT);
994 error = (*(nfsrv4_ops1[op]))(nd, isdgram, vp,
995 &nvp, (fhandle_t *)fh.nfsrvfh_data, &vpnes);
996 if (!error && !nd->nd_repstat) {
997 if (op == NFSV4OP_LOOKUP || op == NFSV4OP_LOOKUPP) {
998 new_mp = nvp->v_mount;
999 if (cur_fsid.val[0] !=
1000 new_mp->mnt_stat.f_fsid.val[0] ||
1002 new_mp->mnt_stat.f_fsid.val[1]) {
1003 /* crossed a server mount point */
1004 nd->nd_repstat = nfsvno_checkexp(new_mp,
1005 nd->nd_nam, &nes, &credanon);
1006 if (!nd->nd_repstat)
1007 nd->nd_repstat = nfsd_excred(nd,
1009 if (credanon != NULL)
1011 if (!nd->nd_repstat) {
1013 cur_fsid = new_mp->mnt_stat.f_fsid;
1016 /* Lookup ops return a locked vnode */
1017 NFSVOPUNLOCK(nvp, 0);
1019 if (!nd->nd_repstat) {
1025 if (nfsv4_opflag[op].modifyfs)
1026 vn_finished_write(temp_mp);
1027 } else if (nfsv4_opflag[op].retfh == 2) {
1028 if (vp == NULL || savevp == NULL) {
1029 nd->nd_repstat = NFSERR_NOFILEHANDLE;
1031 } else if (cur_fsid.val[0] != save_fsid.val[0] ||
1032 cur_fsid.val[1] != save_fsid.val[1]) {
1033 nd->nd_repstat = NFSERR_XDEV;
1036 if (nfsv4_opflag[op].modifyfs)
1037 vn_start_write(savevp, &temp_mp, V_WAIT);
1038 if (NFSVOPLOCK(savevp, LK_EXCLUSIVE) == 0) {
1041 error = (*(nfsrv4_ops2[op]))(nd, isdgram,
1042 savevp, vp, &savevpnes, &vpnes);
1044 nd->nd_repstat = NFSERR_PERM;
1045 if (nfsv4_opflag[op].modifyfs)
1046 vn_finished_write(temp_mp);
1048 if (nfsv4_opflag[op].retfh != 0)
1049 panic("nfsrvd_compound");
1050 if (nfsv4_opflag[op].needscfh) {
1052 lktype = nfsv4_opflag[op].lktype;
1053 if (nfsv4_opflag[op].modifyfs) {
1054 vn_start_write(vp, &temp_mp,
1056 if (op == NFSV4OP_WRITE &&
1057 MNT_SHARED_WRITES(temp_mp))
1060 if (NFSVOPLOCK(vp, lktype) == 0)
1063 nd->nd_repstat = NFSERR_PERM;
1065 nd->nd_repstat = NFSERR_NOFILEHANDLE;
1066 if (op == NFSV4OP_SETATTR) {
1068 * Setattr reply requires a
1069 * bitmap even for errors like
1072 NFSM_BUILD(tl, u_int32_t *,
1078 if (nd->nd_repstat == 0)
1079 error = (*(nfsrv4_ops0[op]))(nd,
1080 isdgram, vp, &vpnes);
1081 if (nfsv4_opflag[op].modifyfs)
1082 vn_finished_write(temp_mp);
1084 error = (*(nfsrv4_ops0[op]))(nd, isdgram,
1090 if (error == EBADRPC || error == NFSERR_BADXDR) {
1091 nd->nd_repstat = NFSERR_BADXDR;
1093 nd->nd_repstat = error;
1094 printf("nfsv4 comperr0=%d\n", error);
1099 if (statsinprog != 0) {
1100 nfsrvd_statend(op, /*bytes*/ 0, /*now*/ NULL,
1101 /*then*/ &start_time);
1106 if (nd->nd_repstat) {
1107 *repp = nfsd_errmap(nd);
1110 *repp = 0; /* NFS4_OK */
1114 if (statsinprog != 0) {
1115 nfsrvd_statend(op, /*bytes*/ 0, /*now*/ NULL,
1116 /*then*/ &start_time);
1120 if (error == EBADRPC || error == NFSERR_BADXDR)
1121 nd->nd_repstat = NFSERR_BADXDR;
1123 printf("nfsv4 comperr1=%d\n", error);
1126 NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
1130 *retopsp = txdr_unsigned(retops);
1136 NFSLOCKV4ROOTMUTEX();
1137 nfsv4_relref(&nfsv4rootfs_lock);
1138 NFSUNLOCKV4ROOTMUTEX();
1140 NFSEXITCODE2(0, nd);