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