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