1 /*-
2 * SPDX-License-Identifier: BSD-3-Clause
3 *
4 * Copyright (c) 1989, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Rick Macklem at The University of Guelph.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
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.
21 *
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
32 * SUCH DAMAGE.
33 *
34 */
35
36 #include <sys/cdefs.h>
37 /*
38 * Socket operations for use by the nfs server.
39 */
40
41 #include <fs/nfs/nfsport.h>
42
43 extern struct nfsrvfh nfs_pubfh;
44 extern int nfs_pubfhset;
45 extern struct nfsv4lock nfsv4rootfs_lock;
46 extern int nfsrv_clienthashsize;
47 extern int nfsd_debuglevel;
48 extern int nfsrv_layouthighwater;
49 extern volatile int nfsrv_layoutcnt;
50 NFSV4ROOTLOCKMUTEX;
51 NFSSTATESPINLOCK;
52
53 NFSD_VNET_DECLARE(struct nfsrv_stablefirst, nfsrv_stablefirst);
54 NFSD_VNET_DECLARE(struct nfsclienthashhead *, nfsclienthash);
55 NFSD_VNET_DECLARE(int, nfsrc_floodlevel);
56 NFSD_VNET_DECLARE(int, nfsrc_tcpsavedreplies);
57 NFSD_VNET_DECLARE(struct nfsrvfh, nfs_rootfh);
58 NFSD_VNET_DECLARE(int, nfs_rootfhset);
59 NFSD_VNET_DECLARE(struct nfsstatsv1 *, nfsstatsv1_p);
60
61 int (*nfsrv3_procs0[NFS_V3NPROCS])(struct nfsrv_descript *,
62 int, vnode_t , struct nfsexstuff *) = {
63 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
64 nfsrvd_getattr,
65 nfsrvd_setattr,
66 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
67 nfsrvd_access,
68 nfsrvd_readlink,
69 nfsrvd_read,
70 nfsrvd_write,
71 nfsrvd_create,
72 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
73 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
74 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
75 nfsrvd_remove,
76 nfsrvd_remove,
77 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
78 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
79 nfsrvd_readdir,
80 nfsrvd_readdirplus,
81 nfsrvd_statfs,
82 nfsrvd_fsinfo,
83 nfsrvd_pathconf,
84 nfsrvd_commit,
85 };
86
87 int (*nfsrv3_procs1[NFS_V3NPROCS])(struct nfsrv_descript *,
88 int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *) = {
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,
91 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
92 nfsrvd_lookup,
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,
97 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
98 nfsrvd_mkdir,
99 nfsrvd_symlink,
100 nfsrvd_mknod,
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,
110 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
111 };
112
113 int (*nfsrv3_procs2[NFS_V3NPROCS])(struct nfsrv_descript *,
114 int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *) = {
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,
128 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
129 nfsrvd_rename,
130 nfsrvd_link,
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,
136 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
137 };
138
139 int (*nfsrv4_ops0[NFSV42_NOPS])(struct nfsrv_descript *,
140 int, vnode_t , struct nfsexstuff *) = {
141 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
142 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
143 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
144 nfsrvd_access,
145 nfsrvd_close,
146 nfsrvd_commit,
147 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
148 nfsrvd_delegpurge,
149 nfsrvd_delegreturn,
150 nfsrvd_getattr,
151 nfsrvd_getfh,
152 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
153 nfsrvd_lock,
154 nfsrvd_lockt,
155 nfsrvd_locku,
156 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
157 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
158 nfsrvd_verify,
159 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
160 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
161 nfsrvd_openconfirm,
162 nfsrvd_opendowngrade,
163 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
164 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
165 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
166 nfsrvd_read,
167 nfsrvd_readdirplus,
168 nfsrvd_readlink,
169 nfsrvd_remove,
170 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
171 nfsrvd_renew,
172 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
173 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
174 nfsrvd_secinfo,
175 nfsrvd_setattr,
176 nfsrvd_setclientid,
177 nfsrvd_setclientidcfrm,
178 nfsrvd_verify,
179 nfsrvd_write,
180 nfsrvd_releaselckown,
181 nfsrvd_notsupp,
182 nfsrvd_bindconnsess,
183 nfsrvd_exchangeid,
184 nfsrvd_createsession,
185 nfsrvd_destroysession,
186 nfsrvd_freestateid,
187 nfsrvd_notsupp,
188 nfsrvd_getdevinfo,
189 nfsrvd_notsupp,
190 nfsrvd_layoutcommit,
191 nfsrvd_layoutget,
192 nfsrvd_layoutreturn,
193 nfsrvd_secinfononame,
194 nfsrvd_sequence,
195 nfsrvd_notsupp,
196 nfsrvd_teststateid,
197 nfsrvd_notsupp,
198 nfsrvd_destroyclientid,
199 nfsrvd_reclaimcomplete,
200 nfsrvd_allocate,
201 (int (*)(struct nfsrv_descript *, int, vnode_t , struct nfsexstuff *))0,
202 nfsrvd_notsupp,
203 nfsrvd_notsupp,
204 nfsrvd_ioadvise,
205 nfsrvd_layouterror,
206 nfsrvd_layoutstats,
207 nfsrvd_notsupp,
208 nfsrvd_notsupp,
209 nfsrvd_notsupp,
210 nfsrvd_seek,
211 nfsrvd_notsupp,
212 nfsrvd_notsupp,
213 nfsrvd_getxattr,
214 nfsrvd_setxattr,
215 nfsrvd_listxattr,
216 nfsrvd_rmxattr,
217 };
218
219 int (*nfsrv4_ops1[NFSV42_NOPS])(struct nfsrv_descript *,
220 int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *) = {
221 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
222 (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 nfsrvd_mknod,
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 nfsrvd_lookup,
237 nfsrvd_lookup,
238 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
239 nfsrvd_open,
240 nfsrvd_openattr,
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,
262 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
263 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
264 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
265 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
266 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
267 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
268 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
269 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
270 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
271 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
272 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
273 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
274 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
275 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
276 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
277 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
278 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
279 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
280 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
281 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
282 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
283 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
284 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
285 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
286 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
287 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
288 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
289 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
290 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
291 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
292 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
293 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
294 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
295 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
296 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t *, fhandle_t *, struct nfsexstuff *))0,
297 };
298
299 int (*nfsrv4_ops2[NFSV42_NOPS])(struct nfsrv_descript *,
300 int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *) = {
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 nfsrvd_link,
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,
325 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
326 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
327 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
328 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
329 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
330 nfsrvd_rename,
331 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
332 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
333 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
334 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
335 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
336 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
337 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
338 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
339 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
340 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
341 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
342 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
343 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
344 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
345 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
346 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
347 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
348 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
349 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
350 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
351 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
352 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
353 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
354 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
355 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
356 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
357 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
358 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
359 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
360 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
361 nfsrvd_copy_file_range,
362 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
363 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
364 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
365 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
366 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
367 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
368 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
369 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
370 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
371 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
372 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
373 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
374 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
375 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
376 (int (*)(struct nfsrv_descript *, int, vnode_t , vnode_t , struct nfsexstuff *, struct nfsexstuff *))0,
377 };
378
379 /*
380 * Static array that defines which nfs rpc's are nonidempotent
381 */
382 static int nfsrv_nonidempotent[NFS_V3NPROCS] = {
383 FALSE,
384 FALSE,
385 TRUE,
386 FALSE,
387 FALSE,
388 FALSE,
389 FALSE,
390 TRUE,
391 TRUE,
392 TRUE,
393 TRUE,
394 TRUE,
395 TRUE,
396 TRUE,
397 TRUE,
398 TRUE,
399 FALSE,
400 FALSE,
401 FALSE,
402 FALSE,
403 FALSE,
404 FALSE,
405 };
406
407 /*
408 * This static array indicates whether or not the RPC modifies the
409 * file system.
410 */
411 int nfsrv_writerpc[NFS_NPROCS] = { 0, 0, 1, 0, 0, 0, 0,
412 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
413 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
414
415 SYSCTL_DECL(_vfs_nfsd);
416 static int nfs_minminorv4 = NFSV4_MINORVERSION;
417 SYSCTL_INT(_vfs_nfsd, OID_AUTO, server_min_minorversion4, CTLFLAG_RWTUN,
418 &nfs_minminorv4, 0,
419 "The lowest minor version of NFSv4 handled by the server");
420
421 static int nfs_maxminorv4 = NFSV42_MINORVERSION;
422 SYSCTL_INT(_vfs_nfsd, OID_AUTO, server_max_minorversion4, CTLFLAG_RWTUN,
423 &nfs_maxminorv4, 0,
424 "The highest minor version of NFSv4 handled by the server");
425
426 /* local functions */
427 static void nfsrvd_compound(struct nfsrv_descript *nd, int isdgram,
428 u_char *tag, int taglen, u_int32_t minorvers);
429
430 /*
431 * This static array indicates which server procedures require the extra
432 * arguments to return the current file handle for V2, 3.
433 */
434 static int nfs_retfh[NFS_V3NPROCS] = { 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1,
435 1, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0 };
436
437 extern struct nfsv4_opflag nfsv4_opflag[NFSV42_NOPS];
438
439 static int nfsv3to4op[NFS_V3NPROCS] = {
440 NFSPROC_NULL,
441 NFSV4OP_GETATTR,
442 NFSV4OP_SETATTR,
443 NFSV4OP_LOOKUP,
444 NFSV4OP_ACCESS,
445 NFSV4OP_READLINK,
446 NFSV4OP_READ,
447 NFSV4OP_WRITE,
448 NFSV4OP_V3CREATE,
449 NFSV4OP_MKDIR,
450 NFSV4OP_SYMLINK,
451 NFSV4OP_MKNOD,
452 NFSV4OP_REMOVE,
453 NFSV4OP_RMDIR,
454 NFSV4OP_RENAME,
455 NFSV4OP_LINK,
456 NFSV4OP_READDIR,
457 NFSV4OP_READDIRPLUS,
458 NFSV4OP_FSSTAT,
459 NFSV4OP_FSINFO,
460 NFSV4OP_PATHCONF,
461 NFSV4OP_COMMIT,
462 };
463
464 static struct mtx nfsrvd_statmtx;
465 MTX_SYSINIT(nfsst, &nfsrvd_statmtx, "NFSstat", MTX_DEF);
466
467 static void
nfsrvd_statstart(int op,struct bintime * now)468 nfsrvd_statstart(int op, struct bintime *now)
469 {
470 if (op > (NFSV42_NOPS + NFSV4OP_FAKENOPS)) {
471 printf("%s: op %d invalid\n", __func__, op);
472 return;
473 }
474
475 mtx_lock(&nfsrvd_statmtx);
476 if (NFSD_VNET(nfsstatsv1_p)->srvstartcnt ==
477 NFSD_VNET(nfsstatsv1_p)->srvdonecnt) {
478 if (now != NULL)
479 NFSD_VNET(nfsstatsv1_p)->busyfrom = *now;
480 else
481 binuptime(&NFSD_VNET(nfsstatsv1_p)->busyfrom);
482
483 }
484 NFSD_VNET(nfsstatsv1_p)->srvrpccnt[op]++;
485 NFSD_VNET(nfsstatsv1_p)->srvstartcnt++;
486 mtx_unlock(&nfsrvd_statmtx);
487
488 }
489
490 static void
nfsrvd_statend(int op,uint64_t bytes,struct bintime * now,struct bintime * then)491 nfsrvd_statend(int op, uint64_t bytes, struct bintime *now,
492 struct bintime *then)
493 {
494 struct bintime dt, lnow;
495
496 if (op > (NFSV42_NOPS + NFSV4OP_FAKENOPS)) {
497 printf("%s: op %d invalid\n", __func__, op);
498 return;
499 }
500
501 if (now == NULL) {
502 now = &lnow;
503 binuptime(now);
504 }
505
506 mtx_lock(&nfsrvd_statmtx);
507
508 NFSD_VNET(nfsstatsv1_p)->srvbytes[op] += bytes;
509 NFSD_VNET(nfsstatsv1_p)->srvops[op]++;
510
511 if (then != NULL) {
512 dt = *now;
513 bintime_sub(&dt, then);
514 bintime_add(&NFSD_VNET(nfsstatsv1_p)->srvduration[op], &dt);
515 }
516
517 dt = *now;
518 bintime_sub(&dt, &NFSD_VNET(nfsstatsv1_p)->busyfrom);
519 bintime_add(&NFSD_VNET(nfsstatsv1_p)->busytime, &dt);
520 NFSD_VNET(nfsstatsv1_p)->busyfrom = *now;
521
522 NFSD_VNET(nfsstatsv1_p)->srvdonecnt++;
523
524 mtx_unlock(&nfsrvd_statmtx);
525 }
526
527 /*
528 * Do an RPC. Basically, get the file handles translated to vnode pointers
529 * and then call the appropriate server routine. The server routines are
530 * split into groups, based on whether they use a file handle or file
531 * handle plus name or ...
532 * The NFS V4 Compound RPC is performed separately by nfsrvd_compound().
533 */
534 void
nfsrvd_dorpc(struct nfsrv_descript * nd,int isdgram,u_char * tag,int taglen,u_int32_t minorvers)535 nfsrvd_dorpc(struct nfsrv_descript *nd, int isdgram, u_char *tag, int taglen,
536 u_int32_t minorvers)
537 {
538 int error = 0, lktype;
539 vnode_t vp;
540 mount_t mp;
541 struct nfsrvfh fh;
542 struct nfsexstuff nes;
543 struct mbuf *md;
544 char *dpos;
545
546 /*
547 * Save the current position in the request mbuf list so
548 * that a rollback to this location can be done upon an
549 * ERELOOKUP error return from an RPC function.
550 */
551 md = nd->nd_md;
552 dpos = nd->nd_dpos;
553 tryagain:
554 mp = NULL;
555
556 /*
557 * Get a locked vnode for the first file handle
558 */
559 if (!(nd->nd_flag & ND_NFSV4)) {
560 KASSERT(nd->nd_repstat == 0, ("nfsrvd_dorpc"));
561 /*
562 * For NFSv3, if the malloc/mget allocation is near limits,
563 * return NFSERR_DELAY.
564 */
565 if ((nd->nd_flag & ND_NFSV3) && nfsrv_mallocmget_limit()) {
566 nd->nd_repstat = NFSERR_DELAY;
567 vp = NULL;
568 } else {
569 error = nfsrv_mtofh(nd, &fh);
570 if (error) {
571 if (error != EBADRPC)
572 printf("nfs dorpc err1=%d\n", error);
573 nd->nd_repstat = NFSERR_GARBAGE;
574 goto out;
575 }
576 if (nd->nd_procnum == NFSPROC_READ ||
577 nd->nd_procnum == NFSPROC_WRITE ||
578 nd->nd_procnum == NFSPROC_READDIR ||
579 nd->nd_procnum == NFSPROC_READDIRPLUS ||
580 nd->nd_procnum == NFSPROC_READLINK ||
581 nd->nd_procnum == NFSPROC_GETATTR ||
582 nd->nd_procnum == NFSPROC_ACCESS ||
583 nd->nd_procnum == NFSPROC_FSSTAT ||
584 nd->nd_procnum == NFSPROC_FSINFO)
585 lktype = LK_SHARED;
586 else
587 lktype = LK_EXCLUSIVE;
588 if (nd->nd_flag & ND_PUBLOOKUP)
589 nfsd_fhtovp(nd, &nfs_pubfh, lktype, &vp, &nes,
590 &mp, nfsrv_writerpc[nd->nd_procnum], -1);
591 else
592 nfsd_fhtovp(nd, &fh, lktype, &vp, &nes,
593 &mp, nfsrv_writerpc[nd->nd_procnum], -1);
594 if (nd->nd_repstat == NFSERR_PROGNOTV4)
595 goto out;
596 }
597 }
598
599 /*
600 * For V2 and 3, set the ND_SAVEREPLY flag for the recent request
601 * cache, as required.
602 * For V4, nfsrvd_compound() does this.
603 */
604 if (!(nd->nd_flag & ND_NFSV4) && nfsrv_nonidempotent[nd->nd_procnum])
605 nd->nd_flag |= ND_SAVEREPLY;
606
607 nfsrvd_rephead(nd);
608 /*
609 * If nd_repstat is non-zero, just fill in the reply status
610 * to complete the RPC reply for V2. Otherwise, you must do
611 * the RPC.
612 */
613 if (nd->nd_repstat && (nd->nd_flag & ND_NFSV2)) {
614 *nd->nd_errp = nfsd_errmap(nd);
615 nfsrvd_statstart(nfsv3to4op[nd->nd_procnum], /*now*/ NULL);
616 nfsrvd_statend(nfsv3to4op[nd->nd_procnum], /*bytes*/ 0,
617 /*now*/ NULL, /*then*/ NULL);
618 vn_finished_write(mp);
619 goto out;
620 }
621
622 /*
623 * Now the procedure can be performed. For V4, nfsrvd_compound()
624 * works through the sub-rpcs, otherwise just call the procedure.
625 * The procedures are in three groups with different arguments.
626 * The group is indicated by the value in nfs_retfh[].
627 */
628 if (nd->nd_flag & ND_NFSV4) {
629 nfsrvd_compound(nd, isdgram, tag, taglen, minorvers);
630 } else {
631 struct bintime start_time;
632
633 binuptime(&start_time);
634 nfsrvd_statstart(nfsv3to4op[nd->nd_procnum], &start_time);
635
636 if (nfs_retfh[nd->nd_procnum] == 1) {
637 if (vp)
638 NFSVOPUNLOCK(vp);
639 error = (*(nfsrv3_procs1[nd->nd_procnum]))(nd, isdgram,
640 vp, NULL, (fhandle_t *)fh.nfsrvfh_data, &nes);
641 } else if (nfs_retfh[nd->nd_procnum] == 2) {
642 error = (*(nfsrv3_procs2[nd->nd_procnum]))(nd, isdgram,
643 vp, NULL, &nes, NULL);
644 } else {
645 error = (*(nfsrv3_procs0[nd->nd_procnum]))(nd, isdgram,
646 vp, &nes);
647 }
648 vn_finished_write(mp);
649
650 if (error == 0 && nd->nd_repstat == ERELOOKUP) {
651 /*
652 * Roll back to the beginning of the RPC request
653 * arguments.
654 */
655 nd->nd_md = md;
656 nd->nd_dpos = dpos;
657
658 /* Free the junk RPC reply and redo the RPC. */
659 m_freem(nd->nd_mreq);
660 nd->nd_mreq = nd->nd_mb = NULL;
661 nd->nd_repstat = 0;
662 goto tryagain;
663 }
664
665 nfsrvd_statend(nfsv3to4op[nd->nd_procnum], /*bytes*/ 0,
666 /*now*/ NULL, /*then*/ &start_time);
667 }
668 if (error) {
669 if (error != EBADRPC)
670 printf("nfs dorpc err2=%d\n", error);
671 nd->nd_repstat = NFSERR_GARBAGE;
672 }
673 *nd->nd_errp = nfsd_errmap(nd);
674
675 /*
676 * Don't cache certain reply status values.
677 */
678 if (nd->nd_repstat && (nd->nd_flag & ND_SAVEREPLY) &&
679 (nd->nd_repstat == NFSERR_GARBAGE ||
680 nd->nd_repstat == NFSERR_BADXDR ||
681 nd->nd_repstat == NFSERR_MOVED ||
682 nd->nd_repstat == NFSERR_DELAY ||
683 nd->nd_repstat == NFSERR_BADSEQID ||
684 nd->nd_repstat == NFSERR_RESOURCE ||
685 nd->nd_repstat == NFSERR_SERVERFAULT ||
686 nd->nd_repstat == NFSERR_STALECLIENTID ||
687 nd->nd_repstat == NFSERR_STALESTATEID ||
688 nd->nd_repstat == NFSERR_OLDSTATEID ||
689 nd->nd_repstat == NFSERR_BADSTATEID ||
690 nd->nd_repstat == NFSERR_GRACE ||
691 nd->nd_repstat == NFSERR_NOGRACE))
692 nd->nd_flag &= ~ND_SAVEREPLY;
693
694 out:
695 NFSEXITCODE2(0, nd);
696 }
697
698 /*
699 * Breaks down a compound RPC request and calls the server routines for
700 * the subprocedures.
701 * Some suboperations are performed directly here to simplify file handle<-->
702 * vnode pointer handling.
703 */
704 static void
nfsrvd_compound(struct nfsrv_descript * nd,int isdgram,u_char * tag,int taglen,u_int32_t minorvers)705 nfsrvd_compound(struct nfsrv_descript *nd, int isdgram, u_char *tag,
706 int taglen, u_int32_t minorvers)
707 {
708 int i, lktype, op, op0 = 0, rstat, statsinprog = 0;
709 u_int32_t *tl;
710 struct nfsclient *clp, *nclp;
711 int error = 0, igotlock, nextop, numops, savefhcnt;
712 u_int32_t retops = 0, *retopsp = NULL, *repp;
713 vnode_t vp, nvp, savevp;
714 struct nfsrvfh fh;
715 mount_t new_mp, temp_mp = NULL;
716 struct ucred *credanon;
717 struct nfsexstuff nes, vpnes, savevpnes;
718 fsid_t cur_fsid, save_fsid;
719 static u_int64_t compref = 0;
720 struct bintime start_time;
721 struct thread *p;
722 struct mbuf *mb, *md;
723 char *bpos, *dpos;
724 int bextpg, bextpgsiz;
725
726 p = curthread;
727
728 /* Check for and optionally clear the no space flags for DSs. */
729 nfsrv_checknospc();
730
731 NFSVNO_EXINIT(&vpnes);
732 NFSVNO_EXINIT(&savevpnes);
733 /*
734 * Put the seq# of the current compound RPC in nfsrv_descript.
735 * (This is used by nfsrv_checkgetattr(), to see if the write
736 * delegation was created by the same compound RPC as the one
737 * with that Getattr in it.)
738 * Don't worry about the 64bit number wrapping around. It ain't
739 * gonna happen before this server gets shut down/rebooted.
740 */
741 nd->nd_compref = compref++;
742
743 /*
744 * Check for and optionally get a lock on the root. This lock means that
745 * no nfsd will be fiddling with the V4 file system and state stuff. It
746 * is required when the V4 root is being changed, the stable storage
747 * restart file is being updated, or callbacks are being done.
748 * When any of the nfsd are processing an NFSv4 compound RPC, they must
749 * either hold a reference count (nfs_usecnt) or the lock. When
750 * nfsrv_unlock() is called to release the lock, it can optionally
751 * also get a reference count, which saves the need for a call to
752 * nfsrv_getref() after nfsrv_unlock().
753 */
754 /*
755 * First, check to see if we need to wait for an update lock.
756 */
757 igotlock = 0;
758 NFSLOCKV4ROOTMUTEX();
759 if (NFSD_VNET(nfsrv_stablefirst).nsf_flags & NFSNSF_NEEDLOCK)
760 igotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL,
761 NFSV4ROOTLOCKMUTEXPTR, NULL);
762 else
763 igotlock = nfsv4_lock(&nfsv4rootfs_lock, 0, NULL,
764 NFSV4ROOTLOCKMUTEXPTR, NULL);
765 NFSUNLOCKV4ROOTMUTEX();
766 if (igotlock) {
767 /*
768 * If I got the lock, I can update the stable storage file.
769 * Done when the grace period is over or a client has long
770 * since expired.
771 */
772 NFSD_VNET(nfsrv_stablefirst).nsf_flags &= ~NFSNSF_NEEDLOCK;
773 if ((NFSD_VNET(nfsrv_stablefirst).nsf_flags &
774 (NFSNSF_GRACEOVER | NFSNSF_UPDATEDONE)) == NFSNSF_GRACEOVER)
775 nfsrv_updatestable(p);
776
777 /*
778 * If at least one client has long since expired, search
779 * the client list for them, write a REVOKE record on the
780 * stable storage file and then remove them from the client
781 * list.
782 */
783 if (NFSD_VNET(nfsrv_stablefirst).nsf_flags &
784 NFSNSF_EXPIREDCLIENT) {
785 NFSD_VNET(nfsrv_stablefirst).nsf_flags &=
786 ~NFSNSF_EXPIREDCLIENT;
787 for (i = 0; i < nfsrv_clienthashsize; i++) {
788 LIST_FOREACH_SAFE(clp, &NFSD_VNET(nfsclienthash)[i],
789 lc_hash, nclp) {
790 if (clp->lc_flags & LCL_EXPIREIT) {
791 if (!LIST_EMPTY(&clp->lc_open) ||
792 !LIST_EMPTY(&clp->lc_deleg))
793 nfsrv_writestable(clp->lc_id,
794 clp->lc_idlen, NFSNST_REVOKE, p);
795 nfsrv_cleanclient(clp, p, false, NULL);
796 nfsrv_freedeleglist(&clp->lc_deleg);
797 nfsrv_freedeleglist(&clp->lc_olddeleg);
798 LIST_REMOVE(clp, lc_hash);
799 nfsrv_zapclient(clp, p);
800 }
801 }
802 }
803 }
804 NFSLOCKV4ROOTMUTEX();
805 nfsv4_unlock(&nfsv4rootfs_lock, 1);
806 NFSUNLOCKV4ROOTMUTEX();
807 } else {
808 /*
809 * If we didn't get the lock, we need to get a refcnt,
810 * which also checks for and waits for the lock.
811 */
812 NFSLOCKV4ROOTMUTEX();
813 nfsv4_getref(&nfsv4rootfs_lock, NULL,
814 NFSV4ROOTLOCKMUTEXPTR, NULL);
815 NFSUNLOCKV4ROOTMUTEX();
816 }
817
818 /*
819 * If flagged, search for open owners that haven't had any opens
820 * for a long time.
821 */
822 if (NFSD_VNET(nfsrv_stablefirst).nsf_flags & NFSNSF_NOOPENS) {
823 nfsrv_throwawayopens(p);
824 }
825
826 /* Do a CBLAYOUTRECALL callback if over the high water mark. */
827 if (nfsrv_layoutcnt > nfsrv_layouthighwater)
828 nfsrv_recalloldlayout(p);
829
830 savevp = vp = NULL;
831 save_fsid.val[0] = save_fsid.val[1] = 0;
832 cur_fsid.val[0] = cur_fsid.val[1] = 0;
833 nextop = -1;
834 savefhcnt = 0;
835
836 /* If taglen < 0, there was a parsing error in nfsd_getminorvers(). */
837 if (taglen < 0) {
838 error = EBADRPC;
839 goto nfsmout;
840 }
841
842 (void) nfsm_strtom(nd, tag, taglen);
843 NFSM_BUILD(retopsp, u_int32_t *, NFSX_UNSIGNED);
844 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
845 if ((minorvers != NFSV4_MINORVERSION &&
846 minorvers != NFSV41_MINORVERSION &&
847 minorvers != NFSV42_MINORVERSION) ||
848 minorvers < nfs_minminorv4 || minorvers > nfs_maxminorv4)
849 nd->nd_repstat = NFSERR_MINORVERMISMATCH;
850 if (nd->nd_repstat)
851 numops = 0;
852 else
853 numops = fxdr_unsigned(int, *tl);
854 /*
855 * Loop around doing the sub ops.
856 * vp - is an unlocked vnode pointer for the CFH
857 * savevp - is an unlocked vnode pointer for the SAVEDFH
858 * (at some future date, it might turn out to be more appropriate
859 * to keep the file handles instead of vnode pointers?)
860 * savevpnes and vpnes - are the export flags for the above.
861 */
862 for (i = 0; i < numops; i++) {
863 NFSM_BUILD(repp, u_int32_t *, 2 * NFSX_UNSIGNED);
864 if (savefhcnt > 0) {
865 op = NFSV4OP_SAVEFH;
866 *repp = txdr_unsigned(op);
867 savefhcnt--;
868 } else if (nextop == -1) {
869 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
870 *repp = *tl;
871 op = fxdr_unsigned(int, *tl);
872 } else {
873 op = nextop;
874 *repp = txdr_unsigned(op);
875 nextop = -1;
876 }
877 NFSD_DEBUG(4, "op=%d\n", op);
878 if (op < NFSV4OP_ACCESS || op >= NFSV42_NOPS ||
879 (op >= NFSV4OP_NOPS && (nd->nd_flag & ND_NFSV41) == 0) ||
880 (op >= NFSV41_NOPS && (nd->nd_flag & ND_NFSV42) == 0)) {
881 nd->nd_repstat = NFSERR_OPILLEGAL;
882 *repp++ = txdr_unsigned(NFSV4OP_OPILLEGAL);
883 *repp = nfsd_errmap(nd);
884 retops++;
885 break;
886 } else {
887 repp++;
888 }
889
890 binuptime(&start_time);
891 nfsrvd_statstart(op, &start_time);
892 statsinprog = 1;
893
894 if (i == 0)
895 op0 = op;
896 if (i == numops - 1)
897 nd->nd_flag |= ND_LASTOP;
898
899 /*
900 * Check for a referral on the current FH and, if so, return
901 * NFSERR_MOVED for all ops that allow it, except Getattr.
902 */
903 if (vp != NULL && op != NFSV4OP_GETATTR &&
904 nfsv4root_getreferral(vp, NULL, 0) != NULL &&
905 nfsrv_errmoved(op)) {
906 nd->nd_repstat = NFSERR_MOVED;
907 *repp = nfsd_errmap(nd);
908 retops++;
909 break;
910 }
911
912 /*
913 * For NFSv4.1, check for a Sequence Operation being first
914 * or one of the other allowed operations by itself.
915 */
916 if ((nd->nd_flag & ND_NFSV41) != 0) {
917 if (i != 0 && op == NFSV4OP_SEQUENCE)
918 nd->nd_repstat = NFSERR_SEQUENCEPOS;
919 else if (i == 0 && op != NFSV4OP_SEQUENCE &&
920 op != NFSV4OP_EXCHANGEID &&
921 op != NFSV4OP_CREATESESSION &&
922 op != NFSV4OP_BINDCONNTOSESS &&
923 op != NFSV4OP_DESTROYCLIENTID &&
924 op != NFSV4OP_DESTROYSESSION)
925 nd->nd_repstat = NFSERR_OPNOTINSESS;
926 else if (i != 0 && op0 != NFSV4OP_SEQUENCE)
927 nd->nd_repstat = NFSERR_NOTONLYOP;
928 if (nd->nd_repstat != 0) {
929 *repp = nfsd_errmap(nd);
930 retops++;
931 break;
932 }
933 }
934
935 nd->nd_procnum = op;
936 /*
937 * If over flood level, reply NFSERR_RESOURCE, if at the first
938 * Op. (Since a client recovery from NFSERR_RESOURCE can get
939 * really nasty for certain Op sequences, I'll play it safe
940 * and only return the error at the beginning.) The cache
941 * will still function over flood level, but uses lots of
942 * mbufs.)
943 * If nfsrv_mallocmget_limit() returns True, the system is near
944 * to its limit for memory that malloc()/mget() can allocate.
945 */
946 if (i == 0 && (nd->nd_rp == NULL ||
947 nd->nd_rp->rc_refcnt == 0) &&
948 (nfsrv_mallocmget_limit() ||
949 NFSD_VNET(nfsrc_tcpsavedreplies) >
950 NFSD_VNET(nfsrc_floodlevel))) {
951 if (NFSD_VNET(nfsrc_tcpsavedreplies) >
952 NFSD_VNET(nfsrc_floodlevel))
953 printf("nfsd server cache flooded, try "
954 "increasing vfs.nfsd.tcphighwater\n");
955 nd->nd_repstat = NFSERR_RESOURCE;
956 *repp = nfsd_errmap(nd);
957 if (op == NFSV4OP_SETATTR) {
958 /*
959 * Setattr replies require a bitmap.
960 * even for errors like these.
961 */
962 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
963 *tl = 0;
964 }
965 retops++;
966 break;
967 }
968 if (nfsv4_opflag[op].savereply)
969 nd->nd_flag |= ND_SAVEREPLY;
970 switch (op) {
971 case NFSV4OP_PUTFH:
972 error = nfsrv_mtofh(nd, &fh);
973 if (error)
974 goto nfsmout;
975 if ((nd->nd_flag & ND_LASTOP) == 0) {
976 /*
977 * Pre-parse the next op#. If it is
978 * SaveFH, count it and skip to the
979 * next op#, if not the last op#.
980 * nextop is used to determine if
981 * NFSERR_WRONGSEC can be returned,
982 * per RFC5661 Sec. 2.6.
983 */
984 do {
985 NFSM_DISSECT(tl, uint32_t *,
986 NFSX_UNSIGNED);
987 nextop = fxdr_unsigned(int, *tl);
988 if (nextop == NFSV4OP_SAVEFH &&
989 i < numops - 1)
990 savefhcnt++;
991 } while (nextop == NFSV4OP_SAVEFH &&
992 i < numops - 1);
993 }
994 if (!nd->nd_repstat)
995 nfsd_fhtovp(nd, &fh, LK_SHARED, &nvp, &nes,
996 NULL, 0, nextop);
997 /* For now, allow this for non-export FHs */
998 if (!nd->nd_repstat) {
999 if (vp)
1000 vrele(vp);
1001 vp = nvp;
1002 cur_fsid = vp->v_mount->mnt_stat.f_fsid;
1003 NFSVOPUNLOCK(vp);
1004 vpnes = nes;
1005 }
1006 break;
1007 case NFSV4OP_PUTPUBFH:
1008 if (nfs_pubfhset) {
1009 if ((nd->nd_flag & ND_LASTOP) == 0) {
1010 /*
1011 * Pre-parse the next op#. If it is
1012 * SaveFH, count it and skip to the
1013 * next op#, if not the last op#.
1014 * nextop is used to determine if
1015 * NFSERR_WRONGSEC can be returned,
1016 * per RFC5661 Sec. 2.6.
1017 */
1018 do {
1019 NFSM_DISSECT(tl, uint32_t *,
1020 NFSX_UNSIGNED);
1021 nextop = fxdr_unsigned(int,
1022 *tl);
1023 if (nextop == NFSV4OP_SAVEFH &&
1024 i < numops - 1)
1025 savefhcnt++;
1026 } while (nextop == NFSV4OP_SAVEFH &&
1027 i < numops - 1);
1028 }
1029 nfsd_fhtovp(nd, &nfs_pubfh, LK_SHARED, &nvp,
1030 &nes, NULL, 0, nextop);
1031 } else
1032 nd->nd_repstat = NFSERR_NOFILEHANDLE;
1033 if (!nd->nd_repstat) {
1034 if (vp)
1035 vrele(vp);
1036 vp = nvp;
1037 cur_fsid = vp->v_mount->mnt_stat.f_fsid;
1038 NFSVOPUNLOCK(vp);
1039 vpnes = nes;
1040 }
1041 break;
1042 case NFSV4OP_PUTROOTFH:
1043 if (NFSD_VNET(nfs_rootfhset)) {
1044 if ((nd->nd_flag & ND_LASTOP) == 0) {
1045 /*
1046 * Pre-parse the next op#. If it is
1047 * SaveFH, count it and skip to the
1048 * next op#, if not the last op#.
1049 * nextop is used to determine if
1050 * NFSERR_WRONGSEC can be returned,
1051 * per RFC5661 Sec. 2.6.
1052 */
1053 do {
1054 NFSM_DISSECT(tl, uint32_t *,
1055 NFSX_UNSIGNED);
1056 nextop = fxdr_unsigned(int,
1057 *tl);
1058 if (nextop == NFSV4OP_SAVEFH &&
1059 i < numops - 1)
1060 savefhcnt++;
1061 } while (nextop == NFSV4OP_SAVEFH &&
1062 i < numops - 1);
1063 }
1064 nfsd_fhtovp(nd, &NFSD_VNET(nfs_rootfh),
1065 LK_SHARED, &nvp, &nes, NULL, 0, nextop);
1066 if (!nd->nd_repstat) {
1067 if (vp)
1068 vrele(vp);
1069 vp = nvp;
1070 cur_fsid = vp->v_mount->mnt_stat.f_fsid;
1071 NFSVOPUNLOCK(vp);
1072 vpnes = nes;
1073 }
1074 } else
1075 nd->nd_repstat = NFSERR_NOFILEHANDLE;
1076 break;
1077 case NFSV4OP_SAVEFH:
1078 if (vp && NFSVNO_EXPORTED(&vpnes)) {
1079 nd->nd_repstat = 0;
1080 /* If vp == savevp, a no-op */
1081 if (vp != savevp) {
1082 if (savevp)
1083 vrele(savevp);
1084 VREF(vp);
1085 savevp = vp;
1086 savevpnes = vpnes;
1087 save_fsid = cur_fsid;
1088 }
1089 if ((nd->nd_flag & ND_CURSTATEID) != 0) {
1090 nd->nd_savedcurstateid =
1091 nd->nd_curstateid;
1092 nd->nd_flag |= ND_SAVEDCURSTATEID;
1093 }
1094 } else {
1095 nd->nd_repstat = NFSERR_NOFILEHANDLE;
1096 }
1097 break;
1098 case NFSV4OP_RESTOREFH:
1099 if (savevp) {
1100 if ((nd->nd_flag & ND_LASTOP) == 0) {
1101 /*
1102 * Pre-parse the next op#. If it is
1103 * SaveFH, count it and skip to the
1104 * next op#, if not the last op#.
1105 * nextop is used to determine if
1106 * NFSERR_WRONGSEC can be returned,
1107 * per RFC5661 Sec. 2.6.
1108 */
1109 do {
1110 NFSM_DISSECT(tl, uint32_t *,
1111 NFSX_UNSIGNED);
1112 nextop = fxdr_unsigned(int,
1113 *tl);
1114 if (nextop == NFSV4OP_SAVEFH &&
1115 i < numops - 1)
1116 savefhcnt++;
1117 } while (nextop == NFSV4OP_SAVEFH &&
1118 i < numops - 1);
1119 }
1120 nd->nd_repstat = 0;
1121 /* If vp == savevp, a no-op */
1122 if (vp != savevp) {
1123 if (nfsrv_checkwrongsec(nd, nextop,
1124 savevp->v_type))
1125 nd->nd_repstat =
1126 nfsvno_testexp(nd,
1127 &savevpnes);
1128 if (nd->nd_repstat == 0) {
1129 VREF(savevp);
1130 vrele(vp);
1131 vp = savevp;
1132 vpnes = savevpnes;
1133 cur_fsid = save_fsid;
1134 }
1135 }
1136 if (nd->nd_repstat == 0 &&
1137 (nd->nd_flag & ND_SAVEDCURSTATEID) != 0) {
1138 nd->nd_curstateid =
1139 nd->nd_savedcurstateid;
1140 nd->nd_flag |= ND_CURSTATEID;
1141 }
1142 } else {
1143 nd->nd_repstat = NFSERR_RESTOREFH;
1144 }
1145 break;
1146 default:
1147 /*
1148 * Allow a Lookup, Getattr, GetFH, Secinfo on an
1149 * non-exported directory if
1150 * nfs_rootfhset. Do I need to allow any other Ops?
1151 * (You can only have a non-exported vpnes if
1152 * nfs_rootfhset is true. See nfsd_fhtovp())
1153 * Allow AUTH_SYS to be used for file systems
1154 * exported GSS only for certain Ops, to allow
1155 * clients to do mounts more easily.
1156 */
1157 if (nfsv4_opflag[op].needscfh && vp) {
1158 if (!NFSVNO_EXPORTED(&vpnes) &&
1159 op != NFSV4OP_LOOKUP &&
1160 op != NFSV4OP_GETATTR &&
1161 op != NFSV4OP_GETFH &&
1162 op != NFSV4OP_ACCESS &&
1163 op != NFSV4OP_READLINK &&
1164 op != NFSV4OP_SECINFO &&
1165 op != NFSV4OP_SECINFONONAME)
1166 nd->nd_repstat = NFSERR_NOFILEHANDLE;
1167 if (nd->nd_repstat) {
1168 if (op == NFSV4OP_SETATTR) {
1169 /*
1170 * Setattr reply requires a bitmap
1171 * even for errors like these.
1172 */
1173 NFSM_BUILD(tl, u_int32_t *,
1174 NFSX_UNSIGNED);
1175 *tl = 0;
1176 }
1177 break;
1178 }
1179 }
1180
1181 /*
1182 * Save the current positions in the mbuf lists so
1183 * that a rollback to this location can be done upon a
1184 * redo due to a ERELOOKUP return for a operation.
1185 */
1186 mb = nd->nd_mb;
1187 bpos = nd->nd_bpos;
1188 bextpg = nd->nd_bextpg;
1189 bextpgsiz = nd->nd_bextpgsiz;
1190 md = nd->nd_md;
1191 dpos = nd->nd_dpos;
1192 tryagain:
1193
1194 if (nfsv4_opflag[op].retfh == 1) {
1195 if (!vp) {
1196 nd->nd_repstat = NFSERR_NOFILEHANDLE;
1197 break;
1198 }
1199 if (NFSVNO_EXPORTED(&vpnes) && (op == NFSV4OP_LOOKUP ||
1200 op == NFSV4OP_LOOKUPP || (op == NFSV4OP_OPEN &&
1201 vp->v_type == VDIR))) {
1202 /* Check for wrong security. */
1203 rstat = nfsvno_testexp(nd, &vpnes);
1204 if (rstat != 0) {
1205 nd->nd_repstat = rstat;
1206 break;
1207 }
1208 }
1209 VREF(vp);
1210 if (nfsv4_opflag[op].modifyfs)
1211 vn_start_write(vp, &temp_mp, V_WAIT);
1212 error = (*(nfsrv4_ops1[op]))(nd, isdgram, vp,
1213 &nvp, (fhandle_t *)fh.nfsrvfh_data, &vpnes);
1214 if (!error && !nd->nd_repstat) {
1215 if (op == NFSV4OP_LOOKUP || op == NFSV4OP_LOOKUPP) {
1216 new_mp = nvp->v_mount;
1217 if (fsidcmp(&cur_fsid, &new_mp->mnt_stat.f_fsid) != 0) {
1218 /* crossed a server mount point */
1219 nd->nd_repstat = nfsvno_checkexp(new_mp,
1220 nd->nd_nam, &nes, &credanon);
1221 if (!nd->nd_repstat)
1222 nd->nd_repstat = nfsd_excred(nd,
1223 &nes, credanon, true);
1224 if (credanon != NULL)
1225 crfree(credanon);
1226 if (!nd->nd_repstat) {
1227 vpnes = nes;
1228 cur_fsid = new_mp->mnt_stat.f_fsid;
1229 }
1230 }
1231 /* Lookup ops return a locked vnode */
1232 NFSVOPUNLOCK(nvp);
1233 }
1234 if (!nd->nd_repstat) {
1235 vrele(vp);
1236 vp = nvp;
1237 } else
1238 vrele(nvp);
1239 }
1240 if (nfsv4_opflag[op].modifyfs)
1241 vn_finished_write(temp_mp);
1242 } else if (nfsv4_opflag[op].retfh == 2) {
1243 if (vp == NULL || savevp == NULL) {
1244 nd->nd_repstat = NFSERR_NOFILEHANDLE;
1245 break;
1246 } else if (fsidcmp(&cur_fsid, &save_fsid) != 0) {
1247 nd->nd_repstat = NFSERR_XDEV;
1248 break;
1249 }
1250 if (nfsv4_opflag[op].modifyfs)
1251 vn_start_write(savevp, &temp_mp, V_WAIT);
1252 if (NFSVOPLOCK(savevp, LK_EXCLUSIVE) == 0) {
1253 VREF(vp);
1254 VREF(savevp);
1255 error = (*(nfsrv4_ops2[op]))(nd, isdgram,
1256 savevp, vp, &savevpnes, &vpnes);
1257 } else
1258 nd->nd_repstat = NFSERR_PERM;
1259 if (nfsv4_opflag[op].modifyfs)
1260 vn_finished_write(temp_mp);
1261 } else {
1262 if (nfsv4_opflag[op].retfh != 0)
1263 panic("nfsrvd_compound");
1264 if (nfsv4_opflag[op].needscfh) {
1265 if (vp != NULL) {
1266 lktype = nfsv4_opflag[op].lktype;
1267 if (nfsv4_opflag[op].modifyfs) {
1268 vn_start_write(vp, &temp_mp,
1269 V_WAIT);
1270 if (op == NFSV4OP_WRITE &&
1271 MNT_SHARED_WRITES(temp_mp))
1272 lktype = LK_SHARED;
1273 }
1274 if (NFSVOPLOCK(vp, lktype) == 0)
1275 VREF(vp);
1276 else
1277 nd->nd_repstat = NFSERR_PERM;
1278 } else {
1279 nd->nd_repstat = NFSERR_NOFILEHANDLE;
1280 if (op == NFSV4OP_SETATTR) {
1281 /*
1282 * Setattr reply requires a
1283 * bitmap even for errors like
1284 * these.
1285 */
1286 NFSM_BUILD(tl, u_int32_t *,
1287 NFSX_UNSIGNED);
1288 *tl = 0;
1289 }
1290 break;
1291 }
1292 if (nd->nd_repstat == 0) {
1293 error = (*(nfsrv4_ops0[op]))(nd,
1294 isdgram, vp, &vpnes);
1295 if ((op == NFSV4OP_SECINFO ||
1296 op == NFSV4OP_SECINFONONAME) &&
1297 error == 0 && nd->nd_repstat == 0) {
1298 /*
1299 * Secinfo and Secinfo_no_name
1300 * consume the current FH.
1301 */
1302 vrele(vp);
1303 vp = NULL;
1304 }
1305 }
1306 if (nfsv4_opflag[op].modifyfs)
1307 vn_finished_write(temp_mp);
1308 } else {
1309 error = (*(nfsrv4_ops0[op]))(nd, isdgram,
1310 NULL, &vpnes);
1311 }
1312 }
1313 }
1314 if (error) {
1315 if (error == EBADRPC || error == NFSERR_BADXDR) {
1316 nd->nd_repstat = NFSERR_BADXDR;
1317 } else {
1318 nd->nd_repstat = error;
1319 printf("nfsv4 comperr0=%d\n", error);
1320 }
1321 error = 0;
1322 }
1323
1324 if (nd->nd_repstat == ERELOOKUP) {
1325 /*
1326 * Roll back to the beginning of the operation
1327 * arguments.
1328 */
1329 nd->nd_md = md;
1330 nd->nd_dpos = dpos;
1331
1332 /*
1333 * Trim off the bogus reply for this operation
1334 * and redo the operation.
1335 */
1336 nfsm_trimtrailing(nd, mb, bpos, bextpg, bextpgsiz);
1337 nd->nd_repstat = 0;
1338 nd->nd_flag |= ND_ERELOOKUP;
1339 goto tryagain;
1340 }
1341 nd->nd_flag &= ~ND_ERELOOKUP;
1342
1343 if (statsinprog != 0) {
1344 nfsrvd_statend(op, /*bytes*/ 0, /*now*/ NULL,
1345 /*then*/ &start_time);
1346 statsinprog = 0;
1347 }
1348
1349 retops++;
1350 if (nd->nd_repstat) {
1351 *repp = nfsd_errmap(nd);
1352 break;
1353 } else {
1354 *repp = 0; /* NFS4_OK */
1355 }
1356 }
1357 nfsmout:
1358 if (statsinprog != 0) {
1359 nfsrvd_statend(op, /*bytes*/ 0, /*now*/ NULL,
1360 /*then*/ &start_time);
1361 statsinprog = 0;
1362 }
1363 if (error) {
1364 if (error == EBADRPC || error == NFSERR_BADXDR)
1365 nd->nd_repstat = NFSERR_BADXDR;
1366 else
1367 printf("nfsv4 comperr1=%d\n", error);
1368 }
1369 if (taglen == -1) {
1370 NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
1371 *tl++ = 0;
1372 *tl = 0;
1373 } else {
1374 *retopsp = txdr_unsigned(retops);
1375 }
1376 if (vp)
1377 vrele(vp);
1378 if (savevp)
1379 vrele(savevp);
1380 NFSLOCKV4ROOTMUTEX();
1381 nfsv4_relref(&nfsv4rootfs_lock);
1382 NFSUNLOCKV4ROOTMUTEX();
1383
1384 NFSEXITCODE2(0, nd);
1385 }
1386