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