xref: /freebsd/sys/fs/nfsserver/nfs_nfsdport.c (revision 2f513db72b034fd5ef7f080b11be5c711c15186a)
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 #include <sys/capsicum.h>
40 #include <sys/extattr.h>
41 
42 /*
43  * Functions that perform the vfs operations required by the routines in
44  * nfsd_serv.c. It is hoped that this change will make the server more
45  * portable.
46  */
47 
48 #include <fs/nfs/nfsport.h>
49 #include <security/mac/mac_framework.h>
50 #include <sys/filio.h>
51 #include <sys/hash.h>
52 #include <sys/sysctl.h>
53 #include <nlm/nlm_prot.h>
54 #include <nlm/nlm.h>
55 
56 FEATURE(nfsd, "NFSv4 server");
57 
58 extern u_int32_t newnfs_true, newnfs_false, newnfs_xdrneg1;
59 extern int nfsrv_useacl;
60 extern int newnfs_numnfsd;
61 extern struct mount nfsv4root_mnt;
62 extern struct nfsrv_stablefirst nfsrv_stablefirst;
63 extern void (*nfsd_call_servertimer)(void);
64 extern SVCPOOL	*nfsrvd_pool;
65 extern struct nfsv4lock nfsd_suspend_lock;
66 extern struct nfsclienthashhead *nfsclienthash;
67 extern struct nfslockhashhead *nfslockhash;
68 extern struct nfssessionhash *nfssessionhash;
69 extern int nfsrv_sessionhashsize;
70 extern struct nfsstatsv1 nfsstatsv1;
71 extern struct nfslayouthash *nfslayouthash;
72 extern int nfsrv_layouthashsize;
73 extern struct mtx nfsrv_dslock_mtx;
74 extern int nfs_pnfsiothreads;
75 extern struct nfsdontlisthead nfsrv_dontlisthead;
76 extern volatile int nfsrv_dontlistlen;
77 extern volatile int nfsrv_devidcnt;
78 extern int nfsrv_maxpnfsmirror;
79 struct vfsoptlist nfsv4root_opt, nfsv4root_newopt;
80 NFSDLOCKMUTEX;
81 NFSSTATESPINLOCK;
82 struct nfsrchash_bucket nfsrchash_table[NFSRVCACHE_HASHSIZE];
83 struct nfsrchash_bucket nfsrcahash_table[NFSRVCACHE_HASHSIZE];
84 struct mtx nfsrc_udpmtx;
85 struct mtx nfs_v4root_mutex;
86 struct mtx nfsrv_dontlistlock_mtx;
87 struct mtx nfsrv_recalllock_mtx;
88 struct nfsrvfh nfs_rootfh, nfs_pubfh;
89 int nfs_pubfhset = 0, nfs_rootfhset = 0;
90 struct proc *nfsd_master_proc = NULL;
91 int nfsd_debuglevel = 0;
92 static pid_t nfsd_master_pid = (pid_t)-1;
93 static char nfsd_master_comm[MAXCOMLEN + 1];
94 static struct timeval nfsd_master_start;
95 static uint32_t nfsv4_sysid = 0;
96 static fhandle_t zerofh;
97 
98 static int nfssvc_srvcall(struct thread *, struct nfssvc_args *,
99     struct ucred *);
100 
101 int nfsrv_enable_crossmntpt = 1;
102 static int nfs_commit_blks;
103 static int nfs_commit_miss;
104 extern int nfsrv_issuedelegs;
105 extern int nfsrv_dolocallocks;
106 extern int nfsd_enable_stringtouid;
107 extern struct nfsdevicehead nfsrv_devidhead;
108 
109 static int nfsrv_createiovec(int, struct mbuf **, struct mbuf **,
110     struct iovec **);
111 static int nfsrv_createiovecw(int, struct mbuf *, char *, struct iovec **,
112     int *);
113 static void nfsrv_pnfscreate(struct vnode *, struct vattr *, struct ucred *,
114     NFSPROC_T *);
115 static void nfsrv_pnfsremovesetup(struct vnode *, NFSPROC_T *, struct vnode **,
116     int *, char *, fhandle_t *);
117 static void nfsrv_pnfsremove(struct vnode **, int, char *, fhandle_t *,
118     NFSPROC_T *);
119 static int nfsrv_proxyds(struct vnode *, off_t, int, struct ucred *,
120     struct thread *, int, struct mbuf **, char *, struct mbuf **,
121     struct nfsvattr *, struct acl *, off_t *, int, bool *);
122 static int nfsrv_setextattr(struct vnode *, struct nfsvattr *, NFSPROC_T *);
123 static int nfsrv_readdsrpc(fhandle_t *, off_t, int, struct ucred *,
124     NFSPROC_T *, struct nfsmount *, struct mbuf **, struct mbuf **);
125 static int nfsrv_writedsrpc(fhandle_t *, off_t, int, struct ucred *,
126     NFSPROC_T *, struct vnode *, struct nfsmount **, int, struct mbuf **,
127     char *, int *);
128 static int nfsrv_allocatedsrpc(fhandle_t *, off_t, off_t, struct ucred *,
129     NFSPROC_T *, struct vnode *, struct nfsmount **, int, int *);
130 static int nfsrv_setacldsrpc(fhandle_t *, struct ucred *, NFSPROC_T *,
131     struct vnode *, struct nfsmount **, int, struct acl *, int *);
132 static int nfsrv_setattrdsrpc(fhandle_t *, struct ucred *, NFSPROC_T *,
133     struct vnode *, struct nfsmount **, int, struct nfsvattr *, int *);
134 static int nfsrv_getattrdsrpc(fhandle_t *, struct ucred *, NFSPROC_T *,
135     struct vnode *, struct nfsmount *, struct nfsvattr *);
136 static int nfsrv_seekdsrpc(fhandle_t *, off_t *, int, bool *, struct ucred *,
137     NFSPROC_T *, struct nfsmount *);
138 static int nfsrv_putfhname(fhandle_t *, char *);
139 static int nfsrv_pnfslookupds(struct vnode *, struct vnode *,
140     struct pnfsdsfile *, struct vnode **, NFSPROC_T *);
141 static void nfsrv_pnfssetfh(struct vnode *, struct pnfsdsfile *, char *, char *,
142     struct vnode *, NFSPROC_T *);
143 static int nfsrv_dsremove(struct vnode *, char *, struct ucred *, NFSPROC_T *);
144 static int nfsrv_dssetacl(struct vnode *, struct acl *, struct ucred *,
145     NFSPROC_T *);
146 static int nfsrv_pnfsstatfs(struct statfs *, struct mount *);
147 
148 int nfs_pnfsio(task_fn_t *, void *);
149 
150 SYSCTL_NODE(_vfs, OID_AUTO, nfsd, CTLFLAG_RW, 0, "NFS server");
151 SYSCTL_INT(_vfs_nfsd, OID_AUTO, mirrormnt, CTLFLAG_RW,
152     &nfsrv_enable_crossmntpt, 0, "Enable nfsd to cross mount points");
153 SYSCTL_INT(_vfs_nfsd, OID_AUTO, commit_blks, CTLFLAG_RW, &nfs_commit_blks,
154     0, "");
155 SYSCTL_INT(_vfs_nfsd, OID_AUTO, commit_miss, CTLFLAG_RW, &nfs_commit_miss,
156     0, "");
157 SYSCTL_INT(_vfs_nfsd, OID_AUTO, issue_delegations, CTLFLAG_RW,
158     &nfsrv_issuedelegs, 0, "Enable nfsd to issue delegations");
159 SYSCTL_INT(_vfs_nfsd, OID_AUTO, enable_locallocks, CTLFLAG_RW,
160     &nfsrv_dolocallocks, 0, "Enable nfsd to acquire local locks on files");
161 SYSCTL_INT(_vfs_nfsd, OID_AUTO, debuglevel, CTLFLAG_RW, &nfsd_debuglevel,
162     0, "Debug level for NFS server");
163 SYSCTL_INT(_vfs_nfsd, OID_AUTO, enable_stringtouid, CTLFLAG_RW,
164     &nfsd_enable_stringtouid, 0, "Enable nfsd to accept numeric owner_names");
165 static int nfsrv_pnfsgetdsattr = 1;
166 SYSCTL_INT(_vfs_nfsd, OID_AUTO, pnfsgetdsattr, CTLFLAG_RW,
167     &nfsrv_pnfsgetdsattr, 0, "When set getattr gets DS attributes via RPC");
168 
169 /*
170  * nfsrv_dsdirsize can only be increased and only when the nfsd threads are
171  * not running.
172  * The dsN subdirectories for the increased values must have been created
173  * on all DS servers before this increase is done.
174  */
175 u_int	nfsrv_dsdirsize = 20;
176 static int
177 sysctl_dsdirsize(SYSCTL_HANDLER_ARGS)
178 {
179 	int error, newdsdirsize;
180 
181 	newdsdirsize = nfsrv_dsdirsize;
182 	error = sysctl_handle_int(oidp, &newdsdirsize, 0, req);
183 	if (error != 0 || req->newptr == NULL)
184 		return (error);
185 	if (newdsdirsize <= nfsrv_dsdirsize || newdsdirsize > 10000 ||
186 	    newnfs_numnfsd != 0)
187 		return (EINVAL);
188 	nfsrv_dsdirsize = newdsdirsize;
189 	return (0);
190 }
191 SYSCTL_PROC(_vfs_nfsd, OID_AUTO, dsdirsize,
192     CTLTYPE_UINT | CTLFLAG_MPSAFE | CTLFLAG_RW, 0, sizeof(nfsrv_dsdirsize),
193     sysctl_dsdirsize, "IU", "Number of dsN subdirs on the DS servers");
194 
195 #define	MAX_REORDERED_RPC	16
196 #define	NUM_HEURISTIC		1031
197 #define	NHUSE_INIT		64
198 #define	NHUSE_INC		16
199 #define	NHUSE_MAX		2048
200 
201 static struct nfsheur {
202 	struct vnode *nh_vp;	/* vp to match (unreferenced pointer) */
203 	off_t nh_nextoff;	/* next offset for sequential detection */
204 	int nh_use;		/* use count for selection */
205 	int nh_seqcount;	/* heuristic */
206 } nfsheur[NUM_HEURISTIC];
207 
208 
209 /*
210  * Heuristic to detect sequential operation.
211  */
212 static struct nfsheur *
213 nfsrv_sequential_heuristic(struct uio *uio, struct vnode *vp)
214 {
215 	struct nfsheur *nh;
216 	int hi, try;
217 
218 	/* Locate best candidate. */
219 	try = 32;
220 	hi = ((int)(vm_offset_t)vp / sizeof(struct vnode)) % NUM_HEURISTIC;
221 	nh = &nfsheur[hi];
222 	while (try--) {
223 		if (nfsheur[hi].nh_vp == vp) {
224 			nh = &nfsheur[hi];
225 			break;
226 		}
227 		if (nfsheur[hi].nh_use > 0)
228 			--nfsheur[hi].nh_use;
229 		hi = (hi + 1) % NUM_HEURISTIC;
230 		if (nfsheur[hi].nh_use < nh->nh_use)
231 			nh = &nfsheur[hi];
232 	}
233 
234 	/* Initialize hint if this is a new file. */
235 	if (nh->nh_vp != vp) {
236 		nh->nh_vp = vp;
237 		nh->nh_nextoff = uio->uio_offset;
238 		nh->nh_use = NHUSE_INIT;
239 		if (uio->uio_offset == 0)
240 			nh->nh_seqcount = 4;
241 		else
242 			nh->nh_seqcount = 1;
243 	}
244 
245 	/* Calculate heuristic. */
246 	if ((uio->uio_offset == 0 && nh->nh_seqcount > 0) ||
247 	    uio->uio_offset == nh->nh_nextoff) {
248 		/* See comments in vfs_vnops.c:sequential_heuristic(). */
249 		nh->nh_seqcount += howmany(uio->uio_resid, 16384);
250 		if (nh->nh_seqcount > IO_SEQMAX)
251 			nh->nh_seqcount = IO_SEQMAX;
252 	} else if (qabs(uio->uio_offset - nh->nh_nextoff) <= MAX_REORDERED_RPC *
253 	    imax(vp->v_mount->mnt_stat.f_iosize, uio->uio_resid)) {
254 		/* Probably a reordered RPC, leave seqcount alone. */
255 	} else if (nh->nh_seqcount > 1) {
256 		nh->nh_seqcount /= 2;
257 	} else {
258 		nh->nh_seqcount = 0;
259 	}
260 	nh->nh_use += NHUSE_INC;
261 	if (nh->nh_use > NHUSE_MAX)
262 		nh->nh_use = NHUSE_MAX;
263 	return (nh);
264 }
265 
266 /*
267  * Get attributes into nfsvattr structure.
268  */
269 int
270 nfsvno_getattr(struct vnode *vp, struct nfsvattr *nvap,
271     struct nfsrv_descript *nd, struct thread *p, int vpislocked,
272     nfsattrbit_t *attrbitp)
273 {
274 	int error, gotattr, lockedit = 0;
275 	struct nfsvattr na;
276 
277 	if (vpislocked == 0) {
278 		/*
279 		 * When vpislocked == 0, the vnode is either exclusively
280 		 * locked by this thread or not locked by this thread.
281 		 * As such, shared lock it, if not exclusively locked.
282 		 */
283 		if (NFSVOPISLOCKED(vp) != LK_EXCLUSIVE) {
284 			lockedit = 1;
285 			NFSVOPLOCK(vp, LK_SHARED | LK_RETRY);
286 		}
287 	}
288 
289 	/*
290 	 * Acquire the Change, Size, TimeAccess, TimeModify and SpaceUsed
291 	 * attributes, as required.
292 	 * This needs to be done for regular files if:
293 	 * - non-NFSv4 RPCs or
294 	 * - when attrbitp == NULL or
295 	 * - an NFSv4 RPC with any of the above attributes in attrbitp.
296 	 * A return of 0 for nfsrv_proxyds() indicates that it has acquired
297 	 * these attributes.  nfsrv_proxyds() will return an error if the
298 	 * server is not a pNFS one.
299 	 */
300 	gotattr = 0;
301 	if (vp->v_type == VREG && nfsrv_devidcnt > 0 && (attrbitp == NULL ||
302 	    (nd->nd_flag & ND_NFSV4) == 0 ||
303 	    NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_CHANGE) ||
304 	    NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_SIZE) ||
305 	    NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_TIMEACCESS) ||
306 	    NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_TIMEMODIFY) ||
307 	    NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_SPACEUSED))) {
308 		error = nfsrv_proxyds(vp, 0, 0, nd->nd_cred, p,
309 		    NFSPROC_GETATTR, NULL, NULL, NULL, &na, NULL, NULL, 0,
310 		    NULL);
311 		if (error == 0)
312 			gotattr = 1;
313 	}
314 
315 	error = VOP_GETATTR(vp, &nvap->na_vattr, nd->nd_cred);
316 	if (lockedit != 0)
317 		NFSVOPUNLOCK(vp);
318 
319 	/*
320 	 * If we got the Change, Size and Modify Time from the DS,
321 	 * replace them.
322 	 */
323 	if (gotattr != 0) {
324 		nvap->na_atime = na.na_atime;
325 		nvap->na_mtime = na.na_mtime;
326 		nvap->na_filerev = na.na_filerev;
327 		nvap->na_size = na.na_size;
328 		nvap->na_bytes = na.na_bytes;
329 	}
330 	NFSD_DEBUG(4, "nfsvno_getattr: gotattr=%d err=%d chg=%ju\n", gotattr,
331 	    error, (uintmax_t)na.na_filerev);
332 
333 	NFSEXITCODE(error);
334 	return (error);
335 }
336 
337 /*
338  * Get a file handle for a vnode.
339  */
340 int
341 nfsvno_getfh(struct vnode *vp, fhandle_t *fhp, struct thread *p)
342 {
343 	int error;
344 
345 	NFSBZERO((caddr_t)fhp, sizeof(fhandle_t));
346 	fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
347 	error = VOP_VPTOFH(vp, &fhp->fh_fid);
348 
349 	NFSEXITCODE(error);
350 	return (error);
351 }
352 
353 /*
354  * Perform access checking for vnodes obtained from file handles that would
355  * refer to files already opened by a Unix client. You cannot just use
356  * vn_writechk() and VOP_ACCESSX() for two reasons.
357  * 1 - You must check for exported rdonly as well as MNT_RDONLY for the write
358  *     case.
359  * 2 - The owner is to be given access irrespective of mode bits for some
360  *     operations, so that processes that chmod after opening a file don't
361  *     break.
362  */
363 int
364 nfsvno_accchk(struct vnode *vp, accmode_t accmode, struct ucred *cred,
365     struct nfsexstuff *exp, struct thread *p, int override, int vpislocked,
366     u_int32_t *supportedtypep)
367 {
368 	struct vattr vattr;
369 	int error = 0, getret = 0;
370 
371 	if (vpislocked == 0) {
372 		if (NFSVOPLOCK(vp, LK_SHARED) != 0) {
373 			error = EPERM;
374 			goto out;
375 		}
376 	}
377 	if (accmode & VWRITE) {
378 		/* Just vn_writechk() changed to check rdonly */
379 		/*
380 		 * Disallow write attempts on read-only file systems;
381 		 * unless the file is a socket or a block or character
382 		 * device resident on the file system.
383 		 */
384 		if (NFSVNO_EXRDONLY(exp) ||
385 		    (vp->v_mount->mnt_flag & MNT_RDONLY)) {
386 			switch (vp->v_type) {
387 			case VREG:
388 			case VDIR:
389 			case VLNK:
390 				error = EROFS;
391 			default:
392 				break;
393 			}
394 		}
395 		/*
396 		 * If there's shared text associated with
397 		 * the inode, try to free it up once.  If
398 		 * we fail, we can't allow writing.
399 		 */
400 		if (VOP_IS_TEXT(vp) && error == 0)
401 			error = ETXTBSY;
402 	}
403 	if (error != 0) {
404 		if (vpislocked == 0)
405 			NFSVOPUNLOCK(vp);
406 		goto out;
407 	}
408 
409 	/*
410 	 * Should the override still be applied when ACLs are enabled?
411 	 */
412 	error = VOP_ACCESSX(vp, accmode, cred, p);
413 	if (error != 0 && (accmode & (VDELETE | VDELETE_CHILD))) {
414 		/*
415 		 * Try again with VEXPLICIT_DENY, to see if the test for
416 		 * deletion is supported.
417 		 */
418 		error = VOP_ACCESSX(vp, accmode | VEXPLICIT_DENY, cred, p);
419 		if (error == 0) {
420 			if (vp->v_type == VDIR) {
421 				accmode &= ~(VDELETE | VDELETE_CHILD);
422 				accmode |= VWRITE;
423 				error = VOP_ACCESSX(vp, accmode, cred, p);
424 			} else if (supportedtypep != NULL) {
425 				*supportedtypep &= ~NFSACCESS_DELETE;
426 			}
427 		}
428 	}
429 
430 	/*
431 	 * Allow certain operations for the owner (reads and writes
432 	 * on files that are already open).
433 	 */
434 	if (override != NFSACCCHK_NOOVERRIDE &&
435 	    (error == EPERM || error == EACCES)) {
436 		if (cred->cr_uid == 0 && (override & NFSACCCHK_ALLOWROOT))
437 			error = 0;
438 		else if (override & NFSACCCHK_ALLOWOWNER) {
439 			getret = VOP_GETATTR(vp, &vattr, cred);
440 			if (getret == 0 && cred->cr_uid == vattr.va_uid)
441 				error = 0;
442 		}
443 	}
444 	if (vpislocked == 0)
445 		NFSVOPUNLOCK(vp);
446 
447 out:
448 	NFSEXITCODE(error);
449 	return (error);
450 }
451 
452 /*
453  * Set attribute(s) vnop.
454  */
455 int
456 nfsvno_setattr(struct vnode *vp, struct nfsvattr *nvap, struct ucred *cred,
457     struct thread *p, struct nfsexstuff *exp)
458 {
459 	u_quad_t savsize = 0;
460 	int error, savedit;
461 
462 	/*
463 	 * If this is an exported file system and a pNFS service is running,
464 	 * don't VOP_SETATTR() of size for the MDS file system.
465 	 */
466 	savedit = 0;
467 	error = 0;
468 	if (vp->v_type == VREG && (vp->v_mount->mnt_flag & MNT_EXPORTED) != 0 &&
469 	    nfsrv_devidcnt != 0 && nvap->na_vattr.va_size != VNOVAL &&
470 	    nvap->na_vattr.va_size > 0) {
471 		savsize = nvap->na_vattr.va_size;
472 		nvap->na_vattr.va_size = VNOVAL;
473 		if (nvap->na_vattr.va_uid != (uid_t)VNOVAL ||
474 		    nvap->na_vattr.va_gid != (gid_t)VNOVAL ||
475 		    nvap->na_vattr.va_mode != (mode_t)VNOVAL ||
476 		    nvap->na_vattr.va_atime.tv_sec != VNOVAL ||
477 		    nvap->na_vattr.va_mtime.tv_sec != VNOVAL)
478 			savedit = 1;
479 		else
480 			savedit = 2;
481 	}
482 	if (savedit != 2)
483 		error = VOP_SETATTR(vp, &nvap->na_vattr, cred);
484 	if (savedit != 0)
485 		nvap->na_vattr.va_size = savsize;
486 	if (error == 0 && (nvap->na_vattr.va_uid != (uid_t)VNOVAL ||
487 	    nvap->na_vattr.va_gid != (gid_t)VNOVAL ||
488 	    nvap->na_vattr.va_size != VNOVAL ||
489 	    nvap->na_vattr.va_mode != (mode_t)VNOVAL ||
490 	    nvap->na_vattr.va_atime.tv_sec != VNOVAL ||
491 	    nvap->na_vattr.va_mtime.tv_sec != VNOVAL)) {
492 		/* For a pNFS server, set the attributes on the DS file. */
493 		error = nfsrv_proxyds(vp, 0, 0, cred, p, NFSPROC_SETATTR,
494 		    NULL, NULL, NULL, nvap, NULL, NULL, 0, NULL);
495 		if (error == ENOENT)
496 			error = 0;
497 	}
498 	NFSEXITCODE(error);
499 	return (error);
500 }
501 
502 /*
503  * Set up nameidata for a lookup() call and do it.
504  */
505 int
506 nfsvno_namei(struct nfsrv_descript *nd, struct nameidata *ndp,
507     struct vnode *dp, int islocked, struct nfsexstuff *exp, struct thread *p,
508     struct vnode **retdirp)
509 {
510 	struct componentname *cnp = &ndp->ni_cnd;
511 	int i;
512 	struct iovec aiov;
513 	struct uio auio;
514 	int lockleaf = (cnp->cn_flags & LOCKLEAF) != 0, linklen;
515 	int error = 0;
516 	char *cp;
517 
518 	*retdirp = NULL;
519 	cnp->cn_nameptr = cnp->cn_pnbuf;
520 	ndp->ni_lcf = 0;
521 	/*
522 	 * Extract and set starting directory.
523 	 */
524 	if (dp->v_type != VDIR) {
525 		if (islocked)
526 			vput(dp);
527 		else
528 			vrele(dp);
529 		nfsvno_relpathbuf(ndp);
530 		error = ENOTDIR;
531 		goto out1;
532 	}
533 	if (islocked)
534 		NFSVOPUNLOCK(dp);
535 	VREF(dp);
536 	*retdirp = dp;
537 	if (NFSVNO_EXRDONLY(exp))
538 		cnp->cn_flags |= RDONLY;
539 	ndp->ni_segflg = UIO_SYSSPACE;
540 
541 	if (nd->nd_flag & ND_PUBLOOKUP) {
542 		ndp->ni_loopcnt = 0;
543 		if (cnp->cn_pnbuf[0] == '/') {
544 			vrele(dp);
545 			/*
546 			 * Check for degenerate pathnames here, since lookup()
547 			 * panics on them.
548 			 */
549 			for (i = 1; i < ndp->ni_pathlen; i++)
550 				if (cnp->cn_pnbuf[i] != '/')
551 					break;
552 			if (i == ndp->ni_pathlen) {
553 				error = NFSERR_ACCES;
554 				goto out;
555 			}
556 			dp = rootvnode;
557 			VREF(dp);
558 		}
559 	} else if ((nfsrv_enable_crossmntpt == 0 && NFSVNO_EXPORTED(exp)) ||
560 	    (nd->nd_flag & ND_NFSV4) == 0) {
561 		/*
562 		 * Only cross mount points for NFSv4 when doing a
563 		 * mount while traversing the file system above
564 		 * the mount point, unless nfsrv_enable_crossmntpt is set.
565 		 */
566 		cnp->cn_flags |= NOCROSSMOUNT;
567 	}
568 
569 	/*
570 	 * Initialize for scan, set ni_startdir and bump ref on dp again
571 	 * because lookup() will dereference ni_startdir.
572 	 */
573 
574 	cnp->cn_thread = p;
575 	ndp->ni_startdir = dp;
576 	ndp->ni_rootdir = rootvnode;
577 	ndp->ni_topdir = NULL;
578 
579 	if (!lockleaf)
580 		cnp->cn_flags |= LOCKLEAF;
581 	for (;;) {
582 		cnp->cn_nameptr = cnp->cn_pnbuf;
583 		/*
584 		 * Call lookup() to do the real work.  If an error occurs,
585 		 * ndp->ni_vp and ni_dvp are left uninitialized or NULL and
586 		 * we do not have to dereference anything before returning.
587 		 * In either case ni_startdir will be dereferenced and NULLed
588 		 * out.
589 		 */
590 		error = lookup(ndp);
591 		if (error)
592 			break;
593 
594 		/*
595 		 * Check for encountering a symbolic link.  Trivial
596 		 * termination occurs if no symlink encountered.
597 		 */
598 		if ((cnp->cn_flags & ISSYMLINK) == 0) {
599 			if ((cnp->cn_flags & (SAVENAME | SAVESTART)) == 0)
600 				nfsvno_relpathbuf(ndp);
601 			if (ndp->ni_vp && !lockleaf)
602 				NFSVOPUNLOCK(ndp->ni_vp);
603 			break;
604 		}
605 
606 		/*
607 		 * Validate symlink
608 		 */
609 		if ((cnp->cn_flags & LOCKPARENT) && ndp->ni_pathlen == 1)
610 			NFSVOPUNLOCK(ndp->ni_dvp);
611 		if (!(nd->nd_flag & ND_PUBLOOKUP)) {
612 			error = EINVAL;
613 			goto badlink2;
614 		}
615 
616 		if (ndp->ni_loopcnt++ >= MAXSYMLINKS) {
617 			error = ELOOP;
618 			goto badlink2;
619 		}
620 		if (ndp->ni_pathlen > 1)
621 			cp = uma_zalloc(namei_zone, M_WAITOK);
622 		else
623 			cp = cnp->cn_pnbuf;
624 		aiov.iov_base = cp;
625 		aiov.iov_len = MAXPATHLEN;
626 		auio.uio_iov = &aiov;
627 		auio.uio_iovcnt = 1;
628 		auio.uio_offset = 0;
629 		auio.uio_rw = UIO_READ;
630 		auio.uio_segflg = UIO_SYSSPACE;
631 		auio.uio_td = NULL;
632 		auio.uio_resid = MAXPATHLEN;
633 		error = VOP_READLINK(ndp->ni_vp, &auio, cnp->cn_cred);
634 		if (error) {
635 		badlink1:
636 			if (ndp->ni_pathlen > 1)
637 				uma_zfree(namei_zone, cp);
638 		badlink2:
639 			vrele(ndp->ni_dvp);
640 			vput(ndp->ni_vp);
641 			break;
642 		}
643 		linklen = MAXPATHLEN - auio.uio_resid;
644 		if (linklen == 0) {
645 			error = ENOENT;
646 			goto badlink1;
647 		}
648 		if (linklen + ndp->ni_pathlen >= MAXPATHLEN) {
649 			error = ENAMETOOLONG;
650 			goto badlink1;
651 		}
652 
653 		/*
654 		 * Adjust or replace path
655 		 */
656 		if (ndp->ni_pathlen > 1) {
657 			NFSBCOPY(ndp->ni_next, cp + linklen, ndp->ni_pathlen);
658 			uma_zfree(namei_zone, cnp->cn_pnbuf);
659 			cnp->cn_pnbuf = cp;
660 		} else
661 			cnp->cn_pnbuf[linklen] = '\0';
662 		ndp->ni_pathlen += linklen;
663 
664 		/*
665 		 * Cleanup refs for next loop and check if root directory
666 		 * should replace current directory.  Normally ni_dvp
667 		 * becomes the new base directory and is cleaned up when
668 		 * we loop.  Explicitly null pointers after invalidation
669 		 * to clarify operation.
670 		 */
671 		vput(ndp->ni_vp);
672 		ndp->ni_vp = NULL;
673 
674 		if (cnp->cn_pnbuf[0] == '/') {
675 			vrele(ndp->ni_dvp);
676 			ndp->ni_dvp = ndp->ni_rootdir;
677 			VREF(ndp->ni_dvp);
678 		}
679 		ndp->ni_startdir = ndp->ni_dvp;
680 		ndp->ni_dvp = NULL;
681 	}
682 	if (!lockleaf)
683 		cnp->cn_flags &= ~LOCKLEAF;
684 
685 out:
686 	if (error) {
687 		nfsvno_relpathbuf(ndp);
688 		ndp->ni_vp = NULL;
689 		ndp->ni_dvp = NULL;
690 		ndp->ni_startdir = NULL;
691 	} else if ((ndp->ni_cnd.cn_flags & (WANTPARENT|LOCKPARENT)) == 0) {
692 		ndp->ni_dvp = NULL;
693 	}
694 
695 out1:
696 	NFSEXITCODE2(error, nd);
697 	return (error);
698 }
699 
700 /*
701  * Set up a pathname buffer and return a pointer to it and, optionally
702  * set a hash pointer.
703  */
704 void
705 nfsvno_setpathbuf(struct nameidata *ndp, char **bufpp, u_long **hashpp)
706 {
707 	struct componentname *cnp = &ndp->ni_cnd;
708 
709 	cnp->cn_flags |= (NOMACCHECK | HASBUF);
710 	cnp->cn_pnbuf = uma_zalloc(namei_zone, M_WAITOK);
711 	if (hashpp != NULL)
712 		*hashpp = NULL;
713 	*bufpp = cnp->cn_pnbuf;
714 }
715 
716 /*
717  * Release the above path buffer, if not released by nfsvno_namei().
718  */
719 void
720 nfsvno_relpathbuf(struct nameidata *ndp)
721 {
722 
723 	if ((ndp->ni_cnd.cn_flags & HASBUF) == 0)
724 		panic("nfsrelpath");
725 	uma_zfree(namei_zone, ndp->ni_cnd.cn_pnbuf);
726 	ndp->ni_cnd.cn_flags &= ~HASBUF;
727 }
728 
729 /*
730  * Readlink vnode op into an mbuf list.
731  */
732 int
733 nfsvno_readlink(struct vnode *vp, struct ucred *cred, struct thread *p,
734     struct mbuf **mpp, struct mbuf **mpendp, int *lenp)
735 {
736 	struct iovec *iv;
737 	struct uio io, *uiop = &io;
738 	struct mbuf *mp, *mp3;
739 	int len, tlen, error = 0;
740 
741 	len = NFS_MAXPATHLEN;
742 	uiop->uio_iovcnt = nfsrv_createiovec(len, &mp3, &mp, &iv);
743 	uiop->uio_iov = iv;
744 	uiop->uio_offset = 0;
745 	uiop->uio_resid = len;
746 	uiop->uio_rw = UIO_READ;
747 	uiop->uio_segflg = UIO_SYSSPACE;
748 	uiop->uio_td = NULL;
749 	error = VOP_READLINK(vp, uiop, cred);
750 	free(iv, M_TEMP);
751 	if (error) {
752 		m_freem(mp3);
753 		*lenp = 0;
754 		goto out;
755 	}
756 	if (uiop->uio_resid > 0) {
757 		len -= uiop->uio_resid;
758 		tlen = NFSM_RNDUP(len);
759 		nfsrv_adj(mp3, NFS_MAXPATHLEN - tlen, tlen - len);
760 	}
761 	*lenp = len;
762 	*mpp = mp3;
763 	*mpendp = mp;
764 
765 out:
766 	NFSEXITCODE(error);
767 	return (error);
768 }
769 
770 /*
771  * Create an mbuf chain and an associated iovec that can be used to Read
772  * or Getextattr of data.
773  * Upon success, return pointers to the first and last mbufs in the chain
774  * plus the malloc'd iovec and its iovlen.
775  */
776 static int
777 nfsrv_createiovec(int len, struct mbuf **mpp, struct mbuf **mpendp,
778     struct iovec **ivp)
779 {
780 	struct mbuf *m, *m2 = NULL, *m3;
781 	struct iovec *iv;
782 	int i, left, siz;
783 
784 	left = len;
785 	m3 = NULL;
786 	/*
787 	 * Generate the mbuf list with the uio_iov ref. to it.
788 	 */
789 	i = 0;
790 	while (left > 0) {
791 		NFSMGET(m);
792 		MCLGET(m, M_WAITOK);
793 		m->m_len = 0;
794 		siz = min(M_TRAILINGSPACE(m), left);
795 		left -= siz;
796 		i++;
797 		if (m3)
798 			m2->m_next = m;
799 		else
800 			m3 = m;
801 		m2 = m;
802 	}
803 	*ivp = iv = malloc(i * sizeof (struct iovec), M_TEMP, M_WAITOK);
804 	m = m3;
805 	left = len;
806 	i = 0;
807 	while (left > 0) {
808 		if (m == NULL)
809 			panic("nfsvno_read iov");
810 		siz = min(M_TRAILINGSPACE(m), left);
811 		if (siz > 0) {
812 			iv->iov_base = mtod(m, caddr_t) + m->m_len;
813 			iv->iov_len = siz;
814 			m->m_len += siz;
815 			left -= siz;
816 			iv++;
817 			i++;
818 		}
819 		m = m->m_next;
820 	}
821 	*mpp = m3;
822 	*mpendp = m2;
823 	return (i);
824 }
825 
826 /*
827  * Read vnode op call into mbuf list.
828  */
829 int
830 nfsvno_read(struct vnode *vp, off_t off, int cnt, struct ucred *cred,
831     struct thread *p, struct mbuf **mpp, struct mbuf **mpendp)
832 {
833 	struct mbuf *m;
834 	struct iovec *iv;
835 	int error = 0, len, tlen, ioflag = 0;
836 	struct mbuf *m3;
837 	struct uio io, *uiop = &io;
838 	struct nfsheur *nh;
839 
840 	/*
841 	 * Attempt to read from a DS file. A return of ENOENT implies
842 	 * there is no DS file to read.
843 	 */
844 	error = nfsrv_proxyds(vp, off, cnt, cred, p, NFSPROC_READDS, mpp,
845 	    NULL, mpendp, NULL, NULL, NULL, 0, NULL);
846 	if (error != ENOENT)
847 		return (error);
848 
849 	len = NFSM_RNDUP(cnt);
850 	uiop->uio_iovcnt = nfsrv_createiovec(len, &m3, &m, &iv);
851 	uiop->uio_iov = iv;
852 	uiop->uio_offset = off;
853 	uiop->uio_resid = len;
854 	uiop->uio_rw = UIO_READ;
855 	uiop->uio_segflg = UIO_SYSSPACE;
856 	uiop->uio_td = NULL;
857 	nh = nfsrv_sequential_heuristic(uiop, vp);
858 	ioflag |= nh->nh_seqcount << IO_SEQSHIFT;
859 	/* XXX KDM make this more systematic? */
860 	nfsstatsv1.srvbytes[NFSV4OP_READ] += uiop->uio_resid;
861 	error = VOP_READ(vp, uiop, IO_NODELOCKED | ioflag, cred);
862 	free(iv, M_TEMP);
863 	if (error) {
864 		m_freem(m3);
865 		*mpp = NULL;
866 		goto out;
867 	}
868 	nh->nh_nextoff = uiop->uio_offset;
869 	tlen = len - uiop->uio_resid;
870 	cnt = cnt < tlen ? cnt : tlen;
871 	tlen = NFSM_RNDUP(cnt);
872 	if (tlen == 0) {
873 		m_freem(m3);
874 		m3 = NULL;
875 	} else if (len != tlen || tlen != cnt)
876 		nfsrv_adj(m3, len - tlen, tlen - cnt);
877 	*mpp = m3;
878 	*mpendp = m;
879 
880 out:
881 	NFSEXITCODE(error);
882 	return (error);
883 }
884 
885 /*
886  * Create the iovec for the mbuf chain passed in as an argument.
887  * The "cp" argument is where the data starts within the first mbuf in
888  * the chain. It returns the iovec and the iovcnt.
889  */
890 static int
891 nfsrv_createiovecw(int retlen, struct mbuf *m, char *cp, struct iovec **ivpp,
892     int *iovcntp)
893 {
894 	struct mbuf *mp;
895 	struct iovec *ivp;
896 	int cnt, i, len;
897 
898 	/*
899 	 * Loop through the mbuf chain, counting how many mbufs are a
900 	 * part of this write operation, so the iovec size is known.
901 	 */
902 	cnt = 0;
903 	len = retlen;
904 	mp = m;
905 	i = mtod(mp, caddr_t) + mbuf_len(mp) - cp;
906 	while (len > 0) {
907 		if (i > 0) {
908 			len -= i;
909 			cnt++;
910 		}
911 		mp = mbuf_next(mp);
912 		if (!mp) {
913 			if (len > 0)
914 				return (EBADRPC);
915 		} else
916 			i = mbuf_len(mp);
917 	}
918 
919 	/* Now, create the iovec. */
920 	mp = m;
921 	*ivpp = ivp = malloc(cnt * sizeof (struct iovec), M_TEMP,
922 	    M_WAITOK);
923 	*iovcntp = cnt;
924 	i = mtod(mp, caddr_t) + mp->m_len - cp;
925 	len = retlen;
926 	while (len > 0) {
927 		if (mp == NULL)
928 			panic("nfsvno_write");
929 		if (i > 0) {
930 			i = min(i, len);
931 			ivp->iov_base = cp;
932 			ivp->iov_len = i;
933 			ivp++;
934 			len -= i;
935 		}
936 		mp = mp->m_next;
937 		if (mp) {
938 			i = mp->m_len;
939 			cp = mtod(mp, caddr_t);
940 		}
941 	}
942 	return (0);
943 }
944 
945 /*
946  * Write vnode op from an mbuf list.
947  */
948 int
949 nfsvno_write(struct vnode *vp, off_t off, int retlen, int *stable,
950     struct mbuf *mp, char *cp, struct ucred *cred, struct thread *p)
951 {
952 	struct iovec *iv;
953 	int cnt, ioflags, error;
954 	struct uio io, *uiop = &io;
955 	struct nfsheur *nh;
956 
957 	/*
958 	 * Attempt to write to a DS file. A return of ENOENT implies
959 	 * there is no DS file to write.
960 	 */
961 	error = nfsrv_proxyds(vp, off, retlen, cred, p, NFSPROC_WRITEDS,
962 	    &mp, cp, NULL, NULL, NULL, NULL, 0, NULL);
963 	if (error != ENOENT) {
964 		*stable = NFSWRITE_FILESYNC;
965 		return (error);
966 	}
967 
968 
969 	if (*stable == NFSWRITE_UNSTABLE)
970 		ioflags = IO_NODELOCKED;
971 	else
972 		ioflags = (IO_SYNC | IO_NODELOCKED);
973 	error = nfsrv_createiovecw(retlen, mp, cp, &iv, &cnt);
974 	if (error != 0)
975 		return (error);
976 	uiop->uio_iov = iv;
977 	uiop->uio_iovcnt = cnt;
978 	uiop->uio_resid = retlen;
979 	uiop->uio_rw = UIO_WRITE;
980 	uiop->uio_segflg = UIO_SYSSPACE;
981 	NFSUIOPROC(uiop, p);
982 	uiop->uio_offset = off;
983 	nh = nfsrv_sequential_heuristic(uiop, vp);
984 	ioflags |= nh->nh_seqcount << IO_SEQSHIFT;
985 	/* XXX KDM make this more systematic? */
986 	nfsstatsv1.srvbytes[NFSV4OP_WRITE] += uiop->uio_resid;
987 	error = VOP_WRITE(vp, uiop, ioflags, cred);
988 	if (error == 0)
989 		nh->nh_nextoff = uiop->uio_offset;
990 	free(iv, M_TEMP);
991 
992 	NFSEXITCODE(error);
993 	return (error);
994 }
995 
996 /*
997  * Common code for creating a regular file (plus special files for V2).
998  */
999 int
1000 nfsvno_createsub(struct nfsrv_descript *nd, struct nameidata *ndp,
1001     struct vnode **vpp, struct nfsvattr *nvap, int *exclusive_flagp,
1002     int32_t *cverf, NFSDEV_T rdev, struct nfsexstuff *exp)
1003 {
1004 	u_quad_t tempsize;
1005 	int error;
1006 	struct thread *p = curthread;
1007 
1008 	error = nd->nd_repstat;
1009 	if (!error && ndp->ni_vp == NULL) {
1010 		if (nvap->na_type == VREG || nvap->na_type == VSOCK) {
1011 			vrele(ndp->ni_startdir);
1012 			error = VOP_CREATE(ndp->ni_dvp,
1013 			    &ndp->ni_vp, &ndp->ni_cnd, &nvap->na_vattr);
1014 			/* For a pNFS server, create the data file on a DS. */
1015 			if (error == 0 && nvap->na_type == VREG) {
1016 				/*
1017 				 * Create a data file on a DS for a pNFS server.
1018 				 * This function just returns if not
1019 				 * running a pNFS DS or the creation fails.
1020 				 */
1021 				nfsrv_pnfscreate(ndp->ni_vp, &nvap->na_vattr,
1022 				    nd->nd_cred, p);
1023 			}
1024 			vput(ndp->ni_dvp);
1025 			nfsvno_relpathbuf(ndp);
1026 			if (!error) {
1027 				if (*exclusive_flagp) {
1028 					*exclusive_flagp = 0;
1029 					NFSVNO_ATTRINIT(nvap);
1030 					nvap->na_atime.tv_sec = cverf[0];
1031 					nvap->na_atime.tv_nsec = cverf[1];
1032 					error = VOP_SETATTR(ndp->ni_vp,
1033 					    &nvap->na_vattr, nd->nd_cred);
1034 					if (error != 0) {
1035 						vput(ndp->ni_vp);
1036 						ndp->ni_vp = NULL;
1037 						error = NFSERR_NOTSUPP;
1038 					}
1039 				}
1040 			}
1041 		/*
1042 		 * NFS V2 Only. nfsrvd_mknod() does this for V3.
1043 		 * (This implies, just get out on an error.)
1044 		 */
1045 		} else if (nvap->na_type == VCHR || nvap->na_type == VBLK ||
1046 			nvap->na_type == VFIFO) {
1047 			if (nvap->na_type == VCHR && rdev == 0xffffffff)
1048 				nvap->na_type = VFIFO;
1049                         if (nvap->na_type != VFIFO &&
1050 			    (error = priv_check_cred(nd->nd_cred, PRIV_VFS_MKNOD_DEV))) {
1051 				vrele(ndp->ni_startdir);
1052 				nfsvno_relpathbuf(ndp);
1053 				vput(ndp->ni_dvp);
1054 				goto out;
1055 			}
1056 			nvap->na_rdev = rdev;
1057 			error = VOP_MKNOD(ndp->ni_dvp, &ndp->ni_vp,
1058 			    &ndp->ni_cnd, &nvap->na_vattr);
1059 			vput(ndp->ni_dvp);
1060 			nfsvno_relpathbuf(ndp);
1061 			vrele(ndp->ni_startdir);
1062 			if (error)
1063 				goto out;
1064 		} else {
1065 			vrele(ndp->ni_startdir);
1066 			nfsvno_relpathbuf(ndp);
1067 			vput(ndp->ni_dvp);
1068 			error = ENXIO;
1069 			goto out;
1070 		}
1071 		*vpp = ndp->ni_vp;
1072 	} else {
1073 		/*
1074 		 * Handle cases where error is already set and/or
1075 		 * the file exists.
1076 		 * 1 - clean up the lookup
1077 		 * 2 - iff !error and na_size set, truncate it
1078 		 */
1079 		vrele(ndp->ni_startdir);
1080 		nfsvno_relpathbuf(ndp);
1081 		*vpp = ndp->ni_vp;
1082 		if (ndp->ni_dvp == *vpp)
1083 			vrele(ndp->ni_dvp);
1084 		else
1085 			vput(ndp->ni_dvp);
1086 		if (!error && nvap->na_size != VNOVAL) {
1087 			error = nfsvno_accchk(*vpp, VWRITE,
1088 			    nd->nd_cred, exp, p, NFSACCCHK_NOOVERRIDE,
1089 			    NFSACCCHK_VPISLOCKED, NULL);
1090 			if (!error) {
1091 				tempsize = nvap->na_size;
1092 				NFSVNO_ATTRINIT(nvap);
1093 				nvap->na_size = tempsize;
1094 				error = VOP_SETATTR(*vpp,
1095 				    &nvap->na_vattr, nd->nd_cred);
1096 			}
1097 		}
1098 		if (error)
1099 			vput(*vpp);
1100 	}
1101 
1102 out:
1103 	NFSEXITCODE(error);
1104 	return (error);
1105 }
1106 
1107 /*
1108  * Do a mknod vnode op.
1109  */
1110 int
1111 nfsvno_mknod(struct nameidata *ndp, struct nfsvattr *nvap, struct ucred *cred,
1112     struct thread *p)
1113 {
1114 	int error = 0;
1115 	enum vtype vtyp;
1116 
1117 	vtyp = nvap->na_type;
1118 	/*
1119 	 * Iff doesn't exist, create it.
1120 	 */
1121 	if (ndp->ni_vp) {
1122 		vrele(ndp->ni_startdir);
1123 		nfsvno_relpathbuf(ndp);
1124 		vput(ndp->ni_dvp);
1125 		vrele(ndp->ni_vp);
1126 		error = EEXIST;
1127 		goto out;
1128 	}
1129 	if (vtyp != VCHR && vtyp != VBLK && vtyp != VSOCK && vtyp != VFIFO) {
1130 		vrele(ndp->ni_startdir);
1131 		nfsvno_relpathbuf(ndp);
1132 		vput(ndp->ni_dvp);
1133 		error = NFSERR_BADTYPE;
1134 		goto out;
1135 	}
1136 	if (vtyp == VSOCK) {
1137 		vrele(ndp->ni_startdir);
1138 		error = VOP_CREATE(ndp->ni_dvp, &ndp->ni_vp,
1139 		    &ndp->ni_cnd, &nvap->na_vattr);
1140 		vput(ndp->ni_dvp);
1141 		nfsvno_relpathbuf(ndp);
1142 	} else {
1143 		if (nvap->na_type != VFIFO &&
1144 		    (error = priv_check_cred(cred, PRIV_VFS_MKNOD_DEV))) {
1145 			vrele(ndp->ni_startdir);
1146 			nfsvno_relpathbuf(ndp);
1147 			vput(ndp->ni_dvp);
1148 			goto out;
1149 		}
1150 		error = VOP_MKNOD(ndp->ni_dvp, &ndp->ni_vp,
1151 		    &ndp->ni_cnd, &nvap->na_vattr);
1152 		vput(ndp->ni_dvp);
1153 		nfsvno_relpathbuf(ndp);
1154 		vrele(ndp->ni_startdir);
1155 		/*
1156 		 * Since VOP_MKNOD returns the ni_vp, I can't
1157 		 * see any reason to do the lookup.
1158 		 */
1159 	}
1160 
1161 out:
1162 	NFSEXITCODE(error);
1163 	return (error);
1164 }
1165 
1166 /*
1167  * Mkdir vnode op.
1168  */
1169 int
1170 nfsvno_mkdir(struct nameidata *ndp, struct nfsvattr *nvap, uid_t saved_uid,
1171     struct ucred *cred, struct thread *p, struct nfsexstuff *exp)
1172 {
1173 	int error = 0;
1174 
1175 	if (ndp->ni_vp != NULL) {
1176 		if (ndp->ni_dvp == ndp->ni_vp)
1177 			vrele(ndp->ni_dvp);
1178 		else
1179 			vput(ndp->ni_dvp);
1180 		vrele(ndp->ni_vp);
1181 		nfsvno_relpathbuf(ndp);
1182 		error = EEXIST;
1183 		goto out;
1184 	}
1185 	error = VOP_MKDIR(ndp->ni_dvp, &ndp->ni_vp, &ndp->ni_cnd,
1186 	    &nvap->na_vattr);
1187 	vput(ndp->ni_dvp);
1188 	nfsvno_relpathbuf(ndp);
1189 
1190 out:
1191 	NFSEXITCODE(error);
1192 	return (error);
1193 }
1194 
1195 /*
1196  * symlink vnode op.
1197  */
1198 int
1199 nfsvno_symlink(struct nameidata *ndp, struct nfsvattr *nvap, char *pathcp,
1200     int pathlen, int not_v2, uid_t saved_uid, struct ucred *cred, struct thread *p,
1201     struct nfsexstuff *exp)
1202 {
1203 	int error = 0;
1204 
1205 	if (ndp->ni_vp) {
1206 		vrele(ndp->ni_startdir);
1207 		nfsvno_relpathbuf(ndp);
1208 		if (ndp->ni_dvp == ndp->ni_vp)
1209 			vrele(ndp->ni_dvp);
1210 		else
1211 			vput(ndp->ni_dvp);
1212 		vrele(ndp->ni_vp);
1213 		error = EEXIST;
1214 		goto out;
1215 	}
1216 
1217 	error = VOP_SYMLINK(ndp->ni_dvp, &ndp->ni_vp, &ndp->ni_cnd,
1218 	    &nvap->na_vattr, pathcp);
1219 	vput(ndp->ni_dvp);
1220 	vrele(ndp->ni_startdir);
1221 	nfsvno_relpathbuf(ndp);
1222 	/*
1223 	 * Although FreeBSD still had the lookup code in
1224 	 * it for 7/current, there doesn't seem to be any
1225 	 * point, since VOP_SYMLINK() returns the ni_vp.
1226 	 * Just vput it for v2.
1227 	 */
1228 	if (!not_v2 && !error)
1229 		vput(ndp->ni_vp);
1230 
1231 out:
1232 	NFSEXITCODE(error);
1233 	return (error);
1234 }
1235 
1236 /*
1237  * Parse symbolic link arguments.
1238  * This function has an ugly side effect. It will malloc() an area for
1239  * the symlink and set iov_base to point to it, only if it succeeds.
1240  * So, if it returns with uiop->uio_iov->iov_base != NULL, that must
1241  * be FREE'd later.
1242  */
1243 int
1244 nfsvno_getsymlink(struct nfsrv_descript *nd, struct nfsvattr *nvap,
1245     struct thread *p, char **pathcpp, int *lenp)
1246 {
1247 	u_int32_t *tl;
1248 	char *pathcp = NULL;
1249 	int error = 0, len;
1250 	struct nfsv2_sattr *sp;
1251 
1252 	*pathcpp = NULL;
1253 	*lenp = 0;
1254 	if ((nd->nd_flag & ND_NFSV3) &&
1255 	    (error = nfsrv_sattr(nd, NULL, nvap, NULL, NULL, p)))
1256 		goto nfsmout;
1257 	NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
1258 	len = fxdr_unsigned(int, *tl);
1259 	if (len > NFS_MAXPATHLEN || len <= 0) {
1260 		error = EBADRPC;
1261 		goto nfsmout;
1262 	}
1263 	pathcp = malloc(len + 1, M_TEMP, M_WAITOK);
1264 	error = nfsrv_mtostr(nd, pathcp, len);
1265 	if (error)
1266 		goto nfsmout;
1267 	if (nd->nd_flag & ND_NFSV2) {
1268 		NFSM_DISSECT(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
1269 		nvap->na_mode = fxdr_unsigned(u_int16_t, sp->sa_mode);
1270 	}
1271 	*pathcpp = pathcp;
1272 	*lenp = len;
1273 	NFSEXITCODE2(0, nd);
1274 	return (0);
1275 nfsmout:
1276 	if (pathcp)
1277 		free(pathcp, M_TEMP);
1278 	NFSEXITCODE2(error, nd);
1279 	return (error);
1280 }
1281 
1282 /*
1283  * Remove a non-directory object.
1284  */
1285 int
1286 nfsvno_removesub(struct nameidata *ndp, int is_v4, struct ucred *cred,
1287     struct thread *p, struct nfsexstuff *exp)
1288 {
1289 	struct vnode *vp, *dsdvp[NFSDEV_MAXMIRRORS];
1290 	int error = 0, mirrorcnt;
1291 	char fname[PNFS_FILENAME_LEN + 1];
1292 	fhandle_t fh;
1293 
1294 	vp = ndp->ni_vp;
1295 	dsdvp[0] = NULL;
1296 	if (vp->v_type == VDIR)
1297 		error = NFSERR_ISDIR;
1298 	else if (is_v4)
1299 		error = nfsrv_checkremove(vp, 1, NULL, (nfsquad_t)((u_quad_t)0),
1300 		    p);
1301 	if (error == 0)
1302 		nfsrv_pnfsremovesetup(vp, p, dsdvp, &mirrorcnt, fname, &fh);
1303 	if (!error)
1304 		error = VOP_REMOVE(ndp->ni_dvp, vp, &ndp->ni_cnd);
1305 	if (error == 0 && dsdvp[0] != NULL)
1306 		nfsrv_pnfsremove(dsdvp, mirrorcnt, fname, &fh, p);
1307 	if (ndp->ni_dvp == vp)
1308 		vrele(ndp->ni_dvp);
1309 	else
1310 		vput(ndp->ni_dvp);
1311 	vput(vp);
1312 	if ((ndp->ni_cnd.cn_flags & SAVENAME) != 0)
1313 		nfsvno_relpathbuf(ndp);
1314 	NFSEXITCODE(error);
1315 	return (error);
1316 }
1317 
1318 /*
1319  * Remove a directory.
1320  */
1321 int
1322 nfsvno_rmdirsub(struct nameidata *ndp, int is_v4, struct ucred *cred,
1323     struct thread *p, struct nfsexstuff *exp)
1324 {
1325 	struct vnode *vp;
1326 	int error = 0;
1327 
1328 	vp = ndp->ni_vp;
1329 	if (vp->v_type != VDIR) {
1330 		error = ENOTDIR;
1331 		goto out;
1332 	}
1333 	/*
1334 	 * No rmdir "." please.
1335 	 */
1336 	if (ndp->ni_dvp == vp) {
1337 		error = EINVAL;
1338 		goto out;
1339 	}
1340 	/*
1341 	 * The root of a mounted filesystem cannot be deleted.
1342 	 */
1343 	if (vp->v_vflag & VV_ROOT)
1344 		error = EBUSY;
1345 out:
1346 	if (!error)
1347 		error = VOP_RMDIR(ndp->ni_dvp, vp, &ndp->ni_cnd);
1348 	if (ndp->ni_dvp == vp)
1349 		vrele(ndp->ni_dvp);
1350 	else
1351 		vput(ndp->ni_dvp);
1352 	vput(vp);
1353 	if ((ndp->ni_cnd.cn_flags & SAVENAME) != 0)
1354 		nfsvno_relpathbuf(ndp);
1355 	NFSEXITCODE(error);
1356 	return (error);
1357 }
1358 
1359 /*
1360  * Rename vnode op.
1361  */
1362 int
1363 nfsvno_rename(struct nameidata *fromndp, struct nameidata *tondp,
1364     u_int32_t ndstat, u_int32_t ndflag, struct ucred *cred, struct thread *p)
1365 {
1366 	struct vnode *fvp, *tvp, *tdvp, *dsdvp[NFSDEV_MAXMIRRORS];
1367 	int error = 0, mirrorcnt;
1368 	char fname[PNFS_FILENAME_LEN + 1];
1369 	fhandle_t fh;
1370 
1371 	dsdvp[0] = NULL;
1372 	fvp = fromndp->ni_vp;
1373 	if (ndstat) {
1374 		vrele(fromndp->ni_dvp);
1375 		vrele(fvp);
1376 		error = ndstat;
1377 		goto out1;
1378 	}
1379 	tdvp = tondp->ni_dvp;
1380 	tvp = tondp->ni_vp;
1381 	if (tvp != NULL) {
1382 		if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
1383 			error = (ndflag & ND_NFSV2) ? EISDIR : EEXIST;
1384 			goto out;
1385 		} else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
1386 			error = (ndflag & ND_NFSV2) ? ENOTDIR : EEXIST;
1387 			goto out;
1388 		}
1389 		if (tvp->v_type == VDIR && tvp->v_mountedhere) {
1390 			error = (ndflag & ND_NFSV2) ? ENOTEMPTY : EXDEV;
1391 			goto out;
1392 		}
1393 
1394 		/*
1395 		 * A rename to '.' or '..' results in a prematurely
1396 		 * unlocked vnode on FreeBSD5, so I'm just going to fail that
1397 		 * here.
1398 		 */
1399 		if ((tondp->ni_cnd.cn_namelen == 1 &&
1400 		     tondp->ni_cnd.cn_nameptr[0] == '.') ||
1401 		    (tondp->ni_cnd.cn_namelen == 2 &&
1402 		     tondp->ni_cnd.cn_nameptr[0] == '.' &&
1403 		     tondp->ni_cnd.cn_nameptr[1] == '.')) {
1404 			error = EINVAL;
1405 			goto out;
1406 		}
1407 	}
1408 	if (fvp->v_type == VDIR && fvp->v_mountedhere) {
1409 		error = (ndflag & ND_NFSV2) ? ENOTEMPTY : EXDEV;
1410 		goto out;
1411 	}
1412 	if (fvp->v_mount != tdvp->v_mount) {
1413 		error = (ndflag & ND_NFSV2) ? ENOTEMPTY : EXDEV;
1414 		goto out;
1415 	}
1416 	if (fvp == tdvp) {
1417 		error = (ndflag & ND_NFSV2) ? ENOTEMPTY : EINVAL;
1418 		goto out;
1419 	}
1420 	if (fvp == tvp) {
1421 		/*
1422 		 * If source and destination are the same, there is nothing to
1423 		 * do. Set error to -1 to indicate this.
1424 		 */
1425 		error = -1;
1426 		goto out;
1427 	}
1428 	if (ndflag & ND_NFSV4) {
1429 		if (NFSVOPLOCK(fvp, LK_EXCLUSIVE) == 0) {
1430 			error = nfsrv_checkremove(fvp, 0, NULL,
1431 			    (nfsquad_t)((u_quad_t)0), p);
1432 			NFSVOPUNLOCK(fvp);
1433 		} else
1434 			error = EPERM;
1435 		if (tvp && !error)
1436 			error = nfsrv_checkremove(tvp, 1, NULL,
1437 			    (nfsquad_t)((u_quad_t)0), p);
1438 	} else {
1439 		/*
1440 		 * For NFSv2 and NFSv3, try to get rid of the delegation, so
1441 		 * that the NFSv4 client won't be confused by the rename.
1442 		 * Since nfsd_recalldelegation() can only be called on an
1443 		 * unlocked vnode at this point and fvp is the file that will
1444 		 * still exist after the rename, just do fvp.
1445 		 */
1446 		nfsd_recalldelegation(fvp, p);
1447 	}
1448 	if (error == 0 && tvp != NULL) {
1449 		nfsrv_pnfsremovesetup(tvp, p, dsdvp, &mirrorcnt, fname, &fh);
1450 		NFSD_DEBUG(4, "nfsvno_rename: pnfsremovesetup"
1451 		    " dsdvp=%p\n", dsdvp[0]);
1452 	}
1453 out:
1454 	if (!error) {
1455 		error = VOP_RENAME(fromndp->ni_dvp, fromndp->ni_vp,
1456 		    &fromndp->ni_cnd, tondp->ni_dvp, tondp->ni_vp,
1457 		    &tondp->ni_cnd);
1458 	} else {
1459 		if (tdvp == tvp)
1460 			vrele(tdvp);
1461 		else
1462 			vput(tdvp);
1463 		if (tvp)
1464 			vput(tvp);
1465 		vrele(fromndp->ni_dvp);
1466 		vrele(fvp);
1467 		if (error == -1)
1468 			error = 0;
1469 	}
1470 
1471 	/*
1472 	 * If dsdvp[0] != NULL, it was set up by nfsrv_pnfsremovesetup() and
1473 	 * if the rename succeeded, the DS file for the tvp needs to be
1474 	 * removed.
1475 	 */
1476 	if (error == 0 && dsdvp[0] != NULL) {
1477 		nfsrv_pnfsremove(dsdvp, mirrorcnt, fname, &fh, p);
1478 		NFSD_DEBUG(4, "nfsvno_rename: pnfsremove\n");
1479 	}
1480 
1481 	vrele(tondp->ni_startdir);
1482 	nfsvno_relpathbuf(tondp);
1483 out1:
1484 	vrele(fromndp->ni_startdir);
1485 	nfsvno_relpathbuf(fromndp);
1486 	NFSEXITCODE(error);
1487 	return (error);
1488 }
1489 
1490 /*
1491  * Link vnode op.
1492  */
1493 int
1494 nfsvno_link(struct nameidata *ndp, struct vnode *vp, struct ucred *cred,
1495     struct thread *p, struct nfsexstuff *exp)
1496 {
1497 	struct vnode *xp;
1498 	int error = 0;
1499 
1500 	xp = ndp->ni_vp;
1501 	if (xp != NULL) {
1502 		error = EEXIST;
1503 	} else {
1504 		xp = ndp->ni_dvp;
1505 		if (vp->v_mount != xp->v_mount)
1506 			error = EXDEV;
1507 	}
1508 	if (!error) {
1509 		NFSVOPLOCK(vp, LK_EXCLUSIVE | LK_RETRY);
1510 		if (!VN_IS_DOOMED(vp))
1511 			error = VOP_LINK(ndp->ni_dvp, vp, &ndp->ni_cnd);
1512 		else
1513 			error = EPERM;
1514 		if (ndp->ni_dvp == vp)
1515 			vrele(ndp->ni_dvp);
1516 		else
1517 			vput(ndp->ni_dvp);
1518 		NFSVOPUNLOCK(vp);
1519 	} else {
1520 		if (ndp->ni_dvp == ndp->ni_vp)
1521 			vrele(ndp->ni_dvp);
1522 		else
1523 			vput(ndp->ni_dvp);
1524 		if (ndp->ni_vp)
1525 			vrele(ndp->ni_vp);
1526 	}
1527 	nfsvno_relpathbuf(ndp);
1528 	NFSEXITCODE(error);
1529 	return (error);
1530 }
1531 
1532 /*
1533  * Do the fsync() appropriate for the commit.
1534  */
1535 int
1536 nfsvno_fsync(struct vnode *vp, u_int64_t off, int cnt, struct ucred *cred,
1537     struct thread *td)
1538 {
1539 	int error = 0;
1540 
1541 	/*
1542 	 * RFC 1813 3.3.21: if count is 0, a flush from offset to the end of
1543 	 * file is done.  At this time VOP_FSYNC does not accept offset and
1544 	 * byte count parameters so call VOP_FSYNC the whole file for now.
1545 	 * The same is true for NFSv4: RFC 3530 Sec. 14.2.3.
1546 	 * File systems that do not use the buffer cache (as indicated
1547 	 * by MNTK_USES_BCACHE not being set) must use VOP_FSYNC().
1548 	 */
1549 	if (cnt == 0 || cnt > MAX_COMMIT_COUNT ||
1550 	    (vp->v_mount->mnt_kern_flag & MNTK_USES_BCACHE) == 0) {
1551 		/*
1552 		 * Give up and do the whole thing
1553 		 */
1554 		if (vp->v_object && vm_object_mightbedirty(vp->v_object)) {
1555 			VM_OBJECT_WLOCK(vp->v_object);
1556 			vm_object_page_clean(vp->v_object, 0, 0, OBJPC_SYNC);
1557 			VM_OBJECT_WUNLOCK(vp->v_object);
1558 		}
1559 		error = VOP_FSYNC(vp, MNT_WAIT, td);
1560 	} else {
1561 		/*
1562 		 * Locate and synchronously write any buffers that fall
1563 		 * into the requested range.  Note:  we are assuming that
1564 		 * f_iosize is a power of 2.
1565 		 */
1566 		int iosize = vp->v_mount->mnt_stat.f_iosize;
1567 		int iomask = iosize - 1;
1568 		struct bufobj *bo;
1569 		daddr_t lblkno;
1570 
1571 		/*
1572 		 * Align to iosize boundary, super-align to page boundary.
1573 		 */
1574 		if (off & iomask) {
1575 			cnt += off & iomask;
1576 			off &= ~(u_quad_t)iomask;
1577 		}
1578 		if (off & PAGE_MASK) {
1579 			cnt += off & PAGE_MASK;
1580 			off &= ~(u_quad_t)PAGE_MASK;
1581 		}
1582 		lblkno = off / iosize;
1583 
1584 		if (vp->v_object && vm_object_mightbedirty(vp->v_object)) {
1585 			VM_OBJECT_WLOCK(vp->v_object);
1586 			vm_object_page_clean(vp->v_object, off, off + cnt,
1587 			    OBJPC_SYNC);
1588 			VM_OBJECT_WUNLOCK(vp->v_object);
1589 		}
1590 
1591 		bo = &vp->v_bufobj;
1592 		BO_LOCK(bo);
1593 		while (cnt > 0) {
1594 			struct buf *bp;
1595 
1596 			/*
1597 			 * If we have a buffer and it is marked B_DELWRI we
1598 			 * have to lock and write it.  Otherwise the prior
1599 			 * write is assumed to have already been committed.
1600 			 *
1601 			 * gbincore() can return invalid buffers now so we
1602 			 * have to check that bit as well (though B_DELWRI
1603 			 * should not be set if B_INVAL is set there could be
1604 			 * a race here since we haven't locked the buffer).
1605 			 */
1606 			if ((bp = gbincore(&vp->v_bufobj, lblkno)) != NULL) {
1607 				if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_SLEEPFAIL |
1608 				    LK_INTERLOCK, BO_LOCKPTR(bo)) == ENOLCK) {
1609 					BO_LOCK(bo);
1610 					continue; /* retry */
1611 				}
1612 			    	if ((bp->b_flags & (B_DELWRI|B_INVAL)) ==
1613 				    B_DELWRI) {
1614 					bremfree(bp);
1615 					bp->b_flags &= ~B_ASYNC;
1616 					bwrite(bp);
1617 					++nfs_commit_miss;
1618 				} else
1619 					BUF_UNLOCK(bp);
1620 				BO_LOCK(bo);
1621 			}
1622 			++nfs_commit_blks;
1623 			if (cnt < iosize)
1624 				break;
1625 			cnt -= iosize;
1626 			++lblkno;
1627 		}
1628 		BO_UNLOCK(bo);
1629 	}
1630 	NFSEXITCODE(error);
1631 	return (error);
1632 }
1633 
1634 /*
1635  * Statfs vnode op.
1636  */
1637 int
1638 nfsvno_statfs(struct vnode *vp, struct statfs *sf)
1639 {
1640 	struct statfs *tsf;
1641 	int error;
1642 
1643 	tsf = NULL;
1644 	if (nfsrv_devidcnt > 0) {
1645 		/* For a pNFS service, get the DS numbers. */
1646 		tsf = malloc(sizeof(*tsf), M_TEMP, M_WAITOK | M_ZERO);
1647 		error = nfsrv_pnfsstatfs(tsf, vp->v_mount);
1648 		if (error != 0) {
1649 			free(tsf, M_TEMP);
1650 			tsf = NULL;
1651 		}
1652 	}
1653 	error = VFS_STATFS(vp->v_mount, sf);
1654 	if (error == 0) {
1655 		if (tsf != NULL) {
1656 			sf->f_blocks = tsf->f_blocks;
1657 			sf->f_bavail = tsf->f_bavail;
1658 			sf->f_bfree = tsf->f_bfree;
1659 			sf->f_bsize = tsf->f_bsize;
1660 		}
1661 		/*
1662 		 * Since NFS handles these values as unsigned on the
1663 		 * wire, there is no way to represent negative values,
1664 		 * so set them to 0. Without this, they will appear
1665 		 * to be very large positive values for clients like
1666 		 * Solaris10.
1667 		 */
1668 		if (sf->f_bavail < 0)
1669 			sf->f_bavail = 0;
1670 		if (sf->f_ffree < 0)
1671 			sf->f_ffree = 0;
1672 	}
1673 	free(tsf, M_TEMP);
1674 	NFSEXITCODE(error);
1675 	return (error);
1676 }
1677 
1678 /*
1679  * Do the vnode op stuff for Open. Similar to nfsvno_createsub(), but
1680  * must handle nfsrv_opencheck() calls after any other access checks.
1681  */
1682 void
1683 nfsvno_open(struct nfsrv_descript *nd, struct nameidata *ndp,
1684     nfsquad_t clientid, nfsv4stateid_t *stateidp, struct nfsstate *stp,
1685     int *exclusive_flagp, struct nfsvattr *nvap, int32_t *cverf, int create,
1686     NFSACL_T *aclp, nfsattrbit_t *attrbitp, struct ucred *cred,
1687     struct nfsexstuff *exp, struct vnode **vpp)
1688 {
1689 	struct vnode *vp = NULL;
1690 	u_quad_t tempsize;
1691 	struct nfsexstuff nes;
1692 	struct thread *p = curthread;
1693 
1694 	if (ndp->ni_vp == NULL)
1695 		nd->nd_repstat = nfsrv_opencheck(clientid,
1696 		    stateidp, stp, NULL, nd, p, nd->nd_repstat);
1697 	if (!nd->nd_repstat) {
1698 		if (ndp->ni_vp == NULL) {
1699 			vrele(ndp->ni_startdir);
1700 			nd->nd_repstat = VOP_CREATE(ndp->ni_dvp,
1701 			    &ndp->ni_vp, &ndp->ni_cnd, &nvap->na_vattr);
1702 			/* For a pNFS server, create the data file on a DS. */
1703 			if (nd->nd_repstat == 0) {
1704 				/*
1705 				 * Create a data file on a DS for a pNFS server.
1706 				 * This function just returns if not
1707 				 * running a pNFS DS or the creation fails.
1708 				 */
1709 				nfsrv_pnfscreate(ndp->ni_vp, &nvap->na_vattr,
1710 				    cred, p);
1711 			}
1712 			vput(ndp->ni_dvp);
1713 			nfsvno_relpathbuf(ndp);
1714 			if (!nd->nd_repstat) {
1715 				if (*exclusive_flagp) {
1716 					*exclusive_flagp = 0;
1717 					NFSVNO_ATTRINIT(nvap);
1718 					nvap->na_atime.tv_sec = cverf[0];
1719 					nvap->na_atime.tv_nsec = cverf[1];
1720 					nd->nd_repstat = VOP_SETATTR(ndp->ni_vp,
1721 					    &nvap->na_vattr, cred);
1722 					if (nd->nd_repstat != 0) {
1723 						vput(ndp->ni_vp);
1724 						ndp->ni_vp = NULL;
1725 						nd->nd_repstat = NFSERR_NOTSUPP;
1726 					} else
1727 						NFSSETBIT_ATTRBIT(attrbitp,
1728 						    NFSATTRBIT_TIMEACCESS);
1729 				} else {
1730 					nfsrv_fixattr(nd, ndp->ni_vp, nvap,
1731 					    aclp, p, attrbitp, exp);
1732 				}
1733 			}
1734 			vp = ndp->ni_vp;
1735 		} else {
1736 			if (ndp->ni_startdir)
1737 				vrele(ndp->ni_startdir);
1738 			nfsvno_relpathbuf(ndp);
1739 			vp = ndp->ni_vp;
1740 			if (create == NFSV4OPEN_CREATE) {
1741 				if (ndp->ni_dvp == vp)
1742 					vrele(ndp->ni_dvp);
1743 				else
1744 					vput(ndp->ni_dvp);
1745 			}
1746 			if (NFSVNO_ISSETSIZE(nvap) && vp->v_type == VREG) {
1747 				if (ndp->ni_cnd.cn_flags & RDONLY)
1748 					NFSVNO_SETEXRDONLY(&nes);
1749 				else
1750 					NFSVNO_EXINIT(&nes);
1751 				nd->nd_repstat = nfsvno_accchk(vp,
1752 				    VWRITE, cred, &nes, p,
1753 				    NFSACCCHK_NOOVERRIDE,
1754 				    NFSACCCHK_VPISLOCKED, NULL);
1755 				nd->nd_repstat = nfsrv_opencheck(clientid,
1756 				    stateidp, stp, vp, nd, p, nd->nd_repstat);
1757 				if (!nd->nd_repstat) {
1758 					tempsize = nvap->na_size;
1759 					NFSVNO_ATTRINIT(nvap);
1760 					nvap->na_size = tempsize;
1761 					nd->nd_repstat = VOP_SETATTR(vp,
1762 					    &nvap->na_vattr, cred);
1763 				}
1764 			} else if (vp->v_type == VREG) {
1765 				nd->nd_repstat = nfsrv_opencheck(clientid,
1766 				    stateidp, stp, vp, nd, p, nd->nd_repstat);
1767 			}
1768 		}
1769 	} else {
1770 		if (ndp->ni_cnd.cn_flags & HASBUF)
1771 			nfsvno_relpathbuf(ndp);
1772 		if (ndp->ni_startdir && create == NFSV4OPEN_CREATE) {
1773 			vrele(ndp->ni_startdir);
1774 			if (ndp->ni_dvp == ndp->ni_vp)
1775 				vrele(ndp->ni_dvp);
1776 			else
1777 				vput(ndp->ni_dvp);
1778 			if (ndp->ni_vp)
1779 				vput(ndp->ni_vp);
1780 		}
1781 	}
1782 	*vpp = vp;
1783 
1784 	NFSEXITCODE2(0, nd);
1785 }
1786 
1787 /*
1788  * Updates the file rev and sets the mtime and ctime
1789  * to the current clock time, returning the va_filerev and va_Xtime
1790  * values.
1791  * Return ESTALE to indicate the vnode is VIRF_DOOMED.
1792  */
1793 int
1794 nfsvno_updfilerev(struct vnode *vp, struct nfsvattr *nvap,
1795     struct nfsrv_descript *nd, struct thread *p)
1796 {
1797 	struct vattr va;
1798 
1799 	VATTR_NULL(&va);
1800 	vfs_timestamp(&va.va_mtime);
1801 	if (NFSVOPISLOCKED(vp) != LK_EXCLUSIVE) {
1802 		NFSVOPLOCK(vp, LK_UPGRADE | LK_RETRY);
1803 		if (VN_IS_DOOMED(vp))
1804 			return (ESTALE);
1805 	}
1806 	(void) VOP_SETATTR(vp, &va, nd->nd_cred);
1807 	(void) nfsvno_getattr(vp, nvap, nd, p, 1, NULL);
1808 	return (0);
1809 }
1810 
1811 /*
1812  * Glue routine to nfsv4_fillattr().
1813  */
1814 int
1815 nfsvno_fillattr(struct nfsrv_descript *nd, struct mount *mp, struct vnode *vp,
1816     struct nfsvattr *nvap, fhandle_t *fhp, int rderror, nfsattrbit_t *attrbitp,
1817     struct ucred *cred, struct thread *p, int isdgram, int reterr,
1818     int supports_nfsv4acls, int at_root, uint64_t mounted_on_fileno)
1819 {
1820 	struct statfs *sf;
1821 	int error;
1822 
1823 	sf = NULL;
1824 	if (nfsrv_devidcnt > 0 &&
1825 	    (NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_SPACEAVAIL) ||
1826 	     NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_SPACEFREE) ||
1827 	     NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_SPACETOTAL))) {
1828 		sf = malloc(sizeof(*sf), M_TEMP, M_WAITOK | M_ZERO);
1829 		error = nfsrv_pnfsstatfs(sf, mp);
1830 		if (error != 0) {
1831 			free(sf, M_TEMP);
1832 			sf = NULL;
1833 		}
1834 	}
1835 	error = nfsv4_fillattr(nd, mp, vp, NULL, &nvap->na_vattr, fhp, rderror,
1836 	    attrbitp, cred, p, isdgram, reterr, supports_nfsv4acls, at_root,
1837 	    mounted_on_fileno, sf);
1838 	free(sf, M_TEMP);
1839 	NFSEXITCODE2(0, nd);
1840 	return (error);
1841 }
1842 
1843 /* Since the Readdir vnode ops vary, put the entire functions in here. */
1844 /*
1845  * nfs readdir service
1846  * - mallocs what it thinks is enough to read
1847  *	count rounded up to a multiple of DIRBLKSIZ <= NFS_MAXREADDIR
1848  * - calls VOP_READDIR()
1849  * - loops around building the reply
1850  *	if the output generated exceeds count break out of loop
1851  *	The NFSM_CLGET macro is used here so that the reply will be packed
1852  *	tightly in mbuf clusters.
1853  * - it trims out records with d_fileno == 0
1854  *	this doesn't matter for Unix clients, but they might confuse clients
1855  *	for other os'.
1856  * - it trims out records with d_type == DT_WHT
1857  *	these cannot be seen through NFS (unless we extend the protocol)
1858  *     The alternate call nfsrvd_readdirplus() does lookups as well.
1859  * PS: The NFS protocol spec. does not clarify what the "count" byte
1860  *	argument is a count of.. just name strings and file id's or the
1861  *	entire reply rpc or ...
1862  *	I tried just file name and id sizes and it confused the Sun client,
1863  *	so I am using the full rpc size now. The "paranoia.." comment refers
1864  *	to including the status longwords that are not a part of the dir.
1865  *	"entry" structures, but are in the rpc.
1866  */
1867 int
1868 nfsrvd_readdir(struct nfsrv_descript *nd, int isdgram,
1869     struct vnode *vp, struct nfsexstuff *exp)
1870 {
1871 	struct dirent *dp;
1872 	u_int32_t *tl;
1873 	int dirlen;
1874 	char *cpos, *cend, *rbuf;
1875 	struct nfsvattr at;
1876 	int nlen, error = 0, getret = 1;
1877 	int siz, cnt, fullsiz, eofflag, ncookies;
1878 	u_int64_t off, toff, verf __unused;
1879 	u_long *cookies = NULL, *cookiep;
1880 	struct uio io;
1881 	struct iovec iv;
1882 	int is_ufs;
1883 	struct thread *p = curthread;
1884 
1885 	if (nd->nd_repstat) {
1886 		nfsrv_postopattr(nd, getret, &at);
1887 		goto out;
1888 	}
1889 	if (nd->nd_flag & ND_NFSV2) {
1890 		NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
1891 		off = fxdr_unsigned(u_quad_t, *tl++);
1892 	} else {
1893 		NFSM_DISSECT(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
1894 		off = fxdr_hyper(tl);
1895 		tl += 2;
1896 		verf = fxdr_hyper(tl);
1897 		tl += 2;
1898 	}
1899 	toff = off;
1900 	cnt = fxdr_unsigned(int, *tl);
1901 	if (cnt > NFS_SRVMAXDATA(nd) || cnt < 0)
1902 		cnt = NFS_SRVMAXDATA(nd);
1903 	siz = ((cnt + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1));
1904 	fullsiz = siz;
1905 	if (nd->nd_flag & ND_NFSV3) {
1906 		nd->nd_repstat = getret = nfsvno_getattr(vp, &at, nd, p, 1,
1907 		    NULL);
1908 #if 0
1909 		/*
1910 		 * va_filerev is not sufficient as a cookie verifier,
1911 		 * since it is not supposed to change when entries are
1912 		 * removed/added unless that offset cookies returned to
1913 		 * the client are no longer valid.
1914 		 */
1915 		if (!nd->nd_repstat && toff && verf != at.na_filerev)
1916 			nd->nd_repstat = NFSERR_BAD_COOKIE;
1917 #endif
1918 	}
1919 	if (!nd->nd_repstat && vp->v_type != VDIR)
1920 		nd->nd_repstat = NFSERR_NOTDIR;
1921 	if (nd->nd_repstat == 0 && cnt == 0) {
1922 		if (nd->nd_flag & ND_NFSV2)
1923 			/* NFSv2 does not have NFSERR_TOOSMALL */
1924 			nd->nd_repstat = EPERM;
1925 		else
1926 			nd->nd_repstat = NFSERR_TOOSMALL;
1927 	}
1928 	if (!nd->nd_repstat)
1929 		nd->nd_repstat = nfsvno_accchk(vp, VEXEC,
1930 		    nd->nd_cred, exp, p, NFSACCCHK_NOOVERRIDE,
1931 		    NFSACCCHK_VPISLOCKED, NULL);
1932 	if (nd->nd_repstat) {
1933 		vput(vp);
1934 		if (nd->nd_flag & ND_NFSV3)
1935 			nfsrv_postopattr(nd, getret, &at);
1936 		goto out;
1937 	}
1938 	is_ufs = strcmp(vp->v_mount->mnt_vfc->vfc_name, "ufs") == 0;
1939 	rbuf = malloc(siz, M_TEMP, M_WAITOK);
1940 again:
1941 	eofflag = 0;
1942 	if (cookies) {
1943 		free(cookies, M_TEMP);
1944 		cookies = NULL;
1945 	}
1946 
1947 	iv.iov_base = rbuf;
1948 	iv.iov_len = siz;
1949 	io.uio_iov = &iv;
1950 	io.uio_iovcnt = 1;
1951 	io.uio_offset = (off_t)off;
1952 	io.uio_resid = siz;
1953 	io.uio_segflg = UIO_SYSSPACE;
1954 	io.uio_rw = UIO_READ;
1955 	io.uio_td = NULL;
1956 	nd->nd_repstat = VOP_READDIR(vp, &io, nd->nd_cred, &eofflag, &ncookies,
1957 	    &cookies);
1958 	off = (u_int64_t)io.uio_offset;
1959 	if (io.uio_resid)
1960 		siz -= io.uio_resid;
1961 
1962 	if (!cookies && !nd->nd_repstat)
1963 		nd->nd_repstat = NFSERR_PERM;
1964 	if (nd->nd_flag & ND_NFSV3) {
1965 		getret = nfsvno_getattr(vp, &at, nd, p, 1, NULL);
1966 		if (!nd->nd_repstat)
1967 			nd->nd_repstat = getret;
1968 	}
1969 
1970 	/*
1971 	 * Handles the failed cases. nd->nd_repstat == 0 past here.
1972 	 */
1973 	if (nd->nd_repstat) {
1974 		vput(vp);
1975 		free(rbuf, M_TEMP);
1976 		if (cookies)
1977 			free(cookies, M_TEMP);
1978 		if (nd->nd_flag & ND_NFSV3)
1979 			nfsrv_postopattr(nd, getret, &at);
1980 		goto out;
1981 	}
1982 	/*
1983 	 * If nothing read, return eof
1984 	 * rpc reply
1985 	 */
1986 	if (siz == 0) {
1987 		vput(vp);
1988 		if (nd->nd_flag & ND_NFSV2) {
1989 			NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
1990 		} else {
1991 			nfsrv_postopattr(nd, getret, &at);
1992 			NFSM_BUILD(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
1993 			txdr_hyper(at.na_filerev, tl);
1994 			tl += 2;
1995 		}
1996 		*tl++ = newnfs_false;
1997 		*tl = newnfs_true;
1998 		free(rbuf, M_TEMP);
1999 		free(cookies, M_TEMP);
2000 		goto out;
2001 	}
2002 
2003 	/*
2004 	 * Check for degenerate cases of nothing useful read.
2005 	 * If so go try again
2006 	 */
2007 	cpos = rbuf;
2008 	cend = rbuf + siz;
2009 	dp = (struct dirent *)cpos;
2010 	cookiep = cookies;
2011 
2012 	/*
2013 	 * For some reason FreeBSD's ufs_readdir() chooses to back the
2014 	 * directory offset up to a block boundary, so it is necessary to
2015 	 * skip over the records that precede the requested offset. This
2016 	 * requires the assumption that file offset cookies monotonically
2017 	 * increase.
2018 	 */
2019 	while (cpos < cend && ncookies > 0 &&
2020 	    (dp->d_fileno == 0 || dp->d_type == DT_WHT ||
2021 	     (is_ufs == 1 && ((u_quad_t)(*cookiep)) <= toff))) {
2022 		cpos += dp->d_reclen;
2023 		dp = (struct dirent *)cpos;
2024 		cookiep++;
2025 		ncookies--;
2026 	}
2027 	if (cpos >= cend || ncookies == 0) {
2028 		siz = fullsiz;
2029 		toff = off;
2030 		goto again;
2031 	}
2032 	vput(vp);
2033 
2034 	/*
2035 	 * dirlen is the size of the reply, including all XDR and must
2036 	 * not exceed cnt. For NFSv2, RFC1094 didn't clearly indicate
2037 	 * if the XDR should be included in "count", but to be safe, we do.
2038 	 * (Include the two booleans at the end of the reply in dirlen now.)
2039 	 */
2040 	if (nd->nd_flag & ND_NFSV3) {
2041 		nfsrv_postopattr(nd, getret, &at);
2042 		NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
2043 		txdr_hyper(at.na_filerev, tl);
2044 		dirlen = NFSX_V3POSTOPATTR + NFSX_VERF + 2 * NFSX_UNSIGNED;
2045 	} else {
2046 		dirlen = 2 * NFSX_UNSIGNED;
2047 	}
2048 
2049 	/* Loop through the records and build reply */
2050 	while (cpos < cend && ncookies > 0) {
2051 		nlen = dp->d_namlen;
2052 		if (dp->d_fileno != 0 && dp->d_type != DT_WHT &&
2053 			nlen <= NFS_MAXNAMLEN) {
2054 			if (nd->nd_flag & ND_NFSV3)
2055 				dirlen += (6*NFSX_UNSIGNED + NFSM_RNDUP(nlen));
2056 			else
2057 				dirlen += (4*NFSX_UNSIGNED + NFSM_RNDUP(nlen));
2058 			if (dirlen > cnt) {
2059 				eofflag = 0;
2060 				break;
2061 			}
2062 
2063 			/*
2064 			 * Build the directory record xdr from
2065 			 * the dirent entry.
2066 			 */
2067 			if (nd->nd_flag & ND_NFSV3) {
2068 				NFSM_BUILD(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
2069 				*tl++ = newnfs_true;
2070 				*tl++ = 0;
2071 			} else {
2072 				NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
2073 				*tl++ = newnfs_true;
2074 			}
2075 			*tl = txdr_unsigned(dp->d_fileno);
2076 			(void) nfsm_strtom(nd, dp->d_name, nlen);
2077 			if (nd->nd_flag & ND_NFSV3) {
2078 				NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
2079 				*tl++ = 0;
2080 			} else
2081 				NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
2082 			*tl = txdr_unsigned(*cookiep);
2083 		}
2084 		cpos += dp->d_reclen;
2085 		dp = (struct dirent *)cpos;
2086 		cookiep++;
2087 		ncookies--;
2088 	}
2089 	if (cpos < cend)
2090 		eofflag = 0;
2091 	NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
2092 	*tl++ = newnfs_false;
2093 	if (eofflag)
2094 		*tl = newnfs_true;
2095 	else
2096 		*tl = newnfs_false;
2097 	free(rbuf, M_TEMP);
2098 	free(cookies, M_TEMP);
2099 
2100 out:
2101 	NFSEXITCODE2(0, nd);
2102 	return (0);
2103 nfsmout:
2104 	vput(vp);
2105 	NFSEXITCODE2(error, nd);
2106 	return (error);
2107 }
2108 
2109 /*
2110  * Readdirplus for V3 and Readdir for V4.
2111  */
2112 int
2113 nfsrvd_readdirplus(struct nfsrv_descript *nd, int isdgram,
2114     struct vnode *vp, struct nfsexstuff *exp)
2115 {
2116 	struct dirent *dp;
2117 	u_int32_t *tl;
2118 	int dirlen;
2119 	char *cpos, *cend, *rbuf;
2120 	struct vnode *nvp;
2121 	fhandle_t nfh;
2122 	struct nfsvattr nva, at, *nvap = &nva;
2123 	struct mbuf *mb0, *mb1;
2124 	struct nfsreferral *refp;
2125 	int nlen, r, error = 0, getret = 1, usevget = 1;
2126 	int siz, cnt, fullsiz, eofflag, ncookies, entrycnt;
2127 	caddr_t bpos0, bpos1;
2128 	u_int64_t off, toff, verf;
2129 	u_long *cookies = NULL, *cookiep;
2130 	nfsattrbit_t attrbits, rderrbits, savbits;
2131 	struct uio io;
2132 	struct iovec iv;
2133 	struct componentname cn;
2134 	int at_root, is_ufs, is_zfs, needs_unbusy, supports_nfsv4acls;
2135 	struct mount *mp, *new_mp;
2136 	uint64_t mounted_on_fileno;
2137 	struct thread *p = curthread;
2138 
2139 	if (nd->nd_repstat) {
2140 		nfsrv_postopattr(nd, getret, &at);
2141 		goto out;
2142 	}
2143 	NFSM_DISSECT(tl, u_int32_t *, 6 * NFSX_UNSIGNED);
2144 	off = fxdr_hyper(tl);
2145 	toff = off;
2146 	tl += 2;
2147 	verf = fxdr_hyper(tl);
2148 	tl += 2;
2149 	siz = fxdr_unsigned(int, *tl++);
2150 	cnt = fxdr_unsigned(int, *tl);
2151 
2152 	/*
2153 	 * Use the server's maximum data transfer size as the upper bound
2154 	 * on reply datalen.
2155 	 */
2156 	if (cnt > NFS_SRVMAXDATA(nd) || cnt < 0)
2157 		cnt = NFS_SRVMAXDATA(nd);
2158 
2159 	/*
2160 	 * siz is a "hint" of how much directory information (name, fileid,
2161 	 * cookie) should be in the reply. At least one client "hints" 0,
2162 	 * so I set it to cnt for that case. I also round it up to the
2163 	 * next multiple of DIRBLKSIZ.
2164 	 * Since the size of a Readdirplus directory entry reply will always
2165 	 * be greater than a directory entry returned by VOP_READDIR(), it
2166 	 * does not make sense to read more than NFS_SRVMAXDATA() via
2167 	 * VOP_READDIR().
2168 	 */
2169 	if (siz <= 0)
2170 		siz = cnt;
2171 	else if (siz > NFS_SRVMAXDATA(nd))
2172 		siz = NFS_SRVMAXDATA(nd);
2173 	siz = ((siz + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1));
2174 
2175 	if (nd->nd_flag & ND_NFSV4) {
2176 		error = nfsrv_getattrbits(nd, &attrbits, NULL, NULL);
2177 		if (error)
2178 			goto nfsmout;
2179 		NFSSET_ATTRBIT(&savbits, &attrbits);
2180 		NFSCLRNOTFILLABLE_ATTRBIT(&attrbits, nd);
2181 		NFSZERO_ATTRBIT(&rderrbits);
2182 		NFSSETBIT_ATTRBIT(&rderrbits, NFSATTRBIT_RDATTRERROR);
2183 	} else {
2184 		NFSZERO_ATTRBIT(&attrbits);
2185 	}
2186 	fullsiz = siz;
2187 	nd->nd_repstat = getret = nfsvno_getattr(vp, &at, nd, p, 1, NULL);
2188 #if 0
2189 	if (!nd->nd_repstat) {
2190 	    if (off && verf != at.na_filerev) {
2191 		/*
2192 		 * va_filerev is not sufficient as a cookie verifier,
2193 		 * since it is not supposed to change when entries are
2194 		 * removed/added unless that offset cookies returned to
2195 		 * the client are no longer valid.
2196 		 */
2197 		if (nd->nd_flag & ND_NFSV4) {
2198 			nd->nd_repstat = NFSERR_NOTSAME;
2199 		} else {
2200 			nd->nd_repstat = NFSERR_BAD_COOKIE;
2201 		}
2202 	    }
2203 	}
2204 #endif
2205 	if (!nd->nd_repstat && vp->v_type != VDIR)
2206 		nd->nd_repstat = NFSERR_NOTDIR;
2207 	if (!nd->nd_repstat && cnt == 0)
2208 		nd->nd_repstat = NFSERR_TOOSMALL;
2209 	if (!nd->nd_repstat)
2210 		nd->nd_repstat = nfsvno_accchk(vp, VEXEC,
2211 		    nd->nd_cred, exp, p, NFSACCCHK_NOOVERRIDE,
2212 		    NFSACCCHK_VPISLOCKED, NULL);
2213 	if (nd->nd_repstat) {
2214 		vput(vp);
2215 		if (nd->nd_flag & ND_NFSV3)
2216 			nfsrv_postopattr(nd, getret, &at);
2217 		goto out;
2218 	}
2219 	is_ufs = strcmp(vp->v_mount->mnt_vfc->vfc_name, "ufs") == 0;
2220 	is_zfs = strcmp(vp->v_mount->mnt_vfc->vfc_name, "zfs") == 0;
2221 
2222 	rbuf = malloc(siz, M_TEMP, M_WAITOK);
2223 again:
2224 	eofflag = 0;
2225 	if (cookies) {
2226 		free(cookies, M_TEMP);
2227 		cookies = NULL;
2228 	}
2229 
2230 	iv.iov_base = rbuf;
2231 	iv.iov_len = siz;
2232 	io.uio_iov = &iv;
2233 	io.uio_iovcnt = 1;
2234 	io.uio_offset = (off_t)off;
2235 	io.uio_resid = siz;
2236 	io.uio_segflg = UIO_SYSSPACE;
2237 	io.uio_rw = UIO_READ;
2238 	io.uio_td = NULL;
2239 	nd->nd_repstat = VOP_READDIR(vp, &io, nd->nd_cred, &eofflag, &ncookies,
2240 	    &cookies);
2241 	off = (u_int64_t)io.uio_offset;
2242 	if (io.uio_resid)
2243 		siz -= io.uio_resid;
2244 
2245 	getret = nfsvno_getattr(vp, &at, nd, p, 1, NULL);
2246 
2247 	if (!cookies && !nd->nd_repstat)
2248 		nd->nd_repstat = NFSERR_PERM;
2249 	if (!nd->nd_repstat)
2250 		nd->nd_repstat = getret;
2251 	if (nd->nd_repstat) {
2252 		vput(vp);
2253 		if (cookies)
2254 			free(cookies, M_TEMP);
2255 		free(rbuf, M_TEMP);
2256 		if (nd->nd_flag & ND_NFSV3)
2257 			nfsrv_postopattr(nd, getret, &at);
2258 		goto out;
2259 	}
2260 	/*
2261 	 * If nothing read, return eof
2262 	 * rpc reply
2263 	 */
2264 	if (siz == 0) {
2265 		vput(vp);
2266 		if (nd->nd_flag & ND_NFSV3)
2267 			nfsrv_postopattr(nd, getret, &at);
2268 		NFSM_BUILD(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
2269 		txdr_hyper(at.na_filerev, tl);
2270 		tl += 2;
2271 		*tl++ = newnfs_false;
2272 		*tl = newnfs_true;
2273 		free(cookies, M_TEMP);
2274 		free(rbuf, M_TEMP);
2275 		goto out;
2276 	}
2277 
2278 	/*
2279 	 * Check for degenerate cases of nothing useful read.
2280 	 * If so go try again
2281 	 */
2282 	cpos = rbuf;
2283 	cend = rbuf + siz;
2284 	dp = (struct dirent *)cpos;
2285 	cookiep = cookies;
2286 
2287 	/*
2288 	 * For some reason FreeBSD's ufs_readdir() chooses to back the
2289 	 * directory offset up to a block boundary, so it is necessary to
2290 	 * skip over the records that precede the requested offset. This
2291 	 * requires the assumption that file offset cookies monotonically
2292 	 * increase.
2293 	 */
2294 	while (cpos < cend && ncookies > 0 &&
2295 	  (dp->d_fileno == 0 || dp->d_type == DT_WHT ||
2296 	   (is_ufs == 1 && ((u_quad_t)(*cookiep)) <= toff) ||
2297 	   ((nd->nd_flag & ND_NFSV4) &&
2298 	    ((dp->d_namlen == 1 && dp->d_name[0] == '.') ||
2299 	     (dp->d_namlen==2 && dp->d_name[0]=='.' && dp->d_name[1]=='.'))))) {
2300 		cpos += dp->d_reclen;
2301 		dp = (struct dirent *)cpos;
2302 		cookiep++;
2303 		ncookies--;
2304 	}
2305 	if (cpos >= cend || ncookies == 0) {
2306 		siz = fullsiz;
2307 		toff = off;
2308 		goto again;
2309 	}
2310 
2311 	/*
2312 	 * Busy the file system so that the mount point won't go away
2313 	 * and, as such, VFS_VGET() can be used safely.
2314 	 */
2315 	mp = vp->v_mount;
2316 	vfs_ref(mp);
2317 	NFSVOPUNLOCK(vp);
2318 	nd->nd_repstat = vfs_busy(mp, 0);
2319 	vfs_rel(mp);
2320 	if (nd->nd_repstat != 0) {
2321 		vrele(vp);
2322 		free(cookies, M_TEMP);
2323 		free(rbuf, M_TEMP);
2324 		if (nd->nd_flag & ND_NFSV3)
2325 			nfsrv_postopattr(nd, getret, &at);
2326 		goto out;
2327 	}
2328 
2329 	/*
2330 	 * Check to see if entries in this directory can be safely acquired
2331 	 * via VFS_VGET() or if a switch to VOP_LOOKUP() is required.
2332 	 * ZFS snapshot directories need VOP_LOOKUP(), so that any
2333 	 * automount of the snapshot directory that is required will
2334 	 * be done.
2335 	 * This needs to be done here for NFSv4, since NFSv4 never does
2336 	 * a VFS_VGET() for "." or "..".
2337 	 */
2338 	if (is_zfs == 1) {
2339 		r = VFS_VGET(mp, at.na_fileid, LK_SHARED, &nvp);
2340 		if (r == EOPNOTSUPP) {
2341 			usevget = 0;
2342 			cn.cn_nameiop = LOOKUP;
2343 			cn.cn_lkflags = LK_SHARED | LK_RETRY;
2344 			cn.cn_cred = nd->nd_cred;
2345 			cn.cn_thread = p;
2346 		} else if (r == 0)
2347 			vput(nvp);
2348 	}
2349 
2350 	/*
2351 	 * Save this position, in case there is an error before one entry
2352 	 * is created.
2353 	 */
2354 	mb0 = nd->nd_mb;
2355 	bpos0 = nd->nd_bpos;
2356 
2357 	/*
2358 	 * Fill in the first part of the reply.
2359 	 * dirlen is the reply length in bytes and cannot exceed cnt.
2360 	 * (Include the two booleans at the end of the reply in dirlen now,
2361 	 *  so we recognize when we have exceeded cnt.)
2362 	 */
2363 	if (nd->nd_flag & ND_NFSV3) {
2364 		dirlen = NFSX_V3POSTOPATTR + NFSX_VERF + 2 * NFSX_UNSIGNED;
2365 		nfsrv_postopattr(nd, getret, &at);
2366 	} else {
2367 		dirlen = NFSX_VERF + 2 * NFSX_UNSIGNED;
2368 	}
2369 	NFSM_BUILD(tl, u_int32_t *, NFSX_VERF);
2370 	txdr_hyper(at.na_filerev, tl);
2371 
2372 	/*
2373 	 * Save this position, in case there is an empty reply needed.
2374 	 */
2375 	mb1 = nd->nd_mb;
2376 	bpos1 = nd->nd_bpos;
2377 
2378 	/* Loop through the records and build reply */
2379 	entrycnt = 0;
2380 	while (cpos < cend && ncookies > 0 && dirlen < cnt) {
2381 		nlen = dp->d_namlen;
2382 		if (dp->d_fileno != 0 && dp->d_type != DT_WHT &&
2383 		    nlen <= NFS_MAXNAMLEN &&
2384 		    ((nd->nd_flag & ND_NFSV3) || nlen > 2 ||
2385 		     (nlen==2 && (dp->d_name[0]!='.' || dp->d_name[1]!='.'))
2386 		      || (nlen == 1 && dp->d_name[0] != '.'))) {
2387 			/*
2388 			 * Save the current position in the reply, in case
2389 			 * this entry exceeds cnt.
2390 			 */
2391 			mb1 = nd->nd_mb;
2392 			bpos1 = nd->nd_bpos;
2393 
2394 			/*
2395 			 * For readdir_and_lookup get the vnode using
2396 			 * the file number.
2397 			 */
2398 			nvp = NULL;
2399 			refp = NULL;
2400 			r = 0;
2401 			at_root = 0;
2402 			needs_unbusy = 0;
2403 			new_mp = mp;
2404 			mounted_on_fileno = (uint64_t)dp->d_fileno;
2405 			if ((nd->nd_flag & ND_NFSV3) ||
2406 			    NFSNONZERO_ATTRBIT(&savbits)) {
2407 				if (nd->nd_flag & ND_NFSV4)
2408 					refp = nfsv4root_getreferral(NULL,
2409 					    vp, dp->d_fileno);
2410 				if (refp == NULL) {
2411 					if (usevget)
2412 						r = VFS_VGET(mp, dp->d_fileno,
2413 						    LK_SHARED, &nvp);
2414 					else
2415 						r = EOPNOTSUPP;
2416 					if (r == EOPNOTSUPP) {
2417 						if (usevget) {
2418 							usevget = 0;
2419 							cn.cn_nameiop = LOOKUP;
2420 							cn.cn_lkflags =
2421 							    LK_SHARED |
2422 							    LK_RETRY;
2423 							cn.cn_cred =
2424 							    nd->nd_cred;
2425 							cn.cn_thread = p;
2426 						}
2427 						cn.cn_nameptr = dp->d_name;
2428 						cn.cn_namelen = nlen;
2429 						cn.cn_flags = ISLASTCN |
2430 						    NOFOLLOW | LOCKLEAF;
2431 						if (nlen == 2 &&
2432 						    dp->d_name[0] == '.' &&
2433 						    dp->d_name[1] == '.')
2434 							cn.cn_flags |=
2435 							    ISDOTDOT;
2436 						if (NFSVOPLOCK(vp, LK_SHARED)
2437 						    != 0) {
2438 							nd->nd_repstat = EPERM;
2439 							break;
2440 						}
2441 						if ((vp->v_vflag & VV_ROOT) != 0
2442 						    && (cn.cn_flags & ISDOTDOT)
2443 						    != 0) {
2444 							vref(vp);
2445 							nvp = vp;
2446 							r = 0;
2447 						} else {
2448 							r = VOP_LOOKUP(vp, &nvp,
2449 							    &cn);
2450 							if (vp != nvp)
2451 								NFSVOPUNLOCK(vp);
2452 						}
2453 					}
2454 
2455 					/*
2456 					 * For NFSv4, check to see if nvp is
2457 					 * a mount point and get the mount
2458 					 * point vnode, as required.
2459 					 */
2460 					if (r == 0 &&
2461 					    nfsrv_enable_crossmntpt != 0 &&
2462 					    (nd->nd_flag & ND_NFSV4) != 0 &&
2463 					    nvp->v_type == VDIR &&
2464 					    nvp->v_mountedhere != NULL) {
2465 						new_mp = nvp->v_mountedhere;
2466 						r = vfs_busy(new_mp, 0);
2467 						vput(nvp);
2468 						nvp = NULL;
2469 						if (r == 0) {
2470 							r = VFS_ROOT(new_mp,
2471 							    LK_SHARED, &nvp);
2472 							needs_unbusy = 1;
2473 							if (r == 0)
2474 								at_root = 1;
2475 						}
2476 					}
2477 				}
2478 
2479 				/*
2480 				 * If we failed to look up the entry, then it
2481 				 * has become invalid, most likely removed.
2482 				 */
2483 				if (r != 0) {
2484 					if (needs_unbusy)
2485 						vfs_unbusy(new_mp);
2486 					goto invalid;
2487 				}
2488 				KASSERT(refp != NULL || nvp != NULL,
2489 				    ("%s: undetected lookup error", __func__));
2490 
2491 				if (refp == NULL &&
2492 				    ((nd->nd_flag & ND_NFSV3) ||
2493 				     NFSNONZERO_ATTRBIT(&attrbits))) {
2494 					r = nfsvno_getfh(nvp, &nfh, p);
2495 					if (!r)
2496 					    r = nfsvno_getattr(nvp, nvap, nd, p,
2497 						1, &attrbits);
2498 					if (r == 0 && is_zfs == 1 &&
2499 					    nfsrv_enable_crossmntpt != 0 &&
2500 					    (nd->nd_flag & ND_NFSV4) != 0 &&
2501 					    nvp->v_type == VDIR &&
2502 					    vp->v_mount != nvp->v_mount) {
2503 					    /*
2504 					     * For a ZFS snapshot, there is a
2505 					     * pseudo mount that does not set
2506 					     * v_mountedhere, so it needs to
2507 					     * be detected via a different
2508 					     * mount structure.
2509 					     */
2510 					    at_root = 1;
2511 					    if (new_mp == mp)
2512 						new_mp = nvp->v_mount;
2513 					}
2514 				}
2515 
2516 				/*
2517 				 * If we failed to get attributes of the entry,
2518 				 * then just skip it for NFSv3 (the traditional
2519 				 * behavior in the old NFS server).
2520 				 * For NFSv4 the behavior is controlled by
2521 				 * RDATTRERROR: we either ignore the error or
2522 				 * fail the request.
2523 				 * Note that RDATTRERROR is never set for NFSv3.
2524 				 */
2525 				if (r != 0) {
2526 					if (!NFSISSET_ATTRBIT(&attrbits,
2527 					    NFSATTRBIT_RDATTRERROR)) {
2528 						vput(nvp);
2529 						if (needs_unbusy != 0)
2530 							vfs_unbusy(new_mp);
2531 						if ((nd->nd_flag & ND_NFSV3))
2532 							goto invalid;
2533 						nd->nd_repstat = r;
2534 						break;
2535 					}
2536 				}
2537 			}
2538 
2539 			/*
2540 			 * Build the directory record xdr
2541 			 */
2542 			if (nd->nd_flag & ND_NFSV3) {
2543 				NFSM_BUILD(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
2544 				*tl++ = newnfs_true;
2545 				*tl++ = 0;
2546 				*tl = txdr_unsigned(dp->d_fileno);
2547 				dirlen += nfsm_strtom(nd, dp->d_name, nlen);
2548 				NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
2549 				*tl++ = 0;
2550 				*tl = txdr_unsigned(*cookiep);
2551 				nfsrv_postopattr(nd, 0, nvap);
2552 				dirlen += nfsm_fhtom(nd,(u_int8_t *)&nfh,0,1);
2553 				dirlen += (5*NFSX_UNSIGNED+NFSX_V3POSTOPATTR);
2554 				if (nvp != NULL)
2555 					vput(nvp);
2556 			} else {
2557 				NFSM_BUILD(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
2558 				*tl++ = newnfs_true;
2559 				*tl++ = 0;
2560 				*tl = txdr_unsigned(*cookiep);
2561 				dirlen += nfsm_strtom(nd, dp->d_name, nlen);
2562 				if (nvp != NULL) {
2563 					supports_nfsv4acls =
2564 					    nfs_supportsnfsv4acls(nvp);
2565 					NFSVOPUNLOCK(nvp);
2566 				} else
2567 					supports_nfsv4acls = 0;
2568 				if (refp != NULL) {
2569 					dirlen += nfsrv_putreferralattr(nd,
2570 					    &savbits, refp, 0,
2571 					    &nd->nd_repstat);
2572 					if (nd->nd_repstat) {
2573 						if (nvp != NULL)
2574 							vrele(nvp);
2575 						if (needs_unbusy != 0)
2576 							vfs_unbusy(new_mp);
2577 						break;
2578 					}
2579 				} else if (r) {
2580 					dirlen += nfsvno_fillattr(nd, new_mp,
2581 					    nvp, nvap, &nfh, r, &rderrbits,
2582 					    nd->nd_cred, p, isdgram, 0,
2583 					    supports_nfsv4acls, at_root,
2584 					    mounted_on_fileno);
2585 				} else {
2586 					dirlen += nfsvno_fillattr(nd, new_mp,
2587 					    nvp, nvap, &nfh, r, &attrbits,
2588 					    nd->nd_cred, p, isdgram, 0,
2589 					    supports_nfsv4acls, at_root,
2590 					    mounted_on_fileno);
2591 				}
2592 				if (nvp != NULL)
2593 					vrele(nvp);
2594 				dirlen += (3 * NFSX_UNSIGNED);
2595 			}
2596 			if (needs_unbusy != 0)
2597 				vfs_unbusy(new_mp);
2598 			if (dirlen <= cnt)
2599 				entrycnt++;
2600 		}
2601 invalid:
2602 		cpos += dp->d_reclen;
2603 		dp = (struct dirent *)cpos;
2604 		cookiep++;
2605 		ncookies--;
2606 	}
2607 	vrele(vp);
2608 	vfs_unbusy(mp);
2609 
2610 	/*
2611 	 * If dirlen > cnt, we must strip off the last entry. If that
2612 	 * results in an empty reply, report NFSERR_TOOSMALL.
2613 	 */
2614 	if (dirlen > cnt || nd->nd_repstat) {
2615 		if (!nd->nd_repstat && entrycnt == 0)
2616 			nd->nd_repstat = NFSERR_TOOSMALL;
2617 		if (nd->nd_repstat) {
2618 			newnfs_trimtrailing(nd, mb0, bpos0);
2619 			if (nd->nd_flag & ND_NFSV3)
2620 				nfsrv_postopattr(nd, getret, &at);
2621 		} else
2622 			newnfs_trimtrailing(nd, mb1, bpos1);
2623 		eofflag = 0;
2624 	} else if (cpos < cend)
2625 		eofflag = 0;
2626 	if (!nd->nd_repstat) {
2627 		NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
2628 		*tl++ = newnfs_false;
2629 		if (eofflag)
2630 			*tl = newnfs_true;
2631 		else
2632 			*tl = newnfs_false;
2633 	}
2634 	free(cookies, M_TEMP);
2635 	free(rbuf, M_TEMP);
2636 
2637 out:
2638 	NFSEXITCODE2(0, nd);
2639 	return (0);
2640 nfsmout:
2641 	vput(vp);
2642 	NFSEXITCODE2(error, nd);
2643 	return (error);
2644 }
2645 
2646 /*
2647  * Get the settable attributes out of the mbuf list.
2648  * (Return 0 or EBADRPC)
2649  */
2650 int
2651 nfsrv_sattr(struct nfsrv_descript *nd, vnode_t vp, struct nfsvattr *nvap,
2652     nfsattrbit_t *attrbitp, NFSACL_T *aclp, struct thread *p)
2653 {
2654 	u_int32_t *tl;
2655 	struct nfsv2_sattr *sp;
2656 	int error = 0, toclient = 0;
2657 
2658 	switch (nd->nd_flag & (ND_NFSV2 | ND_NFSV3 | ND_NFSV4)) {
2659 	case ND_NFSV2:
2660 		NFSM_DISSECT(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
2661 		/*
2662 		 * Some old clients didn't fill in the high order 16bits.
2663 		 * --> check the low order 2 bytes for 0xffff
2664 		 */
2665 		if ((fxdr_unsigned(int, sp->sa_mode) & 0xffff) != 0xffff)
2666 			nvap->na_mode = nfstov_mode(sp->sa_mode);
2667 		if (sp->sa_uid != newnfs_xdrneg1)
2668 			nvap->na_uid = fxdr_unsigned(uid_t, sp->sa_uid);
2669 		if (sp->sa_gid != newnfs_xdrneg1)
2670 			nvap->na_gid = fxdr_unsigned(gid_t, sp->sa_gid);
2671 		if (sp->sa_size != newnfs_xdrneg1)
2672 			nvap->na_size = fxdr_unsigned(u_quad_t, sp->sa_size);
2673 		if (sp->sa_atime.nfsv2_sec != newnfs_xdrneg1) {
2674 #ifdef notyet
2675 			fxdr_nfsv2time(&sp->sa_atime, &nvap->na_atime);
2676 #else
2677 			nvap->na_atime.tv_sec =
2678 				fxdr_unsigned(u_int32_t,sp->sa_atime.nfsv2_sec);
2679 			nvap->na_atime.tv_nsec = 0;
2680 #endif
2681 		}
2682 		if (sp->sa_mtime.nfsv2_sec != newnfs_xdrneg1)
2683 			fxdr_nfsv2time(&sp->sa_mtime, &nvap->na_mtime);
2684 		break;
2685 	case ND_NFSV3:
2686 		NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
2687 		if (*tl == newnfs_true) {
2688 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
2689 			nvap->na_mode = nfstov_mode(*tl);
2690 		}
2691 		NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
2692 		if (*tl == newnfs_true) {
2693 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
2694 			nvap->na_uid = fxdr_unsigned(uid_t, *tl);
2695 		}
2696 		NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
2697 		if (*tl == newnfs_true) {
2698 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
2699 			nvap->na_gid = fxdr_unsigned(gid_t, *tl);
2700 		}
2701 		NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
2702 		if (*tl == newnfs_true) {
2703 			NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
2704 			nvap->na_size = fxdr_hyper(tl);
2705 		}
2706 		NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
2707 		switch (fxdr_unsigned(int, *tl)) {
2708 		case NFSV3SATTRTIME_TOCLIENT:
2709 			NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
2710 			fxdr_nfsv3time(tl, &nvap->na_atime);
2711 			toclient = 1;
2712 			break;
2713 		case NFSV3SATTRTIME_TOSERVER:
2714 			vfs_timestamp(&nvap->na_atime);
2715 			nvap->na_vaflags |= VA_UTIMES_NULL;
2716 			break;
2717 		}
2718 		NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
2719 		switch (fxdr_unsigned(int, *tl)) {
2720 		case NFSV3SATTRTIME_TOCLIENT:
2721 			NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
2722 			fxdr_nfsv3time(tl, &nvap->na_mtime);
2723 			nvap->na_vaflags &= ~VA_UTIMES_NULL;
2724 			break;
2725 		case NFSV3SATTRTIME_TOSERVER:
2726 			vfs_timestamp(&nvap->na_mtime);
2727 			if (!toclient)
2728 				nvap->na_vaflags |= VA_UTIMES_NULL;
2729 			break;
2730 		}
2731 		break;
2732 	case ND_NFSV4:
2733 		error = nfsv4_sattr(nd, vp, nvap, attrbitp, aclp, p);
2734 	}
2735 nfsmout:
2736 	NFSEXITCODE2(error, nd);
2737 	return (error);
2738 }
2739 
2740 /*
2741  * Handle the setable attributes for V4.
2742  * Returns NFSERR_BADXDR if it can't be parsed, 0 otherwise.
2743  */
2744 int
2745 nfsv4_sattr(struct nfsrv_descript *nd, vnode_t vp, struct nfsvattr *nvap,
2746     nfsattrbit_t *attrbitp, NFSACL_T *aclp, struct thread *p)
2747 {
2748 	u_int32_t *tl;
2749 	int attrsum = 0;
2750 	int i, j;
2751 	int error, attrsize, bitpos, aclsize, aceerr, retnotsup = 0;
2752 	int moderet, toclient = 0;
2753 	u_char *cp, namestr[NFSV4_SMALLSTR + 1];
2754 	uid_t uid;
2755 	gid_t gid;
2756 	u_short mode, mask;		/* Same type as va_mode. */
2757 	struct vattr va;
2758 
2759 	error = nfsrv_getattrbits(nd, attrbitp, NULL, &retnotsup);
2760 	if (error)
2761 		goto nfsmout;
2762 	NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
2763 	attrsize = fxdr_unsigned(int, *tl);
2764 
2765 	/*
2766 	 * Loop around getting the setable attributes. If an unsupported
2767 	 * one is found, set nd_repstat == NFSERR_ATTRNOTSUPP and return.
2768 	 */
2769 	if (retnotsup) {
2770 		nd->nd_repstat = NFSERR_ATTRNOTSUPP;
2771 		bitpos = NFSATTRBIT_MAX;
2772 	} else {
2773 		bitpos = 0;
2774 	}
2775 	moderet = 0;
2776 	for (; bitpos < NFSATTRBIT_MAX; bitpos++) {
2777 	    if (attrsum > attrsize) {
2778 		error = NFSERR_BADXDR;
2779 		goto nfsmout;
2780 	    }
2781 	    if (NFSISSET_ATTRBIT(attrbitp, bitpos))
2782 		switch (bitpos) {
2783 		case NFSATTRBIT_SIZE:
2784 			NFSM_DISSECT(tl, u_int32_t *, NFSX_HYPER);
2785                      if (vp != NULL && vp->v_type != VREG) {
2786                             error = (vp->v_type == VDIR) ? NFSERR_ISDIR :
2787                                 NFSERR_INVAL;
2788                             goto nfsmout;
2789 			}
2790 			nvap->na_size = fxdr_hyper(tl);
2791 			attrsum += NFSX_HYPER;
2792 			break;
2793 		case NFSATTRBIT_ACL:
2794 			error = nfsrv_dissectacl(nd, aclp, &aceerr, &aclsize,
2795 			    p);
2796 			if (error)
2797 				goto nfsmout;
2798 			if (aceerr && !nd->nd_repstat)
2799 				nd->nd_repstat = aceerr;
2800 			attrsum += aclsize;
2801 			break;
2802 		case NFSATTRBIT_ARCHIVE:
2803 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
2804 			if (!nd->nd_repstat)
2805 				nd->nd_repstat = NFSERR_ATTRNOTSUPP;
2806 			attrsum += NFSX_UNSIGNED;
2807 			break;
2808 		case NFSATTRBIT_HIDDEN:
2809 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
2810 			if (!nd->nd_repstat)
2811 				nd->nd_repstat = NFSERR_ATTRNOTSUPP;
2812 			attrsum += NFSX_UNSIGNED;
2813 			break;
2814 		case NFSATTRBIT_MIMETYPE:
2815 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
2816 			i = fxdr_unsigned(int, *tl);
2817 			error = nfsm_advance(nd, NFSM_RNDUP(i), -1);
2818 			if (error)
2819 				goto nfsmout;
2820 			if (!nd->nd_repstat)
2821 				nd->nd_repstat = NFSERR_ATTRNOTSUPP;
2822 			attrsum += (NFSX_UNSIGNED + NFSM_RNDUP(i));
2823 			break;
2824 		case NFSATTRBIT_MODE:
2825 			moderet = NFSERR_INVAL;	/* Can't do MODESETMASKED. */
2826 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
2827 			nvap->na_mode = nfstov_mode(*tl);
2828 			attrsum += NFSX_UNSIGNED;
2829 			break;
2830 		case NFSATTRBIT_OWNER:
2831 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
2832 			j = fxdr_unsigned(int, *tl);
2833 			if (j < 0) {
2834 				error = NFSERR_BADXDR;
2835 				goto nfsmout;
2836 			}
2837 			if (j > NFSV4_SMALLSTR)
2838 				cp = malloc(j + 1, M_NFSSTRING, M_WAITOK);
2839 			else
2840 				cp = namestr;
2841 			error = nfsrv_mtostr(nd, cp, j);
2842 			if (error) {
2843 				if (j > NFSV4_SMALLSTR)
2844 					free(cp, M_NFSSTRING);
2845 				goto nfsmout;
2846 			}
2847 			if (!nd->nd_repstat) {
2848 				nd->nd_repstat = nfsv4_strtouid(nd, cp, j,
2849 				    &uid);
2850 				if (!nd->nd_repstat)
2851 					nvap->na_uid = uid;
2852 			}
2853 			if (j > NFSV4_SMALLSTR)
2854 				free(cp, M_NFSSTRING);
2855 			attrsum += (NFSX_UNSIGNED + NFSM_RNDUP(j));
2856 			break;
2857 		case NFSATTRBIT_OWNERGROUP:
2858 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
2859 			j = fxdr_unsigned(int, *tl);
2860 			if (j < 0) {
2861 				error = NFSERR_BADXDR;
2862 				goto nfsmout;
2863 			}
2864 			if (j > NFSV4_SMALLSTR)
2865 				cp = malloc(j + 1, M_NFSSTRING, M_WAITOK);
2866 			else
2867 				cp = namestr;
2868 			error = nfsrv_mtostr(nd, cp, j);
2869 			if (error) {
2870 				if (j > NFSV4_SMALLSTR)
2871 					free(cp, M_NFSSTRING);
2872 				goto nfsmout;
2873 			}
2874 			if (!nd->nd_repstat) {
2875 				nd->nd_repstat = nfsv4_strtogid(nd, cp, j,
2876 				    &gid);
2877 				if (!nd->nd_repstat)
2878 					nvap->na_gid = gid;
2879 			}
2880 			if (j > NFSV4_SMALLSTR)
2881 				free(cp, M_NFSSTRING);
2882 			attrsum += (NFSX_UNSIGNED + NFSM_RNDUP(j));
2883 			break;
2884 		case NFSATTRBIT_SYSTEM:
2885 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
2886 			if (!nd->nd_repstat)
2887 				nd->nd_repstat = NFSERR_ATTRNOTSUPP;
2888 			attrsum += NFSX_UNSIGNED;
2889 			break;
2890 		case NFSATTRBIT_TIMEACCESSSET:
2891 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
2892 			attrsum += NFSX_UNSIGNED;
2893 			if (fxdr_unsigned(int, *tl)==NFSV4SATTRTIME_TOCLIENT) {
2894 			    NFSM_DISSECT(tl, u_int32_t *, NFSX_V4TIME);
2895 			    fxdr_nfsv4time(tl, &nvap->na_atime);
2896 			    toclient = 1;
2897 			    attrsum += NFSX_V4TIME;
2898 			} else {
2899 			    vfs_timestamp(&nvap->na_atime);
2900 			    nvap->na_vaflags |= VA_UTIMES_NULL;
2901 			}
2902 			break;
2903 		case NFSATTRBIT_TIMEBACKUP:
2904 			NFSM_DISSECT(tl, u_int32_t *, NFSX_V4TIME);
2905 			if (!nd->nd_repstat)
2906 				nd->nd_repstat = NFSERR_ATTRNOTSUPP;
2907 			attrsum += NFSX_V4TIME;
2908 			break;
2909 		case NFSATTRBIT_TIMECREATE:
2910 			NFSM_DISSECT(tl, u_int32_t *, NFSX_V4TIME);
2911 			if (!nd->nd_repstat)
2912 				nd->nd_repstat = NFSERR_ATTRNOTSUPP;
2913 			attrsum += NFSX_V4TIME;
2914 			break;
2915 		case NFSATTRBIT_TIMEMODIFYSET:
2916 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
2917 			attrsum += NFSX_UNSIGNED;
2918 			if (fxdr_unsigned(int, *tl)==NFSV4SATTRTIME_TOCLIENT) {
2919 			    NFSM_DISSECT(tl, u_int32_t *, NFSX_V4TIME);
2920 			    fxdr_nfsv4time(tl, &nvap->na_mtime);
2921 			    nvap->na_vaflags &= ~VA_UTIMES_NULL;
2922 			    attrsum += NFSX_V4TIME;
2923 			} else {
2924 			    vfs_timestamp(&nvap->na_mtime);
2925 			    if (!toclient)
2926 				nvap->na_vaflags |= VA_UTIMES_NULL;
2927 			}
2928 			break;
2929 		case NFSATTRBIT_MODESETMASKED:
2930 			NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED);
2931 			mode = fxdr_unsigned(u_short, *tl++);
2932 			mask = fxdr_unsigned(u_short, *tl);
2933 			/*
2934 			 * vp == NULL implies an Open/Create operation.
2935 			 * This attribute can only be used for Setattr and
2936 			 * only for NFSv4.1 or higher.
2937 			 * If moderet != 0, a mode attribute has also been
2938 			 * specified and this attribute cannot be done in the
2939 			 * same Setattr operation.
2940 			 */
2941 			if ((nd->nd_flag & ND_NFSV41) == 0)
2942 				nd->nd_repstat = NFSERR_ATTRNOTSUPP;
2943 			else if ((mode & ~07777) != 0 || (mask & ~07777) != 0 ||
2944 			    vp == NULL)
2945 				nd->nd_repstat = NFSERR_INVAL;
2946 			else if (moderet == 0)
2947 				moderet = VOP_GETATTR(vp, &va, nd->nd_cred);
2948 			if (moderet == 0)
2949 				nvap->na_mode = (mode & mask) |
2950 				    (va.va_mode & ~mask);
2951 			else
2952 				nd->nd_repstat = moderet;
2953 			attrsum += 2 * NFSX_UNSIGNED;
2954 			break;
2955 		default:
2956 			nd->nd_repstat = NFSERR_ATTRNOTSUPP;
2957 			/*
2958 			 * set bitpos so we drop out of the loop.
2959 			 */
2960 			bitpos = NFSATTRBIT_MAX;
2961 			break;
2962 		}
2963 	}
2964 
2965 	/*
2966 	 * some clients pad the attrlist, so we need to skip over the
2967 	 * padding.
2968 	 */
2969 	if (attrsum > attrsize) {
2970 		error = NFSERR_BADXDR;
2971 	} else {
2972 		attrsize = NFSM_RNDUP(attrsize);
2973 		if (attrsum < attrsize)
2974 			error = nfsm_advance(nd, attrsize - attrsum, -1);
2975 	}
2976 nfsmout:
2977 	NFSEXITCODE2(error, nd);
2978 	return (error);
2979 }
2980 
2981 /*
2982  * Check/setup export credentials.
2983  */
2984 int
2985 nfsd_excred(struct nfsrv_descript *nd, struct nfsexstuff *exp,
2986     struct ucred *credanon)
2987 {
2988 	int error = 0;
2989 
2990 	/*
2991 	 * Check/setup credentials.
2992 	 */
2993 	if (nd->nd_flag & ND_GSS)
2994 		exp->nes_exflag &= ~MNT_EXPORTANON;
2995 
2996 	/*
2997 	 * Check to see if the operation is allowed for this security flavor.
2998 	 * RFC2623 suggests that the NFSv3 Fsinfo RPC be allowed to
2999 	 * AUTH_NONE or AUTH_SYS for file systems requiring RPCSEC_GSS.
3000 	 * Also, allow Secinfo, so that it can acquire the correct flavor(s).
3001 	 */
3002 	if (nfsvno_testexp(nd, exp) &&
3003 	    nd->nd_procnum != NFSV4OP_SECINFO &&
3004 	    nd->nd_procnum != NFSPROC_FSINFO) {
3005 		if (nd->nd_flag & ND_NFSV4)
3006 			error = NFSERR_WRONGSEC;
3007 		else
3008 			error = (NFSERR_AUTHERR | AUTH_TOOWEAK);
3009 		goto out;
3010 	}
3011 
3012 	/*
3013 	 * Check to see if the file system is exported V4 only.
3014 	 */
3015 	if (NFSVNO_EXV4ONLY(exp) && !(nd->nd_flag & ND_NFSV4)) {
3016 		error = NFSERR_PROGNOTV4;
3017 		goto out;
3018 	}
3019 
3020 	/*
3021 	 * Now, map the user credentials.
3022 	 * (Note that ND_AUTHNONE will only be set for an NFSv3
3023 	 *  Fsinfo RPC. If set for anything else, this code might need
3024 	 *  to change.)
3025 	 */
3026 	if (NFSVNO_EXPORTED(exp)) {
3027 		if (((nd->nd_flag & ND_GSS) == 0 && nd->nd_cred->cr_uid == 0) ||
3028 		     NFSVNO_EXPORTANON(exp) ||
3029 		     (nd->nd_flag & ND_AUTHNONE) != 0) {
3030 			nd->nd_cred->cr_uid = credanon->cr_uid;
3031 			nd->nd_cred->cr_gid = credanon->cr_gid;
3032 			crsetgroups(nd->nd_cred, credanon->cr_ngroups,
3033 			    credanon->cr_groups);
3034 		} else if ((nd->nd_flag & ND_GSS) == 0) {
3035 			/*
3036 			 * If using AUTH_SYS, call nfsrv_getgrpscred() to see
3037 			 * if there is a replacement credential with a group
3038 			 * list set up by "nfsuserd -manage-gids".
3039 			 * If there is no replacement, nfsrv_getgrpscred()
3040 			 * simply returns its argument.
3041 			 */
3042 			nd->nd_cred = nfsrv_getgrpscred(nd->nd_cred);
3043 		}
3044 	}
3045 
3046 out:
3047 	NFSEXITCODE2(error, nd);
3048 	return (error);
3049 }
3050 
3051 /*
3052  * Check exports.
3053  */
3054 int
3055 nfsvno_checkexp(struct mount *mp, struct sockaddr *nam, struct nfsexstuff *exp,
3056     struct ucred **credp)
3057 {
3058 	int i, error, *secflavors;
3059 
3060 	error = VFS_CHECKEXP(mp, nam, &exp->nes_exflag, credp,
3061 	    &exp->nes_numsecflavor, &secflavors);
3062 	if (error) {
3063 		if (nfs_rootfhset) {
3064 			exp->nes_exflag = 0;
3065 			exp->nes_numsecflavor = 0;
3066 			error = 0;
3067 		}
3068 	} else {
3069 		/* Copy the security flavors. */
3070 		for (i = 0; i < exp->nes_numsecflavor; i++)
3071 			exp->nes_secflavors[i] = secflavors[i];
3072 	}
3073 	NFSEXITCODE(error);
3074 	return (error);
3075 }
3076 
3077 /*
3078  * Get a vnode for a file handle and export stuff.
3079  */
3080 int
3081 nfsvno_fhtovp(struct mount *mp, fhandle_t *fhp, struct sockaddr *nam,
3082     int lktype, struct vnode **vpp, struct nfsexstuff *exp,
3083     struct ucred **credp)
3084 {
3085 	int i, error, *secflavors;
3086 
3087 	*credp = NULL;
3088 	exp->nes_numsecflavor = 0;
3089 	error = VFS_FHTOVP(mp, &fhp->fh_fid, lktype, vpp);
3090 	if (error != 0)
3091 		/* Make sure the server replies ESTALE to the client. */
3092 		error = ESTALE;
3093 	if (nam && !error) {
3094 		error = VFS_CHECKEXP(mp, nam, &exp->nes_exflag, credp,
3095 		    &exp->nes_numsecflavor, &secflavors);
3096 		if (error) {
3097 			if (nfs_rootfhset) {
3098 				exp->nes_exflag = 0;
3099 				exp->nes_numsecflavor = 0;
3100 				error = 0;
3101 			} else {
3102 				vput(*vpp);
3103 			}
3104 		} else {
3105 			/* Copy the security flavors. */
3106 			for (i = 0; i < exp->nes_numsecflavor; i++)
3107 				exp->nes_secflavors[i] = secflavors[i];
3108 		}
3109 	}
3110 	NFSEXITCODE(error);
3111 	return (error);
3112 }
3113 
3114 /*
3115  * nfsd_fhtovp() - convert a fh to a vnode ptr
3116  * 	- look up fsid in mount list (if not found ret error)
3117  *	- get vp and export rights by calling nfsvno_fhtovp()
3118  *	- if cred->cr_uid == 0 or MNT_EXPORTANON set it to credanon
3119  *	  for AUTH_SYS
3120  *	- if mpp != NULL, return the mount point so that it can
3121  *	  be used for vn_finished_write() by the caller
3122  */
3123 void
3124 nfsd_fhtovp(struct nfsrv_descript *nd, struct nfsrvfh *nfp, int lktype,
3125     struct vnode **vpp, struct nfsexstuff *exp,
3126     struct mount **mpp, int startwrite)
3127 {
3128 	struct mount *mp;
3129 	struct ucred *credanon;
3130 	fhandle_t *fhp;
3131 
3132 	fhp = (fhandle_t *)nfp->nfsrvfh_data;
3133 	/*
3134 	 * Check for the special case of the nfsv4root_fh.
3135 	 */
3136 	mp = vfs_busyfs(&fhp->fh_fsid);
3137 	if (mpp != NULL)
3138 		*mpp = mp;
3139 	if (mp == NULL) {
3140 		*vpp = NULL;
3141 		nd->nd_repstat = ESTALE;
3142 		goto out;
3143 	}
3144 
3145 	if (startwrite) {
3146 		vn_start_write(NULL, mpp, V_WAIT);
3147 		if (lktype == LK_SHARED && !(MNT_SHARED_WRITES(mp)))
3148 			lktype = LK_EXCLUSIVE;
3149 	}
3150 	nd->nd_repstat = nfsvno_fhtovp(mp, fhp, nd->nd_nam, lktype, vpp, exp,
3151 	    &credanon);
3152 	vfs_unbusy(mp);
3153 
3154 	/*
3155 	 * For NFSv4 without a pseudo root fs, unexported file handles
3156 	 * can be returned, so that Lookup works everywhere.
3157 	 */
3158 	if (!nd->nd_repstat && exp->nes_exflag == 0 &&
3159 	    !(nd->nd_flag & ND_NFSV4)) {
3160 		vput(*vpp);
3161 		nd->nd_repstat = EACCES;
3162 	}
3163 
3164 	/*
3165 	 * Personally, I've never seen any point in requiring a
3166 	 * reserved port#, since only in the rare case where the
3167 	 * clients are all boxes with secure system privileges,
3168 	 * does it provide any enhanced security, but... some people
3169 	 * believe it to be useful and keep putting this code back in.
3170 	 * (There is also some "security checker" out there that
3171 	 *  complains if the nfs server doesn't enforce this.)
3172 	 * However, note the following:
3173 	 * RFC3530 (NFSv4) specifies that a reserved port# not be
3174 	 *	required.
3175 	 * RFC2623 recommends that, if a reserved port# is checked for,
3176 	 *	that there be a way to turn that off--> ifdef'd.
3177 	 */
3178 #ifdef NFS_REQRSVPORT
3179 	if (!nd->nd_repstat) {
3180 		struct sockaddr_in *saddr;
3181 		struct sockaddr_in6 *saddr6;
3182 
3183 		saddr = NFSSOCKADDR(nd->nd_nam, struct sockaddr_in *);
3184 		saddr6 = NFSSOCKADDR(nd->nd_nam, struct sockaddr_in6 *);
3185 		if (!(nd->nd_flag & ND_NFSV4) &&
3186 		    ((saddr->sin_family == AF_INET &&
3187 		      ntohs(saddr->sin_port) >= IPPORT_RESERVED) ||
3188 		     (saddr6->sin6_family == AF_INET6 &&
3189 		      ntohs(saddr6->sin6_port) >= IPPORT_RESERVED))) {
3190 			vput(*vpp);
3191 			nd->nd_repstat = (NFSERR_AUTHERR | AUTH_TOOWEAK);
3192 		}
3193 	}
3194 #endif	/* NFS_REQRSVPORT */
3195 
3196 	/*
3197 	 * Check/setup credentials.
3198 	 */
3199 	if (!nd->nd_repstat) {
3200 		nd->nd_saveduid = nd->nd_cred->cr_uid;
3201 		nd->nd_repstat = nfsd_excred(nd, exp, credanon);
3202 		if (nd->nd_repstat)
3203 			vput(*vpp);
3204 	}
3205 	if (credanon != NULL)
3206 		crfree(credanon);
3207 	if (nd->nd_repstat) {
3208 		if (startwrite)
3209 			vn_finished_write(mp);
3210 		*vpp = NULL;
3211 		if (mpp != NULL)
3212 			*mpp = NULL;
3213 	}
3214 
3215 out:
3216 	NFSEXITCODE2(0, nd);
3217 }
3218 
3219 /*
3220  * glue for fp.
3221  */
3222 static int
3223 fp_getfvp(struct thread *p, int fd, struct file **fpp, struct vnode **vpp)
3224 {
3225 	struct filedesc *fdp;
3226 	struct file *fp;
3227 	int error = 0;
3228 
3229 	fdp = p->td_proc->p_fd;
3230 	if (fd < 0 || fd >= fdp->fd_nfiles ||
3231 	    (fp = fdp->fd_ofiles[fd].fde_file) == NULL) {
3232 		error = EBADF;
3233 		goto out;
3234 	}
3235 	*fpp = fp;
3236 
3237 out:
3238 	NFSEXITCODE(error);
3239 	return (error);
3240 }
3241 
3242 /*
3243  * Called from nfssvc() to update the exports list. Just call
3244  * vfs_export(). This has to be done, since the v4 root fake fs isn't
3245  * in the mount list.
3246  */
3247 int
3248 nfsrv_v4rootexport(void *argp, struct ucred *cred, struct thread *p)
3249 {
3250 	struct nfsex_args *nfsexargp = (struct nfsex_args *)argp;
3251 	int error = 0;
3252 	struct nameidata nd;
3253 	fhandle_t fh;
3254 
3255 	error = vfs_export(&nfsv4root_mnt, &nfsexargp->export);
3256 	if ((nfsexargp->export.ex_flags & MNT_DELEXPORT) != 0)
3257 		nfs_rootfhset = 0;
3258 	else if (error == 0) {
3259 		if (nfsexargp->fspec == NULL) {
3260 			error = EPERM;
3261 			goto out;
3262 		}
3263 		/*
3264 		 * If fspec != NULL, this is the v4root path.
3265 		 */
3266 		NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE,
3267 		    nfsexargp->fspec, p);
3268 		if ((error = namei(&nd)) != 0)
3269 			goto out;
3270 		error = nfsvno_getfh(nd.ni_vp, &fh, p);
3271 		vrele(nd.ni_vp);
3272 		if (!error) {
3273 			nfs_rootfh.nfsrvfh_len = NFSX_MYFH;
3274 			NFSBCOPY((caddr_t)&fh,
3275 			    nfs_rootfh.nfsrvfh_data,
3276 			    sizeof (fhandle_t));
3277 			nfs_rootfhset = 1;
3278 		}
3279 	}
3280 
3281 out:
3282 	NFSEXITCODE(error);
3283 	return (error);
3284 }
3285 
3286 /*
3287  * This function needs to test to see if the system is near its limit
3288  * for memory allocation via malloc() or mget() and return True iff
3289  * either of these resources are near their limit.
3290  * XXX (For now, this is just a stub.)
3291  */
3292 int nfsrv_testmalloclimit = 0;
3293 int
3294 nfsrv_mallocmget_limit(void)
3295 {
3296 	static int printmesg = 0;
3297 	static int testval = 1;
3298 
3299 	if (nfsrv_testmalloclimit && (testval++ % 1000) == 0) {
3300 		if ((printmesg++ % 100) == 0)
3301 			printf("nfsd: malloc/mget near limit\n");
3302 		return (1);
3303 	}
3304 	return (0);
3305 }
3306 
3307 /*
3308  * BSD specific initialization of a mount point.
3309  */
3310 void
3311 nfsd_mntinit(void)
3312 {
3313 	static int inited = 0;
3314 
3315 	if (inited)
3316 		return;
3317 	inited = 1;
3318 	nfsv4root_mnt.mnt_flag = (MNT_RDONLY | MNT_EXPORTED);
3319 	TAILQ_INIT(&nfsv4root_mnt.mnt_nvnodelist);
3320 	TAILQ_INIT(&nfsv4root_mnt.mnt_lazyvnodelist);
3321 	nfsv4root_mnt.mnt_export = NULL;
3322 	TAILQ_INIT(&nfsv4root_opt);
3323 	TAILQ_INIT(&nfsv4root_newopt);
3324 	nfsv4root_mnt.mnt_opt = &nfsv4root_opt;
3325 	nfsv4root_mnt.mnt_optnew = &nfsv4root_newopt;
3326 	nfsv4root_mnt.mnt_nvnodelistsize = 0;
3327 	nfsv4root_mnt.mnt_lazyvnodelistsize = 0;
3328 }
3329 
3330 /*
3331  * Get a vnode for a file handle, without checking exports, etc.
3332  */
3333 struct vnode *
3334 nfsvno_getvp(fhandle_t *fhp)
3335 {
3336 	struct mount *mp;
3337 	struct vnode *vp;
3338 	int error;
3339 
3340 	mp = vfs_busyfs(&fhp->fh_fsid);
3341 	if (mp == NULL)
3342 		return (NULL);
3343 	error = VFS_FHTOVP(mp, &fhp->fh_fid, LK_EXCLUSIVE, &vp);
3344 	vfs_unbusy(mp);
3345 	if (error)
3346 		return (NULL);
3347 	return (vp);
3348 }
3349 
3350 /*
3351  * Do a local VOP_ADVLOCK().
3352  */
3353 int
3354 nfsvno_advlock(struct vnode *vp, int ftype, u_int64_t first,
3355     u_int64_t end, struct thread *td)
3356 {
3357 	int error = 0;
3358 	struct flock fl;
3359 	u_int64_t tlen;
3360 
3361 	if (nfsrv_dolocallocks == 0)
3362 		goto out;
3363 	ASSERT_VOP_UNLOCKED(vp, "nfsvno_advlock: vp locked");
3364 
3365 	fl.l_whence = SEEK_SET;
3366 	fl.l_type = ftype;
3367 	fl.l_start = (off_t)first;
3368 	if (end == NFS64BITSSET) {
3369 		fl.l_len = 0;
3370 	} else {
3371 		tlen = end - first;
3372 		fl.l_len = (off_t)tlen;
3373 	}
3374 	/*
3375 	 * For FreeBSD8, the l_pid and l_sysid must be set to the same
3376 	 * values for all calls, so that all locks will be held by the
3377 	 * nfsd server. (The nfsd server handles conflicts between the
3378 	 * various clients.)
3379 	 * Since an NFSv4 lockowner is a ClientID plus an array of up to 1024
3380 	 * bytes, so it can't be put in l_sysid.
3381 	 */
3382 	if (nfsv4_sysid == 0)
3383 		nfsv4_sysid = nlm_acquire_next_sysid();
3384 	fl.l_pid = (pid_t)0;
3385 	fl.l_sysid = (int)nfsv4_sysid;
3386 
3387 	if (ftype == F_UNLCK)
3388 		error = VOP_ADVLOCK(vp, (caddr_t)td->td_proc, F_UNLCK, &fl,
3389 		    (F_POSIX | F_REMOTE));
3390 	else
3391 		error = VOP_ADVLOCK(vp, (caddr_t)td->td_proc, F_SETLK, &fl,
3392 		    (F_POSIX | F_REMOTE));
3393 
3394 out:
3395 	NFSEXITCODE(error);
3396 	return (error);
3397 }
3398 
3399 /*
3400  * Check the nfsv4 root exports.
3401  */
3402 int
3403 nfsvno_v4rootexport(struct nfsrv_descript *nd)
3404 {
3405 	struct ucred *credanon;
3406 	int exflags, error = 0, numsecflavor, *secflavors, i;
3407 
3408 	error = vfs_stdcheckexp(&nfsv4root_mnt, nd->nd_nam, &exflags,
3409 	    &credanon, &numsecflavor, &secflavors);
3410 	if (error) {
3411 		error = NFSERR_PROGUNAVAIL;
3412 		goto out;
3413 	}
3414 	if (credanon != NULL)
3415 		crfree(credanon);
3416 	for (i = 0; i < numsecflavor; i++) {
3417 		if (secflavors[i] == AUTH_SYS)
3418 			nd->nd_flag |= ND_EXAUTHSYS;
3419 		else if (secflavors[i] == RPCSEC_GSS_KRB5)
3420 			nd->nd_flag |= ND_EXGSS;
3421 		else if (secflavors[i] == RPCSEC_GSS_KRB5I)
3422 			nd->nd_flag |= ND_EXGSSINTEGRITY;
3423 		else if (secflavors[i] == RPCSEC_GSS_KRB5P)
3424 			nd->nd_flag |= ND_EXGSSPRIVACY;
3425 	}
3426 
3427 out:
3428 	NFSEXITCODE(error);
3429 	return (error);
3430 }
3431 
3432 /*
3433  * Nfs server pseudo system call for the nfsd's
3434  */
3435 /*
3436  * MPSAFE
3437  */
3438 static int
3439 nfssvc_nfsd(struct thread *td, struct nfssvc_args *uap)
3440 {
3441 	struct file *fp;
3442 	struct nfsd_addsock_args sockarg;
3443 	struct nfsd_nfsd_args nfsdarg;
3444 	struct nfsd_nfsd_oargs onfsdarg;
3445 	struct nfsd_pnfsd_args pnfsdarg;
3446 	struct vnode *vp, *nvp, *curdvp;
3447 	struct pnfsdsfile *pf;
3448 	struct nfsdevice *ds, *fds;
3449 	cap_rights_t rights;
3450 	int buflen, error, ret;
3451 	char *buf, *cp, *cp2, *cp3;
3452 	char fname[PNFS_FILENAME_LEN + 1];
3453 
3454 	if (uap->flag & NFSSVC_NFSDADDSOCK) {
3455 		error = copyin(uap->argp, (caddr_t)&sockarg, sizeof (sockarg));
3456 		if (error)
3457 			goto out;
3458 		/*
3459 		 * Since we don't know what rights might be required,
3460 		 * pretend that we need them all. It is better to be too
3461 		 * careful than too reckless.
3462 		 */
3463 		error = fget(td, sockarg.sock,
3464 		    cap_rights_init(&rights, CAP_SOCK_SERVER), &fp);
3465 		if (error != 0)
3466 			goto out;
3467 		if (fp->f_type != DTYPE_SOCKET) {
3468 			fdrop(fp, td);
3469 			error = EPERM;
3470 			goto out;
3471 		}
3472 		error = nfsrvd_addsock(fp);
3473 		fdrop(fp, td);
3474 	} else if (uap->flag & NFSSVC_NFSDNFSD) {
3475 		if (uap->argp == NULL) {
3476 			error = EINVAL;
3477 			goto out;
3478 		}
3479 		if ((uap->flag & NFSSVC_NEWSTRUCT) == 0) {
3480 			error = copyin(uap->argp, &onfsdarg, sizeof(onfsdarg));
3481 			if (error == 0) {
3482 				nfsdarg.principal = onfsdarg.principal;
3483 				nfsdarg.minthreads = onfsdarg.minthreads;
3484 				nfsdarg.maxthreads = onfsdarg.maxthreads;
3485 				nfsdarg.version = 1;
3486 				nfsdarg.addr = NULL;
3487 				nfsdarg.addrlen = 0;
3488 				nfsdarg.dnshost = NULL;
3489 				nfsdarg.dnshostlen = 0;
3490 				nfsdarg.dspath = NULL;
3491 				nfsdarg.dspathlen = 0;
3492 				nfsdarg.mdspath = NULL;
3493 				nfsdarg.mdspathlen = 0;
3494 				nfsdarg.mirrorcnt = 1;
3495 			}
3496 		} else
3497 			error = copyin(uap->argp, &nfsdarg, sizeof(nfsdarg));
3498 		if (error)
3499 			goto out;
3500 		if (nfsdarg.addrlen > 0 && nfsdarg.addrlen < 10000 &&
3501 		    nfsdarg.dnshostlen > 0 && nfsdarg.dnshostlen < 10000 &&
3502 		    nfsdarg.dspathlen > 0 && nfsdarg.dspathlen < 10000 &&
3503 		    nfsdarg.mdspathlen > 0 && nfsdarg.mdspathlen < 10000 &&
3504 		    nfsdarg.mirrorcnt >= 1 &&
3505 		    nfsdarg.mirrorcnt <= NFSDEV_MAXMIRRORS &&
3506 		    nfsdarg.addr != NULL && nfsdarg.dnshost != NULL &&
3507 		    nfsdarg.dspath != NULL && nfsdarg.mdspath != NULL) {
3508 			NFSD_DEBUG(1, "addrlen=%d dspathlen=%d dnslen=%d"
3509 			    " mdspathlen=%d mirrorcnt=%d\n", nfsdarg.addrlen,
3510 			    nfsdarg.dspathlen, nfsdarg.dnshostlen,
3511 			    nfsdarg.mdspathlen, nfsdarg.mirrorcnt);
3512 			cp = malloc(nfsdarg.addrlen + 1, M_TEMP, M_WAITOK);
3513 			error = copyin(nfsdarg.addr, cp, nfsdarg.addrlen);
3514 			if (error != 0) {
3515 				free(cp, M_TEMP);
3516 				goto out;
3517 			}
3518 			cp[nfsdarg.addrlen] = '\0';	/* Ensure nul term. */
3519 			nfsdarg.addr = cp;
3520 			cp = malloc(nfsdarg.dnshostlen + 1, M_TEMP, M_WAITOK);
3521 			error = copyin(nfsdarg.dnshost, cp, nfsdarg.dnshostlen);
3522 			if (error != 0) {
3523 				free(nfsdarg.addr, M_TEMP);
3524 				free(cp, M_TEMP);
3525 				goto out;
3526 			}
3527 			cp[nfsdarg.dnshostlen] = '\0';	/* Ensure nul term. */
3528 			nfsdarg.dnshost = cp;
3529 			cp = malloc(nfsdarg.dspathlen + 1, M_TEMP, M_WAITOK);
3530 			error = copyin(nfsdarg.dspath, cp, nfsdarg.dspathlen);
3531 			if (error != 0) {
3532 				free(nfsdarg.addr, M_TEMP);
3533 				free(nfsdarg.dnshost, M_TEMP);
3534 				free(cp, M_TEMP);
3535 				goto out;
3536 			}
3537 			cp[nfsdarg.dspathlen] = '\0';	/* Ensure nul term. */
3538 			nfsdarg.dspath = cp;
3539 			cp = malloc(nfsdarg.mdspathlen + 1, M_TEMP, M_WAITOK);
3540 			error = copyin(nfsdarg.mdspath, cp, nfsdarg.mdspathlen);
3541 			if (error != 0) {
3542 				free(nfsdarg.addr, M_TEMP);
3543 				free(nfsdarg.dnshost, M_TEMP);
3544 				free(nfsdarg.dspath, M_TEMP);
3545 				free(cp, M_TEMP);
3546 				goto out;
3547 			}
3548 			cp[nfsdarg.mdspathlen] = '\0';	/* Ensure nul term. */
3549 			nfsdarg.mdspath = cp;
3550 		} else {
3551 			nfsdarg.addr = NULL;
3552 			nfsdarg.addrlen = 0;
3553 			nfsdarg.dnshost = NULL;
3554 			nfsdarg.dnshostlen = 0;
3555 			nfsdarg.dspath = NULL;
3556 			nfsdarg.dspathlen = 0;
3557 			nfsdarg.mdspath = NULL;
3558 			nfsdarg.mdspathlen = 0;
3559 			nfsdarg.mirrorcnt = 1;
3560 		}
3561 		error = nfsrvd_nfsd(td, &nfsdarg);
3562 		free(nfsdarg.addr, M_TEMP);
3563 		free(nfsdarg.dnshost, M_TEMP);
3564 		free(nfsdarg.dspath, M_TEMP);
3565 		free(nfsdarg.mdspath, M_TEMP);
3566 	} else if (uap->flag & NFSSVC_PNFSDS) {
3567 		error = copyin(uap->argp, &pnfsdarg, sizeof(pnfsdarg));
3568 		if (error == 0 && (pnfsdarg.op == PNFSDOP_DELDSSERVER ||
3569 		    pnfsdarg.op == PNFSDOP_FORCEDELDS)) {
3570 			cp = malloc(PATH_MAX + 1, M_TEMP, M_WAITOK);
3571 			error = copyinstr(pnfsdarg.dspath, cp, PATH_MAX + 1,
3572 			    NULL);
3573 			if (error == 0)
3574 				error = nfsrv_deldsserver(pnfsdarg.op, cp, td);
3575 			free(cp, M_TEMP);
3576 		} else if (error == 0 && pnfsdarg.op == PNFSDOP_COPYMR) {
3577 			cp = malloc(PATH_MAX + 1, M_TEMP, M_WAITOK);
3578 			buflen = sizeof(*pf) * NFSDEV_MAXMIRRORS;
3579 			buf = malloc(buflen, M_TEMP, M_WAITOK);
3580 			error = copyinstr(pnfsdarg.mdspath, cp, PATH_MAX + 1,
3581 			    NULL);
3582 			NFSD_DEBUG(4, "pnfsdcopymr cp mdspath=%d\n", error);
3583 			if (error == 0 && pnfsdarg.dspath != NULL) {
3584 				cp2 = malloc(PATH_MAX + 1, M_TEMP, M_WAITOK);
3585 				error = copyinstr(pnfsdarg.dspath, cp2,
3586 				    PATH_MAX + 1, NULL);
3587 				NFSD_DEBUG(4, "pnfsdcopymr cp dspath=%d\n",
3588 				    error);
3589 			} else
3590 				cp2 = NULL;
3591 			if (error == 0 && pnfsdarg.curdspath != NULL) {
3592 				cp3 = malloc(PATH_MAX + 1, M_TEMP, M_WAITOK);
3593 				error = copyinstr(pnfsdarg.curdspath, cp3,
3594 				    PATH_MAX + 1, NULL);
3595 				NFSD_DEBUG(4, "pnfsdcopymr cp curdspath=%d\n",
3596 				    error);
3597 			} else
3598 				cp3 = NULL;
3599 			curdvp = NULL;
3600 			fds = NULL;
3601 			if (error == 0)
3602 				error = nfsrv_mdscopymr(cp, cp2, cp3, buf,
3603 				    &buflen, fname, td, &vp, &nvp, &pf, &ds,
3604 				    &fds);
3605 			NFSD_DEBUG(4, "nfsrv_mdscopymr=%d\n", error);
3606 			if (error == 0) {
3607 				if (pf->dsf_dir >= nfsrv_dsdirsize) {
3608 					printf("copymr: dsdir out of range\n");
3609 					pf->dsf_dir = 0;
3610 				}
3611 				NFSD_DEBUG(4, "copymr: buflen=%d\n", buflen);
3612 				error = nfsrv_copymr(vp, nvp,
3613 				    ds->nfsdev_dsdir[pf->dsf_dir], ds, pf,
3614 				    (struct pnfsdsfile *)buf,
3615 				    buflen / sizeof(*pf), td->td_ucred, td);
3616 				vput(vp);
3617 				vput(nvp);
3618 				if (fds != NULL && error == 0) {
3619 					curdvp = fds->nfsdev_dsdir[pf->dsf_dir];
3620 					ret = vn_lock(curdvp, LK_EXCLUSIVE);
3621 					if (ret == 0) {
3622 						nfsrv_dsremove(curdvp, fname,
3623 						    td->td_ucred, td);
3624 						NFSVOPUNLOCK(curdvp);
3625 					}
3626 				}
3627 				NFSD_DEBUG(4, "nfsrv_copymr=%d\n", error);
3628 			}
3629 			free(cp, M_TEMP);
3630 			free(cp2, M_TEMP);
3631 			free(cp3, M_TEMP);
3632 			free(buf, M_TEMP);
3633 		}
3634 	} else {
3635 		error = nfssvc_srvcall(td, uap, td->td_ucred);
3636 	}
3637 
3638 out:
3639 	NFSEXITCODE(error);
3640 	return (error);
3641 }
3642 
3643 static int
3644 nfssvc_srvcall(struct thread *p, struct nfssvc_args *uap, struct ucred *cred)
3645 {
3646 	struct nfsex_args export;
3647 	struct file *fp = NULL;
3648 	int stablefd, len;
3649 	struct nfsd_clid adminrevoke;
3650 	struct nfsd_dumplist dumplist;
3651 	struct nfsd_dumpclients *dumpclients;
3652 	struct nfsd_dumplocklist dumplocklist;
3653 	struct nfsd_dumplocks *dumplocks;
3654 	struct nameidata nd;
3655 	vnode_t vp;
3656 	int error = EINVAL, igotlock;
3657 	struct proc *procp;
3658 	static int suspend_nfsd = 0;
3659 
3660 	if (uap->flag & NFSSVC_PUBLICFH) {
3661 		NFSBZERO((caddr_t)&nfs_pubfh.nfsrvfh_data,
3662 		    sizeof (fhandle_t));
3663 		error = copyin(uap->argp,
3664 		    &nfs_pubfh.nfsrvfh_data, sizeof (fhandle_t));
3665 		if (!error)
3666 			nfs_pubfhset = 1;
3667 	} else if (uap->flag & NFSSVC_V4ROOTEXPORT) {
3668 		error = copyin(uap->argp,(caddr_t)&export,
3669 		    sizeof (struct nfsex_args));
3670 		if (!error)
3671 			error = nfsrv_v4rootexport(&export, cred, p);
3672 	} else if (uap->flag & NFSSVC_NOPUBLICFH) {
3673 		nfs_pubfhset = 0;
3674 		error = 0;
3675 	} else if (uap->flag & NFSSVC_STABLERESTART) {
3676 		error = copyin(uap->argp, (caddr_t)&stablefd,
3677 		    sizeof (int));
3678 		if (!error)
3679 			error = fp_getfvp(p, stablefd, &fp, &vp);
3680 		if (!error && (NFSFPFLAG(fp) & (FREAD | FWRITE)) != (FREAD | FWRITE))
3681 			error = EBADF;
3682 		if (!error && newnfs_numnfsd != 0)
3683 			error = EPERM;
3684 		if (!error) {
3685 			nfsrv_stablefirst.nsf_fp = fp;
3686 			nfsrv_setupstable(p);
3687 		}
3688 	} else if (uap->flag & NFSSVC_ADMINREVOKE) {
3689 		error = copyin(uap->argp, (caddr_t)&adminrevoke,
3690 		    sizeof (struct nfsd_clid));
3691 		if (!error)
3692 			error = nfsrv_adminrevoke(&adminrevoke, p);
3693 	} else if (uap->flag & NFSSVC_DUMPCLIENTS) {
3694 		error = copyin(uap->argp, (caddr_t)&dumplist,
3695 		    sizeof (struct nfsd_dumplist));
3696 		if (!error && (dumplist.ndl_size < 1 ||
3697 			dumplist.ndl_size > NFSRV_MAXDUMPLIST))
3698 			error = EPERM;
3699 		if (!error) {
3700 		    len = sizeof (struct nfsd_dumpclients) * dumplist.ndl_size;
3701 		    dumpclients = malloc(len, M_TEMP, M_WAITOK | M_ZERO);
3702 		    nfsrv_dumpclients(dumpclients, dumplist.ndl_size);
3703 		    error = copyout(dumpclients,
3704 			CAST_USER_ADDR_T(dumplist.ndl_list), len);
3705 		    free(dumpclients, M_TEMP);
3706 		}
3707 	} else if (uap->flag & NFSSVC_DUMPLOCKS) {
3708 		error = copyin(uap->argp, (caddr_t)&dumplocklist,
3709 		    sizeof (struct nfsd_dumplocklist));
3710 		if (!error && (dumplocklist.ndllck_size < 1 ||
3711 			dumplocklist.ndllck_size > NFSRV_MAXDUMPLIST))
3712 			error = EPERM;
3713 		if (!error)
3714 			error = nfsrv_lookupfilename(&nd,
3715 				dumplocklist.ndllck_fname, p);
3716 		if (!error) {
3717 			len = sizeof (struct nfsd_dumplocks) *
3718 				dumplocklist.ndllck_size;
3719 			dumplocks = malloc(len, M_TEMP, M_WAITOK | M_ZERO);
3720 			nfsrv_dumplocks(nd.ni_vp, dumplocks,
3721 			    dumplocklist.ndllck_size, p);
3722 			vput(nd.ni_vp);
3723 			error = copyout(dumplocks,
3724 			    CAST_USER_ADDR_T(dumplocklist.ndllck_list), len);
3725 			free(dumplocks, M_TEMP);
3726 		}
3727 	} else if (uap->flag & NFSSVC_BACKUPSTABLE) {
3728 		procp = p->td_proc;
3729 		PROC_LOCK(procp);
3730 		nfsd_master_pid = procp->p_pid;
3731 		bcopy(procp->p_comm, nfsd_master_comm, MAXCOMLEN + 1);
3732 		nfsd_master_start = procp->p_stats->p_start;
3733 		nfsd_master_proc = procp;
3734 		PROC_UNLOCK(procp);
3735 	} else if ((uap->flag & NFSSVC_SUSPENDNFSD) != 0) {
3736 		NFSLOCKV4ROOTMUTEX();
3737 		if (suspend_nfsd == 0) {
3738 			/* Lock out all nfsd threads */
3739 			do {
3740 				igotlock = nfsv4_lock(&nfsd_suspend_lock, 1,
3741 				    NULL, NFSV4ROOTLOCKMUTEXPTR, NULL);
3742 			} while (igotlock == 0 && suspend_nfsd == 0);
3743 			suspend_nfsd = 1;
3744 		}
3745 		NFSUNLOCKV4ROOTMUTEX();
3746 		error = 0;
3747 	} else if ((uap->flag & NFSSVC_RESUMENFSD) != 0) {
3748 		NFSLOCKV4ROOTMUTEX();
3749 		if (suspend_nfsd != 0) {
3750 			nfsv4_unlock(&nfsd_suspend_lock, 0);
3751 			suspend_nfsd = 0;
3752 		}
3753 		NFSUNLOCKV4ROOTMUTEX();
3754 		error = 0;
3755 	}
3756 
3757 	NFSEXITCODE(error);
3758 	return (error);
3759 }
3760 
3761 /*
3762  * Check exports.
3763  * Returns 0 if ok, 1 otherwise.
3764  */
3765 int
3766 nfsvno_testexp(struct nfsrv_descript *nd, struct nfsexstuff *exp)
3767 {
3768 	int i;
3769 
3770 	/*
3771 	 * This seems odd, but allow the case where the security flavor
3772 	 * list is empty. This happens when NFSv4 is traversing non-exported
3773 	 * file systems. Exported file systems should always have a non-empty
3774 	 * security flavor list.
3775 	 */
3776 	if (exp->nes_numsecflavor == 0)
3777 		return (0);
3778 
3779 	for (i = 0; i < exp->nes_numsecflavor; i++) {
3780 		/*
3781 		 * The tests for privacy and integrity must be first,
3782 		 * since ND_GSS is set for everything but AUTH_SYS.
3783 		 */
3784 		if (exp->nes_secflavors[i] == RPCSEC_GSS_KRB5P &&
3785 		    (nd->nd_flag & ND_GSSPRIVACY))
3786 			return (0);
3787 		if (exp->nes_secflavors[i] == RPCSEC_GSS_KRB5I &&
3788 		    (nd->nd_flag & ND_GSSINTEGRITY))
3789 			return (0);
3790 		if (exp->nes_secflavors[i] == RPCSEC_GSS_KRB5 &&
3791 		    (nd->nd_flag & ND_GSS))
3792 			return (0);
3793 		if (exp->nes_secflavors[i] == AUTH_SYS &&
3794 		    (nd->nd_flag & ND_GSS) == 0)
3795 			return (0);
3796 	}
3797 	return (1);
3798 }
3799 
3800 /*
3801  * Calculate a hash value for the fid in a file handle.
3802  */
3803 uint32_t
3804 nfsrv_hashfh(fhandle_t *fhp)
3805 {
3806 	uint32_t hashval;
3807 
3808 	hashval = hash32_buf(&fhp->fh_fid, sizeof(struct fid), 0);
3809 	return (hashval);
3810 }
3811 
3812 /*
3813  * Calculate a hash value for the sessionid.
3814  */
3815 uint32_t
3816 nfsrv_hashsessionid(uint8_t *sessionid)
3817 {
3818 	uint32_t hashval;
3819 
3820 	hashval = hash32_buf(sessionid, NFSX_V4SESSIONID, 0);
3821 	return (hashval);
3822 }
3823 
3824 /*
3825  * Signal the userland master nfsd to backup the stable restart file.
3826  */
3827 void
3828 nfsrv_backupstable(void)
3829 {
3830 	struct proc *procp;
3831 
3832 	if (nfsd_master_proc != NULL) {
3833 		procp = pfind(nfsd_master_pid);
3834 		/* Try to make sure it is the correct process. */
3835 		if (procp == nfsd_master_proc &&
3836 		    procp->p_stats->p_start.tv_sec ==
3837 		    nfsd_master_start.tv_sec &&
3838 		    procp->p_stats->p_start.tv_usec ==
3839 		    nfsd_master_start.tv_usec &&
3840 		    strcmp(procp->p_comm, nfsd_master_comm) == 0)
3841 			kern_psignal(procp, SIGUSR2);
3842 		else
3843 			nfsd_master_proc = NULL;
3844 
3845 		if (procp != NULL)
3846 			PROC_UNLOCK(procp);
3847 	}
3848 }
3849 
3850 /*
3851  * Create a DS data file for nfsrv_pnfscreate(). Called for each mirror.
3852  * The arguments are in a structure, so that they can be passed through
3853  * taskqueue for a kernel process to execute this function.
3854  */
3855 struct nfsrvdscreate {
3856 	int			done;
3857 	int			inprog;
3858 	struct task		tsk;
3859 	struct ucred		*tcred;
3860 	struct vnode		*dvp;
3861 	NFSPROC_T		*p;
3862 	struct pnfsdsfile	*pf;
3863 	int			err;
3864 	fhandle_t		fh;
3865 	struct vattr		va;
3866 	struct vattr		createva;
3867 };
3868 
3869 int
3870 nfsrv_dscreate(struct vnode *dvp, struct vattr *vap, struct vattr *nvap,
3871     fhandle_t *fhp, struct pnfsdsfile *pf, struct pnfsdsattr *dsa,
3872     char *fnamep, struct ucred *tcred, NFSPROC_T *p, struct vnode **nvpp)
3873 {
3874 	struct vnode *nvp;
3875 	struct nameidata named;
3876 	struct vattr va;
3877 	char *bufp;
3878 	u_long *hashp;
3879 	struct nfsnode *np;
3880 	struct nfsmount *nmp;
3881 	int error;
3882 
3883 	NFSNAMEICNDSET(&named.ni_cnd, tcred, CREATE,
3884 	    LOCKPARENT | LOCKLEAF | SAVESTART | NOCACHE);
3885 	nfsvno_setpathbuf(&named, &bufp, &hashp);
3886 	named.ni_cnd.cn_lkflags = LK_EXCLUSIVE;
3887 	named.ni_cnd.cn_thread = p;
3888 	named.ni_cnd.cn_nameptr = bufp;
3889 	if (fnamep != NULL) {
3890 		strlcpy(bufp, fnamep, PNFS_FILENAME_LEN + 1);
3891 		named.ni_cnd.cn_namelen = strlen(bufp);
3892 	} else
3893 		named.ni_cnd.cn_namelen = nfsrv_putfhname(fhp, bufp);
3894 	NFSD_DEBUG(4, "nfsrv_dscreate: dvp=%p fname=%s\n", dvp, bufp);
3895 
3896 	/* Create the date file in the DS mount. */
3897 	error = NFSVOPLOCK(dvp, LK_EXCLUSIVE);
3898 	if (error == 0) {
3899 		error = VOP_CREATE(dvp, &nvp, &named.ni_cnd, vap);
3900 		NFSVOPUNLOCK(dvp);
3901 		if (error == 0) {
3902 			/* Set the ownership of the file. */
3903 			error = VOP_SETATTR(nvp, nvap, tcred);
3904 			NFSD_DEBUG(4, "nfsrv_dscreate:"
3905 			    " setattr-uid=%d\n", error);
3906 			if (error != 0)
3907 				vput(nvp);
3908 		}
3909 		if (error != 0)
3910 			printf("pNFS: pnfscreate failed=%d\n", error);
3911 	} else
3912 		printf("pNFS: pnfscreate vnlock=%d\n", error);
3913 	if (error == 0) {
3914 		np = VTONFS(nvp);
3915 		nmp = VFSTONFS(nvp->v_mount);
3916 		if (strcmp(nvp->v_mount->mnt_vfc->vfc_name, "nfs")
3917 		    != 0 || nmp->nm_nam->sa_len > sizeof(
3918 		    struct sockaddr_in6) ||
3919 		    np->n_fhp->nfh_len != NFSX_MYFH) {
3920 			printf("Bad DS file: fstype=%s salen=%d"
3921 			    " fhlen=%d\n",
3922 			    nvp->v_mount->mnt_vfc->vfc_name,
3923 			    nmp->nm_nam->sa_len, np->n_fhp->nfh_len);
3924 			error = ENOENT;
3925 		}
3926 
3927 		/* Set extattrs for the DS on the MDS file. */
3928 		if (error == 0) {
3929 			if (dsa != NULL) {
3930 				error = VOP_GETATTR(nvp, &va, tcred);
3931 				if (error == 0) {
3932 					dsa->dsa_filerev = va.va_filerev;
3933 					dsa->dsa_size = va.va_size;
3934 					dsa->dsa_atime = va.va_atime;
3935 					dsa->dsa_mtime = va.va_mtime;
3936 					dsa->dsa_bytes = va.va_bytes;
3937 				}
3938 			}
3939 			if (error == 0) {
3940 				NFSBCOPY(np->n_fhp->nfh_fh, &pf->dsf_fh,
3941 				    NFSX_MYFH);
3942 				NFSBCOPY(nmp->nm_nam, &pf->dsf_sin,
3943 				    nmp->nm_nam->sa_len);
3944 				NFSBCOPY(named.ni_cnd.cn_nameptr,
3945 				    pf->dsf_filename,
3946 				    sizeof(pf->dsf_filename));
3947 			}
3948 		} else
3949 			printf("pNFS: pnfscreate can't get DS"
3950 			    " attr=%d\n", error);
3951 		if (nvpp != NULL && error == 0)
3952 			*nvpp = nvp;
3953 		else
3954 			vput(nvp);
3955 	}
3956 	nfsvno_relpathbuf(&named);
3957 	return (error);
3958 }
3959 
3960 /*
3961  * Start up the thread that will execute nfsrv_dscreate().
3962  */
3963 static void
3964 start_dscreate(void *arg, int pending)
3965 {
3966 	struct nfsrvdscreate *dsc;
3967 
3968 	dsc = (struct nfsrvdscreate *)arg;
3969 	dsc->err = nfsrv_dscreate(dsc->dvp, &dsc->createva, &dsc->va, &dsc->fh,
3970 	    dsc->pf, NULL, NULL, dsc->tcred, dsc->p, NULL);
3971 	dsc->done = 1;
3972 	NFSD_DEBUG(4, "start_dscreate: err=%d\n", dsc->err);
3973 }
3974 
3975 /*
3976  * Create a pNFS data file on the Data Server(s).
3977  */
3978 static void
3979 nfsrv_pnfscreate(struct vnode *vp, struct vattr *vap, struct ucred *cred,
3980     NFSPROC_T *p)
3981 {
3982 	struct nfsrvdscreate *dsc, *tdsc = NULL;
3983 	struct nfsdevice *ds, *tds, *fds;
3984 	struct mount *mp;
3985 	struct pnfsdsfile *pf, *tpf;
3986 	struct pnfsdsattr dsattr;
3987 	struct vattr va;
3988 	struct vnode *dvp[NFSDEV_MAXMIRRORS];
3989 	struct nfsmount *nmp;
3990 	fhandle_t fh;
3991 	uid_t vauid;
3992 	gid_t vagid;
3993 	u_short vamode;
3994 	struct ucred *tcred;
3995 	int dsdir[NFSDEV_MAXMIRRORS], error, i, mirrorcnt, ret;
3996 	int failpos, timo;
3997 
3998 	/* Get a DS server directory in a round-robin order. */
3999 	mirrorcnt = 1;
4000 	mp = vp->v_mount;
4001 	ds = fds = NULL;
4002 	NFSDDSLOCK();
4003 	/*
4004 	 * Search for the first entry that handles this MDS fs, but use the
4005 	 * first entry for all MDS fs's otherwise.
4006 	 */
4007 	TAILQ_FOREACH(tds, &nfsrv_devidhead, nfsdev_list) {
4008 		if (tds->nfsdev_nmp != NULL) {
4009 			if (tds->nfsdev_mdsisset == 0 && ds == NULL)
4010 				ds = tds;
4011 			else if (tds->nfsdev_mdsisset != 0 &&
4012 			    mp->mnt_stat.f_fsid.val[0] ==
4013 			    tds->nfsdev_mdsfsid.val[0] &&
4014 			    mp->mnt_stat.f_fsid.val[1] ==
4015 			    tds->nfsdev_mdsfsid.val[1]) {
4016 				ds = fds = tds;
4017 				break;
4018 			}
4019 		}
4020 	}
4021 	if (ds == NULL) {
4022 		NFSDDSUNLOCK();
4023 		NFSD_DEBUG(4, "nfsrv_pnfscreate: no srv\n");
4024 		return;
4025 	}
4026 	i = dsdir[0] = ds->nfsdev_nextdir;
4027 	ds->nfsdev_nextdir = (ds->nfsdev_nextdir + 1) % nfsrv_dsdirsize;
4028 	dvp[0] = ds->nfsdev_dsdir[i];
4029 	tds = TAILQ_NEXT(ds, nfsdev_list);
4030 	if (nfsrv_maxpnfsmirror > 1 && tds != NULL) {
4031 		TAILQ_FOREACH_FROM(tds, &nfsrv_devidhead, nfsdev_list) {
4032 			if (tds->nfsdev_nmp != NULL &&
4033 			    ((tds->nfsdev_mdsisset == 0 && fds == NULL) ||
4034 			     (tds->nfsdev_mdsisset != 0 && fds != NULL &&
4035 			      mp->mnt_stat.f_fsid.val[0] ==
4036 			      tds->nfsdev_mdsfsid.val[0] &&
4037 			      mp->mnt_stat.f_fsid.val[1] ==
4038 			      tds->nfsdev_mdsfsid.val[1]))) {
4039 				dsdir[mirrorcnt] = i;
4040 				dvp[mirrorcnt] = tds->nfsdev_dsdir[i];
4041 				mirrorcnt++;
4042 				if (mirrorcnt >= nfsrv_maxpnfsmirror)
4043 					break;
4044 			}
4045 		}
4046 	}
4047 	/* Put at end of list to implement round-robin usage. */
4048 	TAILQ_REMOVE(&nfsrv_devidhead, ds, nfsdev_list);
4049 	TAILQ_INSERT_TAIL(&nfsrv_devidhead, ds, nfsdev_list);
4050 	NFSDDSUNLOCK();
4051 	dsc = NULL;
4052 	if (mirrorcnt > 1)
4053 		tdsc = dsc = malloc(sizeof(*dsc) * (mirrorcnt - 1), M_TEMP,
4054 		    M_WAITOK | M_ZERO);
4055 	tpf = pf = malloc(sizeof(*pf) * nfsrv_maxpnfsmirror, M_TEMP, M_WAITOK |
4056 	    M_ZERO);
4057 
4058 	error = nfsvno_getfh(vp, &fh, p);
4059 	if (error == 0)
4060 		error = VOP_GETATTR(vp, &va, cred);
4061 	if (error == 0) {
4062 		/* Set the attributes for "vp" to Setattr the DS vp. */
4063 		vauid = va.va_uid;
4064 		vagid = va.va_gid;
4065 		vamode = va.va_mode;
4066 		VATTR_NULL(&va);
4067 		va.va_uid = vauid;
4068 		va.va_gid = vagid;
4069 		va.va_mode = vamode;
4070 		va.va_size = 0;
4071 	} else
4072 		printf("pNFS: pnfscreate getfh+attr=%d\n", error);
4073 
4074 	NFSD_DEBUG(4, "nfsrv_pnfscreate: cruid=%d crgid=%d\n", cred->cr_uid,
4075 	    cred->cr_gid);
4076 	/* Make data file name based on FH. */
4077 	tcred = newnfs_getcred();
4078 
4079 	/*
4080 	 * Create the file on each DS mirror, using kernel process(es) for the
4081 	 * additional mirrors.
4082 	 */
4083 	failpos = -1;
4084 	for (i = 0; i < mirrorcnt - 1 && error == 0; i++, tpf++, tdsc++) {
4085 		tpf->dsf_dir = dsdir[i];
4086 		tdsc->tcred = tcred;
4087 		tdsc->p = p;
4088 		tdsc->pf = tpf;
4089 		tdsc->createva = *vap;
4090 		NFSBCOPY(&fh, &tdsc->fh, sizeof(fh));
4091 		tdsc->va = va;
4092 		tdsc->dvp = dvp[i];
4093 		tdsc->done = 0;
4094 		tdsc->inprog = 0;
4095 		tdsc->err = 0;
4096 		ret = EIO;
4097 		if (nfs_pnfsiothreads != 0) {
4098 			ret = nfs_pnfsio(start_dscreate, tdsc);
4099 			NFSD_DEBUG(4, "nfsrv_pnfscreate: nfs_pnfsio=%d\n", ret);
4100 		}
4101 		if (ret != 0) {
4102 			ret = nfsrv_dscreate(dvp[i], vap, &va, &fh, tpf, NULL,
4103 			    NULL, tcred, p, NULL);
4104 			if (ret != 0) {
4105 				KASSERT(error == 0, ("nfsrv_dscreate err=%d",
4106 				    error));
4107 				if (failpos == -1 && nfsds_failerr(ret))
4108 					failpos = i;
4109 				else
4110 					error = ret;
4111 			}
4112 		}
4113 	}
4114 	if (error == 0) {
4115 		tpf->dsf_dir = dsdir[mirrorcnt - 1];
4116 		error = nfsrv_dscreate(dvp[mirrorcnt - 1], vap, &va, &fh, tpf,
4117 		    &dsattr, NULL, tcred, p, NULL);
4118 		if (failpos == -1 && mirrorcnt > 1 && nfsds_failerr(error)) {
4119 			failpos = mirrorcnt - 1;
4120 			error = 0;
4121 		}
4122 	}
4123 	timo = hz / 50;		/* Wait for 20msec. */
4124 	if (timo < 1)
4125 		timo = 1;
4126 	/* Wait for kernel task(s) to complete. */
4127 	for (tdsc = dsc, i = 0; i < mirrorcnt - 1; i++, tdsc++) {
4128 		while (tdsc->inprog != 0 && tdsc->done == 0)
4129 			tsleep(&tdsc->tsk, PVFS, "srvdcr", timo);
4130 		if (tdsc->err != 0) {
4131 			if (failpos == -1 && nfsds_failerr(tdsc->err))
4132 				failpos = i;
4133 			else if (error == 0)
4134 				error = tdsc->err;
4135 		}
4136 	}
4137 
4138 	/*
4139 	 * If failpos has been set, that mirror has failed, so it needs
4140 	 * to be disabled.
4141 	 */
4142 	if (failpos >= 0) {
4143 		nmp = VFSTONFS(dvp[failpos]->v_mount);
4144 		NFSLOCKMNT(nmp);
4145 		if ((nmp->nm_privflag & (NFSMNTP_FORCEDISM |
4146 		     NFSMNTP_CANCELRPCS)) == 0) {
4147 			nmp->nm_privflag |= NFSMNTP_CANCELRPCS;
4148 			NFSUNLOCKMNT(nmp);
4149 			ds = nfsrv_deldsnmp(PNFSDOP_DELDSSERVER, nmp, p);
4150 			NFSD_DEBUG(4, "dscreatfail fail=%d ds=%p\n", failpos,
4151 			    ds);
4152 			if (ds != NULL)
4153 				nfsrv_killrpcs(nmp);
4154 			NFSLOCKMNT(nmp);
4155 			nmp->nm_privflag &= ~NFSMNTP_CANCELRPCS;
4156 			wakeup(nmp);
4157 		}
4158 		NFSUNLOCKMNT(nmp);
4159 	}
4160 
4161 	NFSFREECRED(tcred);
4162 	if (error == 0) {
4163 		ASSERT_VOP_ELOCKED(vp, "nfsrv_pnfscreate vp");
4164 
4165 		NFSD_DEBUG(4, "nfsrv_pnfscreate: mirrorcnt=%d maxmirror=%d\n",
4166 		    mirrorcnt, nfsrv_maxpnfsmirror);
4167 		/*
4168 		 * For all mirrors that couldn't be created, fill in the
4169 		 * *pf structure, but with an IP address == 0.0.0.0.
4170 		 */
4171 		tpf = pf + mirrorcnt;
4172 		for (i = mirrorcnt; i < nfsrv_maxpnfsmirror; i++, tpf++) {
4173 			*tpf = *pf;
4174 			tpf->dsf_sin.sin_family = AF_INET;
4175 			tpf->dsf_sin.sin_len = sizeof(struct sockaddr_in);
4176 			tpf->dsf_sin.sin_addr.s_addr = 0;
4177 			tpf->dsf_sin.sin_port = 0;
4178 		}
4179 
4180 		error = vn_extattr_set(vp, IO_NODELOCKED,
4181 		    EXTATTR_NAMESPACE_SYSTEM, "pnfsd.dsfile",
4182 		    sizeof(*pf) * nfsrv_maxpnfsmirror, (char *)pf, p);
4183 		if (error == 0)
4184 			error = vn_extattr_set(vp, IO_NODELOCKED,
4185 			    EXTATTR_NAMESPACE_SYSTEM, "pnfsd.dsattr",
4186 			    sizeof(dsattr), (char *)&dsattr, p);
4187 		if (error != 0)
4188 			printf("pNFS: pnfscreate setextattr=%d\n",
4189 			    error);
4190 	} else
4191 		printf("pNFS: pnfscreate=%d\n", error);
4192 	free(pf, M_TEMP);
4193 	free(dsc, M_TEMP);
4194 }
4195 
4196 /*
4197  * Get the information needed to remove the pNFS Data Server file from the
4198  * Metadata file.  Upon success, ddvp is set non-NULL to the locked
4199  * DS directory vnode.  The caller must unlock *ddvp when done with it.
4200  */
4201 static void
4202 nfsrv_pnfsremovesetup(struct vnode *vp, NFSPROC_T *p, struct vnode **dvpp,
4203     int *mirrorcntp, char *fname, fhandle_t *fhp)
4204 {
4205 	struct vattr va;
4206 	struct ucred *tcred;
4207 	char *buf;
4208 	int buflen, error;
4209 
4210 	dvpp[0] = NULL;
4211 	/* If not an exported regular file or not a pNFS server, just return. */
4212 	if (vp->v_type != VREG || (vp->v_mount->mnt_flag & MNT_EXPORTED) == 0 ||
4213 	    nfsrv_devidcnt == 0)
4214 		return;
4215 
4216 	/* Check to see if this is the last hard link. */
4217 	tcred = newnfs_getcred();
4218 	error = VOP_GETATTR(vp, &va, tcred);
4219 	NFSFREECRED(tcred);
4220 	if (error != 0) {
4221 		printf("pNFS: nfsrv_pnfsremovesetup getattr=%d\n", error);
4222 		return;
4223 	}
4224 	if (va.va_nlink > 1)
4225 		return;
4226 
4227 	error = nfsvno_getfh(vp, fhp, p);
4228 	if (error != 0) {
4229 		printf("pNFS: nfsrv_pnfsremovesetup getfh=%d\n", error);
4230 		return;
4231 	}
4232 
4233 	buflen = 1024;
4234 	buf = malloc(buflen, M_TEMP, M_WAITOK);
4235 	/* Get the directory vnode for the DS mount and the file handle. */
4236 	error = nfsrv_dsgetsockmnt(vp, 0, buf, &buflen, mirrorcntp, p, dvpp,
4237 	    NULL, NULL, fname, NULL, NULL, NULL, NULL, NULL);
4238 	free(buf, M_TEMP);
4239 	if (error != 0)
4240 		printf("pNFS: nfsrv_pnfsremovesetup getsockmnt=%d\n", error);
4241 }
4242 
4243 /*
4244  * Remove a DS data file for nfsrv_pnfsremove(). Called for each mirror.
4245  * The arguments are in a structure, so that they can be passed through
4246  * taskqueue for a kernel process to execute this function.
4247  */
4248 struct nfsrvdsremove {
4249 	int			done;
4250 	int			inprog;
4251 	struct task		tsk;
4252 	struct ucred		*tcred;
4253 	struct vnode		*dvp;
4254 	NFSPROC_T		*p;
4255 	int			err;
4256 	char			fname[PNFS_FILENAME_LEN + 1];
4257 };
4258 
4259 static int
4260 nfsrv_dsremove(struct vnode *dvp, char *fname, struct ucred *tcred,
4261     NFSPROC_T *p)
4262 {
4263 	struct nameidata named;
4264 	struct vnode *nvp;
4265 	char *bufp;
4266 	u_long *hashp;
4267 	int error;
4268 
4269 	error = NFSVOPLOCK(dvp, LK_EXCLUSIVE);
4270 	if (error != 0)
4271 		return (error);
4272 	named.ni_cnd.cn_nameiop = DELETE;
4273 	named.ni_cnd.cn_lkflags = LK_EXCLUSIVE | LK_RETRY;
4274 	named.ni_cnd.cn_cred = tcred;
4275 	named.ni_cnd.cn_thread = p;
4276 	named.ni_cnd.cn_flags = ISLASTCN | LOCKPARENT | LOCKLEAF | SAVENAME;
4277 	nfsvno_setpathbuf(&named, &bufp, &hashp);
4278 	named.ni_cnd.cn_nameptr = bufp;
4279 	named.ni_cnd.cn_namelen = strlen(fname);
4280 	strlcpy(bufp, fname, NAME_MAX);
4281 	NFSD_DEBUG(4, "nfsrv_pnfsremove: filename=%s\n", bufp);
4282 	error = VOP_LOOKUP(dvp, &nvp, &named.ni_cnd);
4283 	NFSD_DEBUG(4, "nfsrv_pnfsremove: aft LOOKUP=%d\n", error);
4284 	if (error == 0) {
4285 		error = VOP_REMOVE(dvp, nvp, &named.ni_cnd);
4286 		vput(nvp);
4287 	}
4288 	NFSVOPUNLOCK(dvp);
4289 	nfsvno_relpathbuf(&named);
4290 	if (error != 0)
4291 		printf("pNFS: nfsrv_pnfsremove failed=%d\n", error);
4292 	return (error);
4293 }
4294 
4295 /*
4296  * Start up the thread that will execute nfsrv_dsremove().
4297  */
4298 static void
4299 start_dsremove(void *arg, int pending)
4300 {
4301 	struct nfsrvdsremove *dsrm;
4302 
4303 	dsrm = (struct nfsrvdsremove *)arg;
4304 	dsrm->err = nfsrv_dsremove(dsrm->dvp, dsrm->fname, dsrm->tcred,
4305 	    dsrm->p);
4306 	dsrm->done = 1;
4307 	NFSD_DEBUG(4, "start_dsremove: err=%d\n", dsrm->err);
4308 }
4309 
4310 /*
4311  * Remove a pNFS data file from a Data Server.
4312  * nfsrv_pnfsremovesetup() must have been called before the MDS file was
4313  * removed to set up the dvp and fill in the FH.
4314  */
4315 static void
4316 nfsrv_pnfsremove(struct vnode **dvp, int mirrorcnt, char *fname, fhandle_t *fhp,
4317     NFSPROC_T *p)
4318 {
4319 	struct ucred *tcred;
4320 	struct nfsrvdsremove *dsrm, *tdsrm;
4321 	struct nfsdevice *ds;
4322 	struct nfsmount *nmp;
4323 	int failpos, i, ret, timo;
4324 
4325 	tcred = newnfs_getcred();
4326 	dsrm = NULL;
4327 	if (mirrorcnt > 1)
4328 		dsrm = malloc(sizeof(*dsrm) * mirrorcnt - 1, M_TEMP, M_WAITOK);
4329 	/*
4330 	 * Remove the file on each DS mirror, using kernel process(es) for the
4331 	 * additional mirrors.
4332 	 */
4333 	failpos = -1;
4334 	for (tdsrm = dsrm, i = 0; i < mirrorcnt - 1; i++, tdsrm++) {
4335 		tdsrm->tcred = tcred;
4336 		tdsrm->p = p;
4337 		tdsrm->dvp = dvp[i];
4338 		strlcpy(tdsrm->fname, fname, PNFS_FILENAME_LEN + 1);
4339 		tdsrm->inprog = 0;
4340 		tdsrm->done = 0;
4341 		tdsrm->err = 0;
4342 		ret = EIO;
4343 		if (nfs_pnfsiothreads != 0) {
4344 			ret = nfs_pnfsio(start_dsremove, tdsrm);
4345 			NFSD_DEBUG(4, "nfsrv_pnfsremove: nfs_pnfsio=%d\n", ret);
4346 		}
4347 		if (ret != 0) {
4348 			ret = nfsrv_dsremove(dvp[i], fname, tcred, p);
4349 			if (failpos == -1 && nfsds_failerr(ret))
4350 				failpos = i;
4351 		}
4352 	}
4353 	ret = nfsrv_dsremove(dvp[mirrorcnt - 1], fname, tcred, p);
4354 	if (failpos == -1 && mirrorcnt > 1 && nfsds_failerr(ret))
4355 		failpos = mirrorcnt - 1;
4356 	timo = hz / 50;		/* Wait for 20msec. */
4357 	if (timo < 1)
4358 		timo = 1;
4359 	/* Wait for kernel task(s) to complete. */
4360 	for (tdsrm = dsrm, i = 0; i < mirrorcnt - 1; i++, tdsrm++) {
4361 		while (tdsrm->inprog != 0 && tdsrm->done == 0)
4362 			tsleep(&tdsrm->tsk, PVFS, "srvdsrm", timo);
4363 		if (failpos == -1 && nfsds_failerr(tdsrm->err))
4364 			failpos = i;
4365 	}
4366 
4367 	/*
4368 	 * If failpos has been set, that mirror has failed, so it needs
4369 	 * to be disabled.
4370 	 */
4371 	if (failpos >= 0) {
4372 		nmp = VFSTONFS(dvp[failpos]->v_mount);
4373 		NFSLOCKMNT(nmp);
4374 		if ((nmp->nm_privflag & (NFSMNTP_FORCEDISM |
4375 		     NFSMNTP_CANCELRPCS)) == 0) {
4376 			nmp->nm_privflag |= NFSMNTP_CANCELRPCS;
4377 			NFSUNLOCKMNT(nmp);
4378 			ds = nfsrv_deldsnmp(PNFSDOP_DELDSSERVER, nmp, p);
4379 			NFSD_DEBUG(4, "dsremovefail fail=%d ds=%p\n", failpos,
4380 			    ds);
4381 			if (ds != NULL)
4382 				nfsrv_killrpcs(nmp);
4383 			NFSLOCKMNT(nmp);
4384 			nmp->nm_privflag &= ~NFSMNTP_CANCELRPCS;
4385 			wakeup(nmp);
4386 		}
4387 		NFSUNLOCKMNT(nmp);
4388 	}
4389 
4390 	/* Get rid all layouts for the file. */
4391 	nfsrv_freefilelayouts(fhp);
4392 
4393 	NFSFREECRED(tcred);
4394 	free(dsrm, M_TEMP);
4395 }
4396 
4397 /*
4398  * Generate a file name based on the file handle and put it in *bufp.
4399  * Return the number of bytes generated.
4400  */
4401 static int
4402 nfsrv_putfhname(fhandle_t *fhp, char *bufp)
4403 {
4404 	int i;
4405 	uint8_t *cp;
4406 	const uint8_t *hexdigits = "0123456789abcdef";
4407 
4408 	cp = (uint8_t *)fhp;
4409 	for (i = 0; i < sizeof(*fhp); i++) {
4410 		bufp[2 * i] = hexdigits[(*cp >> 4) & 0xf];
4411 		bufp[2 * i + 1] = hexdigits[*cp++ & 0xf];
4412 	}
4413 	bufp[2 * i] = '\0';
4414 	return (2 * i);
4415 }
4416 
4417 /*
4418  * Update the Metadata file's attributes from the DS file when a Read/Write
4419  * layout is returned.
4420  * Basically just call nfsrv_proxyds() with procedure == NFSPROC_LAYOUTRETURN
4421  * so that it does a nfsrv_getattrdsrpc() and nfsrv_setextattr() on the DS file.
4422  */
4423 int
4424 nfsrv_updatemdsattr(struct vnode *vp, struct nfsvattr *nap, NFSPROC_T *p)
4425 {
4426 	struct ucred *tcred;
4427 	int error;
4428 
4429 	/* Do this as root so that it won't fail with EACCES. */
4430 	tcred = newnfs_getcred();
4431 	error = nfsrv_proxyds(vp, 0, 0, tcred, p, NFSPROC_LAYOUTRETURN,
4432 	    NULL, NULL, NULL, nap, NULL, NULL, 0, NULL);
4433 	NFSFREECRED(tcred);
4434 	return (error);
4435 }
4436 
4437 /*
4438  * Set the NFSv4 ACL on the DS file to the same ACL as the MDS file.
4439  */
4440 static int
4441 nfsrv_dssetacl(struct vnode *vp, struct acl *aclp, struct ucred *cred,
4442     NFSPROC_T *p)
4443 {
4444 	int error;
4445 
4446 	error = nfsrv_proxyds(vp, 0, 0, cred, p, NFSPROC_SETACL,
4447 	    NULL, NULL, NULL, NULL, aclp, NULL, 0, NULL);
4448 	return (error);
4449 }
4450 
4451 static int
4452 nfsrv_proxyds(struct vnode *vp, off_t off, int cnt, struct ucred *cred,
4453     struct thread *p, int ioproc, struct mbuf **mpp, char *cp,
4454     struct mbuf **mpp2, struct nfsvattr *nap, struct acl *aclp,
4455     off_t *offp, int content, bool *eofp)
4456 {
4457 	struct nfsmount *nmp[NFSDEV_MAXMIRRORS], *failnmp;
4458 	fhandle_t fh[NFSDEV_MAXMIRRORS];
4459 	struct vnode *dvp[NFSDEV_MAXMIRRORS];
4460 	struct nfsdevice *ds;
4461 	struct pnfsdsattr dsattr;
4462 	struct opnfsdsattr odsattr;
4463 	char *buf;
4464 	int buflen, error, failpos, i, mirrorcnt, origmircnt, trycnt;
4465 
4466 	NFSD_DEBUG(4, "in nfsrv_proxyds\n");
4467 	/*
4468 	 * If not a regular file, not exported or not a pNFS server,
4469 	 * just return ENOENT.
4470 	 */
4471 	if (vp->v_type != VREG || (vp->v_mount->mnt_flag & MNT_EXPORTED) == 0 ||
4472 	    nfsrv_devidcnt == 0)
4473 		return (ENOENT);
4474 
4475 	buflen = 1024;
4476 	buf = malloc(buflen, M_TEMP, M_WAITOK);
4477 	error = 0;
4478 
4479 	/*
4480 	 * For Getattr, get the Change attribute (va_filerev) and size (va_size)
4481 	 * from the MetaData file's extended attribute.
4482 	 */
4483 	if (ioproc == NFSPROC_GETATTR) {
4484 		error = vn_extattr_get(vp, IO_NODELOCKED,
4485 		    EXTATTR_NAMESPACE_SYSTEM, "pnfsd.dsattr", &buflen, buf,
4486 		    p);
4487 		if (error == 0) {
4488 			if (buflen == sizeof(odsattr)) {
4489 				NFSBCOPY(buf, &odsattr, buflen);
4490 				nap->na_filerev = odsattr.dsa_filerev;
4491 				nap->na_size = odsattr.dsa_size;
4492 				nap->na_atime = odsattr.dsa_atime;
4493 				nap->na_mtime = odsattr.dsa_mtime;
4494 				/*
4495 				 * Fake na_bytes by rounding up na_size.
4496 				 * Since we don't know the block size, just
4497 				 * use BLKDEV_IOSIZE.
4498 				 */
4499 				nap->na_bytes = (odsattr.dsa_size +
4500 				    BLKDEV_IOSIZE - 1) & ~(BLKDEV_IOSIZE - 1);
4501 			} else if (buflen == sizeof(dsattr)) {
4502 				NFSBCOPY(buf, &dsattr, buflen);
4503 				nap->na_filerev = dsattr.dsa_filerev;
4504 				nap->na_size = dsattr.dsa_size;
4505 				nap->na_atime = dsattr.dsa_atime;
4506 				nap->na_mtime = dsattr.dsa_mtime;
4507 				nap->na_bytes = dsattr.dsa_bytes;
4508 			} else
4509 				error = ENXIO;
4510 		}
4511 		if (error == 0) {
4512 			/*
4513 			 * If nfsrv_pnfsgetdsattr is 0 or nfsrv_checkdsattr()
4514 			 * returns 0, just return now.  nfsrv_checkdsattr()
4515 			 * returns 0 if there is no Read/Write layout
4516 			 * plus either an Open/Write_access or Write
4517 			 * delegation issued to a client for the file.
4518 			 */
4519 			if (nfsrv_pnfsgetdsattr == 0 ||
4520 			    nfsrv_checkdsattr(vp, p) == 0) {
4521 				free(buf, M_TEMP);
4522 				return (error);
4523 			}
4524 		}
4525 
4526 		/*
4527 		 * Clear ENOATTR so the code below will attempt to do a
4528 		 * nfsrv_getattrdsrpc() to get the attributes and (re)create
4529 		 * the extended attribute.
4530 		 */
4531 		if (error == ENOATTR)
4532 			error = 0;
4533 	}
4534 
4535 	origmircnt = -1;
4536 	trycnt = 0;
4537 tryagain:
4538 	if (error == 0) {
4539 		buflen = 1024;
4540 		if (ioproc == NFSPROC_READDS && NFSVOPISLOCKED(vp) ==
4541 		    LK_EXCLUSIVE)
4542 			printf("nfsrv_proxyds: Readds vp exclusively locked\n");
4543 		error = nfsrv_dsgetsockmnt(vp, LK_SHARED, buf, &buflen,
4544 		    &mirrorcnt, p, dvp, fh, NULL, NULL, NULL, NULL, NULL,
4545 		    NULL, NULL);
4546 		if (error == 0) {
4547 			for (i = 0; i < mirrorcnt; i++)
4548 				nmp[i] = VFSTONFS(dvp[i]->v_mount);
4549 		} else
4550 			printf("pNFS: proxy getextattr sockaddr=%d\n", error);
4551 	} else
4552 		printf("pNFS: nfsrv_dsgetsockmnt=%d\n", error);
4553 	if (error == 0) {
4554 		failpos = -1;
4555 		if (origmircnt == -1)
4556 			origmircnt = mirrorcnt;
4557 		/*
4558 		 * If failpos is set to a mirror#, then that mirror has
4559 		 * failed and will be disabled. For Read, Getattr and Seek, the
4560 		 * function only tries one mirror, so if that mirror has
4561 		 * failed, it will need to be retried. As such, increment
4562 		 * tryitagain for these cases.
4563 		 * For Write, Setattr and Setacl, the function tries all
4564 		 * mirrors and will not return an error for the case where
4565 		 * one mirror has failed. For these cases, the functioning
4566 		 * mirror(s) will have been modified, so a retry isn't
4567 		 * necessary. These functions will set failpos for the
4568 		 * failed mirror#.
4569 		 */
4570 		if (ioproc == NFSPROC_READDS) {
4571 			error = nfsrv_readdsrpc(fh, off, cnt, cred, p, nmp[0],
4572 			    mpp, mpp2);
4573 			if (nfsds_failerr(error) && mirrorcnt > 1) {
4574 				/*
4575 				 * Setting failpos will cause the mirror
4576 				 * to be disabled and then a retry of this
4577 				 * read is required.
4578 				 */
4579 				failpos = 0;
4580 				error = 0;
4581 				trycnt++;
4582 			}
4583 		} else if (ioproc == NFSPROC_WRITEDS)
4584 			error = nfsrv_writedsrpc(fh, off, cnt, cred, p, vp,
4585 			    &nmp[0], mirrorcnt, mpp, cp, &failpos);
4586 		else if (ioproc == NFSPROC_SETATTR)
4587 			error = nfsrv_setattrdsrpc(fh, cred, p, vp, &nmp[0],
4588 			    mirrorcnt, nap, &failpos);
4589 		else if (ioproc == NFSPROC_SETACL)
4590 			error = nfsrv_setacldsrpc(fh, cred, p, vp, &nmp[0],
4591 			    mirrorcnt, aclp, &failpos);
4592 		else if (ioproc == NFSPROC_SEEKDS) {
4593 			error = nfsrv_seekdsrpc(fh, offp, content, eofp, cred,
4594 			    p, nmp[0]);
4595 			if (nfsds_failerr(error) && mirrorcnt > 1) {
4596 				/*
4597 				 * Setting failpos will cause the mirror
4598 				 * to be disabled and then a retry of this
4599 				 * read is required.
4600 				 */
4601 				failpos = 0;
4602 				error = 0;
4603 				trycnt++;
4604 			}
4605 		} else if (ioproc == NFSPROC_ALLOCATE)
4606 			error = nfsrv_allocatedsrpc(fh, off, *offp, cred, p, vp,
4607 			    &nmp[0], mirrorcnt, &failpos);
4608 		else {
4609 			error = nfsrv_getattrdsrpc(&fh[mirrorcnt - 1], cred, p,
4610 			    vp, nmp[mirrorcnt - 1], nap);
4611 			if (nfsds_failerr(error) && mirrorcnt > 1) {
4612 				/*
4613 				 * Setting failpos will cause the mirror
4614 				 * to be disabled and then a retry of this
4615 				 * getattr is required.
4616 				 */
4617 				failpos = mirrorcnt - 1;
4618 				error = 0;
4619 				trycnt++;
4620 			}
4621 		}
4622 		ds = NULL;
4623 		if (failpos >= 0) {
4624 			failnmp = nmp[failpos];
4625 			NFSLOCKMNT(failnmp);
4626 			if ((failnmp->nm_privflag & (NFSMNTP_FORCEDISM |
4627 			     NFSMNTP_CANCELRPCS)) == 0) {
4628 				failnmp->nm_privflag |= NFSMNTP_CANCELRPCS;
4629 				NFSUNLOCKMNT(failnmp);
4630 				ds = nfsrv_deldsnmp(PNFSDOP_DELDSSERVER,
4631 				    failnmp, p);
4632 				NFSD_DEBUG(4, "dsldsnmp fail=%d ds=%p\n",
4633 				    failpos, ds);
4634 				if (ds != NULL)
4635 					nfsrv_killrpcs(failnmp);
4636 				NFSLOCKMNT(failnmp);
4637 				failnmp->nm_privflag &= ~NFSMNTP_CANCELRPCS;
4638 				wakeup(failnmp);
4639 			}
4640 			NFSUNLOCKMNT(failnmp);
4641 		}
4642 		for (i = 0; i < mirrorcnt; i++)
4643 			NFSVOPUNLOCK(dvp[i]);
4644 		NFSD_DEBUG(4, "nfsrv_proxyds: aft RPC=%d trya=%d\n", error,
4645 		    trycnt);
4646 		/* Try the Read/Getattr again if a mirror was deleted. */
4647 		if (ds != NULL && trycnt > 0 && trycnt < origmircnt)
4648 			goto tryagain;
4649 	} else {
4650 		/* Return ENOENT for any Extended Attribute error. */
4651 		error = ENOENT;
4652 	}
4653 	free(buf, M_TEMP);
4654 	NFSD_DEBUG(4, "nfsrv_proxyds: error=%d\n", error);
4655 	return (error);
4656 }
4657 
4658 /*
4659  * Get the DS mount point, fh and directory from the "pnfsd.dsfile" extended
4660  * attribute.
4661  * newnmpp - If it points to a non-NULL nmp, that is the destination and needs
4662  *           to be checked.  If it points to a NULL nmp, then it returns
4663  *           a suitable destination.
4664  * curnmp - If non-NULL, it is the source mount for the copy.
4665  */
4666 int
4667 nfsrv_dsgetsockmnt(struct vnode *vp, int lktype, char *buf, int *buflenp,
4668     int *mirrorcntp, NFSPROC_T *p, struct vnode **dvpp, fhandle_t *fhp,
4669     char *devid, char *fnamep, struct vnode **nvpp, struct nfsmount **newnmpp,
4670     struct nfsmount *curnmp, int *ippos, int *dsdirp)
4671 {
4672 	struct vnode *dvp, *nvp = NULL, **tdvpp;
4673 	struct mount *mp;
4674 	struct nfsmount *nmp, *newnmp;
4675 	struct sockaddr *sad;
4676 	struct sockaddr_in *sin;
4677 	struct nfsdevice *ds, *tds, *fndds;
4678 	struct pnfsdsfile *pf;
4679 	uint32_t dsdir;
4680 	int error, fhiszero, fnd, gotone, i, mirrorcnt;
4681 
4682 	ASSERT_VOP_LOCKED(vp, "nfsrv_dsgetsockmnt vp");
4683 	*mirrorcntp = 1;
4684 	tdvpp = dvpp;
4685 	if (nvpp != NULL)
4686 		*nvpp = NULL;
4687 	if (dvpp != NULL)
4688 		*dvpp = NULL;
4689 	if (ippos != NULL)
4690 		*ippos = -1;
4691 	if (newnmpp != NULL)
4692 		newnmp = *newnmpp;
4693 	else
4694 		newnmp = NULL;
4695 	mp = vp->v_mount;
4696 	error = vn_extattr_get(vp, IO_NODELOCKED, EXTATTR_NAMESPACE_SYSTEM,
4697 	    "pnfsd.dsfile", buflenp, buf, p);
4698 	mirrorcnt = *buflenp / sizeof(*pf);
4699 	if (error == 0 && (mirrorcnt < 1 || mirrorcnt > NFSDEV_MAXMIRRORS ||
4700 	    *buflenp != sizeof(*pf) * mirrorcnt))
4701 		error = ENOATTR;
4702 
4703 	pf = (struct pnfsdsfile *)buf;
4704 	/* If curnmp != NULL, check for a match in the mirror list. */
4705 	if (curnmp != NULL && error == 0) {
4706 		fnd = 0;
4707 		for (i = 0; i < mirrorcnt; i++, pf++) {
4708 			sad = (struct sockaddr *)&pf->dsf_sin;
4709 			if (nfsaddr2_match(sad, curnmp->nm_nam)) {
4710 				if (ippos != NULL)
4711 					*ippos = i;
4712 				fnd = 1;
4713 				break;
4714 			}
4715 		}
4716 		if (fnd == 0)
4717 			error = ENXIO;
4718 	}
4719 
4720 	gotone = 0;
4721 	pf = (struct pnfsdsfile *)buf;
4722 	NFSD_DEBUG(4, "nfsrv_dsgetsockmnt: mirrorcnt=%d err=%d\n", mirrorcnt,
4723 	    error);
4724 	for (i = 0; i < mirrorcnt && error == 0; i++, pf++) {
4725 		fhiszero = 0;
4726 		sad = (struct sockaddr *)&pf->dsf_sin;
4727 		sin = &pf->dsf_sin;
4728 		dsdir = pf->dsf_dir;
4729 		if (dsdir >= nfsrv_dsdirsize) {
4730 			printf("nfsrv_dsgetsockmnt: dsdir=%d\n", dsdir);
4731 			error = ENOATTR;
4732 		} else if (nvpp != NULL && newnmp != NULL &&
4733 		    nfsaddr2_match(sad, newnmp->nm_nam))
4734 			error = EEXIST;
4735 		if (error == 0) {
4736 			if (ippos != NULL && curnmp == NULL &&
4737 			    sad->sa_family == AF_INET &&
4738 			    sin->sin_addr.s_addr == 0)
4739 				*ippos = i;
4740 			if (NFSBCMP(&zerofh, &pf->dsf_fh, sizeof(zerofh)) == 0)
4741 				fhiszero = 1;
4742 			/* Use the socket address to find the mount point. */
4743 			fndds = NULL;
4744 			NFSDDSLOCK();
4745 			/* Find a match for the IP address. */
4746 			TAILQ_FOREACH(ds, &nfsrv_devidhead, nfsdev_list) {
4747 				if (ds->nfsdev_nmp != NULL) {
4748 					dvp = ds->nfsdev_dvp;
4749 					nmp = VFSTONFS(dvp->v_mount);
4750 					if (nmp != ds->nfsdev_nmp)
4751 						printf("different2 nmp %p %p\n",
4752 						    nmp, ds->nfsdev_nmp);
4753 					if (nfsaddr2_match(sad, nmp->nm_nam)) {
4754 						fndds = ds;
4755 						break;
4756 					}
4757 				}
4758 			}
4759 			if (fndds != NULL && newnmpp != NULL &&
4760 			    newnmp == NULL) {
4761 				/* Search for a place to make a mirror copy. */
4762 				TAILQ_FOREACH(tds, &nfsrv_devidhead,
4763 				    nfsdev_list) {
4764 					if (tds->nfsdev_nmp != NULL &&
4765 					    fndds != tds &&
4766 					    ((tds->nfsdev_mdsisset == 0 &&
4767 					      fndds->nfsdev_mdsisset == 0) ||
4768 					     (tds->nfsdev_mdsisset != 0 &&
4769 					      fndds->nfsdev_mdsisset != 0 &&
4770 					      tds->nfsdev_mdsfsid.val[0] ==
4771 					      mp->mnt_stat.f_fsid.val[0] &&
4772 					      tds->nfsdev_mdsfsid.val[1] ==
4773 					      mp->mnt_stat.f_fsid.val[1]))) {
4774 						*newnmpp = tds->nfsdev_nmp;
4775 						break;
4776 					}
4777 				}
4778 				if (tds != NULL) {
4779 					/*
4780 					 * Move this entry to the end of the
4781 					 * list, so it won't be selected as
4782 					 * easily the next time.
4783 					 */
4784 					TAILQ_REMOVE(&nfsrv_devidhead, tds,
4785 					    nfsdev_list);
4786 					TAILQ_INSERT_TAIL(&nfsrv_devidhead, tds,
4787 					    nfsdev_list);
4788 				}
4789 			}
4790 			NFSDDSUNLOCK();
4791 			if (fndds != NULL) {
4792 				dvp = fndds->nfsdev_dsdir[dsdir];
4793 				if (lktype != 0 || fhiszero != 0 ||
4794 				    (nvpp != NULL && *nvpp == NULL)) {
4795 					if (fhiszero != 0)
4796 						error = vn_lock(dvp,
4797 						    LK_EXCLUSIVE);
4798 					else if (lktype != 0)
4799 						error = vn_lock(dvp, lktype);
4800 					else
4801 						error = vn_lock(dvp, LK_SHARED);
4802 					/*
4803 					 * If the file handle is all 0's, try to
4804 					 * do a Lookup against the DS to acquire
4805 					 * it.
4806 					 * If dvpp == NULL or the Lookup fails,
4807 					 * unlock dvp after the call.
4808 					 */
4809 					if (error == 0 && (fhiszero != 0 ||
4810 					    (nvpp != NULL && *nvpp == NULL))) {
4811 						error = nfsrv_pnfslookupds(vp,
4812 						    dvp, pf, &nvp, p);
4813 						if (error == 0) {
4814 							if (fhiszero != 0)
4815 								nfsrv_pnfssetfh(
4816 								    vp, pf,
4817 								    devid,
4818 								    fnamep,
4819 								    nvp, p);
4820 							if (nvpp != NULL &&
4821 							    *nvpp == NULL) {
4822 								*nvpp = nvp;
4823 								*dsdirp = dsdir;
4824 							} else
4825 								vput(nvp);
4826 						}
4827 						if (error != 0 || lktype == 0)
4828 							NFSVOPUNLOCK(dvp);
4829 					}
4830 				}
4831 				if (error == 0) {
4832 					gotone++;
4833 					NFSD_DEBUG(4, "gotone=%d\n", gotone);
4834 					if (devid != NULL) {
4835 						NFSBCOPY(fndds->nfsdev_deviceid,
4836 						    devid, NFSX_V4DEVICEID);
4837 						devid += NFSX_V4DEVICEID;
4838 					}
4839 					if (dvpp != NULL)
4840 						*tdvpp++ = dvp;
4841 					if (fhp != NULL)
4842 						NFSBCOPY(&pf->dsf_fh, fhp++,
4843 						    NFSX_MYFH);
4844 					if (fnamep != NULL && gotone == 1)
4845 						strlcpy(fnamep,
4846 						    pf->dsf_filename,
4847 						    sizeof(pf->dsf_filename));
4848 				} else
4849 					NFSD_DEBUG(4, "nfsrv_dsgetsockmnt "
4850 					    "err=%d\n", error);
4851 			}
4852 		}
4853 	}
4854 	if (error == 0 && gotone == 0)
4855 		error = ENOENT;
4856 
4857 	NFSD_DEBUG(4, "eo nfsrv_dsgetsockmnt: gotone=%d err=%d\n", gotone,
4858 	    error);
4859 	if (error == 0)
4860 		*mirrorcntp = gotone;
4861 	else {
4862 		if (gotone > 0 && dvpp != NULL) {
4863 			/*
4864 			 * If the error didn't occur on the first one and
4865 			 * dvpp != NULL, the one(s) prior to the failure will
4866 			 * have locked dvp's that need to be unlocked.
4867 			 */
4868 			for (i = 0; i < gotone; i++) {
4869 				NFSVOPUNLOCK(*dvpp);
4870 				*dvpp++ = NULL;
4871 			}
4872 		}
4873 		/*
4874 		 * If it found the vnode to be copied from before a failure,
4875 		 * it needs to be vput()'d.
4876 		 */
4877 		if (nvpp != NULL && *nvpp != NULL) {
4878 			vput(*nvpp);
4879 			*nvpp = NULL;
4880 		}
4881 	}
4882 	return (error);
4883 }
4884 
4885 /*
4886  * Set the extended attribute for the Change attribute.
4887  */
4888 static int
4889 nfsrv_setextattr(struct vnode *vp, struct nfsvattr *nap, NFSPROC_T *p)
4890 {
4891 	struct pnfsdsattr dsattr;
4892 	int error;
4893 
4894 	ASSERT_VOP_ELOCKED(vp, "nfsrv_setextattr vp");
4895 	dsattr.dsa_filerev = nap->na_filerev;
4896 	dsattr.dsa_size = nap->na_size;
4897 	dsattr.dsa_atime = nap->na_atime;
4898 	dsattr.dsa_mtime = nap->na_mtime;
4899 	dsattr.dsa_bytes = nap->na_bytes;
4900 	error = vn_extattr_set(vp, IO_NODELOCKED, EXTATTR_NAMESPACE_SYSTEM,
4901 	    "pnfsd.dsattr", sizeof(dsattr), (char *)&dsattr, p);
4902 	if (error != 0)
4903 		printf("pNFS: setextattr=%d\n", error);
4904 	return (error);
4905 }
4906 
4907 static int
4908 nfsrv_readdsrpc(fhandle_t *fhp, off_t off, int len, struct ucred *cred,
4909     NFSPROC_T *p, struct nfsmount *nmp, struct mbuf **mpp, struct mbuf **mpendp)
4910 {
4911 	uint32_t *tl;
4912 	struct nfsrv_descript *nd;
4913 	nfsv4stateid_t st;
4914 	struct mbuf *m, *m2;
4915 	int error = 0, retlen, tlen, trimlen;
4916 
4917 	NFSD_DEBUG(4, "in nfsrv_readdsrpc\n");
4918 	nd = malloc(sizeof(*nd), M_TEMP, M_WAITOK | M_ZERO);
4919 	*mpp = NULL;
4920 	/*
4921 	 * Use a stateid where other is an alternating 01010 pattern and
4922 	 * seqid is 0xffffffff.  This value is not defined as special by
4923 	 * the RFC and is used by the FreeBSD NFS server to indicate an
4924 	 * MDS->DS proxy operation.
4925 	 */
4926 	st.other[0] = 0x55555555;
4927 	st.other[1] = 0x55555555;
4928 	st.other[2] = 0x55555555;
4929 	st.seqid = 0xffffffff;
4930 	nfscl_reqstart(nd, NFSPROC_READDS, nmp, (u_int8_t *)fhp, sizeof(*fhp),
4931 	    NULL, NULL, 0, 0);
4932 	nfsm_stateidtom(nd, &st, NFSSTATEID_PUTSTATEID);
4933 	NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED * 3);
4934 	txdr_hyper(off, tl);
4935 	*(tl + 2) = txdr_unsigned(len);
4936 	error = newnfs_request(nd, nmp, NULL, &nmp->nm_sockreq, NULL, p, cred,
4937 	    NFS_PROG, NFS_VER4, NULL, 1, NULL, NULL);
4938 	if (error != 0) {
4939 		free(nd, M_TEMP);
4940 		return (error);
4941 	}
4942 	if (nd->nd_repstat == 0) {
4943 		NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
4944 		NFSM_STRSIZ(retlen, len);
4945 		if (retlen > 0) {
4946 			/* Trim off the pre-data XDR from the mbuf chain. */
4947 			m = nd->nd_mrep;
4948 			while (m != NULL && m != nd->nd_md) {
4949 				if (m->m_next == nd->nd_md) {
4950 					m->m_next = NULL;
4951 					m_freem(nd->nd_mrep);
4952 					nd->nd_mrep = m = nd->nd_md;
4953 				} else
4954 					m = m->m_next;
4955 			}
4956 			if (m == NULL) {
4957 				printf("nfsrv_readdsrpc: busted mbuf list\n");
4958 				error = ENOENT;
4959 				goto nfsmout;
4960 			}
4961 
4962 			/*
4963 			 * Now, adjust first mbuf so that any XDR before the
4964 			 * read data is skipped over.
4965 			 */
4966 			trimlen = nd->nd_dpos - mtod(m, char *);
4967 			if (trimlen > 0) {
4968 				m->m_len -= trimlen;
4969 				NFSM_DATAP(m, trimlen);
4970 			}
4971 
4972 			/*
4973 			 * Truncate the mbuf chain at retlen bytes of data,
4974 			 * plus XDR padding that brings the length up to a
4975 			 * multiple of 4.
4976 			 */
4977 			tlen = NFSM_RNDUP(retlen);
4978 			do {
4979 				if (m->m_len >= tlen) {
4980 					m->m_len = tlen;
4981 					tlen = 0;
4982 					m2 = m->m_next;
4983 					m->m_next = NULL;
4984 					m_freem(m2);
4985 					break;
4986 				}
4987 				tlen -= m->m_len;
4988 				m = m->m_next;
4989 			} while (m != NULL);
4990 			if (tlen > 0) {
4991 				printf("nfsrv_readdsrpc: busted mbuf list\n");
4992 				error = ENOENT;
4993 				goto nfsmout;
4994 			}
4995 			*mpp = nd->nd_mrep;
4996 			*mpendp = m;
4997 			nd->nd_mrep = NULL;
4998 		}
4999 	} else
5000 		error = nd->nd_repstat;
5001 nfsmout:
5002 	/* If nd->nd_mrep is already NULL, this is a no-op. */
5003 	m_freem(nd->nd_mrep);
5004 	free(nd, M_TEMP);
5005 	NFSD_DEBUG(4, "nfsrv_readdsrpc error=%d\n", error);
5006 	return (error);
5007 }
5008 
5009 /*
5010  * Do a write RPC on a DS data file, using this structure for the arguments,
5011  * so that this function can be executed by a separate kernel process.
5012  */
5013 struct nfsrvwritedsdorpc {
5014 	int			done;
5015 	int			inprog;
5016 	struct task		tsk;
5017 	fhandle_t		fh;
5018 	off_t			off;
5019 	int			len;
5020 	struct nfsmount		*nmp;
5021 	struct ucred		*cred;
5022 	NFSPROC_T		*p;
5023 	struct mbuf		*m;
5024 	int			err;
5025 };
5026 
5027 static int
5028 nfsrv_writedsdorpc(struct nfsmount *nmp, fhandle_t *fhp, off_t off, int len,
5029     struct nfsvattr *nap, struct mbuf *m, struct ucred *cred, NFSPROC_T *p)
5030 {
5031 	uint32_t *tl;
5032 	struct nfsrv_descript *nd;
5033 	nfsattrbit_t attrbits;
5034 	nfsv4stateid_t st;
5035 	int commit, error, retlen;
5036 
5037 	nd = malloc(sizeof(*nd), M_TEMP, M_WAITOK | M_ZERO);
5038 	nfscl_reqstart(nd, NFSPROC_WRITE, nmp, (u_int8_t *)fhp,
5039 	    sizeof(fhandle_t), NULL, NULL, 0, 0);
5040 
5041 	/*
5042 	 * Use a stateid where other is an alternating 01010 pattern and
5043 	 * seqid is 0xffffffff.  This value is not defined as special by
5044 	 * the RFC and is used by the FreeBSD NFS server to indicate an
5045 	 * MDS->DS proxy operation.
5046 	 */
5047 	st.other[0] = 0x55555555;
5048 	st.other[1] = 0x55555555;
5049 	st.other[2] = 0x55555555;
5050 	st.seqid = 0xffffffff;
5051 	nfsm_stateidtom(nd, &st, NFSSTATEID_PUTSTATEID);
5052 	NFSM_BUILD(tl, u_int32_t *, NFSX_HYPER + 2 * NFSX_UNSIGNED);
5053 	txdr_hyper(off, tl);
5054 	tl += 2;
5055 	/*
5056 	 * Do all writes FileSync, since the server doesn't hold onto dirty
5057 	 * buffers.  Since clients should be accessing the DS servers directly
5058 	 * using the pNFS layouts, this just needs to work correctly as a
5059 	 * fallback.
5060 	 */
5061 	*tl++ = txdr_unsigned(NFSWRITE_FILESYNC);
5062 	*tl = txdr_unsigned(len);
5063 	NFSD_DEBUG(4, "nfsrv_writedsdorpc: len=%d\n", len);
5064 
5065 	/* Put data in mbuf chain. */
5066 	nd->nd_mb->m_next = m;
5067 
5068 	/* Set nd_mb and nd_bpos to end of data. */
5069 	while (m->m_next != NULL)
5070 		m = m->m_next;
5071 	nd->nd_mb = m;
5072 	nd->nd_bpos = mtod(m, char *) + m->m_len;
5073 	NFSD_DEBUG(4, "nfsrv_writedsdorpc: lastmb len=%d\n", m->m_len);
5074 
5075 	/* Do a Getattr for the attributes that change upon writing. */
5076 	NFSZERO_ATTRBIT(&attrbits);
5077 	NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_SIZE);
5078 	NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_CHANGE);
5079 	NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_TIMEACCESS);
5080 	NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_TIMEMODIFY);
5081 	NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_SPACEUSED);
5082 	NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
5083 	*tl = txdr_unsigned(NFSV4OP_GETATTR);
5084 	(void) nfsrv_putattrbit(nd, &attrbits);
5085 	error = newnfs_request(nd, nmp, NULL, &nmp->nm_sockreq, NULL, p,
5086 	    cred, NFS_PROG, NFS_VER4, NULL, 1, NULL, NULL);
5087 	if (error != 0) {
5088 		free(nd, M_TEMP);
5089 		return (error);
5090 	}
5091 	NFSD_DEBUG(4, "nfsrv_writedsdorpc: aft writerpc=%d\n", nd->nd_repstat);
5092 	/* Get rid of weak cache consistency data for now. */
5093 	if ((nd->nd_flag & (ND_NOMOREDATA | ND_NFSV4 | ND_V4WCCATTR)) ==
5094 	    (ND_NFSV4 | ND_V4WCCATTR)) {
5095 		error = nfsv4_loadattr(nd, NULL, nap, NULL, NULL, 0, NULL, NULL,
5096 		    NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL);
5097 		NFSD_DEBUG(4, "nfsrv_writedsdorpc: wcc attr=%d\n", error);
5098 		if (error != 0)
5099 			goto nfsmout;
5100 		/*
5101 		 * Get rid of Op# and status for next op.
5102 		 */
5103 		NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED);
5104 		if (*++tl != 0)
5105 			nd->nd_flag |= ND_NOMOREDATA;
5106 	}
5107 	if (nd->nd_repstat == 0) {
5108 		NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED + NFSX_VERF);
5109 		retlen = fxdr_unsigned(int, *tl++);
5110 		commit = fxdr_unsigned(int, *tl);
5111 		if (commit != NFSWRITE_FILESYNC)
5112 			error = NFSERR_IO;
5113 		NFSD_DEBUG(4, "nfsrv_writedsdorpc:retlen=%d commit=%d err=%d\n",
5114 		    retlen, commit, error);
5115 	} else
5116 		error = nd->nd_repstat;
5117 	/* We have no use for the Write Verifier since we use FileSync. */
5118 
5119 	/*
5120 	 * Get the Change, Size, Access Time and Modify Time attributes and set
5121 	 * on the Metadata file, so its attributes will be what the file's
5122 	 * would be if it had been written.
5123 	 */
5124 	if (error == 0) {
5125 		NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED);
5126 		error = nfsv4_loadattr(nd, NULL, nap, NULL, NULL, 0, NULL, NULL,
5127 		    NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL);
5128 	}
5129 	NFSD_DEBUG(4, "nfsrv_writedsdorpc: aft loadattr=%d\n", error);
5130 nfsmout:
5131 	m_freem(nd->nd_mrep);
5132 	free(nd, M_TEMP);
5133 	NFSD_DEBUG(4, "nfsrv_writedsdorpc error=%d\n", error);
5134 	return (error);
5135 }
5136 
5137 /*
5138  * Start up the thread that will execute nfsrv_writedsdorpc().
5139  */
5140 static void
5141 start_writedsdorpc(void *arg, int pending)
5142 {
5143 	struct nfsrvwritedsdorpc *drpc;
5144 
5145 	drpc = (struct nfsrvwritedsdorpc *)arg;
5146 	drpc->err = nfsrv_writedsdorpc(drpc->nmp, &drpc->fh, drpc->off,
5147 	    drpc->len, NULL, drpc->m, drpc->cred, drpc->p);
5148 	drpc->done = 1;
5149 	NFSD_DEBUG(4, "start_writedsdorpc: err=%d\n", drpc->err);
5150 }
5151 
5152 static int
5153 nfsrv_writedsrpc(fhandle_t *fhp, off_t off, int len, struct ucred *cred,
5154     NFSPROC_T *p, struct vnode *vp, struct nfsmount **nmpp, int mirrorcnt,
5155     struct mbuf **mpp, char *cp, int *failposp)
5156 {
5157 	struct nfsrvwritedsdorpc *drpc, *tdrpc = NULL;
5158 	struct nfsvattr na;
5159 	struct mbuf *m;
5160 	int error, i, offs, ret, timo;
5161 
5162 	NFSD_DEBUG(4, "in nfsrv_writedsrpc\n");
5163 	KASSERT(*mpp != NULL, ("nfsrv_writedsrpc: NULL mbuf chain"));
5164 	drpc = NULL;
5165 	if (mirrorcnt > 1)
5166 		tdrpc = drpc = malloc(sizeof(*drpc) * (mirrorcnt - 1), M_TEMP,
5167 		    M_WAITOK);
5168 
5169 	/* Calculate offset in mbuf chain that data starts. */
5170 	offs = cp - mtod(*mpp, char *);
5171 	NFSD_DEBUG(4, "nfsrv_writedsrpc: mcopy offs=%d len=%d\n", offs, len);
5172 
5173 	/*
5174 	 * Do the write RPC for every DS, using a separate kernel process
5175 	 * for every DS except the last one.
5176 	 */
5177 	error = 0;
5178 	for (i = 0; i < mirrorcnt - 1; i++, tdrpc++) {
5179 		tdrpc->done = 0;
5180 		NFSBCOPY(fhp, &tdrpc->fh, sizeof(*fhp));
5181 		tdrpc->off = off;
5182 		tdrpc->len = len;
5183 		tdrpc->nmp = *nmpp;
5184 		tdrpc->cred = cred;
5185 		tdrpc->p = p;
5186 		tdrpc->inprog = 0;
5187 		tdrpc->err = 0;
5188 		tdrpc->m = m_copym(*mpp, offs, NFSM_RNDUP(len), M_WAITOK);
5189 		ret = EIO;
5190 		if (nfs_pnfsiothreads != 0) {
5191 			ret = nfs_pnfsio(start_writedsdorpc, tdrpc);
5192 			NFSD_DEBUG(4, "nfsrv_writedsrpc: nfs_pnfsio=%d\n",
5193 			    ret);
5194 		}
5195 		if (ret != 0) {
5196 			ret = nfsrv_writedsdorpc(*nmpp, fhp, off, len, NULL,
5197 			    tdrpc->m, cred, p);
5198 			if (nfsds_failerr(ret) && *failposp == -1)
5199 				*failposp = i;
5200 			else if (error == 0 && ret != 0)
5201 				error = ret;
5202 		}
5203 		nmpp++;
5204 		fhp++;
5205 	}
5206 	m = m_copym(*mpp, offs, NFSM_RNDUP(len), M_WAITOK);
5207 	ret = nfsrv_writedsdorpc(*nmpp, fhp, off, len, &na, m, cred, p);
5208 	if (nfsds_failerr(ret) && *failposp == -1 && mirrorcnt > 1)
5209 		*failposp = mirrorcnt - 1;
5210 	else if (error == 0 && ret != 0)
5211 		error = ret;
5212 	if (error == 0)
5213 		error = nfsrv_setextattr(vp, &na, p);
5214 	NFSD_DEBUG(4, "nfsrv_writedsrpc: aft setextat=%d\n", error);
5215 	tdrpc = drpc;
5216 	timo = hz / 50;		/* Wait for 20msec. */
5217 	if (timo < 1)
5218 		timo = 1;
5219 	for (i = 0; i < mirrorcnt - 1; i++, tdrpc++) {
5220 		/* Wait for RPCs on separate threads to complete. */
5221 		while (tdrpc->inprog != 0 && tdrpc->done == 0)
5222 			tsleep(&tdrpc->tsk, PVFS, "srvwrds", timo);
5223 		if (nfsds_failerr(tdrpc->err) && *failposp == -1)
5224 			*failposp = i;
5225 		else if (error == 0 && tdrpc->err != 0)
5226 			error = tdrpc->err;
5227 	}
5228 	free(drpc, M_TEMP);
5229 	return (error);
5230 }
5231 
5232 /*
5233  * Do a allocate RPC on a DS data file, using this structure for the arguments,
5234  * so that this function can be executed by a separate kernel process.
5235  */
5236 struct nfsrvallocatedsdorpc {
5237 	int			done;
5238 	int			inprog;
5239 	struct task		tsk;
5240 	fhandle_t		fh;
5241 	off_t			off;
5242 	off_t			len;
5243 	struct nfsmount		*nmp;
5244 	struct ucred		*cred;
5245 	NFSPROC_T		*p;
5246 	int			err;
5247 };
5248 
5249 static int
5250 nfsrv_allocatedsdorpc(struct nfsmount *nmp, fhandle_t *fhp, off_t off,
5251     off_t len, struct nfsvattr *nap, struct ucred *cred, NFSPROC_T *p)
5252 {
5253 	uint32_t *tl;
5254 	struct nfsrv_descript *nd;
5255 	nfsattrbit_t attrbits;
5256 	nfsv4stateid_t st;
5257 	int error;
5258 
5259 	nd = malloc(sizeof(*nd), M_TEMP, M_WAITOK | M_ZERO);
5260 	nfscl_reqstart(nd, NFSPROC_ALLOCATE, nmp, (u_int8_t *)fhp,
5261 	    sizeof(fhandle_t), NULL, NULL, 0, 0);
5262 
5263 	/*
5264 	 * Use a stateid where other is an alternating 01010 pattern and
5265 	 * seqid is 0xffffffff.  This value is not defined as special by
5266 	 * the RFC and is used by the FreeBSD NFS server to indicate an
5267 	 * MDS->DS proxy operation.
5268 	 */
5269 	st.other[0] = 0x55555555;
5270 	st.other[1] = 0x55555555;
5271 	st.other[2] = 0x55555555;
5272 	st.seqid = 0xffffffff;
5273 	nfsm_stateidtom(nd, &st, NFSSTATEID_PUTSTATEID);
5274 	NFSM_BUILD(tl, uint32_t *, 2 * NFSX_HYPER + NFSX_UNSIGNED);
5275 	txdr_hyper(off, tl); tl += 2;
5276 	txdr_hyper(len, tl); tl += 2;
5277 	NFSD_DEBUG(4, "nfsrv_allocatedsdorpc: len=%jd\n", (intmax_t)len);
5278 
5279 	*tl = txdr_unsigned(NFSV4OP_GETATTR);
5280 	NFSGETATTR_ATTRBIT(&attrbits);
5281 	nfsrv_putattrbit(nd, &attrbits);
5282 	error = newnfs_request(nd, nmp, NULL, &nmp->nm_sockreq, NULL, p,
5283 	    cred, NFS_PROG, NFS_VER4, NULL, 1, NULL, NULL);
5284 	if (error != 0) {
5285 		free(nd, M_TEMP);
5286 		return (error);
5287 	}
5288 	NFSD_DEBUG(4, "nfsrv_allocatedsdorpc: aft allocaterpc=%d\n",
5289 	    nd->nd_repstat);
5290 	if (nd->nd_repstat == 0) {
5291 		NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED);
5292 		error = nfsv4_loadattr(nd, NULL, nap, NULL, NULL, 0, NULL, NULL,
5293 		    NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL);
5294 	} else
5295 		error = nd->nd_repstat;
5296 	NFSD_DEBUG(4, "nfsrv_allocatedsdorpc: aft loadattr=%d\n", error);
5297 nfsmout:
5298 	m_freem(nd->nd_mrep);
5299 	free(nd, M_TEMP);
5300 	NFSD_DEBUG(4, "nfsrv_allocatedsdorpc error=%d\n", error);
5301 	return (error);
5302 }
5303 
5304 /*
5305  * Start up the thread that will execute nfsrv_allocatedsdorpc().
5306  */
5307 static void
5308 start_allocatedsdorpc(void *arg, int pending)
5309 {
5310 	struct nfsrvallocatedsdorpc *drpc;
5311 
5312 	drpc = (struct nfsrvallocatedsdorpc *)arg;
5313 	drpc->err = nfsrv_allocatedsdorpc(drpc->nmp, &drpc->fh, drpc->off,
5314 	    drpc->len, NULL, drpc->cred, drpc->p);
5315 	drpc->done = 1;
5316 	NFSD_DEBUG(4, "start_allocatedsdorpc: err=%d\n", drpc->err);
5317 }
5318 
5319 static int
5320 nfsrv_allocatedsrpc(fhandle_t *fhp, off_t off, off_t len, struct ucred *cred,
5321     NFSPROC_T *p, struct vnode *vp, struct nfsmount **nmpp, int mirrorcnt,
5322     int *failposp)
5323 {
5324 	struct nfsrvallocatedsdorpc *drpc, *tdrpc = NULL;
5325 	struct nfsvattr na;
5326 	int error, i, ret, timo;
5327 
5328 	NFSD_DEBUG(4, "in nfsrv_allocatedsrpc\n");
5329 	drpc = NULL;
5330 	if (mirrorcnt > 1)
5331 		tdrpc = drpc = malloc(sizeof(*drpc) * (mirrorcnt - 1), M_TEMP,
5332 		    M_WAITOK);
5333 
5334 	/*
5335 	 * Do the allocate RPC for every DS, using a separate kernel process
5336 	 * for every DS except the last one.
5337 	 */
5338 	error = 0;
5339 	for (i = 0; i < mirrorcnt - 1; i++, tdrpc++) {
5340 		tdrpc->done = 0;
5341 		NFSBCOPY(fhp, &tdrpc->fh, sizeof(*fhp));
5342 		tdrpc->off = off;
5343 		tdrpc->len = len;
5344 		tdrpc->nmp = *nmpp;
5345 		tdrpc->cred = cred;
5346 		tdrpc->p = p;
5347 		tdrpc->inprog = 0;
5348 		tdrpc->err = 0;
5349 		ret = EIO;
5350 		if (nfs_pnfsiothreads != 0) {
5351 			ret = nfs_pnfsio(start_allocatedsdorpc, tdrpc);
5352 			NFSD_DEBUG(4, "nfsrv_allocatedsrpc: nfs_pnfsio=%d\n",
5353 			    ret);
5354 		}
5355 		if (ret != 0) {
5356 			ret = nfsrv_allocatedsdorpc(*nmpp, fhp, off, len, NULL,
5357 			    cred, p);
5358 			if (nfsds_failerr(ret) && *failposp == -1)
5359 				*failposp = i;
5360 			else if (error == 0 && ret != 0)
5361 				error = ret;
5362 		}
5363 		nmpp++;
5364 		fhp++;
5365 	}
5366 	ret = nfsrv_allocatedsdorpc(*nmpp, fhp, off, len, &na, cred, p);
5367 	if (nfsds_failerr(ret) && *failposp == -1 && mirrorcnt > 1)
5368 		*failposp = mirrorcnt - 1;
5369 	else if (error == 0 && ret != 0)
5370 		error = ret;
5371 	if (error == 0)
5372 		error = nfsrv_setextattr(vp, &na, p);
5373 	NFSD_DEBUG(4, "nfsrv_allocatedsrpc: aft setextat=%d\n", error);
5374 	tdrpc = drpc;
5375 	timo = hz / 50;		/* Wait for 20msec. */
5376 	if (timo < 1)
5377 		timo = 1;
5378 	for (i = 0; i < mirrorcnt - 1; i++, tdrpc++) {
5379 		/* Wait for RPCs on separate threads to complete. */
5380 		while (tdrpc->inprog != 0 && tdrpc->done == 0)
5381 			tsleep(&tdrpc->tsk, PVFS, "srvalds", timo);
5382 		if (nfsds_failerr(tdrpc->err) && *failposp == -1)
5383 			*failposp = i;
5384 		else if (error == 0 && tdrpc->err != 0)
5385 			error = tdrpc->err;
5386 	}
5387 	free(drpc, M_TEMP);
5388 	return (error);
5389 }
5390 
5391 static int
5392 nfsrv_setattrdsdorpc(fhandle_t *fhp, struct ucred *cred, NFSPROC_T *p,
5393     struct vnode *vp, struct nfsmount *nmp, struct nfsvattr *nap,
5394     struct nfsvattr *dsnap)
5395 {
5396 	uint32_t *tl;
5397 	struct nfsrv_descript *nd;
5398 	nfsv4stateid_t st;
5399 	nfsattrbit_t attrbits;
5400 	int error;
5401 
5402 	NFSD_DEBUG(4, "in nfsrv_setattrdsdorpc\n");
5403 	nd = malloc(sizeof(*nd), M_TEMP, M_WAITOK | M_ZERO);
5404 	/*
5405 	 * Use a stateid where other is an alternating 01010 pattern and
5406 	 * seqid is 0xffffffff.  This value is not defined as special by
5407 	 * the RFC and is used by the FreeBSD NFS server to indicate an
5408 	 * MDS->DS proxy operation.
5409 	 */
5410 	st.other[0] = 0x55555555;
5411 	st.other[1] = 0x55555555;
5412 	st.other[2] = 0x55555555;
5413 	st.seqid = 0xffffffff;
5414 	nfscl_reqstart(nd, NFSPROC_SETATTR, nmp, (u_int8_t *)fhp, sizeof(*fhp),
5415 	    NULL, NULL, 0, 0);
5416 	nfsm_stateidtom(nd, &st, NFSSTATEID_PUTSTATEID);
5417 	nfscl_fillsattr(nd, &nap->na_vattr, vp, NFSSATTR_FULL, 0);
5418 
5419 	/* Do a Getattr for the attributes that change due to writing. */
5420 	NFSZERO_ATTRBIT(&attrbits);
5421 	NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_SIZE);
5422 	NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_CHANGE);
5423 	NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_TIMEACCESS);
5424 	NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_TIMEMODIFY);
5425 	NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_SPACEUSED);
5426 	NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
5427 	*tl = txdr_unsigned(NFSV4OP_GETATTR);
5428 	(void) nfsrv_putattrbit(nd, &attrbits);
5429 	error = newnfs_request(nd, nmp, NULL, &nmp->nm_sockreq, NULL, p, cred,
5430 	    NFS_PROG, NFS_VER4, NULL, 1, NULL, NULL);
5431 	if (error != 0) {
5432 		free(nd, M_TEMP);
5433 		return (error);
5434 	}
5435 	NFSD_DEBUG(4, "nfsrv_setattrdsdorpc: aft setattrrpc=%d\n",
5436 	    nd->nd_repstat);
5437 	/* Get rid of weak cache consistency data for now. */
5438 	if ((nd->nd_flag & (ND_NOMOREDATA | ND_NFSV4 | ND_V4WCCATTR)) ==
5439 	    (ND_NFSV4 | ND_V4WCCATTR)) {
5440 		error = nfsv4_loadattr(nd, NULL, dsnap, NULL, NULL, 0, NULL,
5441 		    NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL);
5442 		NFSD_DEBUG(4, "nfsrv_setattrdsdorpc: wcc attr=%d\n", error);
5443 		if (error != 0)
5444 			goto nfsmout;
5445 		/*
5446 		 * Get rid of Op# and status for next op.
5447 		 */
5448 		NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED);
5449 		if (*++tl != 0)
5450 			nd->nd_flag |= ND_NOMOREDATA;
5451 	}
5452 	error = nfsrv_getattrbits(nd, &attrbits, NULL, NULL);
5453 	if (error != 0)
5454 		goto nfsmout;
5455 	if (nd->nd_repstat != 0)
5456 		error = nd->nd_repstat;
5457 	/*
5458 	 * Get the Change, Size, Access Time and Modify Time attributes and set
5459 	 * on the Metadata file, so its attributes will be what the file's
5460 	 * would be if it had been written.
5461 	 */
5462 	if (error == 0) {
5463 		NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED);
5464 		error = nfsv4_loadattr(nd, NULL, dsnap, NULL, NULL, 0, NULL,
5465 		    NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL);
5466 	}
5467 	NFSD_DEBUG(4, "nfsrv_setattrdsdorpc: aft setattr loadattr=%d\n", error);
5468 nfsmout:
5469 	m_freem(nd->nd_mrep);
5470 	free(nd, M_TEMP);
5471 	NFSD_DEBUG(4, "nfsrv_setattrdsdorpc error=%d\n", error);
5472 	return (error);
5473 }
5474 
5475 struct nfsrvsetattrdsdorpc {
5476 	int			done;
5477 	int			inprog;
5478 	struct task		tsk;
5479 	fhandle_t		fh;
5480 	struct nfsmount		*nmp;
5481 	struct vnode		*vp;
5482 	struct ucred		*cred;
5483 	NFSPROC_T		*p;
5484 	struct nfsvattr		na;
5485 	struct nfsvattr		dsna;
5486 	int			err;
5487 };
5488 
5489 /*
5490  * Start up the thread that will execute nfsrv_setattrdsdorpc().
5491  */
5492 static void
5493 start_setattrdsdorpc(void *arg, int pending)
5494 {
5495 	struct nfsrvsetattrdsdorpc *drpc;
5496 
5497 	drpc = (struct nfsrvsetattrdsdorpc *)arg;
5498 	drpc->err = nfsrv_setattrdsdorpc(&drpc->fh, drpc->cred, drpc->p,
5499 	    drpc->vp, drpc->nmp, &drpc->na, &drpc->dsna);
5500 	drpc->done = 1;
5501 }
5502 
5503 static int
5504 nfsrv_setattrdsrpc(fhandle_t *fhp, struct ucred *cred, NFSPROC_T *p,
5505     struct vnode *vp, struct nfsmount **nmpp, int mirrorcnt,
5506     struct nfsvattr *nap, int *failposp)
5507 {
5508 	struct nfsrvsetattrdsdorpc *drpc, *tdrpc = NULL;
5509 	struct nfsvattr na;
5510 	int error, i, ret, timo;
5511 
5512 	NFSD_DEBUG(4, "in nfsrv_setattrdsrpc\n");
5513 	drpc = NULL;
5514 	if (mirrorcnt > 1)
5515 		tdrpc = drpc = malloc(sizeof(*drpc) * (mirrorcnt - 1), M_TEMP,
5516 		    M_WAITOK);
5517 
5518 	/*
5519 	 * Do the setattr RPC for every DS, using a separate kernel process
5520 	 * for every DS except the last one.
5521 	 */
5522 	error = 0;
5523 	for (i = 0; i < mirrorcnt - 1; i++, tdrpc++) {
5524 		tdrpc->done = 0;
5525 		tdrpc->inprog = 0;
5526 		NFSBCOPY(fhp, &tdrpc->fh, sizeof(*fhp));
5527 		tdrpc->nmp = *nmpp;
5528 		tdrpc->vp = vp;
5529 		tdrpc->cred = cred;
5530 		tdrpc->p = p;
5531 		tdrpc->na = *nap;
5532 		tdrpc->err = 0;
5533 		ret = EIO;
5534 		if (nfs_pnfsiothreads != 0) {
5535 			ret = nfs_pnfsio(start_setattrdsdorpc, tdrpc);
5536 			NFSD_DEBUG(4, "nfsrv_setattrdsrpc: nfs_pnfsio=%d\n",
5537 			    ret);
5538 		}
5539 		if (ret != 0) {
5540 			ret = nfsrv_setattrdsdorpc(fhp, cred, p, vp, *nmpp, nap,
5541 			    &na);
5542 			if (nfsds_failerr(ret) && *failposp == -1)
5543 				*failposp = i;
5544 			else if (error == 0 && ret != 0)
5545 				error = ret;
5546 		}
5547 		nmpp++;
5548 		fhp++;
5549 	}
5550 	ret = nfsrv_setattrdsdorpc(fhp, cred, p, vp, *nmpp, nap, &na);
5551 	if (nfsds_failerr(ret) && *failposp == -1 && mirrorcnt > 1)
5552 		*failposp = mirrorcnt - 1;
5553 	else if (error == 0 && ret != 0)
5554 		error = ret;
5555 	if (error == 0)
5556 		error = nfsrv_setextattr(vp, &na, p);
5557 	NFSD_DEBUG(4, "nfsrv_setattrdsrpc: aft setextat=%d\n", error);
5558 	tdrpc = drpc;
5559 	timo = hz / 50;		/* Wait for 20msec. */
5560 	if (timo < 1)
5561 		timo = 1;
5562 	for (i = 0; i < mirrorcnt - 1; i++, tdrpc++) {
5563 		/* Wait for RPCs on separate threads to complete. */
5564 		while (tdrpc->inprog != 0 && tdrpc->done == 0)
5565 			tsleep(&tdrpc->tsk, PVFS, "srvsads", timo);
5566 		if (nfsds_failerr(tdrpc->err) && *failposp == -1)
5567 			*failposp = i;
5568 		else if (error == 0 && tdrpc->err != 0)
5569 			error = tdrpc->err;
5570 	}
5571 	free(drpc, M_TEMP);
5572 	return (error);
5573 }
5574 
5575 /*
5576  * Do a Setattr of an NFSv4 ACL on the DS file.
5577  */
5578 static int
5579 nfsrv_setacldsdorpc(fhandle_t *fhp, struct ucred *cred, NFSPROC_T *p,
5580     struct vnode *vp, struct nfsmount *nmp, struct acl *aclp)
5581 {
5582 	struct nfsrv_descript *nd;
5583 	nfsv4stateid_t st;
5584 	nfsattrbit_t attrbits;
5585 	int error;
5586 
5587 	NFSD_DEBUG(4, "in nfsrv_setacldsdorpc\n");
5588 	nd = malloc(sizeof(*nd), M_TEMP, M_WAITOK | M_ZERO);
5589 	/*
5590 	 * Use a stateid where other is an alternating 01010 pattern and
5591 	 * seqid is 0xffffffff.  This value is not defined as special by
5592 	 * the RFC and is used by the FreeBSD NFS server to indicate an
5593 	 * MDS->DS proxy operation.
5594 	 */
5595 	st.other[0] = 0x55555555;
5596 	st.other[1] = 0x55555555;
5597 	st.other[2] = 0x55555555;
5598 	st.seqid = 0xffffffff;
5599 	nfscl_reqstart(nd, NFSPROC_SETACL, nmp, (u_int8_t *)fhp, sizeof(*fhp),
5600 	    NULL, NULL, 0, 0);
5601 	nfsm_stateidtom(nd, &st, NFSSTATEID_PUTSTATEID);
5602 	NFSZERO_ATTRBIT(&attrbits);
5603 	NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_ACL);
5604 	/*
5605 	 * The "vp" argument to nfsv4_fillattr() is only used for vnode_type(),
5606 	 * so passing in the metadata "vp" will be ok, since it is of
5607 	 * the same type (VREG).
5608 	 */
5609 	nfsv4_fillattr(nd, NULL, vp, aclp, NULL, NULL, 0, &attrbits, NULL,
5610 	    NULL, 0, 0, 0, 0, 0, NULL);
5611 	error = newnfs_request(nd, nmp, NULL, &nmp->nm_sockreq, NULL, p, cred,
5612 	    NFS_PROG, NFS_VER4, NULL, 1, NULL, NULL);
5613 	if (error != 0) {
5614 		free(nd, M_TEMP);
5615 		return (error);
5616 	}
5617 	NFSD_DEBUG(4, "nfsrv_setacldsdorpc: aft setaclrpc=%d\n",
5618 	    nd->nd_repstat);
5619 	error = nd->nd_repstat;
5620 	m_freem(nd->nd_mrep);
5621 	free(nd, M_TEMP);
5622 	return (error);
5623 }
5624 
5625 struct nfsrvsetacldsdorpc {
5626 	int			done;
5627 	int			inprog;
5628 	struct task		tsk;
5629 	fhandle_t		fh;
5630 	struct nfsmount		*nmp;
5631 	struct vnode		*vp;
5632 	struct ucred		*cred;
5633 	NFSPROC_T		*p;
5634 	struct acl		*aclp;
5635 	int			err;
5636 };
5637 
5638 /*
5639  * Start up the thread that will execute nfsrv_setacldsdorpc().
5640  */
5641 static void
5642 start_setacldsdorpc(void *arg, int pending)
5643 {
5644 	struct nfsrvsetacldsdorpc *drpc;
5645 
5646 	drpc = (struct nfsrvsetacldsdorpc *)arg;
5647 	drpc->err = nfsrv_setacldsdorpc(&drpc->fh, drpc->cred, drpc->p,
5648 	    drpc->vp, drpc->nmp, drpc->aclp);
5649 	drpc->done = 1;
5650 }
5651 
5652 static int
5653 nfsrv_setacldsrpc(fhandle_t *fhp, struct ucred *cred, NFSPROC_T *p,
5654     struct vnode *vp, struct nfsmount **nmpp, int mirrorcnt, struct acl *aclp,
5655     int *failposp)
5656 {
5657 	struct nfsrvsetacldsdorpc *drpc, *tdrpc = NULL;
5658 	int error, i, ret, timo;
5659 
5660 	NFSD_DEBUG(4, "in nfsrv_setacldsrpc\n");
5661 	drpc = NULL;
5662 	if (mirrorcnt > 1)
5663 		tdrpc = drpc = malloc(sizeof(*drpc) * (mirrorcnt - 1), M_TEMP,
5664 		    M_WAITOK);
5665 
5666 	/*
5667 	 * Do the setattr RPC for every DS, using a separate kernel process
5668 	 * for every DS except the last one.
5669 	 */
5670 	error = 0;
5671 	for (i = 0; i < mirrorcnt - 1; i++, tdrpc++) {
5672 		tdrpc->done = 0;
5673 		tdrpc->inprog = 0;
5674 		NFSBCOPY(fhp, &tdrpc->fh, sizeof(*fhp));
5675 		tdrpc->nmp = *nmpp;
5676 		tdrpc->vp = vp;
5677 		tdrpc->cred = cred;
5678 		tdrpc->p = p;
5679 		tdrpc->aclp = aclp;
5680 		tdrpc->err = 0;
5681 		ret = EIO;
5682 		if (nfs_pnfsiothreads != 0) {
5683 			ret = nfs_pnfsio(start_setacldsdorpc, tdrpc);
5684 			NFSD_DEBUG(4, "nfsrv_setacldsrpc: nfs_pnfsio=%d\n",
5685 			    ret);
5686 		}
5687 		if (ret != 0) {
5688 			ret = nfsrv_setacldsdorpc(fhp, cred, p, vp, *nmpp,
5689 			    aclp);
5690 			if (nfsds_failerr(ret) && *failposp == -1)
5691 				*failposp = i;
5692 			else if (error == 0 && ret != 0)
5693 				error = ret;
5694 		}
5695 		nmpp++;
5696 		fhp++;
5697 	}
5698 	ret = nfsrv_setacldsdorpc(fhp, cred, p, vp, *nmpp, aclp);
5699 	if (nfsds_failerr(ret) && *failposp == -1 && mirrorcnt > 1)
5700 		*failposp = mirrorcnt - 1;
5701 	else if (error == 0 && ret != 0)
5702 		error = ret;
5703 	NFSD_DEBUG(4, "nfsrv_setacldsrpc: aft setextat=%d\n", error);
5704 	tdrpc = drpc;
5705 	timo = hz / 50;		/* Wait for 20msec. */
5706 	if (timo < 1)
5707 		timo = 1;
5708 	for (i = 0; i < mirrorcnt - 1; i++, tdrpc++) {
5709 		/* Wait for RPCs on separate threads to complete. */
5710 		while (tdrpc->inprog != 0 && tdrpc->done == 0)
5711 			tsleep(&tdrpc->tsk, PVFS, "srvacds", timo);
5712 		if (nfsds_failerr(tdrpc->err) && *failposp == -1)
5713 			*failposp = i;
5714 		else if (error == 0 && tdrpc->err != 0)
5715 			error = tdrpc->err;
5716 	}
5717 	free(drpc, M_TEMP);
5718 	return (error);
5719 }
5720 
5721 /*
5722  * Getattr call to the DS for the attributes that change due to writing.
5723  */
5724 static int
5725 nfsrv_getattrdsrpc(fhandle_t *fhp, struct ucred *cred, NFSPROC_T *p,
5726     struct vnode *vp, struct nfsmount *nmp, struct nfsvattr *nap)
5727 {
5728 	struct nfsrv_descript *nd;
5729 	int error;
5730 	nfsattrbit_t attrbits;
5731 
5732 	NFSD_DEBUG(4, "in nfsrv_getattrdsrpc\n");
5733 	nd = malloc(sizeof(*nd), M_TEMP, M_WAITOK | M_ZERO);
5734 	nfscl_reqstart(nd, NFSPROC_GETATTR, nmp, (u_int8_t *)fhp,
5735 	    sizeof(fhandle_t), NULL, NULL, 0, 0);
5736 	NFSZERO_ATTRBIT(&attrbits);
5737 	NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_SIZE);
5738 	NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_CHANGE);
5739 	NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_TIMEACCESS);
5740 	NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_TIMEMODIFY);
5741 	NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_SPACEUSED);
5742 	(void) nfsrv_putattrbit(nd, &attrbits);
5743 	error = newnfs_request(nd, nmp, NULL, &nmp->nm_sockreq, NULL, p, cred,
5744 	    NFS_PROG, NFS_VER4, NULL, 1, NULL, NULL);
5745 	if (error != 0) {
5746 		free(nd, M_TEMP);
5747 		return (error);
5748 	}
5749 	NFSD_DEBUG(4, "nfsrv_getattrdsrpc: aft getattrrpc=%d\n",
5750 	    nd->nd_repstat);
5751 	if (nd->nd_repstat == 0) {
5752 		error = nfsv4_loadattr(nd, NULL, nap, NULL, NULL, 0,
5753 		    NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL,
5754 		    NULL, NULL);
5755 		/*
5756 		 * We can only save the updated values in the extended
5757 		 * attribute if the vp is exclusively locked.
5758 		 * This should happen when any of the following operations
5759 		 * occur on the vnode:
5760 		 *    Close, Delegreturn, LayoutCommit, LayoutReturn
5761 		 * As such, the updated extended attribute should get saved
5762 		 * before nfsrv_checkdsattr() returns 0 and allows the cached
5763 		 * attributes to be returned without calling this function.
5764 		 */
5765 		if (error == 0 && VOP_ISLOCKED(vp) == LK_EXCLUSIVE) {
5766 			error = nfsrv_setextattr(vp, nap, p);
5767 			NFSD_DEBUG(4, "nfsrv_getattrdsrpc: aft setextat=%d\n",
5768 			    error);
5769 		}
5770 	} else
5771 		error = nd->nd_repstat;
5772 	m_freem(nd->nd_mrep);
5773 	free(nd, M_TEMP);
5774 	NFSD_DEBUG(4, "nfsrv_getattrdsrpc error=%d\n", error);
5775 	return (error);
5776 }
5777 
5778 /*
5779  * Seek call to a DS.
5780  */
5781 static int
5782 nfsrv_seekdsrpc(fhandle_t *fhp, off_t *offp, int content, bool *eofp,
5783     struct ucred *cred, NFSPROC_T *p, struct nfsmount *nmp)
5784 {
5785 	uint32_t *tl;
5786 	struct nfsrv_descript *nd;
5787 	nfsv4stateid_t st;
5788 	int error;
5789 
5790 	NFSD_DEBUG(4, "in nfsrv_seekdsrpc\n");
5791 	/*
5792 	 * Use a stateid where other is an alternating 01010 pattern and
5793 	 * seqid is 0xffffffff.  This value is not defined as special by
5794 	 * the RFC and is used by the FreeBSD NFS server to indicate an
5795 	 * MDS->DS proxy operation.
5796 	 */
5797 	st.other[0] = 0x55555555;
5798 	st.other[1] = 0x55555555;
5799 	st.other[2] = 0x55555555;
5800 	st.seqid = 0xffffffff;
5801 	nd = malloc(sizeof(*nd), M_TEMP, M_WAITOK | M_ZERO);
5802 	nfscl_reqstart(nd, NFSPROC_SEEKDS, nmp, (u_int8_t *)fhp,
5803 	    sizeof(fhandle_t), NULL, NULL, 0, 0);
5804 	nfsm_stateidtom(nd, &st, NFSSTATEID_PUTSTATEID);
5805 	NFSM_BUILD(tl, uint32_t *, NFSX_HYPER + NFSX_UNSIGNED);
5806 	txdr_hyper(*offp, tl); tl += 2;
5807 	*tl = txdr_unsigned(content);
5808 	error = newnfs_request(nd, nmp, NULL, &nmp->nm_sockreq, NULL, p, cred,
5809 	    NFS_PROG, NFS_VER4, NULL, 1, NULL, NULL);
5810 	if (error != 0) {
5811 		free(nd, M_TEMP);
5812 		return (error);
5813 	}
5814 	NFSD_DEBUG(4, "nfsrv_seekdsrpc: aft seekrpc=%d\n", nd->nd_repstat);
5815 	if (nd->nd_repstat == 0) {
5816 		NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED + NFSX_HYPER);
5817 		if (*tl++ == newnfs_true)
5818 			*eofp = true;
5819 		else
5820 			*eofp = false;
5821 		*offp = fxdr_hyper(tl);
5822 	} else
5823 		error = nd->nd_repstat;
5824 nfsmout:
5825 	m_freem(nd->nd_mrep);
5826 	free(nd, M_TEMP);
5827 	NFSD_DEBUG(4, "nfsrv_seekdsrpc error=%d\n", error);
5828 	return (error);
5829 }
5830 
5831 /*
5832  * Get the device id and file handle for a DS file.
5833  */
5834 int
5835 nfsrv_dsgetdevandfh(struct vnode *vp, NFSPROC_T *p, int *mirrorcntp,
5836     fhandle_t *fhp, char *devid)
5837 {
5838 	int buflen, error;
5839 	char *buf;
5840 
5841 	buflen = 1024;
5842 	buf = malloc(buflen, M_TEMP, M_WAITOK);
5843 	error = nfsrv_dsgetsockmnt(vp, 0, buf, &buflen, mirrorcntp, p, NULL,
5844 	    fhp, devid, NULL, NULL, NULL, NULL, NULL, NULL);
5845 	free(buf, M_TEMP);
5846 	return (error);
5847 }
5848 
5849 /*
5850  * Do a Lookup against the DS for the filename.
5851  */
5852 static int
5853 nfsrv_pnfslookupds(struct vnode *vp, struct vnode *dvp, struct pnfsdsfile *pf,
5854     struct vnode **nvpp, NFSPROC_T *p)
5855 {
5856 	struct nameidata named;
5857 	struct ucred *tcred;
5858 	char *bufp;
5859 	u_long *hashp;
5860 	struct vnode *nvp;
5861 	int error;
5862 
5863 	tcred = newnfs_getcred();
5864 	named.ni_cnd.cn_nameiop = LOOKUP;
5865 	named.ni_cnd.cn_lkflags = LK_SHARED | LK_RETRY;
5866 	named.ni_cnd.cn_cred = tcred;
5867 	named.ni_cnd.cn_thread = p;
5868 	named.ni_cnd.cn_flags = ISLASTCN | LOCKPARENT | LOCKLEAF | SAVENAME;
5869 	nfsvno_setpathbuf(&named, &bufp, &hashp);
5870 	named.ni_cnd.cn_nameptr = bufp;
5871 	named.ni_cnd.cn_namelen = strlen(pf->dsf_filename);
5872 	strlcpy(bufp, pf->dsf_filename, NAME_MAX);
5873 	NFSD_DEBUG(4, "nfsrv_pnfslookupds: filename=%s\n", bufp);
5874 	error = VOP_LOOKUP(dvp, &nvp, &named.ni_cnd);
5875 	NFSD_DEBUG(4, "nfsrv_pnfslookupds: aft LOOKUP=%d\n", error);
5876 	NFSFREECRED(tcred);
5877 	nfsvno_relpathbuf(&named);
5878 	if (error == 0)
5879 		*nvpp = nvp;
5880 	NFSD_DEBUG(4, "eo nfsrv_pnfslookupds=%d\n", error);
5881 	return (error);
5882 }
5883 
5884 /*
5885  * Set the file handle to the correct one.
5886  */
5887 static void
5888 nfsrv_pnfssetfh(struct vnode *vp, struct pnfsdsfile *pf, char *devid,
5889     char *fnamep, struct vnode *nvp, NFSPROC_T *p)
5890 {
5891 	struct nfsnode *np;
5892 	int ret = 0;
5893 
5894 	np = VTONFS(nvp);
5895 	NFSBCOPY(np->n_fhp->nfh_fh, &pf->dsf_fh, NFSX_MYFH);
5896 	/*
5897 	 * We can only do a vn_set_extattr() if the vnode is exclusively
5898 	 * locked and vn_start_write() has been done.  If devid != NULL or
5899 	 * fnamep != NULL or the vnode is shared locked, vn_start_write()
5900 	 * may not have been done.
5901 	 * If not done now, it will be done on a future call.
5902 	 */
5903 	if (devid == NULL && fnamep == NULL && NFSVOPISLOCKED(vp) ==
5904 	    LK_EXCLUSIVE)
5905 		ret = vn_extattr_set(vp, IO_NODELOCKED,
5906 		    EXTATTR_NAMESPACE_SYSTEM, "pnfsd.dsfile", sizeof(*pf),
5907 		    (char *)pf, p);
5908 	NFSD_DEBUG(4, "eo nfsrv_pnfssetfh=%d\n", ret);
5909 }
5910 
5911 /*
5912  * Cause RPCs waiting on "nmp" to fail.  This is called for a DS mount point
5913  * when the DS has failed.
5914  */
5915 void
5916 nfsrv_killrpcs(struct nfsmount *nmp)
5917 {
5918 
5919 	/*
5920 	 * Call newnfs_nmcancelreqs() to cause
5921 	 * any RPCs in progress on the mount point to
5922 	 * fail.
5923 	 * This will cause any process waiting for an
5924 	 * RPC to complete while holding a vnode lock
5925 	 * on the mounted-on vnode (such as "df" or
5926 	 * a non-forced "umount") to fail.
5927 	 * This will unlock the mounted-on vnode so
5928 	 * a forced dismount can succeed.
5929 	 * The NFSMNTP_CANCELRPCS flag should be set when this function is
5930 	 * called.
5931 	 */
5932 	newnfs_nmcancelreqs(nmp);
5933 }
5934 
5935 /*
5936  * Sum up the statfs info for each of the DSs, so that the client will
5937  * receive the total for all DSs.
5938  */
5939 static int
5940 nfsrv_pnfsstatfs(struct statfs *sf, struct mount *mp)
5941 {
5942 	struct statfs *tsf;
5943 	struct nfsdevice *ds;
5944 	struct vnode **dvpp, **tdvpp, *dvp;
5945 	uint64_t tot;
5946 	int cnt, error = 0, i;
5947 
5948 	if (nfsrv_devidcnt <= 0)
5949 		return (ENXIO);
5950 	dvpp = mallocarray(nfsrv_devidcnt, sizeof(*dvpp), M_TEMP, M_WAITOK);
5951 	tsf = malloc(sizeof(*tsf), M_TEMP, M_WAITOK);
5952 
5953 	/* Get an array of the dvps for the DSs. */
5954 	tdvpp = dvpp;
5955 	i = 0;
5956 	NFSDDSLOCK();
5957 	/* First, search for matches for same file system. */
5958 	TAILQ_FOREACH(ds, &nfsrv_devidhead, nfsdev_list) {
5959 		if (ds->nfsdev_nmp != NULL && ds->nfsdev_mdsisset != 0 &&
5960 		    ds->nfsdev_mdsfsid.val[0] == mp->mnt_stat.f_fsid.val[0] &&
5961 		    ds->nfsdev_mdsfsid.val[1] == mp->mnt_stat.f_fsid.val[1]) {
5962 			if (++i > nfsrv_devidcnt)
5963 				break;
5964 			*tdvpp++ = ds->nfsdev_dvp;
5965 		}
5966 	}
5967 	/*
5968 	 * If no matches for same file system, total all servers not assigned
5969 	 * to a file system.
5970 	 */
5971 	if (i == 0) {
5972 		TAILQ_FOREACH(ds, &nfsrv_devidhead, nfsdev_list) {
5973 			if (ds->nfsdev_nmp != NULL &&
5974 			    ds->nfsdev_mdsisset == 0) {
5975 				if (++i > nfsrv_devidcnt)
5976 					break;
5977 				*tdvpp++ = ds->nfsdev_dvp;
5978 			}
5979 		}
5980 	}
5981 	NFSDDSUNLOCK();
5982 	cnt = i;
5983 
5984 	/* Do a VFS_STATFS() for each of the DSs and sum them up. */
5985 	tdvpp = dvpp;
5986 	for (i = 0; i < cnt && error == 0; i++) {
5987 		dvp = *tdvpp++;
5988 		error = VFS_STATFS(dvp->v_mount, tsf);
5989 		if (error == 0) {
5990 			if (sf->f_bsize == 0) {
5991 				if (tsf->f_bsize > 0)
5992 					sf->f_bsize = tsf->f_bsize;
5993 				else
5994 					sf->f_bsize = 8192;
5995 			}
5996 			if (tsf->f_blocks > 0) {
5997 				if (sf->f_bsize != tsf->f_bsize) {
5998 					tot = tsf->f_blocks * tsf->f_bsize;
5999 					sf->f_blocks += (tot / sf->f_bsize);
6000 				} else
6001 					sf->f_blocks += tsf->f_blocks;
6002 			}
6003 			if (tsf->f_bfree > 0) {
6004 				if (sf->f_bsize != tsf->f_bsize) {
6005 					tot = tsf->f_bfree * tsf->f_bsize;
6006 					sf->f_bfree += (tot / sf->f_bsize);
6007 				} else
6008 					sf->f_bfree += tsf->f_bfree;
6009 			}
6010 			if (tsf->f_bavail > 0) {
6011 				if (sf->f_bsize != tsf->f_bsize) {
6012 					tot = tsf->f_bavail * tsf->f_bsize;
6013 					sf->f_bavail += (tot / sf->f_bsize);
6014 				} else
6015 					sf->f_bavail += tsf->f_bavail;
6016 			}
6017 		}
6018 	}
6019 	free(tsf, M_TEMP);
6020 	free(dvpp, M_TEMP);
6021 	return (error);
6022 }
6023 
6024 /*
6025  * Set an NFSv4 acl.
6026  */
6027 int
6028 nfsrv_setacl(struct vnode *vp, NFSACL_T *aclp, struct ucred *cred, NFSPROC_T *p)
6029 {
6030 	int error;
6031 
6032 	if (nfsrv_useacl == 0 || nfs_supportsnfsv4acls(vp) == 0) {
6033 		error = NFSERR_ATTRNOTSUPP;
6034 		goto out;
6035 	}
6036 	/*
6037 	 * With NFSv4 ACLs, chmod(2) may need to add additional entries.
6038 	 * Make sure it has enough room for that - splitting every entry
6039 	 * into two and appending "canonical six" entries at the end.
6040 	 * Cribbed out of kern/vfs_acl.c - Rick M.
6041 	 */
6042 	if (aclp->acl_cnt > (ACL_MAX_ENTRIES - 6) / 2) {
6043 		error = NFSERR_ATTRNOTSUPP;
6044 		goto out;
6045 	}
6046 	error = VOP_SETACL(vp, ACL_TYPE_NFS4, aclp, cred, p);
6047 	if (error == 0) {
6048 		error = nfsrv_dssetacl(vp, aclp, cred, p);
6049 		if (error == ENOENT)
6050 			error = 0;
6051 	}
6052 
6053 out:
6054 	NFSEXITCODE(error);
6055 	return (error);
6056 }
6057 
6058 /*
6059  * Seek vnode op call (actually it is a VOP_IOCTL()).
6060  * This function is called with the vnode locked, but unlocks and vrele()s
6061  * the vp before returning.
6062  */
6063 int
6064 nfsvno_seek(struct nfsrv_descript *nd, struct vnode *vp, u_long cmd,
6065     off_t *offp, int content, bool *eofp, struct ucred *cred, NFSPROC_T *p)
6066 {
6067 	struct nfsvattr at;
6068 	int error, ret;
6069 
6070 	ASSERT_VOP_LOCKED(vp, "nfsvno_seek vp");
6071 	/*
6072 	 * Attempt to seek on a DS file. A return of ENOENT implies
6073 	 * there is no DS file to seek on.
6074 	 */
6075 	error = nfsrv_proxyds(vp, 0, 0, cred, p, NFSPROC_SEEKDS, NULL,
6076 	    NULL, NULL, NULL, NULL, offp, content, eofp);
6077 	if (error != ENOENT) {
6078 		vput(vp);
6079 		return (error);
6080 	}
6081 
6082 	/*
6083 	 * Do the VOP_IOCTL() call.  For the case where *offp == file_size,
6084 	 * VOP_IOCTL() will return ENXIO.  However, the correct reply for
6085 	 * NFSv4.2 is *eofp == true and error == 0 for this case.
6086 	 */
6087 	NFSVOPUNLOCK(vp);
6088 	error = VOP_IOCTL(vp, cmd, offp, 0, cred, p);
6089 	*eofp = false;
6090 	if (error == ENXIO || (error == 0 && cmd == FIOSEEKHOLE)) {
6091 		/* Handle the cases where we might be at EOF. */
6092 		ret = nfsvno_getattr(vp, &at, nd, p, 0, NULL);
6093 		if (ret == 0 && *offp == at.na_size) {
6094 			*eofp = true;
6095 			error = 0;
6096 		}
6097 		if (ret != 0 && error == 0)
6098 			error = ret;
6099 	}
6100 	vrele(vp);
6101 	NFSEXITCODE(error);
6102 	return (error);
6103 }
6104 
6105 /*
6106  * Allocate vnode op call.
6107  */
6108 int
6109 nfsvno_allocate(struct vnode *vp, off_t off, off_t len, struct ucred *cred,
6110     NFSPROC_T *p)
6111 {
6112 	int error, trycnt;
6113 
6114 	ASSERT_VOP_ELOCKED(vp, "nfsvno_allocate vp");
6115 	/*
6116 	 * Attempt to allocate on a DS file. A return of ENOENT implies
6117 	 * there is no DS file to allocate on.
6118 	 */
6119 	error = nfsrv_proxyds(vp, off, 0, cred, p, NFSPROC_ALLOCATE, NULL,
6120 	    NULL, NULL, NULL, NULL, &len, 0, NULL);
6121 	if (error != ENOENT)
6122 		return (error);
6123 	error = 0;
6124 
6125 	/*
6126 	 * Do the actual VOP_ALLOCATE(), looping a reasonable number of
6127 	 * times to achieve completion.
6128 	 */
6129 	trycnt = 0;
6130 	while (error == 0 && len > 0 && trycnt++ < 20)
6131 		error = VOP_ALLOCATE(vp, &off, &len);
6132 	if (error == 0 && len > 0)
6133 		error = NFSERR_IO;
6134 	NFSEXITCODE(error);
6135 	return (error);
6136 }
6137 
6138 /*
6139  * Get Extended Atribute vnode op into an mbuf list.
6140  */
6141 int
6142 nfsvno_getxattr(struct vnode *vp, char *name, uint32_t maxresp,
6143     struct ucred *cred, struct thread *p, struct mbuf **mpp,
6144     struct mbuf **mpendp, int *lenp)
6145 {
6146 	struct iovec *iv;
6147 	struct uio io, *uiop = &io;
6148 	struct mbuf *m, *m2;
6149 	int alen, error, len, tlen;
6150 	size_t siz;
6151 
6152 	/* First, find out the size of the extended attribute. */
6153 	error = VOP_GETEXTATTR(vp, EXTATTR_NAMESPACE_USER, name, NULL,
6154 	    &siz, cred, p);
6155 	if (error != 0)
6156 		return (NFSERR_NOXATTR);
6157 	if (siz > maxresp - NFS_MAXXDR)
6158 		return (NFSERR_XATTR2BIG);
6159 	len = siz;
6160 	tlen = NFSM_RNDUP(len);
6161 	uiop->uio_iovcnt = nfsrv_createiovec(tlen, &m, &m2, &iv);
6162 	uiop->uio_iov = iv;
6163 	uiop->uio_offset = 0;
6164 	uiop->uio_resid = tlen;
6165 	uiop->uio_rw = UIO_READ;
6166 	uiop->uio_segflg = UIO_SYSSPACE;
6167 	uiop->uio_td = p;
6168 #ifdef MAC
6169 	error = mac_vnode_check_getextattr(cred, vp, EXTATTR_NAMESPACE_USER,
6170 	    name);
6171 	if (error != 0)
6172 		goto out;
6173 #endif
6174 
6175 	error = VOP_GETEXTATTR(vp, EXTATTR_NAMESPACE_USER, name, uiop, NULL,
6176 	    cred, p);
6177 	if (error != 0)
6178 		goto out;
6179 	if (uiop->uio_resid > 0) {
6180 		alen = tlen;
6181 		len = tlen - uiop->uio_resid;
6182 		tlen = NFSM_RNDUP(len);
6183 		if (alen != tlen)
6184 			printf("nfsvno_getxattr: weird size read\n");
6185 		nfsrv_adj(m, alen - tlen, tlen - len);
6186 	}
6187 	*lenp = len;
6188 	*mpp = m;
6189 	*mpendp = m2;
6190 
6191 out:
6192 	if (error != 0) {
6193 		m_freem(m);
6194 		*lenp = 0;
6195 	}
6196 	free(iv, M_TEMP);
6197 	NFSEXITCODE(error);
6198 	return (error);
6199 }
6200 
6201 /*
6202  * Set Extended attribute vnode op from an mbuf list.
6203  */
6204 int
6205 nfsvno_setxattr(struct vnode *vp, char *name, int len, struct mbuf *m,
6206     char *cp, struct ucred *cred, struct thread *p)
6207 {
6208 	struct iovec *iv;
6209 	struct uio uio, *uiop = &uio;
6210 	int cnt, error;
6211 
6212 	error = 0;
6213 #ifdef MAC
6214 	error = mac_vnode_check_setextattr(cred, vp, EXTATTR_NAMESPACE_USER,
6215 	    name);
6216 #endif
6217 	if (error != 0)
6218 		goto out;
6219 
6220 	uiop->uio_rw = UIO_WRITE;
6221 	uiop->uio_segflg = UIO_SYSSPACE;
6222 	uiop->uio_td = p;
6223 	uiop->uio_offset = 0;
6224 	uiop->uio_resid = len;
6225 	error = nfsrv_createiovecw(len, m, cp, &iv, &cnt);
6226 	uiop->uio_iov = iv;
6227 	uiop->uio_iovcnt = cnt;
6228 	if (error == 0) {
6229 		error = VOP_SETEXTATTR(vp, EXTATTR_NAMESPACE_USER, name, uiop,
6230 		    cred, p);
6231 		free(iv, M_TEMP);
6232 	}
6233 
6234 out:
6235 	NFSEXITCODE(error);
6236 	return (error);
6237 }
6238 
6239 /*
6240  * Remove Extended attribute vnode op.
6241  */
6242 int
6243 nfsvno_rmxattr(struct nfsrv_descript *nd, struct vnode *vp, char *name,
6244     struct ucred *cred, struct thread *p)
6245 {
6246 	int error;
6247 
6248 	/*
6249 	 * Get rid of any delegations.  I am not sure why this is required,
6250 	 * but RFC-8276 says so.
6251 	 */
6252 	error = nfsrv_checkremove(vp, 0, nd, nd->nd_clientid, p);
6253 	if (error != 0)
6254 		goto out;
6255 #ifdef MAC
6256 	error = mac_vnode_check_deleteextattr(cred, vp, EXTATTR_NAMESPACE_USER,
6257 	    name);
6258 	if (error != 0)
6259 		goto out;
6260 #endif
6261 
6262 	error = VOP_DELETEEXTATTR(vp, EXTATTR_NAMESPACE_USER, name, cred, p);
6263 	if (error == EOPNOTSUPP)
6264 		error = VOP_SETEXTATTR(vp, EXTATTR_NAMESPACE_USER, name, NULL,
6265 		    cred, p);
6266 out:
6267 	NFSEXITCODE(error);
6268 	return (error);
6269 }
6270 
6271 /*
6272  * List Extended Atribute vnode op into an mbuf list.
6273  */
6274 int
6275 nfsvno_listxattr(struct vnode *vp, uint64_t cookie, struct ucred *cred,
6276     struct thread *p, u_char **bufp, uint32_t *lenp, bool *eofp)
6277 {
6278 	struct iovec iv;
6279 	struct uio io;
6280 	int error;
6281 	size_t siz;
6282 
6283 	*bufp = NULL;
6284 	/* First, find out the size of the extended attribute. */
6285 	error = VOP_LISTEXTATTR(vp, EXTATTR_NAMESPACE_USER, NULL, &siz, cred,
6286 	    p);
6287 	if (error != 0)
6288 		return (NFSERR_NOXATTR);
6289 	if (siz <= cookie) {
6290 		*lenp = 0;
6291 		*eofp = true;
6292 		goto out;
6293 	}
6294 	if (siz > cookie + *lenp) {
6295 		siz = cookie + *lenp;
6296 		*eofp = false;
6297 	} else
6298 		*eofp = true;
6299 	/* Just choose a sanity limit of 10Mbytes for malloc(M_TEMP). */
6300 	if (siz > 10 * 1024 * 1024) {
6301 		error = NFSERR_XATTR2BIG;
6302 		goto out;
6303 	}
6304 	*bufp = malloc(siz, M_TEMP, M_WAITOK);
6305 	iv.iov_base = *bufp;
6306 	iv.iov_len = siz;
6307 	io.uio_iovcnt = 1;
6308 	io.uio_iov = &iv;
6309 	io.uio_offset = 0;
6310 	io.uio_resid = siz;
6311 	io.uio_rw = UIO_READ;
6312 	io.uio_segflg = UIO_SYSSPACE;
6313 	io.uio_td = p;
6314 #ifdef MAC
6315 	error = mac_vnode_check_listextattr(cred, vp, EXTATTR_NAMESPACE_USER);
6316 	if (error != 0)
6317 		goto out;
6318 #endif
6319 
6320 	error = VOP_LISTEXTATTR(vp, EXTATTR_NAMESPACE_USER, &io, NULL, cred,
6321 	    p);
6322 	if (error != 0)
6323 		goto out;
6324 	if (io.uio_resid > 0)
6325 		siz -= io.uio_resid;
6326 	*lenp = siz;
6327 
6328 out:
6329 	if (error != 0) {
6330 		free(*bufp, M_TEMP);
6331 		*bufp = NULL;
6332 	}
6333 	NFSEXITCODE(error);
6334 	return (error);
6335 }
6336 
6337 extern int (*nfsd_call_nfsd)(struct thread *, struct nfssvc_args *);
6338 
6339 /*
6340  * Called once to initialize data structures...
6341  */
6342 static int
6343 nfsd_modevent(module_t mod, int type, void *data)
6344 {
6345 	int error = 0, i;
6346 	static int loaded = 0;
6347 
6348 	switch (type) {
6349 	case MOD_LOAD:
6350 		if (loaded)
6351 			goto out;
6352 		newnfs_portinit();
6353 		for (i = 0; i < NFSRVCACHE_HASHSIZE; i++) {
6354 			mtx_init(&nfsrchash_table[i].mtx, "nfsrtc", NULL,
6355 			    MTX_DEF);
6356 			mtx_init(&nfsrcahash_table[i].mtx, "nfsrtca", NULL,
6357 			    MTX_DEF);
6358 		}
6359 		mtx_init(&nfsrc_udpmtx, "nfsuc", NULL, MTX_DEF);
6360 		mtx_init(&nfs_v4root_mutex, "nfs4rt", NULL, MTX_DEF);
6361 		mtx_init(&nfsv4root_mnt.mnt_mtx, "nfs4mnt", NULL, MTX_DEF);
6362 		mtx_init(&nfsrv_dontlistlock_mtx, "nfs4dnl", NULL, MTX_DEF);
6363 		mtx_init(&nfsrv_recalllock_mtx, "nfs4rec", NULL, MTX_DEF);
6364 		lockinit(&nfsv4root_mnt.mnt_explock, PVFS, "explock", 0, 0);
6365 		nfsrvd_initcache();
6366 		nfsd_init();
6367 		NFSD_LOCK();
6368 		nfsrvd_init(0);
6369 		NFSD_UNLOCK();
6370 		nfsd_mntinit();
6371 #ifdef VV_DISABLEDELEG
6372 		vn_deleg_ops.vndeleg_recall = nfsd_recalldelegation;
6373 		vn_deleg_ops.vndeleg_disable = nfsd_disabledelegation;
6374 #endif
6375 		nfsd_call_servertimer = nfsrv_servertimer;
6376 		nfsd_call_nfsd = nfssvc_nfsd;
6377 		loaded = 1;
6378 		break;
6379 
6380 	case MOD_UNLOAD:
6381 		if (newnfs_numnfsd != 0) {
6382 			error = EBUSY;
6383 			break;
6384 		}
6385 
6386 #ifdef VV_DISABLEDELEG
6387 		vn_deleg_ops.vndeleg_recall = NULL;
6388 		vn_deleg_ops.vndeleg_disable = NULL;
6389 #endif
6390 		nfsd_call_servertimer = NULL;
6391 		nfsd_call_nfsd = NULL;
6392 
6393 		/* Clean out all NFSv4 state. */
6394 		nfsrv_throwawayallstate(curthread);
6395 
6396 		/* Clean the NFS server reply cache */
6397 		nfsrvd_cleancache();
6398 
6399 		/* Free up the krpc server pool. */
6400 		if (nfsrvd_pool != NULL)
6401 			svcpool_destroy(nfsrvd_pool);
6402 
6403 		/* and get rid of the locks */
6404 		for (i = 0; i < NFSRVCACHE_HASHSIZE; i++) {
6405 			mtx_destroy(&nfsrchash_table[i].mtx);
6406 			mtx_destroy(&nfsrcahash_table[i].mtx);
6407 		}
6408 		mtx_destroy(&nfsrc_udpmtx);
6409 		mtx_destroy(&nfs_v4root_mutex);
6410 		mtx_destroy(&nfsv4root_mnt.mnt_mtx);
6411 		mtx_destroy(&nfsrv_dontlistlock_mtx);
6412 		mtx_destroy(&nfsrv_recalllock_mtx);
6413 		for (i = 0; i < nfsrv_sessionhashsize; i++)
6414 			mtx_destroy(&nfssessionhash[i].mtx);
6415 		if (nfslayouthash != NULL) {
6416 			for (i = 0; i < nfsrv_layouthashsize; i++)
6417 				mtx_destroy(&nfslayouthash[i].mtx);
6418 			free(nfslayouthash, M_NFSDSESSION);
6419 		}
6420 		lockdestroy(&nfsv4root_mnt.mnt_explock);
6421 		free(nfsclienthash, M_NFSDCLIENT);
6422 		free(nfslockhash, M_NFSDLOCKFILE);
6423 		free(nfssessionhash, M_NFSDSESSION);
6424 		loaded = 0;
6425 		break;
6426 	default:
6427 		error = EOPNOTSUPP;
6428 		break;
6429 	}
6430 
6431 out:
6432 	NFSEXITCODE(error);
6433 	return (error);
6434 }
6435 static moduledata_t nfsd_mod = {
6436 	"nfsd",
6437 	nfsd_modevent,
6438 	NULL,
6439 };
6440 DECLARE_MODULE(nfsd, nfsd_mod, SI_SUB_VFS, SI_ORDER_ANY);
6441 
6442 /* So that loader and kldload(2) can find us, wherever we are.. */
6443 MODULE_VERSION(nfsd, 1);
6444 MODULE_DEPEND(nfsd, nfscommon, 1, 1, 1);
6445 MODULE_DEPEND(nfsd, nfslock, 1, 1, 1);
6446 MODULE_DEPEND(nfsd, nfslockd, 1, 1, 1);
6447 MODULE_DEPEND(nfsd, krpc, 1, 1, 1);
6448 MODULE_DEPEND(nfsd, nfssvc, 1, 1, 1);
6449 
6450