xref: /freebsd/sys/fs/nfsserver/nfs_nfsdstate.c (revision f0cfa1b168014f56c02b83e5f28412cc5f78d117)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2009 Rick Macklem, University of Guelph
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  *
28  */
29 
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
32 
33 #ifndef APPLEKEXT
34 #include <fs/nfs/nfsport.h>
35 
36 struct nfsrv_stablefirst nfsrv_stablefirst;
37 int nfsrv_issuedelegs = 0;
38 int nfsrv_dolocallocks = 0;
39 struct nfsv4lock nfsv4rootfs_lock;
40 
41 extern int newnfs_numnfsd;
42 extern struct nfsstatsv1 nfsstatsv1;
43 extern int nfsrv_lease;
44 extern struct timeval nfsboottime;
45 extern u_int32_t newnfs_true, newnfs_false;
46 NFSV4ROOTLOCKMUTEX;
47 NFSSTATESPINLOCK;
48 
49 SYSCTL_DECL(_vfs_nfsd);
50 int	nfsrv_statehashsize = NFSSTATEHASHSIZE;
51 SYSCTL_INT(_vfs_nfsd, OID_AUTO, statehashsize, CTLFLAG_RDTUN,
52     &nfsrv_statehashsize, 0,
53     "Size of state hash table set via loader.conf");
54 
55 int	nfsrv_clienthashsize = NFSCLIENTHASHSIZE;
56 SYSCTL_INT(_vfs_nfsd, OID_AUTO, clienthashsize, CTLFLAG_RDTUN,
57     &nfsrv_clienthashsize, 0,
58     "Size of client hash table set via loader.conf");
59 
60 int	nfsrv_lockhashsize = NFSLOCKHASHSIZE;
61 SYSCTL_INT(_vfs_nfsd, OID_AUTO, fhhashsize, CTLFLAG_RDTUN,
62     &nfsrv_lockhashsize, 0,
63     "Size of file handle hash table set via loader.conf");
64 
65 int	nfsrv_sessionhashsize = NFSSESSIONHASHSIZE;
66 SYSCTL_INT(_vfs_nfsd, OID_AUTO, sessionhashsize, CTLFLAG_RDTUN,
67     &nfsrv_sessionhashsize, 0,
68     "Size of session hash table set via loader.conf");
69 
70 static int	nfsrv_v4statelimit = NFSRV_V4STATELIMIT;
71 SYSCTL_INT(_vfs_nfsd, OID_AUTO, v4statelimit, CTLFLAG_RWTUN,
72     &nfsrv_v4statelimit, 0,
73     "High water limit for NFSv4 opens+locks+delegations");
74 
75 static int	nfsrv_writedelegifpos = 0;
76 SYSCTL_INT(_vfs_nfsd, OID_AUTO, writedelegifpos, CTLFLAG_RW,
77     &nfsrv_writedelegifpos, 0,
78     "Issue a write delegation for read opens if possible");
79 
80 static int	nfsrv_allowreadforwriteopen = 1;
81 SYSCTL_INT(_vfs_nfsd, OID_AUTO, allowreadforwriteopen, CTLFLAG_RW,
82     &nfsrv_allowreadforwriteopen, 0,
83     "Allow Reads to be done with Write Access StateIDs");
84 
85 /*
86  * Hash lists for nfs V4.
87  */
88 struct nfsclienthashhead	*nfsclienthash;
89 struct nfslockhashhead		*nfslockhash;
90 struct nfssessionhash		*nfssessionhash;
91 #endif	/* !APPLEKEXT */
92 
93 static u_int32_t nfsrv_openpluslock = 0, nfsrv_delegatecnt = 0;
94 static time_t nfsrvboottime;
95 static int nfsrv_returnoldstateid = 0, nfsrv_clients = 0;
96 static int nfsrv_clienthighwater = NFSRV_CLIENTHIGHWATER;
97 static int nfsrv_nogsscallback = 0;
98 
99 /* local functions */
100 static void nfsrv_dumpaclient(struct nfsclient *clp,
101     struct nfsd_dumpclients *dumpp);
102 static void nfsrv_freeopenowner(struct nfsstate *stp, int cansleep,
103     NFSPROC_T *p);
104 static int nfsrv_freeopen(struct nfsstate *stp, vnode_t vp, int cansleep,
105     NFSPROC_T *p);
106 static void nfsrv_freelockowner(struct nfsstate *stp, vnode_t vp, int cansleep,
107     NFSPROC_T *p);
108 static void nfsrv_freeallnfslocks(struct nfsstate *stp, vnode_t vp,
109     int cansleep, NFSPROC_T *p);
110 static void nfsrv_freenfslock(struct nfslock *lop);
111 static void nfsrv_freenfslockfile(struct nfslockfile *lfp);
112 static void nfsrv_freedeleg(struct nfsstate *);
113 static int nfsrv_getstate(struct nfsclient *clp, nfsv4stateid_t *stateidp,
114     u_int32_t flags, struct nfsstate **stpp);
115 static void nfsrv_getowner(struct nfsstatehead *hp, struct nfsstate *new_stp,
116     struct nfsstate **stpp);
117 static int nfsrv_getlockfh(vnode_t vp, u_short flags,
118     struct nfslockfile *new_lfp, fhandle_t *nfhp, NFSPROC_T *p);
119 static int nfsrv_getlockfile(u_short flags, struct nfslockfile **new_lfpp,
120     struct nfslockfile **lfpp, fhandle_t *nfhp, int lockit);
121 static void nfsrv_insertlock(struct nfslock *new_lop,
122     struct nfslock *insert_lop, struct nfsstate *stp, struct nfslockfile *lfp);
123 static void nfsrv_updatelock(struct nfsstate *stp, struct nfslock **new_lopp,
124     struct nfslock **other_lopp, struct nfslockfile *lfp);
125 static int nfsrv_getipnumber(u_char *cp);
126 static int nfsrv_checkrestart(nfsquad_t clientid, u_int32_t flags,
127     nfsv4stateid_t *stateidp, int specialid);
128 static int nfsrv_checkgrace(struct nfsrv_descript *nd, struct nfsclient *clp,
129     u_int32_t flags);
130 static int nfsrv_docallback(struct nfsclient *clp, int procnum,
131     nfsv4stateid_t *stateidp, int trunc, fhandle_t *fhp,
132     struct nfsvattr *nap, nfsattrbit_t *attrbitp, NFSPROC_T *p);
133 static int nfsrv_cbcallargs(struct nfsrv_descript *nd, struct nfsclient *clp,
134     uint32_t callback, int op, const char *optag, struct nfsdsession **sepp);
135 static u_int32_t nfsrv_nextclientindex(void);
136 static u_int32_t nfsrv_nextstateindex(struct nfsclient *clp);
137 static void nfsrv_markstable(struct nfsclient *clp);
138 static int nfsrv_checkstable(struct nfsclient *clp);
139 static int nfsrv_clientconflict(struct nfsclient *clp, int *haslockp, struct
140     vnode *vp, NFSPROC_T *p);
141 static int nfsrv_delegconflict(struct nfsstate *stp, int *haslockp,
142     NFSPROC_T *p, vnode_t vp);
143 static int nfsrv_cleandeleg(vnode_t vp, struct nfslockfile *lfp,
144     struct nfsclient *clp, int *haslockp, NFSPROC_T *p);
145 static int nfsrv_notsamecredname(struct nfsrv_descript *nd,
146     struct nfsclient *clp);
147 static time_t nfsrv_leaseexpiry(void);
148 static void nfsrv_delaydelegtimeout(struct nfsstate *stp);
149 static int nfsrv_checkseqid(struct nfsrv_descript *nd, u_int32_t seqid,
150     struct nfsstate *stp, struct nfsrvcache *op);
151 static int nfsrv_nootherstate(struct nfsstate *stp);
152 static int nfsrv_locallock(vnode_t vp, struct nfslockfile *lfp, int flags,
153     uint64_t first, uint64_t end, struct nfslockconflict *cfp, NFSPROC_T *p);
154 static void nfsrv_localunlock(vnode_t vp, struct nfslockfile *lfp,
155     uint64_t init_first, uint64_t init_end, NFSPROC_T *p);
156 static int nfsrv_dolocal(vnode_t vp, struct nfslockfile *lfp, int flags,
157     int oldflags, uint64_t first, uint64_t end, struct nfslockconflict *cfp,
158     NFSPROC_T *p);
159 static void nfsrv_locallock_rollback(vnode_t vp, struct nfslockfile *lfp,
160     NFSPROC_T *p);
161 static void nfsrv_locallock_commit(struct nfslockfile *lfp, int flags,
162     uint64_t first, uint64_t end);
163 static void nfsrv_locklf(struct nfslockfile *lfp);
164 static void nfsrv_unlocklf(struct nfslockfile *lfp);
165 static struct nfsdsession *nfsrv_findsession(uint8_t *sessionid);
166 static int nfsrv_freesession(struct nfsdsession *sep, uint8_t *sessionid);
167 static int nfsv4_setcbsequence(struct nfsrv_descript *nd, struct nfsclient *clp,
168     int dont_replycache, struct nfsdsession **sepp);
169 static int nfsv4_getcbsession(struct nfsclient *clp, struct nfsdsession **sepp);
170 
171 /*
172  * Scan the client list for a match and either return the current one,
173  * create a new entry or return an error.
174  * If returning a non-error, the clp structure must either be linked into
175  * the client list or free'd.
176  */
177 APPLESTATIC int
178 nfsrv_setclient(struct nfsrv_descript *nd, struct nfsclient **new_clpp,
179     nfsquad_t *clientidp, nfsquad_t *confirmp, NFSPROC_T *p)
180 {
181 	struct nfsclient *clp = NULL, *new_clp = *new_clpp;
182 	int i, error = 0;
183 	struct nfsstate *stp, *tstp;
184 	struct sockaddr_in *sad, *rad;
185 	int zapit = 0, gotit, hasstate = 0, igotlock;
186 	static u_int64_t confirm_index = 0;
187 
188 	/*
189 	 * Check for state resource limit exceeded.
190 	 */
191 	if (nfsrv_openpluslock > nfsrv_v4statelimit) {
192 		error = NFSERR_RESOURCE;
193 		goto out;
194 	}
195 
196 	if (nfsrv_issuedelegs == 0 ||
197 	    ((nd->nd_flag & ND_GSS) != 0 && nfsrv_nogsscallback != 0))
198 		/*
199 		 * Don't do callbacks when delegations are disabled or
200 		 * for AUTH_GSS unless enabled via nfsrv_nogsscallback.
201 		 * If establishing a callback connection is attempted
202 		 * when a firewall is blocking the callback path, the
203 		 * server may wait too long for the connect attempt to
204 		 * succeed during the Open. Some clients, such as Linux,
205 		 * may timeout and give up on the Open before the server
206 		 * replies. Also, since AUTH_GSS callbacks are not
207 		 * yet interoperability tested, they might cause the
208 		 * server to crap out, if they get past the Init call to
209 		 * the client.
210 		 */
211 		new_clp->lc_program = 0;
212 
213 	/* Lock out other nfsd threads */
214 	NFSLOCKV4ROOTMUTEX();
215 	nfsv4_relref(&nfsv4rootfs_lock);
216 	do {
217 		igotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL,
218 		    NFSV4ROOTLOCKMUTEXPTR, NULL);
219 	} while (!igotlock);
220 	NFSUNLOCKV4ROOTMUTEX();
221 
222 	/*
223 	 * Search for a match in the client list.
224 	 */
225 	gotit = i = 0;
226 	while (i < nfsrv_clienthashsize && !gotit) {
227 	    LIST_FOREACH(clp, &nfsclienthash[i], lc_hash) {
228 		if (new_clp->lc_idlen == clp->lc_idlen &&
229 		    !NFSBCMP(new_clp->lc_id, clp->lc_id, clp->lc_idlen)) {
230 			gotit = 1;
231 			break;
232 		}
233 	    }
234 	    if (gotit == 0)
235 		i++;
236 	}
237 	if (!gotit ||
238 	    (clp->lc_flags & (LCL_NEEDSCONFIRM | LCL_ADMINREVOKED))) {
239 		if ((nd->nd_flag & ND_NFSV41) != 0 && confirmp->lval[1] != 0) {
240 			/*
241 			 * For NFSv4.1, if confirmp->lval[1] is non-zero, the
242 			 * client is trying to update a confirmed clientid.
243 			 */
244 			NFSLOCKV4ROOTMUTEX();
245 			nfsv4_unlock(&nfsv4rootfs_lock, 1);
246 			NFSUNLOCKV4ROOTMUTEX();
247 			confirmp->lval[1] = 0;
248 			error = NFSERR_NOENT;
249 			goto out;
250 		}
251 		/*
252 		 * Get rid of the old one.
253 		 */
254 		if (i != nfsrv_clienthashsize) {
255 			LIST_REMOVE(clp, lc_hash);
256 			nfsrv_cleanclient(clp, p);
257 			nfsrv_freedeleglist(&clp->lc_deleg);
258 			nfsrv_freedeleglist(&clp->lc_olddeleg);
259 			zapit = 1;
260 		}
261 		/*
262 		 * Add it after assigning a client id to it.
263 		 */
264 		new_clp->lc_flags |= LCL_NEEDSCONFIRM;
265 		if ((nd->nd_flag & ND_NFSV41) != 0)
266 			new_clp->lc_confirm.lval[0] = confirmp->lval[0] =
267 			    ++confirm_index;
268 		else
269 			confirmp->qval = new_clp->lc_confirm.qval =
270 			    ++confirm_index;
271 		clientidp->lval[0] = new_clp->lc_clientid.lval[0] =
272 		    (u_int32_t)nfsrvboottime;
273 		clientidp->lval[1] = new_clp->lc_clientid.lval[1] =
274 		    nfsrv_nextclientindex();
275 		new_clp->lc_stateindex = 0;
276 		new_clp->lc_statemaxindex = 0;
277 		new_clp->lc_cbref = 0;
278 		new_clp->lc_expiry = nfsrv_leaseexpiry();
279 		LIST_INIT(&new_clp->lc_open);
280 		LIST_INIT(&new_clp->lc_deleg);
281 		LIST_INIT(&new_clp->lc_olddeleg);
282 		LIST_INIT(&new_clp->lc_session);
283 		for (i = 0; i < nfsrv_statehashsize; i++)
284 			LIST_INIT(&new_clp->lc_stateid[i]);
285 		LIST_INSERT_HEAD(NFSCLIENTHASH(new_clp->lc_clientid), new_clp,
286 		    lc_hash);
287 		nfsstatsv1.srvclients++;
288 		nfsrv_openpluslock++;
289 		nfsrv_clients++;
290 		NFSLOCKV4ROOTMUTEX();
291 		nfsv4_unlock(&nfsv4rootfs_lock, 1);
292 		NFSUNLOCKV4ROOTMUTEX();
293 		if (zapit)
294 			nfsrv_zapclient(clp, p);
295 		*new_clpp = NULL;
296 		goto out;
297 	}
298 
299 	/*
300 	 * Now, handle the cases where the id is already issued.
301 	 */
302 	if (nfsrv_notsamecredname(nd, clp)) {
303 	    /*
304 	     * Check to see if there is expired state that should go away.
305 	     */
306 	    if (clp->lc_expiry < NFSD_MONOSEC &&
307 	        (!LIST_EMPTY(&clp->lc_open) || !LIST_EMPTY(&clp->lc_deleg))) {
308 		nfsrv_cleanclient(clp, p);
309 		nfsrv_freedeleglist(&clp->lc_deleg);
310 	    }
311 
312 	    /*
313 	     * If there is outstanding state, then reply NFSERR_CLIDINUSE per
314 	     * RFC3530 Sec. 8.1.2 last para.
315 	     */
316 	    if (!LIST_EMPTY(&clp->lc_deleg)) {
317 		hasstate = 1;
318 	    } else if (LIST_EMPTY(&clp->lc_open)) {
319 		hasstate = 0;
320 	    } else {
321 		hasstate = 0;
322 		/* Look for an Open on the OpenOwner */
323 		LIST_FOREACH(stp, &clp->lc_open, ls_list) {
324 		    if (!LIST_EMPTY(&stp->ls_open)) {
325 			hasstate = 1;
326 			break;
327 		    }
328 		}
329 	    }
330 	    if (hasstate) {
331 		/*
332 		 * If the uid doesn't match, return NFSERR_CLIDINUSE after
333 		 * filling out the correct ipaddr and portnum.
334 		 */
335 		sad = NFSSOCKADDR(new_clp->lc_req.nr_nam, struct sockaddr_in *);
336 		rad = NFSSOCKADDR(clp->lc_req.nr_nam, struct sockaddr_in *);
337 		sad->sin_addr.s_addr = rad->sin_addr.s_addr;
338 		sad->sin_port = rad->sin_port;
339 		NFSLOCKV4ROOTMUTEX();
340 		nfsv4_unlock(&nfsv4rootfs_lock, 1);
341 		NFSUNLOCKV4ROOTMUTEX();
342 		error = NFSERR_CLIDINUSE;
343 		goto out;
344 	    }
345 	}
346 
347 	if (NFSBCMP(new_clp->lc_verf, clp->lc_verf, NFSX_VERF)) {
348 		/*
349 		 * If the verifier has changed, the client has rebooted
350 		 * and a new client id is issued. The old state info
351 		 * can be thrown away once the SETCLIENTID_CONFIRM occurs.
352 		 */
353 		LIST_REMOVE(clp, lc_hash);
354 		new_clp->lc_flags |= LCL_NEEDSCONFIRM;
355 		if ((nd->nd_flag & ND_NFSV41) != 0)
356 			new_clp->lc_confirm.lval[0] = confirmp->lval[0] =
357 			    ++confirm_index;
358 		else
359 			confirmp->qval = new_clp->lc_confirm.qval =
360 			    ++confirm_index;
361 		clientidp->lval[0] = new_clp->lc_clientid.lval[0] =
362 		    nfsrvboottime;
363 		clientidp->lval[1] = new_clp->lc_clientid.lval[1] =
364 		    nfsrv_nextclientindex();
365 		new_clp->lc_stateindex = 0;
366 		new_clp->lc_statemaxindex = 0;
367 		new_clp->lc_cbref = 0;
368 		new_clp->lc_expiry = nfsrv_leaseexpiry();
369 
370 		/*
371 		 * Save the state until confirmed.
372 		 */
373 		LIST_NEWHEAD(&new_clp->lc_open, &clp->lc_open, ls_list);
374 		LIST_FOREACH(tstp, &new_clp->lc_open, ls_list)
375 			tstp->ls_clp = new_clp;
376 		LIST_NEWHEAD(&new_clp->lc_deleg, &clp->lc_deleg, ls_list);
377 		LIST_FOREACH(tstp, &new_clp->lc_deleg, ls_list)
378 			tstp->ls_clp = new_clp;
379 		LIST_NEWHEAD(&new_clp->lc_olddeleg, &clp->lc_olddeleg,
380 		    ls_list);
381 		LIST_FOREACH(tstp, &new_clp->lc_olddeleg, ls_list)
382 			tstp->ls_clp = new_clp;
383 		for (i = 0; i < nfsrv_statehashsize; i++) {
384 			LIST_NEWHEAD(&new_clp->lc_stateid[i],
385 			    &clp->lc_stateid[i], ls_hash);
386 			LIST_FOREACH(tstp, &new_clp->lc_stateid[i], ls_hash)
387 				tstp->ls_clp = new_clp;
388 		}
389 		LIST_INSERT_HEAD(NFSCLIENTHASH(new_clp->lc_clientid), new_clp,
390 		    lc_hash);
391 		nfsstatsv1.srvclients++;
392 		nfsrv_openpluslock++;
393 		nfsrv_clients++;
394 		NFSLOCKV4ROOTMUTEX();
395 		nfsv4_unlock(&nfsv4rootfs_lock, 1);
396 		NFSUNLOCKV4ROOTMUTEX();
397 
398 		/*
399 		 * Must wait until any outstanding callback on the old clp
400 		 * completes.
401 		 */
402 		NFSLOCKSTATE();
403 		while (clp->lc_cbref) {
404 			clp->lc_flags |= LCL_WAKEUPWANTED;
405 			(void)mtx_sleep(clp, NFSSTATEMUTEXPTR, PZERO - 1,
406 			    "nfsd clp", 10 * hz);
407 		}
408 		NFSUNLOCKSTATE();
409 		nfsrv_zapclient(clp, p);
410 		*new_clpp = NULL;
411 		goto out;
412 	}
413 
414 	/* For NFSv4.1, mark that we found a confirmed clientid. */
415 	if ((nd->nd_flag & ND_NFSV41) != 0) {
416 		clientidp->lval[0] = clp->lc_clientid.lval[0];
417 		clientidp->lval[1] = clp->lc_clientid.lval[1];
418 		confirmp->lval[0] = 0;	/* Ignored by client */
419 		confirmp->lval[1] = 1;
420 	} else {
421 		/*
422 		 * id and verifier match, so update the net address info
423 		 * and get rid of any existing callback authentication
424 		 * handle, so a new one will be acquired.
425 		 */
426 		LIST_REMOVE(clp, lc_hash);
427 		new_clp->lc_flags |= (LCL_NEEDSCONFIRM | LCL_DONTCLEAN);
428 		new_clp->lc_expiry = nfsrv_leaseexpiry();
429 		confirmp->qval = new_clp->lc_confirm.qval = ++confirm_index;
430 		clientidp->lval[0] = new_clp->lc_clientid.lval[0] =
431 		    clp->lc_clientid.lval[0];
432 		clientidp->lval[1] = new_clp->lc_clientid.lval[1] =
433 		    clp->lc_clientid.lval[1];
434 		new_clp->lc_delegtime = clp->lc_delegtime;
435 		new_clp->lc_stateindex = clp->lc_stateindex;
436 		new_clp->lc_statemaxindex = clp->lc_statemaxindex;
437 		new_clp->lc_cbref = 0;
438 		LIST_NEWHEAD(&new_clp->lc_open, &clp->lc_open, ls_list);
439 		LIST_FOREACH(tstp, &new_clp->lc_open, ls_list)
440 			tstp->ls_clp = new_clp;
441 		LIST_NEWHEAD(&new_clp->lc_deleg, &clp->lc_deleg, ls_list);
442 		LIST_FOREACH(tstp, &new_clp->lc_deleg, ls_list)
443 			tstp->ls_clp = new_clp;
444 		LIST_NEWHEAD(&new_clp->lc_olddeleg, &clp->lc_olddeleg, ls_list);
445 		LIST_FOREACH(tstp, &new_clp->lc_olddeleg, ls_list)
446 			tstp->ls_clp = new_clp;
447 		for (i = 0; i < nfsrv_statehashsize; i++) {
448 			LIST_NEWHEAD(&new_clp->lc_stateid[i],
449 			    &clp->lc_stateid[i], ls_hash);
450 			LIST_FOREACH(tstp, &new_clp->lc_stateid[i], ls_hash)
451 				tstp->ls_clp = new_clp;
452 		}
453 		LIST_INSERT_HEAD(NFSCLIENTHASH(new_clp->lc_clientid), new_clp,
454 		    lc_hash);
455 		nfsstatsv1.srvclients++;
456 		nfsrv_openpluslock++;
457 		nfsrv_clients++;
458 	}
459 	NFSLOCKV4ROOTMUTEX();
460 	nfsv4_unlock(&nfsv4rootfs_lock, 1);
461 	NFSUNLOCKV4ROOTMUTEX();
462 
463 	if ((nd->nd_flag & ND_NFSV41) == 0) {
464 		/*
465 		 * Must wait until any outstanding callback on the old clp
466 		 * completes.
467 		 */
468 		NFSLOCKSTATE();
469 		while (clp->lc_cbref) {
470 			clp->lc_flags |= LCL_WAKEUPWANTED;
471 			(void)mtx_sleep(clp, NFSSTATEMUTEXPTR, PZERO - 1,
472 			    "nfsdclp", 10 * hz);
473 		}
474 		NFSUNLOCKSTATE();
475 		nfsrv_zapclient(clp, p);
476 		*new_clpp = NULL;
477 	}
478 
479 out:
480 	NFSEXITCODE2(error, nd);
481 	return (error);
482 }
483 
484 /*
485  * Check to see if the client id exists and optionally confirm it.
486  */
487 APPLESTATIC int
488 nfsrv_getclient(nfsquad_t clientid, int opflags, struct nfsclient **clpp,
489     struct nfsdsession *nsep, nfsquad_t confirm, uint32_t cbprogram,
490     struct nfsrv_descript *nd, NFSPROC_T *p)
491 {
492 	struct nfsclient *clp;
493 	struct nfsstate *stp;
494 	int i;
495 	struct nfsclienthashhead *hp;
496 	int error = 0, igotlock, doneok;
497 	struct nfssessionhash *shp;
498 	struct nfsdsession *sep;
499 	uint64_t sessid[2];
500 	static uint64_t next_sess = 0;
501 
502 	if (clpp)
503 		*clpp = NULL;
504 	if ((nd == NULL || (nd->nd_flag & ND_NFSV41) == 0 ||
505 	    opflags != CLOPS_RENEW) && nfsrvboottime != clientid.lval[0]) {
506 		error = NFSERR_STALECLIENTID;
507 		goto out;
508 	}
509 
510 	/*
511 	 * If called with opflags == CLOPS_RENEW, the State Lock is
512 	 * already held. Otherwise, we need to get either that or,
513 	 * for the case of Confirm, lock out the nfsd threads.
514 	 */
515 	if (opflags & CLOPS_CONFIRM) {
516 		NFSLOCKV4ROOTMUTEX();
517 		nfsv4_relref(&nfsv4rootfs_lock);
518 		do {
519 			igotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL,
520 			    NFSV4ROOTLOCKMUTEXPTR, NULL);
521 		} while (!igotlock);
522 		/*
523 		 * Create a new sessionid here, since we need to do it where
524 		 * there is a mutex held to serialize update of next_sess.
525 		 */
526 		if ((nd->nd_flag & ND_NFSV41) != 0) {
527 			sessid[0] = ++next_sess;
528 			sessid[1] = clientid.qval;
529 		}
530 		NFSUNLOCKV4ROOTMUTEX();
531 	} else if (opflags != CLOPS_RENEW) {
532 		NFSLOCKSTATE();
533 	}
534 
535 	/* For NFSv4.1, the clp is acquired from the associated session. */
536 	if (nd != NULL && (nd->nd_flag & ND_NFSV41) != 0 &&
537 	    opflags == CLOPS_RENEW) {
538 		clp = NULL;
539 		if ((nd->nd_flag & ND_HASSEQUENCE) != 0) {
540 			shp = NFSSESSIONHASH(nd->nd_sessionid);
541 			NFSLOCKSESSION(shp);
542 			sep = nfsrv_findsession(nd->nd_sessionid);
543 			if (sep != NULL)
544 				clp = sep->sess_clp;
545 			NFSUNLOCKSESSION(shp);
546 		}
547 	} else {
548 		hp = NFSCLIENTHASH(clientid);
549 		LIST_FOREACH(clp, hp, lc_hash) {
550 			if (clp->lc_clientid.lval[1] == clientid.lval[1])
551 				break;
552 		}
553 	}
554 	if (clp == NULL) {
555 		if (opflags & CLOPS_CONFIRM)
556 			error = NFSERR_STALECLIENTID;
557 		else
558 			error = NFSERR_EXPIRED;
559 	} else if (clp->lc_flags & LCL_ADMINREVOKED) {
560 		/*
561 		 * If marked admin revoked, just return the error.
562 		 */
563 		error = NFSERR_ADMINREVOKED;
564 	}
565 	if (error) {
566 		if (opflags & CLOPS_CONFIRM) {
567 			NFSLOCKV4ROOTMUTEX();
568 			nfsv4_unlock(&nfsv4rootfs_lock, 1);
569 			NFSUNLOCKV4ROOTMUTEX();
570 		} else if (opflags != CLOPS_RENEW) {
571 			NFSUNLOCKSTATE();
572 		}
573 		goto out;
574 	}
575 
576 	/*
577 	 * Perform any operations specified by the opflags.
578 	 */
579 	if (opflags & CLOPS_CONFIRM) {
580 		if (((nd->nd_flag & ND_NFSV41) != 0 &&
581 		     clp->lc_confirm.lval[0] != confirm.lval[0]) ||
582 		    ((nd->nd_flag & ND_NFSV41) == 0 &&
583 		     clp->lc_confirm.qval != confirm.qval))
584 			error = NFSERR_STALECLIENTID;
585 		else if (nfsrv_notsamecredname(nd, clp))
586 			error = NFSERR_CLIDINUSE;
587 
588 		if (!error) {
589 		    if ((clp->lc_flags & (LCL_NEEDSCONFIRM | LCL_DONTCLEAN)) ==
590 			LCL_NEEDSCONFIRM) {
591 			/*
592 			 * Hang onto the delegations (as old delegations)
593 			 * for an Open with CLAIM_DELEGATE_PREV unless in
594 			 * grace, but get rid of the rest of the state.
595 			 */
596 			nfsrv_cleanclient(clp, p);
597 			nfsrv_freedeleglist(&clp->lc_olddeleg);
598 			if (nfsrv_checkgrace(nd, clp, 0)) {
599 			    /* In grace, so just delete delegations */
600 			    nfsrv_freedeleglist(&clp->lc_deleg);
601 			} else {
602 			    LIST_FOREACH(stp, &clp->lc_deleg, ls_list)
603 				stp->ls_flags |= NFSLCK_OLDDELEG;
604 			    clp->lc_delegtime = NFSD_MONOSEC +
605 				nfsrv_lease + NFSRV_LEASEDELTA;
606 			    LIST_NEWHEAD(&clp->lc_olddeleg, &clp->lc_deleg,
607 				ls_list);
608 			}
609 			if ((nd->nd_flag & ND_NFSV41) != 0)
610 			    clp->lc_program = cbprogram;
611 		    }
612 		    clp->lc_flags &= ~(LCL_NEEDSCONFIRM | LCL_DONTCLEAN);
613 		    if (clp->lc_program)
614 			clp->lc_flags |= LCL_NEEDSCBNULL;
615 		    /* For NFSv4.1, link the session onto the client. */
616 		    if (nsep != NULL) {
617 			/* Hold a reference on the xprt for a backchannel. */
618 			if ((nsep->sess_crflags & NFSV4CRSESS_CONNBACKCHAN)
619 			    != 0 && clp->lc_req.nr_client == NULL) {
620 			    clp->lc_req.nr_client = (struct __rpc_client *)
621 				clnt_bck_create(nd->nd_xprt->xp_socket,
622 				cbprogram, NFSV4_CBVERS);
623 			    if (clp->lc_req.nr_client != NULL) {
624 				SVC_ACQUIRE(nd->nd_xprt);
625 				nd->nd_xprt->xp_p2 =
626 				    clp->lc_req.nr_client->cl_private;
627 				/* Disable idle timeout. */
628 				nd->nd_xprt->xp_idletimeout = 0;
629 				nsep->sess_cbsess.nfsess_xprt = nd->nd_xprt;
630 			    } else
631 				nsep->sess_crflags &= ~NFSV4CRSESS_CONNBACKCHAN;
632 			}
633 			NFSBCOPY(sessid, nsep->sess_sessionid,
634 			    NFSX_V4SESSIONID);
635 			NFSBCOPY(sessid, nsep->sess_cbsess.nfsess_sessionid,
636 			    NFSX_V4SESSIONID);
637 			shp = NFSSESSIONHASH(nsep->sess_sessionid);
638 			NFSLOCKSTATE();
639 			NFSLOCKSESSION(shp);
640 			LIST_INSERT_HEAD(&shp->list, nsep, sess_hash);
641 			LIST_INSERT_HEAD(&clp->lc_session, nsep, sess_list);
642 			nsep->sess_clp = clp;
643 			NFSUNLOCKSESSION(shp);
644 			NFSUNLOCKSTATE();
645 		    }
646 		}
647 	} else if (clp->lc_flags & LCL_NEEDSCONFIRM) {
648 		error = NFSERR_EXPIRED;
649 	}
650 
651 	/*
652 	 * If called by the Renew Op, we must check the principal.
653 	 */
654 	if (!error && (opflags & CLOPS_RENEWOP)) {
655 	    if (nfsrv_notsamecredname(nd, clp)) {
656 		doneok = 0;
657 		for (i = 0; i < nfsrv_statehashsize && doneok == 0; i++) {
658 		    LIST_FOREACH(stp, &clp->lc_stateid[i], ls_hash) {
659 			if ((stp->ls_flags & NFSLCK_OPEN) &&
660 			    stp->ls_uid == nd->nd_cred->cr_uid) {
661 				doneok = 1;
662 				break;
663 			}
664 		    }
665 		}
666 		if (!doneok)
667 			error = NFSERR_ACCES;
668 	    }
669 	    if (!error && (clp->lc_flags & LCL_CBDOWN))
670 		error = NFSERR_CBPATHDOWN;
671 	}
672 	if ((!error || error == NFSERR_CBPATHDOWN) &&
673 	     (opflags & CLOPS_RENEW)) {
674 		clp->lc_expiry = nfsrv_leaseexpiry();
675 	}
676 	if (opflags & CLOPS_CONFIRM) {
677 		NFSLOCKV4ROOTMUTEX();
678 		nfsv4_unlock(&nfsv4rootfs_lock, 1);
679 		NFSUNLOCKV4ROOTMUTEX();
680 	} else if (opflags != CLOPS_RENEW) {
681 		NFSUNLOCKSTATE();
682 	}
683 	if (clpp)
684 		*clpp = clp;
685 
686 out:
687 	NFSEXITCODE2(error, nd);
688 	return (error);
689 }
690 
691 /*
692  * Perform the NFSv4.1 destroy clientid.
693  */
694 int
695 nfsrv_destroyclient(nfsquad_t clientid, NFSPROC_T *p)
696 {
697 	struct nfsclient *clp;
698 	struct nfsclienthashhead *hp;
699 	int error = 0, i, igotlock;
700 
701 	if (nfsrvboottime != clientid.lval[0]) {
702 		error = NFSERR_STALECLIENTID;
703 		goto out;
704 	}
705 
706 	/* Lock out other nfsd threads */
707 	NFSLOCKV4ROOTMUTEX();
708 	nfsv4_relref(&nfsv4rootfs_lock);
709 	do {
710 		igotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL,
711 		    NFSV4ROOTLOCKMUTEXPTR, NULL);
712 	} while (igotlock == 0);
713 	NFSUNLOCKV4ROOTMUTEX();
714 
715 	hp = NFSCLIENTHASH(clientid);
716 	LIST_FOREACH(clp, hp, lc_hash) {
717 		if (clp->lc_clientid.lval[1] == clientid.lval[1])
718 			break;
719 	}
720 	if (clp == NULL) {
721 		NFSLOCKV4ROOTMUTEX();
722 		nfsv4_unlock(&nfsv4rootfs_lock, 1);
723 		NFSUNLOCKV4ROOTMUTEX();
724 		/* Just return ok, since it is gone. */
725 		goto out;
726 	}
727 
728 	/* Scan for state on the clientid. */
729 	for (i = 0; i < nfsrv_statehashsize; i++)
730 		if (!LIST_EMPTY(&clp->lc_stateid[i])) {
731 			NFSLOCKV4ROOTMUTEX();
732 			nfsv4_unlock(&nfsv4rootfs_lock, 1);
733 			NFSUNLOCKV4ROOTMUTEX();
734 			error = NFSERR_CLIENTIDBUSY;
735 			goto out;
736 		}
737 	if (!LIST_EMPTY(&clp->lc_session) || !LIST_EMPTY(&clp->lc_deleg)) {
738 		NFSLOCKV4ROOTMUTEX();
739 		nfsv4_unlock(&nfsv4rootfs_lock, 1);
740 		NFSUNLOCKV4ROOTMUTEX();
741 		error = NFSERR_CLIENTIDBUSY;
742 		goto out;
743 	}
744 
745 	/* Destroy the clientid and return ok. */
746 	nfsrv_cleanclient(clp, p);
747 	nfsrv_freedeleglist(&clp->lc_deleg);
748 	nfsrv_freedeleglist(&clp->lc_olddeleg);
749 	LIST_REMOVE(clp, lc_hash);
750 	NFSLOCKV4ROOTMUTEX();
751 	nfsv4_unlock(&nfsv4rootfs_lock, 1);
752 	NFSUNLOCKV4ROOTMUTEX();
753 	nfsrv_zapclient(clp, p);
754 out:
755 	NFSEXITCODE2(error, nd);
756 	return (error);
757 }
758 
759 /*
760  * Called from the new nfssvc syscall to admin revoke a clientid.
761  * Returns 0 for success, error otherwise.
762  */
763 APPLESTATIC int
764 nfsrv_adminrevoke(struct nfsd_clid *revokep, NFSPROC_T *p)
765 {
766 	struct nfsclient *clp = NULL;
767 	int i, error = 0;
768 	int gotit, igotlock;
769 
770 	/*
771 	 * First, lock out the nfsd so that state won't change while the
772 	 * revocation record is being written to the stable storage restart
773 	 * file.
774 	 */
775 	NFSLOCKV4ROOTMUTEX();
776 	do {
777 		igotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL,
778 		    NFSV4ROOTLOCKMUTEXPTR, NULL);
779 	} while (!igotlock);
780 	NFSUNLOCKV4ROOTMUTEX();
781 
782 	/*
783 	 * Search for a match in the client list.
784 	 */
785 	gotit = i = 0;
786 	while (i < nfsrv_clienthashsize && !gotit) {
787 	    LIST_FOREACH(clp, &nfsclienthash[i], lc_hash) {
788 		if (revokep->nclid_idlen == clp->lc_idlen &&
789 		    !NFSBCMP(revokep->nclid_id, clp->lc_id, clp->lc_idlen)) {
790 			gotit = 1;
791 			break;
792 		}
793 	    }
794 	    i++;
795 	}
796 	if (!gotit) {
797 		NFSLOCKV4ROOTMUTEX();
798 		nfsv4_unlock(&nfsv4rootfs_lock, 0);
799 		NFSUNLOCKV4ROOTMUTEX();
800 		error = EPERM;
801 		goto out;
802 	}
803 
804 	/*
805 	 * Now, write out the revocation record
806 	 */
807 	nfsrv_writestable(clp->lc_id, clp->lc_idlen, NFSNST_REVOKE, p);
808 	nfsrv_backupstable();
809 
810 	/*
811 	 * and clear out the state, marking the clientid revoked.
812 	 */
813 	clp->lc_flags &= ~LCL_CALLBACKSON;
814 	clp->lc_flags |= LCL_ADMINREVOKED;
815 	nfsrv_cleanclient(clp, p);
816 	nfsrv_freedeleglist(&clp->lc_deleg);
817 	nfsrv_freedeleglist(&clp->lc_olddeleg);
818 	NFSLOCKV4ROOTMUTEX();
819 	nfsv4_unlock(&nfsv4rootfs_lock, 0);
820 	NFSUNLOCKV4ROOTMUTEX();
821 
822 out:
823 	NFSEXITCODE(error);
824 	return (error);
825 }
826 
827 /*
828  * Dump out stats for all clients. Called from nfssvc(2), that is used
829  * nfsstatsv1.
830  */
831 APPLESTATIC void
832 nfsrv_dumpclients(struct nfsd_dumpclients *dumpp, int maxcnt)
833 {
834 	struct nfsclient *clp;
835 	int i = 0, cnt = 0;
836 
837 	/*
838 	 * First, get a reference on the nfsv4rootfs_lock so that an
839 	 * exclusive lock cannot be acquired while dumping the clients.
840 	 */
841 	NFSLOCKV4ROOTMUTEX();
842 	nfsv4_getref(&nfsv4rootfs_lock, NULL, NFSV4ROOTLOCKMUTEXPTR, NULL);
843 	NFSUNLOCKV4ROOTMUTEX();
844 	NFSLOCKSTATE();
845 	/*
846 	 * Rattle through the client lists until done.
847 	 */
848 	while (i < nfsrv_clienthashsize && cnt < maxcnt) {
849 	    clp = LIST_FIRST(&nfsclienthash[i]);
850 	    while (clp != LIST_END(&nfsclienthash[i]) && cnt < maxcnt) {
851 		nfsrv_dumpaclient(clp, &dumpp[cnt]);
852 		cnt++;
853 		clp = LIST_NEXT(clp, lc_hash);
854 	    }
855 	    i++;
856 	}
857 	if (cnt < maxcnt)
858 	    dumpp[cnt].ndcl_clid.nclid_idlen = 0;
859 	NFSUNLOCKSTATE();
860 	NFSLOCKV4ROOTMUTEX();
861 	nfsv4_relref(&nfsv4rootfs_lock);
862 	NFSUNLOCKV4ROOTMUTEX();
863 }
864 
865 /*
866  * Dump stats for a client. Must be called with the NFSSTATELOCK and spl'd.
867  */
868 static void
869 nfsrv_dumpaclient(struct nfsclient *clp, struct nfsd_dumpclients *dumpp)
870 {
871 	struct nfsstate *stp, *openstp, *lckownstp;
872 	struct nfslock *lop;
873 	struct sockaddr *sad;
874 	struct sockaddr_in *rad;
875 	struct sockaddr_in6 *rad6;
876 
877 	dumpp->ndcl_nopenowners = dumpp->ndcl_nlockowners = 0;
878 	dumpp->ndcl_nopens = dumpp->ndcl_nlocks = 0;
879 	dumpp->ndcl_ndelegs = dumpp->ndcl_nolddelegs = 0;
880 	dumpp->ndcl_flags = clp->lc_flags;
881 	dumpp->ndcl_clid.nclid_idlen = clp->lc_idlen;
882 	NFSBCOPY(clp->lc_id, dumpp->ndcl_clid.nclid_id, clp->lc_idlen);
883 	sad = NFSSOCKADDR(clp->lc_req.nr_nam, struct sockaddr *);
884 	dumpp->ndcl_addrfam = sad->sa_family;
885 	if (sad->sa_family == AF_INET) {
886 		rad = (struct sockaddr_in *)sad;
887 		dumpp->ndcl_cbaddr.sin_addr = rad->sin_addr;
888 	} else {
889 		rad6 = (struct sockaddr_in6 *)sad;
890 		dumpp->ndcl_cbaddr.sin6_addr = rad6->sin6_addr;
891 	}
892 
893 	/*
894 	 * Now, scan the state lists and total up the opens and locks.
895 	 */
896 	LIST_FOREACH(stp, &clp->lc_open, ls_list) {
897 	    dumpp->ndcl_nopenowners++;
898 	    LIST_FOREACH(openstp, &stp->ls_open, ls_list) {
899 		dumpp->ndcl_nopens++;
900 		LIST_FOREACH(lckownstp, &openstp->ls_open, ls_list) {
901 		    dumpp->ndcl_nlockowners++;
902 		    LIST_FOREACH(lop, &lckownstp->ls_lock, lo_lckowner) {
903 			dumpp->ndcl_nlocks++;
904 		    }
905 		}
906 	    }
907 	}
908 
909 	/*
910 	 * and the delegation lists.
911 	 */
912 	LIST_FOREACH(stp, &clp->lc_deleg, ls_list) {
913 	    dumpp->ndcl_ndelegs++;
914 	}
915 	LIST_FOREACH(stp, &clp->lc_olddeleg, ls_list) {
916 	    dumpp->ndcl_nolddelegs++;
917 	}
918 }
919 
920 /*
921  * Dump out lock stats for a file.
922  */
923 APPLESTATIC void
924 nfsrv_dumplocks(vnode_t vp, struct nfsd_dumplocks *ldumpp, int maxcnt,
925     NFSPROC_T *p)
926 {
927 	struct nfsstate *stp;
928 	struct nfslock *lop;
929 	int cnt = 0;
930 	struct nfslockfile *lfp;
931 	struct sockaddr *sad;
932 	struct sockaddr_in *rad;
933 	struct sockaddr_in6 *rad6;
934 	int ret;
935 	fhandle_t nfh;
936 
937 	ret = nfsrv_getlockfh(vp, 0, NULL, &nfh, p);
938 	/*
939 	 * First, get a reference on the nfsv4rootfs_lock so that an
940 	 * exclusive lock on it cannot be acquired while dumping the locks.
941 	 */
942 	NFSLOCKV4ROOTMUTEX();
943 	nfsv4_getref(&nfsv4rootfs_lock, NULL, NFSV4ROOTLOCKMUTEXPTR, NULL);
944 	NFSUNLOCKV4ROOTMUTEX();
945 	NFSLOCKSTATE();
946 	if (!ret)
947 		ret = nfsrv_getlockfile(0, NULL, &lfp, &nfh, 0);
948 	if (ret) {
949 		ldumpp[0].ndlck_clid.nclid_idlen = 0;
950 		NFSUNLOCKSTATE();
951 		NFSLOCKV4ROOTMUTEX();
952 		nfsv4_relref(&nfsv4rootfs_lock);
953 		NFSUNLOCKV4ROOTMUTEX();
954 		return;
955 	}
956 
957 	/*
958 	 * For each open share on file, dump it out.
959 	 */
960 	stp = LIST_FIRST(&lfp->lf_open);
961 	while (stp != LIST_END(&lfp->lf_open) && cnt < maxcnt) {
962 		ldumpp[cnt].ndlck_flags = stp->ls_flags;
963 		ldumpp[cnt].ndlck_stateid.seqid = stp->ls_stateid.seqid;
964 		ldumpp[cnt].ndlck_stateid.other[0] = stp->ls_stateid.other[0];
965 		ldumpp[cnt].ndlck_stateid.other[1] = stp->ls_stateid.other[1];
966 		ldumpp[cnt].ndlck_stateid.other[2] = stp->ls_stateid.other[2];
967 		ldumpp[cnt].ndlck_owner.nclid_idlen =
968 		    stp->ls_openowner->ls_ownerlen;
969 		NFSBCOPY(stp->ls_openowner->ls_owner,
970 		    ldumpp[cnt].ndlck_owner.nclid_id,
971 		    stp->ls_openowner->ls_ownerlen);
972 		ldumpp[cnt].ndlck_clid.nclid_idlen = stp->ls_clp->lc_idlen;
973 		NFSBCOPY(stp->ls_clp->lc_id, ldumpp[cnt].ndlck_clid.nclid_id,
974 		    stp->ls_clp->lc_idlen);
975 		sad=NFSSOCKADDR(stp->ls_clp->lc_req.nr_nam, struct sockaddr *);
976 		ldumpp[cnt].ndlck_addrfam = sad->sa_family;
977 		if (sad->sa_family == AF_INET) {
978 			rad = (struct sockaddr_in *)sad;
979 			ldumpp[cnt].ndlck_cbaddr.sin_addr = rad->sin_addr;
980 		} else {
981 			rad6 = (struct sockaddr_in6 *)sad;
982 			ldumpp[cnt].ndlck_cbaddr.sin6_addr = rad6->sin6_addr;
983 		}
984 		stp = LIST_NEXT(stp, ls_file);
985 		cnt++;
986 	}
987 
988 	/*
989 	 * and all locks.
990 	 */
991 	lop = LIST_FIRST(&lfp->lf_lock);
992 	while (lop != LIST_END(&lfp->lf_lock) && cnt < maxcnt) {
993 		stp = lop->lo_stp;
994 		ldumpp[cnt].ndlck_flags = lop->lo_flags;
995 		ldumpp[cnt].ndlck_first = lop->lo_first;
996 		ldumpp[cnt].ndlck_end = lop->lo_end;
997 		ldumpp[cnt].ndlck_stateid.seqid = stp->ls_stateid.seqid;
998 		ldumpp[cnt].ndlck_stateid.other[0] = stp->ls_stateid.other[0];
999 		ldumpp[cnt].ndlck_stateid.other[1] = stp->ls_stateid.other[1];
1000 		ldumpp[cnt].ndlck_stateid.other[2] = stp->ls_stateid.other[2];
1001 		ldumpp[cnt].ndlck_owner.nclid_idlen = stp->ls_ownerlen;
1002 		NFSBCOPY(stp->ls_owner, ldumpp[cnt].ndlck_owner.nclid_id,
1003 		    stp->ls_ownerlen);
1004 		ldumpp[cnt].ndlck_clid.nclid_idlen = stp->ls_clp->lc_idlen;
1005 		NFSBCOPY(stp->ls_clp->lc_id, ldumpp[cnt].ndlck_clid.nclid_id,
1006 		    stp->ls_clp->lc_idlen);
1007 		sad=NFSSOCKADDR(stp->ls_clp->lc_req.nr_nam, struct sockaddr *);
1008 		ldumpp[cnt].ndlck_addrfam = sad->sa_family;
1009 		if (sad->sa_family == AF_INET) {
1010 			rad = (struct sockaddr_in *)sad;
1011 			ldumpp[cnt].ndlck_cbaddr.sin_addr = rad->sin_addr;
1012 		} else {
1013 			rad6 = (struct sockaddr_in6 *)sad;
1014 			ldumpp[cnt].ndlck_cbaddr.sin6_addr = rad6->sin6_addr;
1015 		}
1016 		lop = LIST_NEXT(lop, lo_lckfile);
1017 		cnt++;
1018 	}
1019 
1020 	/*
1021 	 * and the delegations.
1022 	 */
1023 	stp = LIST_FIRST(&lfp->lf_deleg);
1024 	while (stp != LIST_END(&lfp->lf_deleg) && cnt < maxcnt) {
1025 		ldumpp[cnt].ndlck_flags = stp->ls_flags;
1026 		ldumpp[cnt].ndlck_stateid.seqid = stp->ls_stateid.seqid;
1027 		ldumpp[cnt].ndlck_stateid.other[0] = stp->ls_stateid.other[0];
1028 		ldumpp[cnt].ndlck_stateid.other[1] = stp->ls_stateid.other[1];
1029 		ldumpp[cnt].ndlck_stateid.other[2] = stp->ls_stateid.other[2];
1030 		ldumpp[cnt].ndlck_owner.nclid_idlen = 0;
1031 		ldumpp[cnt].ndlck_clid.nclid_idlen = stp->ls_clp->lc_idlen;
1032 		NFSBCOPY(stp->ls_clp->lc_id, ldumpp[cnt].ndlck_clid.nclid_id,
1033 		    stp->ls_clp->lc_idlen);
1034 		sad=NFSSOCKADDR(stp->ls_clp->lc_req.nr_nam, struct sockaddr *);
1035 		ldumpp[cnt].ndlck_addrfam = sad->sa_family;
1036 		if (sad->sa_family == AF_INET) {
1037 			rad = (struct sockaddr_in *)sad;
1038 			ldumpp[cnt].ndlck_cbaddr.sin_addr = rad->sin_addr;
1039 		} else {
1040 			rad6 = (struct sockaddr_in6 *)sad;
1041 			ldumpp[cnt].ndlck_cbaddr.sin6_addr = rad6->sin6_addr;
1042 		}
1043 		stp = LIST_NEXT(stp, ls_file);
1044 		cnt++;
1045 	}
1046 
1047 	/*
1048 	 * If list isn't full, mark end of list by setting the client name
1049 	 * to zero length.
1050 	 */
1051 	if (cnt < maxcnt)
1052 		ldumpp[cnt].ndlck_clid.nclid_idlen = 0;
1053 	NFSUNLOCKSTATE();
1054 	NFSLOCKV4ROOTMUTEX();
1055 	nfsv4_relref(&nfsv4rootfs_lock);
1056 	NFSUNLOCKV4ROOTMUTEX();
1057 }
1058 
1059 /*
1060  * Server timer routine. It can scan any linked list, so long
1061  * as it holds the spin/mutex lock and there is no exclusive lock on
1062  * nfsv4rootfs_lock.
1063  * (For OpenBSD, a kthread is ok. For FreeBSD, I think it is ok
1064  *  to do this from a callout, since the spin locks work. For
1065  *  Darwin, I'm not sure what will work correctly yet.)
1066  * Should be called once per second.
1067  */
1068 APPLESTATIC void
1069 nfsrv_servertimer(void)
1070 {
1071 	struct nfsclient *clp, *nclp;
1072 	struct nfsstate *stp, *nstp;
1073 	int got_ref, i;
1074 
1075 	/*
1076 	 * Make sure nfsboottime is set. This is used by V3 as well
1077 	 * as V4. Note that nfsboottime is not nfsrvboottime, which is
1078 	 * only used by the V4 server for leases.
1079 	 */
1080 	if (nfsboottime.tv_sec == 0)
1081 		NFSSETBOOTTIME(nfsboottime);
1082 
1083 	/*
1084 	 * If server hasn't started yet, just return.
1085 	 */
1086 	NFSLOCKSTATE();
1087 	if (nfsrv_stablefirst.nsf_eograce == 0) {
1088 		NFSUNLOCKSTATE();
1089 		return;
1090 	}
1091 	if (!(nfsrv_stablefirst.nsf_flags & NFSNSF_UPDATEDONE)) {
1092 		if (!(nfsrv_stablefirst.nsf_flags & NFSNSF_GRACEOVER) &&
1093 		    NFSD_MONOSEC > nfsrv_stablefirst.nsf_eograce)
1094 			nfsrv_stablefirst.nsf_flags |=
1095 			    (NFSNSF_GRACEOVER | NFSNSF_NEEDLOCK);
1096 		NFSUNLOCKSTATE();
1097 		return;
1098 	}
1099 
1100 	/*
1101 	 * Try and get a reference count on the nfsv4rootfs_lock so that
1102 	 * no nfsd thread can acquire an exclusive lock on it before this
1103 	 * call is done. If it is already exclusively locked, just return.
1104 	 */
1105 	NFSLOCKV4ROOTMUTEX();
1106 	got_ref = nfsv4_getref_nonblock(&nfsv4rootfs_lock);
1107 	NFSUNLOCKV4ROOTMUTEX();
1108 	if (got_ref == 0) {
1109 		NFSUNLOCKSTATE();
1110 		return;
1111 	}
1112 
1113 	/*
1114 	 * For each client...
1115 	 */
1116 	for (i = 0; i < nfsrv_clienthashsize; i++) {
1117 	    clp = LIST_FIRST(&nfsclienthash[i]);
1118 	    while (clp != LIST_END(&nfsclienthash[i])) {
1119 		nclp = LIST_NEXT(clp, lc_hash);
1120 		if (!(clp->lc_flags & LCL_EXPIREIT)) {
1121 		    if (((clp->lc_expiry + NFSRV_STALELEASE) < NFSD_MONOSEC
1122 			 && ((LIST_EMPTY(&clp->lc_deleg)
1123 			      && LIST_EMPTY(&clp->lc_open)) ||
1124 			     nfsrv_clients > nfsrv_clienthighwater)) ||
1125 			(clp->lc_expiry + NFSRV_MOULDYLEASE) < NFSD_MONOSEC ||
1126 			(clp->lc_expiry < NFSD_MONOSEC &&
1127 			 (nfsrv_openpluslock * 10 / 9) > nfsrv_v4statelimit)) {
1128 			/*
1129 			 * Lease has expired several nfsrv_lease times ago:
1130 			 * PLUS
1131 			 *    - no state is associated with it
1132 			 *    OR
1133 			 *    - above high water mark for number of clients
1134 			 *      (nfsrv_clienthighwater should be large enough
1135 			 *       that this only occurs when clients fail to
1136 			 *       use the same nfs_client_id4.id. Maybe somewhat
1137 			 *       higher that the maximum number of clients that
1138 			 *       will mount this server?)
1139 			 * OR
1140 			 * Lease has expired a very long time ago
1141 			 * OR
1142 			 * Lease has expired PLUS the number of opens + locks
1143 			 * has exceeded 90% of capacity
1144 			 *
1145 			 * --> Mark for expiry. The actual expiry will be done
1146 			 *     by an nfsd sometime soon.
1147 			 */
1148 			clp->lc_flags |= LCL_EXPIREIT;
1149 			nfsrv_stablefirst.nsf_flags |=
1150 			    (NFSNSF_NEEDLOCK | NFSNSF_EXPIREDCLIENT);
1151 		    } else {
1152 			/*
1153 			 * If there are no opens, increment no open tick cnt
1154 			 * If time exceeds NFSNOOPEN, mark it to be thrown away
1155 			 * otherwise, if there is an open, reset no open time
1156 			 * Hopefully, this will avoid excessive re-creation
1157 			 * of open owners and subsequent open confirms.
1158 			 */
1159 			stp = LIST_FIRST(&clp->lc_open);
1160 			while (stp != LIST_END(&clp->lc_open)) {
1161 				nstp = LIST_NEXT(stp, ls_list);
1162 				if (LIST_EMPTY(&stp->ls_open)) {
1163 					stp->ls_noopens++;
1164 					if (stp->ls_noopens > NFSNOOPEN ||
1165 					    (nfsrv_openpluslock * 2) >
1166 					    nfsrv_v4statelimit)
1167 						nfsrv_stablefirst.nsf_flags |=
1168 							NFSNSF_NOOPENS;
1169 				} else {
1170 					stp->ls_noopens = 0;
1171 				}
1172 				stp = nstp;
1173 			}
1174 		    }
1175 		}
1176 		clp = nclp;
1177 	    }
1178 	}
1179 	NFSUNLOCKSTATE();
1180 	NFSLOCKV4ROOTMUTEX();
1181 	nfsv4_relref(&nfsv4rootfs_lock);
1182 	NFSUNLOCKV4ROOTMUTEX();
1183 }
1184 
1185 /*
1186  * The following set of functions free up the various data structures.
1187  */
1188 /*
1189  * Clear out all open/lock state related to this nfsclient.
1190  * Caller must hold an exclusive lock on nfsv4rootfs_lock, so that
1191  * there are no other active nfsd threads.
1192  */
1193 APPLESTATIC void
1194 nfsrv_cleanclient(struct nfsclient *clp, NFSPROC_T *p)
1195 {
1196 	struct nfsstate *stp, *nstp;
1197 	struct nfsdsession *sep, *nsep;
1198 
1199 	LIST_FOREACH_SAFE(stp, &clp->lc_open, ls_list, nstp)
1200 		nfsrv_freeopenowner(stp, 1, p);
1201 	if ((clp->lc_flags & LCL_ADMINREVOKED) == 0)
1202 		LIST_FOREACH_SAFE(sep, &clp->lc_session, sess_list, nsep)
1203 			(void)nfsrv_freesession(sep, NULL);
1204 }
1205 
1206 /*
1207  * Free a client that has been cleaned. It should also already have been
1208  * removed from the lists.
1209  * (Just to be safe w.r.t. newnfs_disconnect(), call this function when
1210  *  softclock interrupts are enabled.)
1211  */
1212 APPLESTATIC void
1213 nfsrv_zapclient(struct nfsclient *clp, NFSPROC_T *p)
1214 {
1215 
1216 #ifdef notyet
1217 	if ((clp->lc_flags & (LCL_GSS | LCL_CALLBACKSON)) ==
1218 	     (LCL_GSS | LCL_CALLBACKSON) &&
1219 	    (clp->lc_hand.nfsh_flag & NFSG_COMPLETE) &&
1220 	    clp->lc_handlelen > 0) {
1221 		clp->lc_hand.nfsh_flag &= ~NFSG_COMPLETE;
1222 		clp->lc_hand.nfsh_flag |= NFSG_DESTROYED;
1223 		(void) nfsrv_docallback(clp, NFSV4PROC_CBNULL,
1224 			NULL, 0, NULL, NULL, NULL, p);
1225 	}
1226 #endif
1227 	newnfs_disconnect(&clp->lc_req);
1228 	NFSSOCKADDRFREE(clp->lc_req.nr_nam);
1229 	NFSFREEMUTEX(&clp->lc_req.nr_mtx);
1230 	free(clp->lc_stateid, M_NFSDCLIENT);
1231 	free(clp, M_NFSDCLIENT);
1232 	NFSLOCKSTATE();
1233 	nfsstatsv1.srvclients--;
1234 	nfsrv_openpluslock--;
1235 	nfsrv_clients--;
1236 	NFSUNLOCKSTATE();
1237 }
1238 
1239 /*
1240  * Free a list of delegation state structures.
1241  * (This function will also free all nfslockfile structures that no
1242  *  longer have associated state.)
1243  */
1244 APPLESTATIC void
1245 nfsrv_freedeleglist(struct nfsstatehead *sthp)
1246 {
1247 	struct nfsstate *stp, *nstp;
1248 
1249 	LIST_FOREACH_SAFE(stp, sthp, ls_list, nstp) {
1250 		nfsrv_freedeleg(stp);
1251 	}
1252 	LIST_INIT(sthp);
1253 }
1254 
1255 /*
1256  * Free up a delegation.
1257  */
1258 static void
1259 nfsrv_freedeleg(struct nfsstate *stp)
1260 {
1261 	struct nfslockfile *lfp;
1262 
1263 	LIST_REMOVE(stp, ls_hash);
1264 	LIST_REMOVE(stp, ls_list);
1265 	LIST_REMOVE(stp, ls_file);
1266 	lfp = stp->ls_lfp;
1267 	if (LIST_EMPTY(&lfp->lf_open) &&
1268 	    LIST_EMPTY(&lfp->lf_lock) && LIST_EMPTY(&lfp->lf_deleg) &&
1269 	    LIST_EMPTY(&lfp->lf_locallock) && LIST_EMPTY(&lfp->lf_rollback) &&
1270 	    lfp->lf_usecount == 0 &&
1271 	    nfsv4_testlock(&lfp->lf_locallock_lck) == 0)
1272 		nfsrv_freenfslockfile(lfp);
1273 	FREE((caddr_t)stp, M_NFSDSTATE);
1274 	nfsstatsv1.srvdelegates--;
1275 	nfsrv_openpluslock--;
1276 	nfsrv_delegatecnt--;
1277 }
1278 
1279 /*
1280  * This function frees an open owner and all associated opens.
1281  */
1282 static void
1283 nfsrv_freeopenowner(struct nfsstate *stp, int cansleep, NFSPROC_T *p)
1284 {
1285 	struct nfsstate *nstp, *tstp;
1286 
1287 	LIST_REMOVE(stp, ls_list);
1288 	/*
1289 	 * Now, free all associated opens.
1290 	 */
1291 	nstp = LIST_FIRST(&stp->ls_open);
1292 	while (nstp != LIST_END(&stp->ls_open)) {
1293 		tstp = nstp;
1294 		nstp = LIST_NEXT(nstp, ls_list);
1295 		(void) nfsrv_freeopen(tstp, NULL, cansleep, p);
1296 	}
1297 	if (stp->ls_op)
1298 		nfsrvd_derefcache(stp->ls_op);
1299 	FREE((caddr_t)stp, M_NFSDSTATE);
1300 	nfsstatsv1.srvopenowners--;
1301 	nfsrv_openpluslock--;
1302 }
1303 
1304 /*
1305  * This function frees an open (nfsstate open structure) with all associated
1306  * lock_owners and locks. It also frees the nfslockfile structure iff there
1307  * are no other opens on the file.
1308  * Returns 1 if it free'd the nfslockfile, 0 otherwise.
1309  */
1310 static int
1311 nfsrv_freeopen(struct nfsstate *stp, vnode_t vp, int cansleep, NFSPROC_T *p)
1312 {
1313 	struct nfsstate *nstp, *tstp;
1314 	struct nfslockfile *lfp;
1315 	int ret;
1316 
1317 	LIST_REMOVE(stp, ls_hash);
1318 	LIST_REMOVE(stp, ls_list);
1319 	LIST_REMOVE(stp, ls_file);
1320 
1321 	lfp = stp->ls_lfp;
1322 	/*
1323 	 * Now, free all lockowners associated with this open.
1324 	 */
1325 	LIST_FOREACH_SAFE(tstp, &stp->ls_open, ls_list, nstp)
1326 		nfsrv_freelockowner(tstp, vp, cansleep, p);
1327 
1328 	/*
1329 	 * The nfslockfile is freed here if there are no locks
1330 	 * associated with the open.
1331 	 * If there are locks associated with the open, the
1332 	 * nfslockfile structure can be freed via nfsrv_freelockowner().
1333 	 * Acquire the state mutex to avoid races with calls to
1334 	 * nfsrv_getlockfile().
1335 	 */
1336 	if (cansleep != 0)
1337 		NFSLOCKSTATE();
1338 	if (lfp != NULL && LIST_EMPTY(&lfp->lf_open) &&
1339 	    LIST_EMPTY(&lfp->lf_deleg) && LIST_EMPTY(&lfp->lf_lock) &&
1340 	    LIST_EMPTY(&lfp->lf_locallock) && LIST_EMPTY(&lfp->lf_rollback) &&
1341 	    lfp->lf_usecount == 0 &&
1342 	    (cansleep != 0 || nfsv4_testlock(&lfp->lf_locallock_lck) == 0)) {
1343 		nfsrv_freenfslockfile(lfp);
1344 		ret = 1;
1345 	} else
1346 		ret = 0;
1347 	if (cansleep != 0)
1348 		NFSUNLOCKSTATE();
1349 	FREE((caddr_t)stp, M_NFSDSTATE);
1350 	nfsstatsv1.srvopens--;
1351 	nfsrv_openpluslock--;
1352 	return (ret);
1353 }
1354 
1355 /*
1356  * Frees a lockowner and all associated locks.
1357  */
1358 static void
1359 nfsrv_freelockowner(struct nfsstate *stp, vnode_t vp, int cansleep,
1360     NFSPROC_T *p)
1361 {
1362 
1363 	LIST_REMOVE(stp, ls_hash);
1364 	LIST_REMOVE(stp, ls_list);
1365 	nfsrv_freeallnfslocks(stp, vp, cansleep, p);
1366 	if (stp->ls_op)
1367 		nfsrvd_derefcache(stp->ls_op);
1368 	FREE((caddr_t)stp, M_NFSDSTATE);
1369 	nfsstatsv1.srvlockowners--;
1370 	nfsrv_openpluslock--;
1371 }
1372 
1373 /*
1374  * Free all the nfs locks on a lockowner.
1375  */
1376 static void
1377 nfsrv_freeallnfslocks(struct nfsstate *stp, vnode_t vp, int cansleep,
1378     NFSPROC_T *p)
1379 {
1380 	struct nfslock *lop, *nlop;
1381 	struct nfsrollback *rlp, *nrlp;
1382 	struct nfslockfile *lfp = NULL;
1383 	int gottvp = 0;
1384 	vnode_t tvp = NULL;
1385 	uint64_t first, end;
1386 
1387 	if (vp != NULL)
1388 		ASSERT_VOP_UNLOCKED(vp, "nfsrv_freeallnfslocks: vnode locked");
1389 	lop = LIST_FIRST(&stp->ls_lock);
1390 	while (lop != LIST_END(&stp->ls_lock)) {
1391 		nlop = LIST_NEXT(lop, lo_lckowner);
1392 		/*
1393 		 * Since all locks should be for the same file, lfp should
1394 		 * not change.
1395 		 */
1396 		if (lfp == NULL)
1397 			lfp = lop->lo_lfp;
1398 		else if (lfp != lop->lo_lfp)
1399 			panic("allnfslocks");
1400 		/*
1401 		 * If vp is NULL and cansleep != 0, a vnode must be acquired
1402 		 * from the file handle. This only occurs when called from
1403 		 * nfsrv_cleanclient().
1404 		 */
1405 		if (gottvp == 0) {
1406 			if (nfsrv_dolocallocks == 0)
1407 				tvp = NULL;
1408 			else if (vp == NULL && cansleep != 0) {
1409 				tvp = nfsvno_getvp(&lfp->lf_fh);
1410 				NFSVOPUNLOCK(tvp, 0);
1411 			} else
1412 				tvp = vp;
1413 			gottvp = 1;
1414 		}
1415 
1416 		if (tvp != NULL) {
1417 			if (cansleep == 0)
1418 				panic("allnfs2");
1419 			first = lop->lo_first;
1420 			end = lop->lo_end;
1421 			nfsrv_freenfslock(lop);
1422 			nfsrv_localunlock(tvp, lfp, first, end, p);
1423 			LIST_FOREACH_SAFE(rlp, &lfp->lf_rollback, rlck_list,
1424 			    nrlp)
1425 				free(rlp, M_NFSDROLLBACK);
1426 			LIST_INIT(&lfp->lf_rollback);
1427 		} else
1428 			nfsrv_freenfslock(lop);
1429 		lop = nlop;
1430 	}
1431 	if (vp == NULL && tvp != NULL)
1432 		vrele(tvp);
1433 }
1434 
1435 /*
1436  * Free an nfslock structure.
1437  */
1438 static void
1439 nfsrv_freenfslock(struct nfslock *lop)
1440 {
1441 
1442 	if (lop->lo_lckfile.le_prev != NULL) {
1443 		LIST_REMOVE(lop, lo_lckfile);
1444 		nfsstatsv1.srvlocks--;
1445 		nfsrv_openpluslock--;
1446 	}
1447 	LIST_REMOVE(lop, lo_lckowner);
1448 	FREE((caddr_t)lop, M_NFSDLOCK);
1449 }
1450 
1451 /*
1452  * This function frees an nfslockfile structure.
1453  */
1454 static void
1455 nfsrv_freenfslockfile(struct nfslockfile *lfp)
1456 {
1457 
1458 	LIST_REMOVE(lfp, lf_hash);
1459 	FREE((caddr_t)lfp, M_NFSDLOCKFILE);
1460 }
1461 
1462 /*
1463  * This function looks up an nfsstate structure via stateid.
1464  */
1465 static int
1466 nfsrv_getstate(struct nfsclient *clp, nfsv4stateid_t *stateidp, __unused u_int32_t flags,
1467     struct nfsstate **stpp)
1468 {
1469 	struct nfsstate *stp;
1470 	struct nfsstatehead *hp;
1471 	int error = 0;
1472 
1473 	*stpp = NULL;
1474 	hp = NFSSTATEHASH(clp, *stateidp);
1475 	LIST_FOREACH(stp, hp, ls_hash) {
1476 		if (!NFSBCMP(stp->ls_stateid.other, stateidp->other,
1477 			NFSX_STATEIDOTHER))
1478 			break;
1479 	}
1480 
1481 	/*
1482 	 * If no state id in list, return NFSERR_BADSTATEID.
1483 	 */
1484 	if (stp == LIST_END(hp)) {
1485 		error = NFSERR_BADSTATEID;
1486 		goto out;
1487 	}
1488 	*stpp = stp;
1489 
1490 out:
1491 	NFSEXITCODE(error);
1492 	return (error);
1493 }
1494 
1495 /*
1496  * This function gets an nfsstate structure via owner string.
1497  */
1498 static void
1499 nfsrv_getowner(struct nfsstatehead *hp, struct nfsstate *new_stp,
1500     struct nfsstate **stpp)
1501 {
1502 	struct nfsstate *stp;
1503 
1504 	*stpp = NULL;
1505 	LIST_FOREACH(stp, hp, ls_list) {
1506 		if (new_stp->ls_ownerlen == stp->ls_ownerlen &&
1507 		  !NFSBCMP(new_stp->ls_owner,stp->ls_owner,stp->ls_ownerlen)) {
1508 			*stpp = stp;
1509 			return;
1510 		}
1511 	}
1512 }
1513 
1514 /*
1515  * Lock control function called to update lock status.
1516  * Returns 0 upon success, -1 if there is no lock and the flags indicate
1517  * that one isn't to be created and an NFSERR_xxx for other errors.
1518  * The structures new_stp and new_lop are passed in as pointers that should
1519  * be set to NULL if the structure is used and shouldn't be free'd.
1520  * For the NFSLCK_TEST and NFSLCK_CHECK cases, the structures are
1521  * never used and can safely be allocated on the stack. For all other
1522  * cases, *new_stpp and *new_lopp should be malloc'd before the call,
1523  * in case they are used.
1524  */
1525 APPLESTATIC int
1526 nfsrv_lockctrl(vnode_t vp, struct nfsstate **new_stpp,
1527     struct nfslock **new_lopp, struct nfslockconflict *cfp,
1528     nfsquad_t clientid, nfsv4stateid_t *stateidp,
1529     __unused struct nfsexstuff *exp,
1530     struct nfsrv_descript *nd, NFSPROC_T *p)
1531 {
1532 	struct nfslock *lop;
1533 	struct nfsstate *new_stp = *new_stpp;
1534 	struct nfslock *new_lop = *new_lopp;
1535 	struct nfsstate *tstp, *mystp, *nstp;
1536 	int specialid = 0;
1537 	struct nfslockfile *lfp;
1538 	struct nfslock *other_lop = NULL;
1539 	struct nfsstate *stp, *lckstp = NULL;
1540 	struct nfsclient *clp = NULL;
1541 	u_int32_t bits;
1542 	int error = 0, haslock = 0, ret, reterr;
1543 	int getlckret, delegation = 0, filestruct_locked, vnode_unlocked = 0;
1544 	fhandle_t nfh;
1545 	uint64_t first, end;
1546 	uint32_t lock_flags;
1547 
1548 	if (new_stp->ls_flags & (NFSLCK_CHECK | NFSLCK_SETATTR)) {
1549 		/*
1550 		 * Note the special cases of "all 1s" or "all 0s" stateids and
1551 		 * let reads with all 1s go ahead.
1552 		 */
1553 		if (new_stp->ls_stateid.seqid == 0x0 &&
1554 		    new_stp->ls_stateid.other[0] == 0x0 &&
1555 		    new_stp->ls_stateid.other[1] == 0x0 &&
1556 		    new_stp->ls_stateid.other[2] == 0x0)
1557 			specialid = 1;
1558 		else if (new_stp->ls_stateid.seqid == 0xffffffff &&
1559 		    new_stp->ls_stateid.other[0] == 0xffffffff &&
1560 		    new_stp->ls_stateid.other[1] == 0xffffffff &&
1561 		    new_stp->ls_stateid.other[2] == 0xffffffff)
1562 			specialid = 2;
1563 	}
1564 
1565 	/*
1566 	 * Check for restart conditions (client and server).
1567 	 */
1568 	error = nfsrv_checkrestart(clientid, new_stp->ls_flags,
1569 	    &new_stp->ls_stateid, specialid);
1570 	if (error)
1571 		goto out;
1572 
1573 	/*
1574 	 * Check for state resource limit exceeded.
1575 	 */
1576 	if ((new_stp->ls_flags & NFSLCK_LOCK) &&
1577 	    nfsrv_openpluslock > nfsrv_v4statelimit) {
1578 		error = NFSERR_RESOURCE;
1579 		goto out;
1580 	}
1581 
1582 	/*
1583 	 * For the lock case, get another nfslock structure,
1584 	 * just in case we need it.
1585 	 * Malloc now, before we start sifting through the linked lists,
1586 	 * in case we have to wait for memory.
1587 	 */
1588 tryagain:
1589 	if (new_stp->ls_flags & NFSLCK_LOCK)
1590 		MALLOC(other_lop, struct nfslock *, sizeof (struct nfslock),
1591 		    M_NFSDLOCK, M_WAITOK);
1592 	filestruct_locked = 0;
1593 	reterr = 0;
1594 	lfp = NULL;
1595 
1596 	/*
1597 	 * Get the lockfile structure for CFH now, so we can do a sanity
1598 	 * check against the stateid, before incrementing the seqid#, since
1599 	 * we want to return NFSERR_BADSTATEID on failure and the seqid#
1600 	 * shouldn't be incremented for this case.
1601 	 * If nfsrv_getlockfile() returns -1, it means "not found", which
1602 	 * will be handled later.
1603 	 * If we are doing Lock/LockU and local locking is enabled, sleep
1604 	 * lock the nfslockfile structure.
1605 	 */
1606 	getlckret = nfsrv_getlockfh(vp, new_stp->ls_flags, NULL, &nfh, p);
1607 	NFSLOCKSTATE();
1608 	if (getlckret == 0) {
1609 		if ((new_stp->ls_flags & (NFSLCK_LOCK | NFSLCK_UNLOCK)) != 0 &&
1610 		    nfsrv_dolocallocks != 0 && nd->nd_repstat == 0) {
1611 			getlckret = nfsrv_getlockfile(new_stp->ls_flags, NULL,
1612 			    &lfp, &nfh, 1);
1613 			if (getlckret == 0)
1614 				filestruct_locked = 1;
1615 		} else
1616 			getlckret = nfsrv_getlockfile(new_stp->ls_flags, NULL,
1617 			    &lfp, &nfh, 0);
1618 	}
1619 	if (getlckret != 0 && getlckret != -1)
1620 		reterr = getlckret;
1621 
1622 	if (filestruct_locked != 0) {
1623 		LIST_INIT(&lfp->lf_rollback);
1624 		if ((new_stp->ls_flags & NFSLCK_LOCK)) {
1625 			/*
1626 			 * For local locking, do the advisory locking now, so
1627 			 * that any conflict can be detected. A failure later
1628 			 * can be rolled back locally. If an error is returned,
1629 			 * struct nfslockfile has been unlocked and any local
1630 			 * locking rolled back.
1631 			 */
1632 			NFSUNLOCKSTATE();
1633 			if (vnode_unlocked == 0) {
1634 				ASSERT_VOP_ELOCKED(vp, "nfsrv_lockctrl1");
1635 				vnode_unlocked = 1;
1636 				NFSVOPUNLOCK(vp, 0);
1637 			}
1638 			reterr = nfsrv_locallock(vp, lfp,
1639 			    (new_lop->lo_flags & (NFSLCK_READ | NFSLCK_WRITE)),
1640 			    new_lop->lo_first, new_lop->lo_end, cfp, p);
1641 			NFSLOCKSTATE();
1642 		}
1643 	}
1644 
1645 	if (specialid == 0) {
1646 	    if (new_stp->ls_flags & NFSLCK_TEST) {
1647 		/*
1648 		 * RFC 3530 does not list LockT as an op that renews a
1649 		 * lease, but the consensus seems to be that it is ok
1650 		 * for a server to do so.
1651 		 */
1652 		error = nfsrv_getclient(clientid, CLOPS_RENEW, &clp, NULL,
1653 		    (nfsquad_t)((u_quad_t)0), 0, nd, p);
1654 
1655 		/*
1656 		 * Since NFSERR_EXPIRED, NFSERR_ADMINREVOKED are not valid
1657 		 * error returns for LockT, just go ahead and test for a lock,
1658 		 * since there are no locks for this client, but other locks
1659 		 * can conflict. (ie. same client will always be false)
1660 		 */
1661 		if (error == NFSERR_EXPIRED || error == NFSERR_ADMINREVOKED)
1662 		    error = 0;
1663 		lckstp = new_stp;
1664 	    } else {
1665 	      error = nfsrv_getclient(clientid, CLOPS_RENEW, &clp, NULL,
1666 		(nfsquad_t)((u_quad_t)0), 0, nd, p);
1667 	      if (error == 0)
1668 		/*
1669 		 * Look up the stateid
1670 		 */
1671 		error = nfsrv_getstate(clp, &new_stp->ls_stateid,
1672 		  new_stp->ls_flags, &stp);
1673 	      /*
1674 	       * do some sanity checks for an unconfirmed open or a
1675 	       * stateid that refers to the wrong file, for an open stateid
1676 	       */
1677 	      if (error == 0 && (stp->ls_flags & NFSLCK_OPEN) &&
1678 		  ((stp->ls_openowner->ls_flags & NFSLCK_NEEDSCONFIRM) ||
1679 		   (getlckret == 0 && stp->ls_lfp != lfp))){
1680 		      /*
1681 		       * NFSLCK_SETATTR should return OK rather than NFSERR_BADSTATEID
1682 		       * The only exception is using SETATTR with SIZE.
1683 		       * */
1684                     if ((new_stp->ls_flags &
1685                          (NFSLCK_SETATTR | NFSLCK_CHECK)) != NFSLCK_SETATTR)
1686 			     error = NFSERR_BADSTATEID;
1687 	      }
1688 
1689 		if (error == 0 &&
1690 		  (stp->ls_flags & (NFSLCK_DELEGREAD | NFSLCK_DELEGWRITE)) &&
1691 		  getlckret == 0 && stp->ls_lfp != lfp)
1692 			error = NFSERR_BADSTATEID;
1693 
1694 	      /*
1695 	       * If the lockowner stateid doesn't refer to the same file,
1696 	       * I believe that is considered ok, since some clients will
1697 	       * only create a single lockowner and use that for all locks
1698 	       * on all files.
1699 	       * For now, log it as a diagnostic, instead of considering it
1700 	       * a BadStateid.
1701 	       */
1702 	      if (error == 0 && (stp->ls_flags &
1703 		  (NFSLCK_OPEN | NFSLCK_DELEGREAD | NFSLCK_DELEGWRITE)) == 0 &&
1704 		  getlckret == 0 && stp->ls_lfp != lfp) {
1705 #ifdef DIAGNOSTIC
1706 		  printf("Got a lock statid for different file open\n");
1707 #endif
1708 		  /*
1709 		  error = NFSERR_BADSTATEID;
1710 		  */
1711 	      }
1712 
1713 	      if (error == 0) {
1714 		    if (new_stp->ls_flags & NFSLCK_OPENTOLOCK) {
1715 			/*
1716 			 * If haslock set, we've already checked the seqid.
1717 			 */
1718 			if (!haslock) {
1719 			    if (stp->ls_flags & NFSLCK_OPEN)
1720 				error = nfsrv_checkseqid(nd, new_stp->ls_seq,
1721 				    stp->ls_openowner, new_stp->ls_op);
1722 			    else
1723 				error = NFSERR_BADSTATEID;
1724 			}
1725 			if (!error)
1726 			    nfsrv_getowner(&stp->ls_open, new_stp, &lckstp);
1727 			if (lckstp)
1728 			    /*
1729 			     * I believe this should be an error, but it
1730 			     * isn't obvious what NFSERR_xxx would be
1731 			     * appropriate, so I'll use NFSERR_INVAL for now.
1732 			     */
1733 			    error = NFSERR_INVAL;
1734 			else
1735 			    lckstp = new_stp;
1736 		    } else if (new_stp->ls_flags&(NFSLCK_LOCK|NFSLCK_UNLOCK)) {
1737 			/*
1738 			 * If haslock set, ditto above.
1739 			 */
1740 			if (!haslock) {
1741 			    if (stp->ls_flags & NFSLCK_OPEN)
1742 				error = NFSERR_BADSTATEID;
1743 			    else
1744 				error = nfsrv_checkseqid(nd, new_stp->ls_seq,
1745 				    stp, new_stp->ls_op);
1746 			}
1747 			lckstp = stp;
1748 		    } else {
1749 			lckstp = stp;
1750 		    }
1751 	      }
1752 	      /*
1753 	       * If the seqid part of the stateid isn't the same, return
1754 	       * NFSERR_OLDSTATEID for cases other than I/O Ops.
1755 	       * For I/O Ops, only return NFSERR_OLDSTATEID if
1756 	       * nfsrv_returnoldstateid is set. (The consensus on the email
1757 	       * list was that most clients would prefer to not receive
1758 	       * NFSERR_OLDSTATEID for I/O Ops, but the RFC suggests that that
1759 	       * is what will happen, so I use the nfsrv_returnoldstateid to
1760 	       * allow for either server configuration.)
1761 	       */
1762 	      if (!error && stp->ls_stateid.seqid!=new_stp->ls_stateid.seqid &&
1763 		  (((nd->nd_flag & ND_NFSV41) == 0 &&
1764 		   (!(new_stp->ls_flags & NFSLCK_CHECK) ||
1765 		    nfsrv_returnoldstateid)) ||
1766 		   ((nd->nd_flag & ND_NFSV41) != 0 &&
1767 		    new_stp->ls_stateid.seqid != 0)))
1768 		    error = NFSERR_OLDSTATEID;
1769 	    }
1770 	}
1771 
1772 	/*
1773 	 * Now we can check for grace.
1774 	 */
1775 	if (!error)
1776 		error = nfsrv_checkgrace(nd, clp, new_stp->ls_flags);
1777 	if ((new_stp->ls_flags & NFSLCK_RECLAIM) && !error &&
1778 		nfsrv_checkstable(clp))
1779 		error = NFSERR_NOGRACE;
1780 	/*
1781 	 * If we successfully Reclaimed state, note that.
1782 	 */
1783 	if ((new_stp->ls_flags & NFSLCK_RECLAIM) && !error)
1784 		nfsrv_markstable(clp);
1785 
1786 	/*
1787 	 * At this point, either error == NFSERR_BADSTATEID or the
1788 	 * seqid# has been updated, so we can return any error.
1789 	 * If error == 0, there may be an error in:
1790 	 *    nd_repstat - Set by the calling function.
1791 	 *    reterr - Set above, if getting the nfslockfile structure
1792 	 *       or acquiring the local lock failed.
1793 	 *    (If both of these are set, nd_repstat should probably be
1794 	 *     returned, since that error was detected before this
1795 	 *     function call.)
1796 	 */
1797 	if (error != 0 || nd->nd_repstat != 0 || reterr != 0) {
1798 		if (error == 0) {
1799 			if (nd->nd_repstat != 0)
1800 				error = nd->nd_repstat;
1801 			else
1802 				error = reterr;
1803 		}
1804 		if (filestruct_locked != 0) {
1805 			/* Roll back local locks. */
1806 			NFSUNLOCKSTATE();
1807 			if (vnode_unlocked == 0) {
1808 				ASSERT_VOP_ELOCKED(vp, "nfsrv_lockctrl2");
1809 				vnode_unlocked = 1;
1810 				NFSVOPUNLOCK(vp, 0);
1811 			}
1812 			nfsrv_locallock_rollback(vp, lfp, p);
1813 			NFSLOCKSTATE();
1814 			nfsrv_unlocklf(lfp);
1815 		}
1816 		NFSUNLOCKSTATE();
1817 		goto out;
1818 	}
1819 
1820 	/*
1821 	 * Check the nfsrv_getlockfile return.
1822 	 * Returned -1 if no structure found.
1823 	 */
1824 	if (getlckret == -1) {
1825 		error = NFSERR_EXPIRED;
1826 		/*
1827 		 * Called from lockt, so no lock is OK.
1828 		 */
1829 		if (new_stp->ls_flags & NFSLCK_TEST) {
1830 			error = 0;
1831 		} else if (new_stp->ls_flags &
1832 		    (NFSLCK_CHECK | NFSLCK_SETATTR)) {
1833 			/*
1834 			 * Called to check for a lock, OK if the stateid is all
1835 			 * 1s or all 0s, but there should be an nfsstate
1836 			 * otherwise.
1837 			 * (ie. If there is no open, I'll assume no share
1838 			 *  deny bits.)
1839 			 */
1840 			if (specialid)
1841 				error = 0;
1842 			else
1843 				error = NFSERR_BADSTATEID;
1844 		}
1845 		NFSUNLOCKSTATE();
1846 		goto out;
1847 	}
1848 
1849 	/*
1850 	 * For NFSLCK_CHECK and NFSLCK_LOCK, test for a share conflict.
1851 	 * For NFSLCK_CHECK, allow a read if write access is granted,
1852 	 * but check for a deny. For NFSLCK_LOCK, require correct access,
1853 	 * which implies a conflicting deny can't exist.
1854 	 */
1855 	if (new_stp->ls_flags & (NFSLCK_CHECK | NFSLCK_LOCK)) {
1856 	    /*
1857 	     * Four kinds of state id:
1858 	     * - specialid (all 0s or all 1s), only for NFSLCK_CHECK
1859 	     * - stateid for an open
1860 	     * - stateid for a delegation
1861 	     * - stateid for a lock owner
1862 	     */
1863 	    if (!specialid) {
1864 		if (stp->ls_flags & (NFSLCK_DELEGREAD | NFSLCK_DELEGWRITE)) {
1865 		    delegation = 1;
1866 		    mystp = stp;
1867 		    nfsrv_delaydelegtimeout(stp);
1868 	        } else if (stp->ls_flags & NFSLCK_OPEN) {
1869 		    mystp = stp;
1870 		} else {
1871 		    mystp = stp->ls_openstp;
1872 		}
1873 		/*
1874 		 * If locking or checking, require correct access
1875 		 * bit set.
1876 		 */
1877 		if (((new_stp->ls_flags & NFSLCK_LOCK) &&
1878 		     !((new_lop->lo_flags >> NFSLCK_LOCKSHIFT) &
1879 		       mystp->ls_flags & NFSLCK_ACCESSBITS)) ||
1880 		    ((new_stp->ls_flags & (NFSLCK_CHECK|NFSLCK_READACCESS)) ==
1881 		      (NFSLCK_CHECK | NFSLCK_READACCESS) &&
1882 		     !(mystp->ls_flags & NFSLCK_READACCESS) &&
1883 		     nfsrv_allowreadforwriteopen == 0) ||
1884 		    ((new_stp->ls_flags & (NFSLCK_CHECK|NFSLCK_WRITEACCESS)) ==
1885 		      (NFSLCK_CHECK | NFSLCK_WRITEACCESS) &&
1886 		     !(mystp->ls_flags & NFSLCK_WRITEACCESS))) {
1887 			if (filestruct_locked != 0) {
1888 				/* Roll back local locks. */
1889 				NFSUNLOCKSTATE();
1890 				if (vnode_unlocked == 0) {
1891 					ASSERT_VOP_ELOCKED(vp,
1892 					    "nfsrv_lockctrl3");
1893 					vnode_unlocked = 1;
1894 					NFSVOPUNLOCK(vp, 0);
1895 				}
1896 				nfsrv_locallock_rollback(vp, lfp, p);
1897 				NFSLOCKSTATE();
1898 				nfsrv_unlocklf(lfp);
1899 			}
1900 			NFSUNLOCKSTATE();
1901 			error = NFSERR_OPENMODE;
1902 			goto out;
1903 		}
1904 	    } else
1905 		mystp = NULL;
1906 	    if ((new_stp->ls_flags & NFSLCK_CHECK) && !delegation) {
1907 		/*
1908 		 * Check for a conflicting deny bit.
1909 		 */
1910 		LIST_FOREACH(tstp, &lfp->lf_open, ls_file) {
1911 		    if (tstp != mystp) {
1912 			bits = tstp->ls_flags;
1913 			bits >>= NFSLCK_SHIFT;
1914 			if (new_stp->ls_flags & bits & NFSLCK_ACCESSBITS) {
1915 			    KASSERT(vnode_unlocked == 0,
1916 				("nfsrv_lockctrl: vnode unlocked1"));
1917 			    ret = nfsrv_clientconflict(tstp->ls_clp, &haslock,
1918 				vp, p);
1919 			    if (ret == 1) {
1920 				/*
1921 				* nfsrv_clientconflict unlocks state
1922 				 * when it returns non-zero.
1923 				 */
1924 				lckstp = NULL;
1925 				goto tryagain;
1926 			    }
1927 			    if (ret == 0)
1928 				NFSUNLOCKSTATE();
1929 			    if (ret == 2)
1930 				error = NFSERR_PERM;
1931 			    else
1932 				error = NFSERR_OPENMODE;
1933 			    goto out;
1934 			}
1935 		    }
1936 		}
1937 
1938 		/* We're outta here */
1939 		NFSUNLOCKSTATE();
1940 		goto out;
1941 	    }
1942 	}
1943 
1944 	/*
1945 	 * For setattr, just get rid of all the Delegations for other clients.
1946 	 */
1947 	if (new_stp->ls_flags & NFSLCK_SETATTR) {
1948 		KASSERT(vnode_unlocked == 0,
1949 		    ("nfsrv_lockctrl: vnode unlocked2"));
1950 		ret = nfsrv_cleandeleg(vp, lfp, clp, &haslock, p);
1951 		if (ret) {
1952 			/*
1953 			 * nfsrv_cleandeleg() unlocks state when it
1954 			 * returns non-zero.
1955 			 */
1956 			if (ret == -1) {
1957 				lckstp = NULL;
1958 				goto tryagain;
1959 			}
1960 			error = ret;
1961 			goto out;
1962 		}
1963 		if (!(new_stp->ls_flags & NFSLCK_CHECK) ||
1964 		    (LIST_EMPTY(&lfp->lf_open) && LIST_EMPTY(&lfp->lf_lock) &&
1965 		     LIST_EMPTY(&lfp->lf_deleg))) {
1966 			NFSUNLOCKSTATE();
1967 			goto out;
1968 		}
1969 	}
1970 
1971 	/*
1972 	 * Check for a conflicting delegation. If one is found, call
1973 	 * nfsrv_delegconflict() to handle it. If the v4root lock hasn't
1974 	 * been set yet, it will get the lock. Otherwise, it will recall
1975 	 * the delegation. Then, we try try again...
1976 	 * I currently believe the conflict algorithm to be:
1977 	 * For Lock Ops (Lock/LockT/LockU)
1978 	 * - there is a conflict iff a different client has a write delegation
1979 	 * For Reading (Read Op)
1980 	 * - there is a conflict iff a different client has a write delegation
1981 	 *   (the specialids are always a different client)
1982 	 * For Writing (Write/Setattr of size)
1983 	 * - there is a conflict if a different client has any delegation
1984 	 * - there is a conflict if the same client has a read delegation
1985 	 *   (I don't understand why this isn't allowed, but that seems to be
1986 	 *    the current consensus?)
1987 	 */
1988 	tstp = LIST_FIRST(&lfp->lf_deleg);
1989 	while (tstp != LIST_END(&lfp->lf_deleg)) {
1990 	    nstp = LIST_NEXT(tstp, ls_file);
1991 	    if ((((new_stp->ls_flags&(NFSLCK_LOCK|NFSLCK_UNLOCK|NFSLCK_TEST))||
1992 		 ((new_stp->ls_flags & NFSLCK_CHECK) &&
1993 		  (new_lop->lo_flags & NFSLCK_READ))) &&
1994 		  clp != tstp->ls_clp &&
1995 		 (tstp->ls_flags & NFSLCK_DELEGWRITE)) ||
1996 		 ((new_stp->ls_flags & NFSLCK_CHECK) &&
1997 		   (new_lop->lo_flags & NFSLCK_WRITE) &&
1998 		  (clp != tstp->ls_clp ||
1999 		   (tstp->ls_flags & NFSLCK_DELEGREAD)))) {
2000 		ret = 0;
2001 		if (filestruct_locked != 0) {
2002 			/* Roll back local locks. */
2003 			NFSUNLOCKSTATE();
2004 			if (vnode_unlocked == 0) {
2005 				ASSERT_VOP_ELOCKED(vp, "nfsrv_lockctrl4");
2006 				NFSVOPUNLOCK(vp, 0);
2007 			}
2008 			nfsrv_locallock_rollback(vp, lfp, p);
2009 			NFSLOCKSTATE();
2010 			nfsrv_unlocklf(lfp);
2011 			NFSUNLOCKSTATE();
2012 			NFSVOPLOCK(vp, LK_EXCLUSIVE | LK_RETRY);
2013 			vnode_unlocked = 0;
2014 			if ((vp->v_iflag & VI_DOOMED) != 0)
2015 				ret = NFSERR_SERVERFAULT;
2016 			NFSLOCKSTATE();
2017 		}
2018 		if (ret == 0)
2019 			ret = nfsrv_delegconflict(tstp, &haslock, p, vp);
2020 		if (ret) {
2021 		    /*
2022 		     * nfsrv_delegconflict unlocks state when it
2023 		     * returns non-zero, which it always does.
2024 		     */
2025 		    if (other_lop) {
2026 			FREE((caddr_t)other_lop, M_NFSDLOCK);
2027 			other_lop = NULL;
2028 		    }
2029 		    if (ret == -1) {
2030 			lckstp = NULL;
2031 			goto tryagain;
2032 		    }
2033 		    error = ret;
2034 		    goto out;
2035 		}
2036 		/* Never gets here. */
2037 	    }
2038 	    tstp = nstp;
2039 	}
2040 
2041 	/*
2042 	 * Handle the unlock case by calling nfsrv_updatelock().
2043 	 * (Should I have done some access checking above for unlock? For now,
2044 	 *  just let it happen.)
2045 	 */
2046 	if (new_stp->ls_flags & NFSLCK_UNLOCK) {
2047 		first = new_lop->lo_first;
2048 		end = new_lop->lo_end;
2049 		nfsrv_updatelock(stp, new_lopp, &other_lop, lfp);
2050 		stateidp->seqid = ++(stp->ls_stateid.seqid);
2051 		if ((nd->nd_flag & ND_NFSV41) != 0 && stateidp->seqid == 0)
2052 			stateidp->seqid = stp->ls_stateid.seqid = 1;
2053 		stateidp->other[0] = stp->ls_stateid.other[0];
2054 		stateidp->other[1] = stp->ls_stateid.other[1];
2055 		stateidp->other[2] = stp->ls_stateid.other[2];
2056 		if (filestruct_locked != 0) {
2057 			NFSUNLOCKSTATE();
2058 			if (vnode_unlocked == 0) {
2059 				ASSERT_VOP_ELOCKED(vp, "nfsrv_lockctrl5");
2060 				vnode_unlocked = 1;
2061 				NFSVOPUNLOCK(vp, 0);
2062 			}
2063 			/* Update the local locks. */
2064 			nfsrv_localunlock(vp, lfp, first, end, p);
2065 			NFSLOCKSTATE();
2066 			nfsrv_unlocklf(lfp);
2067 		}
2068 		NFSUNLOCKSTATE();
2069 		goto out;
2070 	}
2071 
2072 	/*
2073 	 * Search for a conflicting lock. A lock conflicts if:
2074 	 * - the lock range overlaps and
2075 	 * - at least one lock is a write lock and
2076 	 * - it is not owned by the same lock owner
2077 	 */
2078 	if (!delegation) {
2079 	  LIST_FOREACH(lop, &lfp->lf_lock, lo_lckfile) {
2080 	    if (new_lop->lo_end > lop->lo_first &&
2081 		new_lop->lo_first < lop->lo_end &&
2082 		(new_lop->lo_flags == NFSLCK_WRITE ||
2083 		 lop->lo_flags == NFSLCK_WRITE) &&
2084 		lckstp != lop->lo_stp &&
2085 		(clp != lop->lo_stp->ls_clp ||
2086 		 lckstp->ls_ownerlen != lop->lo_stp->ls_ownerlen ||
2087 		 NFSBCMP(lckstp->ls_owner, lop->lo_stp->ls_owner,
2088 		    lckstp->ls_ownerlen))) {
2089 		if (other_lop) {
2090 		    FREE((caddr_t)other_lop, M_NFSDLOCK);
2091 		    other_lop = NULL;
2092 		}
2093 		if (vnode_unlocked != 0)
2094 		    ret = nfsrv_clientconflict(lop->lo_stp->ls_clp, &haslock,
2095 			NULL, p);
2096 		else
2097 		    ret = nfsrv_clientconflict(lop->lo_stp->ls_clp, &haslock,
2098 			vp, p);
2099 		if (ret == 1) {
2100 		    if (filestruct_locked != 0) {
2101 			if (vnode_unlocked == 0) {
2102 				ASSERT_VOP_ELOCKED(vp, "nfsrv_lockctrl6");
2103 				NFSVOPUNLOCK(vp, 0);
2104 			}
2105 			/* Roll back local locks. */
2106 			nfsrv_locallock_rollback(vp, lfp, p);
2107 			NFSLOCKSTATE();
2108 			nfsrv_unlocklf(lfp);
2109 			NFSUNLOCKSTATE();
2110 			NFSVOPLOCK(vp, LK_EXCLUSIVE | LK_RETRY);
2111 			vnode_unlocked = 0;
2112 			if ((vp->v_iflag & VI_DOOMED) != 0) {
2113 				error = NFSERR_SERVERFAULT;
2114 				goto out;
2115 			}
2116 		    }
2117 		    /*
2118 		     * nfsrv_clientconflict() unlocks state when it
2119 		     * returns non-zero.
2120 		     */
2121 		    lckstp = NULL;
2122 		    goto tryagain;
2123 		}
2124 		/*
2125 		 * Found a conflicting lock, so record the conflict and
2126 		 * return the error.
2127 		 */
2128 		if (cfp != NULL && ret == 0) {
2129 		    cfp->cl_clientid.lval[0]=lop->lo_stp->ls_stateid.other[0];
2130 		    cfp->cl_clientid.lval[1]=lop->lo_stp->ls_stateid.other[1];
2131 		    cfp->cl_first = lop->lo_first;
2132 		    cfp->cl_end = lop->lo_end;
2133 		    cfp->cl_flags = lop->lo_flags;
2134 		    cfp->cl_ownerlen = lop->lo_stp->ls_ownerlen;
2135 		    NFSBCOPY(lop->lo_stp->ls_owner, cfp->cl_owner,
2136 			cfp->cl_ownerlen);
2137 		}
2138 		if (ret == 2)
2139 		    error = NFSERR_PERM;
2140 		else if (new_stp->ls_flags & NFSLCK_RECLAIM)
2141 		    error = NFSERR_RECLAIMCONFLICT;
2142 		else if (new_stp->ls_flags & NFSLCK_CHECK)
2143 		    error = NFSERR_LOCKED;
2144 		else
2145 		    error = NFSERR_DENIED;
2146 		if (filestruct_locked != 0 && ret == 0) {
2147 			/* Roll back local locks. */
2148 			NFSUNLOCKSTATE();
2149 			if (vnode_unlocked == 0) {
2150 				ASSERT_VOP_ELOCKED(vp, "nfsrv_lockctrl7");
2151 				vnode_unlocked = 1;
2152 				NFSVOPUNLOCK(vp, 0);
2153 			}
2154 			nfsrv_locallock_rollback(vp, lfp, p);
2155 			NFSLOCKSTATE();
2156 			nfsrv_unlocklf(lfp);
2157 		}
2158 		if (ret == 0)
2159 			NFSUNLOCKSTATE();
2160 		goto out;
2161 	    }
2162 	  }
2163 	}
2164 
2165 	/*
2166 	 * We only get here if there was no lock that conflicted.
2167 	 */
2168 	if (new_stp->ls_flags & (NFSLCK_TEST | NFSLCK_CHECK)) {
2169 		NFSUNLOCKSTATE();
2170 		goto out;
2171 	}
2172 
2173 	/*
2174 	 * We only get here when we are creating or modifying a lock.
2175 	 * There are two variants:
2176 	 * - exist_lock_owner where lock_owner exists
2177 	 * - open_to_lock_owner with new lock_owner
2178 	 */
2179 	first = new_lop->lo_first;
2180 	end = new_lop->lo_end;
2181 	lock_flags = new_lop->lo_flags;
2182 	if (!(new_stp->ls_flags & NFSLCK_OPENTOLOCK)) {
2183 		nfsrv_updatelock(lckstp, new_lopp, &other_lop, lfp);
2184 		stateidp->seqid = ++(lckstp->ls_stateid.seqid);
2185 		if ((nd->nd_flag & ND_NFSV41) != 0 && stateidp->seqid == 0)
2186 			stateidp->seqid = lckstp->ls_stateid.seqid = 1;
2187 		stateidp->other[0] = lckstp->ls_stateid.other[0];
2188 		stateidp->other[1] = lckstp->ls_stateid.other[1];
2189 		stateidp->other[2] = lckstp->ls_stateid.other[2];
2190 	} else {
2191 		/*
2192 		 * The new open_to_lock_owner case.
2193 		 * Link the new nfsstate into the lists.
2194 		 */
2195 		new_stp->ls_seq = new_stp->ls_opentolockseq;
2196 		nfsrvd_refcache(new_stp->ls_op);
2197 		stateidp->seqid = new_stp->ls_stateid.seqid = 1;
2198 		stateidp->other[0] = new_stp->ls_stateid.other[0] =
2199 		    clp->lc_clientid.lval[0];
2200 		stateidp->other[1] = new_stp->ls_stateid.other[1] =
2201 		    clp->lc_clientid.lval[1];
2202 		stateidp->other[2] = new_stp->ls_stateid.other[2] =
2203 		    nfsrv_nextstateindex(clp);
2204 		new_stp->ls_clp = clp;
2205 		LIST_INIT(&new_stp->ls_lock);
2206 		new_stp->ls_openstp = stp;
2207 		new_stp->ls_lfp = lfp;
2208 		nfsrv_insertlock(new_lop, (struct nfslock *)new_stp, new_stp,
2209 		    lfp);
2210 		LIST_INSERT_HEAD(NFSSTATEHASH(clp, new_stp->ls_stateid),
2211 		    new_stp, ls_hash);
2212 		LIST_INSERT_HEAD(&stp->ls_open, new_stp, ls_list);
2213 		*new_lopp = NULL;
2214 		*new_stpp = NULL;
2215 		nfsstatsv1.srvlockowners++;
2216 		nfsrv_openpluslock++;
2217 	}
2218 	if (filestruct_locked != 0) {
2219 		NFSUNLOCKSTATE();
2220 		nfsrv_locallock_commit(lfp, lock_flags, first, end);
2221 		NFSLOCKSTATE();
2222 		nfsrv_unlocklf(lfp);
2223 	}
2224 	NFSUNLOCKSTATE();
2225 
2226 out:
2227 	if (haslock) {
2228 		NFSLOCKV4ROOTMUTEX();
2229 		nfsv4_unlock(&nfsv4rootfs_lock, 1);
2230 		NFSUNLOCKV4ROOTMUTEX();
2231 	}
2232 	if (vnode_unlocked != 0) {
2233 		NFSVOPLOCK(vp, LK_EXCLUSIVE | LK_RETRY);
2234 		if (error == 0 && (vp->v_iflag & VI_DOOMED) != 0)
2235 			error = NFSERR_SERVERFAULT;
2236 	}
2237 	if (other_lop)
2238 		FREE((caddr_t)other_lop, M_NFSDLOCK);
2239 	NFSEXITCODE2(error, nd);
2240 	return (error);
2241 }
2242 
2243 /*
2244  * Check for state errors for Open.
2245  * repstat is passed back out as an error if more critical errors
2246  * are not detected.
2247  */
2248 APPLESTATIC int
2249 nfsrv_opencheck(nfsquad_t clientid, nfsv4stateid_t *stateidp,
2250     struct nfsstate *new_stp, vnode_t vp, struct nfsrv_descript *nd,
2251     NFSPROC_T *p, int repstat)
2252 {
2253 	struct nfsstate *stp, *nstp;
2254 	struct nfsclient *clp;
2255 	struct nfsstate *ownerstp;
2256 	struct nfslockfile *lfp, *new_lfp;
2257 	int error = 0, haslock = 0, ret, readonly = 0, getfhret = 0;
2258 
2259 	if ((new_stp->ls_flags & NFSLCK_SHAREBITS) == NFSLCK_READACCESS)
2260 		readonly = 1;
2261 	/*
2262 	 * Check for restart conditions (client and server).
2263 	 */
2264 	error = nfsrv_checkrestart(clientid, new_stp->ls_flags,
2265 		&new_stp->ls_stateid, 0);
2266 	if (error)
2267 		goto out;
2268 
2269 	/*
2270 	 * Check for state resource limit exceeded.
2271 	 * Technically this should be SMP protected, but the worst
2272 	 * case error is "out by one or two" on the count when it
2273 	 * returns NFSERR_RESOURCE and the limit is just a rather
2274 	 * arbitrary high water mark, so no harm is done.
2275 	 */
2276 	if (nfsrv_openpluslock > nfsrv_v4statelimit) {
2277 		error = NFSERR_RESOURCE;
2278 		goto out;
2279 	}
2280 
2281 tryagain:
2282 	MALLOC(new_lfp, struct nfslockfile *, sizeof (struct nfslockfile),
2283 	    M_NFSDLOCKFILE, M_WAITOK);
2284 	if (vp)
2285 		getfhret = nfsrv_getlockfh(vp, new_stp->ls_flags, new_lfp,
2286 		    NULL, p);
2287 	NFSLOCKSTATE();
2288 	/*
2289 	 * Get the nfsclient structure.
2290 	 */
2291 	error = nfsrv_getclient(clientid, CLOPS_RENEW, &clp, NULL,
2292 	    (nfsquad_t)((u_quad_t)0), 0, nd, p);
2293 
2294 	/*
2295 	 * Look up the open owner. See if it needs confirmation and
2296 	 * check the seq#, as required.
2297 	 */
2298 	if (!error)
2299 		nfsrv_getowner(&clp->lc_open, new_stp, &ownerstp);
2300 
2301 	if (!error && ownerstp) {
2302 		error = nfsrv_checkseqid(nd, new_stp->ls_seq, ownerstp,
2303 		    new_stp->ls_op);
2304 		/*
2305 		 * If the OpenOwner hasn't been confirmed, assume the
2306 		 * old one was a replay and this one is ok.
2307 		 * See: RFC3530 Sec. 14.2.18.
2308 		 */
2309 		if (error == NFSERR_BADSEQID &&
2310 		    (ownerstp->ls_flags & NFSLCK_NEEDSCONFIRM))
2311 			error = 0;
2312 	}
2313 
2314 	/*
2315 	 * Check for grace.
2316 	 */
2317 	if (!error)
2318 		error = nfsrv_checkgrace(nd, clp, new_stp->ls_flags);
2319 	if ((new_stp->ls_flags & NFSLCK_RECLAIM) && !error &&
2320 		nfsrv_checkstable(clp))
2321 		error = NFSERR_NOGRACE;
2322 
2323 	/*
2324 	 * If none of the above errors occurred, let repstat be
2325 	 * returned.
2326 	 */
2327 	if (repstat && !error)
2328 		error = repstat;
2329 	if (error) {
2330 		NFSUNLOCKSTATE();
2331 		if (haslock) {
2332 			NFSLOCKV4ROOTMUTEX();
2333 			nfsv4_unlock(&nfsv4rootfs_lock, 1);
2334 			NFSUNLOCKV4ROOTMUTEX();
2335 		}
2336 		free((caddr_t)new_lfp, M_NFSDLOCKFILE);
2337 		goto out;
2338 	}
2339 
2340 	/*
2341 	 * If vp == NULL, the file doesn't exist yet, so return ok.
2342 	 * (This always happens on the first pass, so haslock must be 0.)
2343 	 */
2344 	if (vp == NULL) {
2345 		NFSUNLOCKSTATE();
2346 		FREE((caddr_t)new_lfp, M_NFSDLOCKFILE);
2347 		goto out;
2348 	}
2349 
2350 	/*
2351 	 * Get the structure for the underlying file.
2352 	 */
2353 	if (getfhret)
2354 		error = getfhret;
2355 	else
2356 		error = nfsrv_getlockfile(new_stp->ls_flags, &new_lfp, &lfp,
2357 		    NULL, 0);
2358 	if (new_lfp)
2359 		FREE((caddr_t)new_lfp, M_NFSDLOCKFILE);
2360 	if (error) {
2361 		NFSUNLOCKSTATE();
2362 		if (haslock) {
2363 			NFSLOCKV4ROOTMUTEX();
2364 			nfsv4_unlock(&nfsv4rootfs_lock, 1);
2365 			NFSUNLOCKV4ROOTMUTEX();
2366 		}
2367 		goto out;
2368 	}
2369 
2370 	/*
2371 	 * Search for a conflicting open/share.
2372 	 */
2373 	if (new_stp->ls_flags & NFSLCK_DELEGCUR) {
2374 	    /*
2375 	     * For Delegate_Cur, search for the matching Delegation,
2376 	     * which indicates no conflict.
2377 	     * An old delegation should have been recovered by the
2378 	     * client doing a Claim_DELEGATE_Prev, so I won't let
2379 	     * it match and return NFSERR_EXPIRED. Should I let it
2380 	     * match?
2381 	     */
2382 	    LIST_FOREACH(stp, &lfp->lf_deleg, ls_file) {
2383 		if (!(stp->ls_flags & NFSLCK_OLDDELEG) &&
2384 		    (((nd->nd_flag & ND_NFSV41) != 0 &&
2385 		    stateidp->seqid == 0) ||
2386 		    stateidp->seqid == stp->ls_stateid.seqid) &&
2387 		    !NFSBCMP(stateidp->other, stp->ls_stateid.other,
2388 			  NFSX_STATEIDOTHER))
2389 			break;
2390 	    }
2391 	    if (stp == LIST_END(&lfp->lf_deleg) ||
2392 		((new_stp->ls_flags & NFSLCK_WRITEACCESS) &&
2393 		 (stp->ls_flags & NFSLCK_DELEGREAD))) {
2394 		NFSUNLOCKSTATE();
2395 		if (haslock) {
2396 			NFSLOCKV4ROOTMUTEX();
2397 			nfsv4_unlock(&nfsv4rootfs_lock, 1);
2398 			NFSUNLOCKV4ROOTMUTEX();
2399 		}
2400 		error = NFSERR_EXPIRED;
2401 		goto out;
2402 	    }
2403 	}
2404 
2405 	/*
2406 	 * Check for access/deny bit conflicts. I check for the same
2407 	 * owner as well, in case the client didn't bother.
2408 	 */
2409 	LIST_FOREACH(stp, &lfp->lf_open, ls_file) {
2410 		if (!(new_stp->ls_flags & NFSLCK_DELEGCUR) &&
2411 		    (((new_stp->ls_flags & NFSLCK_ACCESSBITS) &
2412 		      ((stp->ls_flags>>NFSLCK_SHIFT) & NFSLCK_ACCESSBITS))||
2413 		     ((stp->ls_flags & NFSLCK_ACCESSBITS) &
2414 		      ((new_stp->ls_flags>>NFSLCK_SHIFT)&NFSLCK_ACCESSBITS)))){
2415 			ret = nfsrv_clientconflict(stp->ls_clp,&haslock,vp,p);
2416 			if (ret == 1) {
2417 				/*
2418 				 * nfsrv_clientconflict() unlocks
2419 				 * state when it returns non-zero.
2420 				 */
2421 				goto tryagain;
2422 			}
2423 			if (ret == 2)
2424 				error = NFSERR_PERM;
2425 			else if (new_stp->ls_flags & NFSLCK_RECLAIM)
2426 				error = NFSERR_RECLAIMCONFLICT;
2427 			else
2428 				error = NFSERR_SHAREDENIED;
2429 			if (ret == 0)
2430 				NFSUNLOCKSTATE();
2431 			if (haslock) {
2432 				NFSLOCKV4ROOTMUTEX();
2433 				nfsv4_unlock(&nfsv4rootfs_lock, 1);
2434 				NFSUNLOCKV4ROOTMUTEX();
2435 			}
2436 			goto out;
2437 		}
2438 	}
2439 
2440 	/*
2441 	 * Check for a conflicting delegation. If one is found, call
2442 	 * nfsrv_delegconflict() to handle it. If the v4root lock hasn't
2443 	 * been set yet, it will get the lock. Otherwise, it will recall
2444 	 * the delegation. Then, we try try again...
2445 	 * (If NFSLCK_DELEGCUR is set, it has a delegation, so there
2446 	 *  isn't a conflict.)
2447 	 * I currently believe the conflict algorithm to be:
2448 	 * For Open with Read Access and Deny None
2449 	 * - there is a conflict iff a different client has a write delegation
2450 	 * For Open with other Write Access or any Deny except None
2451 	 * - there is a conflict if a different client has any delegation
2452 	 * - there is a conflict if the same client has a read delegation
2453 	 *   (The current consensus is that this last case should be
2454 	 *    considered a conflict since the client with a read delegation
2455 	 *    could have done an Open with ReadAccess and WriteDeny
2456 	 *    locally and then not have checked for the WriteDeny.)
2457 	 * Don't check for a Reclaim, since that will be dealt with
2458 	 * by nfsrv_openctrl().
2459 	 */
2460 	if (!(new_stp->ls_flags &
2461 		(NFSLCK_DELEGPREV | NFSLCK_DELEGCUR | NFSLCK_RECLAIM))) {
2462 	    stp = LIST_FIRST(&lfp->lf_deleg);
2463 	    while (stp != LIST_END(&lfp->lf_deleg)) {
2464 		nstp = LIST_NEXT(stp, ls_file);
2465 		if ((readonly && stp->ls_clp != clp &&
2466 		       (stp->ls_flags & NFSLCK_DELEGWRITE)) ||
2467 		    (!readonly && (stp->ls_clp != clp ||
2468 		         (stp->ls_flags & NFSLCK_DELEGREAD)))) {
2469 			ret = nfsrv_delegconflict(stp, &haslock, p, vp);
2470 			if (ret) {
2471 			    /*
2472 			     * nfsrv_delegconflict() unlocks state
2473 			     * when it returns non-zero.
2474 			     */
2475 			    if (ret == -1)
2476 				goto tryagain;
2477 			    error = ret;
2478 			    goto out;
2479 			}
2480 		}
2481 		stp = nstp;
2482 	    }
2483 	}
2484 	NFSUNLOCKSTATE();
2485 	if (haslock) {
2486 		NFSLOCKV4ROOTMUTEX();
2487 		nfsv4_unlock(&nfsv4rootfs_lock, 1);
2488 		NFSUNLOCKV4ROOTMUTEX();
2489 	}
2490 
2491 out:
2492 	NFSEXITCODE2(error, nd);
2493 	return (error);
2494 }
2495 
2496 /*
2497  * Open control function to create/update open state for an open.
2498  */
2499 APPLESTATIC int
2500 nfsrv_openctrl(struct nfsrv_descript *nd, vnode_t vp,
2501     struct nfsstate **new_stpp, nfsquad_t clientid, nfsv4stateid_t *stateidp,
2502     nfsv4stateid_t *delegstateidp, u_int32_t *rflagsp, struct nfsexstuff *exp,
2503     NFSPROC_T *p, u_quad_t filerev)
2504 {
2505 	struct nfsstate *new_stp = *new_stpp;
2506 	struct nfsstate *stp, *nstp;
2507 	struct nfsstate *openstp = NULL, *new_open, *ownerstp, *new_deleg;
2508 	struct nfslockfile *lfp, *new_lfp;
2509 	struct nfsclient *clp;
2510 	int error = 0, haslock = 0, ret, delegate = 1, writedeleg = 1;
2511 	int readonly = 0, cbret = 1, getfhret = 0;
2512 	int gotstate = 0, len = 0;
2513 	u_char *clidp = NULL;
2514 
2515 	if ((new_stp->ls_flags & NFSLCK_SHAREBITS) == NFSLCK_READACCESS)
2516 		readonly = 1;
2517 	/*
2518 	 * Check for restart conditions (client and server).
2519 	 * (Paranoia, should have been detected by nfsrv_opencheck().)
2520 	 * If an error does show up, return NFSERR_EXPIRED, since the
2521 	 * the seqid# has already been incremented.
2522 	 */
2523 	error = nfsrv_checkrestart(clientid, new_stp->ls_flags,
2524 	    &new_stp->ls_stateid, 0);
2525 	if (error) {
2526 		printf("Nfsd: openctrl unexpected restart err=%d\n",
2527 		    error);
2528 		error = NFSERR_EXPIRED;
2529 		goto out;
2530 	}
2531 
2532 	clidp = malloc(NFSV4_OPAQUELIMIT, M_TEMP, M_WAITOK);
2533 tryagain:
2534 	MALLOC(new_lfp, struct nfslockfile *, sizeof (struct nfslockfile),
2535 	    M_NFSDLOCKFILE, M_WAITOK);
2536 	MALLOC(new_open, struct nfsstate *, sizeof (struct nfsstate),
2537 	    M_NFSDSTATE, M_WAITOK);
2538 	MALLOC(new_deleg, struct nfsstate *, sizeof (struct nfsstate),
2539 	    M_NFSDSTATE, M_WAITOK);
2540 	getfhret = nfsrv_getlockfh(vp, new_stp->ls_flags, new_lfp,
2541 	    NULL, p);
2542 	NFSLOCKSTATE();
2543 	/*
2544 	 * Get the client structure. Since the linked lists could be changed
2545 	 * by other nfsd processes if this process does a tsleep(), one of
2546 	 * two things must be done.
2547 	 * 1 - don't tsleep()
2548 	 * or
2549 	 * 2 - get the nfsv4_lock() { indicated by haslock == 1 }
2550 	 *     before using the lists, since this lock stops the other
2551 	 *     nfsd. This should only be used for rare cases, since it
2552 	 *     essentially single threads the nfsd.
2553 	 *     At this time, it is only done for cases where the stable
2554 	 *     storage file must be written prior to completion of state
2555 	 *     expiration.
2556 	 */
2557 	error = nfsrv_getclient(clientid, CLOPS_RENEW, &clp, NULL,
2558 	    (nfsquad_t)((u_quad_t)0), 0, nd, p);
2559 	if (!error && (clp->lc_flags & LCL_NEEDSCBNULL) &&
2560 	    clp->lc_program) {
2561 		/*
2562 		 * This happens on the first open for a client
2563 		 * that supports callbacks.
2564 		 */
2565 		NFSUNLOCKSTATE();
2566 		/*
2567 		 * Although nfsrv_docallback() will sleep, clp won't
2568 		 * go away, since they are only removed when the
2569 		 * nfsv4_lock() has blocked the nfsd threads. The
2570 		 * fields in clp can change, but having multiple
2571 		 * threads do this Null callback RPC should be
2572 		 * harmless.
2573 		 */
2574 		cbret = nfsrv_docallback(clp, NFSV4PROC_CBNULL,
2575 		    NULL, 0, NULL, NULL, NULL, p);
2576 		NFSLOCKSTATE();
2577 		clp->lc_flags &= ~LCL_NEEDSCBNULL;
2578 		if (!cbret)
2579 			clp->lc_flags |= LCL_CALLBACKSON;
2580 	}
2581 
2582 	/*
2583 	 * Look up the open owner. See if it needs confirmation and
2584 	 * check the seq#, as required.
2585 	 */
2586 	if (!error)
2587 		nfsrv_getowner(&clp->lc_open, new_stp, &ownerstp);
2588 
2589 	if (error) {
2590 		NFSUNLOCKSTATE();
2591 		printf("Nfsd: openctrl unexpected state err=%d\n",
2592 			error);
2593 		free((caddr_t)new_lfp, M_NFSDLOCKFILE);
2594 		free((caddr_t)new_open, M_NFSDSTATE);
2595 		free((caddr_t)new_deleg, M_NFSDSTATE);
2596 		if (haslock) {
2597 			NFSLOCKV4ROOTMUTEX();
2598 			nfsv4_unlock(&nfsv4rootfs_lock, 1);
2599 			NFSUNLOCKV4ROOTMUTEX();
2600 		}
2601 		error = NFSERR_EXPIRED;
2602 		goto out;
2603 	}
2604 
2605 	if (new_stp->ls_flags & NFSLCK_RECLAIM)
2606 		nfsrv_markstable(clp);
2607 
2608 	/*
2609 	 * Get the structure for the underlying file.
2610 	 */
2611 	if (getfhret)
2612 		error = getfhret;
2613 	else
2614 		error = nfsrv_getlockfile(new_stp->ls_flags, &new_lfp, &lfp,
2615 		    NULL, 0);
2616 	if (new_lfp)
2617 		FREE((caddr_t)new_lfp, M_NFSDLOCKFILE);
2618 	if (error) {
2619 		NFSUNLOCKSTATE();
2620 		printf("Nfsd openctrl unexpected getlockfile err=%d\n",
2621 		    error);
2622 		free((caddr_t)new_open, M_NFSDSTATE);
2623 		free((caddr_t)new_deleg, M_NFSDSTATE);
2624 		if (haslock) {
2625 			NFSLOCKV4ROOTMUTEX();
2626 			nfsv4_unlock(&nfsv4rootfs_lock, 1);
2627 			NFSUNLOCKV4ROOTMUTEX();
2628 		}
2629 		goto out;
2630 	}
2631 
2632 	/*
2633 	 * Search for a conflicting open/share.
2634 	 */
2635 	if (new_stp->ls_flags & NFSLCK_DELEGCUR) {
2636 	    /*
2637 	     * For Delegate_Cur, search for the matching Delegation,
2638 	     * which indicates no conflict.
2639 	     * An old delegation should have been recovered by the
2640 	     * client doing a Claim_DELEGATE_Prev, so I won't let
2641 	     * it match and return NFSERR_EXPIRED. Should I let it
2642 	     * match?
2643 	     */
2644 	    LIST_FOREACH(stp, &lfp->lf_deleg, ls_file) {
2645 		if (!(stp->ls_flags & NFSLCK_OLDDELEG) &&
2646 		    (((nd->nd_flag & ND_NFSV41) != 0 &&
2647 		    stateidp->seqid == 0) ||
2648 		    stateidp->seqid == stp->ls_stateid.seqid) &&
2649 		    !NFSBCMP(stateidp->other, stp->ls_stateid.other,
2650 			NFSX_STATEIDOTHER))
2651 			break;
2652 	    }
2653 	    if (stp == LIST_END(&lfp->lf_deleg) ||
2654 		((new_stp->ls_flags & NFSLCK_WRITEACCESS) &&
2655 		 (stp->ls_flags & NFSLCK_DELEGREAD))) {
2656 		NFSUNLOCKSTATE();
2657 		printf("Nfsd openctrl unexpected expiry\n");
2658 		free((caddr_t)new_open, M_NFSDSTATE);
2659 		free((caddr_t)new_deleg, M_NFSDSTATE);
2660 		if (haslock) {
2661 			NFSLOCKV4ROOTMUTEX();
2662 			nfsv4_unlock(&nfsv4rootfs_lock, 1);
2663 			NFSUNLOCKV4ROOTMUTEX();
2664 		}
2665 		error = NFSERR_EXPIRED;
2666 		goto out;
2667 	    }
2668 
2669 	    /*
2670 	     * Don't issue a Delegation, since one already exists and
2671 	     * delay delegation timeout, as required.
2672 	     */
2673 	    delegate = 0;
2674 	    nfsrv_delaydelegtimeout(stp);
2675 	}
2676 
2677 	/*
2678 	 * Check for access/deny bit conflicts. I also check for the
2679 	 * same owner, since the client might not have bothered to check.
2680 	 * Also, note an open for the same file and owner, if found,
2681 	 * which is all we do here for Delegate_Cur, since conflict
2682 	 * checking is already done.
2683 	 */
2684 	LIST_FOREACH(stp, &lfp->lf_open, ls_file) {
2685 		if (ownerstp && stp->ls_openowner == ownerstp)
2686 			openstp = stp;
2687 		if (!(new_stp->ls_flags & NFSLCK_DELEGCUR)) {
2688 		    /*
2689 		     * If another client has the file open, the only
2690 		     * delegation that can be issued is a Read delegation
2691 		     * and only if it is a Read open with Deny none.
2692 		     */
2693 		    if (clp != stp->ls_clp) {
2694 			if ((stp->ls_flags & NFSLCK_SHAREBITS) ==
2695 			    NFSLCK_READACCESS)
2696 			    writedeleg = 0;
2697 			else
2698 			    delegate = 0;
2699 		    }
2700 		    if(((new_stp->ls_flags & NFSLCK_ACCESSBITS) &
2701 		        ((stp->ls_flags>>NFSLCK_SHIFT) & NFSLCK_ACCESSBITS))||
2702 		       ((stp->ls_flags & NFSLCK_ACCESSBITS) &
2703 		        ((new_stp->ls_flags>>NFSLCK_SHIFT)&NFSLCK_ACCESSBITS))){
2704 			ret = nfsrv_clientconflict(stp->ls_clp,&haslock,vp,p);
2705 			if (ret == 1) {
2706 				/*
2707 				 * nfsrv_clientconflict() unlocks state
2708 				 * when it returns non-zero.
2709 				 */
2710 				free((caddr_t)new_open, M_NFSDSTATE);
2711 				free((caddr_t)new_deleg, M_NFSDSTATE);
2712 				openstp = NULL;
2713 				goto tryagain;
2714 			}
2715 			if (ret == 2)
2716 				error = NFSERR_PERM;
2717 			else if (new_stp->ls_flags & NFSLCK_RECLAIM)
2718 				error = NFSERR_RECLAIMCONFLICT;
2719 			else
2720 				error = NFSERR_SHAREDENIED;
2721 			if (ret == 0)
2722 				NFSUNLOCKSTATE();
2723 			if (haslock) {
2724 				NFSLOCKV4ROOTMUTEX();
2725 				nfsv4_unlock(&nfsv4rootfs_lock, 1);
2726 				NFSUNLOCKV4ROOTMUTEX();
2727 			}
2728 			free((caddr_t)new_open, M_NFSDSTATE);
2729 			free((caddr_t)new_deleg, M_NFSDSTATE);
2730 			printf("nfsd openctrl unexpected client cnfl\n");
2731 			goto out;
2732 		    }
2733 		}
2734 	}
2735 
2736 	/*
2737 	 * Check for a conflicting delegation. If one is found, call
2738 	 * nfsrv_delegconflict() to handle it. If the v4root lock hasn't
2739 	 * been set yet, it will get the lock. Otherwise, it will recall
2740 	 * the delegation. Then, we try try again...
2741 	 * (If NFSLCK_DELEGCUR is set, it has a delegation, so there
2742 	 *  isn't a conflict.)
2743 	 * I currently believe the conflict algorithm to be:
2744 	 * For Open with Read Access and Deny None
2745 	 * - there is a conflict iff a different client has a write delegation
2746 	 * For Open with other Write Access or any Deny except None
2747 	 * - there is a conflict if a different client has any delegation
2748 	 * - there is a conflict if the same client has a read delegation
2749 	 *   (The current consensus is that this last case should be
2750 	 *    considered a conflict since the client with a read delegation
2751 	 *    could have done an Open with ReadAccess and WriteDeny
2752 	 *    locally and then not have checked for the WriteDeny.)
2753 	 */
2754 	if (!(new_stp->ls_flags & (NFSLCK_DELEGPREV | NFSLCK_DELEGCUR))) {
2755 	    stp = LIST_FIRST(&lfp->lf_deleg);
2756 	    while (stp != LIST_END(&lfp->lf_deleg)) {
2757 		nstp = LIST_NEXT(stp, ls_file);
2758 		if (stp->ls_clp != clp && (stp->ls_flags & NFSLCK_DELEGREAD))
2759 			writedeleg = 0;
2760 		else
2761 			delegate = 0;
2762 		if ((readonly && stp->ls_clp != clp &&
2763 		       (stp->ls_flags & NFSLCK_DELEGWRITE)) ||
2764 		    (!readonly && (stp->ls_clp != clp ||
2765 		         (stp->ls_flags & NFSLCK_DELEGREAD)))) {
2766 		    if (new_stp->ls_flags & NFSLCK_RECLAIM) {
2767 			delegate = 2;
2768 		    } else {
2769 			ret = nfsrv_delegconflict(stp, &haslock, p, vp);
2770 			if (ret) {
2771 			    /*
2772 			     * nfsrv_delegconflict() unlocks state
2773 			     * when it returns non-zero.
2774 			     */
2775 			    printf("Nfsd openctrl unexpected deleg cnfl\n");
2776 			    free((caddr_t)new_open, M_NFSDSTATE);
2777 			    free((caddr_t)new_deleg, M_NFSDSTATE);
2778 			    if (ret == -1) {
2779 				openstp = NULL;
2780 				goto tryagain;
2781 			    }
2782 			    error = ret;
2783 			    goto out;
2784 			}
2785 		    }
2786 		}
2787 		stp = nstp;
2788 	    }
2789 	}
2790 
2791 	/*
2792 	 * We only get here if there was no open that conflicted.
2793 	 * If an open for the owner exists, or in the access/deny bits.
2794 	 * Otherwise it is a new open. If the open_owner hasn't been
2795 	 * confirmed, replace the open with the new one needing confirmation,
2796 	 * otherwise add the open.
2797 	 */
2798 	if (new_stp->ls_flags & NFSLCK_DELEGPREV) {
2799 	    /*
2800 	     * Handle NFSLCK_DELEGPREV by searching the old delegations for
2801 	     * a match. If found, just move the old delegation to the current
2802 	     * delegation list and issue open. If not found, return
2803 	     * NFSERR_EXPIRED.
2804 	     */
2805 	    LIST_FOREACH(stp, &clp->lc_olddeleg, ls_list) {
2806 		if (stp->ls_lfp == lfp) {
2807 		    /* Found it */
2808 		    if (stp->ls_clp != clp)
2809 			panic("olddeleg clp");
2810 		    LIST_REMOVE(stp, ls_list);
2811 		    LIST_REMOVE(stp, ls_hash);
2812 		    stp->ls_flags &= ~NFSLCK_OLDDELEG;
2813 		    stp->ls_stateid.seqid = delegstateidp->seqid = 1;
2814 		    stp->ls_stateid.other[0] = delegstateidp->other[0] =
2815 			clp->lc_clientid.lval[0];
2816 		    stp->ls_stateid.other[1] = delegstateidp->other[1] =
2817 			clp->lc_clientid.lval[1];
2818 		    stp->ls_stateid.other[2] = delegstateidp->other[2] =
2819 			nfsrv_nextstateindex(clp);
2820 		    stp->ls_compref = nd->nd_compref;
2821 		    LIST_INSERT_HEAD(&clp->lc_deleg, stp, ls_list);
2822 		    LIST_INSERT_HEAD(NFSSTATEHASH(clp,
2823 			stp->ls_stateid), stp, ls_hash);
2824 		    if (stp->ls_flags & NFSLCK_DELEGWRITE)
2825 			*rflagsp |= NFSV4OPEN_WRITEDELEGATE;
2826 		    else
2827 			*rflagsp |= NFSV4OPEN_READDELEGATE;
2828 		    clp->lc_delegtime = NFSD_MONOSEC +
2829 			nfsrv_lease + NFSRV_LEASEDELTA;
2830 
2831 		    /*
2832 		     * Now, do the associated open.
2833 		     */
2834 		    new_open->ls_stateid.seqid = 1;
2835 		    new_open->ls_stateid.other[0] = clp->lc_clientid.lval[0];
2836 		    new_open->ls_stateid.other[1] = clp->lc_clientid.lval[1];
2837 		    new_open->ls_stateid.other[2] = nfsrv_nextstateindex(clp);
2838 		    new_open->ls_flags = (new_stp->ls_flags&NFSLCK_DENYBITS)|
2839 			NFSLCK_OPEN;
2840 		    if (stp->ls_flags & NFSLCK_DELEGWRITE)
2841 			new_open->ls_flags |= (NFSLCK_READACCESS |
2842 			    NFSLCK_WRITEACCESS);
2843 		    else
2844 			new_open->ls_flags |= NFSLCK_READACCESS;
2845 		    new_open->ls_uid = new_stp->ls_uid;
2846 		    new_open->ls_lfp = lfp;
2847 		    new_open->ls_clp = clp;
2848 		    LIST_INIT(&new_open->ls_open);
2849 		    LIST_INSERT_HEAD(&lfp->lf_open, new_open, ls_file);
2850 		    LIST_INSERT_HEAD(NFSSTATEHASH(clp, new_open->ls_stateid),
2851 			new_open, ls_hash);
2852 		    /*
2853 		     * and handle the open owner
2854 		     */
2855 		    if (ownerstp) {
2856 			new_open->ls_openowner = ownerstp;
2857 			LIST_INSERT_HEAD(&ownerstp->ls_open,new_open,ls_list);
2858 		    } else {
2859 			new_open->ls_openowner = new_stp;
2860 			new_stp->ls_flags = 0;
2861 			nfsrvd_refcache(new_stp->ls_op);
2862 			new_stp->ls_noopens = 0;
2863 			LIST_INIT(&new_stp->ls_open);
2864 			LIST_INSERT_HEAD(&new_stp->ls_open, new_open, ls_list);
2865 			LIST_INSERT_HEAD(&clp->lc_open, new_stp, ls_list);
2866 			*new_stpp = NULL;
2867 			nfsstatsv1.srvopenowners++;
2868 			nfsrv_openpluslock++;
2869 		    }
2870 		    openstp = new_open;
2871 		    new_open = NULL;
2872 		    nfsstatsv1.srvopens++;
2873 		    nfsrv_openpluslock++;
2874 		    break;
2875 		}
2876 	    }
2877 	    if (stp == LIST_END(&clp->lc_olddeleg))
2878 		error = NFSERR_EXPIRED;
2879 	} else if (new_stp->ls_flags & (NFSLCK_DELEGREAD | NFSLCK_DELEGWRITE)) {
2880 	    /*
2881 	     * Scan to see that no delegation for this client and file
2882 	     * doesn't already exist.
2883 	     * There also shouldn't yet be an Open for this file and
2884 	     * openowner.
2885 	     */
2886 	    LIST_FOREACH(stp, &lfp->lf_deleg, ls_file) {
2887 		if (stp->ls_clp == clp)
2888 		    break;
2889 	    }
2890 	    if (stp == LIST_END(&lfp->lf_deleg) && openstp == NULL) {
2891 		/*
2892 		 * This is the Claim_Previous case with a delegation
2893 		 * type != Delegate_None.
2894 		 */
2895 		/*
2896 		 * First, add the delegation. (Although we must issue the
2897 		 * delegation, we can also ask for an immediate return.)
2898 		 */
2899 		new_deleg->ls_stateid.seqid = delegstateidp->seqid = 1;
2900 		new_deleg->ls_stateid.other[0] = delegstateidp->other[0] =
2901 		    clp->lc_clientid.lval[0];
2902 		new_deleg->ls_stateid.other[1] = delegstateidp->other[1] =
2903 		    clp->lc_clientid.lval[1];
2904 		new_deleg->ls_stateid.other[2] = delegstateidp->other[2] =
2905 		    nfsrv_nextstateindex(clp);
2906 		if (new_stp->ls_flags & NFSLCK_DELEGWRITE) {
2907 		    new_deleg->ls_flags = (NFSLCK_DELEGWRITE |
2908 			NFSLCK_READACCESS | NFSLCK_WRITEACCESS);
2909 		    *rflagsp |= NFSV4OPEN_WRITEDELEGATE;
2910 		} else {
2911 		    new_deleg->ls_flags = (NFSLCK_DELEGREAD |
2912 			NFSLCK_READACCESS);
2913 		    *rflagsp |= NFSV4OPEN_READDELEGATE;
2914 		}
2915 		new_deleg->ls_uid = new_stp->ls_uid;
2916 		new_deleg->ls_lfp = lfp;
2917 		new_deleg->ls_clp = clp;
2918 		new_deleg->ls_filerev = filerev;
2919 		new_deleg->ls_compref = nd->nd_compref;
2920 		LIST_INSERT_HEAD(&lfp->lf_deleg, new_deleg, ls_file);
2921 		LIST_INSERT_HEAD(NFSSTATEHASH(clp,
2922 		    new_deleg->ls_stateid), new_deleg, ls_hash);
2923 		LIST_INSERT_HEAD(&clp->lc_deleg, new_deleg, ls_list);
2924 		new_deleg = NULL;
2925 		if (delegate == 2 || nfsrv_issuedelegs == 0 ||
2926 		    (clp->lc_flags & (LCL_CALLBACKSON | LCL_CBDOWN)) !=
2927 		     LCL_CALLBACKSON ||
2928 		    NFSRV_V4DELEGLIMIT(nfsrv_delegatecnt) ||
2929 		    !NFSVNO_DELEGOK(vp))
2930 		    *rflagsp |= NFSV4OPEN_RECALL;
2931 		nfsstatsv1.srvdelegates++;
2932 		nfsrv_openpluslock++;
2933 		nfsrv_delegatecnt++;
2934 
2935 		/*
2936 		 * Now, do the associated open.
2937 		 */
2938 		new_open->ls_stateid.seqid = 1;
2939 		new_open->ls_stateid.other[0] = clp->lc_clientid.lval[0];
2940 		new_open->ls_stateid.other[1] = clp->lc_clientid.lval[1];
2941 		new_open->ls_stateid.other[2] = nfsrv_nextstateindex(clp);
2942 		new_open->ls_flags = (new_stp->ls_flags & NFSLCK_DENYBITS) |
2943 		    NFSLCK_OPEN;
2944 		if (new_stp->ls_flags & NFSLCK_DELEGWRITE)
2945 			new_open->ls_flags |= (NFSLCK_READACCESS |
2946 			    NFSLCK_WRITEACCESS);
2947 		else
2948 			new_open->ls_flags |= NFSLCK_READACCESS;
2949 		new_open->ls_uid = new_stp->ls_uid;
2950 		new_open->ls_lfp = lfp;
2951 		new_open->ls_clp = clp;
2952 		LIST_INIT(&new_open->ls_open);
2953 		LIST_INSERT_HEAD(&lfp->lf_open, new_open, ls_file);
2954 		LIST_INSERT_HEAD(NFSSTATEHASH(clp, new_open->ls_stateid),
2955 		   new_open, ls_hash);
2956 		/*
2957 		 * and handle the open owner
2958 		 */
2959 		if (ownerstp) {
2960 		    new_open->ls_openowner = ownerstp;
2961 		    LIST_INSERT_HEAD(&ownerstp->ls_open, new_open, ls_list);
2962 		} else {
2963 		    new_open->ls_openowner = new_stp;
2964 		    new_stp->ls_flags = 0;
2965 		    nfsrvd_refcache(new_stp->ls_op);
2966 		    new_stp->ls_noopens = 0;
2967 		    LIST_INIT(&new_stp->ls_open);
2968 		    LIST_INSERT_HEAD(&new_stp->ls_open, new_open, ls_list);
2969 		    LIST_INSERT_HEAD(&clp->lc_open, new_stp, ls_list);
2970 		    *new_stpp = NULL;
2971 		    nfsstatsv1.srvopenowners++;
2972 		    nfsrv_openpluslock++;
2973 		}
2974 		openstp = new_open;
2975 		new_open = NULL;
2976 		nfsstatsv1.srvopens++;
2977 		nfsrv_openpluslock++;
2978 	    } else {
2979 		error = NFSERR_RECLAIMCONFLICT;
2980 	    }
2981 	} else if (ownerstp) {
2982 		if (ownerstp->ls_flags & NFSLCK_NEEDSCONFIRM) {
2983 		    /* Replace the open */
2984 		    if (ownerstp->ls_op)
2985 			nfsrvd_derefcache(ownerstp->ls_op);
2986 		    ownerstp->ls_op = new_stp->ls_op;
2987 		    nfsrvd_refcache(ownerstp->ls_op);
2988 		    ownerstp->ls_seq = new_stp->ls_seq;
2989 		    *rflagsp |= NFSV4OPEN_RESULTCONFIRM;
2990 		    stp = LIST_FIRST(&ownerstp->ls_open);
2991 		    stp->ls_flags = (new_stp->ls_flags & NFSLCK_SHAREBITS) |
2992 			NFSLCK_OPEN;
2993 		    stp->ls_stateid.seqid = 1;
2994 		    stp->ls_uid = new_stp->ls_uid;
2995 		    if (lfp != stp->ls_lfp) {
2996 			LIST_REMOVE(stp, ls_file);
2997 			LIST_INSERT_HEAD(&lfp->lf_open, stp, ls_file);
2998 			stp->ls_lfp = lfp;
2999 		    }
3000 		    openstp = stp;
3001 		} else if (openstp) {
3002 		    openstp->ls_flags |= (new_stp->ls_flags & NFSLCK_SHAREBITS);
3003 		    openstp->ls_stateid.seqid++;
3004 		    if ((nd->nd_flag & ND_NFSV41) != 0 &&
3005 			openstp->ls_stateid.seqid == 0)
3006 			openstp->ls_stateid.seqid = 1;
3007 
3008 		    /*
3009 		     * This is where we can choose to issue a delegation.
3010 		     */
3011 		    if (delegate == 0 || writedeleg == 0 ||
3012 			NFSVNO_EXRDONLY(exp) || (readonly != 0 &&
3013 			nfsrv_writedelegifpos == 0) ||
3014 			!NFSVNO_DELEGOK(vp) ||
3015 			(new_stp->ls_flags & NFSLCK_WANTRDELEG) != 0 ||
3016 			(clp->lc_flags & (LCL_CALLBACKSON | LCL_CBDOWN)) !=
3017 			 LCL_CALLBACKSON)
3018 			*rflagsp |= NFSV4OPEN_WDCONTENTION;
3019 		    else if (nfsrv_issuedelegs == 0 ||
3020 			NFSRV_V4DELEGLIMIT(nfsrv_delegatecnt))
3021 			*rflagsp |= NFSV4OPEN_WDRESOURCE;
3022 		    else if ((new_stp->ls_flags & NFSLCK_WANTNODELEG) != 0)
3023 			*rflagsp |= NFSV4OPEN_WDNOTWANTED;
3024 		    else {
3025 			new_deleg->ls_stateid.seqid = delegstateidp->seqid = 1;
3026 			new_deleg->ls_stateid.other[0] = delegstateidp->other[0]
3027 			    = clp->lc_clientid.lval[0];
3028 			new_deleg->ls_stateid.other[1] = delegstateidp->other[1]
3029 			    = clp->lc_clientid.lval[1];
3030 			new_deleg->ls_stateid.other[2] = delegstateidp->other[2]
3031 			    = nfsrv_nextstateindex(clp);
3032 			new_deleg->ls_flags = (NFSLCK_DELEGWRITE |
3033 			    NFSLCK_READACCESS | NFSLCK_WRITEACCESS);
3034 			*rflagsp |= NFSV4OPEN_WRITEDELEGATE;
3035 			new_deleg->ls_uid = new_stp->ls_uid;
3036 			new_deleg->ls_lfp = lfp;
3037 			new_deleg->ls_clp = clp;
3038 			new_deleg->ls_filerev = filerev;
3039 			new_deleg->ls_compref = nd->nd_compref;
3040 			LIST_INSERT_HEAD(&lfp->lf_deleg, new_deleg, ls_file);
3041 			LIST_INSERT_HEAD(NFSSTATEHASH(clp,
3042 			    new_deleg->ls_stateid), new_deleg, ls_hash);
3043 			LIST_INSERT_HEAD(&clp->lc_deleg, new_deleg, ls_list);
3044 			new_deleg = NULL;
3045 			nfsstatsv1.srvdelegates++;
3046 			nfsrv_openpluslock++;
3047 			nfsrv_delegatecnt++;
3048 		    }
3049 		} else {
3050 		    new_open->ls_stateid.seqid = 1;
3051 		    new_open->ls_stateid.other[0] = clp->lc_clientid.lval[0];
3052 		    new_open->ls_stateid.other[1] = clp->lc_clientid.lval[1];
3053 		    new_open->ls_stateid.other[2] = nfsrv_nextstateindex(clp);
3054 		    new_open->ls_flags = (new_stp->ls_flags & NFSLCK_SHAREBITS)|
3055 			NFSLCK_OPEN;
3056 		    new_open->ls_uid = new_stp->ls_uid;
3057 		    new_open->ls_openowner = ownerstp;
3058 		    new_open->ls_lfp = lfp;
3059 		    new_open->ls_clp = clp;
3060 		    LIST_INIT(&new_open->ls_open);
3061 		    LIST_INSERT_HEAD(&lfp->lf_open, new_open, ls_file);
3062 		    LIST_INSERT_HEAD(&ownerstp->ls_open, new_open, ls_list);
3063 		    LIST_INSERT_HEAD(NFSSTATEHASH(clp, new_open->ls_stateid),
3064 			new_open, ls_hash);
3065 		    openstp = new_open;
3066 		    new_open = NULL;
3067 		    nfsstatsv1.srvopens++;
3068 		    nfsrv_openpluslock++;
3069 
3070 		    /*
3071 		     * This is where we can choose to issue a delegation.
3072 		     */
3073 		    if (delegate == 0 || (writedeleg == 0 && readonly == 0) ||
3074 			!NFSVNO_DELEGOK(vp) ||
3075 			(clp->lc_flags & (LCL_CALLBACKSON | LCL_CBDOWN)) !=
3076 			 LCL_CALLBACKSON)
3077 			*rflagsp |= NFSV4OPEN_WDCONTENTION;
3078 		    else if (nfsrv_issuedelegs == 0 ||
3079 			NFSRV_V4DELEGLIMIT(nfsrv_delegatecnt))
3080 			*rflagsp |= NFSV4OPEN_WDRESOURCE;
3081 		    else if ((new_stp->ls_flags & NFSLCK_WANTNODELEG) != 0)
3082 			*rflagsp |= NFSV4OPEN_WDNOTWANTED;
3083 		    else {
3084 			new_deleg->ls_stateid.seqid = delegstateidp->seqid = 1;
3085 			new_deleg->ls_stateid.other[0] = delegstateidp->other[0]
3086 			    = clp->lc_clientid.lval[0];
3087 			new_deleg->ls_stateid.other[1] = delegstateidp->other[1]
3088 			    = clp->lc_clientid.lval[1];
3089 			new_deleg->ls_stateid.other[2] = delegstateidp->other[2]
3090 			    = nfsrv_nextstateindex(clp);
3091 			if (writedeleg && !NFSVNO_EXRDONLY(exp) &&
3092 			    (nfsrv_writedelegifpos || !readonly) &&
3093 			    (new_stp->ls_flags & NFSLCK_WANTRDELEG) == 0) {
3094 			    new_deleg->ls_flags = (NFSLCK_DELEGWRITE |
3095 				NFSLCK_READACCESS | NFSLCK_WRITEACCESS);
3096 			    *rflagsp |= NFSV4OPEN_WRITEDELEGATE;
3097 			} else {
3098 			    new_deleg->ls_flags = (NFSLCK_DELEGREAD |
3099 				NFSLCK_READACCESS);
3100 			    *rflagsp |= NFSV4OPEN_READDELEGATE;
3101 			}
3102 			new_deleg->ls_uid = new_stp->ls_uid;
3103 			new_deleg->ls_lfp = lfp;
3104 			new_deleg->ls_clp = clp;
3105 			new_deleg->ls_filerev = filerev;
3106 			new_deleg->ls_compref = nd->nd_compref;
3107 			LIST_INSERT_HEAD(&lfp->lf_deleg, new_deleg, ls_file);
3108 			LIST_INSERT_HEAD(NFSSTATEHASH(clp,
3109 			    new_deleg->ls_stateid), new_deleg, ls_hash);
3110 			LIST_INSERT_HEAD(&clp->lc_deleg, new_deleg, ls_list);
3111 			new_deleg = NULL;
3112 			nfsstatsv1.srvdelegates++;
3113 			nfsrv_openpluslock++;
3114 			nfsrv_delegatecnt++;
3115 		    }
3116 		}
3117 	} else {
3118 		/*
3119 		 * New owner case. Start the open_owner sequence with a
3120 		 * Needs confirmation (unless a reclaim) and hang the
3121 		 * new open off it.
3122 		 */
3123 		new_open->ls_stateid.seqid = 1;
3124 		new_open->ls_stateid.other[0] = clp->lc_clientid.lval[0];
3125 		new_open->ls_stateid.other[1] = clp->lc_clientid.lval[1];
3126 		new_open->ls_stateid.other[2] = nfsrv_nextstateindex(clp);
3127 		new_open->ls_flags = (new_stp->ls_flags & NFSLCK_SHAREBITS) |
3128 		    NFSLCK_OPEN;
3129 		new_open->ls_uid = new_stp->ls_uid;
3130 		LIST_INIT(&new_open->ls_open);
3131 		new_open->ls_openowner = new_stp;
3132 		new_open->ls_lfp = lfp;
3133 		new_open->ls_clp = clp;
3134 		LIST_INSERT_HEAD(&lfp->lf_open, new_open, ls_file);
3135 		if (new_stp->ls_flags & NFSLCK_RECLAIM) {
3136 			new_stp->ls_flags = 0;
3137 		} else if ((nd->nd_flag & ND_NFSV41) != 0) {
3138 			/* NFSv4.1 never needs confirmation. */
3139 			new_stp->ls_flags = 0;
3140 
3141 			/*
3142 			 * This is where we can choose to issue a delegation.
3143 			 */
3144 			if (delegate && nfsrv_issuedelegs &&
3145 			    (writedeleg || readonly) &&
3146 			    (clp->lc_flags & (LCL_CALLBACKSON | LCL_CBDOWN)) ==
3147 			     LCL_CALLBACKSON &&
3148 			    !NFSRV_V4DELEGLIMIT(nfsrv_delegatecnt) &&
3149 			    NFSVNO_DELEGOK(vp) &&
3150 			    ((nd->nd_flag & ND_NFSV41) == 0 ||
3151 			     (new_stp->ls_flags & NFSLCK_WANTNODELEG) == 0)) {
3152 				new_deleg->ls_stateid.seqid =
3153 				    delegstateidp->seqid = 1;
3154 				new_deleg->ls_stateid.other[0] =
3155 				    delegstateidp->other[0]
3156 				    = clp->lc_clientid.lval[0];
3157 				new_deleg->ls_stateid.other[1] =
3158 				    delegstateidp->other[1]
3159 				    = clp->lc_clientid.lval[1];
3160 				new_deleg->ls_stateid.other[2] =
3161 				    delegstateidp->other[2]
3162 				    = nfsrv_nextstateindex(clp);
3163 				if (writedeleg && !NFSVNO_EXRDONLY(exp) &&
3164 				    (nfsrv_writedelegifpos || !readonly) &&
3165 				    ((nd->nd_flag & ND_NFSV41) == 0 ||
3166 				     (new_stp->ls_flags & NFSLCK_WANTRDELEG) ==
3167 				     0)) {
3168 					new_deleg->ls_flags =
3169 					    (NFSLCK_DELEGWRITE |
3170 					     NFSLCK_READACCESS |
3171 					     NFSLCK_WRITEACCESS);
3172 					*rflagsp |= NFSV4OPEN_WRITEDELEGATE;
3173 				} else {
3174 					new_deleg->ls_flags =
3175 					    (NFSLCK_DELEGREAD |
3176 					     NFSLCK_READACCESS);
3177 					*rflagsp |= NFSV4OPEN_READDELEGATE;
3178 				}
3179 				new_deleg->ls_uid = new_stp->ls_uid;
3180 				new_deleg->ls_lfp = lfp;
3181 				new_deleg->ls_clp = clp;
3182 				new_deleg->ls_filerev = filerev;
3183 				new_deleg->ls_compref = nd->nd_compref;
3184 				LIST_INSERT_HEAD(&lfp->lf_deleg, new_deleg,
3185 				    ls_file);
3186 				LIST_INSERT_HEAD(NFSSTATEHASH(clp,
3187 				    new_deleg->ls_stateid), new_deleg, ls_hash);
3188 				LIST_INSERT_HEAD(&clp->lc_deleg, new_deleg,
3189 				    ls_list);
3190 				new_deleg = NULL;
3191 				nfsstatsv1.srvdelegates++;
3192 				nfsrv_openpluslock++;
3193 				nfsrv_delegatecnt++;
3194 			}
3195 			/*
3196 			 * Since NFSv4.1 never does an OpenConfirm, the first
3197 			 * open state will be acquired here.
3198 			 */
3199 			if (!(clp->lc_flags & LCL_STAMPEDSTABLE)) {
3200 				clp->lc_flags |= LCL_STAMPEDSTABLE;
3201 				len = clp->lc_idlen;
3202 				NFSBCOPY(clp->lc_id, clidp, len);
3203 				gotstate = 1;
3204 			}
3205 		} else {
3206 			*rflagsp |= NFSV4OPEN_RESULTCONFIRM;
3207 			new_stp->ls_flags = NFSLCK_NEEDSCONFIRM;
3208 		}
3209 		nfsrvd_refcache(new_stp->ls_op);
3210 		new_stp->ls_noopens = 0;
3211 		LIST_INIT(&new_stp->ls_open);
3212 		LIST_INSERT_HEAD(&new_stp->ls_open, new_open, ls_list);
3213 		LIST_INSERT_HEAD(&clp->lc_open, new_stp, ls_list);
3214 		LIST_INSERT_HEAD(NFSSTATEHASH(clp, new_open->ls_stateid),
3215 		    new_open, ls_hash);
3216 		openstp = new_open;
3217 		new_open = NULL;
3218 		*new_stpp = NULL;
3219 		nfsstatsv1.srvopens++;
3220 		nfsrv_openpluslock++;
3221 		nfsstatsv1.srvopenowners++;
3222 		nfsrv_openpluslock++;
3223 	}
3224 	if (!error) {
3225 		stateidp->seqid = openstp->ls_stateid.seqid;
3226 		stateidp->other[0] = openstp->ls_stateid.other[0];
3227 		stateidp->other[1] = openstp->ls_stateid.other[1];
3228 		stateidp->other[2] = openstp->ls_stateid.other[2];
3229 	}
3230 	NFSUNLOCKSTATE();
3231 	if (haslock) {
3232 		NFSLOCKV4ROOTMUTEX();
3233 		nfsv4_unlock(&nfsv4rootfs_lock, 1);
3234 		NFSUNLOCKV4ROOTMUTEX();
3235 	}
3236 	if (new_open)
3237 		FREE((caddr_t)new_open, M_NFSDSTATE);
3238 	if (new_deleg)
3239 		FREE((caddr_t)new_deleg, M_NFSDSTATE);
3240 
3241 	/*
3242 	 * If the NFSv4.1 client just acquired its first open, write a timestamp
3243 	 * to the stable storage file.
3244 	 */
3245 	if (gotstate != 0) {
3246 		nfsrv_writestable(clidp, len, NFSNST_NEWSTATE, p);
3247 		nfsrv_backupstable();
3248 	}
3249 
3250 out:
3251 	free(clidp, M_TEMP);
3252 	NFSEXITCODE2(error, nd);
3253 	return (error);
3254 }
3255 
3256 /*
3257  * Open update. Does the confirm, downgrade and close.
3258  */
3259 APPLESTATIC int
3260 nfsrv_openupdate(vnode_t vp, struct nfsstate *new_stp, nfsquad_t clientid,
3261     nfsv4stateid_t *stateidp, struct nfsrv_descript *nd, NFSPROC_T *p)
3262 {
3263 	struct nfsstate *stp, *ownerstp;
3264 	struct nfsclient *clp;
3265 	struct nfslockfile *lfp;
3266 	u_int32_t bits;
3267 	int error = 0, gotstate = 0, len = 0;
3268 	u_char *clidp = NULL;
3269 
3270 	/*
3271 	 * Check for restart conditions (client and server).
3272 	 */
3273 	error = nfsrv_checkrestart(clientid, new_stp->ls_flags,
3274 	    &new_stp->ls_stateid, 0);
3275 	if (error)
3276 		goto out;
3277 
3278 	clidp = malloc(NFSV4_OPAQUELIMIT, M_TEMP, M_WAITOK);
3279 	NFSLOCKSTATE();
3280 	/*
3281 	 * Get the open structure via clientid and stateid.
3282 	 */
3283 	error = nfsrv_getclient(clientid, CLOPS_RENEW, &clp, NULL,
3284 	    (nfsquad_t)((u_quad_t)0), 0, nd, p);
3285 	if (!error)
3286 		error = nfsrv_getstate(clp, &new_stp->ls_stateid,
3287 		    new_stp->ls_flags, &stp);
3288 
3289 	/*
3290 	 * Sanity check the open.
3291 	 */
3292 	if (!error && (!(stp->ls_flags & NFSLCK_OPEN) ||
3293 		(!(new_stp->ls_flags & NFSLCK_CONFIRM) &&
3294 		 (stp->ls_openowner->ls_flags & NFSLCK_NEEDSCONFIRM)) ||
3295 		((new_stp->ls_flags & NFSLCK_CONFIRM) &&
3296 		 (!(stp->ls_openowner->ls_flags & NFSLCK_NEEDSCONFIRM)))))
3297 		error = NFSERR_BADSTATEID;
3298 
3299 	if (!error)
3300 		error = nfsrv_checkseqid(nd, new_stp->ls_seq,
3301 		    stp->ls_openowner, new_stp->ls_op);
3302 	if (!error && stp->ls_stateid.seqid != new_stp->ls_stateid.seqid &&
3303 	    (((nd->nd_flag & ND_NFSV41) == 0 &&
3304 	      !(new_stp->ls_flags & NFSLCK_CONFIRM)) ||
3305 	     ((nd->nd_flag & ND_NFSV41) != 0 &&
3306 	      new_stp->ls_stateid.seqid != 0)))
3307 		error = NFSERR_OLDSTATEID;
3308 	if (!error && vnode_vtype(vp) != VREG) {
3309 		if (vnode_vtype(vp) == VDIR)
3310 			error = NFSERR_ISDIR;
3311 		else
3312 			error = NFSERR_INVAL;
3313 	}
3314 
3315 	if (error) {
3316 		/*
3317 		 * If a client tries to confirm an Open with a bad
3318 		 * seqid# and there are no byte range locks or other Opens
3319 		 * on the openowner, just throw it away, so the next use of the
3320 		 * openowner will start a fresh seq#.
3321 		 */
3322 		if (error == NFSERR_BADSEQID &&
3323 		    (new_stp->ls_flags & NFSLCK_CONFIRM) &&
3324 		    nfsrv_nootherstate(stp))
3325 			nfsrv_freeopenowner(stp->ls_openowner, 0, p);
3326 		NFSUNLOCKSTATE();
3327 		goto out;
3328 	}
3329 
3330 	/*
3331 	 * Set the return stateid.
3332 	 */
3333 	stateidp->seqid = stp->ls_stateid.seqid + 1;
3334 	if ((nd->nd_flag & ND_NFSV41) != 0 && stateidp->seqid == 0)
3335 		stateidp->seqid = 1;
3336 	stateidp->other[0] = stp->ls_stateid.other[0];
3337 	stateidp->other[1] = stp->ls_stateid.other[1];
3338 	stateidp->other[2] = stp->ls_stateid.other[2];
3339 	/*
3340 	 * Now, handle the three cases.
3341 	 */
3342 	if (new_stp->ls_flags & NFSLCK_CONFIRM) {
3343 		/*
3344 		 * If the open doesn't need confirmation, it seems to me that
3345 		 * there is a client error, but I'll just log it and keep going?
3346 		 */
3347 		if (!(stp->ls_openowner->ls_flags & NFSLCK_NEEDSCONFIRM))
3348 			printf("Nfsv4d: stray open confirm\n");
3349 		stp->ls_openowner->ls_flags = 0;
3350 		stp->ls_stateid.seqid++;
3351 		if ((nd->nd_flag & ND_NFSV41) != 0 &&
3352 		    stp->ls_stateid.seqid == 0)
3353 			stp->ls_stateid.seqid = 1;
3354 		if (!(clp->lc_flags & LCL_STAMPEDSTABLE)) {
3355 			clp->lc_flags |= LCL_STAMPEDSTABLE;
3356 			len = clp->lc_idlen;
3357 			NFSBCOPY(clp->lc_id, clidp, len);
3358 			gotstate = 1;
3359 		}
3360 		NFSUNLOCKSTATE();
3361 	} else if (new_stp->ls_flags & NFSLCK_CLOSE) {
3362 		ownerstp = stp->ls_openowner;
3363 		lfp = stp->ls_lfp;
3364 		if (nfsrv_dolocallocks != 0 && !LIST_EMPTY(&stp->ls_open)) {
3365 			/* Get the lf lock */
3366 			nfsrv_locklf(lfp);
3367 			NFSUNLOCKSTATE();
3368 			ASSERT_VOP_ELOCKED(vp, "nfsrv_openupdate");
3369 			NFSVOPUNLOCK(vp, 0);
3370 			if (nfsrv_freeopen(stp, vp, 1, p) == 0) {
3371 				NFSLOCKSTATE();
3372 				nfsrv_unlocklf(lfp);
3373 				NFSUNLOCKSTATE();
3374 			}
3375 			NFSVOPLOCK(vp, LK_EXCLUSIVE | LK_RETRY);
3376 		} else {
3377 			(void) nfsrv_freeopen(stp, NULL, 0, p);
3378 			NFSUNLOCKSTATE();
3379 		}
3380 	} else {
3381 		/*
3382 		 * Update the share bits, making sure that the new set are a
3383 		 * subset of the old ones.
3384 		 */
3385 		bits = (new_stp->ls_flags & NFSLCK_SHAREBITS);
3386 		if (~(stp->ls_flags) & bits) {
3387 			NFSUNLOCKSTATE();
3388 			error = NFSERR_INVAL;
3389 			goto out;
3390 		}
3391 		stp->ls_flags = (bits | NFSLCK_OPEN);
3392 		stp->ls_stateid.seqid++;
3393 		if ((nd->nd_flag & ND_NFSV41) != 0 &&
3394 		    stp->ls_stateid.seqid == 0)
3395 			stp->ls_stateid.seqid = 1;
3396 		NFSUNLOCKSTATE();
3397 	}
3398 
3399 	/*
3400 	 * If the client just confirmed its first open, write a timestamp
3401 	 * to the stable storage file.
3402 	 */
3403 	if (gotstate != 0) {
3404 		nfsrv_writestable(clidp, len, NFSNST_NEWSTATE, p);
3405 		nfsrv_backupstable();
3406 	}
3407 
3408 out:
3409 	free(clidp, M_TEMP);
3410 	NFSEXITCODE2(error, nd);
3411 	return (error);
3412 }
3413 
3414 /*
3415  * Delegation update. Does the purge and return.
3416  */
3417 APPLESTATIC int
3418 nfsrv_delegupdate(struct nfsrv_descript *nd, nfsquad_t clientid,
3419     nfsv4stateid_t *stateidp, vnode_t vp, int op, struct ucred *cred,
3420     NFSPROC_T *p)
3421 {
3422 	struct nfsstate *stp;
3423 	struct nfsclient *clp;
3424 	int error = 0;
3425 	fhandle_t fh;
3426 
3427 	/*
3428 	 * Do a sanity check against the file handle for DelegReturn.
3429 	 */
3430 	if (vp) {
3431 		error = nfsvno_getfh(vp, &fh, p);
3432 		if (error)
3433 			goto out;
3434 	}
3435 	/*
3436 	 * Check for restart conditions (client and server).
3437 	 */
3438 	if (op == NFSV4OP_DELEGRETURN)
3439 		error = nfsrv_checkrestart(clientid, NFSLCK_DELEGRETURN,
3440 			stateidp, 0);
3441 	else
3442 		error = nfsrv_checkrestart(clientid, NFSLCK_DELEGPURGE,
3443 			stateidp, 0);
3444 
3445 	NFSLOCKSTATE();
3446 	/*
3447 	 * Get the open structure via clientid and stateid.
3448 	 */
3449 	if (!error)
3450 	    error = nfsrv_getclient(clientid, CLOPS_RENEW, &clp, NULL,
3451 		(nfsquad_t)((u_quad_t)0), 0, nd, p);
3452 	if (error) {
3453 		if (error == NFSERR_CBPATHDOWN)
3454 			error = 0;
3455 		if (error == NFSERR_STALECLIENTID && op == NFSV4OP_DELEGRETURN)
3456 			error = NFSERR_STALESTATEID;
3457 	}
3458 	if (!error && op == NFSV4OP_DELEGRETURN) {
3459 	    error = nfsrv_getstate(clp, stateidp, NFSLCK_DELEGRETURN, &stp);
3460 	    if (!error && stp->ls_stateid.seqid != stateidp->seqid &&
3461 		((nd->nd_flag & ND_NFSV41) == 0 || stateidp->seqid != 0))
3462 		error = NFSERR_OLDSTATEID;
3463 	}
3464 	/*
3465 	 * NFSERR_EXPIRED means that the state has gone away,
3466 	 * so Delegations have been purged. Just return ok.
3467 	 */
3468 	if (error == NFSERR_EXPIRED && op == NFSV4OP_DELEGPURGE) {
3469 		NFSUNLOCKSTATE();
3470 		error = 0;
3471 		goto out;
3472 	}
3473 	if (error) {
3474 		NFSUNLOCKSTATE();
3475 		goto out;
3476 	}
3477 
3478 	if (op == NFSV4OP_DELEGRETURN) {
3479 		if (NFSBCMP((caddr_t)&fh, (caddr_t)&stp->ls_lfp->lf_fh,
3480 		    sizeof (fhandle_t))) {
3481 			NFSUNLOCKSTATE();
3482 			error = NFSERR_BADSTATEID;
3483 			goto out;
3484 		}
3485 		nfsrv_freedeleg(stp);
3486 	} else {
3487 		nfsrv_freedeleglist(&clp->lc_olddeleg);
3488 	}
3489 	NFSUNLOCKSTATE();
3490 	error = 0;
3491 
3492 out:
3493 	NFSEXITCODE(error);
3494 	return (error);
3495 }
3496 
3497 /*
3498  * Release lock owner.
3499  */
3500 APPLESTATIC int
3501 nfsrv_releaselckown(struct nfsstate *new_stp, nfsquad_t clientid,
3502     NFSPROC_T *p)
3503 {
3504 	struct nfsstate *stp, *nstp, *openstp, *ownstp;
3505 	struct nfsclient *clp;
3506 	int error = 0;
3507 
3508 	/*
3509 	 * Check for restart conditions (client and server).
3510 	 */
3511 	error = nfsrv_checkrestart(clientid, new_stp->ls_flags,
3512 	    &new_stp->ls_stateid, 0);
3513 	if (error)
3514 		goto out;
3515 
3516 	NFSLOCKSTATE();
3517 	/*
3518 	 * Get the lock owner by name.
3519 	 */
3520 	error = nfsrv_getclient(clientid, CLOPS_RENEW, &clp, NULL,
3521 	    (nfsquad_t)((u_quad_t)0), 0, NULL, p);
3522 	if (error) {
3523 		NFSUNLOCKSTATE();
3524 		goto out;
3525 	}
3526 	LIST_FOREACH(ownstp, &clp->lc_open, ls_list) {
3527 	    LIST_FOREACH(openstp, &ownstp->ls_open, ls_list) {
3528 		stp = LIST_FIRST(&openstp->ls_open);
3529 		while (stp != LIST_END(&openstp->ls_open)) {
3530 		    nstp = LIST_NEXT(stp, ls_list);
3531 		    /*
3532 		     * If the owner matches, check for locks and
3533 		     * then free or return an error.
3534 		     */
3535 		    if (stp->ls_ownerlen == new_stp->ls_ownerlen &&
3536 			!NFSBCMP(stp->ls_owner, new_stp->ls_owner,
3537 			 stp->ls_ownerlen)){
3538 			if (LIST_EMPTY(&stp->ls_lock)) {
3539 			    nfsrv_freelockowner(stp, NULL, 0, p);
3540 			} else {
3541 			    NFSUNLOCKSTATE();
3542 			    error = NFSERR_LOCKSHELD;
3543 			    goto out;
3544 			}
3545 		    }
3546 		    stp = nstp;
3547 		}
3548 	    }
3549 	}
3550 	NFSUNLOCKSTATE();
3551 
3552 out:
3553 	NFSEXITCODE(error);
3554 	return (error);
3555 }
3556 
3557 /*
3558  * Get the file handle for a lock structure.
3559  */
3560 static int
3561 nfsrv_getlockfh(vnode_t vp, u_short flags, struct nfslockfile *new_lfp,
3562     fhandle_t *nfhp, NFSPROC_T *p)
3563 {
3564 	fhandle_t *fhp = NULL;
3565 	int error;
3566 
3567 	/*
3568 	 * For lock, use the new nfslock structure, otherwise just
3569 	 * a fhandle_t on the stack.
3570 	 */
3571 	if (flags & NFSLCK_OPEN) {
3572 		KASSERT(new_lfp != NULL, ("nfsrv_getlockfh: new_lfp NULL"));
3573 		fhp = &new_lfp->lf_fh;
3574 	} else if (nfhp) {
3575 		fhp = nfhp;
3576 	} else {
3577 		panic("nfsrv_getlockfh");
3578 	}
3579 	error = nfsvno_getfh(vp, fhp, p);
3580 	NFSEXITCODE(error);
3581 	return (error);
3582 }
3583 
3584 /*
3585  * Get an nfs lock structure. Allocate one, as required, and return a
3586  * pointer to it.
3587  * Returns an NFSERR_xxx upon failure or -1 to indicate no current lock.
3588  */
3589 static int
3590 nfsrv_getlockfile(u_short flags, struct nfslockfile **new_lfpp,
3591     struct nfslockfile **lfpp, fhandle_t *nfhp, int lockit)
3592 {
3593 	struct nfslockfile *lfp;
3594 	fhandle_t *fhp = NULL, *tfhp;
3595 	struct nfslockhashhead *hp;
3596 	struct nfslockfile *new_lfp = NULL;
3597 
3598 	/*
3599 	 * For lock, use the new nfslock structure, otherwise just
3600 	 * a fhandle_t on the stack.
3601 	 */
3602 	if (flags & NFSLCK_OPEN) {
3603 		new_lfp = *new_lfpp;
3604 		fhp = &new_lfp->lf_fh;
3605 	} else if (nfhp) {
3606 		fhp = nfhp;
3607 	} else {
3608 		panic("nfsrv_getlockfile");
3609 	}
3610 
3611 	hp = NFSLOCKHASH(fhp);
3612 	LIST_FOREACH(lfp, hp, lf_hash) {
3613 		tfhp = &lfp->lf_fh;
3614 		if (NFSVNO_CMPFH(fhp, tfhp)) {
3615 			if (lockit)
3616 				nfsrv_locklf(lfp);
3617 			*lfpp = lfp;
3618 			return (0);
3619 		}
3620 	}
3621 	if (!(flags & NFSLCK_OPEN))
3622 		return (-1);
3623 
3624 	/*
3625 	 * No match, so chain the new one into the list.
3626 	 */
3627 	LIST_INIT(&new_lfp->lf_open);
3628 	LIST_INIT(&new_lfp->lf_lock);
3629 	LIST_INIT(&new_lfp->lf_deleg);
3630 	LIST_INIT(&new_lfp->lf_locallock);
3631 	LIST_INIT(&new_lfp->lf_rollback);
3632 	new_lfp->lf_locallock_lck.nfslock_usecnt = 0;
3633 	new_lfp->lf_locallock_lck.nfslock_lock = 0;
3634 	new_lfp->lf_usecount = 0;
3635 	LIST_INSERT_HEAD(hp, new_lfp, lf_hash);
3636 	*lfpp = new_lfp;
3637 	*new_lfpp = NULL;
3638 	return (0);
3639 }
3640 
3641 /*
3642  * This function adds a nfslock lock structure to the list for the associated
3643  * nfsstate and nfslockfile structures. It will be inserted after the
3644  * entry pointed at by insert_lop.
3645  */
3646 static void
3647 nfsrv_insertlock(struct nfslock *new_lop, struct nfslock *insert_lop,
3648     struct nfsstate *stp, struct nfslockfile *lfp)
3649 {
3650 	struct nfslock *lop, *nlop;
3651 
3652 	new_lop->lo_stp = stp;
3653 	new_lop->lo_lfp = lfp;
3654 
3655 	if (stp != NULL) {
3656 		/* Insert in increasing lo_first order */
3657 		lop = LIST_FIRST(&lfp->lf_lock);
3658 		if (lop == LIST_END(&lfp->lf_lock) ||
3659 		    new_lop->lo_first <= lop->lo_first) {
3660 			LIST_INSERT_HEAD(&lfp->lf_lock, new_lop, lo_lckfile);
3661 		} else {
3662 			nlop = LIST_NEXT(lop, lo_lckfile);
3663 			while (nlop != LIST_END(&lfp->lf_lock) &&
3664 			       nlop->lo_first < new_lop->lo_first) {
3665 				lop = nlop;
3666 				nlop = LIST_NEXT(lop, lo_lckfile);
3667 			}
3668 			LIST_INSERT_AFTER(lop, new_lop, lo_lckfile);
3669 		}
3670 	} else {
3671 		new_lop->lo_lckfile.le_prev = NULL;	/* list not used */
3672 	}
3673 
3674 	/*
3675 	 * Insert after insert_lop, which is overloaded as stp or lfp for
3676 	 * an empty list.
3677 	 */
3678 	if (stp == NULL && (struct nfslockfile *)insert_lop == lfp)
3679 		LIST_INSERT_HEAD(&lfp->lf_locallock, new_lop, lo_lckowner);
3680 	else if ((struct nfsstate *)insert_lop == stp)
3681 		LIST_INSERT_HEAD(&stp->ls_lock, new_lop, lo_lckowner);
3682 	else
3683 		LIST_INSERT_AFTER(insert_lop, new_lop, lo_lckowner);
3684 	if (stp != NULL) {
3685 		nfsstatsv1.srvlocks++;
3686 		nfsrv_openpluslock++;
3687 	}
3688 }
3689 
3690 /*
3691  * This function updates the locking for a lock owner and given file. It
3692  * maintains a list of lock ranges ordered on increasing file offset that
3693  * are NFSLCK_READ or NFSLCK_WRITE and non-overlapping (aka POSIX style).
3694  * It always adds new_lop to the list and sometimes uses the one pointed
3695  * at by other_lopp.
3696  */
3697 static void
3698 nfsrv_updatelock(struct nfsstate *stp, struct nfslock **new_lopp,
3699     struct nfslock **other_lopp, struct nfslockfile *lfp)
3700 {
3701 	struct nfslock *new_lop = *new_lopp;
3702 	struct nfslock *lop, *tlop, *ilop;
3703 	struct nfslock *other_lop = *other_lopp;
3704 	int unlock = 0, myfile = 0;
3705 	u_int64_t tmp;
3706 
3707 	/*
3708 	 * Work down the list until the lock is merged.
3709 	 */
3710 	if (new_lop->lo_flags & NFSLCK_UNLOCK)
3711 		unlock = 1;
3712 	if (stp != NULL) {
3713 		ilop = (struct nfslock *)stp;
3714 		lop = LIST_FIRST(&stp->ls_lock);
3715 	} else {
3716 		ilop = (struct nfslock *)lfp;
3717 		lop = LIST_FIRST(&lfp->lf_locallock);
3718 	}
3719 	while (lop != NULL) {
3720 	    /*
3721 	     * Only check locks for this file that aren't before the start of
3722 	     * new lock's range.
3723 	     */
3724 	    if (lop->lo_lfp == lfp) {
3725 	      myfile = 1;
3726 	      if (lop->lo_end >= new_lop->lo_first) {
3727 		if (new_lop->lo_end < lop->lo_first) {
3728 			/*
3729 			 * If the new lock ends before the start of the
3730 			 * current lock's range, no merge, just insert
3731 			 * the new lock.
3732 			 */
3733 			break;
3734 		}
3735 		if (new_lop->lo_flags == lop->lo_flags ||
3736 		    (new_lop->lo_first <= lop->lo_first &&
3737 		     new_lop->lo_end >= lop->lo_end)) {
3738 			/*
3739 			 * This lock can be absorbed by the new lock/unlock.
3740 			 * This happens when it covers the entire range
3741 			 * of the old lock or is contiguous
3742 			 * with the old lock and is of the same type or an
3743 			 * unlock.
3744 			 */
3745 			if (lop->lo_first < new_lop->lo_first)
3746 				new_lop->lo_first = lop->lo_first;
3747 			if (lop->lo_end > new_lop->lo_end)
3748 				new_lop->lo_end = lop->lo_end;
3749 			tlop = lop;
3750 			lop = LIST_NEXT(lop, lo_lckowner);
3751 			nfsrv_freenfslock(tlop);
3752 			continue;
3753 		}
3754 
3755 		/*
3756 		 * All these cases are for contiguous locks that are not the
3757 		 * same type, so they can't be merged.
3758 		 */
3759 		if (new_lop->lo_first <= lop->lo_first) {
3760 			/*
3761 			 * This case is where the new lock overlaps with the
3762 			 * first part of the old lock. Move the start of the
3763 			 * old lock to just past the end of the new lock. The
3764 			 * new lock will be inserted in front of the old, since
3765 			 * ilop hasn't been updated. (We are done now.)
3766 			 */
3767 			lop->lo_first = new_lop->lo_end;
3768 			break;
3769 		}
3770 		if (new_lop->lo_end >= lop->lo_end) {
3771 			/*
3772 			 * This case is where the new lock overlaps with the
3773 			 * end of the old lock's range. Move the old lock's
3774 			 * end to just before the new lock's first and insert
3775 			 * the new lock after the old lock.
3776 			 * Might not be done yet, since the new lock could
3777 			 * overlap further locks with higher ranges.
3778 			 */
3779 			lop->lo_end = new_lop->lo_first;
3780 			ilop = lop;
3781 			lop = LIST_NEXT(lop, lo_lckowner);
3782 			continue;
3783 		}
3784 		/*
3785 		 * The final case is where the new lock's range is in the
3786 		 * middle of the current lock's and splits the current lock
3787 		 * up. Use *other_lopp to handle the second part of the
3788 		 * split old lock range. (We are done now.)
3789 		 * For unlock, we use new_lop as other_lop and tmp, since
3790 		 * other_lop and new_lop are the same for this case.
3791 		 * We noted the unlock case above, so we don't need
3792 		 * new_lop->lo_flags any longer.
3793 		 */
3794 		tmp = new_lop->lo_first;
3795 		if (other_lop == NULL) {
3796 			if (!unlock)
3797 				panic("nfsd srv update unlock");
3798 			other_lop = new_lop;
3799 			*new_lopp = NULL;
3800 		}
3801 		other_lop->lo_first = new_lop->lo_end;
3802 		other_lop->lo_end = lop->lo_end;
3803 		other_lop->lo_flags = lop->lo_flags;
3804 		other_lop->lo_stp = stp;
3805 		other_lop->lo_lfp = lfp;
3806 		lop->lo_end = tmp;
3807 		nfsrv_insertlock(other_lop, lop, stp, lfp);
3808 		*other_lopp = NULL;
3809 		ilop = lop;
3810 		break;
3811 	      }
3812 	    }
3813 	    ilop = lop;
3814 	    lop = LIST_NEXT(lop, lo_lckowner);
3815 	    if (myfile && (lop == NULL || lop->lo_lfp != lfp))
3816 		break;
3817 	}
3818 
3819 	/*
3820 	 * Insert the new lock in the list at the appropriate place.
3821 	 */
3822 	if (!unlock) {
3823 		nfsrv_insertlock(new_lop, ilop, stp, lfp);
3824 		*new_lopp = NULL;
3825 	}
3826 }
3827 
3828 /*
3829  * This function handles sequencing of locks, etc.
3830  * It returns an error that indicates what the caller should do.
3831  */
3832 static int
3833 nfsrv_checkseqid(struct nfsrv_descript *nd, u_int32_t seqid,
3834     struct nfsstate *stp, struct nfsrvcache *op)
3835 {
3836 	int error = 0;
3837 
3838 	if ((nd->nd_flag & ND_NFSV41) != 0)
3839 		/* NFSv4.1 ignores the open_seqid and lock_seqid. */
3840 		goto out;
3841 	if (op != nd->nd_rp)
3842 		panic("nfsrvstate checkseqid");
3843 	if (!(op->rc_flag & RC_INPROG))
3844 		panic("nfsrvstate not inprog");
3845 	if (stp->ls_op && stp->ls_op->rc_refcnt <= 0) {
3846 		printf("refcnt=%d\n", stp->ls_op->rc_refcnt);
3847 		panic("nfsrvstate op refcnt");
3848 	}
3849 	if ((stp->ls_seq + 1) == seqid) {
3850 		if (stp->ls_op)
3851 			nfsrvd_derefcache(stp->ls_op);
3852 		stp->ls_op = op;
3853 		nfsrvd_refcache(op);
3854 		stp->ls_seq = seqid;
3855 		goto out;
3856 	} else if (stp->ls_seq == seqid && stp->ls_op &&
3857 		op->rc_xid == stp->ls_op->rc_xid &&
3858 		op->rc_refcnt == 0 &&
3859 		op->rc_reqlen == stp->ls_op->rc_reqlen &&
3860 		op->rc_cksum == stp->ls_op->rc_cksum) {
3861 		if (stp->ls_op->rc_flag & RC_INPROG) {
3862 			error = NFSERR_DONTREPLY;
3863 			goto out;
3864 		}
3865 		nd->nd_rp = stp->ls_op;
3866 		nd->nd_rp->rc_flag |= RC_INPROG;
3867 		nfsrvd_delcache(op);
3868 		error = NFSERR_REPLYFROMCACHE;
3869 		goto out;
3870 	}
3871 	error = NFSERR_BADSEQID;
3872 
3873 out:
3874 	NFSEXITCODE2(error, nd);
3875 	return (error);
3876 }
3877 
3878 /*
3879  * Get the client ip address for callbacks. If the strings can't be parsed,
3880  * just set lc_program to 0 to indicate no callbacks are possible.
3881  * (For cases where the address can't be parsed or is 0.0.0.0.0.0, set
3882  *  the address to the client's transport address. This won't be used
3883  *  for callbacks, but can be printed out by nfsstats for info.)
3884  * Return error if the xdr can't be parsed, 0 otherwise.
3885  */
3886 APPLESTATIC int
3887 nfsrv_getclientipaddr(struct nfsrv_descript *nd, struct nfsclient *clp)
3888 {
3889 	u_int32_t *tl;
3890 	u_char *cp, *cp2;
3891 	int i, j;
3892 	struct sockaddr_in *rad, *sad;
3893 	u_char protocol[5], addr[24];
3894 	int error = 0, cantparse = 0;
3895 	union {
3896 		in_addr_t ival;
3897 		u_char cval[4];
3898 	} ip;
3899 	union {
3900 		in_port_t sval;
3901 		u_char cval[2];
3902 	} port;
3903 
3904 	rad = NFSSOCKADDR(clp->lc_req.nr_nam, struct sockaddr_in *);
3905 	rad->sin_family = AF_INET;
3906 	rad->sin_len = sizeof (struct sockaddr_in);
3907 	rad->sin_addr.s_addr = 0;
3908 	rad->sin_port = 0;
3909 	clp->lc_req.nr_client = NULL;
3910 	clp->lc_req.nr_lock = 0;
3911 	NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
3912 	i = fxdr_unsigned(int, *tl);
3913 	if (i >= 3 && i <= 4) {
3914 		error = nfsrv_mtostr(nd, protocol, i);
3915 		if (error)
3916 			goto nfsmout;
3917 		if (!strcmp(protocol, "tcp")) {
3918 			clp->lc_flags |= LCL_TCPCALLBACK;
3919 			clp->lc_req.nr_sotype = SOCK_STREAM;
3920 			clp->lc_req.nr_soproto = IPPROTO_TCP;
3921 		} else if (!strcmp(protocol, "udp")) {
3922 			clp->lc_req.nr_sotype = SOCK_DGRAM;
3923 			clp->lc_req.nr_soproto = IPPROTO_UDP;
3924 		} else {
3925 			cantparse = 1;
3926 		}
3927 	} else {
3928 		cantparse = 1;
3929 		if (i > 0) {
3930 			error = nfsm_advance(nd, NFSM_RNDUP(i), -1);
3931 			if (error)
3932 				goto nfsmout;
3933 		}
3934 	}
3935 	NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
3936 	i = fxdr_unsigned(int, *tl);
3937 	if (i < 0) {
3938 		error = NFSERR_BADXDR;
3939 		goto nfsmout;
3940 	} else if (i == 0) {
3941 		cantparse = 1;
3942 	} else if (!cantparse && i <= 23 && i >= 11) {
3943 		error = nfsrv_mtostr(nd, addr, i);
3944 		if (error)
3945 			goto nfsmout;
3946 
3947 		/*
3948 		 * Parse out the address fields. We expect 6 decimal numbers
3949 		 * separated by '.'s.
3950 		 */
3951 		cp = addr;
3952 		i = 0;
3953 		while (*cp && i < 6) {
3954 			cp2 = cp;
3955 			while (*cp2 && *cp2 != '.')
3956 				cp2++;
3957 			if (*cp2)
3958 				*cp2++ = '\0';
3959 			else if (i != 5) {
3960 				cantparse = 1;
3961 				break;
3962 			}
3963 			j = nfsrv_getipnumber(cp);
3964 			if (j >= 0) {
3965 				if (i < 4)
3966 					ip.cval[3 - i] = j;
3967 				else
3968 					port.cval[5 - i] = j;
3969 			} else {
3970 				cantparse = 1;
3971 				break;
3972 			}
3973 			cp = cp2;
3974 			i++;
3975 		}
3976 		if (!cantparse) {
3977 			if (ip.ival != 0x0) {
3978 				rad->sin_addr.s_addr = htonl(ip.ival);
3979 				rad->sin_port = htons(port.sval);
3980 			} else {
3981 				cantparse = 1;
3982 			}
3983 		}
3984 	} else {
3985 		cantparse = 1;
3986 		if (i > 0) {
3987 			error = nfsm_advance(nd, NFSM_RNDUP(i), -1);
3988 			if (error)
3989 				goto nfsmout;
3990 		}
3991 	}
3992 	if (cantparse) {
3993 		sad = NFSSOCKADDR(nd->nd_nam, struct sockaddr_in *);
3994 		if (sad->sin_family == AF_INET) {
3995 			rad->sin_addr.s_addr = sad->sin_addr.s_addr;
3996 			rad->sin_port = 0x0;
3997 		}
3998 		clp->lc_program = 0;
3999 	}
4000 nfsmout:
4001 	NFSEXITCODE2(error, nd);
4002 	return (error);
4003 }
4004 
4005 /*
4006  * Turn a string of up to three decimal digits into a number. Return -1 upon
4007  * error.
4008  */
4009 static int
4010 nfsrv_getipnumber(u_char *cp)
4011 {
4012 	int i = 0, j = 0;
4013 
4014 	while (*cp) {
4015 		if (j > 2 || *cp < '0' || *cp > '9')
4016 			return (-1);
4017 		i *= 10;
4018 		i += (*cp - '0');
4019 		cp++;
4020 		j++;
4021 	}
4022 	if (i < 256)
4023 		return (i);
4024 	return (-1);
4025 }
4026 
4027 /*
4028  * This function checks for restart conditions.
4029  */
4030 static int
4031 nfsrv_checkrestart(nfsquad_t clientid, u_int32_t flags,
4032     nfsv4stateid_t *stateidp, int specialid)
4033 {
4034 	int ret = 0;
4035 
4036 	/*
4037 	 * First check for a server restart. Open, LockT, ReleaseLockOwner
4038 	 * and DelegPurge have a clientid, the rest a stateid.
4039 	 */
4040 	if (flags &
4041 	    (NFSLCK_OPEN | NFSLCK_TEST | NFSLCK_RELEASE | NFSLCK_DELEGPURGE)) {
4042 		if (clientid.lval[0] != nfsrvboottime) {
4043 			ret = NFSERR_STALECLIENTID;
4044 			goto out;
4045 		}
4046 	} else if (stateidp->other[0] != nfsrvboottime &&
4047 		specialid == 0) {
4048 		ret = NFSERR_STALESTATEID;
4049 		goto out;
4050 	}
4051 
4052 	/*
4053 	 * Read, Write, Setattr and LockT can return NFSERR_GRACE and do
4054 	 * not use a lock/open owner seqid#, so the check can be done now.
4055 	 * (The others will be checked, as required, later.)
4056 	 */
4057 	if (!(flags & (NFSLCK_CHECK | NFSLCK_TEST)))
4058 		goto out;
4059 
4060 	NFSLOCKSTATE();
4061 	ret = nfsrv_checkgrace(NULL, NULL, flags);
4062 	NFSUNLOCKSTATE();
4063 
4064 out:
4065 	NFSEXITCODE(ret);
4066 	return (ret);
4067 }
4068 
4069 /*
4070  * Check for grace.
4071  */
4072 static int
4073 nfsrv_checkgrace(struct nfsrv_descript *nd, struct nfsclient *clp,
4074     u_int32_t flags)
4075 {
4076 	int error = 0;
4077 
4078 	if ((nfsrv_stablefirst.nsf_flags & NFSNSF_GRACEOVER) != 0) {
4079 		if (flags & NFSLCK_RECLAIM) {
4080 			error = NFSERR_NOGRACE;
4081 			goto out;
4082 		}
4083 	} else {
4084 		if (!(flags & NFSLCK_RECLAIM)) {
4085 			error = NFSERR_GRACE;
4086 			goto out;
4087 		}
4088 		if (nd != NULL && clp != NULL &&
4089 		    (nd->nd_flag & ND_NFSV41) != 0 &&
4090 		    (clp->lc_flags & LCL_RECLAIMCOMPLETE) != 0) {
4091 			error = NFSERR_NOGRACE;
4092 			goto out;
4093 		}
4094 
4095 		/*
4096 		 * If grace is almost over and we are still getting Reclaims,
4097 		 * extend grace a bit.
4098 		 */
4099 		if ((NFSD_MONOSEC + NFSRV_LEASEDELTA) >
4100 		    nfsrv_stablefirst.nsf_eograce)
4101 			nfsrv_stablefirst.nsf_eograce = NFSD_MONOSEC +
4102 				NFSRV_LEASEDELTA;
4103 	}
4104 
4105 out:
4106 	NFSEXITCODE(error);
4107 	return (error);
4108 }
4109 
4110 /*
4111  * Do a server callback.
4112  */
4113 static int
4114 nfsrv_docallback(struct nfsclient *clp, int procnum,
4115     nfsv4stateid_t *stateidp, int trunc, fhandle_t *fhp,
4116     struct nfsvattr *nap, nfsattrbit_t *attrbitp, NFSPROC_T *p)
4117 {
4118 	mbuf_t m;
4119 	u_int32_t *tl;
4120 	struct nfsrv_descript nfsd, *nd = &nfsd;
4121 	struct ucred *cred;
4122 	int error = 0;
4123 	u_int32_t callback;
4124 	struct nfsdsession *sep = NULL;
4125 
4126 	cred = newnfs_getcred();
4127 	NFSLOCKSTATE();	/* mostly for lc_cbref++ */
4128 	if (clp->lc_flags & LCL_NEEDSCONFIRM) {
4129 		NFSUNLOCKSTATE();
4130 		panic("docallb");
4131 	}
4132 	clp->lc_cbref++;
4133 
4134 	/*
4135 	 * Fill the callback program# and version into the request
4136 	 * structure for newnfs_connect() to use.
4137 	 */
4138 	clp->lc_req.nr_prog = clp->lc_program;
4139 #ifdef notnow
4140 	if ((clp->lc_flags & LCL_NFSV41) != 0)
4141 		clp->lc_req.nr_vers = NFSV41_CBVERS;
4142 	else
4143 #endif
4144 		clp->lc_req.nr_vers = NFSV4_CBVERS;
4145 
4146 	/*
4147 	 * First, fill in some of the fields of nd and cr.
4148 	 */
4149 	nd->nd_flag = ND_NFSV4;
4150 	if (clp->lc_flags & LCL_GSS)
4151 		nd->nd_flag |= ND_KERBV;
4152 	if ((clp->lc_flags & LCL_NFSV41) != 0)
4153 		nd->nd_flag |= ND_NFSV41;
4154 	nd->nd_repstat = 0;
4155 	cred->cr_uid = clp->lc_uid;
4156 	cred->cr_gid = clp->lc_gid;
4157 	callback = clp->lc_callback;
4158 	NFSUNLOCKSTATE();
4159 	cred->cr_ngroups = 1;
4160 
4161 	/*
4162 	 * Get the first mbuf for the request.
4163 	 */
4164 	MGET(m, M_WAITOK, MT_DATA);
4165 	mbuf_setlen(m, 0);
4166 	nd->nd_mreq = nd->nd_mb = m;
4167 	nd->nd_bpos = NFSMTOD(m, caddr_t);
4168 
4169 	/*
4170 	 * and build the callback request.
4171 	 */
4172 	if (procnum == NFSV4OP_CBGETATTR) {
4173 		nd->nd_procnum = NFSV4PROC_CBCOMPOUND;
4174 		error = nfsrv_cbcallargs(nd, clp, callback, NFSV4OP_CBGETATTR,
4175 		    "CB Getattr", &sep);
4176 		if (error != 0) {
4177 			mbuf_freem(nd->nd_mreq);
4178 			goto errout;
4179 		}
4180 		(void)nfsm_fhtom(nd, (u_int8_t *)fhp, NFSX_MYFH, 0);
4181 		(void)nfsrv_putattrbit(nd, attrbitp);
4182 	} else if (procnum == NFSV4OP_CBRECALL) {
4183 		nd->nd_procnum = NFSV4PROC_CBCOMPOUND;
4184 		error = nfsrv_cbcallargs(nd, clp, callback, NFSV4OP_CBRECALL,
4185 		    "CB Recall", &sep);
4186 		if (error != 0) {
4187 			mbuf_freem(nd->nd_mreq);
4188 			goto errout;
4189 		}
4190 		NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED + NFSX_STATEID);
4191 		*tl++ = txdr_unsigned(stateidp->seqid);
4192 		NFSBCOPY((caddr_t)stateidp->other, (caddr_t)tl,
4193 		    NFSX_STATEIDOTHER);
4194 		tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED);
4195 		if (trunc)
4196 			*tl = newnfs_true;
4197 		else
4198 			*tl = newnfs_false;
4199 		(void)nfsm_fhtom(nd, (u_int8_t *)fhp, NFSX_MYFH, 0);
4200 	} else if (procnum == NFSV4PROC_CBNULL) {
4201 		nd->nd_procnum = NFSV4PROC_CBNULL;
4202 		if ((clp->lc_flags & LCL_NFSV41) != 0) {
4203 			error = nfsv4_getcbsession(clp, &sep);
4204 			if (error != 0) {
4205 				mbuf_freem(nd->nd_mreq);
4206 				goto errout;
4207 			}
4208 		}
4209 	} else {
4210 		error = NFSERR_SERVERFAULT;
4211 		mbuf_freem(nd->nd_mreq);
4212 		goto errout;
4213 	}
4214 
4215 	/*
4216 	 * Call newnfs_connect(), as required, and then newnfs_request().
4217 	 */
4218 	(void) newnfs_sndlock(&clp->lc_req.nr_lock);
4219 	if (clp->lc_req.nr_client == NULL) {
4220 		if ((clp->lc_flags & LCL_NFSV41) != 0)
4221 			error = ECONNREFUSED;
4222 		else if (nd->nd_procnum == NFSV4PROC_CBNULL)
4223 			error = newnfs_connect(NULL, &clp->lc_req, cred,
4224 			    NULL, 1);
4225 		else
4226 			error = newnfs_connect(NULL, &clp->lc_req, cred,
4227 			    NULL, 3);
4228 	}
4229 	newnfs_sndunlock(&clp->lc_req.nr_lock);
4230 	if (!error) {
4231 		if ((nd->nd_flag & ND_NFSV41) != 0) {
4232 			KASSERT(sep != NULL, ("sep NULL"));
4233 			if (sep->sess_cbsess.nfsess_xprt != NULL)
4234 				error = newnfs_request(nd, NULL, clp,
4235 				    &clp->lc_req, NULL, NULL, cred,
4236 				    clp->lc_program, clp->lc_req.nr_vers, NULL,
4237 				    1, NULL, &sep->sess_cbsess);
4238 			else {
4239 				/*
4240 				 * This should probably never occur, but if a
4241 				 * client somehow does an RPC without a
4242 				 * SequenceID Op that causes a callback just
4243 				 * after the nfsd threads have been terminated
4244 				 * and restared we could conceivably get here
4245 				 * without a backchannel xprt.
4246 				 */
4247 				printf("nfsrv_docallback: no xprt\n");
4248 				error = ECONNREFUSED;
4249 			}
4250 			nfsrv_freesession(sep, NULL);
4251 		} else
4252 			error = newnfs_request(nd, NULL, clp, &clp->lc_req,
4253 			    NULL, NULL, cred, clp->lc_program,
4254 			    clp->lc_req.nr_vers, NULL, 1, NULL, NULL);
4255 	}
4256 errout:
4257 	NFSFREECRED(cred);
4258 
4259 	/*
4260 	 * If error is set here, the Callback path isn't working
4261 	 * properly, so twiddle the appropriate LCL_ flags.
4262 	 * (nd_repstat != 0 indicates the Callback path is working,
4263 	 *  but the callback failed on the client.)
4264 	 */
4265 	if (error) {
4266 		/*
4267 		 * Mark the callback pathway down, which disabled issuing
4268 		 * of delegations and gets Renew to return NFSERR_CBPATHDOWN.
4269 		 */
4270 		NFSLOCKSTATE();
4271 		clp->lc_flags |= LCL_CBDOWN;
4272 		NFSUNLOCKSTATE();
4273 	} else {
4274 		/*
4275 		 * Callback worked. If the callback path was down, disable
4276 		 * callbacks, so no more delegations will be issued. (This
4277 		 * is done on the assumption that the callback pathway is
4278 		 * flakey.)
4279 		 */
4280 		NFSLOCKSTATE();
4281 		if (clp->lc_flags & LCL_CBDOWN)
4282 			clp->lc_flags &= ~(LCL_CBDOWN | LCL_CALLBACKSON);
4283 		NFSUNLOCKSTATE();
4284 		if (nd->nd_repstat)
4285 			error = nd->nd_repstat;
4286 		else if (error == 0 && procnum == NFSV4OP_CBGETATTR)
4287 			error = nfsv4_loadattr(nd, NULL, nap, NULL, NULL, 0,
4288 			    NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL,
4289 			    p, NULL);
4290 		mbuf_freem(nd->nd_mrep);
4291 	}
4292 	NFSLOCKSTATE();
4293 	clp->lc_cbref--;
4294 	if ((clp->lc_flags & LCL_WAKEUPWANTED) && clp->lc_cbref == 0) {
4295 		clp->lc_flags &= ~LCL_WAKEUPWANTED;
4296 		wakeup(clp);
4297 	}
4298 	NFSUNLOCKSTATE();
4299 
4300 	NFSEXITCODE(error);
4301 	return (error);
4302 }
4303 
4304 /*
4305  * Set up the compound RPC for the callback.
4306  */
4307 static int
4308 nfsrv_cbcallargs(struct nfsrv_descript *nd, struct nfsclient *clp,
4309     uint32_t callback, int op, const char *optag, struct nfsdsession **sepp)
4310 {
4311 	uint32_t *tl;
4312 	int error, len;
4313 
4314 	len = strlen(optag);
4315 	(void)nfsm_strtom(nd, optag, len);
4316 	NFSM_BUILD(tl, uint32_t *, 4 * NFSX_UNSIGNED);
4317 	if ((nd->nd_flag & ND_NFSV41) != 0) {
4318 		*tl++ = txdr_unsigned(NFSV41_MINORVERSION);
4319 		*tl++ = txdr_unsigned(callback);
4320 		*tl++ = txdr_unsigned(2);
4321 		*tl = txdr_unsigned(NFSV4OP_CBSEQUENCE);
4322 		error = nfsv4_setcbsequence(nd, clp, 1, sepp);
4323 		if (error != 0)
4324 			return (error);
4325 		NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
4326 		*tl = txdr_unsigned(op);
4327 	} else {
4328 		*tl++ = txdr_unsigned(NFSV4_MINORVERSION);
4329 		*tl++ = txdr_unsigned(callback);
4330 		*tl++ = txdr_unsigned(1);
4331 		*tl = txdr_unsigned(op);
4332 	}
4333 	return (0);
4334 }
4335 
4336 /*
4337  * Return the next index# for a clientid. Mostly just increment and return
4338  * the next one, but... if the 32bit unsigned does actually wrap around,
4339  * it should be rebooted.
4340  * At an average rate of one new client per second, it will wrap around in
4341  * approximately 136 years. (I think the server will have been shut
4342  * down or rebooted before then.)
4343  */
4344 static u_int32_t
4345 nfsrv_nextclientindex(void)
4346 {
4347 	static u_int32_t client_index = 0;
4348 
4349 	client_index++;
4350 	if (client_index != 0)
4351 		return (client_index);
4352 
4353 	printf("%s: out of clientids\n", __func__);
4354 	return (client_index);
4355 }
4356 
4357 /*
4358  * Return the next index# for a stateid. Mostly just increment and return
4359  * the next one, but... if the 32bit unsigned does actually wrap around
4360  * (will a BSD server stay up that long?), find
4361  * new start and end values.
4362  */
4363 static u_int32_t
4364 nfsrv_nextstateindex(struct nfsclient *clp)
4365 {
4366 	struct nfsstate *stp;
4367 	int i;
4368 	u_int32_t canuse, min_index, max_index;
4369 
4370 	if (!(clp->lc_flags & LCL_INDEXNOTOK)) {
4371 		clp->lc_stateindex++;
4372 		if (clp->lc_stateindex != clp->lc_statemaxindex)
4373 			return (clp->lc_stateindex);
4374 	}
4375 
4376 	/*
4377 	 * Yuck, we've hit the end.
4378 	 * Look for a new min and max.
4379 	 */
4380 	min_index = 0;
4381 	max_index = 0xffffffff;
4382 	for (i = 0; i < nfsrv_statehashsize; i++) {
4383 	    LIST_FOREACH(stp, &clp->lc_stateid[i], ls_hash) {
4384 		if (stp->ls_stateid.other[2] > 0x80000000) {
4385 		    if (stp->ls_stateid.other[2] < max_index)
4386 			max_index = stp->ls_stateid.other[2];
4387 		} else {
4388 		    if (stp->ls_stateid.other[2] > min_index)
4389 			min_index = stp->ls_stateid.other[2];
4390 		}
4391 	    }
4392 	}
4393 
4394 	/*
4395 	 * Yikes, highly unlikely, but I'll handle it anyhow.
4396 	 */
4397 	if (min_index == 0x80000000 && max_index == 0x80000001) {
4398 	    canuse = 0;
4399 	    /*
4400 	     * Loop around until we find an unused entry. Return that
4401 	     * and set LCL_INDEXNOTOK, so the search will continue next time.
4402 	     * (This is one of those rare cases where a goto is the
4403 	     *  cleanest way to code the loop.)
4404 	     */
4405 tryagain:
4406 	    for (i = 0; i < nfsrv_statehashsize; i++) {
4407 		LIST_FOREACH(stp, &clp->lc_stateid[i], ls_hash) {
4408 		    if (stp->ls_stateid.other[2] == canuse) {
4409 			canuse++;
4410 			goto tryagain;
4411 		    }
4412 		}
4413 	    }
4414 	    clp->lc_flags |= LCL_INDEXNOTOK;
4415 	    return (canuse);
4416 	}
4417 
4418 	/*
4419 	 * Ok to start again from min + 1.
4420 	 */
4421 	clp->lc_stateindex = min_index + 1;
4422 	clp->lc_statemaxindex = max_index;
4423 	clp->lc_flags &= ~LCL_INDEXNOTOK;
4424 	return (clp->lc_stateindex);
4425 }
4426 
4427 /*
4428  * The following functions handle the stable storage file that deals with
4429  * the edge conditions described in RFC3530 Sec. 8.6.3.
4430  * The file is as follows:
4431  * - a single record at the beginning that has the lease time of the
4432  *   previous server instance (before the last reboot) and the nfsrvboottime
4433  *   values for the previous server boots.
4434  *   These previous boot times are used to ensure that the current
4435  *   nfsrvboottime does not, somehow, get set to a previous one.
4436  *   (This is important so that Stale ClientIDs and StateIDs can
4437  *    be recognized.)
4438  *   The number of previous nfsvrboottime values precedes the list.
4439  * - followed by some number of appended records with:
4440  *   - client id string
4441  *   - flag that indicates it is a record revoking state via lease
4442  *     expiration or similar
4443  *     OR has successfully acquired state.
4444  * These structures vary in length, with the client string at the end, up
4445  * to NFSV4_OPAQUELIMIT in size.
4446  *
4447  * At the end of the grace period, the file is truncated, the first
4448  * record is rewritten with updated information and any acquired state
4449  * records for successful reclaims of state are written.
4450  *
4451  * Subsequent records are appended when the first state is issued to
4452  * a client and when state is revoked for a client.
4453  *
4454  * When reading the file in, state issued records that come later in
4455  * the file override older ones, since the append log is in cronological order.
4456  * If, for some reason, the file can't be read, the grace period is
4457  * immediately terminated and all reclaims get NFSERR_NOGRACE.
4458  */
4459 
4460 /*
4461  * Read in the stable storage file. Called by nfssvc() before the nfsd
4462  * processes start servicing requests.
4463  */
4464 APPLESTATIC void
4465 nfsrv_setupstable(NFSPROC_T *p)
4466 {
4467 	struct nfsrv_stablefirst *sf = &nfsrv_stablefirst;
4468 	struct nfsrv_stable *sp, *nsp;
4469 	struct nfst_rec *tsp;
4470 	int error, i, tryagain;
4471 	off_t off = 0;
4472 	ssize_t aresid, len;
4473 
4474 	/*
4475 	 * If NFSNSF_UPDATEDONE is set, this is a restart of the nfsds without
4476 	 * a reboot, so state has not been lost.
4477 	 */
4478 	if (sf->nsf_flags & NFSNSF_UPDATEDONE)
4479 		return;
4480 	/*
4481 	 * Set Grace over just until the file reads successfully.
4482 	 */
4483 	nfsrvboottime = time_second;
4484 	LIST_INIT(&sf->nsf_head);
4485 	sf->nsf_flags = (NFSNSF_GRACEOVER | NFSNSF_NEEDLOCK);
4486 	sf->nsf_eograce = NFSD_MONOSEC + NFSRV_LEASEDELTA;
4487 	if (sf->nsf_fp == NULL)
4488 		return;
4489 	error = NFSD_RDWR(UIO_READ, NFSFPVNODE(sf->nsf_fp),
4490 	    (caddr_t)&sf->nsf_rec, sizeof (struct nfsf_rec), off, UIO_SYSSPACE,
4491 	    0, NFSFPCRED(sf->nsf_fp), &aresid, p);
4492 	if (error || aresid || sf->nsf_numboots == 0 ||
4493 		sf->nsf_numboots > NFSNSF_MAXNUMBOOTS)
4494 		return;
4495 
4496 	/*
4497 	 * Now, read in the boottimes.
4498 	 */
4499 	sf->nsf_bootvals = (time_t *)malloc((sf->nsf_numboots + 1) *
4500 		sizeof (time_t), M_TEMP, M_WAITOK);
4501 	off = sizeof (struct nfsf_rec);
4502 	error = NFSD_RDWR(UIO_READ, NFSFPVNODE(sf->nsf_fp),
4503 	    (caddr_t)sf->nsf_bootvals, sf->nsf_numboots * sizeof (time_t), off,
4504 	    UIO_SYSSPACE, 0, NFSFPCRED(sf->nsf_fp), &aresid, p);
4505 	if (error || aresid) {
4506 		free((caddr_t)sf->nsf_bootvals, M_TEMP);
4507 		sf->nsf_bootvals = NULL;
4508 		return;
4509 	}
4510 
4511 	/*
4512 	 * Make sure this nfsrvboottime is different from all recorded
4513 	 * previous ones.
4514 	 */
4515 	do {
4516 		tryagain = 0;
4517 		for (i = 0; i < sf->nsf_numboots; i++) {
4518 			if (nfsrvboottime == sf->nsf_bootvals[i]) {
4519 				nfsrvboottime++;
4520 				tryagain = 1;
4521 				break;
4522 			}
4523 		}
4524 	} while (tryagain);
4525 
4526 	sf->nsf_flags |= NFSNSF_OK;
4527 	off += (sf->nsf_numboots * sizeof (time_t));
4528 
4529 	/*
4530 	 * Read through the file, building a list of records for grace
4531 	 * checking.
4532 	 * Each record is between sizeof (struct nfst_rec) and
4533 	 * sizeof (struct nfst_rec) + NFSV4_OPAQUELIMIT - 1
4534 	 * and is actually sizeof (struct nfst_rec) + nst_len - 1.
4535 	 */
4536 	tsp = (struct nfst_rec *)malloc(sizeof (struct nfst_rec) +
4537 		NFSV4_OPAQUELIMIT - 1, M_TEMP, M_WAITOK);
4538 	do {
4539 	    error = NFSD_RDWR(UIO_READ, NFSFPVNODE(sf->nsf_fp),
4540 	        (caddr_t)tsp, sizeof (struct nfst_rec) + NFSV4_OPAQUELIMIT - 1,
4541 	        off, UIO_SYSSPACE, 0, NFSFPCRED(sf->nsf_fp), &aresid, p);
4542 	    len = (sizeof (struct nfst_rec) + NFSV4_OPAQUELIMIT - 1) - aresid;
4543 	    if (error || (len > 0 && (len < sizeof (struct nfst_rec) ||
4544 		len < (sizeof (struct nfst_rec) + tsp->len - 1)))) {
4545 		/*
4546 		 * Yuck, the file has been corrupted, so just return
4547 		 * after clearing out any restart state, so the grace period
4548 		 * is over.
4549 		 */
4550 		LIST_FOREACH_SAFE(sp, &sf->nsf_head, nst_list, nsp) {
4551 			LIST_REMOVE(sp, nst_list);
4552 			free((caddr_t)sp, M_TEMP);
4553 		}
4554 		free((caddr_t)tsp, M_TEMP);
4555 		sf->nsf_flags &= ~NFSNSF_OK;
4556 		free((caddr_t)sf->nsf_bootvals, M_TEMP);
4557 		sf->nsf_bootvals = NULL;
4558 		return;
4559 	    }
4560 	    if (len > 0) {
4561 		off += sizeof (struct nfst_rec) + tsp->len - 1;
4562 		/*
4563 		 * Search the list for a matching client.
4564 		 */
4565 		LIST_FOREACH(sp, &sf->nsf_head, nst_list) {
4566 			if (tsp->len == sp->nst_len &&
4567 			    !NFSBCMP(tsp->client, sp->nst_client, tsp->len))
4568 				break;
4569 		}
4570 		if (sp == LIST_END(&sf->nsf_head)) {
4571 			sp = (struct nfsrv_stable *)malloc(tsp->len +
4572 				sizeof (struct nfsrv_stable) - 1, M_TEMP,
4573 				M_WAITOK);
4574 			NFSBCOPY((caddr_t)tsp, (caddr_t)&sp->nst_rec,
4575 				sizeof (struct nfst_rec) + tsp->len - 1);
4576 			LIST_INSERT_HEAD(&sf->nsf_head, sp, nst_list);
4577 		} else {
4578 			if (tsp->flag == NFSNST_REVOKE)
4579 				sp->nst_flag |= NFSNST_REVOKE;
4580 			else
4581 				/*
4582 				 * A subsequent timestamp indicates the client
4583 				 * did a setclientid/confirm and any previous
4584 				 * revoke is no longer relevant.
4585 				 */
4586 				sp->nst_flag &= ~NFSNST_REVOKE;
4587 		}
4588 	    }
4589 	} while (len > 0);
4590 	free((caddr_t)tsp, M_TEMP);
4591 	sf->nsf_flags = NFSNSF_OK;
4592 	sf->nsf_eograce = NFSD_MONOSEC + sf->nsf_lease +
4593 		NFSRV_LEASEDELTA;
4594 }
4595 
4596 /*
4597  * Update the stable storage file, now that the grace period is over.
4598  */
4599 APPLESTATIC void
4600 nfsrv_updatestable(NFSPROC_T *p)
4601 {
4602 	struct nfsrv_stablefirst *sf = &nfsrv_stablefirst;
4603 	struct nfsrv_stable *sp, *nsp;
4604 	int i;
4605 	struct nfsvattr nva;
4606 	vnode_t vp;
4607 #if defined(__FreeBSD_version) && (__FreeBSD_version >= 500000)
4608 	mount_t mp = NULL;
4609 #endif
4610 	int error;
4611 
4612 	if (sf->nsf_fp == NULL || (sf->nsf_flags & NFSNSF_UPDATEDONE))
4613 		return;
4614 	sf->nsf_flags |= NFSNSF_UPDATEDONE;
4615 	/*
4616 	 * Ok, we need to rewrite the stable storage file.
4617 	 * - truncate to 0 length
4618 	 * - write the new first structure
4619 	 * - loop through the data structures, writing out any that
4620 	 *   have timestamps older than the old boot
4621 	 */
4622 	if (sf->nsf_bootvals) {
4623 		sf->nsf_numboots++;
4624 		for (i = sf->nsf_numboots - 2; i >= 0; i--)
4625 			sf->nsf_bootvals[i + 1] = sf->nsf_bootvals[i];
4626 	} else {
4627 		sf->nsf_numboots = 1;
4628 		sf->nsf_bootvals = (time_t *)malloc(sizeof (time_t),
4629 			M_TEMP, M_WAITOK);
4630 	}
4631 	sf->nsf_bootvals[0] = nfsrvboottime;
4632 	sf->nsf_lease = nfsrv_lease;
4633 	NFSVNO_ATTRINIT(&nva);
4634 	NFSVNO_SETATTRVAL(&nva, size, 0);
4635 	vp = NFSFPVNODE(sf->nsf_fp);
4636 	vn_start_write(vp, &mp, V_WAIT);
4637 	if (NFSVOPLOCK(vp, LK_EXCLUSIVE) == 0) {
4638 		error = nfsvno_setattr(vp, &nva, NFSFPCRED(sf->nsf_fp), p,
4639 		    NULL);
4640 		NFSVOPUNLOCK(vp, 0);
4641 	} else
4642 		error = EPERM;
4643 	vn_finished_write(mp);
4644 	if (!error)
4645 	    error = NFSD_RDWR(UIO_WRITE, vp,
4646 		(caddr_t)&sf->nsf_rec, sizeof (struct nfsf_rec), (off_t)0,
4647 		UIO_SYSSPACE, IO_SYNC, NFSFPCRED(sf->nsf_fp), NULL, p);
4648 	if (!error)
4649 	    error = NFSD_RDWR(UIO_WRITE, vp,
4650 		(caddr_t)sf->nsf_bootvals,
4651 		sf->nsf_numboots * sizeof (time_t),
4652 		(off_t)(sizeof (struct nfsf_rec)),
4653 		UIO_SYSSPACE, IO_SYNC, NFSFPCRED(sf->nsf_fp), NULL, p);
4654 	free((caddr_t)sf->nsf_bootvals, M_TEMP);
4655 	sf->nsf_bootvals = NULL;
4656 	if (error) {
4657 		sf->nsf_flags &= ~NFSNSF_OK;
4658 		printf("EEK! Can't write NfsV4 stable storage file\n");
4659 		return;
4660 	}
4661 	sf->nsf_flags |= NFSNSF_OK;
4662 
4663 	/*
4664 	 * Loop through the list and write out timestamp records for
4665 	 * any clients that successfully reclaimed state.
4666 	 */
4667 	LIST_FOREACH_SAFE(sp, &sf->nsf_head, nst_list, nsp) {
4668 		if (sp->nst_flag & NFSNST_GOTSTATE) {
4669 			nfsrv_writestable(sp->nst_client, sp->nst_len,
4670 				NFSNST_NEWSTATE, p);
4671 			sp->nst_clp->lc_flags |= LCL_STAMPEDSTABLE;
4672 		}
4673 		LIST_REMOVE(sp, nst_list);
4674 		free((caddr_t)sp, M_TEMP);
4675 	}
4676 	nfsrv_backupstable();
4677 }
4678 
4679 /*
4680  * Append a record to the stable storage file.
4681  */
4682 APPLESTATIC void
4683 nfsrv_writestable(u_char *client, int len, int flag, NFSPROC_T *p)
4684 {
4685 	struct nfsrv_stablefirst *sf = &nfsrv_stablefirst;
4686 	struct nfst_rec *sp;
4687 	int error;
4688 
4689 	if (!(sf->nsf_flags & NFSNSF_OK) || sf->nsf_fp == NULL)
4690 		return;
4691 	sp = (struct nfst_rec *)malloc(sizeof (struct nfst_rec) +
4692 		len - 1, M_TEMP, M_WAITOK);
4693 	sp->len = len;
4694 	NFSBCOPY(client, sp->client, len);
4695 	sp->flag = flag;
4696 	error = NFSD_RDWR(UIO_WRITE, NFSFPVNODE(sf->nsf_fp),
4697 	    (caddr_t)sp, sizeof (struct nfst_rec) + len - 1, (off_t)0,
4698 	    UIO_SYSSPACE, (IO_SYNC | IO_APPEND), NFSFPCRED(sf->nsf_fp), NULL, p);
4699 	free((caddr_t)sp, M_TEMP);
4700 	if (error) {
4701 		sf->nsf_flags &= ~NFSNSF_OK;
4702 		printf("EEK! Can't write NfsV4 stable storage file\n");
4703 	}
4704 }
4705 
4706 /*
4707  * This function is called during the grace period to mark a client
4708  * that successfully reclaimed state.
4709  */
4710 static void
4711 nfsrv_markstable(struct nfsclient *clp)
4712 {
4713 	struct nfsrv_stable *sp;
4714 
4715 	/*
4716 	 * First find the client structure.
4717 	 */
4718 	LIST_FOREACH(sp, &nfsrv_stablefirst.nsf_head, nst_list) {
4719 		if (sp->nst_len == clp->lc_idlen &&
4720 		    !NFSBCMP(sp->nst_client, clp->lc_id, sp->nst_len))
4721 			break;
4722 	}
4723 	if (sp == LIST_END(&nfsrv_stablefirst.nsf_head))
4724 		return;
4725 
4726 	/*
4727 	 * Now, just mark it and set the nfsclient back pointer.
4728 	 */
4729 	sp->nst_flag |= NFSNST_GOTSTATE;
4730 	sp->nst_clp = clp;
4731 }
4732 
4733 /*
4734  * This function is called for a reclaim, to see if it gets grace.
4735  * It returns 0 if a reclaim is allowed, 1 otherwise.
4736  */
4737 static int
4738 nfsrv_checkstable(struct nfsclient *clp)
4739 {
4740 	struct nfsrv_stable *sp;
4741 
4742 	/*
4743 	 * First, find the entry for the client.
4744 	 */
4745 	LIST_FOREACH(sp, &nfsrv_stablefirst.nsf_head, nst_list) {
4746 		if (sp->nst_len == clp->lc_idlen &&
4747 		    !NFSBCMP(sp->nst_client, clp->lc_id, sp->nst_len))
4748 			break;
4749 	}
4750 
4751 	/*
4752 	 * If not in the list, state was revoked or no state was issued
4753 	 * since the previous reboot, a reclaim is denied.
4754 	 */
4755 	if (sp == LIST_END(&nfsrv_stablefirst.nsf_head) ||
4756 	    (sp->nst_flag & NFSNST_REVOKE) ||
4757 	    !(nfsrv_stablefirst.nsf_flags & NFSNSF_OK))
4758 		return (1);
4759 	return (0);
4760 }
4761 
4762 /*
4763  * Test for and try to clear out a conflicting client. This is called by
4764  * nfsrv_lockctrl() and nfsrv_openctrl() when conflicts with other clients
4765  * a found.
4766  * The trick here is that it can't revoke a conflicting client with an
4767  * expired lease unless it holds the v4root lock, so...
4768  * If no v4root lock, get the lock and return 1 to indicate "try again".
4769  * Return 0 to indicate the conflict can't be revoked and 1 to indicate
4770  * the revocation worked and the conflicting client is "bye, bye", so it
4771  * can be tried again.
4772  * Return 2 to indicate that the vnode is VI_DOOMED after NFSVOPLOCK().
4773  * Unlocks State before a non-zero value is returned.
4774  */
4775 static int
4776 nfsrv_clientconflict(struct nfsclient *clp, int *haslockp, vnode_t vp,
4777     NFSPROC_T *p)
4778 {
4779 	int gotlock, lktype = 0;
4780 
4781 	/*
4782 	 * If lease hasn't expired, we can't fix it.
4783 	 */
4784 	if (clp->lc_expiry >= NFSD_MONOSEC ||
4785 	    !(nfsrv_stablefirst.nsf_flags & NFSNSF_UPDATEDONE))
4786 		return (0);
4787 	if (*haslockp == 0) {
4788 		NFSUNLOCKSTATE();
4789 		if (vp != NULL) {
4790 			lktype = NFSVOPISLOCKED(vp);
4791 			NFSVOPUNLOCK(vp, 0);
4792 		}
4793 		NFSLOCKV4ROOTMUTEX();
4794 		nfsv4_relref(&nfsv4rootfs_lock);
4795 		do {
4796 			gotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL,
4797 			    NFSV4ROOTLOCKMUTEXPTR, NULL);
4798 		} while (!gotlock);
4799 		NFSUNLOCKV4ROOTMUTEX();
4800 		*haslockp = 1;
4801 		if (vp != NULL) {
4802 			NFSVOPLOCK(vp, lktype | LK_RETRY);
4803 			if ((vp->v_iflag & VI_DOOMED) != 0)
4804 				return (2);
4805 		}
4806 		return (1);
4807 	}
4808 	NFSUNLOCKSTATE();
4809 
4810 	/*
4811 	 * Ok, we can expire the conflicting client.
4812 	 */
4813 	nfsrv_writestable(clp->lc_id, clp->lc_idlen, NFSNST_REVOKE, p);
4814 	nfsrv_backupstable();
4815 	nfsrv_cleanclient(clp, p);
4816 	nfsrv_freedeleglist(&clp->lc_deleg);
4817 	nfsrv_freedeleglist(&clp->lc_olddeleg);
4818 	LIST_REMOVE(clp, lc_hash);
4819 	nfsrv_zapclient(clp, p);
4820 	return (1);
4821 }
4822 
4823 /*
4824  * Resolve a delegation conflict.
4825  * Returns 0 to indicate the conflict was resolved without sleeping.
4826  * Return -1 to indicate that the caller should check for conflicts again.
4827  * Return > 0 for an error that should be returned, normally NFSERR_DELAY.
4828  *
4829  * Also, manipulate the nfsv4root_lock, as required. It isn't changed
4830  * for a return of 0, since there was no sleep and it could be required
4831  * later. It is released for a return of NFSERR_DELAY, since the caller
4832  * will return that error. It is released when a sleep was done waiting
4833  * for the delegation to be returned or expire (so that other nfsds can
4834  * handle ops). Then, it must be acquired for the write to stable storage.
4835  * (This function is somewhat similar to nfsrv_clientconflict(), but
4836  *  the semantics differ in a couple of subtle ways. The return of 0
4837  *  indicates the conflict was resolved without sleeping here, not
4838  *  that the conflict can't be resolved and the handling of nfsv4root_lock
4839  *  differs, as noted above.)
4840  * Unlocks State before returning a non-zero value.
4841  */
4842 static int
4843 nfsrv_delegconflict(struct nfsstate *stp, int *haslockp, NFSPROC_T *p,
4844     vnode_t vp)
4845 {
4846 	struct nfsclient *clp = stp->ls_clp;
4847 	int gotlock, error, lktype = 0, retrycnt, zapped_clp;
4848 	nfsv4stateid_t tstateid;
4849 	fhandle_t tfh;
4850 
4851 	/*
4852 	 * If the conflict is with an old delegation...
4853 	 */
4854 	if (stp->ls_flags & NFSLCK_OLDDELEG) {
4855 		/*
4856 		 * You can delete it, if it has expired.
4857 		 */
4858 		if (clp->lc_delegtime < NFSD_MONOSEC) {
4859 			nfsrv_freedeleg(stp);
4860 			NFSUNLOCKSTATE();
4861 			error = -1;
4862 			goto out;
4863 		}
4864 		NFSUNLOCKSTATE();
4865 		/*
4866 		 * During this delay, the old delegation could expire or it
4867 		 * could be recovered by the client via an Open with
4868 		 * CLAIM_DELEGATE_PREV.
4869 		 * Release the nfsv4root_lock, if held.
4870 		 */
4871 		if (*haslockp) {
4872 			*haslockp = 0;
4873 			NFSLOCKV4ROOTMUTEX();
4874 			nfsv4_unlock(&nfsv4rootfs_lock, 1);
4875 			NFSUNLOCKV4ROOTMUTEX();
4876 		}
4877 		error = NFSERR_DELAY;
4878 		goto out;
4879 	}
4880 
4881 	/*
4882 	 * It's a current delegation, so:
4883 	 * - check to see if the delegation has expired
4884 	 *   - if so, get the v4root lock and then expire it
4885 	 */
4886 	if (!(stp->ls_flags & NFSLCK_DELEGRECALL)) {
4887 		/*
4888 		 * - do a recall callback, since not yet done
4889 		 * For now, never allow truncate to be set. To use
4890 		 * truncate safely, it must be guaranteed that the
4891 		 * Remove, Rename or Setattr with size of 0 will
4892 		 * succeed and that would require major changes to
4893 		 * the VFS/Vnode OPs.
4894 		 * Set the expiry time large enough so that it won't expire
4895 		 * until after the callback, then set it correctly, once
4896 		 * the callback is done. (The delegation will now time
4897 		 * out whether or not the Recall worked ok. The timeout
4898 		 * will be extended when ops are done on the delegation
4899 		 * stateid, up to the timelimit.)
4900 		 */
4901 		stp->ls_delegtime = NFSD_MONOSEC + (2 * nfsrv_lease) +
4902 		    NFSRV_LEASEDELTA;
4903 		stp->ls_delegtimelimit = NFSD_MONOSEC + (6 * nfsrv_lease) +
4904 		    NFSRV_LEASEDELTA;
4905 		stp->ls_flags |= NFSLCK_DELEGRECALL;
4906 
4907 		/*
4908 		 * Loop NFSRV_CBRETRYCNT times while the CBRecall replies
4909 		 * NFSERR_BADSTATEID or NFSERR_BADHANDLE. This is done
4910 		 * in order to try and avoid a race that could happen
4911 		 * when a CBRecall request passed the Open reply with
4912 		 * the delegation in it when transitting the network.
4913 		 * Since nfsrv_docallback will sleep, don't use stp after
4914 		 * the call.
4915 		 */
4916 		NFSBCOPY((caddr_t)&stp->ls_stateid, (caddr_t)&tstateid,
4917 		    sizeof (tstateid));
4918 		NFSBCOPY((caddr_t)&stp->ls_lfp->lf_fh, (caddr_t)&tfh,
4919 		    sizeof (tfh));
4920 		NFSUNLOCKSTATE();
4921 		if (*haslockp) {
4922 			*haslockp = 0;
4923 			NFSLOCKV4ROOTMUTEX();
4924 			nfsv4_unlock(&nfsv4rootfs_lock, 1);
4925 			NFSUNLOCKV4ROOTMUTEX();
4926 		}
4927 		retrycnt = 0;
4928 		do {
4929 		    error = nfsrv_docallback(clp, NFSV4OP_CBRECALL,
4930 			&tstateid, 0, &tfh, NULL, NULL, p);
4931 		    retrycnt++;
4932 		} while ((error == NFSERR_BADSTATEID ||
4933 		    error == NFSERR_BADHANDLE) && retrycnt < NFSV4_CBRETRYCNT);
4934 		error = NFSERR_DELAY;
4935 		goto out;
4936 	}
4937 
4938 	if (clp->lc_expiry >= NFSD_MONOSEC &&
4939 	    stp->ls_delegtime >= NFSD_MONOSEC) {
4940 		NFSUNLOCKSTATE();
4941 		/*
4942 		 * A recall has been done, but it has not yet expired.
4943 		 * So, RETURN_DELAY.
4944 		 */
4945 		if (*haslockp) {
4946 			*haslockp = 0;
4947 			NFSLOCKV4ROOTMUTEX();
4948 			nfsv4_unlock(&nfsv4rootfs_lock, 1);
4949 			NFSUNLOCKV4ROOTMUTEX();
4950 		}
4951 		error = NFSERR_DELAY;
4952 		goto out;
4953 	}
4954 
4955 	/*
4956 	 * If we don't yet have the lock, just get it and then return,
4957 	 * since we need that before deleting expired state, such as
4958 	 * this delegation.
4959 	 * When getting the lock, unlock the vnode, so other nfsds that
4960 	 * are in progress, won't get stuck waiting for the vnode lock.
4961 	 */
4962 	if (*haslockp == 0) {
4963 		NFSUNLOCKSTATE();
4964 		if (vp != NULL) {
4965 			lktype = NFSVOPISLOCKED(vp);
4966 			NFSVOPUNLOCK(vp, 0);
4967 		}
4968 		NFSLOCKV4ROOTMUTEX();
4969 		nfsv4_relref(&nfsv4rootfs_lock);
4970 		do {
4971 			gotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL,
4972 			    NFSV4ROOTLOCKMUTEXPTR, NULL);
4973 		} while (!gotlock);
4974 		NFSUNLOCKV4ROOTMUTEX();
4975 		*haslockp = 1;
4976 		if (vp != NULL) {
4977 			NFSVOPLOCK(vp, lktype | LK_RETRY);
4978 			if ((vp->v_iflag & VI_DOOMED) != 0) {
4979 				*haslockp = 0;
4980 				NFSLOCKV4ROOTMUTEX();
4981 				nfsv4_unlock(&nfsv4rootfs_lock, 1);
4982 				NFSUNLOCKV4ROOTMUTEX();
4983 				error = NFSERR_PERM;
4984 				goto out;
4985 			}
4986 		}
4987 		error = -1;
4988 		goto out;
4989 	}
4990 
4991 	NFSUNLOCKSTATE();
4992 	/*
4993 	 * Ok, we can delete the expired delegation.
4994 	 * First, write the Revoke record to stable storage and then
4995 	 * clear out the conflict.
4996 	 * Since all other nfsd threads are now blocked, we can safely
4997 	 * sleep without the state changing.
4998 	 */
4999 	nfsrv_writestable(clp->lc_id, clp->lc_idlen, NFSNST_REVOKE, p);
5000 	nfsrv_backupstable();
5001 	if (clp->lc_expiry < NFSD_MONOSEC) {
5002 		nfsrv_cleanclient(clp, p);
5003 		nfsrv_freedeleglist(&clp->lc_deleg);
5004 		nfsrv_freedeleglist(&clp->lc_olddeleg);
5005 		LIST_REMOVE(clp, lc_hash);
5006 		zapped_clp = 1;
5007 	} else {
5008 		nfsrv_freedeleg(stp);
5009 		zapped_clp = 0;
5010 	}
5011 	if (zapped_clp)
5012 		nfsrv_zapclient(clp, p);
5013 	error = -1;
5014 
5015 out:
5016 	NFSEXITCODE(error);
5017 	return (error);
5018 }
5019 
5020 /*
5021  * Check for a remove allowed, if remove is set to 1 and get rid of
5022  * delegations.
5023  */
5024 APPLESTATIC int
5025 nfsrv_checkremove(vnode_t vp, int remove, NFSPROC_T *p)
5026 {
5027 	struct nfsstate *stp;
5028 	struct nfslockfile *lfp;
5029 	int error, haslock = 0;
5030 	fhandle_t nfh;
5031 
5032 	/*
5033 	 * First, get the lock file structure.
5034 	 * (A return of -1 means no associated state, so remove ok.)
5035 	 */
5036 	error = nfsrv_getlockfh(vp, NFSLCK_CHECK, NULL, &nfh, p);
5037 tryagain:
5038 	NFSLOCKSTATE();
5039 	if (!error)
5040 		error = nfsrv_getlockfile(NFSLCK_CHECK, NULL, &lfp, &nfh, 0);
5041 	if (error) {
5042 		NFSUNLOCKSTATE();
5043 		if (haslock) {
5044 			NFSLOCKV4ROOTMUTEX();
5045 			nfsv4_unlock(&nfsv4rootfs_lock, 1);
5046 			NFSUNLOCKV4ROOTMUTEX();
5047 		}
5048 		if (error == -1)
5049 			error = 0;
5050 		goto out;
5051 	}
5052 
5053 	/*
5054 	 * Now, we must Recall any delegations.
5055 	 */
5056 	error = nfsrv_cleandeleg(vp, lfp, NULL, &haslock, p);
5057 	if (error) {
5058 		/*
5059 		 * nfsrv_cleandeleg() unlocks state for non-zero
5060 		 * return.
5061 		 */
5062 		if (error == -1)
5063 			goto tryagain;
5064 		if (haslock) {
5065 			NFSLOCKV4ROOTMUTEX();
5066 			nfsv4_unlock(&nfsv4rootfs_lock, 1);
5067 			NFSUNLOCKV4ROOTMUTEX();
5068 		}
5069 		goto out;
5070 	}
5071 
5072 	/*
5073 	 * Now, look for a conflicting open share.
5074 	 */
5075 	if (remove) {
5076 		/*
5077 		 * If the entry in the directory was the last reference to the
5078 		 * corresponding filesystem object, the object can be destroyed
5079 		 * */
5080 		if(lfp->lf_usecount>1)
5081 			LIST_FOREACH(stp, &lfp->lf_open, ls_file) {
5082 				if (stp->ls_flags & NFSLCK_WRITEDENY) {
5083 					error = NFSERR_FILEOPEN;
5084 					break;
5085 				}
5086 			}
5087 	}
5088 
5089 	NFSUNLOCKSTATE();
5090 	if (haslock) {
5091 		NFSLOCKV4ROOTMUTEX();
5092 		nfsv4_unlock(&nfsv4rootfs_lock, 1);
5093 		NFSUNLOCKV4ROOTMUTEX();
5094 	}
5095 
5096 out:
5097 	NFSEXITCODE(error);
5098 	return (error);
5099 }
5100 
5101 /*
5102  * Clear out all delegations for the file referred to by lfp.
5103  * May return NFSERR_DELAY, if there will be a delay waiting for
5104  * delegations to expire.
5105  * Returns -1 to indicate it slept while recalling a delegation.
5106  * This function has the side effect of deleting the nfslockfile structure,
5107  * if it no longer has associated state and didn't have to sleep.
5108  * Unlocks State before a non-zero value is returned.
5109  */
5110 static int
5111 nfsrv_cleandeleg(vnode_t vp, struct nfslockfile *lfp,
5112     struct nfsclient *clp, int *haslockp, NFSPROC_T *p)
5113 {
5114 	struct nfsstate *stp, *nstp;
5115 	int ret = 0;
5116 
5117 	stp = LIST_FIRST(&lfp->lf_deleg);
5118 	while (stp != LIST_END(&lfp->lf_deleg)) {
5119 		nstp = LIST_NEXT(stp, ls_file);
5120 		if (stp->ls_clp != clp) {
5121 			ret = nfsrv_delegconflict(stp, haslockp, p, vp);
5122 			if (ret) {
5123 				/*
5124 				 * nfsrv_delegconflict() unlocks state
5125 				 * when it returns non-zero.
5126 				 */
5127 				goto out;
5128 			}
5129 		}
5130 		stp = nstp;
5131 	}
5132 out:
5133 	NFSEXITCODE(ret);
5134 	return (ret);
5135 }
5136 
5137 /*
5138  * There are certain operations that, when being done outside of NFSv4,
5139  * require that any NFSv4 delegation for the file be recalled.
5140  * This function is to be called for those cases:
5141  * VOP_RENAME() - When a delegation is being recalled for any reason,
5142  *	the client may have to do Opens against the server, using the file's
5143  *	final component name. If the file has been renamed on the server,
5144  *	that component name will be incorrect and the Open will fail.
5145  * VOP_REMOVE() - Theoretically, a client could Open a file after it has
5146  *	been removed on the server, if there is a delegation issued to
5147  *	that client for the file. I say "theoretically" since clients
5148  *	normally do an Access Op before the Open and that Access Op will
5149  *	fail with ESTALE. Note that NFSv2 and 3 don't even do Opens, so
5150  *	they will detect the file's removal in the same manner. (There is
5151  *	one case where RFC3530 allows a client to do an Open without first
5152  *	doing an Access Op, which is passage of a check against the ACE
5153  *	returned with a Write delegation, but current practice is to ignore
5154  *	the ACE and always do an Access Op.)
5155  *	Since the functions can only be called with an unlocked vnode, this
5156  *	can't be done at this time.
5157  * VOP_ADVLOCK() - When a client holds a delegation, it can issue byte range
5158  *	locks locally in the client, which are not visible to the server. To
5159  *	deal with this, issuing of delegations for a vnode must be disabled
5160  *	and all delegations for the vnode recalled. This is done via the
5161  *	second function, using the VV_DISABLEDELEG vflag on the vnode.
5162  */
5163 APPLESTATIC void
5164 nfsd_recalldelegation(vnode_t vp, NFSPROC_T *p)
5165 {
5166 	time_t starttime;
5167 	int error;
5168 
5169 	/*
5170 	 * First, check to see if the server is currently running and it has
5171 	 * been called for a regular file when issuing delegations.
5172 	 */
5173 	if (newnfs_numnfsd == 0 || vp->v_type != VREG ||
5174 	    nfsrv_issuedelegs == 0)
5175 		return;
5176 
5177 	KASSERT((NFSVOPISLOCKED(vp) != LK_EXCLUSIVE), ("vp %p is locked", vp));
5178 	/*
5179 	 * First, get a reference on the nfsv4rootfs_lock so that an
5180 	 * exclusive lock cannot be acquired by another thread.
5181 	 */
5182 	NFSLOCKV4ROOTMUTEX();
5183 	nfsv4_getref(&nfsv4rootfs_lock, NULL, NFSV4ROOTLOCKMUTEXPTR, NULL);
5184 	NFSUNLOCKV4ROOTMUTEX();
5185 
5186 	/*
5187 	 * Now, call nfsrv_checkremove() in a loop while it returns
5188 	 * NFSERR_DELAY. Return upon any other error or when timed out.
5189 	 */
5190 	starttime = NFSD_MONOSEC;
5191 	do {
5192 		if (NFSVOPLOCK(vp, LK_EXCLUSIVE) == 0) {
5193 			error = nfsrv_checkremove(vp, 0, p);
5194 			NFSVOPUNLOCK(vp, 0);
5195 		} else
5196 			error = EPERM;
5197 		if (error == NFSERR_DELAY) {
5198 			if (NFSD_MONOSEC - starttime > NFS_REMOVETIMEO)
5199 				break;
5200 			/* Sleep for a short period of time */
5201 			(void) nfs_catnap(PZERO, 0, "nfsremove");
5202 		}
5203 	} while (error == NFSERR_DELAY);
5204 	NFSLOCKV4ROOTMUTEX();
5205 	nfsv4_relref(&nfsv4rootfs_lock);
5206 	NFSUNLOCKV4ROOTMUTEX();
5207 }
5208 
5209 APPLESTATIC void
5210 nfsd_disabledelegation(vnode_t vp, NFSPROC_T *p)
5211 {
5212 
5213 #ifdef VV_DISABLEDELEG
5214 	/*
5215 	 * First, flag issuance of delegations disabled.
5216 	 */
5217 	atomic_set_long(&vp->v_vflag, VV_DISABLEDELEG);
5218 #endif
5219 
5220 	/*
5221 	 * Then call nfsd_recalldelegation() to get rid of all extant
5222 	 * delegations.
5223 	 */
5224 	nfsd_recalldelegation(vp, p);
5225 }
5226 
5227 /*
5228  * Check for conflicting locks, etc. and then get rid of delegations.
5229  * (At one point I thought that I should get rid of delegations for any
5230  *  Setattr, since it could potentially disallow the I/O op (read or write)
5231  *  allowed by the delegation. However, Setattr Ops that aren't changing
5232  *  the size get a stateid of all 0s, so you can't tell if it is a delegation
5233  *  for the same client or a different one, so I decided to only get rid
5234  *  of delegations for other clients when the size is being changed.)
5235  * In general, a Setattr can disable NFS I/O Ops that are outstanding, such
5236  * as Write backs, even if there is no delegation, so it really isn't any
5237  * different?)
5238  */
5239 APPLESTATIC int
5240 nfsrv_checksetattr(vnode_t vp, struct nfsrv_descript *nd,
5241     nfsv4stateid_t *stateidp, struct nfsvattr *nvap, nfsattrbit_t *attrbitp,
5242     struct nfsexstuff *exp, NFSPROC_T *p)
5243 {
5244 	struct nfsstate st, *stp = &st;
5245 	struct nfslock lo, *lop = &lo;
5246 	int error = 0;
5247 	nfsquad_t clientid;
5248 
5249 	if (NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_SIZE)) {
5250 		stp->ls_flags = (NFSLCK_CHECK | NFSLCK_WRITEACCESS);
5251 		lop->lo_first = nvap->na_size;
5252 	} else {
5253 		stp->ls_flags = 0;
5254 		lop->lo_first = 0;
5255 	}
5256 	if (NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_OWNER) ||
5257 	    NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_OWNERGROUP) ||
5258 	    NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_MODE) ||
5259 	    NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_ACL))
5260 		stp->ls_flags |= NFSLCK_SETATTR;
5261 	if (stp->ls_flags == 0)
5262 		goto out;
5263 	lop->lo_end = NFS64BITSSET;
5264 	lop->lo_flags = NFSLCK_WRITE;
5265 	stp->ls_ownerlen = 0;
5266 	stp->ls_op = NULL;
5267 	stp->ls_uid = nd->nd_cred->cr_uid;
5268 	stp->ls_stateid.seqid = stateidp->seqid;
5269 	clientid.lval[0] = stp->ls_stateid.other[0] = stateidp->other[0];
5270 	clientid.lval[1] = stp->ls_stateid.other[1] = stateidp->other[1];
5271 	stp->ls_stateid.other[2] = stateidp->other[2];
5272 	error = nfsrv_lockctrl(vp, &stp, &lop, NULL, clientid,
5273 	    stateidp, exp, nd, p);
5274 
5275 out:
5276 	NFSEXITCODE2(error, nd);
5277 	return (error);
5278 }
5279 
5280 /*
5281  * Check for a write delegation and do a CBGETATTR if there is one, updating
5282  * the attributes, as required.
5283  * Should I return an error if I can't get the attributes? (For now, I'll
5284  * just return ok.
5285  */
5286 APPLESTATIC int
5287 nfsrv_checkgetattr(struct nfsrv_descript *nd, vnode_t vp,
5288     struct nfsvattr *nvap, nfsattrbit_t *attrbitp, struct ucred *cred,
5289     NFSPROC_T *p)
5290 {
5291 	struct nfsstate *stp;
5292 	struct nfslockfile *lfp;
5293 	struct nfsclient *clp;
5294 	struct nfsvattr nva;
5295 	fhandle_t nfh;
5296 	int error = 0;
5297 	nfsattrbit_t cbbits;
5298 	u_quad_t delegfilerev;
5299 
5300 	NFSCBGETATTR_ATTRBIT(attrbitp, &cbbits);
5301 	if (!NFSNONZERO_ATTRBIT(&cbbits))
5302 		goto out;
5303 
5304 	/*
5305 	 * Get the lock file structure.
5306 	 * (A return of -1 means no associated state, so return ok.)
5307 	 */
5308 	error = nfsrv_getlockfh(vp, NFSLCK_CHECK, NULL, &nfh, p);
5309 	NFSLOCKSTATE();
5310 	if (!error)
5311 		error = nfsrv_getlockfile(NFSLCK_CHECK, NULL, &lfp, &nfh, 0);
5312 	if (error) {
5313 		NFSUNLOCKSTATE();
5314 		if (error == -1)
5315 			error = 0;
5316 		goto out;
5317 	}
5318 
5319 	/*
5320 	 * Now, look for a write delegation.
5321 	 */
5322 	LIST_FOREACH(stp, &lfp->lf_deleg, ls_file) {
5323 		if (stp->ls_flags & NFSLCK_DELEGWRITE)
5324 			break;
5325 	}
5326 	if (stp == LIST_END(&lfp->lf_deleg)) {
5327 		NFSUNLOCKSTATE();
5328 		goto out;
5329 	}
5330 	clp = stp->ls_clp;
5331 	delegfilerev = stp->ls_filerev;
5332 
5333 	/*
5334 	 * If the Write delegation was issued as a part of this Compound RPC
5335 	 * or if we have an Implied Clientid (used in a previous Op in this
5336 	 * compound) and it is the client the delegation was issued to,
5337 	 * just return ok.
5338 	 * I also assume that it is from the same client iff the network
5339 	 * host IP address is the same as the callback address. (Not
5340 	 * exactly correct by the RFC, but avoids a lot of Getattr
5341 	 * callbacks.)
5342 	 */
5343 	if (nd->nd_compref == stp->ls_compref ||
5344 	    ((nd->nd_flag & ND_IMPLIEDCLID) &&
5345 	     clp->lc_clientid.qval == nd->nd_clientid.qval) ||
5346 	     nfsaddr2_match(clp->lc_req.nr_nam, nd->nd_nam)) {
5347 		NFSUNLOCKSTATE();
5348 		goto out;
5349 	}
5350 
5351 	/*
5352 	 * We are now done with the delegation state structure,
5353 	 * so the statelock can be released and we can now tsleep().
5354 	 */
5355 
5356 	/*
5357 	 * Now, we must do the CB Getattr callback, to see if Change or Size
5358 	 * has changed.
5359 	 */
5360 	if (clp->lc_expiry >= NFSD_MONOSEC) {
5361 		NFSUNLOCKSTATE();
5362 		NFSVNO_ATTRINIT(&nva);
5363 		nva.na_filerev = NFS64BITSSET;
5364 		error = nfsrv_docallback(clp, NFSV4OP_CBGETATTR, NULL,
5365 		    0, &nfh, &nva, &cbbits, p);
5366 		if (!error) {
5367 			if ((nva.na_filerev != NFS64BITSSET &&
5368 			    nva.na_filerev > delegfilerev) ||
5369 			    (NFSVNO_ISSETSIZE(&nva) &&
5370 			     nva.na_size != nvap->na_size)) {
5371 				error = nfsvno_updfilerev(vp, nvap, cred, p);
5372 				if (NFSVNO_ISSETSIZE(&nva))
5373 					nvap->na_size = nva.na_size;
5374 			}
5375 		} else
5376 			error = 0;	/* Ignore callback errors for now. */
5377 	} else {
5378 		NFSUNLOCKSTATE();
5379 	}
5380 
5381 out:
5382 	NFSEXITCODE2(error, nd);
5383 	return (error);
5384 }
5385 
5386 /*
5387  * This function looks for openowners that haven't had any opens for
5388  * a while and throws them away. Called by an nfsd when NFSNSF_NOOPENS
5389  * is set.
5390  */
5391 APPLESTATIC void
5392 nfsrv_throwawayopens(NFSPROC_T *p)
5393 {
5394 	struct nfsclient *clp, *nclp;
5395 	struct nfsstate *stp, *nstp;
5396 	int i;
5397 
5398 	NFSLOCKSTATE();
5399 	nfsrv_stablefirst.nsf_flags &= ~NFSNSF_NOOPENS;
5400 	/*
5401 	 * For each client...
5402 	 */
5403 	for (i = 0; i < nfsrv_clienthashsize; i++) {
5404 	    LIST_FOREACH_SAFE(clp, &nfsclienthash[i], lc_hash, nclp) {
5405 		LIST_FOREACH_SAFE(stp, &clp->lc_open, ls_list, nstp) {
5406 			if (LIST_EMPTY(&stp->ls_open) &&
5407 			    (stp->ls_noopens > NFSNOOPEN ||
5408 			     (nfsrv_openpluslock * 2) >
5409 			     nfsrv_v4statelimit))
5410 				nfsrv_freeopenowner(stp, 0, p);
5411 		}
5412 	    }
5413 	}
5414 	NFSUNLOCKSTATE();
5415 }
5416 
5417 /*
5418  * This function checks to see if the credentials are the same.
5419  * Returns 1 for not same, 0 otherwise.
5420  */
5421 static int
5422 nfsrv_notsamecredname(struct nfsrv_descript *nd, struct nfsclient *clp)
5423 {
5424 
5425 	if (nd->nd_flag & ND_GSS) {
5426 		if (!(clp->lc_flags & LCL_GSS))
5427 			return (1);
5428 		if (clp->lc_flags & LCL_NAME) {
5429 			if (nd->nd_princlen != clp->lc_namelen ||
5430 			    NFSBCMP(nd->nd_principal, clp->lc_name,
5431 				clp->lc_namelen))
5432 				return (1);
5433 			else
5434 				return (0);
5435 		}
5436 		if (nd->nd_cred->cr_uid == clp->lc_uid)
5437 			return (0);
5438 		else
5439 			return (1);
5440 	} else if (clp->lc_flags & LCL_GSS)
5441 		return (1);
5442 	/*
5443 	 * For AUTH_SYS, allow the same uid or root. (This is underspecified
5444 	 * in RFC3530, which talks about principals, but doesn't say anything
5445 	 * about uids for AUTH_SYS.)
5446 	 */
5447 	if (nd->nd_cred->cr_uid == clp->lc_uid || nd->nd_cred->cr_uid == 0)
5448 		return (0);
5449 	else
5450 		return (1);
5451 }
5452 
5453 /*
5454  * Calculate the lease expiry time.
5455  */
5456 static time_t
5457 nfsrv_leaseexpiry(void)
5458 {
5459 
5460 	if (nfsrv_stablefirst.nsf_eograce > NFSD_MONOSEC)
5461 		return (NFSD_MONOSEC + 2 * (nfsrv_lease + NFSRV_LEASEDELTA));
5462 	return (NFSD_MONOSEC + nfsrv_lease + NFSRV_LEASEDELTA);
5463 }
5464 
5465 /*
5466  * Delay the delegation timeout as far as ls_delegtimelimit, as required.
5467  */
5468 static void
5469 nfsrv_delaydelegtimeout(struct nfsstate *stp)
5470 {
5471 
5472 	if ((stp->ls_flags & NFSLCK_DELEGRECALL) == 0)
5473 		return;
5474 
5475 	if ((stp->ls_delegtime + 15) > NFSD_MONOSEC &&
5476 	    stp->ls_delegtime < stp->ls_delegtimelimit) {
5477 		stp->ls_delegtime += nfsrv_lease;
5478 		if (stp->ls_delegtime > stp->ls_delegtimelimit)
5479 			stp->ls_delegtime = stp->ls_delegtimelimit;
5480 	}
5481 }
5482 
5483 /*
5484  * This function checks to see if there is any other state associated
5485  * with the openowner for this Open.
5486  * It returns 1 if there is no other state, 0 otherwise.
5487  */
5488 static int
5489 nfsrv_nootherstate(struct nfsstate *stp)
5490 {
5491 	struct nfsstate *tstp;
5492 
5493 	LIST_FOREACH(tstp, &stp->ls_openowner->ls_open, ls_list) {
5494 		if (tstp != stp || !LIST_EMPTY(&tstp->ls_lock))
5495 			return (0);
5496 	}
5497 	return (1);
5498 }
5499 
5500 /*
5501  * Create a list of lock deltas (changes to local byte range locking
5502  * that can be rolled back using the list) and apply the changes via
5503  * nfsvno_advlock(). Optionally, lock the list. It is expected that either
5504  * the rollback or update function will be called after this.
5505  * It returns an error (and rolls back, as required), if any nfsvno_advlock()
5506  * call fails. If it returns an error, it will unlock the list.
5507  */
5508 static int
5509 nfsrv_locallock(vnode_t vp, struct nfslockfile *lfp, int flags,
5510     uint64_t first, uint64_t end, struct nfslockconflict *cfp, NFSPROC_T *p)
5511 {
5512 	struct nfslock *lop, *nlop;
5513 	int error = 0;
5514 
5515 	/* Loop through the list of locks. */
5516 	lop = LIST_FIRST(&lfp->lf_locallock);
5517 	while (first < end && lop != NULL) {
5518 		nlop = LIST_NEXT(lop, lo_lckowner);
5519 		if (first >= lop->lo_end) {
5520 			/* not there yet */
5521 			lop = nlop;
5522 		} else if (first < lop->lo_first) {
5523 			/* new one starts before entry in list */
5524 			if (end <= lop->lo_first) {
5525 				/* no overlap between old and new */
5526 				error = nfsrv_dolocal(vp, lfp, flags,
5527 				    NFSLCK_UNLOCK, first, end, cfp, p);
5528 				if (error != 0)
5529 					break;
5530 				first = end;
5531 			} else {
5532 				/* handle fragment overlapped with new one */
5533 				error = nfsrv_dolocal(vp, lfp, flags,
5534 				    NFSLCK_UNLOCK, first, lop->lo_first, cfp,
5535 				    p);
5536 				if (error != 0)
5537 					break;
5538 				first = lop->lo_first;
5539 			}
5540 		} else {
5541 			/* new one overlaps this entry in list */
5542 			if (end <= lop->lo_end) {
5543 				/* overlaps all of new one */
5544 				error = nfsrv_dolocal(vp, lfp, flags,
5545 				    lop->lo_flags, first, end, cfp, p);
5546 				if (error != 0)
5547 					break;
5548 				first = end;
5549 			} else {
5550 				/* handle fragment overlapped with new one */
5551 				error = nfsrv_dolocal(vp, lfp, flags,
5552 				    lop->lo_flags, first, lop->lo_end, cfp, p);
5553 				if (error != 0)
5554 					break;
5555 				first = lop->lo_end;
5556 				lop = nlop;
5557 			}
5558 		}
5559 	}
5560 	if (first < end && error == 0)
5561 		/* handle fragment past end of list */
5562 		error = nfsrv_dolocal(vp, lfp, flags, NFSLCK_UNLOCK, first,
5563 		    end, cfp, p);
5564 
5565 	NFSEXITCODE(error);
5566 	return (error);
5567 }
5568 
5569 /*
5570  * Local lock unlock. Unlock all byte ranges that are no longer locked
5571  * by NFSv4. To do this, unlock any subranges of first-->end that
5572  * do not overlap with the byte ranges of any lock in the lfp->lf_lock
5573  * list. This list has all locks for the file held by other
5574  * <clientid, lockowner> tuples. The list is ordered by increasing
5575  * lo_first value, but may have entries that overlap each other, for
5576  * the case of read locks.
5577  */
5578 static void
5579 nfsrv_localunlock(vnode_t vp, struct nfslockfile *lfp, uint64_t init_first,
5580     uint64_t init_end, NFSPROC_T *p)
5581 {
5582 	struct nfslock *lop;
5583 	uint64_t first, end, prevfirst;
5584 
5585 	first = init_first;
5586 	end = init_end;
5587 	while (first < init_end) {
5588 		/* Loop through all nfs locks, adjusting first and end */
5589 		prevfirst = 0;
5590 		LIST_FOREACH(lop, &lfp->lf_lock, lo_lckfile) {
5591 			KASSERT(prevfirst <= lop->lo_first,
5592 			    ("nfsv4 locks out of order"));
5593 			KASSERT(lop->lo_first < lop->lo_end,
5594 			    ("nfsv4 bogus lock"));
5595 			prevfirst = lop->lo_first;
5596 			if (first >= lop->lo_first &&
5597 			    first < lop->lo_end)
5598 				/*
5599 				 * Overlaps with initial part, so trim
5600 				 * off that initial part by moving first past
5601 				 * it.
5602 				 */
5603 				first = lop->lo_end;
5604 			else if (end > lop->lo_first &&
5605 			    lop->lo_first > first) {
5606 				/*
5607 				 * This lock defines the end of the
5608 				 * segment to unlock, so set end to the
5609 				 * start of it and break out of the loop.
5610 				 */
5611 				end = lop->lo_first;
5612 				break;
5613 			}
5614 			if (first >= end)
5615 				/*
5616 				 * There is no segment left to do, so
5617 				 * break out of this loop and then exit
5618 				 * the outer while() since first will be set
5619 				 * to end, which must equal init_end here.
5620 				 */
5621 				break;
5622 		}
5623 		if (first < end) {
5624 			/* Unlock this segment */
5625 			(void) nfsrv_dolocal(vp, lfp, NFSLCK_UNLOCK,
5626 			    NFSLCK_READ, first, end, NULL, p);
5627 			nfsrv_locallock_commit(lfp, NFSLCK_UNLOCK,
5628 			    first, end);
5629 		}
5630 		/*
5631 		 * Now move past this segment and look for any further
5632 		 * segment in the range, if there is one.
5633 		 */
5634 		first = end;
5635 		end = init_end;
5636 	}
5637 }
5638 
5639 /*
5640  * Do the local lock operation and update the rollback list, as required.
5641  * Perform the rollback and return the error if nfsvno_advlock() fails.
5642  */
5643 static int
5644 nfsrv_dolocal(vnode_t vp, struct nfslockfile *lfp, int flags, int oldflags,
5645     uint64_t first, uint64_t end, struct nfslockconflict *cfp, NFSPROC_T *p)
5646 {
5647 	struct nfsrollback *rlp;
5648 	int error = 0, ltype, oldltype;
5649 
5650 	if (flags & NFSLCK_WRITE)
5651 		ltype = F_WRLCK;
5652 	else if (flags & NFSLCK_READ)
5653 		ltype = F_RDLCK;
5654 	else
5655 		ltype = F_UNLCK;
5656 	if (oldflags & NFSLCK_WRITE)
5657 		oldltype = F_WRLCK;
5658 	else if (oldflags & NFSLCK_READ)
5659 		oldltype = F_RDLCK;
5660 	else
5661 		oldltype = F_UNLCK;
5662 	if (ltype == oldltype || (oldltype == F_WRLCK && ltype == F_RDLCK))
5663 		/* nothing to do */
5664 		goto out;
5665 	error = nfsvno_advlock(vp, ltype, first, end, p);
5666 	if (error != 0) {
5667 		if (cfp != NULL) {
5668 			cfp->cl_clientid.lval[0] = 0;
5669 			cfp->cl_clientid.lval[1] = 0;
5670 			cfp->cl_first = 0;
5671 			cfp->cl_end = NFS64BITSSET;
5672 			cfp->cl_flags = NFSLCK_WRITE;
5673 			cfp->cl_ownerlen = 5;
5674 			NFSBCOPY("LOCAL", cfp->cl_owner, 5);
5675 		}
5676 		nfsrv_locallock_rollback(vp, lfp, p);
5677 	} else if (ltype != F_UNLCK) {
5678 		rlp = malloc(sizeof (struct nfsrollback), M_NFSDROLLBACK,
5679 		    M_WAITOK);
5680 		rlp->rlck_first = first;
5681 		rlp->rlck_end = end;
5682 		rlp->rlck_type = oldltype;
5683 		LIST_INSERT_HEAD(&lfp->lf_rollback, rlp, rlck_list);
5684 	}
5685 
5686 out:
5687 	NFSEXITCODE(error);
5688 	return (error);
5689 }
5690 
5691 /*
5692  * Roll back local lock changes and free up the rollback list.
5693  */
5694 static void
5695 nfsrv_locallock_rollback(vnode_t vp, struct nfslockfile *lfp, NFSPROC_T *p)
5696 {
5697 	struct nfsrollback *rlp, *nrlp;
5698 
5699 	LIST_FOREACH_SAFE(rlp, &lfp->lf_rollback, rlck_list, nrlp) {
5700 		(void) nfsvno_advlock(vp, rlp->rlck_type, rlp->rlck_first,
5701 		    rlp->rlck_end, p);
5702 		free(rlp, M_NFSDROLLBACK);
5703 	}
5704 	LIST_INIT(&lfp->lf_rollback);
5705 }
5706 
5707 /*
5708  * Update local lock list and delete rollback list (ie now committed to the
5709  * local locks). Most of the work is done by the internal function.
5710  */
5711 static void
5712 nfsrv_locallock_commit(struct nfslockfile *lfp, int flags, uint64_t first,
5713     uint64_t end)
5714 {
5715 	struct nfsrollback *rlp, *nrlp;
5716 	struct nfslock *new_lop, *other_lop;
5717 
5718 	new_lop = malloc(sizeof (struct nfslock), M_NFSDLOCK, M_WAITOK);
5719 	if (flags & (NFSLCK_READ | NFSLCK_WRITE))
5720 		other_lop = malloc(sizeof (struct nfslock), M_NFSDLOCK,
5721 		    M_WAITOK);
5722 	else
5723 		other_lop = NULL;
5724 	new_lop->lo_flags = flags;
5725 	new_lop->lo_first = first;
5726 	new_lop->lo_end = end;
5727 	nfsrv_updatelock(NULL, &new_lop, &other_lop, lfp);
5728 	if (new_lop != NULL)
5729 		free(new_lop, M_NFSDLOCK);
5730 	if (other_lop != NULL)
5731 		free(other_lop, M_NFSDLOCK);
5732 
5733 	/* and get rid of the rollback list */
5734 	LIST_FOREACH_SAFE(rlp, &lfp->lf_rollback, rlck_list, nrlp)
5735 		free(rlp, M_NFSDROLLBACK);
5736 	LIST_INIT(&lfp->lf_rollback);
5737 }
5738 
5739 /*
5740  * Lock the struct nfslockfile for local lock updating.
5741  */
5742 static void
5743 nfsrv_locklf(struct nfslockfile *lfp)
5744 {
5745 	int gotlock;
5746 
5747 	/* lf_usecount ensures *lfp won't be free'd */
5748 	lfp->lf_usecount++;
5749 	do {
5750 		gotlock = nfsv4_lock(&lfp->lf_locallock_lck, 1, NULL,
5751 		    NFSSTATEMUTEXPTR, NULL);
5752 	} while (gotlock == 0);
5753 	lfp->lf_usecount--;
5754 }
5755 
5756 /*
5757  * Unlock the struct nfslockfile after local lock updating.
5758  */
5759 static void
5760 nfsrv_unlocklf(struct nfslockfile *lfp)
5761 {
5762 
5763 	nfsv4_unlock(&lfp->lf_locallock_lck, 0);
5764 }
5765 
5766 /*
5767  * Clear out all state for the NFSv4 server.
5768  * Must be called by a thread that can sleep when no nfsds are running.
5769  */
5770 void
5771 nfsrv_throwawayallstate(NFSPROC_T *p)
5772 {
5773 	struct nfsclient *clp, *nclp;
5774 	struct nfslockfile *lfp, *nlfp;
5775 	int i;
5776 
5777 	/*
5778 	 * For each client, clean out the state and then free the structure.
5779 	 */
5780 	for (i = 0; i < nfsrv_clienthashsize; i++) {
5781 		LIST_FOREACH_SAFE(clp, &nfsclienthash[i], lc_hash, nclp) {
5782 			nfsrv_cleanclient(clp, p);
5783 			nfsrv_freedeleglist(&clp->lc_deleg);
5784 			nfsrv_freedeleglist(&clp->lc_olddeleg);
5785 			free(clp->lc_stateid, M_NFSDCLIENT);
5786 			free(clp, M_NFSDCLIENT);
5787 		}
5788 	}
5789 
5790 	/*
5791 	 * Also, free up any remaining lock file structures.
5792 	 */
5793 	for (i = 0; i < nfsrv_lockhashsize; i++) {
5794 		LIST_FOREACH_SAFE(lfp, &nfslockhash[i], lf_hash, nlfp) {
5795 			printf("nfsd unload: fnd a lock file struct\n");
5796 			nfsrv_freenfslockfile(lfp);
5797 		}
5798 	}
5799 }
5800 
5801 /*
5802  * Check the sequence# for the session and slot provided as an argument.
5803  * Also, renew the lease if the session will return NFS_OK.
5804  */
5805 int
5806 nfsrv_checksequence(struct nfsrv_descript *nd, uint32_t sequenceid,
5807     uint32_t *highest_slotidp, uint32_t *target_highest_slotidp, int cache_this,
5808     uint32_t *sflagsp, NFSPROC_T *p)
5809 {
5810 	struct nfsdsession *sep;
5811 	struct nfssessionhash *shp;
5812 	int error;
5813 	SVCXPRT *savxprt;
5814 
5815 	shp = NFSSESSIONHASH(nd->nd_sessionid);
5816 	NFSLOCKSESSION(shp);
5817 	sep = nfsrv_findsession(nd->nd_sessionid);
5818 	if (sep == NULL) {
5819 		NFSUNLOCKSESSION(shp);
5820 		return (NFSERR_BADSESSION);
5821 	}
5822 	error = nfsv4_seqsession(sequenceid, nd->nd_slotid, *highest_slotidp,
5823 	    sep->sess_slots, NULL, NFSV4_SLOTS - 1);
5824 	if (error != 0) {
5825 		NFSUNLOCKSESSION(shp);
5826 		return (error);
5827 	}
5828 	if (cache_this != 0)
5829 		nd->nd_flag |= ND_SAVEREPLY;
5830 	/* Renew the lease. */
5831 	sep->sess_clp->lc_expiry = nfsrv_leaseexpiry();
5832 	nd->nd_clientid.qval = sep->sess_clp->lc_clientid.qval;
5833 	nd->nd_flag |= ND_IMPLIEDCLID;
5834 
5835 	/*
5836 	 * If this session handles the backchannel, save the nd_xprt for this
5837 	 * RPC, since this is the one being used.
5838 	 */
5839 	if (sep->sess_clp->lc_req.nr_client != NULL &&
5840 	    (sep->sess_crflags & NFSV4CRSESS_CONNBACKCHAN) != 0) {
5841 		savxprt = sep->sess_cbsess.nfsess_xprt;
5842 		SVC_ACQUIRE(nd->nd_xprt);
5843 		nd->nd_xprt->xp_p2 =
5844 		    sep->sess_clp->lc_req.nr_client->cl_private;
5845 		nd->nd_xprt->xp_idletimeout = 0;	/* Disable timeout. */
5846 		sep->sess_cbsess.nfsess_xprt = nd->nd_xprt;
5847 		if (savxprt != NULL)
5848 			SVC_RELEASE(savxprt);
5849 	}
5850 
5851 	*sflagsp = 0;
5852 	if (sep->sess_clp->lc_req.nr_client == NULL)
5853 		*sflagsp |= NFSV4SEQ_CBPATHDOWN;
5854 	NFSUNLOCKSESSION(shp);
5855 	if (error == NFSERR_EXPIRED) {
5856 		*sflagsp |= NFSV4SEQ_EXPIREDALLSTATEREVOKED;
5857 		error = 0;
5858 	} else if (error == NFSERR_ADMINREVOKED) {
5859 		*sflagsp |= NFSV4SEQ_ADMINSTATEREVOKED;
5860 		error = 0;
5861 	}
5862 	*highest_slotidp = *target_highest_slotidp = NFSV4_SLOTS - 1;
5863 	return (0);
5864 }
5865 
5866 /*
5867  * Check/set reclaim complete for this session/clientid.
5868  */
5869 int
5870 nfsrv_checkreclaimcomplete(struct nfsrv_descript *nd)
5871 {
5872 	struct nfsdsession *sep;
5873 	struct nfssessionhash *shp;
5874 	int error = 0;
5875 
5876 	shp = NFSSESSIONHASH(nd->nd_sessionid);
5877 	NFSLOCKSTATE();
5878 	NFSLOCKSESSION(shp);
5879 	sep = nfsrv_findsession(nd->nd_sessionid);
5880 	if (sep == NULL) {
5881 		NFSUNLOCKSESSION(shp);
5882 		NFSUNLOCKSTATE();
5883 		return (NFSERR_BADSESSION);
5884 	}
5885 
5886 	/* Check to see if reclaim complete has already happened. */
5887 	if ((sep->sess_clp->lc_flags & LCL_RECLAIMCOMPLETE) != 0)
5888 		error = NFSERR_COMPLETEALREADY;
5889 	else
5890 		sep->sess_clp->lc_flags |= LCL_RECLAIMCOMPLETE;
5891 	NFSUNLOCKSESSION(shp);
5892 	NFSUNLOCKSTATE();
5893 	return (error);
5894 }
5895 
5896 /*
5897  * Cache the reply in a session slot.
5898  */
5899 void
5900 nfsrv_cache_session(uint8_t *sessionid, uint32_t slotid, int repstat,
5901    struct mbuf **m)
5902 {
5903 	struct nfsdsession *sep;
5904 	struct nfssessionhash *shp;
5905 
5906 	shp = NFSSESSIONHASH(sessionid);
5907 	NFSLOCKSESSION(shp);
5908 	sep = nfsrv_findsession(sessionid);
5909 	if (sep == NULL) {
5910 		NFSUNLOCKSESSION(shp);
5911 		printf("nfsrv_cache_session: no session\n");
5912 		m_freem(*m);
5913 		return;
5914 	}
5915 	nfsv4_seqsess_cacherep(slotid, sep->sess_slots, repstat, m);
5916 	NFSUNLOCKSESSION(shp);
5917 }
5918 
5919 /*
5920  * Search for a session that matches the sessionid.
5921  */
5922 static struct nfsdsession *
5923 nfsrv_findsession(uint8_t *sessionid)
5924 {
5925 	struct nfsdsession *sep;
5926 	struct nfssessionhash *shp;
5927 
5928 	shp = NFSSESSIONHASH(sessionid);
5929 	LIST_FOREACH(sep, &shp->list, sess_hash) {
5930 		if (!NFSBCMP(sessionid, sep->sess_sessionid, NFSX_V4SESSIONID))
5931 			break;
5932 	}
5933 	return (sep);
5934 }
5935 
5936 /*
5937  * Destroy a session.
5938  */
5939 int
5940 nfsrv_destroysession(struct nfsrv_descript *nd, uint8_t *sessionid)
5941 {
5942 	int error, samesess;
5943 
5944 	samesess = 0;
5945 	if (!NFSBCMP(sessionid, nd->nd_sessionid, NFSX_V4SESSIONID)) {
5946 		samesess = 1;
5947 		if ((nd->nd_flag & ND_LASTOP) == 0)
5948 			return (NFSERR_BADSESSION);
5949 	}
5950 	error = nfsrv_freesession(NULL, sessionid);
5951 	if (error == 0 && samesess != 0)
5952 		nd->nd_flag &= ~ND_HASSEQUENCE;
5953 	return (error);
5954 }
5955 
5956 /*
5957  * Free up a session structure.
5958  */
5959 static int
5960 nfsrv_freesession(struct nfsdsession *sep, uint8_t *sessionid)
5961 {
5962 	struct nfssessionhash *shp;
5963 	int i;
5964 
5965 	NFSLOCKSTATE();
5966 	if (sep == NULL) {
5967 		shp = NFSSESSIONHASH(sessionid);
5968 		NFSLOCKSESSION(shp);
5969 		sep = nfsrv_findsession(sessionid);
5970 	} else {
5971 		shp = NFSSESSIONHASH(sep->sess_sessionid);
5972 		NFSLOCKSESSION(shp);
5973 	}
5974 	if (sep != NULL) {
5975 		sep->sess_refcnt--;
5976 		if (sep->sess_refcnt > 0) {
5977 			NFSUNLOCKSESSION(shp);
5978 			NFSUNLOCKSTATE();
5979 			return (0);
5980 		}
5981 		LIST_REMOVE(sep, sess_hash);
5982 		LIST_REMOVE(sep, sess_list);
5983 	}
5984 	NFSUNLOCKSESSION(shp);
5985 	NFSUNLOCKSTATE();
5986 	if (sep == NULL)
5987 		return (NFSERR_BADSESSION);
5988 	for (i = 0; i < NFSV4_SLOTS; i++)
5989 		if (sep->sess_slots[i].nfssl_reply != NULL)
5990 			m_freem(sep->sess_slots[i].nfssl_reply);
5991 	if (sep->sess_cbsess.nfsess_xprt != NULL)
5992 		SVC_RELEASE(sep->sess_cbsess.nfsess_xprt);
5993 	free(sep, M_NFSDSESSION);
5994 	return (0);
5995 }
5996 
5997 /*
5998  * Free a stateid.
5999  * RFC5661 says that it should fail when there are associated opens, locks
6000  * or delegations. Since stateids represent opens, I don't see how you can
6001  * free an open stateid (it will be free'd when closed), so this function
6002  * only works for lock stateids (freeing the lock_owner) or delegations.
6003  */
6004 int
6005 nfsrv_freestateid(struct nfsrv_descript *nd, nfsv4stateid_t *stateidp,
6006     NFSPROC_T *p)
6007 {
6008 	struct nfsclient *clp;
6009 	struct nfsstate *stp;
6010 	int error;
6011 
6012 	NFSLOCKSTATE();
6013 	/*
6014 	 * Look up the stateid
6015 	 */
6016 	error = nfsrv_getclient((nfsquad_t)((u_quad_t)0), CLOPS_RENEW, &clp,
6017 	    NULL, (nfsquad_t)((u_quad_t)0), 0, nd, p);
6018 	if (error == 0) {
6019 		/* First, check for a delegation. */
6020 		LIST_FOREACH(stp, &clp->lc_deleg, ls_list) {
6021 			if (!NFSBCMP(stp->ls_stateid.other, stateidp->other,
6022 			    NFSX_STATEIDOTHER))
6023 				break;
6024 		}
6025 		if (stp != NULL) {
6026 			nfsrv_freedeleg(stp);
6027 			NFSUNLOCKSTATE();
6028 			return (error);
6029 		}
6030 	}
6031 	/* Not a delegation, try for a lock_owner. */
6032 	if (error == 0)
6033 		error = nfsrv_getstate(clp, stateidp, 0, &stp);
6034 	if (error == 0 && ((stp->ls_flags & (NFSLCK_OPEN | NFSLCK_DELEGREAD |
6035 	    NFSLCK_DELEGWRITE)) != 0 || (stp->ls_flags & NFSLCK_LOCK) == 0))
6036 		/* Not a lock_owner stateid. */
6037 		error = NFSERR_LOCKSHELD;
6038 	if (error == 0 && !LIST_EMPTY(&stp->ls_lock))
6039 		error = NFSERR_LOCKSHELD;
6040 	if (error == 0)
6041 		nfsrv_freelockowner(stp, NULL, 0, p);
6042 	NFSUNLOCKSTATE();
6043 	return (error);
6044 }
6045 
6046 /*
6047  * Generate the xdr for an NFSv4.1 CBSequence Operation.
6048  */
6049 static int
6050 nfsv4_setcbsequence(struct nfsrv_descript *nd, struct nfsclient *clp,
6051     int dont_replycache, struct nfsdsession **sepp)
6052 {
6053 	struct nfsdsession *sep;
6054 	uint32_t *tl, slotseq = 0;
6055 	int maxslot, slotpos;
6056 	uint8_t sessionid[NFSX_V4SESSIONID];
6057 	int error;
6058 
6059 	error = nfsv4_getcbsession(clp, sepp);
6060 	if (error != 0)
6061 		return (error);
6062 	sep = *sepp;
6063 	(void)nfsv4_sequencelookup(NULL, &sep->sess_cbsess, &slotpos, &maxslot,
6064 	    &slotseq, sessionid);
6065 	KASSERT(maxslot >= 0, ("nfsv4_setcbsequence neg maxslot"));
6066 
6067 	/* Build the Sequence arguments. */
6068 	NFSM_BUILD(tl, uint32_t *, NFSX_V4SESSIONID + 5 * NFSX_UNSIGNED);
6069 	bcopy(sessionid, tl, NFSX_V4SESSIONID);
6070 	tl += NFSX_V4SESSIONID / NFSX_UNSIGNED;
6071 	nd->nd_slotseq = tl;
6072 	*tl++ = txdr_unsigned(slotseq);
6073 	*tl++ = txdr_unsigned(slotpos);
6074 	*tl++ = txdr_unsigned(maxslot);
6075 	if (dont_replycache == 0)
6076 		*tl++ = newnfs_true;
6077 	else
6078 		*tl++ = newnfs_false;
6079 	*tl = 0;			/* No referring call list, for now. */
6080 	nd->nd_flag |= ND_HASSEQUENCE;
6081 	return (0);
6082 }
6083 
6084 /*
6085  * Get a session for the callback.
6086  */
6087 static int
6088 nfsv4_getcbsession(struct nfsclient *clp, struct nfsdsession **sepp)
6089 {
6090 	struct nfsdsession *sep;
6091 
6092 	NFSLOCKSTATE();
6093 	LIST_FOREACH(sep, &clp->lc_session, sess_list) {
6094 		if ((sep->sess_crflags & NFSV4CRSESS_CONNBACKCHAN) != 0)
6095 			break;
6096 	}
6097 	if (sep == NULL) {
6098 		NFSUNLOCKSTATE();
6099 		return (NFSERR_BADSESSION);
6100 	}
6101 	sep->sess_refcnt++;
6102 	*sepp = sep;
6103 	NFSUNLOCKSTATE();
6104 	return (0);
6105 }
6106 
6107 /*
6108  * Free up all backchannel xprts.  This needs to be done when the nfsd threads
6109  * exit, since those transports will all be going away.
6110  * This is only called after all the nfsd threads are done performing RPCs,
6111  * so locking shouldn't be an issue.
6112  */
6113 APPLESTATIC void
6114 nfsrv_freeallbackchannel_xprts(void)
6115 {
6116 	struct nfsdsession *sep;
6117 	struct nfsclient *clp;
6118 	SVCXPRT *xprt;
6119 	int i;
6120 
6121 	for (i = 0; i < nfsrv_clienthashsize; i++) {
6122 		LIST_FOREACH(clp, &nfsclienthash[i], lc_hash) {
6123 			LIST_FOREACH(sep, &clp->lc_session, sess_list) {
6124 				xprt = sep->sess_cbsess.nfsess_xprt;
6125 				sep->sess_cbsess.nfsess_xprt = NULL;
6126 				if (xprt != NULL)
6127 					SVC_RELEASE(xprt);
6128 			}
6129 		}
6130 	}
6131 }
6132 
6133