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