]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/fs/nfsserver/nfs_nfsdsocket.c
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / sys / fs / nfsserver / nfs_nfsdsocket.c
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_notsupp,
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_notsupp,
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 /*
430  * This static array indicates which server procedures require the extra
431  * arguments to return the current file handle for V2, 3.
432  */
433 static int nfs_retfh[NFS_V3NPROCS] = { 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1,
434         1, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0 };
435
436 extern struct nfsv4_opflag nfsv4_opflag[NFSV42_NOPS];
437
438 static int nfsv3to4op[NFS_V3NPROCS] = {
439         NFSPROC_NULL,
440         NFSV4OP_GETATTR,
441         NFSV4OP_SETATTR,
442         NFSV4OP_LOOKUP,
443         NFSV4OP_ACCESS,
444         NFSV4OP_READLINK,
445         NFSV4OP_READ,
446         NFSV4OP_WRITE,
447         NFSV4OP_V3CREATE,
448         NFSV4OP_MKDIR,
449         NFSV4OP_SYMLINK,
450         NFSV4OP_MKNOD,
451         NFSV4OP_REMOVE,
452         NFSV4OP_RMDIR,
453         NFSV4OP_RENAME,
454         NFSV4OP_LINK,
455         NFSV4OP_READDIR,
456         NFSV4OP_READDIRPLUS,
457         NFSV4OP_FSSTAT,
458         NFSV4OP_FSINFO,
459         NFSV4OP_PATHCONF,
460         NFSV4OP_COMMIT,
461 };
462
463 static struct mtx nfsrvd_statmtx;
464 MTX_SYSINIT(nfsst, &nfsrvd_statmtx, "NFSstat", MTX_DEF);
465
466 static void
467 nfsrvd_statstart(int op, struct bintime *now)
468 {
469         if (op > (NFSV42_NOPS + NFSV4OP_FAKENOPS)) {
470                 printf("%s: op %d invalid\n", __func__, op);
471                 return;
472         }
473
474         mtx_lock(&nfsrvd_statmtx);
475         if (nfsstatsv1.srvstartcnt == nfsstatsv1.srvdonecnt) {
476                 if (now != NULL)
477                         nfsstatsv1.busyfrom = *now;
478                 else
479                         binuptime(&nfsstatsv1.busyfrom);
480                 
481         }
482         nfsstatsv1.srvrpccnt[op]++;
483         nfsstatsv1.srvstartcnt++;
484         mtx_unlock(&nfsrvd_statmtx);
485
486 }
487
488 static void
489 nfsrvd_statend(int op, uint64_t bytes, struct bintime *now,
490     struct bintime *then)
491 {
492         struct bintime dt, lnow;
493
494         if (op > (NFSV42_NOPS + NFSV4OP_FAKENOPS)) {
495                 printf("%s: op %d invalid\n", __func__, op);
496                 return;
497         }
498
499         if (now == NULL) {
500                 now = &lnow;
501                 binuptime(now);
502         }
503
504         mtx_lock(&nfsrvd_statmtx);
505
506         nfsstatsv1.srvbytes[op] += bytes;
507         nfsstatsv1.srvops[op]++;
508
509         if (then != NULL) {
510                 dt = *now;
511                 bintime_sub(&dt, then);
512                 bintime_add(&nfsstatsv1.srvduration[op], &dt);
513         }
514
515         dt = *now;
516         bintime_sub(&dt, &nfsstatsv1.busyfrom);
517         bintime_add(&nfsstatsv1.busytime, &dt);
518         nfsstatsv1.busyfrom = *now;
519
520         nfsstatsv1.srvdonecnt++;
521
522         mtx_unlock(&nfsrvd_statmtx);
523 }
524
525 /*
526  * Do an RPC. Basically, get the file handles translated to vnode pointers
527  * and then call the appropriate server routine. The server routines are
528  * split into groups, based on whether they use a file handle or file
529  * handle plus name or ...
530  * The NFS V4 Compound RPC is performed separately by nfsrvd_compound().
531  */
532 void
533 nfsrvd_dorpc(struct nfsrv_descript *nd, int isdgram, u_char *tag, int taglen,
534     u_int32_t minorvers)
535 {
536         int error = 0, lktype;
537         vnode_t vp;
538         mount_t mp = NULL;
539         struct nfsrvfh fh;
540         struct nfsexstuff nes;
541
542         /*
543          * Get a locked vnode for the first file handle
544          */
545         if (!(nd->nd_flag & ND_NFSV4)) {
546                 KASSERT(nd->nd_repstat == 0, ("nfsrvd_dorpc"));
547                 /*
548                  * For NFSv3, if the malloc/mget allocation is near limits,
549                  * return NFSERR_DELAY.
550                  */
551                 if ((nd->nd_flag & ND_NFSV3) && nfsrv_mallocmget_limit()) {
552                         nd->nd_repstat = NFSERR_DELAY;
553                         vp = NULL;
554                 } else {
555                         error = nfsrv_mtofh(nd, &fh);
556                         if (error) {
557                                 if (error != EBADRPC)
558                                         printf("nfs dorpc err1=%d\n", error);
559                                 nd->nd_repstat = NFSERR_GARBAGE;
560                                 goto out;
561                         }
562                         if (nd->nd_procnum == NFSPROC_READ ||
563                             nd->nd_procnum == NFSPROC_WRITE ||
564                             nd->nd_procnum == NFSPROC_READDIR ||
565                             nd->nd_procnum == NFSPROC_READDIRPLUS ||
566                             nd->nd_procnum == NFSPROC_READLINK ||
567                             nd->nd_procnum == NFSPROC_GETATTR ||
568                             nd->nd_procnum == NFSPROC_ACCESS ||
569                             nd->nd_procnum == NFSPROC_FSSTAT ||
570                             nd->nd_procnum == NFSPROC_FSINFO)
571                                 lktype = LK_SHARED;
572                         else
573                                 lktype = LK_EXCLUSIVE;
574                         if (nd->nd_flag & ND_PUBLOOKUP)
575                                 nfsd_fhtovp(nd, &nfs_pubfh, lktype, &vp, &nes,
576                                     &mp, nfsrv_writerpc[nd->nd_procnum]);
577                         else
578                                 nfsd_fhtovp(nd, &fh, lktype, &vp, &nes,
579                                     &mp, nfsrv_writerpc[nd->nd_procnum]);
580                         if (nd->nd_repstat == NFSERR_PROGNOTV4)
581                                 goto out;
582                 }
583         }
584
585         /*
586          * For V2 and 3, set the ND_SAVEREPLY flag for the recent request
587          * cache, as required.
588          * For V4, nfsrvd_compound() does this.
589          */
590         if (!(nd->nd_flag & ND_NFSV4) && nfsrv_nonidempotent[nd->nd_procnum])
591                 nd->nd_flag |= ND_SAVEREPLY;
592
593         nfsrvd_rephead(nd);
594         /*
595          * If nd_repstat is non-zero, just fill in the reply status
596          * to complete the RPC reply for V2. Otherwise, you must do
597          * the RPC.
598          */
599         if (nd->nd_repstat && (nd->nd_flag & ND_NFSV2)) {
600                 *nd->nd_errp = nfsd_errmap(nd);
601                 nfsrvd_statstart(nfsv3to4op[nd->nd_procnum], /*now*/ NULL);
602                 nfsrvd_statend(nfsv3to4op[nd->nd_procnum], /*bytes*/ 0,
603                    /*now*/ NULL, /*then*/ NULL);
604                 if (mp != NULL && nfsrv_writerpc[nd->nd_procnum] != 0)
605                         vn_finished_write(mp);
606                 goto out;
607         }
608
609         /*
610          * Now the procedure can be performed. For V4, nfsrvd_compound()
611          * works through the sub-rpcs, otherwise just call the procedure.
612          * The procedures are in three groups with different arguments.
613          * The group is indicated by the value in nfs_retfh[].
614          */
615         if (nd->nd_flag & ND_NFSV4) {
616                 nfsrvd_compound(nd, isdgram, tag, taglen, minorvers);
617         } else {
618                 struct bintime start_time;
619
620                 binuptime(&start_time);
621                 nfsrvd_statstart(nfsv3to4op[nd->nd_procnum], &start_time);
622
623                 if (nfs_retfh[nd->nd_procnum] == 1) {
624                         if (vp)
625                                 NFSVOPUNLOCK(vp);
626                         error = (*(nfsrv3_procs1[nd->nd_procnum]))(nd, isdgram,
627                             vp, NULL, (fhandle_t *)fh.nfsrvfh_data, &nes);
628                 } else if (nfs_retfh[nd->nd_procnum] == 2) {
629                         error = (*(nfsrv3_procs2[nd->nd_procnum]))(nd, isdgram,
630                             vp, NULL, &nes, NULL);
631                 } else {
632                         error = (*(nfsrv3_procs0[nd->nd_procnum]))(nd, isdgram,
633                             vp, &nes);
634                 }
635                 if (mp != NULL && nfsrv_writerpc[nd->nd_procnum] != 0)
636                         vn_finished_write(mp);
637
638                 nfsrvd_statend(nfsv3to4op[nd->nd_procnum], /*bytes*/ 0,
639                     /*now*/ NULL, /*then*/ &start_time);
640         }
641         if (error) {
642                 if (error != EBADRPC)
643                         printf("nfs dorpc err2=%d\n", error);
644                 nd->nd_repstat = NFSERR_GARBAGE;
645         }
646         *nd->nd_errp = nfsd_errmap(nd);
647
648         /*
649          * Don't cache certain reply status values.
650          */
651         if (nd->nd_repstat && (nd->nd_flag & ND_SAVEREPLY) &&
652             (nd->nd_repstat == NFSERR_GARBAGE ||
653              nd->nd_repstat == NFSERR_BADXDR ||
654              nd->nd_repstat == NFSERR_MOVED ||
655              nd->nd_repstat == NFSERR_DELAY ||
656              nd->nd_repstat == NFSERR_BADSEQID ||
657              nd->nd_repstat == NFSERR_RESOURCE ||
658              nd->nd_repstat == NFSERR_SERVERFAULT ||
659              nd->nd_repstat == NFSERR_STALECLIENTID ||
660              nd->nd_repstat == NFSERR_STALESTATEID ||
661              nd->nd_repstat == NFSERR_OLDSTATEID ||
662              nd->nd_repstat == NFSERR_BADSTATEID ||
663              nd->nd_repstat == NFSERR_GRACE ||
664              nd->nd_repstat == NFSERR_NOGRACE))
665                 nd->nd_flag &= ~ND_SAVEREPLY;
666
667 out:
668         NFSEXITCODE2(0, nd);
669 }
670
671 /*
672  * Breaks down a compound RPC request and calls the server routines for
673  * the subprocedures.
674  * Some suboperations are performed directly here to simplify file handle<-->
675  * vnode pointer handling.
676  */
677 static void
678 nfsrvd_compound(struct nfsrv_descript *nd, int isdgram, u_char *tag,
679     int taglen, u_int32_t minorvers)
680 {
681         int i, lktype, op, op0 = 0, statsinprog = 0;
682         u_int32_t *tl;
683         struct nfsclient *clp, *nclp;
684         int numops, error = 0, igotlock;
685         u_int32_t retops = 0, *retopsp = NULL, *repp;
686         vnode_t vp, nvp, savevp;
687         struct nfsrvfh fh;
688         mount_t new_mp, temp_mp = NULL;
689         struct ucred *credanon;
690         struct nfsexstuff nes, vpnes, savevpnes;
691         fsid_t cur_fsid, save_fsid;
692         static u_int64_t compref = 0;
693         struct bintime start_time;
694         struct thread *p;
695
696         p = curthread;
697
698         NFSVNO_EXINIT(&vpnes);
699         NFSVNO_EXINIT(&savevpnes);
700         /*
701          * Put the seq# of the current compound RPC in nfsrv_descript.
702          * (This is used by nfsrv_checkgetattr(), to see if the write
703          *  delegation was created by the same compound RPC as the one
704          *  with that Getattr in it.)
705          * Don't worry about the 64bit number wrapping around. It ain't
706          * gonna happen before this server gets shut down/rebooted.
707          */
708         nd->nd_compref = compref++;
709
710         /*
711          * Check for and optionally get a lock on the root. This lock means that
712          * no nfsd will be fiddling with the V4 file system and state stuff. It
713          * is required when the V4 root is being changed, the stable storage
714          * restart file is being updated, or callbacks are being done.
715          * When any of the nfsd are processing an NFSv4 compound RPC, they must
716          * either hold a reference count (nfs_usecnt) or the lock. When
717          * nfsrv_unlock() is called to release the lock, it can optionally
718          * also get a reference count, which saves the need for a call to
719          * nfsrv_getref() after nfsrv_unlock().
720          */
721         /*
722          * First, check to see if we need to wait for an update lock.
723          */
724         igotlock = 0;
725         NFSLOCKV4ROOTMUTEX();
726         if (nfsrv_stablefirst.nsf_flags & NFSNSF_NEEDLOCK)
727                 igotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL,
728                     NFSV4ROOTLOCKMUTEXPTR, NULL);
729         else
730                 igotlock = nfsv4_lock(&nfsv4rootfs_lock, 0, NULL,
731                     NFSV4ROOTLOCKMUTEXPTR, NULL);
732         NFSUNLOCKV4ROOTMUTEX();
733         if (igotlock) {
734                 /*
735                  * If I got the lock, I can update the stable storage file.
736                  * Done when the grace period is over or a client has long
737                  * since expired.
738                  */
739                 nfsrv_stablefirst.nsf_flags &= ~NFSNSF_NEEDLOCK;
740                 if ((nfsrv_stablefirst.nsf_flags &
741                     (NFSNSF_GRACEOVER | NFSNSF_UPDATEDONE)) == NFSNSF_GRACEOVER)
742                         nfsrv_updatestable(p);
743
744                 /*
745                  * If at least one client has long since expired, search
746                  * the client list for them, write a REVOKE record on the
747                  * stable storage file and then remove them from the client
748                  * list.
749                  */
750                 if (nfsrv_stablefirst.nsf_flags & NFSNSF_EXPIREDCLIENT) {
751                         nfsrv_stablefirst.nsf_flags &= ~NFSNSF_EXPIREDCLIENT;
752                         for (i = 0; i < nfsrv_clienthashsize; i++) {
753                             LIST_FOREACH_SAFE(clp, &nfsclienthash[i], lc_hash,
754                                 nclp) {
755                                 if (clp->lc_flags & LCL_EXPIREIT) {
756                                     if (!LIST_EMPTY(&clp->lc_open) ||
757                                         !LIST_EMPTY(&clp->lc_deleg))
758                                         nfsrv_writestable(clp->lc_id,
759                                             clp->lc_idlen, NFSNST_REVOKE, p);
760                                     nfsrv_cleanclient(clp, p);
761                                     nfsrv_freedeleglist(&clp->lc_deleg);
762                                     nfsrv_freedeleglist(&clp->lc_olddeleg);
763                                     LIST_REMOVE(clp, lc_hash);
764                                     nfsrv_zapclient(clp, p);
765                                 }
766                             }
767                         }
768                 }
769                 NFSLOCKV4ROOTMUTEX();
770                 nfsv4_unlock(&nfsv4rootfs_lock, 1);
771                 NFSUNLOCKV4ROOTMUTEX();
772         } else {
773                 /*
774                  * If we didn't get the lock, we need to get a refcnt,
775                  * which also checks for and waits for the lock.
776                  */
777                 NFSLOCKV4ROOTMUTEX();
778                 nfsv4_getref(&nfsv4rootfs_lock, NULL,
779                     NFSV4ROOTLOCKMUTEXPTR, NULL);
780                 NFSUNLOCKV4ROOTMUTEX();
781         }
782
783         /*
784          * If flagged, search for open owners that haven't had any opens
785          * for a long time.
786          */
787         if (nfsrv_stablefirst.nsf_flags & NFSNSF_NOOPENS) {
788                 nfsrv_throwawayopens(p);
789         }
790
791         /* Do a CBLAYOUTRECALL callback if over the high water mark. */
792         if (nfsrv_layoutcnt > nfsrv_layouthighwater)
793                 nfsrv_recalloldlayout(p);
794
795         savevp = vp = NULL;
796         save_fsid.val[0] = save_fsid.val[1] = 0;
797         cur_fsid.val[0] = cur_fsid.val[1] = 0;
798
799         /* If taglen < 0, there was a parsing error in nfsd_getminorvers(). */
800         if (taglen < 0) {
801                 error = EBADRPC;
802                 goto nfsmout;
803         }
804
805         (void) nfsm_strtom(nd, tag, taglen);
806         NFSM_BUILD(retopsp, u_int32_t *, NFSX_UNSIGNED);
807         NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
808         if ((minorvers != NFSV4_MINORVERSION &&
809             minorvers != NFSV41_MINORVERSION &&
810             minorvers != NFSV42_MINORVERSION) ||
811             minorvers < nfs_minminorv4 || minorvers > nfs_maxminorv4)
812                 nd->nd_repstat = NFSERR_MINORVERMISMATCH;
813         if (nd->nd_repstat)
814                 numops = 0;
815         else
816                 numops = fxdr_unsigned(int, *tl);
817         /*
818          * Loop around doing the sub ops.
819          * vp - is an unlocked vnode pointer for the CFH
820          * savevp - is an unlocked vnode pointer for the SAVEDFH
821          * (at some future date, it might turn out to be more appropriate
822          *  to keep the file handles instead of vnode pointers?)
823          * savevpnes and vpnes - are the export flags for the above.
824          */
825         for (i = 0; i < numops; i++) {
826                 NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
827                 NFSM_BUILD(repp, u_int32_t *, 2 * NFSX_UNSIGNED);
828                 *repp = *tl;
829                 op = fxdr_unsigned(int, *tl);
830                 NFSD_DEBUG(4, "op=%d\n", op);
831                 if (op < NFSV4OP_ACCESS || op >= NFSV42_NOPS ||
832                     (op >= NFSV4OP_NOPS && (nd->nd_flag & ND_NFSV41) == 0) ||
833                     (op >= NFSV41_NOPS && (nd->nd_flag & ND_NFSV42) == 0)) {
834                         nd->nd_repstat = NFSERR_OPILLEGAL;
835                         *repp++ = txdr_unsigned(NFSV4OP_OPILLEGAL);
836                         *repp = nfsd_errmap(nd);
837                         retops++;
838                         break;
839                 } else {
840                         repp++;
841                 }
842
843                 binuptime(&start_time);
844                 nfsrvd_statstart(op, &start_time);
845                 statsinprog = 1;
846
847                 if (i == 0)
848                         op0 = op;
849                 if (i == numops - 1)
850                         nd->nd_flag |= ND_LASTOP;
851
852                 /*
853                  * Check for a referral on the current FH and, if so, return
854                  * NFSERR_MOVED for all ops that allow it, except Getattr.
855                  */
856                 if (vp != NULL && op != NFSV4OP_GETATTR &&
857                     nfsv4root_getreferral(vp, NULL, 0) != NULL &&
858                     nfsrv_errmoved(op)) {
859                         nd->nd_repstat = NFSERR_MOVED;
860                         *repp = nfsd_errmap(nd);
861                         retops++;
862                         break;
863                 }
864
865                 /*
866                  * For NFSv4.1, check for a Sequence Operation being first
867                  * or one of the other allowed operations by itself.
868                  */
869                 if ((nd->nd_flag & ND_NFSV41) != 0) {
870                         if (i != 0 && op == NFSV4OP_SEQUENCE)
871                                 nd->nd_repstat = NFSERR_SEQUENCEPOS;
872                         else if (i == 0 && op != NFSV4OP_SEQUENCE &&
873                             op != NFSV4OP_EXCHANGEID &&
874                             op != NFSV4OP_CREATESESSION &&
875                             op != NFSV4OP_BINDCONNTOSESS &&
876                             op != NFSV4OP_DESTROYCLIENTID &&
877                             op != NFSV4OP_DESTROYSESSION)
878                                 nd->nd_repstat = NFSERR_OPNOTINSESS;
879                         else if (i != 0 && op0 != NFSV4OP_SEQUENCE)
880                                 nd->nd_repstat = NFSERR_NOTONLYOP;
881                         if (nd->nd_repstat != 0) {
882                                 *repp = nfsd_errmap(nd);
883                                 retops++;
884                                 break;
885                         }
886                 }
887
888                 nd->nd_procnum = op;
889                 /*
890                  * If over flood level, reply NFSERR_RESOURCE, if at the first
891                  * Op. (Since a client recovery from NFSERR_RESOURCE can get
892                  * really nasty for certain Op sequences, I'll play it safe
893                  * and only return the error at the beginning.) The cache
894                  * will still function over flood level, but uses lots of
895                  * mbufs.)
896                  * If nfsrv_mallocmget_limit() returns True, the system is near
897                  * to its limit for memory that malloc()/mget() can allocate.
898                  */
899                 if (i == 0 && (nd->nd_rp == NULL ||
900                     nd->nd_rp->rc_refcnt == 0) &&
901                     (nfsrv_mallocmget_limit() ||
902                      nfsrc_tcpsavedreplies > nfsrc_floodlevel)) {
903                         if (nfsrc_tcpsavedreplies > nfsrc_floodlevel)
904                                 printf("nfsd server cache flooded, try "
905                                     "increasing vfs.nfsd.tcphighwater\n");
906                         nd->nd_repstat = NFSERR_RESOURCE;
907                         *repp = nfsd_errmap(nd);
908                         if (op == NFSV4OP_SETATTR) {
909                                 /*
910                                  * Setattr replies require a bitmap.
911                                  * even for errors like these.
912                                  */
913                                 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
914                                 *tl = 0;
915                         }
916                         retops++;
917                         break;
918                 }
919                 if (nfsv4_opflag[op].savereply)
920                         nd->nd_flag |= ND_SAVEREPLY;
921                 switch (op) {
922                 case NFSV4OP_PUTFH:
923                         error = nfsrv_mtofh(nd, &fh);
924                         if (error)
925                                 goto nfsmout;
926                         if (!nd->nd_repstat)
927                                 nfsd_fhtovp(nd, &fh, LK_SHARED, &nvp, &nes,
928                                     NULL, 0);
929                         /* For now, allow this for non-export FHs */
930                         if (!nd->nd_repstat) {
931                                 if (vp)
932                                         vrele(vp);
933                                 vp = nvp;
934                                 cur_fsid = vp->v_mount->mnt_stat.f_fsid;
935                                 NFSVOPUNLOCK(vp);
936                                 vpnes = nes;
937                         }
938                         break;
939                 case NFSV4OP_PUTPUBFH:
940                         if (nfs_pubfhset)
941                             nfsd_fhtovp(nd, &nfs_pubfh, LK_SHARED, &nvp,
942                                 &nes, NULL, 0);
943                         else
944                             nd->nd_repstat = NFSERR_NOFILEHANDLE;
945                         if (!nd->nd_repstat) {
946                                 if (vp)
947                                         vrele(vp);
948                                 vp = nvp;
949                                 cur_fsid = vp->v_mount->mnt_stat.f_fsid;
950                                 NFSVOPUNLOCK(vp);
951                                 vpnes = nes;
952                         }
953                         break;
954                 case NFSV4OP_PUTROOTFH:
955                         if (nfs_rootfhset) {
956                                 nfsd_fhtovp(nd, &nfs_rootfh, LK_SHARED, &nvp,
957                                     &nes, NULL, 0);
958                                 if (!nd->nd_repstat) {
959                                         if (vp)
960                                                 vrele(vp);
961                                         vp = nvp;
962                                         cur_fsid = vp->v_mount->mnt_stat.f_fsid;
963                                         NFSVOPUNLOCK(vp);
964                                         vpnes = nes;
965                                 }
966                         } else
967                                 nd->nd_repstat = NFSERR_NOFILEHANDLE;
968                         break;
969                 case NFSV4OP_SAVEFH:
970                         if (vp && NFSVNO_EXPORTED(&vpnes)) {
971                                 nd->nd_repstat = 0;
972                                 /* If vp == savevp, a no-op */
973                                 if (vp != savevp) {
974                                         if (savevp)
975                                                 vrele(savevp);
976                                         VREF(vp);
977                                         savevp = vp;
978                                         savevpnes = vpnes;
979                                         save_fsid = cur_fsid;
980                                 }
981                                 if ((nd->nd_flag & ND_CURSTATEID) != 0) {
982                                         nd->nd_savedcurstateid =
983                                             nd->nd_curstateid;
984                                         nd->nd_flag |= ND_SAVEDCURSTATEID;
985                                 }
986                         } else {
987                                 nd->nd_repstat = NFSERR_NOFILEHANDLE;
988                         }
989                         break;
990                 case NFSV4OP_RESTOREFH:
991                         if (savevp) {
992                                 nd->nd_repstat = 0;
993                                 /* If vp == savevp, a no-op */
994                                 if (vp != savevp) {
995                                         VREF(savevp);
996                                         vrele(vp);
997                                         vp = savevp;
998                                         vpnes = savevpnes;
999                                         cur_fsid = save_fsid;
1000                                 }
1001                                 if ((nd->nd_flag & ND_SAVEDCURSTATEID) != 0) {
1002                                         nd->nd_curstateid =
1003                                             nd->nd_savedcurstateid;
1004                                         nd->nd_flag |= ND_CURSTATEID;
1005                                 }
1006                         } else {
1007                                 nd->nd_repstat = NFSERR_RESTOREFH;
1008                         }
1009                         break;
1010                 default:
1011                     /*
1012                      * Allow a Lookup, Getattr, GetFH, Secinfo on an
1013                      * non-exported directory if
1014                      * nfs_rootfhset. Do I need to allow any other Ops?
1015                      * (You can only have a non-exported vpnes if
1016                      *  nfs_rootfhset is true. See nfsd_fhtovp())
1017                      * Allow AUTH_SYS to be used for file systems
1018                      * exported GSS only for certain Ops, to allow
1019                      * clients to do mounts more easily.
1020                      */
1021                     if (nfsv4_opflag[op].needscfh && vp) {
1022                         if (!NFSVNO_EXPORTED(&vpnes) &&
1023                             op != NFSV4OP_LOOKUP &&
1024                             op != NFSV4OP_GETATTR &&
1025                             op != NFSV4OP_GETFH &&
1026                             op != NFSV4OP_ACCESS &&
1027                             op != NFSV4OP_READLINK &&
1028                             op != NFSV4OP_SECINFO)
1029                                 nd->nd_repstat = NFSERR_NOFILEHANDLE;
1030                         else if (nfsvno_testexp(nd, &vpnes) &&
1031                             op != NFSV4OP_LOOKUP &&
1032                             op != NFSV4OP_GETFH &&
1033                             op != NFSV4OP_GETATTR &&
1034                             op != NFSV4OP_SECINFO)
1035                                 nd->nd_repstat = NFSERR_WRONGSEC;
1036                         if (nd->nd_repstat) {
1037                                 if (op == NFSV4OP_SETATTR) {
1038                                     /*
1039                                      * Setattr reply requires a bitmap
1040                                      * even for errors like these.
1041                                      */
1042                                     NFSM_BUILD(tl, u_int32_t *,
1043                                         NFSX_UNSIGNED);
1044                                     *tl = 0;
1045                                 }
1046                                 break;
1047                         }
1048                     }
1049                     if (nfsv4_opflag[op].retfh == 1) {
1050                         if (!vp) {
1051                                 nd->nd_repstat = NFSERR_NOFILEHANDLE;
1052                                 break;
1053                         }
1054                         VREF(vp);
1055                         if (nfsv4_opflag[op].modifyfs)
1056                                 vn_start_write(vp, &temp_mp, V_WAIT);
1057                         error = (*(nfsrv4_ops1[op]))(nd, isdgram, vp,
1058                             &nvp, (fhandle_t *)fh.nfsrvfh_data, &vpnes);
1059                         if (!error && !nd->nd_repstat) {
1060                             if (op == NFSV4OP_LOOKUP || op == NFSV4OP_LOOKUPP) {
1061                                 new_mp = nvp->v_mount;
1062                                 if (fsidcmp(&cur_fsid, &new_mp->mnt_stat.f_fsid) != 0) {
1063                                     /* crossed a server mount point */
1064                                     nd->nd_repstat = nfsvno_checkexp(new_mp,
1065                                         nd->nd_nam, &nes, &credanon);
1066                                     if (!nd->nd_repstat)
1067                                         nd->nd_repstat = nfsd_excred(nd,
1068                                             &nes, credanon);
1069                                     if (credanon != NULL)
1070                                         crfree(credanon);
1071                                     if (!nd->nd_repstat) {
1072                                         vpnes = nes;
1073                                         cur_fsid = new_mp->mnt_stat.f_fsid;
1074                                     }
1075                                 }
1076                                 /* Lookup ops return a locked vnode */
1077                                 NFSVOPUNLOCK(nvp);
1078                             }
1079                             if (!nd->nd_repstat) {
1080                                     vrele(vp);
1081                                     vp = nvp;
1082                             } else
1083                                     vrele(nvp);
1084                         }
1085                         if (nfsv4_opflag[op].modifyfs)
1086                                 vn_finished_write(temp_mp);
1087                     } else if (nfsv4_opflag[op].retfh == 2) {
1088                         if (vp == NULL || savevp == NULL) {
1089                                 nd->nd_repstat = NFSERR_NOFILEHANDLE;
1090                                 break;
1091                         } else if (fsidcmp(&cur_fsid, &save_fsid) != 0) {
1092                                 nd->nd_repstat = NFSERR_XDEV;
1093                                 break;
1094                         }
1095                         if (nfsv4_opflag[op].modifyfs)
1096                                 vn_start_write(savevp, &temp_mp, V_WAIT);
1097                         if (NFSVOPLOCK(savevp, LK_EXCLUSIVE) == 0) {
1098                                 VREF(vp);
1099                                 VREF(savevp);
1100                                 error = (*(nfsrv4_ops2[op]))(nd, isdgram,
1101                                     savevp, vp, &savevpnes, &vpnes);
1102                         } else
1103                                 nd->nd_repstat = NFSERR_PERM;
1104                         if (nfsv4_opflag[op].modifyfs)
1105                                 vn_finished_write(temp_mp);
1106                     } else {
1107                         if (nfsv4_opflag[op].retfh != 0)
1108                                 panic("nfsrvd_compound");
1109                         if (nfsv4_opflag[op].needscfh) {
1110                                 if (vp != NULL) {
1111                                         lktype = nfsv4_opflag[op].lktype;
1112                                         if (nfsv4_opflag[op].modifyfs) {
1113                                                 vn_start_write(vp, &temp_mp,
1114                                                     V_WAIT);
1115                                                 if (op == NFSV4OP_WRITE &&
1116                                                     MNT_SHARED_WRITES(temp_mp))
1117                                                         lktype = LK_SHARED;
1118                                         }
1119                                         if (NFSVOPLOCK(vp, lktype) == 0)
1120                                                 VREF(vp);
1121                                         else
1122                                                 nd->nd_repstat = NFSERR_PERM;
1123                                 } else {
1124                                         nd->nd_repstat = NFSERR_NOFILEHANDLE;
1125                                         if (op == NFSV4OP_SETATTR) {
1126                                                 /*
1127                                                  * Setattr reply requires a
1128                                                  * bitmap even for errors like
1129                                                  * these.
1130                                                  */
1131                                                 NFSM_BUILD(tl, u_int32_t *,
1132                                                     NFSX_UNSIGNED);
1133                                                 *tl = 0;
1134                                         }
1135                                         break;
1136                                 }
1137                                 if (nd->nd_repstat == 0)
1138                                         error = (*(nfsrv4_ops0[op]))(nd,
1139                                             isdgram, vp, &vpnes);
1140                                 if (nfsv4_opflag[op].modifyfs)
1141                                         vn_finished_write(temp_mp);
1142                         } else {
1143                                 error = (*(nfsrv4_ops0[op]))(nd, isdgram,
1144                                     NULL, &vpnes);
1145                         }
1146                     }
1147                 }
1148                 if (error) {
1149                         if (error == EBADRPC || error == NFSERR_BADXDR) {
1150                                 nd->nd_repstat = NFSERR_BADXDR;
1151                         } else {
1152                                 nd->nd_repstat = error;
1153                                 printf("nfsv4 comperr0=%d\n", error);
1154                         }
1155                         error = 0;
1156                 }
1157
1158                 if (statsinprog != 0) {
1159                         nfsrvd_statend(op, /*bytes*/ 0, /*now*/ NULL,
1160                             /*then*/ &start_time);
1161                         statsinprog = 0;
1162                 }
1163
1164                 retops++;
1165                 if (nd->nd_repstat) {
1166                         *repp = nfsd_errmap(nd);
1167                         break;
1168                 } else {
1169                         *repp = 0;      /* NFS4_OK */
1170                 }
1171         }
1172 nfsmout:
1173         if (statsinprog != 0) {
1174                 nfsrvd_statend(op, /*bytes*/ 0, /*now*/ NULL,
1175                     /*then*/ &start_time);
1176                 statsinprog = 0;
1177         }
1178         if (error) {
1179                 if (error == EBADRPC || error == NFSERR_BADXDR)
1180                         nd->nd_repstat = NFSERR_BADXDR;
1181                 else
1182                         printf("nfsv4 comperr1=%d\n", error);
1183         }
1184         if (taglen == -1) {
1185                 NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
1186                 *tl++ = 0;
1187                 *tl = 0;
1188         } else {
1189                 *retopsp = txdr_unsigned(retops);
1190         }
1191         if (vp)
1192                 vrele(vp);
1193         if (savevp)
1194                 vrele(savevp);
1195         NFSLOCKV4ROOTMUTEX();
1196         nfsv4_relref(&nfsv4rootfs_lock);
1197         NFSUNLOCKV4ROOTMUTEX();
1198
1199         NFSEXITCODE2(0, nd);
1200 }