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