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