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