]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - sys/fs/nfsserver/nfs_nfsdstate.c
MFC: r357149
[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                                 if (tvp != NULL)
1492                                         NFSVOPUNLOCK(tvp, 0);
1493                         } else
1494                                 tvp = vp;
1495                         gottvp = 1;
1496                 }
1497
1498                 if (tvp != NULL) {
1499                         if (cansleep == 0)
1500                                 panic("allnfs2");
1501                         first = lop->lo_first;
1502                         end = lop->lo_end;
1503                         nfsrv_freenfslock(lop);
1504                         nfsrv_localunlock(tvp, lfp, first, end, p);
1505                         LIST_FOREACH_SAFE(rlp, &lfp->lf_rollback, rlck_list,
1506                             nrlp)
1507                                 free(rlp, M_NFSDROLLBACK);
1508                         LIST_INIT(&lfp->lf_rollback);
1509                 } else
1510                         nfsrv_freenfslock(lop);
1511                 lop = nlop;
1512         }
1513         if (vp == NULL && tvp != NULL)
1514                 vrele(tvp);
1515 }
1516
1517 /*
1518  * Free an nfslock structure.
1519  */
1520 static void
1521 nfsrv_freenfslock(struct nfslock *lop)
1522 {
1523
1524         if (lop->lo_lckfile.le_prev != NULL) {
1525                 LIST_REMOVE(lop, lo_lckfile);
1526                 newnfsstats.srvlocks--;
1527                 nfsrv_openpluslock--;
1528         }
1529         LIST_REMOVE(lop, lo_lckowner);
1530         FREE((caddr_t)lop, M_NFSDLOCK);
1531 }
1532
1533 /*
1534  * This function frees an nfslockfile structure.
1535  */
1536 static void
1537 nfsrv_freenfslockfile(struct nfslockfile *lfp)
1538 {
1539
1540         LIST_REMOVE(lfp, lf_hash);
1541         FREE((caddr_t)lfp, M_NFSDLOCKFILE);
1542 }
1543
1544 /*
1545  * This function looks up an nfsstate structure via stateid.
1546  */
1547 static int
1548 nfsrv_getstate(struct nfsclient *clp, nfsv4stateid_t *stateidp, __unused u_int32_t flags,
1549     struct nfsstate **stpp)
1550 {
1551         struct nfsstate *stp;
1552         struct nfsstatehead *hp;
1553         int error = 0;
1554
1555         *stpp = NULL;
1556         hp = NFSSTATEHASH(clp, *stateidp);
1557         LIST_FOREACH(stp, hp, ls_hash) {
1558                 if (!NFSBCMP(stp->ls_stateid.other, stateidp->other,
1559                         NFSX_STATEIDOTHER))
1560                         break;
1561         }
1562
1563         /*
1564          * If no state id in list, return NFSERR_BADSTATEID.
1565          */
1566         if (stp == LIST_END(hp)) {
1567                 error = NFSERR_BADSTATEID;
1568                 goto out;
1569         }
1570         *stpp = stp;
1571
1572 out:
1573         NFSEXITCODE(error);
1574         return (error);
1575 }
1576
1577 /*
1578  * This function gets an nfsstate structure via owner string.
1579  */
1580 static void
1581 nfsrv_getowner(struct nfsstatehead *hp, struct nfsstate *new_stp,
1582     struct nfsstate **stpp)
1583 {
1584         struct nfsstate *stp;
1585
1586         *stpp = NULL;
1587         LIST_FOREACH(stp, hp, ls_list) {
1588                 if (new_stp->ls_ownerlen == stp->ls_ownerlen &&
1589                   !NFSBCMP(new_stp->ls_owner,stp->ls_owner,stp->ls_ownerlen)) {
1590                         *stpp = stp;
1591                         return;
1592                 }
1593         }
1594 }
1595
1596 /*
1597  * Lock control function called to update lock status.
1598  * Returns 0 upon success, -1 if there is no lock and the flags indicate
1599  * that one isn't to be created and an NFSERR_xxx for other errors.
1600  * The structures new_stp and new_lop are passed in as pointers that should
1601  * be set to NULL if the structure is used and shouldn't be free'd.
1602  * For the NFSLCK_TEST and NFSLCK_CHECK cases, the structures are
1603  * never used and can safely be allocated on the stack. For all other
1604  * cases, *new_stpp and *new_lopp should be malloc'd before the call,
1605  * in case they are used.
1606  */
1607 APPLESTATIC int
1608 nfsrv_lockctrl(vnode_t vp, struct nfsstate **new_stpp,
1609     struct nfslock **new_lopp, struct nfslockconflict *cfp,
1610     nfsquad_t clientid, nfsv4stateid_t *stateidp,
1611     __unused struct nfsexstuff *exp,
1612     struct nfsrv_descript *nd, NFSPROC_T *p)
1613 {
1614         struct nfslock *lop;
1615         struct nfsstate *new_stp = *new_stpp;
1616         struct nfslock *new_lop = *new_lopp;
1617         struct nfsstate *tstp, *mystp, *nstp;
1618         int specialid = 0;
1619         struct nfslockfile *lfp;
1620         struct nfslock *other_lop = NULL;
1621         struct nfsstate *stp, *lckstp = NULL;
1622         struct nfsclient *clp = NULL;
1623         u_int32_t bits;
1624         int error = 0, haslock = 0, ret, reterr;
1625         int getlckret, delegation = 0, filestruct_locked, vnode_unlocked = 0;
1626         fhandle_t nfh;
1627         uint64_t first, end;
1628         uint32_t lock_flags;
1629
1630         if (new_stp->ls_flags & (NFSLCK_CHECK | NFSLCK_SETATTR)) {
1631                 /*
1632                  * Note the special cases of "all 1s" or "all 0s" stateids and
1633                  * let reads with all 1s go ahead.
1634                  */
1635                 if (new_stp->ls_stateid.seqid == 0x0 &&
1636                     new_stp->ls_stateid.other[0] == 0x0 &&
1637                     new_stp->ls_stateid.other[1] == 0x0 &&
1638                     new_stp->ls_stateid.other[2] == 0x0)
1639                         specialid = 1;
1640                 else if (new_stp->ls_stateid.seqid == 0xffffffff &&
1641                     new_stp->ls_stateid.other[0] == 0xffffffff &&
1642                     new_stp->ls_stateid.other[1] == 0xffffffff &&
1643                     new_stp->ls_stateid.other[2] == 0xffffffff)
1644                         specialid = 2;
1645         }
1646
1647         /*
1648          * Check for restart conditions (client and server).
1649          */
1650         error = nfsrv_checkrestart(clientid, new_stp->ls_flags,
1651             &new_stp->ls_stateid, specialid);
1652         if (error)
1653                 goto out;
1654
1655         /*
1656          * Check for state resource limit exceeded.
1657          */
1658         if ((new_stp->ls_flags & NFSLCK_LOCK) &&
1659             nfsrv_openpluslock > nfsrv_v4statelimit) {
1660                 error = NFSERR_RESOURCE;
1661                 goto out;
1662         }
1663
1664         /*
1665          * For the lock case, get another nfslock structure,
1666          * just in case we need it.
1667          * Malloc now, before we start sifting through the linked lists,
1668          * in case we have to wait for memory.
1669          */
1670 tryagain:
1671         if (new_stp->ls_flags & NFSLCK_LOCK)
1672                 MALLOC(other_lop, struct nfslock *, sizeof (struct nfslock),
1673                     M_NFSDLOCK, M_WAITOK);
1674         filestruct_locked = 0;
1675         reterr = 0;
1676         lfp = NULL;
1677
1678         /*
1679          * Get the lockfile structure for CFH now, so we can do a sanity
1680          * check against the stateid, before incrementing the seqid#, since
1681          * we want to return NFSERR_BADSTATEID on failure and the seqid#
1682          * shouldn't be incremented for this case.
1683          * If nfsrv_getlockfile() returns -1, it means "not found", which
1684          * will be handled later.
1685          * If we are doing Lock/LockU and local locking is enabled, sleep
1686          * lock the nfslockfile structure.
1687          */
1688         getlckret = nfsrv_getlockfh(vp, new_stp->ls_flags, NULL, &nfh, p);
1689         NFSLOCKSTATE();
1690         if (getlckret == 0) {
1691                 if ((new_stp->ls_flags & (NFSLCK_LOCK | NFSLCK_UNLOCK)) != 0 &&
1692                     nfsrv_dolocallocks != 0 && nd->nd_repstat == 0) {
1693                         getlckret = nfsrv_getlockfile(new_stp->ls_flags, NULL,
1694                             &lfp, &nfh, 1);
1695                         if (getlckret == 0)
1696                                 filestruct_locked = 1;
1697                 } else
1698                         getlckret = nfsrv_getlockfile(new_stp->ls_flags, NULL,
1699                             &lfp, &nfh, 0);
1700         }
1701         if (getlckret != 0 && getlckret != -1)
1702                 reterr = getlckret;
1703
1704         if (filestruct_locked != 0) {
1705                 LIST_INIT(&lfp->lf_rollback);
1706                 if ((new_stp->ls_flags & NFSLCK_LOCK)) {
1707                         /*
1708                          * For local locking, do the advisory locking now, so
1709                          * that any conflict can be detected. A failure later
1710                          * can be rolled back locally. If an error is returned,
1711                          * struct nfslockfile has been unlocked and any local
1712                          * locking rolled back.
1713                          */
1714                         NFSUNLOCKSTATE();
1715                         if (vnode_unlocked == 0) {
1716                                 ASSERT_VOP_ELOCKED(vp, "nfsrv_lockctrl1");
1717                                 vnode_unlocked = 1;
1718                                 NFSVOPUNLOCK(vp, 0);
1719                         }
1720                         reterr = nfsrv_locallock(vp, lfp,
1721                             (new_lop->lo_flags & (NFSLCK_READ | NFSLCK_WRITE)),
1722                             new_lop->lo_first, new_lop->lo_end, cfp, p);
1723                         NFSLOCKSTATE();
1724                 }
1725         }
1726
1727         if (specialid == 0) {
1728             if (new_stp->ls_flags & NFSLCK_TEST) {
1729                 /*
1730                  * RFC 3530 does not list LockT as an op that renews a
1731                  * lease, but the concensus seems to be that it is ok
1732                  * for a server to do so.
1733                  */
1734                 error = nfsrv_getclient(clientid, CLOPS_RENEW, &clp, NULL,
1735                     (nfsquad_t)((u_quad_t)0), 0, nd, p);
1736
1737                 /*
1738                  * Since NFSERR_EXPIRED, NFSERR_ADMINREVOKED are not valid
1739                  * error returns for LockT, just go ahead and test for a lock,
1740                  * since there are no locks for this client, but other locks
1741                  * can conflict. (ie. same client will always be false)
1742                  */
1743                 if (error == NFSERR_EXPIRED || error == NFSERR_ADMINREVOKED)
1744                     error = 0;
1745                 lckstp = new_stp;
1746             } else {
1747               error = nfsrv_getclient(clientid, CLOPS_RENEW, &clp, NULL,
1748                 (nfsquad_t)((u_quad_t)0), 0, nd, p);
1749               if (error == 0)
1750                 /*
1751                  * Look up the stateid
1752                  */
1753                 error = nfsrv_getstate(clp, &new_stp->ls_stateid,
1754                   new_stp->ls_flags, &stp);
1755               /*
1756                * do some sanity checks for an unconfirmed open or a
1757                * stateid that refers to the wrong file, for an open stateid
1758                */
1759               if (error == 0 && (stp->ls_flags & NFSLCK_OPEN) &&
1760                   ((stp->ls_openowner->ls_flags & NFSLCK_NEEDSCONFIRM) ||
1761                    (getlckret == 0 && stp->ls_lfp != lfp)))
1762                         error = NFSERR_BADSTATEID;
1763               if (error == 0 &&
1764                   (stp->ls_flags & (NFSLCK_DELEGREAD | NFSLCK_DELEGWRITE)) &&
1765                   getlckret == 0 && stp->ls_lfp != lfp)
1766                         error = NFSERR_BADSTATEID;
1767
1768               /*
1769                * If the lockowner stateid doesn't refer to the same file,
1770                * I believe that is considered ok, since some clients will
1771                * only create a single lockowner and use that for all locks
1772                * on all files.
1773                * For now, log it as a diagnostic, instead of considering it
1774                * a BadStateid.
1775                */
1776               if (error == 0 && (stp->ls_flags &
1777                   (NFSLCK_OPEN | NFSLCK_DELEGREAD | NFSLCK_DELEGWRITE)) == 0 &&
1778                   getlckret == 0 && stp->ls_lfp != lfp) {
1779 #ifdef DIAGNOSTIC
1780                   printf("Got a lock statid for different file open\n");
1781 #endif
1782                   /*
1783                   error = NFSERR_BADSTATEID;
1784                   */
1785               }
1786
1787               if (error == 0) {
1788                     if (new_stp->ls_flags & NFSLCK_OPENTOLOCK) {
1789                         /*
1790                          * If haslock set, we've already checked the seqid.
1791                          */
1792                         if (!haslock) {
1793                             if (stp->ls_flags & NFSLCK_OPEN)
1794                                 error = nfsrv_checkseqid(nd, new_stp->ls_seq,
1795                                     stp->ls_openowner, new_stp->ls_op);
1796                             else
1797                                 error = NFSERR_BADSTATEID;
1798                         }
1799                         if (!error)
1800                             nfsrv_getowner(&stp->ls_open, new_stp, &lckstp);
1801                         if (lckstp)
1802                             /*
1803                              * I believe this should be an error, but it
1804                              * isn't obvious what NFSERR_xxx would be
1805                              * appropriate, so I'll use NFSERR_INVAL for now.
1806                              */
1807                             error = NFSERR_INVAL;
1808                         else
1809                             lckstp = new_stp;
1810                     } else if (new_stp->ls_flags&(NFSLCK_LOCK|NFSLCK_UNLOCK)) {
1811                         /*
1812                          * If haslock set, ditto above.
1813                          */
1814                         if (!haslock) {
1815                             if (stp->ls_flags & NFSLCK_OPEN)
1816                                 error = NFSERR_BADSTATEID;
1817                             else
1818                                 error = nfsrv_checkseqid(nd, new_stp->ls_seq,
1819                                     stp, new_stp->ls_op);
1820                         }
1821                         lckstp = stp;
1822                     } else {
1823                         lckstp = stp;
1824                     }
1825               }
1826               /*
1827                * If the seqid part of the stateid isn't the same, return
1828                * NFSERR_OLDSTATEID for cases other than I/O Ops.
1829                * For I/O Ops, only return NFSERR_OLDSTATEID if
1830                * nfsrv_returnoldstateid is set. (The concensus on the email
1831                * list was that most clients would prefer to not receive
1832                * NFSERR_OLDSTATEID for I/O Ops, but the RFC suggests that that
1833                * is what will happen, so I use the nfsrv_returnoldstateid to
1834                * allow for either server configuration.)
1835                */
1836               if (!error && stp->ls_stateid.seqid!=new_stp->ls_stateid.seqid &&
1837                   (((nd->nd_flag & ND_NFSV41) == 0 &&
1838                    (!(new_stp->ls_flags & NFSLCK_CHECK) ||
1839                     nfsrv_returnoldstateid)) ||
1840                    ((nd->nd_flag & ND_NFSV41) != 0 &&
1841                     new_stp->ls_stateid.seqid != 0)))
1842                     error = NFSERR_OLDSTATEID;
1843             }
1844         }
1845
1846         /*
1847          * Now we can check for grace.
1848          */
1849         if (!error)
1850                 error = nfsrv_checkgrace(nd, clp, new_stp->ls_flags);
1851         if ((new_stp->ls_flags & NFSLCK_RECLAIM) && !error &&
1852                 nfsrv_checkstable(clp))
1853                 error = NFSERR_NOGRACE;
1854         /*
1855          * If we successfully Reclaimed state, note that.
1856          */
1857         if ((new_stp->ls_flags & NFSLCK_RECLAIM) && !error)
1858                 nfsrv_markstable(clp);
1859
1860         /*
1861          * At this point, either error == NFSERR_BADSTATEID or the
1862          * seqid# has been updated, so we can return any error.
1863          * If error == 0, there may be an error in:
1864          *    nd_repstat - Set by the calling function.
1865          *    reterr - Set above, if getting the nfslockfile structure
1866          *       or acquiring the local lock failed.
1867          *    (If both of these are set, nd_repstat should probably be
1868          *     returned, since that error was detected before this
1869          *     function call.)
1870          */
1871         if (error != 0 || nd->nd_repstat != 0 || reterr != 0) {
1872                 if (error == 0) {
1873                         if (nd->nd_repstat != 0)
1874                                 error = nd->nd_repstat;
1875                         else
1876                                 error = reterr;
1877                 }
1878                 if (filestruct_locked != 0) {
1879                         /* Roll back local locks. */
1880                         NFSUNLOCKSTATE();
1881                         if (vnode_unlocked == 0) {
1882                                 ASSERT_VOP_ELOCKED(vp, "nfsrv_lockctrl2");
1883                                 vnode_unlocked = 1;
1884                                 NFSVOPUNLOCK(vp, 0);
1885                         }
1886                         nfsrv_locallock_rollback(vp, lfp, p);
1887                         NFSLOCKSTATE();
1888                         nfsrv_unlocklf(lfp);
1889                 }
1890                 NFSUNLOCKSTATE();
1891                 goto out;
1892         }
1893
1894         /*
1895          * Check the nfsrv_getlockfile return.
1896          * Returned -1 if no structure found.
1897          */
1898         if (getlckret == -1) {
1899                 error = NFSERR_EXPIRED;
1900                 /*
1901                  * Called from lockt, so no lock is OK.
1902                  */
1903                 if (new_stp->ls_flags & NFSLCK_TEST) {
1904                         error = 0;
1905                 } else if (new_stp->ls_flags &
1906                     (NFSLCK_CHECK | NFSLCK_SETATTR)) {
1907                         /*
1908                          * Called to check for a lock, OK if the stateid is all
1909                          * 1s or all 0s, but there should be an nfsstate
1910                          * otherwise.
1911                          * (ie. If there is no open, I'll assume no share
1912                          *  deny bits.)
1913                          */
1914                         if (specialid)
1915                                 error = 0;
1916                         else
1917                                 error = NFSERR_BADSTATEID;
1918                 }
1919                 NFSUNLOCKSTATE();
1920                 goto out;
1921         }
1922
1923         /*
1924          * For NFSLCK_CHECK and NFSLCK_LOCK, test for a share conflict.
1925          * For NFSLCK_CHECK, allow a read if write access is granted,
1926          * but check for a deny. For NFSLCK_LOCK, require correct access,
1927          * which implies a conflicting deny can't exist.
1928          */
1929         if (new_stp->ls_flags & (NFSLCK_CHECK | NFSLCK_LOCK)) {
1930             /*
1931              * Four kinds of state id:
1932              * - specialid (all 0s or all 1s), only for NFSLCK_CHECK
1933              * - stateid for an open
1934              * - stateid for a delegation
1935              * - stateid for a lock owner
1936              */
1937             if (!specialid) {
1938                 if (stp->ls_flags & (NFSLCK_DELEGREAD | NFSLCK_DELEGWRITE)) {
1939                     delegation = 1;
1940                     mystp = stp;
1941                     nfsrv_delaydelegtimeout(stp);
1942                 } else if (stp->ls_flags & NFSLCK_OPEN) {
1943                     mystp = stp;
1944                 } else {
1945                     mystp = stp->ls_openstp;
1946                 }
1947                 /*
1948                  * If locking or checking, require correct access
1949                  * bit set.
1950                  */
1951                 if (((new_stp->ls_flags & NFSLCK_LOCK) &&
1952                      !((new_lop->lo_flags >> NFSLCK_LOCKSHIFT) &
1953                        mystp->ls_flags & NFSLCK_ACCESSBITS)) ||
1954                     ((new_stp->ls_flags & (NFSLCK_CHECK|NFSLCK_READACCESS)) ==
1955                       (NFSLCK_CHECK | NFSLCK_READACCESS) &&
1956                      !(mystp->ls_flags & NFSLCK_READACCESS) &&
1957                      nfsrv_allowreadforwriteopen == 0) ||
1958                     ((new_stp->ls_flags & (NFSLCK_CHECK|NFSLCK_WRITEACCESS)) ==
1959                       (NFSLCK_CHECK | NFSLCK_WRITEACCESS) &&
1960                      !(mystp->ls_flags & NFSLCK_WRITEACCESS))) {
1961                         if (filestruct_locked != 0) {
1962                                 /* Roll back local locks. */
1963                                 NFSUNLOCKSTATE();
1964                                 if (vnode_unlocked == 0) {
1965                                         ASSERT_VOP_ELOCKED(vp,
1966                                             "nfsrv_lockctrl3");
1967                                         vnode_unlocked = 1;
1968                                         NFSVOPUNLOCK(vp, 0);
1969                                 }
1970                                 nfsrv_locallock_rollback(vp, lfp, p);
1971                                 NFSLOCKSTATE();
1972                                 nfsrv_unlocklf(lfp);
1973                         }
1974                         NFSUNLOCKSTATE();
1975                         error = NFSERR_OPENMODE;
1976                         goto out;
1977                 }
1978             } else
1979                 mystp = NULL;
1980             if ((new_stp->ls_flags & NFSLCK_CHECK) && !delegation) {
1981                 /*
1982                  * Check for a conflicting deny bit.
1983                  */
1984                 LIST_FOREACH(tstp, &lfp->lf_open, ls_file) {
1985                     if (tstp != mystp) {
1986                         bits = tstp->ls_flags;
1987                         bits >>= NFSLCK_SHIFT;
1988                         if (new_stp->ls_flags & bits & NFSLCK_ACCESSBITS) {
1989                             KASSERT(vnode_unlocked == 0,
1990                                 ("nfsrv_lockctrl: vnode unlocked1"));
1991                             ret = nfsrv_clientconflict(tstp->ls_clp, &haslock,
1992                                 vp, p);
1993                             if (ret == 1) {
1994                                 /*
1995                                 * nfsrv_clientconflict unlocks state
1996                                  * when it returns non-zero.
1997                                  */
1998                                 lckstp = NULL;
1999                                 goto tryagain;
2000                             }
2001                             if (ret == 0)
2002                                 NFSUNLOCKSTATE();
2003                             if (ret == 2)
2004                                 error = NFSERR_PERM;
2005                             else
2006                                 error = NFSERR_OPENMODE;
2007                             goto out;
2008                         }
2009                     }
2010                 }
2011
2012                 /* We're outta here */
2013                 NFSUNLOCKSTATE();
2014                 goto out;
2015             }
2016         }
2017
2018         /*
2019          * For setattr, just get rid of all the Delegations for other clients.
2020          */
2021         if (new_stp->ls_flags & NFSLCK_SETATTR) {
2022                 KASSERT(vnode_unlocked == 0,
2023                     ("nfsrv_lockctrl: vnode unlocked2"));
2024                 ret = nfsrv_cleandeleg(vp, lfp, clp, &haslock, p);
2025                 if (ret) {
2026                         /*
2027                          * nfsrv_cleandeleg() unlocks state when it
2028                          * returns non-zero.
2029                          */
2030                         if (ret == -1) {
2031                                 lckstp = NULL;
2032                                 goto tryagain;
2033                         }
2034                         error = ret;
2035                         goto out;
2036                 }
2037                 if (!(new_stp->ls_flags & NFSLCK_CHECK) ||
2038                     (LIST_EMPTY(&lfp->lf_open) && LIST_EMPTY(&lfp->lf_lock) &&
2039                      LIST_EMPTY(&lfp->lf_deleg))) {
2040                         NFSUNLOCKSTATE();
2041                         goto out;
2042                 }
2043         }
2044
2045         /*
2046          * Check for a conflicting delegation. If one is found, call
2047          * nfsrv_delegconflict() to handle it. If the v4root lock hasn't
2048          * been set yet, it will get the lock. Otherwise, it will recall
2049          * the delegation. Then, we try try again...
2050          * I currently believe the conflict algorithm to be:
2051          * For Lock Ops (Lock/LockT/LockU)
2052          * - there is a conflict iff a different client has a write delegation
2053          * For Reading (Read Op)
2054          * - there is a conflict iff a different client has a write delegation
2055          *   (the specialids are always a different client)
2056          * For Writing (Write/Setattr of size)
2057          * - there is a conflict if a different client has any delegation
2058          * - there is a conflict if the same client has a read delegation
2059          *   (I don't understand why this isn't allowed, but that seems to be
2060          *    the current concensus?)
2061          */
2062         tstp = LIST_FIRST(&lfp->lf_deleg);
2063         while (tstp != LIST_END(&lfp->lf_deleg)) {
2064             nstp = LIST_NEXT(tstp, ls_file);
2065             if ((((new_stp->ls_flags&(NFSLCK_LOCK|NFSLCK_UNLOCK|NFSLCK_TEST))||
2066                  ((new_stp->ls_flags & NFSLCK_CHECK) &&
2067                   (new_lop->lo_flags & NFSLCK_READ))) &&
2068                   clp != tstp->ls_clp &&
2069                  (tstp->ls_flags & NFSLCK_DELEGWRITE)) ||
2070                  ((new_stp->ls_flags & NFSLCK_CHECK) &&
2071                    (new_lop->lo_flags & NFSLCK_WRITE) &&
2072                   (clp != tstp->ls_clp ||
2073                    (tstp->ls_flags & NFSLCK_DELEGREAD)))) {
2074                 ret = 0;
2075                 if (filestruct_locked != 0) {
2076                         /* Roll back local locks. */
2077                         NFSUNLOCKSTATE();
2078                         if (vnode_unlocked == 0) {
2079                                 ASSERT_VOP_ELOCKED(vp, "nfsrv_lockctrl4");
2080                                 NFSVOPUNLOCK(vp, 0);
2081                         }
2082                         nfsrv_locallock_rollback(vp, lfp, p);
2083                         NFSLOCKSTATE();
2084                         nfsrv_unlocklf(lfp);
2085                         NFSUNLOCKSTATE();
2086                         NFSVOPLOCK(vp, LK_EXCLUSIVE | LK_RETRY);
2087                         vnode_unlocked = 0;
2088                         if ((vp->v_iflag & VI_DOOMED) != 0)
2089                                 ret = NFSERR_SERVERFAULT;
2090                         NFSLOCKSTATE();
2091                 }
2092                 if (ret == 0)
2093                         ret = nfsrv_delegconflict(tstp, &haslock, p, vp);
2094                 if (ret) {
2095                     /*
2096                      * nfsrv_delegconflict unlocks state when it
2097                      * returns non-zero, which it always does.
2098                      */
2099                     if (other_lop) {
2100                         FREE((caddr_t)other_lop, M_NFSDLOCK);
2101                         other_lop = NULL;
2102                     }
2103                     if (ret == -1) {
2104                         lckstp = NULL;
2105                         goto tryagain;
2106                     }
2107                     error = ret;
2108                     goto out;
2109                 }
2110                 /* Never gets here. */
2111             }
2112             tstp = nstp;
2113         }
2114
2115         /*
2116          * Handle the unlock case by calling nfsrv_updatelock().
2117          * (Should I have done some access checking above for unlock? For now,
2118          *  just let it happen.)
2119          */
2120         if (new_stp->ls_flags & NFSLCK_UNLOCK) {
2121                 first = new_lop->lo_first;
2122                 end = new_lop->lo_end;
2123                 nfsrv_updatelock(stp, new_lopp, &other_lop, lfp);
2124                 stateidp->seqid = ++(stp->ls_stateid.seqid);
2125                 if ((nd->nd_flag & ND_NFSV41) != 0 && stateidp->seqid == 0)
2126                         stateidp->seqid = stp->ls_stateid.seqid = 1;
2127                 stateidp->other[0] = stp->ls_stateid.other[0];
2128                 stateidp->other[1] = stp->ls_stateid.other[1];
2129                 stateidp->other[2] = stp->ls_stateid.other[2];
2130                 if (filestruct_locked != 0) {
2131                         NFSUNLOCKSTATE();
2132                         if (vnode_unlocked == 0) {
2133                                 ASSERT_VOP_ELOCKED(vp, "nfsrv_lockctrl5");
2134                                 vnode_unlocked = 1;
2135                                 NFSVOPUNLOCK(vp, 0);
2136                         }
2137                         /* Update the local locks. */
2138                         nfsrv_localunlock(vp, lfp, first, end, p);
2139                         NFSLOCKSTATE();
2140                         nfsrv_unlocklf(lfp);
2141                 }
2142                 NFSUNLOCKSTATE();
2143                 goto out;
2144         }
2145
2146         /*
2147          * Search for a conflicting lock. A lock conflicts if:
2148          * - the lock range overlaps and
2149          * - at least one lock is a write lock and
2150          * - it is not owned by the same lock owner
2151          */
2152         if (!delegation) {
2153           LIST_FOREACH(lop, &lfp->lf_lock, lo_lckfile) {
2154             if (new_lop->lo_end > lop->lo_first &&
2155                 new_lop->lo_first < lop->lo_end &&
2156                 (new_lop->lo_flags == NFSLCK_WRITE ||
2157                  lop->lo_flags == NFSLCK_WRITE) &&
2158                 lckstp != lop->lo_stp &&
2159                 (clp != lop->lo_stp->ls_clp ||
2160                  lckstp->ls_ownerlen != lop->lo_stp->ls_ownerlen ||
2161                  NFSBCMP(lckstp->ls_owner, lop->lo_stp->ls_owner,
2162                     lckstp->ls_ownerlen))) {
2163                 if (other_lop) {
2164                     FREE((caddr_t)other_lop, M_NFSDLOCK);
2165                     other_lop = NULL;
2166                 }
2167                 if (vnode_unlocked != 0)
2168                     ret = nfsrv_clientconflict(lop->lo_stp->ls_clp, &haslock,
2169                         NULL, p);
2170                 else
2171                     ret = nfsrv_clientconflict(lop->lo_stp->ls_clp, &haslock,
2172                         vp, p);
2173                 if (ret == 1) {
2174                     if (filestruct_locked != 0) {
2175                         if (vnode_unlocked == 0) {
2176                                 ASSERT_VOP_ELOCKED(vp, "nfsrv_lockctrl6");
2177                                 NFSVOPUNLOCK(vp, 0);
2178                         }
2179                         /* Roll back local locks. */
2180                         nfsrv_locallock_rollback(vp, lfp, p);
2181                         NFSLOCKSTATE();
2182                         nfsrv_unlocklf(lfp);
2183                         NFSUNLOCKSTATE();
2184                         NFSVOPLOCK(vp, LK_EXCLUSIVE | LK_RETRY);
2185                         vnode_unlocked = 0;
2186                         if ((vp->v_iflag & VI_DOOMED) != 0) {
2187                                 error = NFSERR_SERVERFAULT;
2188                                 goto out;
2189                         }
2190                     }
2191                     /*
2192                      * nfsrv_clientconflict() unlocks state when it
2193                      * returns non-zero.
2194                      */
2195                     lckstp = NULL;
2196                     goto tryagain;
2197                 }
2198                 /*
2199                  * Found a conflicting lock, so record the conflict and
2200                  * return the error.
2201                  */
2202                 if (cfp != NULL && ret == 0) {
2203                     cfp->cl_clientid.lval[0]=lop->lo_stp->ls_stateid.other[0];
2204                     cfp->cl_clientid.lval[1]=lop->lo_stp->ls_stateid.other[1];
2205                     cfp->cl_first = lop->lo_first;
2206                     cfp->cl_end = lop->lo_end;
2207                     cfp->cl_flags = lop->lo_flags;
2208                     cfp->cl_ownerlen = lop->lo_stp->ls_ownerlen;
2209                     NFSBCOPY(lop->lo_stp->ls_owner, cfp->cl_owner,
2210                         cfp->cl_ownerlen);
2211                 }
2212                 if (ret == 2)
2213                     error = NFSERR_PERM;
2214                 else if (new_stp->ls_flags & NFSLCK_RECLAIM)
2215                     error = NFSERR_RECLAIMCONFLICT;
2216                 else if (new_stp->ls_flags & NFSLCK_CHECK)
2217                     error = NFSERR_LOCKED;
2218                 else
2219                     error = NFSERR_DENIED;
2220                 if (filestruct_locked != 0 && ret == 0) {
2221                         /* Roll back local locks. */
2222                         NFSUNLOCKSTATE();
2223                         if (vnode_unlocked == 0) {
2224                                 ASSERT_VOP_ELOCKED(vp, "nfsrv_lockctrl7");
2225                                 vnode_unlocked = 1;
2226                                 NFSVOPUNLOCK(vp, 0);
2227                         }
2228                         nfsrv_locallock_rollback(vp, lfp, p);
2229                         NFSLOCKSTATE();
2230                         nfsrv_unlocklf(lfp);
2231                 }
2232                 if (ret == 0)
2233                         NFSUNLOCKSTATE();
2234                 goto out;
2235             }
2236           }
2237         }
2238
2239         /*
2240          * We only get here if there was no lock that conflicted.
2241          */
2242         if (new_stp->ls_flags & (NFSLCK_TEST | NFSLCK_CHECK)) {
2243                 NFSUNLOCKSTATE();
2244                 goto out;
2245         }
2246
2247         /*
2248          * We only get here when we are creating or modifying a lock.
2249          * There are two variants:
2250          * - exist_lock_owner where lock_owner exists
2251          * - open_to_lock_owner with new lock_owner
2252          */
2253         first = new_lop->lo_first;
2254         end = new_lop->lo_end;
2255         lock_flags = new_lop->lo_flags;
2256         if (!(new_stp->ls_flags & NFSLCK_OPENTOLOCK)) {
2257                 nfsrv_updatelock(lckstp, new_lopp, &other_lop, lfp);
2258                 stateidp->seqid = ++(lckstp->ls_stateid.seqid);
2259                 if ((nd->nd_flag & ND_NFSV41) != 0 && stateidp->seqid == 0)
2260                         stateidp->seqid = lckstp->ls_stateid.seqid = 1;
2261                 stateidp->other[0] = lckstp->ls_stateid.other[0];
2262                 stateidp->other[1] = lckstp->ls_stateid.other[1];
2263                 stateidp->other[2] = lckstp->ls_stateid.other[2];
2264         } else {
2265                 /*
2266                  * The new open_to_lock_owner case.
2267                  * Link the new nfsstate into the lists.
2268                  */
2269                 new_stp->ls_seq = new_stp->ls_opentolockseq;
2270                 nfsrvd_refcache(new_stp->ls_op);
2271                 stateidp->seqid = new_stp->ls_stateid.seqid = 1;
2272                 stateidp->other[0] = new_stp->ls_stateid.other[0] =
2273                     clp->lc_clientid.lval[0];
2274                 stateidp->other[1] = new_stp->ls_stateid.other[1] =
2275                     clp->lc_clientid.lval[1];
2276                 stateidp->other[2] = new_stp->ls_stateid.other[2] =
2277                     nfsrv_nextstateindex(clp);
2278                 new_stp->ls_clp = clp;
2279                 LIST_INIT(&new_stp->ls_lock);
2280                 new_stp->ls_openstp = stp;
2281                 new_stp->ls_lfp = lfp;
2282                 nfsrv_insertlock(new_lop, (struct nfslock *)new_stp, new_stp,
2283                     lfp);
2284                 LIST_INSERT_HEAD(NFSSTATEHASH(clp, new_stp->ls_stateid),
2285                     new_stp, ls_hash);
2286                 LIST_INSERT_HEAD(&stp->ls_open, new_stp, ls_list);
2287                 *new_lopp = NULL;
2288                 *new_stpp = NULL;
2289                 newnfsstats.srvlockowners++;
2290                 nfsrv_openpluslock++;
2291         }
2292         if (filestruct_locked != 0) {
2293                 NFSUNLOCKSTATE();
2294                 nfsrv_locallock_commit(lfp, lock_flags, first, end);
2295                 NFSLOCKSTATE();
2296                 nfsrv_unlocklf(lfp);
2297         }
2298         NFSUNLOCKSTATE();
2299
2300 out:
2301         if (haslock) {
2302                 NFSLOCKV4ROOTMUTEX();
2303                 nfsv4_unlock(&nfsv4rootfs_lock, 1);
2304                 NFSUNLOCKV4ROOTMUTEX();
2305         }
2306         if (vnode_unlocked != 0) {
2307                 NFSVOPLOCK(vp, LK_EXCLUSIVE | LK_RETRY);
2308                 if (error == 0 && (vp->v_iflag & VI_DOOMED) != 0)
2309                         error = NFSERR_SERVERFAULT;
2310         }
2311         if (other_lop)
2312                 FREE((caddr_t)other_lop, M_NFSDLOCK);
2313         NFSEXITCODE2(error, nd);
2314         return (error);
2315 }
2316
2317 /*
2318  * Check for state errors for Open.
2319  * repstat is passed back out as an error if more critical errors
2320  * are not detected.
2321  */
2322 APPLESTATIC int
2323 nfsrv_opencheck(nfsquad_t clientid, nfsv4stateid_t *stateidp,
2324     struct nfsstate *new_stp, vnode_t vp, struct nfsrv_descript *nd,
2325     NFSPROC_T *p, int repstat)
2326 {
2327         struct nfsstate *stp, *nstp;
2328         struct nfsclient *clp;
2329         struct nfsstate *ownerstp;
2330         struct nfslockfile *lfp, *new_lfp;
2331         int error = 0, haslock = 0, ret, readonly = 0, getfhret = 0;
2332
2333         if ((new_stp->ls_flags & NFSLCK_SHAREBITS) == NFSLCK_READACCESS)
2334                 readonly = 1;
2335         /*
2336          * Check for restart conditions (client and server).
2337          */
2338         error = nfsrv_checkrestart(clientid, new_stp->ls_flags,
2339                 &new_stp->ls_stateid, 0);
2340         if (error)
2341                 goto out;
2342
2343         /*
2344          * Check for state resource limit exceeded.
2345          * Technically this should be SMP protected, but the worst
2346          * case error is "out by one or two" on the count when it
2347          * returns NFSERR_RESOURCE and the limit is just a rather
2348          * arbitrary high water mark, so no harm is done.
2349          */
2350         if (nfsrv_openpluslock > nfsrv_v4statelimit) {
2351                 error = NFSERR_RESOURCE;
2352                 goto out;
2353         }
2354
2355 tryagain:
2356         MALLOC(new_lfp, struct nfslockfile *, sizeof (struct nfslockfile),
2357             M_NFSDLOCKFILE, M_WAITOK);
2358         if (vp)
2359                 getfhret = nfsrv_getlockfh(vp, new_stp->ls_flags, new_lfp,
2360                     NULL, p);
2361         NFSLOCKSTATE();
2362         /*
2363          * Get the nfsclient structure.
2364          */
2365         error = nfsrv_getclient(clientid, CLOPS_RENEW, &clp, NULL,
2366             (nfsquad_t)((u_quad_t)0), 0, nd, p);
2367
2368         /*
2369          * Look up the open owner. See if it needs confirmation and
2370          * check the seq#, as required.
2371          */
2372         if (!error)
2373                 nfsrv_getowner(&clp->lc_open, new_stp, &ownerstp);
2374
2375         if (!error && ownerstp) {
2376                 error = nfsrv_checkseqid(nd, new_stp->ls_seq, ownerstp,
2377                     new_stp->ls_op);
2378                 /*
2379                  * If the OpenOwner hasn't been confirmed, assume the
2380                  * old one was a replay and this one is ok.
2381                  * See: RFC3530 Sec. 14.2.18.
2382                  */
2383                 if (error == NFSERR_BADSEQID &&
2384                     (ownerstp->ls_flags & NFSLCK_NEEDSCONFIRM))
2385                         error = 0;
2386         }
2387
2388         /*
2389          * Check for grace.
2390          */
2391         if (!error)
2392                 error = nfsrv_checkgrace(nd, clp, new_stp->ls_flags);
2393         if ((new_stp->ls_flags & NFSLCK_RECLAIM) && !error &&
2394                 nfsrv_checkstable(clp))
2395                 error = NFSERR_NOGRACE;
2396
2397         /*
2398          * If none of the above errors occurred, let repstat be
2399          * returned.
2400          */
2401         if (repstat && !error)
2402                 error = repstat;
2403         if (error) {
2404                 NFSUNLOCKSTATE();
2405                 if (haslock) {
2406                         NFSLOCKV4ROOTMUTEX();
2407                         nfsv4_unlock(&nfsv4rootfs_lock, 1);
2408                         NFSUNLOCKV4ROOTMUTEX();
2409                 }
2410                 free((caddr_t)new_lfp, M_NFSDLOCKFILE);
2411                 goto out;
2412         }
2413
2414         /*
2415          * If vp == NULL, the file doesn't exist yet, so return ok.
2416          * (This always happens on the first pass, so haslock must be 0.)
2417          */
2418         if (vp == NULL) {
2419                 NFSUNLOCKSTATE();
2420                 FREE((caddr_t)new_lfp, M_NFSDLOCKFILE);
2421                 goto out;
2422         }
2423
2424         /*
2425          * Get the structure for the underlying file.
2426          */
2427         if (getfhret)
2428                 error = getfhret;
2429         else
2430                 error = nfsrv_getlockfile(new_stp->ls_flags, &new_lfp, &lfp,
2431                     NULL, 0);
2432         if (new_lfp)
2433                 FREE((caddr_t)new_lfp, M_NFSDLOCKFILE);
2434         if (error) {
2435                 NFSUNLOCKSTATE();
2436                 if (haslock) {
2437                         NFSLOCKV4ROOTMUTEX();
2438                         nfsv4_unlock(&nfsv4rootfs_lock, 1);
2439                         NFSUNLOCKV4ROOTMUTEX();
2440                 }
2441                 goto out;
2442         }
2443
2444         /*
2445          * Search for a conflicting open/share.
2446          */
2447         if (new_stp->ls_flags & NFSLCK_DELEGCUR) {
2448             /*
2449              * For Delegate_Cur, search for the matching Delegation,
2450              * which indicates no conflict.
2451              * An old delegation should have been recovered by the
2452              * client doing a Claim_DELEGATE_Prev, so I won't let
2453              * it match and return NFSERR_EXPIRED. Should I let it
2454              * match?
2455              */
2456             LIST_FOREACH(stp, &lfp->lf_deleg, ls_file) {
2457                 if (!(stp->ls_flags & NFSLCK_OLDDELEG) &&
2458                     (((nd->nd_flag & ND_NFSV41) != 0 &&
2459                     stateidp->seqid == 0) ||
2460                     stateidp->seqid == stp->ls_stateid.seqid) &&
2461                     !NFSBCMP(stateidp->other, stp->ls_stateid.other,
2462                           NFSX_STATEIDOTHER))
2463                         break;
2464             }
2465             if (stp == LIST_END(&lfp->lf_deleg) ||
2466                 ((new_stp->ls_flags & NFSLCK_WRITEACCESS) &&
2467                  (stp->ls_flags & NFSLCK_DELEGREAD))) {
2468                 NFSUNLOCKSTATE();
2469                 if (haslock) {
2470                         NFSLOCKV4ROOTMUTEX();
2471                         nfsv4_unlock(&nfsv4rootfs_lock, 1);
2472                         NFSUNLOCKV4ROOTMUTEX();
2473                 }
2474                 error = NFSERR_EXPIRED;
2475                 goto out;
2476             }
2477         }
2478
2479         /*
2480          * Check for access/deny bit conflicts. I check for the same
2481          * owner as well, in case the client didn't bother.
2482          */
2483         LIST_FOREACH(stp, &lfp->lf_open, ls_file) {
2484                 if (!(new_stp->ls_flags & NFSLCK_DELEGCUR) &&
2485                     (((new_stp->ls_flags & NFSLCK_ACCESSBITS) &
2486                       ((stp->ls_flags>>NFSLCK_SHIFT) & NFSLCK_ACCESSBITS))||
2487                      ((stp->ls_flags & NFSLCK_ACCESSBITS) &
2488                       ((new_stp->ls_flags>>NFSLCK_SHIFT)&NFSLCK_ACCESSBITS)))){
2489                         ret = nfsrv_clientconflict(stp->ls_clp,&haslock,vp,p);
2490                         if (ret == 1) {
2491                                 /*
2492                                  * nfsrv_clientconflict() unlocks
2493                                  * state when it returns non-zero.
2494                                  */
2495                                 goto tryagain;
2496                         }
2497                         if (ret == 2)
2498                                 error = NFSERR_PERM;
2499                         else if (new_stp->ls_flags & NFSLCK_RECLAIM)
2500                                 error = NFSERR_RECLAIMCONFLICT;
2501                         else
2502                                 error = NFSERR_SHAREDENIED;
2503                         if (ret == 0)
2504                                 NFSUNLOCKSTATE();
2505                         if (haslock) {
2506                                 NFSLOCKV4ROOTMUTEX();
2507                                 nfsv4_unlock(&nfsv4rootfs_lock, 1);
2508                                 NFSUNLOCKV4ROOTMUTEX();
2509                         }
2510                         goto out;
2511                 }
2512         }
2513
2514         /*
2515          * Check for a conflicting delegation. If one is found, call
2516          * nfsrv_delegconflict() to handle it. If the v4root lock hasn't
2517          * been set yet, it will get the lock. Otherwise, it will recall
2518          * the delegation. Then, we try try again...
2519          * (If NFSLCK_DELEGCUR is set, it has a delegation, so there
2520          *  isn't a conflict.)
2521          * I currently believe the conflict algorithm to be:
2522          * For Open with Read Access and Deny None
2523          * - there is a conflict iff a different client has a write delegation
2524          * For Open with other Write Access or any Deny except None
2525          * - there is a conflict if a different client has any delegation
2526          * - there is a conflict if the same client has a read delegation
2527          *   (The current concensus is that this last case should be
2528          *    considered a conflict since the client with a read delegation
2529          *    could have done an Open with ReadAccess and WriteDeny
2530          *    locally and then not have checked for the WriteDeny.)
2531          * Don't check for a Reclaim, since that will be dealt with
2532          * by nfsrv_openctrl().
2533          */
2534         if (!(new_stp->ls_flags &
2535                 (NFSLCK_DELEGPREV | NFSLCK_DELEGCUR | NFSLCK_RECLAIM))) {
2536             stp = LIST_FIRST(&lfp->lf_deleg);
2537             while (stp != LIST_END(&lfp->lf_deleg)) {
2538                 nstp = LIST_NEXT(stp, ls_file);
2539                 if ((readonly && stp->ls_clp != clp &&
2540                        (stp->ls_flags & NFSLCK_DELEGWRITE)) ||
2541                     (!readonly && (stp->ls_clp != clp ||
2542                          (stp->ls_flags & NFSLCK_DELEGREAD)))) {
2543                         ret = nfsrv_delegconflict(stp, &haslock, p, vp);
2544                         if (ret) {
2545                             /*
2546                              * nfsrv_delegconflict() unlocks state
2547                              * when it returns non-zero.
2548                              */
2549                             if (ret == -1)
2550                                 goto tryagain;
2551                             error = ret;
2552                             goto out;
2553                         }
2554                 }
2555                 stp = nstp;
2556             }
2557         }
2558         NFSUNLOCKSTATE();
2559         if (haslock) {
2560                 NFSLOCKV4ROOTMUTEX();
2561                 nfsv4_unlock(&nfsv4rootfs_lock, 1);
2562                 NFSUNLOCKV4ROOTMUTEX();
2563         }
2564
2565 out:
2566         NFSEXITCODE2(error, nd);
2567         return (error);
2568 }
2569
2570 /*
2571  * Open control function to create/update open state for an open.
2572  */
2573 APPLESTATIC int
2574 nfsrv_openctrl(struct nfsrv_descript *nd, vnode_t vp,
2575     struct nfsstate **new_stpp, nfsquad_t clientid, nfsv4stateid_t *stateidp,
2576     nfsv4stateid_t *delegstateidp, u_int32_t *rflagsp, struct nfsexstuff *exp,
2577     NFSPROC_T *p, u_quad_t filerev)
2578 {
2579         struct nfsstate *new_stp = *new_stpp;
2580         struct nfsstate *stp, *nstp;
2581         struct nfsstate *openstp = NULL, *new_open, *ownerstp, *new_deleg;
2582         struct nfslockfile *lfp, *new_lfp;
2583         struct nfsclient *clp;
2584         int error = 0, haslock = 0, ret, delegate = 1, writedeleg = 1;
2585         int readonly = 0, cbret = 1, getfhret = 0;
2586         int gotstate = 0, len = 0;
2587         u_char *clidp = NULL;
2588
2589         if ((new_stp->ls_flags & NFSLCK_SHAREBITS) == NFSLCK_READACCESS)
2590                 readonly = 1;
2591         /*
2592          * Check for restart conditions (client and server).
2593          * (Paranoia, should have been detected by nfsrv_opencheck().)
2594          * If an error does show up, return NFSERR_EXPIRED, since the
2595          * the seqid# has already been incremented.
2596          */
2597         error = nfsrv_checkrestart(clientid, new_stp->ls_flags,
2598             &new_stp->ls_stateid, 0);
2599         if (error) {
2600                 printf("Nfsd: openctrl unexpected restart err=%d\n",
2601                     error);
2602                 error = NFSERR_EXPIRED;
2603                 goto out;
2604         }
2605
2606         clidp = malloc(NFSV4_OPAQUELIMIT, M_TEMP, M_WAITOK);
2607 tryagain:
2608         MALLOC(new_lfp, struct nfslockfile *, sizeof (struct nfslockfile),
2609             M_NFSDLOCKFILE, M_WAITOK);
2610         MALLOC(new_open, struct nfsstate *, sizeof (struct nfsstate),
2611             M_NFSDSTATE, M_WAITOK);
2612         MALLOC(new_deleg, struct nfsstate *, sizeof (struct nfsstate),
2613             M_NFSDSTATE, M_WAITOK);
2614         getfhret = nfsrv_getlockfh(vp, new_stp->ls_flags, new_lfp,
2615             NULL, p);
2616         NFSLOCKSTATE();
2617         /*
2618          * Get the client structure. Since the linked lists could be changed
2619          * by other nfsd processes if this process does a tsleep(), one of
2620          * two things must be done.
2621          * 1 - don't tsleep()
2622          * or
2623          * 2 - get the nfsv4_lock() { indicated by haslock == 1 }
2624          *     before using the lists, since this lock stops the other
2625          *     nfsd. This should only be used for rare cases, since it
2626          *     essentially single threads the nfsd.
2627          *     At this time, it is only done for cases where the stable
2628          *     storage file must be written prior to completion of state
2629          *     expiration.
2630          */
2631         error = nfsrv_getclient(clientid, CLOPS_RENEW, &clp, NULL,
2632             (nfsquad_t)((u_quad_t)0), 0, nd, p);
2633         if (!error && (clp->lc_flags & LCL_NEEDSCBNULL) &&
2634             clp->lc_program) {
2635                 /*
2636                  * This happens on the first open for a client
2637                  * that supports callbacks.
2638                  */
2639                 NFSUNLOCKSTATE();
2640                 /*
2641                  * Although nfsrv_docallback() will sleep, clp won't
2642                  * go away, since they are only removed when the
2643                  * nfsv4_lock() has blocked the nfsd threads. The
2644                  * fields in clp can change, but having multiple
2645                  * threads do this Null callback RPC should be
2646                  * harmless.
2647                  */
2648                 cbret = nfsrv_docallback(clp, NFSV4PROC_CBNULL,
2649                     NULL, 0, NULL, NULL, NULL, p);
2650                 NFSLOCKSTATE();
2651                 clp->lc_flags &= ~LCL_NEEDSCBNULL;
2652                 if (!cbret)
2653                         clp->lc_flags |= LCL_CALLBACKSON;
2654         }
2655
2656         /*
2657          * Look up the open owner. See if it needs confirmation and
2658          * check the seq#, as required.
2659          */
2660         if (!error)
2661                 nfsrv_getowner(&clp->lc_open, new_stp, &ownerstp);
2662
2663         if (error) {
2664                 NFSUNLOCKSTATE();
2665                 printf("Nfsd: openctrl unexpected state err=%d\n",
2666                         error);
2667                 free((caddr_t)new_lfp, M_NFSDLOCKFILE);
2668                 free((caddr_t)new_open, M_NFSDSTATE);
2669                 free((caddr_t)new_deleg, M_NFSDSTATE);
2670                 if (haslock) {
2671                         NFSLOCKV4ROOTMUTEX();
2672                         nfsv4_unlock(&nfsv4rootfs_lock, 1);
2673                         NFSUNLOCKV4ROOTMUTEX();
2674                 }
2675                 error = NFSERR_EXPIRED;
2676                 goto out;
2677         }
2678
2679         if (new_stp->ls_flags & NFSLCK_RECLAIM)
2680                 nfsrv_markstable(clp);
2681
2682         /*
2683          * Get the structure for the underlying file.
2684          */
2685         if (getfhret)
2686                 error = getfhret;
2687         else
2688                 error = nfsrv_getlockfile(new_stp->ls_flags, &new_lfp, &lfp,
2689                     NULL, 0);
2690         if (new_lfp)
2691                 FREE((caddr_t)new_lfp, M_NFSDLOCKFILE);
2692         if (error) {
2693                 NFSUNLOCKSTATE();
2694                 printf("Nfsd openctrl unexpected getlockfile err=%d\n",
2695                     error);
2696                 free((caddr_t)new_open, M_NFSDSTATE);
2697                 free((caddr_t)new_deleg, M_NFSDSTATE);
2698                 if (haslock) {
2699                         NFSLOCKV4ROOTMUTEX();
2700                         nfsv4_unlock(&nfsv4rootfs_lock, 1);
2701                         NFSUNLOCKV4ROOTMUTEX();
2702                 }
2703                 goto out;
2704         }
2705
2706         /*
2707          * Search for a conflicting open/share.
2708          */
2709         if (new_stp->ls_flags & NFSLCK_DELEGCUR) {
2710             /*
2711              * For Delegate_Cur, search for the matching Delegation,
2712              * which indicates no conflict.
2713              * An old delegation should have been recovered by the
2714              * client doing a Claim_DELEGATE_Prev, so I won't let
2715              * it match and return NFSERR_EXPIRED. Should I let it
2716              * match?
2717              */
2718             LIST_FOREACH(stp, &lfp->lf_deleg, ls_file) {
2719                 if (!(stp->ls_flags & NFSLCK_OLDDELEG) &&
2720                     (((nd->nd_flag & ND_NFSV41) != 0 &&
2721                     stateidp->seqid == 0) ||
2722                     stateidp->seqid == stp->ls_stateid.seqid) &&
2723                     !NFSBCMP(stateidp->other, stp->ls_stateid.other,
2724                         NFSX_STATEIDOTHER))
2725                         break;
2726             }
2727             if (stp == LIST_END(&lfp->lf_deleg) ||
2728                 ((new_stp->ls_flags & NFSLCK_WRITEACCESS) &&
2729                  (stp->ls_flags & NFSLCK_DELEGREAD))) {
2730                 NFSUNLOCKSTATE();
2731                 printf("Nfsd openctrl unexpected expiry\n");
2732                 free((caddr_t)new_open, M_NFSDSTATE);
2733                 free((caddr_t)new_deleg, M_NFSDSTATE);
2734                 if (haslock) {
2735                         NFSLOCKV4ROOTMUTEX();
2736                         nfsv4_unlock(&nfsv4rootfs_lock, 1);
2737                         NFSUNLOCKV4ROOTMUTEX();
2738                 }
2739                 error = NFSERR_EXPIRED;
2740                 goto out;
2741             }
2742
2743             /*
2744              * Don't issue a Delegation, since one already exists and
2745              * delay delegation timeout, as required.
2746              */
2747             delegate = 0;
2748             nfsrv_delaydelegtimeout(stp);
2749         }
2750
2751         /*
2752          * Check for access/deny bit conflicts. I also check for the
2753          * same owner, since the client might not have bothered to check.
2754          * Also, note an open for the same file and owner, if found,
2755          * which is all we do here for Delegate_Cur, since conflict
2756          * checking is already done.
2757          */
2758         LIST_FOREACH(stp, &lfp->lf_open, ls_file) {
2759                 if (ownerstp && stp->ls_openowner == ownerstp)
2760                         openstp = stp;
2761                 if (!(new_stp->ls_flags & NFSLCK_DELEGCUR)) {
2762                     /*
2763                      * If another client has the file open, the only
2764                      * delegation that can be issued is a Read delegation
2765                      * and only if it is a Read open with Deny none.
2766                      */
2767                     if (clp != stp->ls_clp) {
2768                         if ((stp->ls_flags & NFSLCK_SHAREBITS) ==
2769                             NFSLCK_READACCESS)
2770                             writedeleg = 0;
2771                         else
2772                             delegate = 0;
2773                     }
2774                     if(((new_stp->ls_flags & NFSLCK_ACCESSBITS) &
2775                         ((stp->ls_flags>>NFSLCK_SHIFT) & NFSLCK_ACCESSBITS))||
2776                        ((stp->ls_flags & NFSLCK_ACCESSBITS) &
2777                         ((new_stp->ls_flags>>NFSLCK_SHIFT)&NFSLCK_ACCESSBITS))){
2778                         ret = nfsrv_clientconflict(stp->ls_clp,&haslock,vp,p);
2779                         if (ret == 1) {
2780                                 /*
2781                                  * nfsrv_clientconflict() unlocks state
2782                                  * when it returns non-zero.
2783                                  */
2784                                 free((caddr_t)new_open, M_NFSDSTATE);
2785                                 free((caddr_t)new_deleg, M_NFSDSTATE);
2786                                 openstp = NULL;
2787                                 goto tryagain;
2788                         }
2789                         if (ret == 2)
2790                                 error = NFSERR_PERM;
2791                         else if (new_stp->ls_flags & NFSLCK_RECLAIM)
2792                                 error = NFSERR_RECLAIMCONFLICT;
2793                         else
2794                                 error = NFSERR_SHAREDENIED;
2795                         if (ret == 0)
2796                                 NFSUNLOCKSTATE();
2797                         if (haslock) {
2798                                 NFSLOCKV4ROOTMUTEX();
2799                                 nfsv4_unlock(&nfsv4rootfs_lock, 1);
2800                                 NFSUNLOCKV4ROOTMUTEX();
2801                         }
2802                         free((caddr_t)new_open, M_NFSDSTATE);
2803                         free((caddr_t)new_deleg, M_NFSDSTATE);
2804                         printf("nfsd openctrl unexpected client cnfl\n");
2805                         goto out;
2806                     }
2807                 }
2808         }
2809
2810         /*
2811          * Check for a conflicting delegation. If one is found, call
2812          * nfsrv_delegconflict() to handle it. If the v4root lock hasn't
2813          * been set yet, it will get the lock. Otherwise, it will recall
2814          * the delegation. Then, we try try again...
2815          * (If NFSLCK_DELEGCUR is set, it has a delegation, so there
2816          *  isn't a conflict.)
2817          * I currently believe the conflict algorithm to be:
2818          * For Open with Read Access and Deny None
2819          * - there is a conflict iff a different client has a write delegation
2820          * For Open with other Write Access or any Deny except None
2821          * - there is a conflict if a different client has any delegation
2822          * - there is a conflict if the same client has a read delegation
2823          *   (The current concensus is that this last case should be
2824          *    considered a conflict since the client with a read delegation
2825          *    could have done an Open with ReadAccess and WriteDeny
2826          *    locally and then not have checked for the WriteDeny.)
2827          */
2828         if (!(new_stp->ls_flags & (NFSLCK_DELEGPREV | NFSLCK_DELEGCUR))) {
2829             stp = LIST_FIRST(&lfp->lf_deleg);
2830             while (stp != LIST_END(&lfp->lf_deleg)) {
2831                 nstp = LIST_NEXT(stp, ls_file);
2832                 if (stp->ls_clp != clp && (stp->ls_flags & NFSLCK_DELEGREAD))
2833                         writedeleg = 0;
2834                 else
2835                         delegate = 0;
2836                 if ((readonly && stp->ls_clp != clp &&
2837                        (stp->ls_flags & NFSLCK_DELEGWRITE)) ||
2838                     (!readonly && (stp->ls_clp != clp ||
2839                          (stp->ls_flags & NFSLCK_DELEGREAD)))) {
2840                     if (new_stp->ls_flags & NFSLCK_RECLAIM) {
2841                         delegate = 2;
2842                     } else {
2843                         ret = nfsrv_delegconflict(stp, &haslock, p, vp);
2844                         if (ret) {
2845                             /*
2846                              * nfsrv_delegconflict() unlocks state
2847                              * when it returns non-zero.
2848                              */
2849                             printf("Nfsd openctrl unexpected deleg cnfl\n");
2850                             free((caddr_t)new_open, M_NFSDSTATE);
2851                             free((caddr_t)new_deleg, M_NFSDSTATE);
2852                             if (ret == -1) {
2853                                 openstp = NULL;
2854                                 goto tryagain;
2855                             }
2856                             error = ret;
2857                             goto out;
2858                         }
2859                     }
2860                 }
2861                 stp = nstp;
2862             }
2863         }
2864
2865         /*
2866          * We only get here if there was no open that conflicted.
2867          * If an open for the owner exists, or in the access/deny bits.
2868          * Otherwise it is a new open. If the open_owner hasn't been
2869          * confirmed, replace the open with the new one needing confirmation,
2870          * otherwise add the open.
2871          */
2872         if (new_stp->ls_flags & NFSLCK_DELEGPREV) {
2873             /*
2874              * Handle NFSLCK_DELEGPREV by searching the old delegations for
2875              * a match. If found, just move the old delegation to the current
2876              * delegation list and issue open. If not found, return
2877              * NFSERR_EXPIRED.
2878              */
2879             LIST_FOREACH(stp, &clp->lc_olddeleg, ls_list) {
2880                 if (stp->ls_lfp == lfp) {
2881                     /* Found it */
2882                     if (stp->ls_clp != clp)
2883                         panic("olddeleg clp");
2884                     LIST_REMOVE(stp, ls_list);
2885                     LIST_REMOVE(stp, ls_hash);
2886                     stp->ls_flags &= ~NFSLCK_OLDDELEG;
2887                     stp->ls_stateid.seqid = delegstateidp->seqid = 1;
2888                     stp->ls_stateid.other[0] = delegstateidp->other[0] =
2889                         clp->lc_clientid.lval[0];
2890                     stp->ls_stateid.other[1] = delegstateidp->other[1] =
2891                         clp->lc_clientid.lval[1];
2892                     stp->ls_stateid.other[2] = delegstateidp->other[2] =
2893                         nfsrv_nextstateindex(clp);
2894                     stp->ls_compref = nd->nd_compref;
2895                     LIST_INSERT_HEAD(&clp->lc_deleg, stp, ls_list);
2896                     LIST_INSERT_HEAD(NFSSTATEHASH(clp,
2897                         stp->ls_stateid), stp, ls_hash);
2898                     if (stp->ls_flags & NFSLCK_DELEGWRITE)
2899                         *rflagsp |= NFSV4OPEN_WRITEDELEGATE;
2900                     else
2901                         *rflagsp |= NFSV4OPEN_READDELEGATE;
2902                     clp->lc_delegtime = NFSD_MONOSEC +
2903                         nfsrv_lease + NFSRV_LEASEDELTA;
2904
2905                     /*
2906                      * Now, do the associated open.
2907                      */
2908                     new_open->ls_stateid.seqid = 1;
2909                     new_open->ls_stateid.other[0] = clp->lc_clientid.lval[0];
2910                     new_open->ls_stateid.other[1] = clp->lc_clientid.lval[1];
2911                     new_open->ls_stateid.other[2] = nfsrv_nextstateindex(clp);
2912                     new_open->ls_flags = (new_stp->ls_flags&NFSLCK_DENYBITS)|
2913                         NFSLCK_OPEN;
2914                     if (stp->ls_flags & NFSLCK_DELEGWRITE)
2915                         new_open->ls_flags |= (NFSLCK_READACCESS |
2916                             NFSLCK_WRITEACCESS);
2917                     else
2918                         new_open->ls_flags |= NFSLCK_READACCESS;
2919                     new_open->ls_uid = new_stp->ls_uid;
2920                     new_open->ls_lfp = lfp;
2921                     new_open->ls_clp = clp;
2922                     LIST_INIT(&new_open->ls_open);
2923                     LIST_INSERT_HEAD(&lfp->lf_open, new_open, ls_file);
2924                     LIST_INSERT_HEAD(NFSSTATEHASH(clp, new_open->ls_stateid),
2925                         new_open, ls_hash);
2926                     /*
2927                      * and handle the open owner
2928                      */
2929                     if (ownerstp) {
2930                         new_open->ls_openowner = ownerstp;
2931                         LIST_INSERT_HEAD(&ownerstp->ls_open,new_open,ls_list);
2932                     } else {
2933                         new_open->ls_openowner = new_stp;
2934                         new_stp->ls_flags = 0;
2935                         nfsrvd_refcache(new_stp->ls_op);
2936                         new_stp->ls_noopens = 0;
2937                         LIST_INIT(&new_stp->ls_open);
2938                         LIST_INSERT_HEAD(&new_stp->ls_open, new_open, ls_list);
2939                         LIST_INSERT_HEAD(&clp->lc_open, new_stp, ls_list);
2940                         *new_stpp = NULL;
2941                         newnfsstats.srvopenowners++;
2942                         nfsrv_openpluslock++;
2943                     }
2944                     openstp = new_open;
2945                     new_open = NULL;
2946                     newnfsstats.srvopens++;
2947                     nfsrv_openpluslock++;
2948                     break;
2949                 }
2950             }
2951             if (stp == LIST_END(&clp->lc_olddeleg))
2952                 error = NFSERR_EXPIRED;
2953         } else if (new_stp->ls_flags & (NFSLCK_DELEGREAD | NFSLCK_DELEGWRITE)) {
2954             /*
2955              * Scan to see that no delegation for this client and file
2956              * doesn't already exist.
2957              * There also shouldn't yet be an Open for this file and
2958              * openowner.
2959              */
2960             LIST_FOREACH(stp, &lfp->lf_deleg, ls_file) {
2961                 if (stp->ls_clp == clp)
2962                     break;
2963             }
2964             if (stp == LIST_END(&lfp->lf_deleg) && openstp == NULL) {
2965                 /*
2966                  * This is the Claim_Previous case with a delegation
2967                  * type != Delegate_None.
2968                  */
2969                 /*
2970                  * First, add the delegation. (Although we must issue the
2971                  * delegation, we can also ask for an immediate return.)
2972                  */
2973                 new_deleg->ls_stateid.seqid = delegstateidp->seqid = 1;
2974                 new_deleg->ls_stateid.other[0] = delegstateidp->other[0] =
2975                     clp->lc_clientid.lval[0];
2976                 new_deleg->ls_stateid.other[1] = delegstateidp->other[1] =
2977                     clp->lc_clientid.lval[1];
2978                 new_deleg->ls_stateid.other[2] = delegstateidp->other[2] =
2979                     nfsrv_nextstateindex(clp);
2980                 if (new_stp->ls_flags & NFSLCK_DELEGWRITE) {
2981                     new_deleg->ls_flags = (NFSLCK_DELEGWRITE |
2982                         NFSLCK_READACCESS | NFSLCK_WRITEACCESS);
2983                     *rflagsp |= NFSV4OPEN_WRITEDELEGATE;
2984                     nfsrv_writedelegcnt++;
2985                 } else {
2986                     new_deleg->ls_flags = (NFSLCK_DELEGREAD |
2987                         NFSLCK_READACCESS);
2988                     *rflagsp |= NFSV4OPEN_READDELEGATE;
2989                 }
2990                 new_deleg->ls_uid = new_stp->ls_uid;
2991                 new_deleg->ls_lfp = lfp;
2992                 new_deleg->ls_clp = clp;
2993                 new_deleg->ls_filerev = filerev;
2994                 new_deleg->ls_compref = nd->nd_compref;
2995                 LIST_INSERT_HEAD(&lfp->lf_deleg, new_deleg, ls_file);
2996                 LIST_INSERT_HEAD(NFSSTATEHASH(clp,
2997                     new_deleg->ls_stateid), new_deleg, ls_hash);
2998                 LIST_INSERT_HEAD(&clp->lc_deleg, new_deleg, ls_list);
2999                 new_deleg = NULL;
3000                 if (delegate == 2 || nfsrv_issuedelegs == 0 ||
3001                     (clp->lc_flags & (LCL_CALLBACKSON | LCL_CBDOWN)) !=
3002                      LCL_CALLBACKSON ||
3003                     NFSRV_V4DELEGLIMIT(nfsrv_delegatecnt) ||
3004                     !NFSVNO_DELEGOK(vp))
3005                     *rflagsp |= NFSV4OPEN_RECALL;
3006                 newnfsstats.srvdelegates++;
3007                 nfsrv_openpluslock++;
3008                 nfsrv_delegatecnt++;
3009
3010                 /*
3011                  * Now, do the associated open.
3012                  */
3013                 new_open->ls_stateid.seqid = 1;
3014                 new_open->ls_stateid.other[0] = clp->lc_clientid.lval[0];
3015                 new_open->ls_stateid.other[1] = clp->lc_clientid.lval[1];
3016                 new_open->ls_stateid.other[2] = nfsrv_nextstateindex(clp);
3017                 new_open->ls_flags = (new_stp->ls_flags & NFSLCK_DENYBITS) |
3018                     NFSLCK_OPEN;
3019                 if (new_stp->ls_flags & NFSLCK_DELEGWRITE)
3020                         new_open->ls_flags |= (NFSLCK_READACCESS |
3021                             NFSLCK_WRITEACCESS);
3022                 else
3023                         new_open->ls_flags |= NFSLCK_READACCESS;
3024                 new_open->ls_uid = new_stp->ls_uid;
3025                 new_open->ls_lfp = lfp;
3026                 new_open->ls_clp = clp;
3027                 LIST_INIT(&new_open->ls_open);
3028                 LIST_INSERT_HEAD(&lfp->lf_open, new_open, ls_file);
3029                 LIST_INSERT_HEAD(NFSSTATEHASH(clp, new_open->ls_stateid),
3030                    new_open, ls_hash);
3031                 /*
3032                  * and handle the open owner
3033                  */
3034                 if (ownerstp) {
3035                     new_open->ls_openowner = ownerstp;
3036                     LIST_INSERT_HEAD(&ownerstp->ls_open, new_open, ls_list);
3037                 } else {
3038                     new_open->ls_openowner = new_stp;
3039                     new_stp->ls_flags = 0;
3040                     nfsrvd_refcache(new_stp->ls_op);
3041                     new_stp->ls_noopens = 0;
3042                     LIST_INIT(&new_stp->ls_open);
3043                     LIST_INSERT_HEAD(&new_stp->ls_open, new_open, ls_list);
3044                     LIST_INSERT_HEAD(&clp->lc_open, new_stp, ls_list);
3045                     *new_stpp = NULL;
3046                     newnfsstats.srvopenowners++;
3047                     nfsrv_openpluslock++;
3048                 }
3049                 openstp = new_open;
3050                 new_open = NULL;
3051                 newnfsstats.srvopens++;
3052                 nfsrv_openpluslock++;
3053             } else {
3054                 error = NFSERR_RECLAIMCONFLICT;
3055             }
3056         } else if (ownerstp) {
3057                 if (ownerstp->ls_flags & NFSLCK_NEEDSCONFIRM) {
3058                     /* Replace the open */
3059                     if (ownerstp->ls_op)
3060                         nfsrvd_derefcache(ownerstp->ls_op);
3061                     ownerstp->ls_op = new_stp->ls_op;
3062                     nfsrvd_refcache(ownerstp->ls_op);
3063                     ownerstp->ls_seq = new_stp->ls_seq;
3064                     *rflagsp |= NFSV4OPEN_RESULTCONFIRM;
3065                     stp = LIST_FIRST(&ownerstp->ls_open);
3066                     stp->ls_flags = (new_stp->ls_flags & NFSLCK_SHAREBITS) |
3067                         NFSLCK_OPEN;
3068                     stp->ls_stateid.seqid = 1;
3069                     stp->ls_uid = new_stp->ls_uid;
3070                     if (lfp != stp->ls_lfp) {
3071                         LIST_REMOVE(stp, ls_file);
3072                         LIST_INSERT_HEAD(&lfp->lf_open, stp, ls_file);
3073                         stp->ls_lfp = lfp;
3074                     }
3075                     openstp = stp;
3076                 } else if (openstp) {
3077                     openstp->ls_flags |= (new_stp->ls_flags & NFSLCK_SHAREBITS);
3078                     openstp->ls_stateid.seqid++;
3079                     if ((nd->nd_flag & ND_NFSV41) != 0 &&
3080                         openstp->ls_stateid.seqid == 0)
3081                         openstp->ls_stateid.seqid = 1;
3082
3083                     /*
3084                      * This is where we can choose to issue a delegation.
3085                      */
3086                     if ((new_stp->ls_flags & NFSLCK_WANTNODELEG) != 0)
3087                         *rflagsp |= NFSV4OPEN_WDNOTWANTED;
3088                     else if (nfsrv_issuedelegs == 0)
3089                         *rflagsp |= NFSV4OPEN_WDSUPPFTYPE;
3090                     else if (NFSRV_V4DELEGLIMIT(nfsrv_delegatecnt))
3091                         *rflagsp |= NFSV4OPEN_WDRESOURCE;
3092                     else if (delegate == 0 || writedeleg == 0 ||
3093                         NFSVNO_EXRDONLY(exp) || (readonly != 0 &&
3094                         nfsrv_writedelegifpos == 0) ||
3095                         !NFSVNO_DELEGOK(vp) ||
3096                         (new_stp->ls_flags & NFSLCK_WANTRDELEG) != 0 ||
3097                         (clp->lc_flags & (LCL_CALLBACKSON | LCL_CBDOWN)) !=
3098                          LCL_CALLBACKSON)
3099                         *rflagsp |= NFSV4OPEN_WDCONTENTION;
3100                     else {
3101                         new_deleg->ls_stateid.seqid = delegstateidp->seqid = 1;
3102                         new_deleg->ls_stateid.other[0] = delegstateidp->other[0]
3103                             = clp->lc_clientid.lval[0];
3104                         new_deleg->ls_stateid.other[1] = delegstateidp->other[1]
3105                             = clp->lc_clientid.lval[1];
3106                         new_deleg->ls_stateid.other[2] = delegstateidp->other[2]
3107                             = nfsrv_nextstateindex(clp);
3108                         new_deleg->ls_flags = (NFSLCK_DELEGWRITE |
3109                             NFSLCK_READACCESS | NFSLCK_WRITEACCESS);
3110                         *rflagsp |= NFSV4OPEN_WRITEDELEGATE;
3111                         new_deleg->ls_uid = new_stp->ls_uid;
3112                         new_deleg->ls_lfp = lfp;
3113                         new_deleg->ls_clp = clp;
3114                         new_deleg->ls_filerev = filerev;
3115                         new_deleg->ls_compref = nd->nd_compref;
3116                         nfsrv_writedelegcnt++;
3117                         LIST_INSERT_HEAD(&lfp->lf_deleg, new_deleg, ls_file);
3118                         LIST_INSERT_HEAD(NFSSTATEHASH(clp,
3119                             new_deleg->ls_stateid), new_deleg, ls_hash);
3120                         LIST_INSERT_HEAD(&clp->lc_deleg, new_deleg, ls_list);
3121                         new_deleg = NULL;
3122                         newnfsstats.srvdelegates++;
3123                         nfsrv_openpluslock++;
3124                         nfsrv_delegatecnt++;
3125                     }
3126                 } else {
3127                     new_open->ls_stateid.seqid = 1;
3128                     new_open->ls_stateid.other[0] = clp->lc_clientid.lval[0];
3129                     new_open->ls_stateid.other[1] = clp->lc_clientid.lval[1];
3130                     new_open->ls_stateid.other[2] = nfsrv_nextstateindex(clp);
3131                     new_open->ls_flags = (new_stp->ls_flags & NFSLCK_SHAREBITS)|
3132                         NFSLCK_OPEN;
3133                     new_open->ls_uid = new_stp->ls_uid;
3134                     new_open->ls_openowner = ownerstp;
3135                     new_open->ls_lfp = lfp;
3136                     new_open->ls_clp = clp;
3137                     LIST_INIT(&new_open->ls_open);
3138                     LIST_INSERT_HEAD(&lfp->lf_open, new_open, ls_file);
3139                     LIST_INSERT_HEAD(&ownerstp->ls_open, new_open, ls_list);
3140                     LIST_INSERT_HEAD(NFSSTATEHASH(clp, new_open->ls_stateid),
3141                         new_open, ls_hash);
3142                     openstp = new_open;
3143                     new_open = NULL;
3144                     newnfsstats.srvopens++;
3145                     nfsrv_openpluslock++;
3146
3147                     /*
3148                      * This is where we can choose to issue a delegation.
3149                      */
3150                     if ((new_stp->ls_flags & NFSLCK_WANTNODELEG) != 0)
3151                         *rflagsp |= NFSV4OPEN_WDNOTWANTED;
3152                     else if (nfsrv_issuedelegs == 0)
3153                         *rflagsp |= NFSV4OPEN_WDSUPPFTYPE;
3154                     else if (NFSRV_V4DELEGLIMIT(nfsrv_delegatecnt))
3155                         *rflagsp |= NFSV4OPEN_WDRESOURCE;
3156                     else if (delegate == 0 || (writedeleg == 0 &&
3157                         readonly == 0) || !NFSVNO_DELEGOK(vp) ||
3158                         (clp->lc_flags & (LCL_CALLBACKSON | LCL_CBDOWN)) !=
3159                          LCL_CALLBACKSON)
3160                         *rflagsp |= NFSV4OPEN_WDCONTENTION;
3161                     else {
3162                         new_deleg->ls_stateid.seqid = delegstateidp->seqid = 1;
3163                         new_deleg->ls_stateid.other[0] = delegstateidp->other[0]
3164                             = clp->lc_clientid.lval[0];
3165                         new_deleg->ls_stateid.other[1] = delegstateidp->other[1]
3166                             = clp->lc_clientid.lval[1];
3167                         new_deleg->ls_stateid.other[2] = delegstateidp->other[2]
3168                             = nfsrv_nextstateindex(clp);
3169                         if (writedeleg && !NFSVNO_EXRDONLY(exp) &&
3170                             (nfsrv_writedelegifpos || !readonly) &&
3171                             (new_stp->ls_flags & NFSLCK_WANTRDELEG) == 0) {
3172                             new_deleg->ls_flags = (NFSLCK_DELEGWRITE |
3173                                 NFSLCK_READACCESS | NFSLCK_WRITEACCESS);
3174                             *rflagsp |= NFSV4OPEN_WRITEDELEGATE;
3175                             nfsrv_writedelegcnt++;
3176                         } else {
3177                             new_deleg->ls_flags = (NFSLCK_DELEGREAD |
3178                                 NFSLCK_READACCESS);
3179                             *rflagsp |= NFSV4OPEN_READDELEGATE;
3180                         }
3181                         new_deleg->ls_uid = new_stp->ls_uid;
3182                         new_deleg->ls_lfp = lfp;
3183                         new_deleg->ls_clp = clp;
3184                         new_deleg->ls_filerev = filerev;
3185                         new_deleg->ls_compref = nd->nd_compref;
3186                         LIST_INSERT_HEAD(&lfp->lf_deleg, new_deleg, ls_file);
3187                         LIST_INSERT_HEAD(NFSSTATEHASH(clp,
3188                             new_deleg->ls_stateid), new_deleg, ls_hash);
3189                         LIST_INSERT_HEAD(&clp->lc_deleg, new_deleg, ls_list);
3190                         new_deleg = NULL;
3191                         newnfsstats.srvdelegates++;
3192                         nfsrv_openpluslock++;
3193                         nfsrv_delegatecnt++;
3194                     }
3195                 }
3196         } else {
3197                 /*
3198                  * New owner case. Start the open_owner sequence with a
3199                  * Needs confirmation (unless a reclaim) and hang the
3200                  * new open off it.
3201                  */
3202                 new_open->ls_stateid.seqid = 1;
3203                 new_open->ls_stateid.other[0] = clp->lc_clientid.lval[0];
3204                 new_open->ls_stateid.other[1] = clp->lc_clientid.lval[1];
3205                 new_open->ls_stateid.other[2] = nfsrv_nextstateindex(clp);
3206                 new_open->ls_flags = (new_stp->ls_flags & NFSLCK_SHAREBITS) |
3207                     NFSLCK_OPEN;
3208                 new_open->ls_uid = new_stp->ls_uid;
3209                 LIST_INIT(&new_open->ls_open);
3210                 new_open->ls_openowner = new_stp;
3211                 new_open->ls_lfp = lfp;
3212                 new_open->ls_clp = clp;
3213                 LIST_INSERT_HEAD(&lfp->lf_open, new_open, ls_file);
3214                 if (new_stp->ls_flags & NFSLCK_RECLAIM) {
3215                         new_stp->ls_flags = 0;
3216                 } else if ((nd->nd_flag & ND_NFSV41) != 0) {
3217                         /* NFSv4.1 never needs confirmation. */
3218                         new_stp->ls_flags = 0;
3219
3220                         /*
3221                          * This is where we can choose to issue a delegation.
3222                          */
3223                         if (delegate && nfsrv_issuedelegs &&
3224                             (writedeleg || readonly) &&
3225                             (clp->lc_flags & (LCL_CALLBACKSON | LCL_CBDOWN)) ==
3226                              LCL_CALLBACKSON &&
3227                             !NFSRV_V4DELEGLIMIT(nfsrv_delegatecnt) &&
3228                             NFSVNO_DELEGOK(vp) &&
3229                             ((nd->nd_flag & ND_NFSV41) == 0 ||
3230                              (new_stp->ls_flags & NFSLCK_WANTNODELEG) == 0)) {
3231                                 new_deleg->ls_stateid.seqid =
3232                                     delegstateidp->seqid = 1;
3233                                 new_deleg->ls_stateid.other[0] =
3234                                     delegstateidp->other[0]
3235                                     = clp->lc_clientid.lval[0];
3236                                 new_deleg->ls_stateid.other[1] =
3237                                     delegstateidp->other[1]
3238                                     = clp->lc_clientid.lval[1];
3239                                 new_deleg->ls_stateid.other[2] =
3240                                     delegstateidp->other[2]
3241                                     = nfsrv_nextstateindex(clp);
3242                                 if (writedeleg && !NFSVNO_EXRDONLY(exp) &&
3243                                     (nfsrv_writedelegifpos || !readonly) &&
3244                                     ((nd->nd_flag & ND_NFSV41) == 0 ||
3245                                      (new_stp->ls_flags & NFSLCK_WANTRDELEG) ==
3246                                      0)) {
3247                                         new_deleg->ls_flags =
3248                                             (NFSLCK_DELEGWRITE |
3249                                              NFSLCK_READACCESS |
3250                                              NFSLCK_WRITEACCESS);
3251                                         *rflagsp |= NFSV4OPEN_WRITEDELEGATE;
3252                                         nfsrv_writedelegcnt++;
3253                                 } else {
3254                                         new_deleg->ls_flags =
3255                                             (NFSLCK_DELEGREAD |
3256                                              NFSLCK_READACCESS);
3257                                         *rflagsp |= NFSV4OPEN_READDELEGATE;
3258                                 }
3259                                 new_deleg->ls_uid = new_stp->ls_uid;
3260                                 new_deleg->ls_lfp = lfp;
3261                                 new_deleg->ls_clp = clp;
3262                                 new_deleg->ls_filerev = filerev;
3263                                 new_deleg->ls_compref = nd->nd_compref;
3264                                 LIST_INSERT_HEAD(&lfp->lf_deleg, new_deleg,
3265                                     ls_file);
3266                                 LIST_INSERT_HEAD(NFSSTATEHASH(clp,
3267                                     new_deleg->ls_stateid), new_deleg, ls_hash);
3268                                 LIST_INSERT_HEAD(&clp->lc_deleg, new_deleg,
3269                                     ls_list);
3270                                 new_deleg = NULL;
3271                                 newnfsstats.srvdelegates++;
3272                                 nfsrv_openpluslock++;
3273                                 nfsrv_delegatecnt++;
3274                         }
3275                         /*
3276                          * Since NFSv4.1 never does an OpenConfirm, the first
3277                          * open state will be acquired here.
3278                          */
3279                         if (!(clp->lc_flags & LCL_STAMPEDSTABLE)) {
3280                                 clp->lc_flags |= LCL_STAMPEDSTABLE;
3281                                 len = clp->lc_idlen;
3282                                 NFSBCOPY(clp->lc_id, clidp, len);
3283                                 gotstate = 1;
3284                         }
3285                 } else {
3286                         *rflagsp |= NFSV4OPEN_RESULTCONFIRM;
3287                         new_stp->ls_flags = NFSLCK_NEEDSCONFIRM;
3288                 }
3289                 nfsrvd_refcache(new_stp->ls_op);
3290                 new_stp->ls_noopens = 0;
3291                 LIST_INIT(&new_stp->ls_open);
3292                 LIST_INSERT_HEAD(&new_stp->ls_open, new_open, ls_list);
3293                 LIST_INSERT_HEAD(&clp->lc_open, new_stp, ls_list);
3294                 LIST_INSERT_HEAD(NFSSTATEHASH(clp, new_open->ls_stateid),
3295                     new_open, ls_hash);
3296                 openstp = new_open;
3297                 new_open = NULL;
3298                 *new_stpp = NULL;
3299                 newnfsstats.srvopens++;
3300                 nfsrv_openpluslock++;
3301                 newnfsstats.srvopenowners++;
3302                 nfsrv_openpluslock++;
3303         }
3304         if (!error) {
3305                 stateidp->seqid = openstp->ls_stateid.seqid;
3306                 stateidp->other[0] = openstp->ls_stateid.other[0];
3307                 stateidp->other[1] = openstp->ls_stateid.other[1];
3308                 stateidp->other[2] = openstp->ls_stateid.other[2];
3309         }
3310         NFSUNLOCKSTATE();
3311         if (haslock) {
3312                 NFSLOCKV4ROOTMUTEX();
3313                 nfsv4_unlock(&nfsv4rootfs_lock, 1);
3314                 NFSUNLOCKV4ROOTMUTEX();
3315         }
3316         if (new_open)
3317                 FREE((caddr_t)new_open, M_NFSDSTATE);
3318         if (new_deleg)
3319                 FREE((caddr_t)new_deleg, M_NFSDSTATE);
3320
3321         /*
3322          * If the NFSv4.1 client just acquired its first open, write a timestamp
3323          * to the stable storage file.
3324          */
3325         if (gotstate != 0) {
3326                 nfsrv_writestable(clidp, len, NFSNST_NEWSTATE, p);
3327                 nfsrv_backupstable();
3328         }
3329
3330 out:
3331         free(clidp, M_TEMP);
3332         NFSEXITCODE2(error, nd);
3333         return (error);
3334 }
3335
3336 /*
3337  * Open update. Does the confirm, downgrade and close.
3338  */
3339 APPLESTATIC int
3340 nfsrv_openupdate(vnode_t vp, struct nfsstate *new_stp, nfsquad_t clientid,
3341     nfsv4stateid_t *stateidp, struct nfsrv_descript *nd, NFSPROC_T *p)
3342 {
3343         struct nfsstate *stp, *ownerstp;
3344         struct nfsclient *clp;
3345         struct nfslockfile *lfp;
3346         u_int32_t bits;
3347         int error = 0, gotstate = 0, len = 0;
3348         u_char *clidp = NULL;
3349
3350         /*
3351          * Check for restart conditions (client and server).
3352          */
3353         error = nfsrv_checkrestart(clientid, new_stp->ls_flags,
3354             &new_stp->ls_stateid, 0);
3355         if (error)
3356                 goto out;
3357
3358         clidp = malloc(NFSV4_OPAQUELIMIT, M_TEMP, M_WAITOK);
3359         NFSLOCKSTATE();
3360         /*
3361          * Get the open structure via clientid and stateid.
3362          */
3363         error = nfsrv_getclient(clientid, CLOPS_RENEW, &clp, NULL,
3364             (nfsquad_t)((u_quad_t)0), 0, nd, p);
3365         if (!error)
3366                 error = nfsrv_getstate(clp, &new_stp->ls_stateid,
3367                     new_stp->ls_flags, &stp);
3368
3369         /*
3370          * Sanity check the open.
3371          */
3372         if (!error && (!(stp->ls_flags & NFSLCK_OPEN) ||
3373                 (!(new_stp->ls_flags & NFSLCK_CONFIRM) &&
3374                  (stp->ls_openowner->ls_flags & NFSLCK_NEEDSCONFIRM)) ||
3375                 ((new_stp->ls_flags & NFSLCK_CONFIRM) &&
3376                  (!(stp->ls_openowner->ls_flags & NFSLCK_NEEDSCONFIRM)))))
3377                 error = NFSERR_BADSTATEID;
3378
3379         if (!error)
3380                 error = nfsrv_checkseqid(nd, new_stp->ls_seq,
3381                     stp->ls_openowner, new_stp->ls_op);
3382         if (!error && stp->ls_stateid.seqid != new_stp->ls_stateid.seqid &&
3383             (((nd->nd_flag & ND_NFSV41) == 0 &&
3384               !(new_stp->ls_flags & NFSLCK_CONFIRM)) ||
3385              ((nd->nd_flag & ND_NFSV41) != 0 &&
3386               new_stp->ls_stateid.seqid != 0)))
3387                 error = NFSERR_OLDSTATEID;
3388         if (!error && vnode_vtype(vp) != VREG) {
3389                 if (vnode_vtype(vp) == VDIR)
3390                         error = NFSERR_ISDIR;
3391                 else
3392                         error = NFSERR_INVAL;
3393         }
3394
3395         if (error) {
3396                 /*
3397                  * If a client tries to confirm an Open with a bad
3398                  * seqid# and there are no byte range locks or other Opens
3399                  * on the openowner, just throw it away, so the next use of the
3400                  * openowner will start a fresh seq#.
3401                  */
3402                 if (error == NFSERR_BADSEQID &&
3403                     (new_stp->ls_flags & NFSLCK_CONFIRM) &&
3404                     nfsrv_nootherstate(stp))
3405                         nfsrv_freeopenowner(stp->ls_openowner, 0, p);
3406                 NFSUNLOCKSTATE();
3407                 goto out;
3408         }
3409
3410         /*
3411          * Set the return stateid.
3412          */
3413         stateidp->seqid = stp->ls_stateid.seqid + 1;
3414         if ((nd->nd_flag & ND_NFSV41) != 0 && stateidp->seqid == 0)
3415                 stateidp->seqid = 1;
3416         stateidp->other[0] = stp->ls_stateid.other[0];
3417         stateidp->other[1] = stp->ls_stateid.other[1];
3418         stateidp->other[2] = stp->ls_stateid.other[2];
3419         /*
3420          * Now, handle the three cases.
3421          */
3422         if (new_stp->ls_flags & NFSLCK_CONFIRM) {
3423                 /*
3424                  * If the open doesn't need confirmation, it seems to me that
3425                  * there is a client error, but I'll just log it and keep going?
3426                  */
3427                 if (!(stp->ls_openowner->ls_flags & NFSLCK_NEEDSCONFIRM))
3428                         printf("Nfsv4d: stray open confirm\n");
3429                 stp->ls_openowner->ls_flags = 0;
3430                 stp->ls_stateid.seqid++;
3431                 if ((nd->nd_flag & ND_NFSV41) != 0 &&
3432                     stp->ls_stateid.seqid == 0)
3433                         stp->ls_stateid.seqid = 1;
3434                 if (!(clp->lc_flags & LCL_STAMPEDSTABLE)) {
3435                         clp->lc_flags |= LCL_STAMPEDSTABLE;
3436                         len = clp->lc_idlen;
3437                         NFSBCOPY(clp->lc_id, clidp, len);
3438                         gotstate = 1;
3439                 }
3440                 NFSUNLOCKSTATE();
3441         } else if (new_stp->ls_flags & NFSLCK_CLOSE) {
3442                 ownerstp = stp->ls_openowner;
3443                 lfp = stp->ls_lfp;
3444                 if (nfsrv_dolocallocks != 0 && !LIST_EMPTY(&stp->ls_open)) {
3445                         /* Get the lf lock */
3446                         nfsrv_locklf(lfp);
3447                         NFSUNLOCKSTATE();
3448                         ASSERT_VOP_ELOCKED(vp, "nfsrv_openupdate");
3449                         NFSVOPUNLOCK(vp, 0);
3450                         if (nfsrv_freeopen(stp, vp, 1, p) == 0) {
3451                                 NFSLOCKSTATE();
3452                                 nfsrv_unlocklf(lfp);
3453                                 NFSUNLOCKSTATE();
3454                         }
3455                         NFSVOPLOCK(vp, LK_EXCLUSIVE | LK_RETRY);
3456                 } else {
3457                         (void) nfsrv_freeopen(stp, NULL, 0, p);
3458                         NFSUNLOCKSTATE();
3459                 }
3460         } else {
3461                 /*
3462                  * Update the share bits, making sure that the new set are a
3463                  * subset of the old ones.
3464                  */
3465                 bits = (new_stp->ls_flags & NFSLCK_SHAREBITS);
3466                 if (~(stp->ls_flags) & bits) {
3467                         NFSUNLOCKSTATE();
3468                         error = NFSERR_INVAL;
3469                         goto out;
3470                 }
3471                 stp->ls_flags = (bits | NFSLCK_OPEN);
3472                 stp->ls_stateid.seqid++;
3473                 if ((nd->nd_flag & ND_NFSV41) != 0 &&
3474                     stp->ls_stateid.seqid == 0)
3475                         stp->ls_stateid.seqid = 1;
3476                 NFSUNLOCKSTATE();
3477         }
3478
3479         /*
3480          * If the client just confirmed its first open, write a timestamp
3481          * to the stable storage file.
3482          */
3483         if (gotstate != 0) {
3484                 nfsrv_writestable(clidp, len, NFSNST_NEWSTATE, p);
3485                 nfsrv_backupstable();
3486         }
3487
3488 out:
3489         free(clidp, M_TEMP);
3490         NFSEXITCODE2(error, nd);
3491         return (error);
3492 }
3493
3494 /*
3495  * Delegation update. Does the purge and return.
3496  */
3497 APPLESTATIC int
3498 nfsrv_delegupdate(struct nfsrv_descript *nd, nfsquad_t clientid,
3499     nfsv4stateid_t *stateidp, vnode_t vp, int op, struct ucred *cred,
3500     NFSPROC_T *p)
3501 {
3502         struct nfsstate *stp;
3503         struct nfsclient *clp;
3504         int error = 0;
3505         fhandle_t fh;
3506
3507         /*
3508          * Do a sanity check against the file handle for DelegReturn.
3509          */
3510         if (vp) {
3511                 error = nfsvno_getfh(vp, &fh, p);
3512                 if (error)
3513                         goto out;
3514         }
3515         /*
3516          * Check for restart conditions (client and server).
3517          */
3518         if (op == NFSV4OP_DELEGRETURN)
3519                 error = nfsrv_checkrestart(clientid, NFSLCK_DELEGRETURN,
3520                         stateidp, 0);
3521         else
3522                 error = nfsrv_checkrestart(clientid, NFSLCK_DELEGPURGE,
3523                         stateidp, 0);
3524
3525         NFSLOCKSTATE();
3526         /*
3527          * Get the open structure via clientid and stateid.
3528          */
3529         if (!error)
3530             error = nfsrv_getclient(clientid, CLOPS_RENEW, &clp, NULL,
3531                 (nfsquad_t)((u_quad_t)0), 0, nd, p);
3532         if (error) {
3533                 if (error == NFSERR_CBPATHDOWN)
3534                         error = 0;
3535                 if (error == NFSERR_STALECLIENTID && op == NFSV4OP_DELEGRETURN)
3536                         error = NFSERR_STALESTATEID;
3537         }
3538         if (!error && op == NFSV4OP_DELEGRETURN) {
3539             error = nfsrv_getstate(clp, stateidp, NFSLCK_DELEGRETURN, &stp);
3540             if (!error && stp->ls_stateid.seqid != stateidp->seqid &&
3541                 ((nd->nd_flag & ND_NFSV41) == 0 || stateidp->seqid != 0))
3542                 error = NFSERR_OLDSTATEID;
3543         }
3544         /*
3545          * NFSERR_EXPIRED means that the state has gone away,
3546          * so Delegations have been purged. Just return ok.
3547          */
3548         if (error == NFSERR_EXPIRED && op == NFSV4OP_DELEGPURGE) {
3549                 NFSUNLOCKSTATE();
3550                 error = 0;
3551                 goto out;
3552         }
3553         if (error) {
3554                 NFSUNLOCKSTATE();
3555                 goto out;
3556         }
3557
3558         if (op == NFSV4OP_DELEGRETURN) {
3559                 if (NFSBCMP((caddr_t)&fh, (caddr_t)&stp->ls_lfp->lf_fh,
3560                     sizeof (fhandle_t))) {
3561                         NFSUNLOCKSTATE();
3562                         error = NFSERR_BADSTATEID;
3563                         goto out;
3564                 }
3565                 nfsrv_freedeleg(stp);
3566         } else {
3567                 nfsrv_freedeleglist(&clp->lc_olddeleg);
3568         }
3569         NFSUNLOCKSTATE();
3570         error = 0;
3571
3572 out:
3573         NFSEXITCODE(error);
3574         return (error);
3575 }
3576
3577 /*
3578  * Release lock owner.
3579  */
3580 APPLESTATIC int
3581 nfsrv_releaselckown(struct nfsstate *new_stp, nfsquad_t clientid,
3582     NFSPROC_T *p)
3583 {
3584         struct nfsstate *stp, *nstp, *openstp, *ownstp;
3585         struct nfsclient *clp;
3586         int error = 0;
3587
3588         /*
3589          * Check for restart conditions (client and server).
3590          */
3591         error = nfsrv_checkrestart(clientid, new_stp->ls_flags,
3592             &new_stp->ls_stateid, 0);
3593         if (error)
3594                 goto out;
3595
3596         NFSLOCKSTATE();
3597         /*
3598          * Get the lock owner by name.
3599          */
3600         error = nfsrv_getclient(clientid, CLOPS_RENEW, &clp, NULL,
3601             (nfsquad_t)((u_quad_t)0), 0, NULL, p);
3602         if (error) {
3603                 NFSUNLOCKSTATE();
3604                 goto out;
3605         }
3606         LIST_FOREACH(ownstp, &clp->lc_open, ls_list) {
3607             LIST_FOREACH(openstp, &ownstp->ls_open, ls_list) {
3608                 stp = LIST_FIRST(&openstp->ls_open);
3609                 while (stp != LIST_END(&openstp->ls_open)) {
3610                     nstp = LIST_NEXT(stp, ls_list);
3611                     /*
3612                      * If the owner matches, check for locks and
3613                      * then free or return an error.
3614                      */
3615                     if (stp->ls_ownerlen == new_stp->ls_ownerlen &&
3616                         !NFSBCMP(stp->ls_owner, new_stp->ls_owner,
3617                          stp->ls_ownerlen)){
3618                         if (LIST_EMPTY(&stp->ls_lock)) {
3619                             nfsrv_freelockowner(stp, NULL, 0, p);
3620                         } else {
3621                             NFSUNLOCKSTATE();
3622                             error = NFSERR_LOCKSHELD;
3623                             goto out;
3624                         }
3625                     }
3626                     stp = nstp;
3627                 }
3628             }
3629         }
3630         NFSUNLOCKSTATE();
3631
3632 out:
3633         NFSEXITCODE(error);
3634         return (error);
3635 }
3636
3637 /*
3638  * Get the file handle for a lock structure.
3639  */
3640 static int
3641 nfsrv_getlockfh(vnode_t vp, u_short flags, struct nfslockfile *new_lfp,
3642     fhandle_t *nfhp, NFSPROC_T *p)
3643 {
3644         fhandle_t *fhp = NULL;
3645         int error;
3646
3647         /*
3648          * For lock, use the new nfslock structure, otherwise just
3649          * a fhandle_t on the stack.
3650          */
3651         if (flags & NFSLCK_OPEN) {
3652                 KASSERT(new_lfp != NULL, ("nfsrv_getlockfh: new_lfp NULL"));
3653                 fhp = &new_lfp->lf_fh;
3654         } else if (nfhp) {
3655                 fhp = nfhp;
3656         } else {
3657                 panic("nfsrv_getlockfh");
3658         }
3659         error = nfsvno_getfh(vp, fhp, p);
3660         NFSEXITCODE(error);
3661         return (error);
3662 }
3663
3664 /*
3665  * Get an nfs lock structure. Allocate one, as required, and return a
3666  * pointer to it.
3667  * Returns an NFSERR_xxx upon failure or -1 to indicate no current lock.
3668  */
3669 static int
3670 nfsrv_getlockfile(u_short flags, struct nfslockfile **new_lfpp,
3671     struct nfslockfile **lfpp, fhandle_t *nfhp, int lockit)
3672 {
3673         struct nfslockfile *lfp;
3674         fhandle_t *fhp = NULL, *tfhp;
3675         struct nfslockhashhead *hp;
3676         struct nfslockfile *new_lfp = NULL;
3677
3678         /*
3679          * For lock, use the new nfslock structure, otherwise just
3680          * a fhandle_t on the stack.
3681          */
3682         if (flags & NFSLCK_OPEN) {
3683                 new_lfp = *new_lfpp;
3684                 fhp = &new_lfp->lf_fh;
3685         } else if (nfhp) {
3686                 fhp = nfhp;
3687         } else {
3688                 panic("nfsrv_getlockfile");
3689         }
3690
3691         hp = NFSLOCKHASH(fhp);
3692         LIST_FOREACH(lfp, hp, lf_hash) {
3693                 tfhp = &lfp->lf_fh;
3694                 if (NFSVNO_CMPFH(fhp, tfhp)) {
3695                         if (lockit)
3696                                 nfsrv_locklf(lfp);
3697                         *lfpp = lfp;
3698                         return (0);
3699                 }
3700         }
3701         if (!(flags & NFSLCK_OPEN))
3702                 return (-1);
3703
3704         /*
3705          * No match, so chain the new one into the list.
3706          */
3707         LIST_INIT(&new_lfp->lf_open);
3708         LIST_INIT(&new_lfp->lf_lock);
3709         LIST_INIT(&new_lfp->lf_deleg);
3710         LIST_INIT(&new_lfp->lf_locallock);
3711         LIST_INIT(&new_lfp->lf_rollback);
3712         new_lfp->lf_locallock_lck.nfslock_usecnt = 0;
3713         new_lfp->lf_locallock_lck.nfslock_lock = 0;
3714         new_lfp->lf_usecount = 0;
3715         LIST_INSERT_HEAD(hp, new_lfp, lf_hash);
3716         *lfpp = new_lfp;
3717         *new_lfpp = NULL;
3718         return (0);
3719 }
3720
3721 /*
3722  * This function adds a nfslock lock structure to the list for the associated
3723  * nfsstate and nfslockfile structures. It will be inserted after the
3724  * entry pointed at by insert_lop.
3725  */
3726 static void
3727 nfsrv_insertlock(struct nfslock *new_lop, struct nfslock *insert_lop,
3728     struct nfsstate *stp, struct nfslockfile *lfp)
3729 {
3730         struct nfslock *lop, *nlop;
3731
3732         new_lop->lo_stp = stp;
3733         new_lop->lo_lfp = lfp;
3734
3735         if (stp != NULL) {
3736                 /* Insert in increasing lo_first order */
3737                 lop = LIST_FIRST(&lfp->lf_lock);
3738                 if (lop == LIST_END(&lfp->lf_lock) ||
3739                     new_lop->lo_first <= lop->lo_first) {
3740                         LIST_INSERT_HEAD(&lfp->lf_lock, new_lop, lo_lckfile);
3741                 } else {
3742                         nlop = LIST_NEXT(lop, lo_lckfile);
3743                         while (nlop != LIST_END(&lfp->lf_lock) &&
3744                                nlop->lo_first < new_lop->lo_first) {
3745                                 lop = nlop;
3746                                 nlop = LIST_NEXT(lop, lo_lckfile);
3747                         }
3748                         LIST_INSERT_AFTER(lop, new_lop, lo_lckfile);
3749                 }
3750         } else {
3751                 new_lop->lo_lckfile.le_prev = NULL;     /* list not used */
3752         }
3753
3754         /*
3755          * Insert after insert_lop, which is overloaded as stp or lfp for
3756          * an empty list.
3757          */
3758         if (stp == NULL && (struct nfslockfile *)insert_lop == lfp)
3759                 LIST_INSERT_HEAD(&lfp->lf_locallock, new_lop, lo_lckowner);
3760         else if ((struct nfsstate *)insert_lop == stp)
3761                 LIST_INSERT_HEAD(&stp->ls_lock, new_lop, lo_lckowner);
3762         else
3763                 LIST_INSERT_AFTER(insert_lop, new_lop, lo_lckowner);
3764         if (stp != NULL) {
3765                 newnfsstats.srvlocks++;
3766                 nfsrv_openpluslock++;
3767         }
3768 }
3769
3770 /*
3771  * This function updates the locking for a lock owner and given file. It
3772  * maintains a list of lock ranges ordered on increasing file offset that
3773  * are NFSLCK_READ or NFSLCK_WRITE and non-overlapping (aka POSIX style).
3774  * It always adds new_lop to the list and sometimes uses the one pointed
3775  * at by other_lopp.
3776  */
3777 static void
3778 nfsrv_updatelock(struct nfsstate *stp, struct nfslock **new_lopp,
3779     struct nfslock **other_lopp, struct nfslockfile *lfp)
3780 {
3781         struct nfslock *new_lop = *new_lopp;
3782         struct nfslock *lop, *tlop, *ilop;
3783         struct nfslock *other_lop = *other_lopp;
3784         int unlock = 0, myfile = 0;
3785         u_int64_t tmp;
3786
3787         /*
3788          * Work down the list until the lock is merged.
3789          */
3790         if (new_lop->lo_flags & NFSLCK_UNLOCK)
3791                 unlock = 1;
3792         if (stp != NULL) {
3793                 ilop = (struct nfslock *)stp;
3794                 lop = LIST_FIRST(&stp->ls_lock);
3795         } else {
3796                 ilop = (struct nfslock *)lfp;
3797                 lop = LIST_FIRST(&lfp->lf_locallock);
3798         }
3799         while (lop != NULL) {
3800             /*
3801              * Only check locks for this file that aren't before the start of
3802              * new lock's range.
3803              */
3804             if (lop->lo_lfp == lfp) {
3805               myfile = 1;
3806               if (lop->lo_end >= new_lop->lo_first) {
3807                 if (new_lop->lo_end < lop->lo_first) {
3808                         /*
3809                          * If the new lock ends before the start of the
3810                          * current lock's range, no merge, just insert
3811                          * the new lock.
3812                          */
3813                         break;
3814                 }
3815                 if (new_lop->lo_flags == lop->lo_flags ||
3816                     (new_lop->lo_first <= lop->lo_first &&
3817                      new_lop->lo_end >= lop->lo_end)) {
3818                         /*
3819                          * This lock can be absorbed by the new lock/unlock.
3820                          * This happens when it covers the entire range
3821                          * of the old lock or is contiguous
3822                          * with the old lock and is of the same type or an
3823                          * unlock.
3824                          */
3825                         if (lop->lo_first < new_lop->lo_first)
3826                                 new_lop->lo_first = lop->lo_first;
3827                         if (lop->lo_end > new_lop->lo_end)
3828                                 new_lop->lo_end = lop->lo_end;
3829                         tlop = lop;
3830                         lop = LIST_NEXT(lop, lo_lckowner);
3831                         nfsrv_freenfslock(tlop);
3832                         continue;
3833                 }
3834
3835                 /*
3836                  * All these cases are for contiguous locks that are not the
3837                  * same type, so they can't be merged.
3838                  */
3839                 if (new_lop->lo_first <= lop->lo_first) {
3840                         /*
3841                          * This case is where the new lock overlaps with the
3842                          * first part of the old lock. Move the start of the
3843                          * old lock to just past the end of the new lock. The
3844                          * new lock will be inserted in front of the old, since
3845                          * ilop hasn't been updated. (We are done now.)
3846                          */
3847                         lop->lo_first = new_lop->lo_end;
3848                         break;
3849                 }
3850                 if (new_lop->lo_end >= lop->lo_end) {
3851                         /*
3852                          * This case is where the new lock overlaps with the
3853                          * end of the old lock's range. Move the old lock's
3854                          * end to just before the new lock's first and insert
3855                          * the new lock after the old lock.
3856                          * Might not be done yet, since the new lock could
3857                          * overlap further locks with higher ranges.
3858                          */
3859                         lop->lo_end = new_lop->lo_first;
3860                         ilop = lop;
3861                         lop = LIST_NEXT(lop, lo_lckowner);
3862                         continue;
3863                 }
3864                 /*
3865                  * The final case is where the new lock's range is in the
3866                  * middle of the current lock's and splits the current lock
3867                  * up. Use *other_lopp to handle the second part of the
3868                  * split old lock range. (We are done now.)
3869                  * For unlock, we use new_lop as other_lop and tmp, since
3870                  * other_lop and new_lop are the same for this case.
3871                  * We noted the unlock case above, so we don't need
3872                  * new_lop->lo_flags any longer.
3873                  */
3874                 tmp = new_lop->lo_first;
3875                 if (other_lop == NULL) {
3876                         if (!unlock)
3877                                 panic("nfsd srv update unlock");
3878                         other_lop = new_lop;
3879                         *new_lopp = NULL;
3880                 }
3881                 other_lop->lo_first = new_lop->lo_end;
3882                 other_lop->lo_end = lop->lo_end;
3883                 other_lop->lo_flags = lop->lo_flags;
3884                 other_lop->lo_stp = stp;
3885                 other_lop->lo_lfp = lfp;
3886                 lop->lo_end = tmp;
3887                 nfsrv_insertlock(other_lop, lop, stp, lfp);
3888                 *other_lopp = NULL;
3889                 ilop = lop;
3890                 break;
3891               }
3892             }
3893             ilop = lop;
3894             lop = LIST_NEXT(lop, lo_lckowner);
3895             if (myfile && (lop == NULL || lop->lo_lfp != lfp))
3896                 break;
3897         }
3898
3899         /*
3900          * Insert the new lock in the list at the appropriate place.
3901          */
3902         if (!unlock) {
3903                 nfsrv_insertlock(new_lop, ilop, stp, lfp);
3904                 *new_lopp = NULL;
3905         }
3906 }
3907
3908 /*
3909  * This function handles sequencing of locks, etc.
3910  * It returns an error that indicates what the caller should do.
3911  */
3912 static int
3913 nfsrv_checkseqid(struct nfsrv_descript *nd, u_int32_t seqid,
3914     struct nfsstate *stp, struct nfsrvcache *op)
3915 {
3916         int error = 0;
3917
3918         if ((nd->nd_flag & ND_NFSV41) != 0)
3919                 /* NFSv4.1 ignores the open_seqid and lock_seqid. */
3920                 goto out;
3921         if (op != nd->nd_rp)
3922                 panic("nfsrvstate checkseqid");
3923         if (!(op->rc_flag & RC_INPROG))
3924                 panic("nfsrvstate not inprog");
3925         if (stp->ls_op && stp->ls_op->rc_refcnt <= 0) {
3926                 printf("refcnt=%d\n", stp->ls_op->rc_refcnt);
3927                 panic("nfsrvstate op refcnt");
3928         }
3929         if ((stp->ls_seq + 1) == seqid) {
3930                 if (stp->ls_op)
3931                         nfsrvd_derefcache(stp->ls_op);
3932                 stp->ls_op = op;
3933                 nfsrvd_refcache(op);
3934                 stp->ls_seq = seqid;
3935                 goto out;
3936         } else if (stp->ls_seq == seqid && stp->ls_op &&
3937                 op->rc_xid == stp->ls_op->rc_xid &&
3938                 op->rc_refcnt == 0 &&
3939                 op->rc_reqlen == stp->ls_op->rc_reqlen &&
3940                 op->rc_cksum == stp->ls_op->rc_cksum) {
3941                 if (stp->ls_op->rc_flag & RC_INPROG) {
3942                         error = NFSERR_DONTREPLY;
3943                         goto out;
3944                 }
3945                 nd->nd_rp = stp->ls_op;
3946                 nd->nd_rp->rc_flag |= RC_INPROG;
3947                 nfsrvd_delcache(op);
3948                 error = NFSERR_REPLYFROMCACHE;
3949                 goto out;
3950         }
3951         error = NFSERR_BADSEQID;
3952
3953 out:
3954         NFSEXITCODE2(error, nd);
3955         return (error);
3956 }
3957
3958 /*
3959  * Get the client ip address for callbacks. If the strings can't be parsed,
3960  * just set lc_program to 0 to indicate no callbacks are possible.
3961  * (For cases where the address can't be parsed or is 0.0.0.0.0.0, set
3962  *  the address to the client's transport address. This won't be used
3963  *  for callbacks, but can be printed out by newnfsstats for info.)
3964  * Return error if the xdr can't be parsed, 0 otherwise.
3965  */
3966 APPLESTATIC int
3967 nfsrv_getclientipaddr(struct nfsrv_descript *nd, struct nfsclient *clp)
3968 {
3969         u_int32_t *tl;
3970         u_char *cp, *cp2;
3971         int i, j, maxalen = 0, minalen = 0;
3972         sa_family_t af;
3973 #ifdef INET
3974         struct sockaddr_in *rin, *sin;
3975 #endif
3976 #ifdef INET6
3977         struct sockaddr_in6 *rin6, *sin6;
3978 #endif
3979         u_char *addr;
3980         int error = 0, cantparse = 0;
3981         union {
3982                 in_addr_t ival;
3983                 u_char cval[4];
3984         } ip;
3985         union {
3986                 in_port_t sval;
3987                 u_char cval[2];
3988         } port;
3989
3990         /* 8 is the maximum length of the port# string. */
3991         addr = malloc(INET6_ADDRSTRLEN + 8, M_TEMP, M_WAITOK);
3992         clp->lc_req.nr_client = NULL;
3993         clp->lc_req.nr_lock = 0;
3994         af = AF_UNSPEC;
3995         NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
3996         i = fxdr_unsigned(int, *tl);
3997         if (i >= 3 && i <= 4) {
3998                 error = nfsrv_mtostr(nd, addr, i);
3999                 if (error)
4000                         goto nfsmout;
4001 #ifdef INET
4002                 if (!strcmp(addr, "tcp")) {
4003                         clp->lc_flags |= LCL_TCPCALLBACK;
4004                         clp->lc_req.nr_sotype = SOCK_STREAM;
4005                         clp->lc_req.nr_soproto = IPPROTO_TCP;
4006                         af = AF_INET;
4007                 } else if (!strcmp(addr, "udp")) {
4008                         clp->lc_req.nr_sotype = SOCK_DGRAM;
4009                         clp->lc_req.nr_soproto = IPPROTO_UDP;
4010                         af = AF_INET;
4011                 }
4012 #endif
4013 #ifdef INET6
4014                 if (af == AF_UNSPEC) {
4015                         if (!strcmp(addr, "tcp6")) {
4016                                 clp->lc_flags |= LCL_TCPCALLBACK;
4017                                 clp->lc_req.nr_sotype = SOCK_STREAM;
4018                                 clp->lc_req.nr_soproto = IPPROTO_TCP;
4019                                 af = AF_INET6;
4020                         } else if (!strcmp(addr, "udp6")) {
4021                                 clp->lc_req.nr_sotype = SOCK_DGRAM;
4022                                 clp->lc_req.nr_soproto = IPPROTO_UDP;
4023                                 af = AF_INET6;
4024                         }
4025                 }
4026 #endif
4027                 if (af == AF_UNSPEC) {
4028                         cantparse = 1;
4029                 }
4030         } else {
4031                 cantparse = 1;
4032                 if (i > 0) {
4033                         error = nfsm_advance(nd, NFSM_RNDUP(i), -1);
4034                         if (error)
4035                                 goto nfsmout;
4036                 }
4037         }
4038         /*
4039          * The caller has allocated clp->lc_req.nr_nam to be large enough
4040          * for either AF_INET or AF_INET6 and zeroed out the contents.
4041          * maxalen is set to the maximum length of the host IP address string
4042          * plus 8 for the maximum length of the port#.
4043          * minalen is set to the minimum length of the host IP address string
4044          * plus 4 for the minimum length of the port#.
4045          * These lengths do not include NULL termination,
4046          * so INET[6]_ADDRSTRLEN - 1 is used in the calculations.
4047          */
4048         switch (af) {
4049 #ifdef INET
4050         case AF_INET:
4051                 rin = (struct sockaddr_in *)clp->lc_req.nr_nam;
4052                 rin->sin_family = AF_INET;
4053                 rin->sin_len = sizeof(struct sockaddr_in);
4054                 maxalen = INET_ADDRSTRLEN - 1 + 8;
4055                 minalen = 7 + 4;
4056                 break;
4057 #endif
4058 #ifdef INET6
4059         case AF_INET6:
4060                 rin6 = (struct sockaddr_in6 *)clp->lc_req.nr_nam;
4061                 rin6->sin6_family = AF_INET6;
4062                 rin6->sin6_len = sizeof(struct sockaddr_in6);
4063                 maxalen = INET6_ADDRSTRLEN - 1 + 8;
4064                 minalen = 3 + 4;
4065                 break;
4066 #endif
4067         }
4068         NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
4069         i = fxdr_unsigned(int, *tl);
4070         if (i < 0) {
4071                 error = NFSERR_BADXDR;
4072                 goto nfsmout;
4073         } else if (i == 0) {
4074                 cantparse = 1;
4075         } else if (!cantparse && i <= maxalen && i >= minalen) {
4076                 error = nfsrv_mtostr(nd, addr, i);
4077                 if (error)
4078                         goto nfsmout;
4079
4080                 /*
4081                  * Parse out the address fields. We expect 6 decimal numbers
4082                  * separated by '.'s for AF_INET and two decimal numbers
4083                  * preceeded by '.'s for AF_INET6.
4084                  */
4085                 cp = NULL;
4086                 switch (af) {
4087 #ifdef INET6
4088                 /*
4089                  * For AF_INET6, first parse the host address.
4090                  */
4091                 case AF_INET6:
4092                         cp = strchr(addr, '.');
4093                         if (cp != NULL) {
4094                                 *cp++ = '\0';
4095                                 if (inet_pton(af, addr, &rin6->sin6_addr) == 1)
4096                                         i = 4;
4097                                 else {
4098                                         cp = NULL;
4099                                         cantparse = 1;
4100                                 }
4101                         }
4102                         break;
4103 #endif
4104 #ifdef INET
4105                 case AF_INET:
4106                         cp = addr;
4107                         i = 0;
4108                         break;
4109 #endif
4110                 }
4111                 while (cp != NULL && *cp && i < 6) {
4112                         cp2 = cp;
4113                         while (*cp2 && *cp2 != '.')
4114                                 cp2++;
4115                         if (*cp2)
4116                                 *cp2++ = '\0';
4117                         else if (i != 5) {
4118                                 cantparse = 1;
4119                                 break;
4120                         }
4121                         j = nfsrv_getipnumber(cp);
4122                         if (j >= 0) {
4123                                 if (i < 4)
4124                                         ip.cval[3 - i] = j;
4125                                 else
4126                                         port.cval[5 - i] = j;
4127                         } else {
4128                                 cantparse = 1;
4129                                 break;
4130                         }
4131                         cp = cp2;
4132                         i++;
4133                 }
4134                 if (!cantparse) {
4135                         /*
4136                          * The host address INADDR_ANY is (mis)used to indicate
4137                          * "there is no valid callback address".
4138                          */
4139                         switch (af) {
4140 #ifdef INET6
4141                         case AF_INET6:
4142                                 if (!IN6_ARE_ADDR_EQUAL(&rin6->sin6_addr,
4143                                     &in6addr_any))
4144                                         rin6->sin6_port = htons(port.sval);
4145                                 else
4146                                         cantparse = 1;
4147                                 break;
4148 #endif
4149 #ifdef INET
4150                         case AF_INET:
4151                                 if (ip.ival != INADDR_ANY) {
4152                                         rin->sin_addr.s_addr = htonl(ip.ival);
4153                                         rin->sin_port = htons(port.sval);
4154                                 } else {
4155                                         cantparse = 1;
4156                                 }
4157                                 break;
4158 #endif
4159                         }
4160                 }
4161         } else {
4162                 cantparse = 1;
4163                 if (i > 0) {
4164                         error = nfsm_advance(nd, NFSM_RNDUP(i), -1);
4165                         if (error)
4166                                 goto nfsmout;
4167                 }
4168         }
4169         if (cantparse) {
4170                 switch (nd->nd_nam->sa_family) {
4171 #ifdef INET
4172                 case AF_INET:
4173                         sin = (struct sockaddr_in *)nd->nd_nam;
4174                         rin = (struct sockaddr_in *)clp->lc_req.nr_nam;
4175                         rin->sin_family = AF_INET;
4176                         rin->sin_len = sizeof(struct sockaddr_in);
4177                         rin->sin_addr.s_addr = sin->sin_addr.s_addr;
4178                         rin->sin_port = 0x0;
4179                         break;
4180 #endif
4181 #ifdef INET6
4182                 case AF_INET6:
4183                         sin6 = (struct sockaddr_in6 *)nd->nd_nam;
4184                         rin6 = (struct sockaddr_in6 *)clp->lc_req.nr_nam;
4185                         rin6->sin6_family = AF_INET6;
4186                         rin6->sin6_len = sizeof(struct sockaddr_in6);
4187                         rin6->sin6_addr = sin6->sin6_addr;
4188                         rin6->sin6_port = 0x0;
4189                         break;
4190 #endif
4191                 }
4192                 clp->lc_program = 0;
4193         }
4194 nfsmout:
4195         free(addr, M_TEMP);
4196         NFSEXITCODE2(error, nd);
4197         return (error);
4198 }
4199
4200 /*
4201  * Turn a string of up to three decimal digits into a number. Return -1 upon
4202  * error.
4203  */
4204 static int
4205 nfsrv_getipnumber(u_char *cp)
4206 {
4207         int i = 0, j = 0;
4208
4209         while (*cp) {
4210                 if (j > 2 || *cp < '0' || *cp > '9')
4211                         return (-1);
4212                 i *= 10;
4213                 i += (*cp - '0');
4214                 cp++;
4215                 j++;
4216         }
4217         if (i < 256)
4218                 return (i);
4219         return (-1);
4220 }
4221
4222 /*
4223  * This function checks for restart conditions.
4224  */
4225 static int
4226 nfsrv_checkrestart(nfsquad_t clientid, u_int32_t flags,
4227     nfsv4stateid_t *stateidp, int specialid)
4228 {
4229         int ret = 0;
4230
4231         /*
4232          * First check for a server restart. Open, LockT, ReleaseLockOwner
4233          * and DelegPurge have a clientid, the rest a stateid.
4234          */
4235         if (flags &
4236             (NFSLCK_OPEN | NFSLCK_TEST | NFSLCK_RELEASE | NFSLCK_DELEGPURGE)) {
4237                 if (clientid.lval[0] != nfsrvboottime) {
4238                         ret = NFSERR_STALECLIENTID;
4239                         goto out;
4240                 }
4241         } else if (stateidp->other[0] != nfsrvboottime &&
4242                 specialid == 0) {
4243                 ret = NFSERR_STALESTATEID;
4244                 goto out;
4245         }
4246
4247         /*
4248          * Read, Write, Setattr and LockT can return NFSERR_GRACE and do
4249          * not use a lock/open owner seqid#, so the check can be done now.
4250          * (The others will be checked, as required, later.)
4251          */
4252         if (!(flags & (NFSLCK_CHECK | NFSLCK_TEST)))
4253                 goto out;
4254
4255         NFSLOCKSTATE();
4256         ret = nfsrv_checkgrace(NULL, NULL, flags);
4257         NFSUNLOCKSTATE();
4258
4259 out:
4260         NFSEXITCODE(ret);
4261         return (ret);
4262 }
4263
4264 /*
4265  * Check for grace.
4266  */
4267 static int
4268 nfsrv_checkgrace(struct nfsrv_descript *nd, struct nfsclient *clp,
4269     u_int32_t flags)
4270 {
4271         int error = 0, notreclaimed;
4272         struct nfsrv_stable *sp;
4273
4274         if ((nfsrv_stablefirst.nsf_flags & (NFSNSF_UPDATEDONE |
4275              NFSNSF_GRACEOVER)) == 0) {
4276                 /*
4277                  * First, check to see if all of the clients have done a
4278                  * ReclaimComplete.  If so, grace can end now.
4279                  */
4280                 notreclaimed = 0;
4281                 LIST_FOREACH(sp, &nfsrv_stablefirst.nsf_head, nst_list) {
4282                         if ((sp->nst_flag & NFSNST_RECLAIMED) == 0) {
4283                                 notreclaimed = 1;
4284                                 break;
4285                         }
4286                 }
4287                 if (notreclaimed == 0)
4288                         nfsrv_stablefirst.nsf_flags |= (NFSNSF_GRACEOVER |
4289                             NFSNSF_NEEDLOCK);
4290         }
4291
4292         if ((nfsrv_stablefirst.nsf_flags & NFSNSF_GRACEOVER) != 0) {
4293                 if (flags & NFSLCK_RECLAIM) {
4294                         error = NFSERR_NOGRACE;
4295                         goto out;
4296                 }
4297         } else {
4298                 if (!(flags & NFSLCK_RECLAIM)) {
4299                         error = NFSERR_GRACE;
4300                         goto out;
4301                 }
4302                 if (nd != NULL && clp != NULL &&
4303                     (nd->nd_flag & ND_NFSV41) != 0 &&
4304                     (clp->lc_flags & LCL_RECLAIMCOMPLETE) != 0) {
4305                         error = NFSERR_NOGRACE;
4306                         goto out;
4307                 }
4308
4309                 /*
4310                  * If grace is almost over and we are still getting Reclaims,
4311                  * extend grace a bit.
4312                  */
4313                 if ((NFSD_MONOSEC + NFSRV_LEASEDELTA) >
4314                     nfsrv_stablefirst.nsf_eograce)
4315                         nfsrv_stablefirst.nsf_eograce = NFSD_MONOSEC +
4316                                 NFSRV_LEASEDELTA;
4317         }
4318
4319 out:
4320         NFSEXITCODE(error);
4321         return (error);
4322 }
4323
4324 /*
4325  * Do a server callback.
4326  */
4327 static int
4328 nfsrv_docallback(struct nfsclient *clp, int procnum,
4329     nfsv4stateid_t *stateidp, int trunc, fhandle_t *fhp,
4330     struct nfsvattr *nap, nfsattrbit_t *attrbitp, NFSPROC_T *p)
4331 {
4332         mbuf_t m;
4333         u_int32_t *tl;
4334         struct nfsrv_descript nfsd, *nd = &nfsd;
4335         struct ucred *cred;
4336         int error = 0;
4337         u_int32_t callback;
4338         struct nfsdsession *sep = NULL;
4339
4340         cred = newnfs_getcred();
4341         NFSLOCKSTATE(); /* mostly for lc_cbref++ */
4342         if (clp->lc_flags & LCL_NEEDSCONFIRM) {
4343                 NFSUNLOCKSTATE();
4344                 panic("docallb");
4345         }
4346         clp->lc_cbref++;
4347
4348         /*
4349          * Fill the callback program# and version into the request
4350          * structure for newnfs_connect() to use.
4351          */
4352         clp->lc_req.nr_prog = clp->lc_program;
4353 #ifdef notnow
4354         if ((clp->lc_flags & LCL_NFSV41) != 0)
4355                 clp->lc_req.nr_vers = NFSV41_CBVERS;
4356         else
4357 #endif
4358                 clp->lc_req.nr_vers = NFSV4_CBVERS;
4359
4360         /*
4361          * First, fill in some of the fields of nd and cr.
4362          */
4363         nd->nd_flag = ND_NFSV4;
4364         if (clp->lc_flags & LCL_GSS)
4365                 nd->nd_flag |= ND_KERBV;
4366         if ((clp->lc_flags & LCL_NFSV41) != 0)
4367                 nd->nd_flag |= ND_NFSV41;
4368         nd->nd_repstat = 0;
4369         cred->cr_uid = clp->lc_uid;
4370         cred->cr_gid = clp->lc_gid;
4371         callback = clp->lc_callback;
4372         NFSUNLOCKSTATE();
4373         cred->cr_ngroups = 1;
4374
4375         /*
4376          * Get the first mbuf for the request.
4377          */
4378         MGET(m, M_WAITOK, MT_DATA);
4379         mbuf_setlen(m, 0);
4380         nd->nd_mreq = nd->nd_mb = m;
4381         nd->nd_bpos = NFSMTOD(m, caddr_t);
4382         
4383         /*
4384          * and build the callback request.
4385          */
4386         if (procnum == NFSV4OP_CBGETATTR) {
4387                 nd->nd_procnum = NFSV4PROC_CBCOMPOUND;
4388                 error = nfsrv_cbcallargs(nd, clp, callback, NFSV4OP_CBGETATTR,
4389                     "CB Getattr", &sep);
4390                 if (error != 0) {
4391                         mbuf_freem(nd->nd_mreq);
4392                         goto errout;
4393                 }
4394                 (void)nfsm_fhtom(nd, (u_int8_t *)fhp, NFSX_MYFH, 0);
4395                 (void)nfsrv_putattrbit(nd, attrbitp);
4396         } else if (procnum == NFSV4OP_CBRECALL) {
4397                 nd->nd_procnum = NFSV4PROC_CBCOMPOUND;
4398                 error = nfsrv_cbcallargs(nd, clp, callback, NFSV4OP_CBRECALL,
4399                     "CB Recall", &sep);
4400                 if (error != 0) {
4401                         mbuf_freem(nd->nd_mreq);
4402                         goto errout;
4403                 }
4404                 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED + NFSX_STATEID);
4405                 *tl++ = txdr_unsigned(stateidp->seqid);
4406                 NFSBCOPY((caddr_t)stateidp->other, (caddr_t)tl,
4407                     NFSX_STATEIDOTHER);
4408                 tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED);
4409                 if (trunc)
4410                         *tl = newnfs_true;
4411                 else
4412                         *tl = newnfs_false;
4413                 (void)nfsm_fhtom(nd, (u_int8_t *)fhp, NFSX_MYFH, 0);
4414         } else if (procnum == NFSV4PROC_CBNULL) {
4415                 nd->nd_procnum = NFSV4PROC_CBNULL;
4416                 if ((clp->lc_flags & LCL_NFSV41) != 0) {
4417                         error = nfsv4_getcbsession(clp, &sep);
4418                         if (error != 0) {
4419                                 mbuf_freem(nd->nd_mreq);
4420                                 goto errout;
4421                         }
4422                 }
4423         } else {
4424                 error = NFSERR_SERVERFAULT;
4425                 mbuf_freem(nd->nd_mreq);
4426                 goto errout;
4427         }
4428
4429         /*
4430          * Call newnfs_connect(), as required, and then newnfs_request().
4431          */
4432         (void) newnfs_sndlock(&clp->lc_req.nr_lock);
4433         if (clp->lc_req.nr_client == NULL) {
4434                 if ((clp->lc_flags & LCL_NFSV41) != 0) {
4435                         error = ECONNREFUSED;
4436                         nfsrv_freesession(sep, NULL);
4437                 } else if (nd->nd_procnum == NFSV4PROC_CBNULL)
4438                         error = newnfs_connect(NULL, &clp->lc_req, cred,
4439                             NULL, 1);
4440                 else
4441                         error = newnfs_connect(NULL, &clp->lc_req, cred,
4442                             NULL, 3);
4443         }
4444         newnfs_sndunlock(&clp->lc_req.nr_lock);
4445         if (!error) {
4446                 if ((nd->nd_flag & ND_NFSV41) != 0) {
4447                         KASSERT(sep != NULL, ("sep NULL"));
4448                         if (sep->sess_cbsess.nfsess_xprt != NULL)
4449                                 error = newnfs_request(nd, NULL, clp,
4450                                     &clp->lc_req, NULL, NULL, cred,
4451                                     clp->lc_program, clp->lc_req.nr_vers, NULL,
4452                                     1, NULL, &sep->sess_cbsess);
4453                         else {
4454                                 /*
4455                                  * This should probably never occur, but if a
4456                                  * client somehow does an RPC without a
4457                                  * SequenceID Op that causes a callback just
4458                                  * after the nfsd threads have been terminated
4459                                  * and restared we could conceivably get here
4460                                  * without a backchannel xprt.
4461                                  */
4462                                 printf("nfsrv_docallback: no xprt\n");
4463                                 error = ECONNREFUSED;
4464                         }
4465                         nfsrv_freesession(sep, NULL);
4466                 } else
4467                         error = newnfs_request(nd, NULL, clp, &clp->lc_req,
4468                             NULL, NULL, cred, clp->lc_program,
4469                             clp->lc_req.nr_vers, NULL, 1, NULL, NULL);
4470         }
4471 errout:
4472         NFSFREECRED(cred);
4473
4474         /*
4475          * If error is set here, the Callback path isn't working
4476          * properly, so twiddle the appropriate LCL_ flags.
4477          * (nd_repstat != 0 indicates the Callback path is working,
4478          *  but the callback failed on the client.)
4479          */
4480         if (error) {
4481                 /*
4482                  * Mark the callback pathway down, which disabled issuing
4483                  * of delegations and gets Renew to return NFSERR_CBPATHDOWN.
4484                  */
4485                 NFSLOCKSTATE();
4486                 clp->lc_flags |= LCL_CBDOWN;
4487                 NFSUNLOCKSTATE();
4488         } else {
4489                 /*
4490                  * Callback worked. If the callback path was down, disable
4491                  * callbacks, so no more delegations will be issued. (This
4492                  * is done on the assumption that the callback pathway is
4493                  * flakey.)
4494                  */
4495                 NFSLOCKSTATE();
4496                 if (clp->lc_flags & LCL_CBDOWN)
4497                         clp->lc_flags &= ~(LCL_CBDOWN | LCL_CALLBACKSON);
4498                 NFSUNLOCKSTATE();
4499                 if (nd->nd_repstat)
4500                         error = nd->nd_repstat;
4501                 else if (error == 0 && procnum == NFSV4OP_CBGETATTR)
4502                         error = nfsv4_loadattr(nd, NULL, nap, NULL, NULL, 0,
4503                             NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL,
4504                             p, NULL);
4505                 mbuf_freem(nd->nd_mrep);
4506         }
4507         NFSLOCKSTATE();
4508         clp->lc_cbref--;
4509         if ((clp->lc_flags & LCL_WAKEUPWANTED) && clp->lc_cbref == 0) {
4510                 clp->lc_flags &= ~LCL_WAKEUPWANTED;
4511                 wakeup(clp);
4512         }
4513         NFSUNLOCKSTATE();
4514
4515         NFSEXITCODE(error);
4516         return (error);
4517 }
4518
4519 /*
4520  * Set up the compound RPC for the callback.
4521  */
4522 static int
4523 nfsrv_cbcallargs(struct nfsrv_descript *nd, struct nfsclient *clp,
4524     uint32_t callback, int op, const char *optag, struct nfsdsession **sepp)
4525 {
4526         uint32_t *tl;
4527         int error, len;
4528
4529         len = strlen(optag);
4530         (void)nfsm_strtom(nd, optag, len);
4531         NFSM_BUILD(tl, uint32_t *, 4 * NFSX_UNSIGNED);
4532         if ((nd->nd_flag & ND_NFSV41) != 0) {
4533                 *tl++ = txdr_unsigned(NFSV41_MINORVERSION);
4534                 *tl++ = txdr_unsigned(callback);
4535                 *tl++ = txdr_unsigned(2);
4536                 *tl = txdr_unsigned(NFSV4OP_CBSEQUENCE);
4537                 error = nfsv4_setcbsequence(nd, clp, 1, sepp);
4538                 if (error != 0)
4539                         return (error);
4540                 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
4541                 *tl = txdr_unsigned(op);
4542         } else {
4543                 *tl++ = txdr_unsigned(NFSV4_MINORVERSION);
4544                 *tl++ = txdr_unsigned(callback);
4545                 *tl++ = txdr_unsigned(1);
4546                 *tl = txdr_unsigned(op);
4547         }
4548         return (0);
4549 }
4550
4551 /*
4552  * Return the next index# for a clientid. Mostly just increment and return
4553  * the next one, but... if the 32bit unsigned does actually wrap around,
4554  * it should be rebooted.
4555  * At an average rate of one new client per second, it will wrap around in
4556  * approximately 136 years. (I think the server will have been shut
4557  * down or rebooted before then.)
4558  */
4559 static u_int32_t
4560 nfsrv_nextclientindex(void)
4561 {
4562         static u_int32_t client_index = 0;
4563
4564         client_index++;
4565         if (client_index != 0)
4566                 return (client_index);
4567
4568         printf("%s: out of clientids\n", __func__);
4569         return (client_index);
4570 }
4571
4572 /*
4573  * Return the next index# for a stateid. Mostly just increment and return
4574  * the next one, but... if the 32bit unsigned does actually wrap around
4575  * (will a BSD server stay up that long?), find
4576  * new start and end values.
4577  */
4578 static u_int32_t
4579 nfsrv_nextstateindex(struct nfsclient *clp)
4580 {
4581         struct nfsstate *stp;
4582         int i;
4583         u_int32_t canuse, min_index, max_index;
4584
4585         if (!(clp->lc_flags & LCL_INDEXNOTOK)) {
4586                 clp->lc_stateindex++;
4587                 if (clp->lc_stateindex != clp->lc_statemaxindex)
4588                         return (clp->lc_stateindex);
4589         }
4590
4591         /*
4592          * Yuck, we've hit the end.
4593          * Look for a new min and max.
4594          */
4595         min_index = 0;
4596         max_index = 0xffffffff;
4597         for (i = 0; i < nfsrv_statehashsize; i++) {
4598             LIST_FOREACH(stp, &clp->lc_stateid[i], ls_hash) {
4599                 if (stp->ls_stateid.other[2] > 0x80000000) {
4600                     if (stp->ls_stateid.other[2] < max_index)
4601                         max_index = stp->ls_stateid.other[2];
4602                 } else {
4603                     if (stp->ls_stateid.other[2] > min_index)
4604                         min_index = stp->ls_stateid.other[2];
4605                 }
4606             }
4607         }
4608
4609         /*
4610          * Yikes, highly unlikely, but I'll handle it anyhow.
4611          */
4612         if (min_index == 0x80000000 && max_index == 0x80000001) {
4613             canuse = 0;
4614             /*
4615              * Loop around until we find an unused entry. Return that
4616              * and set LCL_INDEXNOTOK, so the search will continue next time.
4617              * (This is one of those rare cases where a goto is the
4618              *  cleanest way to code the loop.)
4619              */
4620 tryagain:
4621             for (i = 0; i < nfsrv_statehashsize; i++) {
4622                 LIST_FOREACH(stp, &clp->lc_stateid[i], ls_hash) {
4623                     if (stp->ls_stateid.other[2] == canuse) {
4624                         canuse++;
4625                         goto tryagain;
4626                     }
4627                 }
4628             }
4629             clp->lc_flags |= LCL_INDEXNOTOK;
4630             return (canuse);
4631         }
4632
4633         /*
4634          * Ok to start again from min + 1.
4635          */
4636         clp->lc_stateindex = min_index + 1;
4637         clp->lc_statemaxindex = max_index;
4638         clp->lc_flags &= ~LCL_INDEXNOTOK;
4639         return (clp->lc_stateindex);
4640 }
4641
4642 /*
4643  * The following functions handle the stable storage file that deals with
4644  * the edge conditions described in RFC3530 Sec. 8.6.3.
4645  * The file is as follows:
4646  * - a single record at the beginning that has the lease time of the
4647  *   previous server instance (before the last reboot) and the nfsrvboottime
4648  *   values for the previous server boots.
4649  *   These previous boot times are used to ensure that the current
4650  *   nfsrvboottime does not, somehow, get set to a previous one.
4651  *   (This is important so that Stale ClientIDs and StateIDs can
4652  *    be recognized.)
4653  *   The number of previous nfsvrboottime values preceeds the list.
4654  * - followed by some number of appended records with:
4655  *   - client id string
4656  *   - flag that indicates it is a record revoking state via lease
4657  *     expiration or similar
4658  *     OR has successfully acquired state.
4659  * These structures vary in length, with the client string at the end, up
4660  * to NFSV4_OPAQUELIMIT in size.
4661  *
4662  * At the end of the grace period, the file is truncated, the first
4663  * record is rewritten with updated information and any acquired state
4664  * records for successful reclaims of state are written.
4665  *
4666  * Subsequent records are appended when the first state is issued to
4667  * a client and when state is revoked for a client.
4668  *
4669  * When reading the file in, state issued records that come later in
4670  * the file override older ones, since the append log is in cronological order.
4671  * If, for some reason, the file can't be read, the grace period is
4672  * immediately terminated and all reclaims get NFSERR_NOGRACE.
4673  */
4674
4675 /*
4676  * Read in the stable storage file. Called by nfssvc() before the nfsd
4677  * processes start servicing requests.
4678  */
4679 APPLESTATIC void
4680 nfsrv_setupstable(NFSPROC_T *p)
4681 {
4682         struct nfsrv_stablefirst *sf = &nfsrv_stablefirst;
4683         struct nfsrv_stable *sp, *nsp;
4684         struct nfst_rec *tsp;
4685         int error, i, tryagain;
4686         off_t off = 0;
4687         ssize_t aresid, len;
4688
4689         /*
4690          * If NFSNSF_UPDATEDONE is set, this is a restart of the nfsds without
4691          * a reboot, so state has not been lost.
4692          */
4693         if (sf->nsf_flags & NFSNSF_UPDATEDONE)
4694                 return;
4695         /*
4696          * Set Grace over just until the file reads successfully.
4697          */
4698         nfsrvboottime = time_second;
4699         LIST_INIT(&sf->nsf_head);
4700         sf->nsf_flags = (NFSNSF_GRACEOVER | NFSNSF_NEEDLOCK);
4701         sf->nsf_eograce = NFSD_MONOSEC + NFSRV_LEASEDELTA;
4702         if (sf->nsf_fp == NULL)
4703                 return;
4704         error = NFSD_RDWR(UIO_READ, NFSFPVNODE(sf->nsf_fp),
4705             (caddr_t)&sf->nsf_rec, sizeof (struct nfsf_rec), off, UIO_SYSSPACE,
4706             0, NFSFPCRED(sf->nsf_fp), &aresid, p);
4707         if (error || aresid || sf->nsf_numboots == 0 ||
4708                 sf->nsf_numboots > NFSNSF_MAXNUMBOOTS)
4709                 return;
4710
4711         /*
4712          * Now, read in the boottimes.
4713          */
4714         sf->nsf_bootvals = (time_t *)malloc((sf->nsf_numboots + 1) *
4715                 sizeof (time_t), M_TEMP, M_WAITOK);
4716         off = sizeof (struct nfsf_rec);
4717         error = NFSD_RDWR(UIO_READ, NFSFPVNODE(sf->nsf_fp),
4718             (caddr_t)sf->nsf_bootvals, sf->nsf_numboots * sizeof (time_t), off,
4719             UIO_SYSSPACE, 0, NFSFPCRED(sf->nsf_fp), &aresid, p);
4720         if (error || aresid) {
4721                 free((caddr_t)sf->nsf_bootvals, M_TEMP);
4722                 sf->nsf_bootvals = NULL;
4723                 return;
4724         }
4725
4726         /*
4727          * Make sure this nfsrvboottime is different from all recorded
4728          * previous ones.
4729          */
4730         do {
4731                 tryagain = 0;
4732                 for (i = 0; i < sf->nsf_numboots; i++) {
4733                         if (nfsrvboottime == sf->nsf_bootvals[i]) {
4734                                 nfsrvboottime++;
4735                                 tryagain = 1;
4736                                 break;
4737                         }
4738                 }
4739         } while (tryagain);
4740
4741         sf->nsf_flags |= NFSNSF_OK;
4742         off += (sf->nsf_numboots * sizeof (time_t));
4743
4744         /*
4745          * Read through the file, building a list of records for grace
4746          * checking.
4747          * Each record is between sizeof (struct nfst_rec) and
4748          * sizeof (struct nfst_rec) + NFSV4_OPAQUELIMIT - 1
4749          * and is actually sizeof (struct nfst_rec) + nst_len - 1.
4750          */
4751         tsp = (struct nfst_rec *)malloc(sizeof (struct nfst_rec) +
4752                 NFSV4_OPAQUELIMIT - 1, M_TEMP, M_WAITOK);
4753         do {
4754             error = NFSD_RDWR(UIO_READ, NFSFPVNODE(sf->nsf_fp),
4755                 (caddr_t)tsp, sizeof (struct nfst_rec) + NFSV4_OPAQUELIMIT - 1,
4756                 off, UIO_SYSSPACE, 0, NFSFPCRED(sf->nsf_fp), &aresid, p);
4757             len = (sizeof (struct nfst_rec) + NFSV4_OPAQUELIMIT - 1) - aresid;
4758             if (error || (len > 0 && (len < sizeof (struct nfst_rec) ||
4759                 len < (sizeof (struct nfst_rec) + tsp->len - 1)))) {
4760                 /*
4761                  * Yuck, the file has been corrupted, so just return
4762                  * after clearing out any restart state, so the grace period
4763                  * is over.
4764                  */
4765                 LIST_FOREACH_SAFE(sp, &sf->nsf_head, nst_list, nsp) {
4766                         LIST_REMOVE(sp, nst_list);
4767                         free((caddr_t)sp, M_TEMP);
4768                 }
4769                 free((caddr_t)tsp, M_TEMP);
4770                 sf->nsf_flags &= ~NFSNSF_OK;
4771                 free((caddr_t)sf->nsf_bootvals, M_TEMP);
4772                 sf->nsf_bootvals = NULL;
4773                 return;
4774             }
4775             if (len > 0) {
4776                 off += sizeof (struct nfst_rec) + tsp->len - 1;
4777                 /*
4778                  * Search the list for a matching client.
4779                  */
4780                 LIST_FOREACH(sp, &sf->nsf_head, nst_list) {
4781                         if (tsp->len == sp->nst_len &&
4782                             !NFSBCMP(tsp->client, sp->nst_client, tsp->len))
4783                                 break;
4784                 }
4785                 if (sp == LIST_END(&sf->nsf_head)) {
4786                         sp = (struct nfsrv_stable *)malloc(tsp->len +
4787                                 sizeof (struct nfsrv_stable) - 1, M_TEMP,
4788                                 M_WAITOK);
4789                         NFSBCOPY((caddr_t)tsp, (caddr_t)&sp->nst_rec,
4790                                 sizeof (struct nfst_rec) + tsp->len - 1);
4791                         LIST_INSERT_HEAD(&sf->nsf_head, sp, nst_list);
4792                 } else {
4793                         if (tsp->flag == NFSNST_REVOKE)
4794                                 sp->nst_flag |= NFSNST_REVOKE;
4795                         else
4796                                 /*
4797                                  * A subsequent timestamp indicates the client
4798                                  * did a setclientid/confirm and any previous
4799                                  * revoke is no longer relevant.
4800                                  */
4801                                 sp->nst_flag &= ~NFSNST_REVOKE;
4802                 }
4803             }
4804         } while (len > 0);
4805         free((caddr_t)tsp, M_TEMP);
4806         sf->nsf_flags = NFSNSF_OK;
4807         sf->nsf_eograce = NFSD_MONOSEC + sf->nsf_lease +
4808                 NFSRV_LEASEDELTA;
4809 }
4810
4811 /*
4812  * Update the stable storage file, now that the grace period is over.
4813  */
4814 APPLESTATIC void
4815 nfsrv_updatestable(NFSPROC_T *p)
4816 {
4817         struct nfsrv_stablefirst *sf = &nfsrv_stablefirst;
4818         struct nfsrv_stable *sp, *nsp;
4819         int i;
4820         struct nfsvattr nva;
4821         vnode_t vp;
4822 #if defined(__FreeBSD_version) && (__FreeBSD_version >= 500000)
4823         mount_t mp = NULL;
4824 #endif
4825         int error;
4826
4827         if (sf->nsf_fp == NULL || (sf->nsf_flags & NFSNSF_UPDATEDONE))
4828                 return;
4829         sf->nsf_flags |= NFSNSF_UPDATEDONE;
4830         /*
4831          * Ok, we need to rewrite the stable storage file.
4832          * - truncate to 0 length
4833          * - write the new first structure
4834          * - loop through the data structures, writing out any that
4835          *   have timestamps older than the old boot
4836          */
4837         if (sf->nsf_bootvals) {
4838                 sf->nsf_numboots++;
4839                 for (i = sf->nsf_numboots - 2; i >= 0; i--)
4840                         sf->nsf_bootvals[i + 1] = sf->nsf_bootvals[i];
4841         } else {
4842                 sf->nsf_numboots = 1;
4843                 sf->nsf_bootvals = (time_t *)malloc(sizeof (time_t),
4844                         M_TEMP, M_WAITOK);
4845         }
4846         sf->nsf_bootvals[0] = nfsrvboottime;
4847         sf->nsf_lease = nfsrv_lease;
4848         NFSVNO_ATTRINIT(&nva);
4849         NFSVNO_SETATTRVAL(&nva, size, 0);
4850         vp = NFSFPVNODE(sf->nsf_fp);
4851         vn_start_write(vp, &mp, V_WAIT);
4852         if (NFSVOPLOCK(vp, LK_EXCLUSIVE) == 0) {
4853                 error = nfsvno_setattr(vp, &nva, NFSFPCRED(sf->nsf_fp), p,
4854                     NULL);
4855                 NFSVOPUNLOCK(vp, 0);
4856         } else
4857                 error = EPERM;
4858         vn_finished_write(mp);
4859         if (!error)
4860             error = NFSD_RDWR(UIO_WRITE, vp,
4861                 (caddr_t)&sf->nsf_rec, sizeof (struct nfsf_rec), (off_t)0,
4862                 UIO_SYSSPACE, IO_SYNC, NFSFPCRED(sf->nsf_fp), NULL, p);
4863         if (!error)
4864             error = NFSD_RDWR(UIO_WRITE, vp,
4865                 (caddr_t)sf->nsf_bootvals,
4866                 sf->nsf_numboots * sizeof (time_t),
4867                 (off_t)(sizeof (struct nfsf_rec)),
4868                 UIO_SYSSPACE, IO_SYNC, NFSFPCRED(sf->nsf_fp), NULL, p);
4869         free((caddr_t)sf->nsf_bootvals, M_TEMP);
4870         sf->nsf_bootvals = NULL;
4871         if (error) {
4872                 sf->nsf_flags &= ~NFSNSF_OK;
4873                 printf("EEK! Can't write NfsV4 stable storage file\n");
4874                 return;
4875         }
4876         sf->nsf_flags |= NFSNSF_OK;
4877
4878         /*
4879          * Loop through the list and write out timestamp records for
4880          * any clients that successfully reclaimed state.
4881          */
4882         LIST_FOREACH_SAFE(sp, &sf->nsf_head, nst_list, nsp) {
4883                 if (sp->nst_flag & NFSNST_GOTSTATE) {
4884                         nfsrv_writestable(sp->nst_client, sp->nst_len,
4885                                 NFSNST_NEWSTATE, p);
4886                         sp->nst_clp->lc_flags |= LCL_STAMPEDSTABLE;
4887                 }
4888                 LIST_REMOVE(sp, nst_list);
4889                 free((caddr_t)sp, M_TEMP);
4890         }
4891         nfsrv_backupstable();
4892 }
4893
4894 /*
4895  * Append a record to the stable storage file.
4896  */
4897 APPLESTATIC void
4898 nfsrv_writestable(u_char *client, int len, int flag, NFSPROC_T *p)
4899 {
4900         struct nfsrv_stablefirst *sf = &nfsrv_stablefirst;
4901         struct nfst_rec *sp;
4902         int error;
4903
4904         if (!(sf->nsf_flags & NFSNSF_OK) || sf->nsf_fp == NULL)
4905                 return;
4906         sp = (struct nfst_rec *)malloc(sizeof (struct nfst_rec) +
4907                 len - 1, M_TEMP, M_WAITOK);
4908         sp->len = len;
4909         NFSBCOPY(client, sp->client, len);
4910         sp->flag = flag;
4911         error = NFSD_RDWR(UIO_WRITE, NFSFPVNODE(sf->nsf_fp),
4912             (caddr_t)sp, sizeof (struct nfst_rec) + len - 1, (off_t)0,
4913             UIO_SYSSPACE, (IO_SYNC | IO_APPEND), NFSFPCRED(sf->nsf_fp), NULL, p);
4914         free((caddr_t)sp, M_TEMP);
4915         if (error) {
4916                 sf->nsf_flags &= ~NFSNSF_OK;
4917                 printf("EEK! Can't write NfsV4 stable storage file\n");
4918         }
4919 }
4920
4921 /*
4922  * This function is called during the grace period to mark a client
4923  * that successfully reclaimed state.
4924  */
4925 static void
4926 nfsrv_markstable(struct nfsclient *clp)
4927 {
4928         struct nfsrv_stable *sp;
4929
4930         /*
4931          * First find the client structure.
4932          */
4933         LIST_FOREACH(sp, &nfsrv_stablefirst.nsf_head, nst_list) {
4934                 if (sp->nst_len == clp->lc_idlen &&
4935                     !NFSBCMP(sp->nst_client, clp->lc_id, sp->nst_len))
4936                         break;
4937         }
4938         if (sp == LIST_END(&nfsrv_stablefirst.nsf_head))
4939                 return;
4940
4941         /*
4942          * Now, just mark it and set the nfsclient back pointer.
4943          */
4944         sp->nst_flag |= NFSNST_GOTSTATE;
4945         sp->nst_clp = clp;
4946 }
4947
4948 /*
4949  * This function is called when a NFSv4.1 client does a ReclaimComplete.
4950  * Very similar to nfsrv_markstable(), except for the flag being set.
4951  */
4952 static void
4953 nfsrv_markreclaim(struct nfsclient *clp)
4954 {
4955         struct nfsrv_stable *sp;
4956
4957         /*
4958          * First find the client structure.
4959          */
4960         LIST_FOREACH(sp, &nfsrv_stablefirst.nsf_head, nst_list) {
4961                 if (sp->nst_len == clp->lc_idlen &&
4962                     !NFSBCMP(sp->nst_client, clp->lc_id, sp->nst_len))
4963                         break;
4964         }
4965         if (sp == LIST_END(&nfsrv_stablefirst.nsf_head))
4966                 return;
4967
4968         /*
4969          * Now, just set the flag.
4970          */
4971         sp->nst_flag |= NFSNST_RECLAIMED;
4972 }
4973
4974 /*
4975  * This function is called for a reclaim, to see if it gets grace.
4976  * It returns 0 if a reclaim is allowed, 1 otherwise.
4977  */
4978 static int
4979 nfsrv_checkstable(struct nfsclient *clp)
4980 {
4981         struct nfsrv_stable *sp;
4982
4983         /*
4984          * First, find the entry for the client.
4985          */
4986         LIST_FOREACH(sp, &nfsrv_stablefirst.nsf_head, nst_list) {
4987                 if (sp->nst_len == clp->lc_idlen &&
4988                     !NFSBCMP(sp->nst_client, clp->lc_id, sp->nst_len))
4989                         break;
4990         }
4991
4992         /*
4993          * If not in the list, state was revoked or no state was issued
4994          * since the previous reboot, a reclaim is denied.
4995          */
4996         if (sp == LIST_END(&nfsrv_stablefirst.nsf_head) ||
4997             (sp->nst_flag & NFSNST_REVOKE) ||
4998             !(nfsrv_stablefirst.nsf_flags & NFSNSF_OK))
4999                 return (1);
5000         return (0);
5001 }
5002
5003 /*
5004  * Test for and try to clear out a conflicting client. This is called by
5005  * nfsrv_lockctrl() and nfsrv_openctrl() when conflicts with other clients
5006  * a found.
5007  * The trick here is that it can't revoke a conflicting client with an
5008  * expired lease unless it holds the v4root lock, so...
5009  * If no v4root lock, get the lock and return 1 to indicate "try again".
5010  * Return 0 to indicate the conflict can't be revoked and 1 to indicate
5011  * the revocation worked and the conflicting client is "bye, bye", so it
5012  * can be tried again.
5013  * Return 2 to indicate that the vnode is VI_DOOMED after NFSVOPLOCK().
5014  * Unlocks State before a non-zero value is returned.
5015  */
5016 static int
5017 nfsrv_clientconflict(struct nfsclient *clp, int *haslockp, vnode_t vp,
5018     NFSPROC_T *p)
5019 {
5020         int gotlock, lktype = 0;
5021
5022         /*
5023          * If lease hasn't expired, we can't fix it.
5024          */
5025         if (clp->lc_expiry >= NFSD_MONOSEC ||
5026             !(nfsrv_stablefirst.nsf_flags & NFSNSF_UPDATEDONE))
5027                 return (0);
5028         if (*haslockp == 0) {
5029                 NFSUNLOCKSTATE();
5030                 if (vp != NULL) {
5031                         lktype = NFSVOPISLOCKED(vp);
5032                         NFSVOPUNLOCK(vp, 0);
5033                 }
5034                 NFSLOCKV4ROOTMUTEX();
5035                 nfsv4_relref(&nfsv4rootfs_lock);
5036                 do {
5037                         gotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL,
5038                             NFSV4ROOTLOCKMUTEXPTR, NULL);
5039                 } while (!gotlock);
5040                 NFSUNLOCKV4ROOTMUTEX();
5041                 *haslockp = 1;
5042                 if (vp != NULL) {
5043                         NFSVOPLOCK(vp, lktype | LK_RETRY);
5044                         if ((vp->v_iflag & VI_DOOMED) != 0)
5045                                 return (2);
5046                 }
5047                 return (1);
5048         }
5049         NFSUNLOCKSTATE();
5050
5051         /*
5052          * Ok, we can expire the conflicting client.
5053          */
5054         nfsrv_writestable(clp->lc_id, clp->lc_idlen, NFSNST_REVOKE, p);
5055         nfsrv_backupstable();
5056         nfsrv_cleanclient(clp, p);
5057         nfsrv_freedeleglist(&clp->lc_deleg);
5058         nfsrv_freedeleglist(&clp->lc_olddeleg);
5059         LIST_REMOVE(clp, lc_hash);
5060         nfsrv_zapclient(clp, p);
5061         return (1);
5062 }
5063
5064 /*
5065  * Resolve a delegation conflict.
5066  * Returns 0 to indicate the conflict was resolved without sleeping.
5067  * Return -1 to indicate that the caller should check for conflicts again.
5068  * Return > 0 for an error that should be returned, normally NFSERR_DELAY.
5069  *
5070  * Also, manipulate the nfsv4root_lock, as required. It isn't changed
5071  * for a return of 0, since there was no sleep and it could be required
5072  * later. It is released for a return of NFSERR_DELAY, since the caller
5073  * will return that error. It is released when a sleep was done waiting
5074  * for the delegation to be returned or expire (so that other nfsds can
5075  * handle ops). Then, it must be acquired for the write to stable storage.
5076  * (This function is somewhat similar to nfsrv_clientconflict(), but
5077  *  the semantics differ in a couple of subtle ways. The return of 0
5078  *  indicates the conflict was resolved without sleeping here, not
5079  *  that the conflict can't be resolved and the handling of nfsv4root_lock
5080  *  differs, as noted above.)
5081  * Unlocks State before returning a non-zero value.
5082  */
5083 static int
5084 nfsrv_delegconflict(struct nfsstate *stp, int *haslockp, NFSPROC_T *p,
5085     vnode_t vp)
5086 {
5087         struct nfsclient *clp = stp->ls_clp;
5088         int gotlock, error, lktype = 0, retrycnt, zapped_clp;
5089         nfsv4stateid_t tstateid;
5090         fhandle_t tfh;
5091
5092         /*
5093          * If the conflict is with an old delegation...
5094          */
5095         if (stp->ls_flags & NFSLCK_OLDDELEG) {
5096                 /*
5097                  * You can delete it, if it has expired.
5098                  */
5099                 if (clp->lc_delegtime < NFSD_MONOSEC) {
5100                         nfsrv_freedeleg(stp);
5101                         NFSUNLOCKSTATE();
5102                         error = -1;
5103                         goto out;
5104                 }
5105                 NFSUNLOCKSTATE();
5106                 /*
5107                  * During this delay, the old delegation could expire or it
5108                  * could be recovered by the client via an Open with
5109                  * CLAIM_DELEGATE_PREV.
5110                  * Release the nfsv4root_lock, if held.
5111                  */
5112                 if (*haslockp) {
5113                         *haslockp = 0;
5114                         NFSLOCKV4ROOTMUTEX();
5115                         nfsv4_unlock(&nfsv4rootfs_lock, 1);
5116                         NFSUNLOCKV4ROOTMUTEX();
5117                 }
5118                 error = NFSERR_DELAY;
5119                 goto out;
5120         }
5121
5122         /*
5123          * It's a current delegation, so:
5124          * - check to see if the delegation has expired
5125          *   - if so, get the v4root lock and then expire it
5126          */
5127         if (!(stp->ls_flags & NFSLCK_DELEGRECALL)) {
5128                 /*
5129                  * - do a recall callback, since not yet done
5130                  * For now, never allow truncate to be set. To use
5131                  * truncate safely, it must be guaranteed that the
5132                  * Remove, Rename or Setattr with size of 0 will
5133                  * succeed and that would require major changes to
5134                  * the VFS/Vnode OPs.
5135                  * Set the expiry time large enough so that it won't expire
5136                  * until after the callback, then set it correctly, once
5137                  * the callback is done. (The delegation will now time
5138                  * out whether or not the Recall worked ok. The timeout
5139                  * will be extended when ops are done on the delegation
5140                  * stateid, up to the timelimit.)
5141                  */
5142                 stp->ls_delegtime = NFSD_MONOSEC + (2 * nfsrv_lease) +
5143                     NFSRV_LEASEDELTA;
5144                 stp->ls_delegtimelimit = NFSD_MONOSEC + (6 * nfsrv_lease) +
5145                     NFSRV_LEASEDELTA;
5146                 stp->ls_flags |= NFSLCK_DELEGRECALL;
5147
5148                 /*
5149                  * Loop NFSRV_CBRETRYCNT times while the CBRecall replies
5150                  * NFSERR_BADSTATEID or NFSERR_BADHANDLE. This is done
5151                  * in order to try and avoid a race that could happen
5152                  * when a CBRecall request passed the Open reply with
5153                  * the delegation in it when transitting the network.
5154                  * Since nfsrv_docallback will sleep, don't use stp after
5155                  * the call.
5156                  */
5157                 NFSBCOPY((caddr_t)&stp->ls_stateid, (caddr_t)&tstateid,
5158                     sizeof (tstateid));
5159                 NFSBCOPY((caddr_t)&stp->ls_lfp->lf_fh, (caddr_t)&tfh,
5160                     sizeof (tfh));
5161                 NFSUNLOCKSTATE();
5162                 if (*haslockp) {
5163                         *haslockp = 0;
5164                         NFSLOCKV4ROOTMUTEX();
5165                         nfsv4_unlock(&nfsv4rootfs_lock, 1);
5166                         NFSUNLOCKV4ROOTMUTEX();
5167                 }
5168                 retrycnt = 0;
5169                 do {
5170                     error = nfsrv_docallback(clp, NFSV4OP_CBRECALL,
5171                         &tstateid, 0, &tfh, NULL, NULL, p);
5172                     retrycnt++;
5173                 } while ((error == NFSERR_BADSTATEID ||
5174                     error == NFSERR_BADHANDLE) && retrycnt < NFSV4_CBRETRYCNT);
5175                 error = NFSERR_DELAY;
5176                 goto out;
5177         }
5178
5179         if (clp->lc_expiry >= NFSD_MONOSEC &&
5180             stp->ls_delegtime >= NFSD_MONOSEC) {
5181                 NFSUNLOCKSTATE();
5182                 /*
5183                  * A recall has been done, but it has not yet expired.
5184                  * So, RETURN_DELAY.
5185                  */
5186                 if (*haslockp) {
5187                         *haslockp = 0;
5188                         NFSLOCKV4ROOTMUTEX();
5189                         nfsv4_unlock(&nfsv4rootfs_lock, 1);
5190                         NFSUNLOCKV4ROOTMUTEX();
5191                 }
5192                 error = NFSERR_DELAY;
5193                 goto out;
5194         }
5195
5196         /*
5197          * If we don't yet have the lock, just get it and then return,
5198          * since we need that before deleting expired state, such as
5199          * this delegation.
5200          * When getting the lock, unlock the vnode, so other nfsds that
5201          * are in progress, won't get stuck waiting for the vnode lock.
5202          */
5203         if (*haslockp == 0) {
5204                 NFSUNLOCKSTATE();
5205                 if (vp != NULL) {
5206                         lktype = NFSVOPISLOCKED(vp);
5207                         NFSVOPUNLOCK(vp, 0);
5208                 }
5209                 NFSLOCKV4ROOTMUTEX();
5210                 nfsv4_relref(&nfsv4rootfs_lock);
5211                 do {
5212                         gotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL,
5213                             NFSV4ROOTLOCKMUTEXPTR, NULL);
5214                 } while (!gotlock);
5215                 NFSUNLOCKV4ROOTMUTEX();
5216                 *haslockp = 1;
5217                 if (vp != NULL) {
5218                         NFSVOPLOCK(vp, lktype | LK_RETRY);
5219                         if ((vp->v_iflag & VI_DOOMED) != 0) {
5220                                 *haslockp = 0;
5221                                 NFSLOCKV4ROOTMUTEX();
5222                                 nfsv4_unlock(&nfsv4rootfs_lock, 1);
5223                                 NFSUNLOCKV4ROOTMUTEX();
5224                                 error = NFSERR_PERM;
5225                                 goto out;
5226                         }
5227                 }
5228                 error = -1;
5229                 goto out;
5230         }
5231
5232         NFSUNLOCKSTATE();
5233         /*
5234          * Ok, we can delete the expired delegation.
5235          * First, write the Revoke record to stable storage and then
5236          * clear out the conflict.
5237          * Since all other nfsd threads are now blocked, we can safely
5238          * sleep without the state changing.
5239          */
5240         nfsrv_writestable(clp->lc_id, clp->lc_idlen, NFSNST_REVOKE, p);
5241         nfsrv_backupstable();
5242         if (clp->lc_expiry < NFSD_MONOSEC) {
5243                 nfsrv_cleanclient(clp, p);
5244                 nfsrv_freedeleglist(&clp->lc_deleg);
5245                 nfsrv_freedeleglist(&clp->lc_olddeleg);
5246                 LIST_REMOVE(clp, lc_hash);
5247                 zapped_clp = 1;
5248         } else {
5249                 nfsrv_freedeleg(stp);
5250                 zapped_clp = 0;
5251         }
5252         if (zapped_clp)
5253                 nfsrv_zapclient(clp, p);
5254         error = -1;
5255
5256 out:
5257         NFSEXITCODE(error);
5258         return (error);
5259 }
5260
5261 /*
5262  * Check for a remove allowed, if remove is set to 1 and get rid of
5263  * delegations.
5264  */
5265 APPLESTATIC int
5266 nfsrv_checkremove(vnode_t vp, int remove, NFSPROC_T *p)
5267 {
5268         struct nfsstate *stp;
5269         struct nfslockfile *lfp;
5270         int error, haslock = 0;
5271         fhandle_t nfh;
5272
5273         /*
5274          * First, get the lock file structure.
5275          * (A return of -1 means no associated state, so remove ok.)
5276          */
5277         error = nfsrv_getlockfh(vp, NFSLCK_CHECK, NULL, &nfh, p);
5278 tryagain:
5279         NFSLOCKSTATE();
5280         if (!error)
5281                 error = nfsrv_getlockfile(NFSLCK_CHECK, NULL, &lfp, &nfh, 0);
5282         if (error) {
5283                 NFSUNLOCKSTATE();
5284                 if (haslock) {
5285                         NFSLOCKV4ROOTMUTEX();
5286                         nfsv4_unlock(&nfsv4rootfs_lock, 1);
5287                         NFSUNLOCKV4ROOTMUTEX();
5288                 }
5289                 if (error == -1)
5290                         error = 0;
5291                 goto out;
5292         }
5293
5294         /*
5295          * Now, we must Recall any delegations.
5296          */
5297         error = nfsrv_cleandeleg(vp, lfp, NULL, &haslock, p);
5298         if (error) {
5299                 /*
5300                  * nfsrv_cleandeleg() unlocks state for non-zero
5301                  * return.
5302                  */
5303                 if (error == -1)
5304                         goto tryagain;
5305                 if (haslock) {
5306                         NFSLOCKV4ROOTMUTEX();
5307                         nfsv4_unlock(&nfsv4rootfs_lock, 1);
5308                         NFSUNLOCKV4ROOTMUTEX();
5309                 }
5310                 goto out;
5311         }
5312
5313         /*
5314          * Now, look for a conflicting open share.
5315          */
5316         if (remove) {
5317                 LIST_FOREACH(stp, &lfp->lf_open, ls_file) {
5318                         if (stp->ls_flags & NFSLCK_WRITEDENY) {
5319                                 error = NFSERR_FILEOPEN;
5320                                 break;
5321                         }
5322                 }
5323         }
5324
5325         NFSUNLOCKSTATE();
5326         if (haslock) {
5327                 NFSLOCKV4ROOTMUTEX();
5328                 nfsv4_unlock(&nfsv4rootfs_lock, 1);
5329                 NFSUNLOCKV4ROOTMUTEX();
5330         }
5331
5332 out:
5333         NFSEXITCODE(error);
5334         return (error);
5335 }
5336
5337 /*
5338  * Clear out all delegations for the file referred to by lfp.
5339  * May return NFSERR_DELAY, if there will be a delay waiting for
5340  * delegations to expire.
5341  * Returns -1 to indicate it slept while recalling a delegation.
5342  * This function has the side effect of deleting the nfslockfile structure,
5343  * if it no longer has associated state and didn't have to sleep.
5344  * Unlocks State before a non-zero value is returned.
5345  */
5346 static int
5347 nfsrv_cleandeleg(vnode_t vp, struct nfslockfile *lfp,
5348     struct nfsclient *clp, int *haslockp, NFSPROC_T *p)
5349 {
5350         struct nfsstate *stp, *nstp;
5351         int ret = 0;
5352
5353         stp = LIST_FIRST(&lfp->lf_deleg);
5354         while (stp != LIST_END(&lfp->lf_deleg)) {
5355                 nstp = LIST_NEXT(stp, ls_file);
5356                 if (stp->ls_clp != clp) {
5357                         ret = nfsrv_delegconflict(stp, haslockp, p, vp);
5358                         if (ret) {
5359                                 /*
5360                                  * nfsrv_delegconflict() unlocks state
5361                                  * when it returns non-zero.
5362                                  */
5363                                 goto out;
5364                         }
5365                 }
5366                 stp = nstp;
5367         }
5368 out:
5369         NFSEXITCODE(ret);
5370         return (ret);
5371 }
5372
5373 /*
5374  * There are certain operations that, when being done outside of NFSv4,
5375  * require that any NFSv4 delegation for the file be recalled.
5376  * This function is to be called for those cases:
5377  * VOP_RENAME() - When a delegation is being recalled for any reason,
5378  *      the client may have to do Opens against the server, using the file's
5379  *      final component name. If the file has been renamed on the server,
5380  *      that component name will be incorrect and the Open will fail.
5381  * VOP_REMOVE() - Theoretically, a client could Open a file after it has
5382  *      been removed on the server, if there is a delegation issued to
5383  *      that client for the file. I say "theoretically" since clients
5384  *      normally do an Access Op before the Open and that Access Op will
5385  *      fail with ESTALE. Note that NFSv2 and 3 don't even do Opens, so
5386  *      they will detect the file's removal in the same manner. (There is
5387  *      one case where RFC3530 allows a client to do an Open without first
5388  *      doing an Access Op, which is passage of a check against the ACE
5389  *      returned with a Write delegation, but current practice is to ignore
5390  *      the ACE and always do an Access Op.)
5391  *      Since the functions can only be called with an unlocked vnode, this
5392  *      can't be done at this time.
5393  * VOP_ADVLOCK() - When a client holds a delegation, it can issue byte range
5394  *      locks locally in the client, which are not visible to the server. To
5395  *      deal with this, issuing of delegations for a vnode must be disabled
5396  *      and all delegations for the vnode recalled. This is done via the
5397  *      second function, using the VV_DISABLEDELEG vflag on the vnode.
5398  */
5399 APPLESTATIC void
5400 nfsd_recalldelegation(vnode_t vp, NFSPROC_T *p)
5401 {
5402         time_t starttime;
5403         int error;
5404
5405         /*
5406          * First, check to see if the server is currently running and it has
5407          * been called for a regular file when issuing delegations.
5408          */
5409         if (newnfs_numnfsd == 0 || vp->v_type != VREG ||
5410             nfsrv_issuedelegs == 0)
5411                 return;
5412
5413         KASSERT((NFSVOPISLOCKED(vp) != LK_EXCLUSIVE), ("vp %p is locked", vp));
5414         /*
5415          * First, get a reference on the nfsv4rootfs_lock so that an
5416          * exclusive lock cannot be acquired by another thread.
5417          */
5418         NFSLOCKV4ROOTMUTEX();
5419         nfsv4_getref(&nfsv4rootfs_lock, NULL, NFSV4ROOTLOCKMUTEXPTR, NULL);
5420         NFSUNLOCKV4ROOTMUTEX();
5421
5422         /*
5423          * Now, call nfsrv_checkremove() in a loop while it returns
5424          * NFSERR_DELAY. Return upon any other error or when timed out.
5425          */
5426         starttime = NFSD_MONOSEC;
5427         do {
5428                 if (NFSVOPLOCK(vp, LK_EXCLUSIVE) == 0) {
5429                         error = nfsrv_checkremove(vp, 0, p);
5430                         NFSVOPUNLOCK(vp, 0);
5431                 } else
5432                         error = EPERM;
5433                 if (error == NFSERR_DELAY) {
5434                         if (NFSD_MONOSEC - starttime > NFS_REMOVETIMEO)
5435                                 break;
5436                         /* Sleep for a short period of time */
5437                         (void) nfs_catnap(PZERO, 0, "nfsremove");
5438                 }
5439         } while (error == NFSERR_DELAY);
5440         NFSLOCKV4ROOTMUTEX();
5441         nfsv4_relref(&nfsv4rootfs_lock);
5442         NFSUNLOCKV4ROOTMUTEX();
5443 }
5444
5445 APPLESTATIC void
5446 nfsd_disabledelegation(vnode_t vp, NFSPROC_T *p)
5447 {
5448
5449 #ifdef VV_DISABLEDELEG
5450         /*
5451          * First, flag issuance of delegations disabled.
5452          */
5453         atomic_set_long(&vp->v_vflag, VV_DISABLEDELEG);
5454 #endif
5455
5456         /*
5457          * Then call nfsd_recalldelegation() to get rid of all extant
5458          * delegations.
5459          */
5460         nfsd_recalldelegation(vp, p);
5461 }
5462
5463 /*
5464  * Check for conflicting locks, etc. and then get rid of delegations.
5465  * (At one point I thought that I should get rid of delegations for any
5466  *  Setattr, since it could potentially disallow the I/O op (read or write)
5467  *  allowed by the delegation. However, Setattr Ops that aren't changing
5468  *  the size get a stateid of all 0s, so you can't tell if it is a delegation
5469  *  for the same client or a different one, so I decided to only get rid
5470  *  of delegations for other clients when the size is being changed.)
5471  * In general, a Setattr can disable NFS I/O Ops that are outstanding, such
5472  * as Write backs, even if there is no delegation, so it really isn't any
5473  * different?)
5474  */
5475 APPLESTATIC int
5476 nfsrv_checksetattr(vnode_t vp, struct nfsrv_descript *nd,
5477     nfsv4stateid_t *stateidp, struct nfsvattr *nvap, nfsattrbit_t *attrbitp,
5478     struct nfsexstuff *exp, NFSPROC_T *p)
5479 {
5480         struct nfsstate st, *stp = &st;
5481         struct nfslock lo, *lop = &lo;
5482         int error = 0;
5483         nfsquad_t clientid;
5484
5485         if (NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_SIZE)) {
5486                 stp->ls_flags = (NFSLCK_CHECK | NFSLCK_WRITEACCESS);
5487                 lop->lo_first = nvap->na_size;
5488         } else {
5489                 stp->ls_flags = 0;
5490                 lop->lo_first = 0;
5491         }
5492         if (NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_OWNER) ||
5493             NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_OWNERGROUP) ||
5494             NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_MODE) ||
5495             NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_ACL))
5496                 stp->ls_flags |= NFSLCK_SETATTR;
5497         if (stp->ls_flags == 0)
5498                 goto out;
5499         lop->lo_end = NFS64BITSSET;
5500         lop->lo_flags = NFSLCK_WRITE;
5501         stp->ls_ownerlen = 0;
5502         stp->ls_op = NULL;
5503         stp->ls_uid = nd->nd_cred->cr_uid;
5504         stp->ls_stateid.seqid = stateidp->seqid;
5505         clientid.lval[0] = stp->ls_stateid.other[0] = stateidp->other[0];
5506         clientid.lval[1] = stp->ls_stateid.other[1] = stateidp->other[1];
5507         stp->ls_stateid.other[2] = stateidp->other[2];
5508         error = nfsrv_lockctrl(vp, &stp, &lop, NULL, clientid,
5509             stateidp, exp, nd, p);
5510
5511 out:
5512         NFSEXITCODE2(error, nd);
5513         return (error);
5514 }
5515
5516 /*
5517  * Check for a write delegation and do a CBGETATTR if there is one, updating
5518  * the attributes, as required.
5519  * Should I return an error if I can't get the attributes? (For now, I'll
5520  * just return ok.
5521  */
5522 APPLESTATIC int
5523 nfsrv_checkgetattr(struct nfsrv_descript *nd, vnode_t vp,
5524     struct nfsvattr *nvap, nfsattrbit_t *attrbitp, struct ucred *cred,
5525     NFSPROC_T *p)
5526 {
5527         struct nfsstate *stp;
5528         struct nfslockfile *lfp;
5529         struct nfsclient *clp;
5530         struct nfsvattr nva;
5531         fhandle_t nfh;
5532         int error = 0;
5533         nfsattrbit_t cbbits;
5534         u_quad_t delegfilerev;
5535
5536         NFSCBGETATTR_ATTRBIT(attrbitp, &cbbits);
5537         if (!NFSNONZERO_ATTRBIT(&cbbits))
5538                 goto out;
5539         if (nfsrv_writedelegcnt == 0)
5540                 goto out;
5541
5542         /*
5543          * Get the lock file structure.
5544          * (A return of -1 means no associated state, so return ok.)
5545          */
5546         error = nfsrv_getlockfh(vp, NFSLCK_CHECK, NULL, &nfh, p);
5547         NFSLOCKSTATE();
5548         if (!error)
5549                 error = nfsrv_getlockfile(NFSLCK_CHECK, NULL, &lfp, &nfh, 0);
5550         if (error) {
5551                 NFSUNLOCKSTATE();
5552                 if (error == -1)
5553                         error = 0;
5554                 goto out;
5555         }
5556
5557         /*
5558          * Now, look for a write delegation.
5559          */
5560         LIST_FOREACH(stp, &lfp->lf_deleg, ls_file) {
5561                 if (stp->ls_flags & NFSLCK_DELEGWRITE)
5562                         break;
5563         }
5564         if (stp == LIST_END(&lfp->lf_deleg)) {
5565                 NFSUNLOCKSTATE();
5566                 goto out;
5567         }
5568         clp = stp->ls_clp;
5569         delegfilerev = stp->ls_filerev;
5570
5571         /*
5572          * If the Write delegation was issued as a part of this Compound RPC
5573          * or if we have an Implied Clientid (used in a previous Op in this
5574          * compound) and it is the client the delegation was issued to,
5575          * just return ok.
5576          * I also assume that it is from the same client iff the network
5577          * host IP address is the same as the callback address. (Not
5578          * exactly correct by the RFC, but avoids a lot of Getattr
5579          * callbacks.)
5580          */
5581         if (nd->nd_compref == stp->ls_compref ||
5582             ((nd->nd_flag & ND_IMPLIEDCLID) &&
5583              clp->lc_clientid.qval == nd->nd_clientid.qval) ||
5584              nfsaddr2_match(clp->lc_req.nr_nam, nd->nd_nam)) {
5585                 NFSUNLOCKSTATE();
5586                 goto out;
5587         }
5588
5589         /*
5590          * We are now done with the delegation state structure,
5591          * so the statelock can be released and we can now tsleep().
5592          */
5593
5594         /*
5595          * Now, we must do the CB Getattr callback, to see if Change or Size
5596          * has changed.
5597          */
5598         if (clp->lc_expiry >= NFSD_MONOSEC) {
5599                 NFSUNLOCKSTATE();
5600                 NFSVNO_ATTRINIT(&nva);
5601                 nva.na_filerev = NFS64BITSSET;
5602                 error = nfsrv_docallback(clp, NFSV4OP_CBGETATTR, NULL,
5603                     0, &nfh, &nva, &cbbits, p);
5604                 if (!error) {
5605                         if ((nva.na_filerev != NFS64BITSSET &&
5606                             nva.na_filerev > delegfilerev) ||
5607                             (NFSVNO_ISSETSIZE(&nva) &&
5608                              nva.na_size != nvap->na_size)) {
5609                                 error = nfsvno_updfilerev(vp, nvap, cred, p);
5610                                 if (NFSVNO_ISSETSIZE(&nva))
5611                                         nvap->na_size = nva.na_size;
5612                         }
5613                 } else
5614                         error = 0;      /* Ignore callback errors for now. */
5615         } else {
5616                 NFSUNLOCKSTATE();
5617         }
5618
5619 out:
5620         NFSEXITCODE2(error, nd);
5621         return (error);
5622 }
5623
5624 /*
5625  * This function looks for openowners that haven't had any opens for
5626  * a while and throws them away. Called by an nfsd when NFSNSF_NOOPENS
5627  * is set.
5628  */
5629 APPLESTATIC void
5630 nfsrv_throwawayopens(NFSPROC_T *p)
5631 {
5632         struct nfsclient *clp, *nclp;
5633         struct nfsstate *stp, *nstp;
5634         int i;
5635
5636         NFSLOCKSTATE();
5637         nfsrv_stablefirst.nsf_flags &= ~NFSNSF_NOOPENS;
5638         /*
5639          * For each client...
5640          */
5641         for (i = 0; i < nfsrv_clienthashsize; i++) {
5642             LIST_FOREACH_SAFE(clp, &nfsclienthash[i], lc_hash, nclp) {
5643                 LIST_FOREACH_SAFE(stp, &clp->lc_open, ls_list, nstp) {
5644                         if (LIST_EMPTY(&stp->ls_open) &&
5645                             (stp->ls_noopens > NFSNOOPEN ||
5646                              (nfsrv_openpluslock * 2) >
5647                              nfsrv_v4statelimit))
5648                                 nfsrv_freeopenowner(stp, 0, p);
5649                 }
5650             }
5651         }
5652         NFSUNLOCKSTATE();
5653 }
5654
5655 /*
5656  * This function checks to see if the credentials are the same.
5657  * Returns 1 for not same, 0 otherwise.
5658  */
5659 static int
5660 nfsrv_notsamecredname(struct nfsrv_descript *nd, struct nfsclient *clp)
5661 {
5662
5663         if (nd->nd_flag & ND_GSS) {
5664                 if (!(clp->lc_flags & LCL_GSS))
5665                         return (1);
5666                 if (clp->lc_flags & LCL_NAME) {
5667                         if (nd->nd_princlen != clp->lc_namelen ||
5668                             NFSBCMP(nd->nd_principal, clp->lc_name,
5669                                 clp->lc_namelen))
5670                                 return (1);
5671                         else
5672                                 return (0);
5673                 }
5674                 if (nd->nd_cred->cr_uid == clp->lc_uid)
5675                         return (0);
5676                 else
5677                         return (1);
5678         } else if (clp->lc_flags & LCL_GSS)
5679                 return (1);
5680         /*
5681          * For AUTH_SYS, allow the same uid or root. (This is underspecified
5682          * in RFC3530, which talks about principals, but doesn't say anything
5683          * about uids for AUTH_SYS.)
5684          */
5685         if (nd->nd_cred->cr_uid == clp->lc_uid || nd->nd_cred->cr_uid == 0)
5686                 return (0);
5687         else
5688                 return (1);
5689 }
5690
5691 /*
5692  * Calculate the lease expiry time.
5693  */
5694 static time_t
5695 nfsrv_leaseexpiry(void)
5696 {
5697
5698         if (nfsrv_stablefirst.nsf_eograce > NFSD_MONOSEC)
5699                 return (NFSD_MONOSEC + 2 * (nfsrv_lease + NFSRV_LEASEDELTA));
5700         return (NFSD_MONOSEC + nfsrv_lease + NFSRV_LEASEDELTA);
5701 }
5702
5703 /*
5704  * Delay the delegation timeout as far as ls_delegtimelimit, as required.
5705  */
5706 static void
5707 nfsrv_delaydelegtimeout(struct nfsstate *stp)
5708 {
5709
5710         if ((stp->ls_flags & NFSLCK_DELEGRECALL) == 0)
5711                 return;
5712
5713         if ((stp->ls_delegtime + 15) > NFSD_MONOSEC &&
5714             stp->ls_delegtime < stp->ls_delegtimelimit) {
5715                 stp->ls_delegtime += nfsrv_lease;
5716                 if (stp->ls_delegtime > stp->ls_delegtimelimit)
5717                         stp->ls_delegtime = stp->ls_delegtimelimit;
5718         }
5719 }
5720
5721 /*
5722  * This function checks to see if there is any other state associated
5723  * with the openowner for this Open.
5724  * It returns 1 if there is no other state, 0 otherwise.
5725  */
5726 static int
5727 nfsrv_nootherstate(struct nfsstate *stp)
5728 {
5729         struct nfsstate *tstp;
5730
5731         LIST_FOREACH(tstp, &stp->ls_openowner->ls_open, ls_list) {
5732                 if (tstp != stp || !LIST_EMPTY(&tstp->ls_lock))
5733                         return (0);
5734         }
5735         return (1);
5736 }
5737
5738 /*
5739  * Create a list of lock deltas (changes to local byte range locking
5740  * that can be rolled back using the list) and apply the changes via
5741  * nfsvno_advlock(). Optionally, lock the list. It is expected that either
5742  * the rollback or update function will be called after this.
5743  * It returns an error (and rolls back, as required), if any nfsvno_advlock()
5744  * call fails. If it returns an error, it will unlock the list.
5745  */
5746 static int
5747 nfsrv_locallock(vnode_t vp, struct nfslockfile *lfp, int flags,
5748     uint64_t first, uint64_t end, struct nfslockconflict *cfp, NFSPROC_T *p)
5749 {
5750         struct nfslock *lop, *nlop;
5751         int error = 0;
5752
5753         /* Loop through the list of locks. */
5754         lop = LIST_FIRST(&lfp->lf_locallock);
5755         while (first < end && lop != NULL) {
5756                 nlop = LIST_NEXT(lop, lo_lckowner);
5757                 if (first >= lop->lo_end) {
5758                         /* not there yet */
5759                         lop = nlop;
5760                 } else if (first < lop->lo_first) {
5761                         /* new one starts before entry in list */
5762                         if (end <= lop->lo_first) {
5763                                 /* no overlap between old and new */
5764                                 error = nfsrv_dolocal(vp, lfp, flags,
5765                                     NFSLCK_UNLOCK, first, end, cfp, p);
5766                                 if (error != 0)
5767                                         break;
5768                                 first = end;
5769                         } else {
5770                                 /* handle fragment overlapped with new one */
5771                                 error = nfsrv_dolocal(vp, lfp, flags,
5772                                     NFSLCK_UNLOCK, first, lop->lo_first, cfp,
5773                                     p);
5774                                 if (error != 0)
5775                                         break;
5776                                 first = lop->lo_first;
5777                         }
5778                 } else {
5779                         /* new one overlaps this entry in list */
5780                         if (end <= lop->lo_end) {
5781                                 /* overlaps all of new one */
5782                                 error = nfsrv_dolocal(vp, lfp, flags,
5783                                     lop->lo_flags, first, end, cfp, p);
5784                                 if (error != 0)
5785                                         break;
5786                                 first = end;
5787                         } else {
5788                                 /* handle fragment overlapped with new one */
5789                                 error = nfsrv_dolocal(vp, lfp, flags,
5790                                     lop->lo_flags, first, lop->lo_end, cfp, p);
5791                                 if (error != 0)
5792                                         break;
5793                                 first = lop->lo_end;
5794                                 lop = nlop;
5795                         }
5796                 }
5797         }
5798         if (first < end && error == 0)
5799                 /* handle fragment past end of list */
5800                 error = nfsrv_dolocal(vp, lfp, flags, NFSLCK_UNLOCK, first,
5801                     end, cfp, p);
5802
5803         NFSEXITCODE(error);
5804         return (error);
5805 }
5806
5807 /*
5808  * Local lock unlock. Unlock all byte ranges that are no longer locked
5809  * by NFSv4. To do this, unlock any subranges of first-->end that
5810  * do not overlap with the byte ranges of any lock in the lfp->lf_lock
5811  * list. This list has all locks for the file held by other
5812  * <clientid, lockowner> tuples. The list is ordered by increasing
5813  * lo_first value, but may have entries that overlap each other, for
5814  * the case of read locks.
5815  */
5816 static void
5817 nfsrv_localunlock(vnode_t vp, struct nfslockfile *lfp, uint64_t init_first,
5818     uint64_t init_end, NFSPROC_T *p)
5819 {
5820         struct nfslock *lop;
5821         uint64_t first, end, prevfirst;
5822
5823         first = init_first;
5824         end = init_end;
5825         while (first < init_end) {
5826                 /* Loop through all nfs locks, adjusting first and end */
5827                 prevfirst = 0;
5828                 LIST_FOREACH(lop, &lfp->lf_lock, lo_lckfile) {
5829                         KASSERT(prevfirst <= lop->lo_first,
5830                             ("nfsv4 locks out of order"));
5831                         KASSERT(lop->lo_first < lop->lo_end,
5832                             ("nfsv4 bogus lock"));
5833                         prevfirst = lop->lo_first;
5834                         if (first >= lop->lo_first &&
5835                             first < lop->lo_end)
5836                                 /*
5837                                  * Overlaps with initial part, so trim
5838                                  * off that initial part by moving first past
5839                                  * it.
5840                                  */
5841                                 first = lop->lo_end;
5842                         else if (end > lop->lo_first &&
5843                             lop->lo_first > first) {
5844                                 /*
5845                                  * This lock defines the end of the
5846                                  * segment to unlock, so set end to the
5847                                  * start of it and break out of the loop.
5848                                  */
5849                                 end = lop->lo_first;
5850                                 break;
5851                         }
5852                         if (first >= end)
5853                                 /*
5854                                  * There is no segment left to do, so
5855                                  * break out of this loop and then exit
5856                                  * the outer while() since first will be set
5857                                  * to end, which must equal init_end here.
5858                                  */
5859                                 break;
5860                 }
5861                 if (first < end) {
5862                         /* Unlock this segment */
5863                         (void) nfsrv_dolocal(vp, lfp, NFSLCK_UNLOCK,
5864                             NFSLCK_READ, first, end, NULL, p);
5865                         nfsrv_locallock_commit(lfp, NFSLCK_UNLOCK,
5866                             first, end);
5867                 }
5868                 /*
5869                  * Now move past this segment and look for any further
5870                  * segment in the range, if there is one.
5871                  */
5872                 first = end;
5873                 end = init_end;
5874         }
5875 }
5876
5877 /*
5878  * Do the local lock operation and update the rollback list, as required.
5879  * Perform the rollback and return the error if nfsvno_advlock() fails.
5880  */
5881 static int
5882 nfsrv_dolocal(vnode_t vp, struct nfslockfile *lfp, int flags, int oldflags,
5883     uint64_t first, uint64_t end, struct nfslockconflict *cfp, NFSPROC_T *p)
5884 {
5885         struct nfsrollback *rlp;
5886         int error = 0, ltype, oldltype;
5887
5888         if (flags & NFSLCK_WRITE)
5889                 ltype = F_WRLCK;
5890         else if (flags & NFSLCK_READ)
5891                 ltype = F_RDLCK;
5892         else
5893                 ltype = F_UNLCK;
5894         if (oldflags & NFSLCK_WRITE)
5895                 oldltype = F_WRLCK;
5896         else if (oldflags & NFSLCK_READ)
5897                 oldltype = F_RDLCK;
5898         else
5899                 oldltype = F_UNLCK;
5900         if (ltype == oldltype || (oldltype == F_WRLCK && ltype == F_RDLCK))
5901                 /* nothing to do */
5902                 goto out;
5903         error = nfsvno_advlock(vp, ltype, first, end, p);
5904         if (error != 0) {
5905                 if (cfp != NULL) {
5906                         cfp->cl_clientid.lval[0] = 0;
5907                         cfp->cl_clientid.lval[1] = 0;
5908                         cfp->cl_first = 0;
5909                         cfp->cl_end = NFS64BITSSET;
5910                         cfp->cl_flags = NFSLCK_WRITE;
5911                         cfp->cl_ownerlen = 5;
5912                         NFSBCOPY("LOCAL", cfp->cl_owner, 5);
5913                 }
5914                 nfsrv_locallock_rollback(vp, lfp, p);
5915         } else if (ltype != F_UNLCK) {
5916                 rlp = malloc(sizeof (struct nfsrollback), M_NFSDROLLBACK,
5917                     M_WAITOK);
5918                 rlp->rlck_first = first;
5919                 rlp->rlck_end = end;
5920                 rlp->rlck_type = oldltype;
5921                 LIST_INSERT_HEAD(&lfp->lf_rollback, rlp, rlck_list);
5922         }
5923
5924 out:
5925         NFSEXITCODE(error);
5926         return (error);
5927 }
5928
5929 /*
5930  * Roll back local lock changes and free up the rollback list.
5931  */
5932 static void
5933 nfsrv_locallock_rollback(vnode_t vp, struct nfslockfile *lfp, NFSPROC_T *p)
5934 {
5935         struct nfsrollback *rlp, *nrlp;
5936
5937         LIST_FOREACH_SAFE(rlp, &lfp->lf_rollback, rlck_list, nrlp) {
5938                 (void) nfsvno_advlock(vp, rlp->rlck_type, rlp->rlck_first,
5939                     rlp->rlck_end, p);
5940                 free(rlp, M_NFSDROLLBACK);
5941         }
5942         LIST_INIT(&lfp->lf_rollback);
5943 }
5944
5945 /*
5946  * Update local lock list and delete rollback list (ie now committed to the
5947  * local locks). Most of the work is done by the internal function.
5948  */
5949 static void
5950 nfsrv_locallock_commit(struct nfslockfile *lfp, int flags, uint64_t first,
5951     uint64_t end)
5952 {
5953         struct nfsrollback *rlp, *nrlp;
5954         struct nfslock *new_lop, *other_lop;
5955
5956         new_lop = malloc(sizeof (struct nfslock), M_NFSDLOCK, M_WAITOK);
5957         if (flags & (NFSLCK_READ | NFSLCK_WRITE))
5958                 other_lop = malloc(sizeof (struct nfslock), M_NFSDLOCK,
5959                     M_WAITOK);
5960         else
5961                 other_lop = NULL;
5962         new_lop->lo_flags = flags;
5963         new_lop->lo_first = first;
5964         new_lop->lo_end = end;
5965         nfsrv_updatelock(NULL, &new_lop, &other_lop, lfp);
5966         if (new_lop != NULL)
5967                 free(new_lop, M_NFSDLOCK);
5968         if (other_lop != NULL)
5969                 free(other_lop, M_NFSDLOCK);
5970
5971         /* and get rid of the rollback list */
5972         LIST_FOREACH_SAFE(rlp, &lfp->lf_rollback, rlck_list, nrlp)
5973                 free(rlp, M_NFSDROLLBACK);
5974         LIST_INIT(&lfp->lf_rollback);
5975 }
5976
5977 /*
5978  * Lock the struct nfslockfile for local lock updating.
5979  */
5980 static void
5981 nfsrv_locklf(struct nfslockfile *lfp)
5982 {
5983         int gotlock;
5984
5985         /* lf_usecount ensures *lfp won't be free'd */
5986         lfp->lf_usecount++;
5987         do {
5988                 gotlock = nfsv4_lock(&lfp->lf_locallock_lck, 1, NULL,
5989                     NFSSTATEMUTEXPTR, NULL);
5990         } while (gotlock == 0);
5991         lfp->lf_usecount--;
5992 }
5993
5994 /*
5995  * Unlock the struct nfslockfile after local lock updating.
5996  */
5997 static void
5998 nfsrv_unlocklf(struct nfslockfile *lfp)
5999 {
6000
6001         nfsv4_unlock(&lfp->lf_locallock_lck, 0);
6002 }
6003
6004 /*
6005  * Clear out all state for the NFSv4 server.
6006  * Must be called by a thread that can sleep when no nfsds are running.
6007  */
6008 void
6009 nfsrv_throwawayallstate(NFSPROC_T *p)
6010 {
6011         struct nfsclient *clp, *nclp;
6012         struct nfslockfile *lfp, *nlfp;
6013         int i;
6014
6015         /*
6016          * For each client, clean out the state and then free the structure.
6017          */
6018         for (i = 0; i < nfsrv_clienthashsize; i++) {
6019                 LIST_FOREACH_SAFE(clp, &nfsclienthash[i], lc_hash, nclp) {
6020                         nfsrv_cleanclient(clp, p);
6021                         nfsrv_freedeleglist(&clp->lc_deleg);
6022                         nfsrv_freedeleglist(&clp->lc_olddeleg);
6023                         free(clp->lc_stateid, M_NFSDCLIENT);
6024                         free(clp, M_NFSDCLIENT);
6025                 }
6026         }
6027
6028         /*
6029          * Also, free up any remaining lock file structures.
6030          */
6031         for (i = 0; i < nfsrv_lockhashsize; i++) {
6032                 LIST_FOREACH_SAFE(lfp, &nfslockhash[i], lf_hash, nlfp) {
6033                         printf("nfsd unload: fnd a lock file struct\n");
6034                         nfsrv_freenfslockfile(lfp);
6035                 }
6036         }
6037 }
6038
6039 /*
6040  * Check the sequence# for the session and slot provided as an argument.
6041  * Also, renew the lease if the session will return NFS_OK.
6042  */
6043 int
6044 nfsrv_checksequence(struct nfsrv_descript *nd, uint32_t sequenceid,
6045     uint32_t *highest_slotidp, uint32_t *target_highest_slotidp, int cache_this,
6046     uint32_t *sflagsp, NFSPROC_T *p)
6047 {
6048         struct nfsdsession *sep;
6049         struct nfssessionhash *shp;
6050         int error;
6051         SVCXPRT *savxprt;
6052
6053         shp = NFSSESSIONHASH(nd->nd_sessionid);
6054         NFSLOCKSESSION(shp);
6055         sep = nfsrv_findsession(nd->nd_sessionid);
6056         if (sep == NULL) {
6057                 NFSUNLOCKSESSION(shp);
6058                 return (NFSERR_BADSESSION);
6059         }
6060         error = nfsv4_seqsession(sequenceid, nd->nd_slotid, *highest_slotidp,
6061             sep->sess_slots, NULL, NFSV4_SLOTS - 1);
6062         if (error != 0) {
6063                 NFSUNLOCKSESSION(shp);
6064                 return (error);
6065         }
6066         if (cache_this != 0)
6067                 nd->nd_flag |= ND_SAVEREPLY;
6068         /* Renew the lease. */
6069         sep->sess_clp->lc_expiry = nfsrv_leaseexpiry();
6070         nd->nd_clientid.qval = sep->sess_clp->lc_clientid.qval;
6071         nd->nd_flag |= ND_IMPLIEDCLID;
6072
6073         /*
6074          * If this session handles the backchannel, save the nd_xprt for this
6075          * RPC, since this is the one being used.
6076          * RFC-5661 specifies that the fore channel will be implicitly
6077          * bound by a Sequence operation.  However, since some NFSv4.1 clients
6078          * erroneously assumed that the back channel would be implicitly
6079          * bound as well, do the implicit binding unless a
6080          * BindConnectiontoSession has already been done on the session.
6081          */
6082         if (sep->sess_clp->lc_req.nr_client != NULL &&
6083             sep->sess_cbsess.nfsess_xprt != nd->nd_xprt &&
6084             (sep->sess_crflags & NFSV4CRSESS_CONNBACKCHAN) != 0 &&
6085             (sep->sess_clp->lc_flags & LCL_DONEBINDCONN) == 0) {
6086                 NFSD_DEBUG(2,
6087                     "nfsrv_checksequence: implicit back channel bind\n");
6088                 savxprt = sep->sess_cbsess.nfsess_xprt;
6089                 SVC_ACQUIRE(nd->nd_xprt);
6090                 nd->nd_xprt->xp_p2 =
6091                     sep->sess_clp->lc_req.nr_client->cl_private;
6092                 nd->nd_xprt->xp_idletimeout = 0;        /* Disable timeout. */
6093                 sep->sess_cbsess.nfsess_xprt = nd->nd_xprt;
6094                 if (savxprt != NULL)
6095                         SVC_RELEASE(savxprt);
6096         }
6097
6098         *sflagsp = 0;
6099         if (sep->sess_clp->lc_req.nr_client == NULL)
6100                 *sflagsp |= NFSV4SEQ_CBPATHDOWN;
6101         NFSUNLOCKSESSION(shp);
6102         if (error == NFSERR_EXPIRED) {
6103                 *sflagsp |= NFSV4SEQ_EXPIREDALLSTATEREVOKED;
6104                 error = 0;
6105         } else if (error == NFSERR_ADMINREVOKED) {
6106                 *sflagsp |= NFSV4SEQ_ADMINSTATEREVOKED;
6107                 error = 0;
6108         }
6109         *highest_slotidp = *target_highest_slotidp = NFSV4_SLOTS - 1;
6110         return (0);
6111 }
6112
6113 /*
6114  * Check/set reclaim complete for this session/clientid.
6115  */
6116 int
6117 nfsrv_checkreclaimcomplete(struct nfsrv_descript *nd, int onefs)
6118 {
6119         struct nfsdsession *sep;
6120         struct nfssessionhash *shp;
6121         int error = 0;
6122
6123         shp = NFSSESSIONHASH(nd->nd_sessionid);
6124         NFSLOCKSTATE();
6125         NFSLOCKSESSION(shp);
6126         sep = nfsrv_findsession(nd->nd_sessionid);
6127         if (sep == NULL) {
6128                 NFSUNLOCKSESSION(shp);
6129                 NFSUNLOCKSTATE();
6130                 return (NFSERR_BADSESSION);
6131         }
6132
6133         if (onefs != 0)
6134                 sep->sess_clp->lc_flags |= LCL_RECLAIMONEFS;
6135                 /* Check to see if reclaim complete has already happened. */
6136         else if ((sep->sess_clp->lc_flags & LCL_RECLAIMCOMPLETE) != 0)
6137                 error = NFSERR_COMPLETEALREADY;
6138         else {
6139                 sep->sess_clp->lc_flags |= LCL_RECLAIMCOMPLETE;
6140                 nfsrv_markreclaim(sep->sess_clp);
6141         }
6142         NFSUNLOCKSESSION(shp);
6143         NFSUNLOCKSTATE();
6144         return (error);
6145 }
6146
6147 /*
6148  * Cache the reply in a session slot.
6149  */
6150 void
6151 nfsrv_cache_session(uint8_t *sessionid, uint32_t slotid, int repstat,
6152    struct mbuf **m)
6153 {
6154         struct nfsdsession *sep;
6155         struct nfssessionhash *shp;
6156
6157         shp = NFSSESSIONHASH(sessionid);
6158         NFSLOCKSESSION(shp);
6159         sep = nfsrv_findsession(sessionid);
6160         if (sep == NULL) {
6161                 NFSUNLOCKSESSION(shp);
6162                 printf("nfsrv_cache_session: no session\n");
6163                 m_freem(*m);
6164                 return;
6165         }
6166         nfsv4_seqsess_cacherep(slotid, sep->sess_slots, repstat, m);
6167         NFSUNLOCKSESSION(shp);
6168 }
6169
6170 /*
6171  * Search for a session that matches the sessionid.
6172  */
6173 static struct nfsdsession *
6174 nfsrv_findsession(uint8_t *sessionid)
6175 {
6176         struct nfsdsession *sep;
6177         struct nfssessionhash *shp;
6178
6179         shp = NFSSESSIONHASH(sessionid);
6180         LIST_FOREACH(sep, &shp->list, sess_hash) {
6181                 if (!NFSBCMP(sessionid, sep->sess_sessionid, NFSX_V4SESSIONID))
6182                         break;
6183         }
6184         return (sep);
6185 }
6186
6187 /*
6188  * Destroy a session.
6189  */
6190 int
6191 nfsrv_destroysession(struct nfsrv_descript *nd, uint8_t *sessionid)
6192 {
6193         int error, igotlock, samesess;
6194
6195         samesess = 0;
6196         if (!NFSBCMP(sessionid, nd->nd_sessionid, NFSX_V4SESSIONID) &&
6197             (nd->nd_flag & ND_HASSEQUENCE) != 0) {
6198                 samesess = 1;
6199                 if ((nd->nd_flag & ND_LASTOP) == 0)
6200                         return (NFSERR_BADSESSION);
6201         }
6202
6203         /* Lock out other nfsd threads */
6204         NFSLOCKV4ROOTMUTEX();
6205         nfsv4_relref(&nfsv4rootfs_lock);
6206         do {
6207                 igotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL,
6208                     NFSV4ROOTLOCKMUTEXPTR, NULL);
6209         } while (igotlock == 0);
6210         NFSUNLOCKV4ROOTMUTEX();
6211
6212         error = nfsrv_freesession(NULL, sessionid);
6213         if (error == 0 && samesess != 0)
6214                 nd->nd_flag &= ~ND_HASSEQUENCE;
6215
6216         NFSLOCKV4ROOTMUTEX();
6217         nfsv4_unlock(&nfsv4rootfs_lock, 1);
6218         NFSUNLOCKV4ROOTMUTEX();
6219         return (error);
6220 }
6221
6222 /*
6223  * Bind a connection to a session.
6224  * For now, only certain variants are supported, since the current session
6225  * structure can only handle a single backchannel entry, which will be
6226  * applied to all connections if it is set.
6227  */
6228 int
6229 nfsrv_bindconnsess(struct nfsrv_descript *nd, uint8_t *sessionid, int *foreaftp)
6230 {
6231         struct nfssessionhash *shp;
6232         struct nfsdsession *sep;
6233         struct nfsclient *clp;
6234         SVCXPRT *savxprt;
6235         int error;
6236
6237         error = 0;
6238         shp = NFSSESSIONHASH(sessionid);
6239         NFSLOCKSTATE();
6240         NFSLOCKSESSION(shp);
6241         sep = nfsrv_findsession(sessionid);
6242         if (sep != NULL) {
6243                 clp = sep->sess_clp;
6244                 if (*foreaftp == NFSCDFC4_BACK ||
6245                     *foreaftp == NFSCDFC4_BACK_OR_BOTH ||
6246                     *foreaftp == NFSCDFC4_FORE_OR_BOTH) {
6247                         /* Try to set up a backchannel. */
6248                         if (clp->lc_req.nr_client == NULL) {
6249                                 NFSD_DEBUG(2, "nfsrv_bindconnsess: acquire "
6250                                     "backchannel\n");
6251                                 clp->lc_req.nr_client = (struct __rpc_client *)
6252                                     clnt_bck_create(nd->nd_xprt->xp_socket,
6253                                     sep->sess_cbprogram, NFSV4_CBVERS);
6254                         }
6255                         if (clp->lc_req.nr_client != NULL) {
6256                                 NFSD_DEBUG(2, "nfsrv_bindconnsess: set up "
6257                                     "backchannel\n");
6258                                 savxprt = sep->sess_cbsess.nfsess_xprt;
6259                                 SVC_ACQUIRE(nd->nd_xprt);
6260                                 nd->nd_xprt->xp_p2 =
6261                                     clp->lc_req.nr_client->cl_private;
6262                                 /* Disable idle timeout. */
6263                                 nd->nd_xprt->xp_idletimeout = 0;
6264                                 sep->sess_cbsess.nfsess_xprt = nd->nd_xprt;
6265                                 if (savxprt != NULL)
6266                                         SVC_RELEASE(savxprt);
6267                                 sep->sess_crflags |= NFSV4CRSESS_CONNBACKCHAN;
6268                                 clp->lc_flags |= LCL_DONEBINDCONN;
6269                                 if (*foreaftp == NFSCDFS4_BACK)
6270                                         *foreaftp = NFSCDFS4_BACK;
6271                                 else
6272                                         *foreaftp = NFSCDFS4_BOTH;
6273                         } else if (*foreaftp != NFSCDFC4_BACK) {
6274                                 NFSD_DEBUG(2, "nfsrv_bindconnsess: can't set "
6275                                     "up backchannel\n");
6276                                 sep->sess_crflags &= ~NFSV4CRSESS_CONNBACKCHAN;
6277                                 clp->lc_flags |= LCL_DONEBINDCONN;
6278                                 *foreaftp = NFSCDFS4_FORE;
6279                         } else {
6280                                 error = NFSERR_NOTSUPP;
6281                                 printf("nfsrv_bindconnsess: Can't add "
6282                                     "backchannel\n");
6283                         }
6284                 } else {
6285                         NFSD_DEBUG(2, "nfsrv_bindconnsess: Set forechannel\n");
6286                         clp->lc_flags |= LCL_DONEBINDCONN;
6287                         *foreaftp = NFSCDFS4_FORE;
6288                 }
6289         } else
6290                 error = NFSERR_BADSESSION;
6291         NFSUNLOCKSESSION(shp);
6292         NFSUNLOCKSTATE();
6293         return (error);
6294 }
6295
6296 /*
6297  * Free up a session structure.
6298  */
6299 static int
6300 nfsrv_freesession(struct nfsdsession *sep, uint8_t *sessionid)
6301 {
6302         struct nfssessionhash *shp;
6303         int i;
6304
6305         NFSLOCKSTATE();
6306         if (sep == NULL) {
6307                 shp = NFSSESSIONHASH(sessionid);
6308                 NFSLOCKSESSION(shp);
6309                 sep = nfsrv_findsession(sessionid);
6310         } else {
6311                 shp = NFSSESSIONHASH(sep->sess_sessionid);
6312                 NFSLOCKSESSION(shp);
6313         }
6314         if (sep != NULL) {
6315                 sep->sess_refcnt--;
6316                 if (sep->sess_refcnt > 0) {
6317                         NFSUNLOCKSESSION(shp);
6318                         NFSUNLOCKSTATE();
6319                         return (NFSERR_BACKCHANBUSY);
6320                 }
6321                 LIST_REMOVE(sep, sess_hash);
6322                 LIST_REMOVE(sep, sess_list);
6323         }
6324         NFSUNLOCKSESSION(shp);
6325         NFSUNLOCKSTATE();
6326         if (sep == NULL)
6327                 return (NFSERR_BADSESSION);
6328         for (i = 0; i < NFSV4_SLOTS; i++)
6329                 if (sep->sess_slots[i].nfssl_reply != NULL)
6330                         m_freem(sep->sess_slots[i].nfssl_reply);
6331         if (sep->sess_cbsess.nfsess_xprt != NULL)
6332                 SVC_RELEASE(sep->sess_cbsess.nfsess_xprt);
6333         free(sep, M_NFSDSESSION);
6334         return (0);
6335 }
6336
6337 /*
6338  * Free a stateid.
6339  * RFC5661 says that it should fail when there are associated opens, locks
6340  * or delegations. Since stateids represent opens, I don't see how you can
6341  * free an open stateid (it will be free'd when closed), so this function
6342  * only works for lock stateids (freeing the lock_owner) or delegations.
6343  */
6344 int
6345 nfsrv_freestateid(struct nfsrv_descript *nd, nfsv4stateid_t *stateidp,
6346     NFSPROC_T *p)
6347 {
6348         struct nfsclient *clp;
6349         struct nfsstate *stp;
6350         int error;
6351
6352         NFSLOCKSTATE();
6353         /*
6354          * Look up the stateid
6355          */
6356         error = nfsrv_getclient((nfsquad_t)((u_quad_t)0), CLOPS_RENEW, &clp,
6357             NULL, (nfsquad_t)((u_quad_t)0), 0, nd, p);
6358         if (error == 0) {
6359                 /* First, check for a delegation. */
6360                 LIST_FOREACH(stp, &clp->lc_deleg, ls_list) {
6361                         if (!NFSBCMP(stp->ls_stateid.other, stateidp->other,
6362                             NFSX_STATEIDOTHER))
6363                                 break;
6364                 }
6365                 if (stp != NULL) {
6366                         nfsrv_freedeleg(stp);
6367                         NFSUNLOCKSTATE();
6368                         return (error);
6369                 }
6370         }
6371         /* Not a delegation, try for a lock_owner. */
6372         if (error == 0)
6373                 error = nfsrv_getstate(clp, stateidp, 0, &stp);
6374         if (error == 0 && ((stp->ls_flags & (NFSLCK_OPEN | NFSLCK_DELEGREAD |
6375             NFSLCK_DELEGWRITE)) != 0 || (stp->ls_flags & NFSLCK_LOCK) == 0))
6376                 /* Not a lock_owner stateid. */
6377                 error = NFSERR_LOCKSHELD;
6378         if (error == 0 && !LIST_EMPTY(&stp->ls_lock))
6379                 error = NFSERR_LOCKSHELD;
6380         if (error == 0)
6381                 nfsrv_freelockowner(stp, NULL, 0, p);
6382         NFSUNLOCKSTATE();
6383         return (error);
6384 }
6385
6386 /*
6387  * Test a stateid.
6388  */
6389 int
6390 nfsrv_teststateid(struct nfsrv_descript *nd, nfsv4stateid_t *stateidp,
6391     NFSPROC_T *p)
6392 {
6393         struct nfsclient *clp;
6394         struct nfsstate *stp;
6395         int error;
6396
6397         NFSLOCKSTATE();
6398         /*
6399          * Look up the stateid
6400          */
6401         error = nfsrv_getclient((nfsquad_t)((u_quad_t)0), CLOPS_RENEW, &clp,
6402             NULL, (nfsquad_t)((u_quad_t)0), 0, nd, p);
6403         if (error == 0)
6404                 error = nfsrv_getstate(clp, stateidp, 0, &stp);
6405         if (error == 0 && stateidp->seqid != 0 &&
6406             SEQ_LT(stateidp->seqid, stp->ls_stateid.seqid))
6407                 error = NFSERR_OLDSTATEID;
6408         NFSUNLOCKSTATE();
6409         return (error);
6410 }
6411
6412 /*
6413  * Generate the xdr for an NFSv4.1 CBSequence Operation.
6414  */
6415 static int
6416 nfsv4_setcbsequence(struct nfsrv_descript *nd, struct nfsclient *clp,
6417     int dont_replycache, struct nfsdsession **sepp)
6418 {
6419         struct nfsdsession *sep;
6420         uint32_t *tl, slotseq = 0;
6421         int maxslot, slotpos;
6422         uint8_t sessionid[NFSX_V4SESSIONID];
6423         int error;
6424
6425         error = nfsv4_getcbsession(clp, sepp);
6426         if (error != 0)
6427                 return (error);
6428         sep = *sepp;
6429         (void)nfsv4_sequencelookup(NULL, &sep->sess_cbsess, &slotpos, &maxslot,
6430             &slotseq, sessionid);
6431         KASSERT(maxslot >= 0, ("nfsv4_setcbsequence neg maxslot"));
6432
6433         /* Build the Sequence arguments. */
6434         NFSM_BUILD(tl, uint32_t *, NFSX_V4SESSIONID + 5 * NFSX_UNSIGNED);
6435         bcopy(sessionid, tl, NFSX_V4SESSIONID);
6436         tl += NFSX_V4SESSIONID / NFSX_UNSIGNED;
6437         nd->nd_slotseq = tl;
6438         *tl++ = txdr_unsigned(slotseq);
6439         *tl++ = txdr_unsigned(slotpos);
6440         *tl++ = txdr_unsigned(maxslot);
6441         if (dont_replycache == 0)
6442                 *tl++ = newnfs_true;
6443         else
6444                 *tl++ = newnfs_false;
6445         *tl = 0;                        /* No referring call list, for now. */
6446         nd->nd_flag |= ND_HASSEQUENCE;
6447         return (0);
6448 }
6449
6450 /*
6451  * Get a session for the callback.
6452  */
6453 static int
6454 nfsv4_getcbsession(struct nfsclient *clp, struct nfsdsession **sepp)
6455 {
6456         struct nfsdsession *sep;
6457
6458         NFSLOCKSTATE();
6459         LIST_FOREACH(sep, &clp->lc_session, sess_list) {
6460                 if ((sep->sess_crflags & NFSV4CRSESS_CONNBACKCHAN) != 0)
6461                         break;
6462         }
6463         if (sep == NULL) {
6464                 NFSUNLOCKSTATE();
6465                 return (NFSERR_BADSESSION);
6466         }
6467         sep->sess_refcnt++;
6468         *sepp = sep;
6469         NFSUNLOCKSTATE();
6470         return (0);
6471 }
6472
6473 /*
6474  * Free up all backchannel xprts.  This needs to be done when the nfsd threads
6475  * exit, since those transports will all be going away.
6476  * This is only called after all the nfsd threads are done performing RPCs,
6477  * so locking shouldn't be an issue.
6478  */
6479 APPLESTATIC void
6480 nfsrv_freeallbackchannel_xprts(void)
6481 {
6482         struct nfsdsession *sep;
6483         struct nfsclient *clp;
6484         SVCXPRT *xprt;
6485         int i;
6486
6487         for (i = 0; i < nfsrv_clienthashsize; i++) {
6488                 LIST_FOREACH(clp, &nfsclienthash[i], lc_hash) {
6489                         LIST_FOREACH(sep, &clp->lc_session, sess_list) {
6490                                 xprt = sep->sess_cbsess.nfsess_xprt;
6491                                 sep->sess_cbsess.nfsess_xprt = NULL;
6492                                 if (xprt != NULL)
6493                                         SVC_RELEASE(xprt);
6494                         }
6495                 }
6496         }
6497 }
6498