]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/fs/nfsserver/nfs_nfsdstate.c
Import lua 5.3.4 to contrib
[FreeBSD/FreeBSD.git] / sys / fs / nfsserver / nfs_nfsdstate.c
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