]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/fs/nfsserver/nfs_nfsdstate.c
MFV r366990: less v563.
[FreeBSD/FreeBSD.git] / sys / fs / nfsserver / nfs_nfsdstate.c
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2009 Rick Macklem, University of Guelph
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  *
28  */
29
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
32
33 #include "opt_inet.h"
34 #include "opt_inet6.h"
35 #include <sys/extattr.h>
36 #include <fs/nfs/nfsport.h>
37
38 struct nfsrv_stablefirst nfsrv_stablefirst;
39 int nfsrv_issuedelegs = 0;
40 int nfsrv_dolocallocks = 0;
41 struct nfsv4lock nfsv4rootfs_lock;
42 time_t nfsdev_time = 0;
43 int nfsrv_layouthashsize;
44 volatile int nfsrv_layoutcnt = 0;
45
46 extern int newnfs_numnfsd;
47 extern struct nfsstatsv1 nfsstatsv1;
48 extern int nfsrv_lease;
49 extern struct timeval nfsboottime;
50 extern u_int32_t newnfs_true, newnfs_false;
51 extern struct mtx nfsrv_dslock_mtx;
52 extern struct mtx nfsrv_recalllock_mtx;
53 extern struct mtx nfsrv_dontlistlock_mtx;
54 extern int nfsd_debuglevel;
55 extern u_int nfsrv_dsdirsize;
56 extern struct nfsdevicehead nfsrv_devidhead;
57 extern int nfsrv_doflexfile;
58 extern int nfsrv_maxpnfsmirror;
59 NFSV4ROOTLOCKMUTEX;
60 NFSSTATESPINLOCK;
61 extern struct nfsdontlisthead nfsrv_dontlisthead;
62 extern volatile int nfsrv_devidcnt;
63 extern struct nfslayouthead nfsrv_recalllisthead;
64 extern char *nfsrv_zeropnfsdat;
65
66 SYSCTL_DECL(_vfs_nfsd);
67 int     nfsrv_statehashsize = NFSSTATEHASHSIZE;
68 SYSCTL_INT(_vfs_nfsd, OID_AUTO, statehashsize, CTLFLAG_RDTUN,
69     &nfsrv_statehashsize, 0,
70     "Size of state hash table set via loader.conf");
71
72 int     nfsrv_clienthashsize = NFSCLIENTHASHSIZE;
73 SYSCTL_INT(_vfs_nfsd, OID_AUTO, clienthashsize, CTLFLAG_RDTUN,
74     &nfsrv_clienthashsize, 0,
75     "Size of client hash table set via loader.conf");
76
77 int     nfsrv_lockhashsize = NFSLOCKHASHSIZE;
78 SYSCTL_INT(_vfs_nfsd, OID_AUTO, fhhashsize, CTLFLAG_RDTUN,
79     &nfsrv_lockhashsize, 0,
80     "Size of file handle hash table set via loader.conf");
81
82 int     nfsrv_sessionhashsize = NFSSESSIONHASHSIZE;
83 SYSCTL_INT(_vfs_nfsd, OID_AUTO, sessionhashsize, CTLFLAG_RDTUN,
84     &nfsrv_sessionhashsize, 0,
85     "Size of session hash table set via loader.conf");
86
87 int     nfsrv_layouthighwater = NFSLAYOUTHIGHWATER;
88 SYSCTL_INT(_vfs_nfsd, OID_AUTO, layouthighwater, CTLFLAG_RDTUN,
89     &nfsrv_layouthighwater, 0,
90     "High water mark for number of layouts set via loader.conf");
91
92 static int      nfsrv_v4statelimit = NFSRV_V4STATELIMIT;
93 SYSCTL_INT(_vfs_nfsd, OID_AUTO, v4statelimit, CTLFLAG_RWTUN,
94     &nfsrv_v4statelimit, 0,
95     "High water limit for NFSv4 opens+locks+delegations");
96
97 static int      nfsrv_writedelegifpos = 0;
98 SYSCTL_INT(_vfs_nfsd, OID_AUTO, writedelegifpos, CTLFLAG_RW,
99     &nfsrv_writedelegifpos, 0,
100     "Issue a write delegation for read opens if possible");
101
102 static int      nfsrv_allowreadforwriteopen = 1;
103 SYSCTL_INT(_vfs_nfsd, OID_AUTO, allowreadforwriteopen, CTLFLAG_RW,
104     &nfsrv_allowreadforwriteopen, 0,
105     "Allow Reads to be done with Write Access StateIDs");
106
107 int     nfsrv_pnfsatime = 0;
108 SYSCTL_INT(_vfs_nfsd, OID_AUTO, pnfsstrictatime, CTLFLAG_RW,
109     &nfsrv_pnfsatime, 0,
110     "For pNFS service, do Getattr ops to keep atime up-to-date");
111
112 int     nfsrv_flexlinuxhack = 0;
113 SYSCTL_INT(_vfs_nfsd, OID_AUTO, flexlinuxhack, CTLFLAG_RW,
114     &nfsrv_flexlinuxhack, 0,
115     "For Linux clients, hack around Flex File Layout bug");
116
117 /*
118  * Hash lists for nfs V4.
119  */
120 struct nfsclienthashhead        *nfsclienthash;
121 struct nfslockhashhead          *nfslockhash;
122 struct nfssessionhash           *nfssessionhash;
123 struct nfslayouthash            *nfslayouthash;
124 volatile int nfsrv_dontlistlen = 0;
125
126 static u_int32_t nfsrv_openpluslock = 0, nfsrv_delegatecnt = 0;
127 static time_t nfsrvboottime;
128 static int nfsrv_returnoldstateid = 0, nfsrv_clients = 0;
129 static int nfsrv_clienthighwater = NFSRV_CLIENTHIGHWATER;
130 static int nfsrv_nogsscallback = 0;
131 static volatile int nfsrv_writedelegcnt = 0;
132 static int nfsrv_faildscnt;
133
134 /* local functions */
135 static void nfsrv_dumpaclient(struct nfsclient *clp,
136     struct nfsd_dumpclients *dumpp);
137 static void nfsrv_freeopenowner(struct nfsstate *stp, int cansleep,
138     NFSPROC_T *p);
139 static int nfsrv_freeopen(struct nfsstate *stp, vnode_t vp, int cansleep,
140     NFSPROC_T *p);
141 static void nfsrv_freelockowner(struct nfsstate *stp, vnode_t vp, int cansleep,
142     NFSPROC_T *p);
143 static void nfsrv_freeallnfslocks(struct nfsstate *stp, vnode_t vp,
144     int cansleep, NFSPROC_T *p);
145 static void nfsrv_freenfslock(struct nfslock *lop);
146 static void nfsrv_freenfslockfile(struct nfslockfile *lfp);
147 static void nfsrv_freedeleg(struct nfsstate *);
148 static int nfsrv_getstate(struct nfsclient *clp, nfsv4stateid_t *stateidp, 
149     u_int32_t flags, struct nfsstate **stpp);
150 static void nfsrv_getowner(struct nfsstatehead *hp, struct nfsstate *new_stp,
151     struct nfsstate **stpp);
152 static int nfsrv_getlockfh(vnode_t vp, u_short flags,
153     struct nfslockfile *new_lfp, fhandle_t *nfhp, NFSPROC_T *p);
154 static int nfsrv_getlockfile(u_short flags, struct nfslockfile **new_lfpp,
155     struct nfslockfile **lfpp, fhandle_t *nfhp, int lockit);
156 static void nfsrv_insertlock(struct nfslock *new_lop,
157     struct nfslock *insert_lop, struct nfsstate *stp, struct nfslockfile *lfp);
158 static void nfsrv_updatelock(struct nfsstate *stp, struct nfslock **new_lopp,
159     struct nfslock **other_lopp, struct nfslockfile *lfp);
160 static int nfsrv_getipnumber(u_char *cp);
161 static int nfsrv_checkrestart(nfsquad_t clientid, u_int32_t flags,
162     nfsv4stateid_t *stateidp, int specialid);
163 static int nfsrv_checkgrace(struct nfsrv_descript *nd, struct nfsclient *clp,
164     u_int32_t flags);
165 static int nfsrv_docallback(struct nfsclient *clp, int procnum,
166     nfsv4stateid_t *stateidp, int trunc, fhandle_t *fhp,
167     struct nfsvattr *nap, nfsattrbit_t *attrbitp, int laytype, NFSPROC_T *p);
168 static int nfsrv_cbcallargs(struct nfsrv_descript *nd, struct nfsclient *clp,
169     uint32_t callback, int op, const char *optag, struct nfsdsession **sepp);
170 static u_int32_t nfsrv_nextclientindex(void);
171 static u_int32_t nfsrv_nextstateindex(struct nfsclient *clp);
172 static void nfsrv_markstable(struct nfsclient *clp);
173 static void nfsrv_markreclaim(struct nfsclient *clp);
174 static int nfsrv_checkstable(struct nfsclient *clp);
175 static int nfsrv_clientconflict(struct nfsclient *clp, int *haslockp, struct 
176     vnode *vp, NFSPROC_T *p);
177 static int nfsrv_delegconflict(struct nfsstate *stp, int *haslockp,
178     NFSPROC_T *p, vnode_t vp);
179 static int nfsrv_cleandeleg(vnode_t vp, struct nfslockfile *lfp,
180     struct nfsclient *clp, int *haslockp, NFSPROC_T *p);
181 static int nfsrv_notsamecredname(struct nfsrv_descript *nd,
182     struct nfsclient *clp);
183 static time_t nfsrv_leaseexpiry(void);
184 static void nfsrv_delaydelegtimeout(struct nfsstate *stp);
185 static int nfsrv_checkseqid(struct nfsrv_descript *nd, u_int32_t seqid,
186     struct nfsstate *stp, struct nfsrvcache *op);
187 static int nfsrv_nootherstate(struct nfsstate *stp);
188 static int nfsrv_locallock(vnode_t vp, struct nfslockfile *lfp, int flags,
189     uint64_t first, uint64_t end, struct nfslockconflict *cfp, NFSPROC_T *p);
190 static void nfsrv_localunlock(vnode_t vp, struct nfslockfile *lfp,
191     uint64_t init_first, uint64_t init_end, NFSPROC_T *p);
192 static int nfsrv_dolocal(vnode_t vp, struct nfslockfile *lfp, int flags,
193     int oldflags, uint64_t first, uint64_t end, struct nfslockconflict *cfp,
194     NFSPROC_T *p);
195 static void nfsrv_locallock_rollback(vnode_t vp, struct nfslockfile *lfp,
196     NFSPROC_T *p);
197 static void nfsrv_locallock_commit(struct nfslockfile *lfp, int flags,
198     uint64_t first, uint64_t end);
199 static void nfsrv_locklf(struct nfslockfile *lfp);
200 static void nfsrv_unlocklf(struct nfslockfile *lfp);
201 static struct nfsdsession *nfsrv_findsession(uint8_t *sessionid);
202 static int nfsrv_freesession(struct nfsdsession *sep, uint8_t *sessionid);
203 static int nfsv4_setcbsequence(struct nfsrv_descript *nd, struct nfsclient *clp,
204     int dont_replycache, struct nfsdsession **sepp);
205 static int nfsv4_getcbsession(struct nfsclient *clp, struct nfsdsession **sepp);
206 static int nfsrv_addlayout(struct nfsrv_descript *nd, struct nfslayout **lypp,
207     nfsv4stateid_t *stateidp, char *layp, int *layoutlenp, NFSPROC_T *p);
208 static void nfsrv_freelayout(struct nfslayouthead *lhp, struct nfslayout *lyp);
209 static void nfsrv_freelayoutlist(nfsquad_t clientid);
210 static void nfsrv_freelayouts(nfsquad_t *clid, fsid_t *fs, int laytype,
211     int iomode);
212 static void nfsrv_freealllayouts(void);
213 static void nfsrv_freedevid(struct nfsdevice *ds);
214 static int nfsrv_setdsserver(char *dspathp, char *mdspathp, NFSPROC_T *p,
215     struct nfsdevice **dsp);
216 static void nfsrv_deleteds(struct nfsdevice *fndds);
217 static void nfsrv_allocdevid(struct nfsdevice *ds, char *addr, char *dnshost);
218 static void nfsrv_freealldevids(void);
219 static void nfsrv_flexlayouterr(struct nfsrv_descript *nd, uint32_t *layp,
220     int maxcnt, NFSPROC_T *p);
221 static int nfsrv_recalllayout(nfsquad_t clid, nfsv4stateid_t *stateidp,
222     fhandle_t *fhp, struct nfslayout *lyp, int changed, int laytype,
223     NFSPROC_T *p);
224 static int nfsrv_findlayout(nfsquad_t *clientidp, fhandle_t *fhp, int laytype,
225     NFSPROC_T *, struct nfslayout **lypp);
226 static int nfsrv_fndclid(nfsquad_t *clidvec, nfsquad_t clid, int clidcnt);
227 static struct nfslayout *nfsrv_filelayout(struct nfsrv_descript *nd, int iomode,
228     fhandle_t *fhp, fhandle_t *dsfhp, char *devid, fsid_t fs);
229 static struct nfslayout *nfsrv_flexlayout(struct nfsrv_descript *nd, int iomode,
230     int mirrorcnt, fhandle_t *fhp, fhandle_t *dsfhp, char *devid, fsid_t fs);
231 static int nfsrv_dontlayout(fhandle_t *fhp);
232 static int nfsrv_createdsfile(vnode_t vp, fhandle_t *fhp, struct pnfsdsfile *pf,
233     vnode_t dvp, struct nfsdevice *ds, struct ucred *cred, NFSPROC_T *p,
234     vnode_t *tvpp);
235 static struct nfsdevice *nfsrv_findmirroredds(struct nfsmount *nmp);
236
237 /*
238  * Scan the client list for a match and either return the current one,
239  * create a new entry or return an error.
240  * If returning a non-error, the clp structure must either be linked into
241  * the client list or free'd.
242  */
243 int
244 nfsrv_setclient(struct nfsrv_descript *nd, struct nfsclient **new_clpp,
245     nfsquad_t *clientidp, nfsquad_t *confirmp, NFSPROC_T *p)
246 {
247         struct nfsclient *clp = NULL, *new_clp = *new_clpp;
248         int i, error = 0, ret;
249         struct nfsstate *stp, *tstp;
250 #ifdef INET
251         struct sockaddr_in *sin, *rin;
252 #endif
253 #ifdef INET6
254         struct sockaddr_in6 *sin6, *rin6;
255 #endif
256         struct nfsdsession *sep, *nsep;
257         int zapit = 0, gotit, hasstate = 0, igotlock;
258         static u_int64_t confirm_index = 0;
259
260         /*
261          * Check for state resource limit exceeded.
262          */
263         if (nfsrv_openpluslock > nfsrv_v4statelimit) {
264                 error = NFSERR_RESOURCE;
265                 goto out;
266         }
267
268         if (nfsrv_issuedelegs == 0 ||
269             ((nd->nd_flag & ND_GSS) != 0 && nfsrv_nogsscallback != 0))
270                 /*
271                  * Don't do callbacks when delegations are disabled or
272                  * for AUTH_GSS unless enabled via nfsrv_nogsscallback.
273                  * If establishing a callback connection is attempted
274                  * when a firewall is blocking the callback path, the
275                  * server may wait too long for the connect attempt to
276                  * succeed during the Open. Some clients, such as Linux,
277                  * may timeout and give up on the Open before the server
278                  * replies. Also, since AUTH_GSS callbacks are not
279                  * yet interoperability tested, they might cause the
280                  * server to crap out, if they get past the Init call to
281                  * the client.
282                  */
283                 new_clp->lc_program = 0;
284
285         /* Lock out other nfsd threads */
286         NFSLOCKV4ROOTMUTEX();
287         nfsv4_relref(&nfsv4rootfs_lock);
288         do {
289                 igotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL,
290                     NFSV4ROOTLOCKMUTEXPTR, NULL);
291         } while (!igotlock);
292         NFSUNLOCKV4ROOTMUTEX();
293
294         /*
295          * Search for a match in the client list.
296          */
297         gotit = i = 0;
298         while (i < nfsrv_clienthashsize && !gotit) {
299             LIST_FOREACH(clp, &nfsclienthash[i], lc_hash) {
300                 if (new_clp->lc_idlen == clp->lc_idlen &&
301                     !NFSBCMP(new_clp->lc_id, clp->lc_id, clp->lc_idlen)) {
302                         gotit = 1;
303                         break;
304                 }
305             }
306             if (gotit == 0)
307                 i++;
308         }
309         if (!gotit ||
310             (clp->lc_flags & (LCL_NEEDSCONFIRM | LCL_ADMINREVOKED))) {
311                 if ((nd->nd_flag & ND_NFSV41) != 0 && confirmp->lval[1] != 0) {
312                         /*
313                          * For NFSv4.1, if confirmp->lval[1] is non-zero, the
314                          * client is trying to update a confirmed clientid.
315                          */
316                         NFSLOCKV4ROOTMUTEX();
317                         nfsv4_unlock(&nfsv4rootfs_lock, 1);
318                         NFSUNLOCKV4ROOTMUTEX();
319                         confirmp->lval[1] = 0;
320                         error = NFSERR_NOENT;
321                         goto out;
322                 }
323                 /*
324                  * Get rid of the old one.
325                  */
326                 if (i != nfsrv_clienthashsize) {
327                         LIST_REMOVE(clp, lc_hash);
328                         nfsrv_cleanclient(clp, p);
329                         nfsrv_freedeleglist(&clp->lc_deleg);
330                         nfsrv_freedeleglist(&clp->lc_olddeleg);
331                         zapit = 1;
332                 }
333                 /*
334                  * Add it after assigning a client id to it.
335                  */
336                 new_clp->lc_flags |= LCL_NEEDSCONFIRM;
337                 if ((nd->nd_flag & ND_NFSV41) != 0)
338                         new_clp->lc_confirm.lval[0] = confirmp->lval[0] =
339                             ++confirm_index;
340                 else
341                         confirmp->qval = new_clp->lc_confirm.qval =
342                             ++confirm_index;
343                 clientidp->lval[0] = new_clp->lc_clientid.lval[0] =
344                     (u_int32_t)nfsrvboottime;
345                 clientidp->lval[1] = new_clp->lc_clientid.lval[1] =
346                     nfsrv_nextclientindex();
347                 new_clp->lc_stateindex = 0;
348                 new_clp->lc_statemaxindex = 0;
349                 new_clp->lc_cbref = 0;
350                 new_clp->lc_expiry = nfsrv_leaseexpiry();
351                 LIST_INIT(&new_clp->lc_open);
352                 LIST_INIT(&new_clp->lc_deleg);
353                 LIST_INIT(&new_clp->lc_olddeleg);
354                 LIST_INIT(&new_clp->lc_session);
355                 for (i = 0; i < nfsrv_statehashsize; i++)
356                         LIST_INIT(&new_clp->lc_stateid[i]);
357                 LIST_INSERT_HEAD(NFSCLIENTHASH(new_clp->lc_clientid), new_clp,
358                     lc_hash);
359                 nfsstatsv1.srvclients++;
360                 nfsrv_openpluslock++;
361                 nfsrv_clients++;
362                 NFSLOCKV4ROOTMUTEX();
363                 nfsv4_unlock(&nfsv4rootfs_lock, 1);
364                 NFSUNLOCKV4ROOTMUTEX();
365                 if (zapit)
366                         nfsrv_zapclient(clp, p);
367                 *new_clpp = NULL;
368                 goto out;
369         }
370
371         /*
372          * Now, handle the cases where the id is already issued.
373          */
374         if (nfsrv_notsamecredname(nd, clp)) {
375             /*
376              * Check to see if there is expired state that should go away.
377              */
378             if (clp->lc_expiry < NFSD_MONOSEC &&
379                 (!LIST_EMPTY(&clp->lc_open) || !LIST_EMPTY(&clp->lc_deleg))) {
380                 nfsrv_cleanclient(clp, p);
381                 nfsrv_freedeleglist(&clp->lc_deleg);
382             }
383
384             /*
385              * If there is outstanding state, then reply NFSERR_CLIDINUSE per
386              * RFC3530 Sec. 8.1.2 last para.
387              */
388             if (!LIST_EMPTY(&clp->lc_deleg)) {
389                 hasstate = 1;
390             } else if (LIST_EMPTY(&clp->lc_open)) {
391                 hasstate = 0;
392             } else {
393                 hasstate = 0;
394                 /* Look for an Open on the OpenOwner */
395                 LIST_FOREACH(stp, &clp->lc_open, ls_list) {
396                     if (!LIST_EMPTY(&stp->ls_open)) {
397                         hasstate = 1;
398                         break;
399                     }
400                 }
401             }
402             if (hasstate) {
403                 /*
404                  * If the uid doesn't match, return NFSERR_CLIDINUSE after
405                  * filling out the correct ipaddr and portnum.
406                  */
407                 switch (clp->lc_req.nr_nam->sa_family) {
408 #ifdef INET
409                 case AF_INET:
410                         sin = (struct sockaddr_in *)new_clp->lc_req.nr_nam;
411                         rin = (struct sockaddr_in *)clp->lc_req.nr_nam;
412                         sin->sin_addr.s_addr = rin->sin_addr.s_addr;
413                         sin->sin_port = rin->sin_port;
414                         break;
415 #endif
416 #ifdef INET6
417                 case AF_INET6:
418                         sin6 = (struct sockaddr_in6 *)new_clp->lc_req.nr_nam;
419                         rin6 = (struct sockaddr_in6 *)clp->lc_req.nr_nam;
420                         sin6->sin6_addr = rin6->sin6_addr;
421                         sin6->sin6_port = rin6->sin6_port;
422                         break;
423 #endif
424                 }
425                 NFSLOCKV4ROOTMUTEX();
426                 nfsv4_unlock(&nfsv4rootfs_lock, 1);
427                 NFSUNLOCKV4ROOTMUTEX();
428                 error = NFSERR_CLIDINUSE;
429                 goto out;
430             }
431         }
432
433         if (NFSBCMP(new_clp->lc_verf, clp->lc_verf, NFSX_VERF)) {
434                 /*
435                  * If the verifier has changed, the client has rebooted
436                  * and a new client id is issued. The old state info
437                  * can be thrown away once the SETCLIENTID_CONFIRM occurs.
438                  */
439                 LIST_REMOVE(clp, lc_hash);
440
441                 /* Get rid of all sessions on this clientid. */
442                 LIST_FOREACH_SAFE(sep, &clp->lc_session, sess_list, nsep) {
443                         ret = nfsrv_freesession(sep, NULL);
444                         if (ret != 0)
445                                 printf("nfsrv_setclient: verifier changed free"
446                                     " session failed=%d\n", ret);
447                 }
448
449                 new_clp->lc_flags |= LCL_NEEDSCONFIRM;
450                 if ((nd->nd_flag & ND_NFSV41) != 0)
451                         new_clp->lc_confirm.lval[0] = confirmp->lval[0] =
452                             ++confirm_index;
453                 else
454                         confirmp->qval = new_clp->lc_confirm.qval =
455                             ++confirm_index;
456                 clientidp->lval[0] = new_clp->lc_clientid.lval[0] =
457                     nfsrvboottime;
458                 clientidp->lval[1] = new_clp->lc_clientid.lval[1] =
459                     nfsrv_nextclientindex();
460                 new_clp->lc_stateindex = 0;
461                 new_clp->lc_statemaxindex = 0;
462                 new_clp->lc_cbref = 0;
463                 new_clp->lc_expiry = nfsrv_leaseexpiry();
464
465                 /*
466                  * Save the state until confirmed.
467                  */
468                 LIST_NEWHEAD(&new_clp->lc_open, &clp->lc_open, ls_list);
469                 LIST_FOREACH(tstp, &new_clp->lc_open, ls_list)
470                         tstp->ls_clp = new_clp;
471                 LIST_NEWHEAD(&new_clp->lc_deleg, &clp->lc_deleg, ls_list);
472                 LIST_FOREACH(tstp, &new_clp->lc_deleg, ls_list)
473                         tstp->ls_clp = new_clp;
474                 LIST_NEWHEAD(&new_clp->lc_olddeleg, &clp->lc_olddeleg,
475                     ls_list);
476                 LIST_FOREACH(tstp, &new_clp->lc_olddeleg, ls_list)
477                         tstp->ls_clp = new_clp;
478                 for (i = 0; i < nfsrv_statehashsize; i++) {
479                         LIST_NEWHEAD(&new_clp->lc_stateid[i],
480                             &clp->lc_stateid[i], ls_hash);
481                         LIST_FOREACH(tstp, &new_clp->lc_stateid[i], ls_hash)
482                                 tstp->ls_clp = new_clp;
483                 }
484                 LIST_INIT(&new_clp->lc_session);
485                 LIST_INSERT_HEAD(NFSCLIENTHASH(new_clp->lc_clientid), new_clp,
486                     lc_hash);
487                 nfsstatsv1.srvclients++;
488                 nfsrv_openpluslock++;
489                 nfsrv_clients++;
490                 NFSLOCKV4ROOTMUTEX();
491                 nfsv4_unlock(&nfsv4rootfs_lock, 1);
492                 NFSUNLOCKV4ROOTMUTEX();
493
494                 /*
495                  * Must wait until any outstanding callback on the old clp
496                  * completes.
497                  */
498                 NFSLOCKSTATE();
499                 while (clp->lc_cbref) {
500                         clp->lc_flags |= LCL_WAKEUPWANTED;
501                         (void)mtx_sleep(clp, NFSSTATEMUTEXPTR, PZERO - 1,
502                             "nfsd clp", 10 * hz);
503                 }
504                 NFSUNLOCKSTATE();
505                 nfsrv_zapclient(clp, p);
506                 *new_clpp = NULL;
507                 goto out;
508         }
509
510         /* For NFSv4.1, mark that we found a confirmed clientid. */
511         if ((nd->nd_flag & ND_NFSV41) != 0) {
512                 clientidp->lval[0] = clp->lc_clientid.lval[0];
513                 clientidp->lval[1] = clp->lc_clientid.lval[1];
514                 confirmp->lval[0] = 0;  /* Ignored by client */
515                 confirmp->lval[1] = 1;
516         } else {
517                 /*
518                  * id and verifier match, so update the net address info
519                  * and get rid of any existing callback authentication
520                  * handle, so a new one will be acquired.
521                  */
522                 LIST_REMOVE(clp, lc_hash);
523                 new_clp->lc_flags |= (LCL_NEEDSCONFIRM | LCL_DONTCLEAN);
524                 new_clp->lc_expiry = nfsrv_leaseexpiry();
525                 confirmp->qval = new_clp->lc_confirm.qval = ++confirm_index;
526                 clientidp->lval[0] = new_clp->lc_clientid.lval[0] =
527                     clp->lc_clientid.lval[0];
528                 clientidp->lval[1] = new_clp->lc_clientid.lval[1] =
529                     clp->lc_clientid.lval[1];
530                 new_clp->lc_delegtime = clp->lc_delegtime;
531                 new_clp->lc_stateindex = clp->lc_stateindex;
532                 new_clp->lc_statemaxindex = clp->lc_statemaxindex;
533                 new_clp->lc_cbref = 0;
534                 LIST_NEWHEAD(&new_clp->lc_open, &clp->lc_open, ls_list);
535                 LIST_FOREACH(tstp, &new_clp->lc_open, ls_list)
536                         tstp->ls_clp = new_clp;
537                 LIST_NEWHEAD(&new_clp->lc_deleg, &clp->lc_deleg, ls_list);
538                 LIST_FOREACH(tstp, &new_clp->lc_deleg, ls_list)
539                         tstp->ls_clp = new_clp;
540                 LIST_NEWHEAD(&new_clp->lc_olddeleg, &clp->lc_olddeleg, ls_list);
541                 LIST_FOREACH(tstp, &new_clp->lc_olddeleg, ls_list)
542                         tstp->ls_clp = new_clp;
543                 for (i = 0; i < nfsrv_statehashsize; i++) {
544                         LIST_NEWHEAD(&new_clp->lc_stateid[i],
545                             &clp->lc_stateid[i], ls_hash);
546                         LIST_FOREACH(tstp, &new_clp->lc_stateid[i], ls_hash)
547                                 tstp->ls_clp = new_clp;
548                 }
549                 LIST_INIT(&new_clp->lc_session);
550                 LIST_INSERT_HEAD(NFSCLIENTHASH(new_clp->lc_clientid), new_clp,
551                     lc_hash);
552                 nfsstatsv1.srvclients++;
553                 nfsrv_openpluslock++;
554                 nfsrv_clients++;
555         }
556         NFSLOCKV4ROOTMUTEX();
557         nfsv4_unlock(&nfsv4rootfs_lock, 1);
558         NFSUNLOCKV4ROOTMUTEX();
559
560         if ((nd->nd_flag & ND_NFSV41) == 0) {
561                 /*
562                  * Must wait until any outstanding callback on the old clp
563                  * completes.
564                  */
565                 NFSLOCKSTATE();
566                 while (clp->lc_cbref) {
567                         clp->lc_flags |= LCL_WAKEUPWANTED;
568                         (void)mtx_sleep(clp, NFSSTATEMUTEXPTR, PZERO - 1,
569                             "nfsdclp", 10 * hz);
570                 }
571                 NFSUNLOCKSTATE();
572                 nfsrv_zapclient(clp, p);
573                 *new_clpp = NULL;
574         }
575
576 out:
577         NFSEXITCODE2(error, nd);
578         return (error);
579 }
580
581 /*
582  * Check to see if the client id exists and optionally confirm it.
583  */
584 int
585 nfsrv_getclient(nfsquad_t clientid, int opflags, struct nfsclient **clpp,
586     struct nfsdsession *nsep, nfsquad_t confirm, uint32_t cbprogram,
587     struct nfsrv_descript *nd, NFSPROC_T *p)
588 {
589         struct nfsclient *clp;
590         struct nfsstate *stp;
591         int i;
592         struct nfsclienthashhead *hp;
593         int error = 0, igotlock, doneok;
594         struct nfssessionhash *shp;
595         struct nfsdsession *sep;
596         uint64_t sessid[2];
597         static uint64_t next_sess = 0;
598
599         if (clpp)
600                 *clpp = NULL;
601         if ((nd == NULL || (nd->nd_flag & ND_NFSV41) == 0 ||
602             opflags != CLOPS_RENEW) && nfsrvboottime != clientid.lval[0]) {
603                 error = NFSERR_STALECLIENTID;
604                 goto out;
605         }
606
607         /*
608          * If called with opflags == CLOPS_RENEW, the State Lock is
609          * already held. Otherwise, we need to get either that or,
610          * for the case of Confirm, lock out the nfsd threads.
611          */
612         if (opflags & CLOPS_CONFIRM) {
613                 NFSLOCKV4ROOTMUTEX();
614                 nfsv4_relref(&nfsv4rootfs_lock);
615                 do {
616                         igotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL,
617                             NFSV4ROOTLOCKMUTEXPTR, NULL);
618                 } while (!igotlock);
619                 /*
620                  * Create a new sessionid here, since we need to do it where
621                  * there is a mutex held to serialize update of next_sess.
622                  */
623                 if ((nd->nd_flag & ND_NFSV41) != 0) {
624                         sessid[0] = ++next_sess;
625                         sessid[1] = clientid.qval;
626                 }
627                 NFSUNLOCKV4ROOTMUTEX();
628         } else if (opflags != CLOPS_RENEW) {
629                 NFSLOCKSTATE();
630         }
631
632         /* For NFSv4.1, the clp is acquired from the associated session. */
633         if (nd != NULL && (nd->nd_flag & ND_NFSV41) != 0 &&
634             opflags == CLOPS_RENEW) {
635                 clp = NULL;
636                 if ((nd->nd_flag & ND_HASSEQUENCE) != 0) {
637                         shp = NFSSESSIONHASH(nd->nd_sessionid);
638                         NFSLOCKSESSION(shp);
639                         sep = nfsrv_findsession(nd->nd_sessionid);
640                         if (sep != NULL)
641                                 clp = sep->sess_clp;
642                         NFSUNLOCKSESSION(shp);
643                 }
644         } else {
645                 hp = NFSCLIENTHASH(clientid);
646                 LIST_FOREACH(clp, hp, lc_hash) {
647                         if (clp->lc_clientid.lval[1] == clientid.lval[1])
648                                 break;
649                 }
650         }
651         if (clp == NULL) {
652                 if (opflags & CLOPS_CONFIRM)
653                         error = NFSERR_STALECLIENTID;
654                 else
655                         error = NFSERR_EXPIRED;
656         } else if (clp->lc_flags & LCL_ADMINREVOKED) {
657                 /*
658                  * If marked admin revoked, just return the error.
659                  */
660                 error = NFSERR_ADMINREVOKED;
661         }
662         if (error) {
663                 if (opflags & CLOPS_CONFIRM) {
664                         NFSLOCKV4ROOTMUTEX();
665                         nfsv4_unlock(&nfsv4rootfs_lock, 1);
666                         NFSUNLOCKV4ROOTMUTEX();
667                 } else if (opflags != CLOPS_RENEW) {
668                         NFSUNLOCKSTATE();
669                 }
670                 goto out;
671         }
672
673         /*
674          * Perform any operations specified by the opflags.
675          */
676         if (opflags & CLOPS_CONFIRM) {
677                 if (((nd->nd_flag & ND_NFSV41) != 0 &&
678                      clp->lc_confirm.lval[0] != confirm.lval[0]) ||
679                     ((nd->nd_flag & ND_NFSV41) == 0 &&
680                      clp->lc_confirm.qval != confirm.qval))
681                         error = NFSERR_STALECLIENTID;
682                 else if (nfsrv_notsamecredname(nd, clp))
683                         error = NFSERR_CLIDINUSE;
684
685                 if (!error) {
686                     if ((clp->lc_flags & (LCL_NEEDSCONFIRM | LCL_DONTCLEAN)) ==
687                         LCL_NEEDSCONFIRM) {
688                         /*
689                          * Hang onto the delegations (as old delegations)
690                          * for an Open with CLAIM_DELEGATE_PREV unless in
691                          * grace, but get rid of the rest of the state.
692                          */
693                         nfsrv_cleanclient(clp, p);
694                         nfsrv_freedeleglist(&clp->lc_olddeleg);
695                         if (nfsrv_checkgrace(nd, clp, 0)) {
696                             /* In grace, so just delete delegations */
697                             nfsrv_freedeleglist(&clp->lc_deleg);
698                         } else {
699                             LIST_FOREACH(stp, &clp->lc_deleg, ls_list)
700                                 stp->ls_flags |= NFSLCK_OLDDELEG;
701                             clp->lc_delegtime = NFSD_MONOSEC +
702                                 nfsrv_lease + NFSRV_LEASEDELTA;
703                             LIST_NEWHEAD(&clp->lc_olddeleg, &clp->lc_deleg,
704                                 ls_list);
705                         }
706                         if ((nd->nd_flag & ND_NFSV41) != 0)
707                             clp->lc_program = cbprogram;
708                     }
709                     clp->lc_flags &= ~(LCL_NEEDSCONFIRM | LCL_DONTCLEAN);
710                     if (clp->lc_program)
711                         clp->lc_flags |= LCL_NEEDSCBNULL;
712                     /* For NFSv4.1, link the session onto the client. */
713                     if (nsep != NULL) {
714                         /* Hold a reference on the xprt for a backchannel. */
715                         if ((nsep->sess_crflags & NFSV4CRSESS_CONNBACKCHAN)
716                             != 0) {
717                             if (clp->lc_req.nr_client == NULL)
718                                 clp->lc_req.nr_client = (struct __rpc_client *)
719                                     clnt_bck_create(nd->nd_xprt->xp_socket,
720                                     cbprogram, NFSV4_CBVERS);
721                             if (clp->lc_req.nr_client != NULL) {
722                                 SVC_ACQUIRE(nd->nd_xprt);
723                                 nd->nd_xprt->xp_p2 =
724                                     clp->lc_req.nr_client->cl_private;
725                                 /* Disable idle timeout. */
726                                 nd->nd_xprt->xp_idletimeout = 0;
727                                 nsep->sess_cbsess.nfsess_xprt = nd->nd_xprt;
728                             } else
729                                 nsep->sess_crflags &= ~NFSV4CRSESS_CONNBACKCHAN;
730                         }
731                         NFSBCOPY(sessid, nsep->sess_sessionid,
732                             NFSX_V4SESSIONID);
733                         NFSBCOPY(sessid, nsep->sess_cbsess.nfsess_sessionid,
734                             NFSX_V4SESSIONID);
735                         shp = NFSSESSIONHASH(nsep->sess_sessionid);
736                         NFSLOCKSTATE();
737                         NFSLOCKSESSION(shp);
738                         LIST_INSERT_HEAD(&shp->list, nsep, sess_hash);
739                         LIST_INSERT_HEAD(&clp->lc_session, nsep, sess_list);
740                         nsep->sess_clp = clp;
741                         NFSUNLOCKSESSION(shp);
742                         NFSUNLOCKSTATE();
743                     }
744                 }
745         } else if (clp->lc_flags & LCL_NEEDSCONFIRM) {
746                 error = NFSERR_EXPIRED;
747         }
748
749         /*
750          * If called by the Renew Op, we must check the principal.
751          */
752         if (!error && (opflags & CLOPS_RENEWOP)) {
753             if (nfsrv_notsamecredname(nd, clp)) {
754                 doneok = 0;
755                 for (i = 0; i < nfsrv_statehashsize && doneok == 0; i++) {
756                     LIST_FOREACH(stp, &clp->lc_stateid[i], ls_hash) {
757                         if ((stp->ls_flags & NFSLCK_OPEN) &&
758                             stp->ls_uid == nd->nd_cred->cr_uid) {
759                                 doneok = 1;
760                                 break;
761                         }
762                     }
763                 }
764                 if (!doneok)
765                         error = NFSERR_ACCES;
766             }
767             if (!error && (clp->lc_flags & LCL_CBDOWN))
768                 error = NFSERR_CBPATHDOWN;
769         }
770         if ((!error || error == NFSERR_CBPATHDOWN) &&
771              (opflags & CLOPS_RENEW)) {
772                 clp->lc_expiry = nfsrv_leaseexpiry();
773         }
774         if (opflags & CLOPS_CONFIRM) {
775                 NFSLOCKV4ROOTMUTEX();
776                 nfsv4_unlock(&nfsv4rootfs_lock, 1);
777                 NFSUNLOCKV4ROOTMUTEX();
778         } else if (opflags != CLOPS_RENEW) {
779                 NFSUNLOCKSTATE();
780         }
781         if (clpp)
782                 *clpp = clp;
783
784 out:
785         NFSEXITCODE2(error, nd);
786         return (error);
787 }
788
789 /*
790  * Perform the NFSv4.1 destroy clientid.
791  */
792 int
793 nfsrv_destroyclient(nfsquad_t clientid, NFSPROC_T *p)
794 {
795         struct nfsclient *clp;
796         struct nfsclienthashhead *hp;
797         int error = 0, i, igotlock;
798
799         if (nfsrvboottime != clientid.lval[0]) {
800                 error = NFSERR_STALECLIENTID;
801                 goto out;
802         }
803
804         /* Lock out other nfsd threads */
805         NFSLOCKV4ROOTMUTEX();
806         nfsv4_relref(&nfsv4rootfs_lock);
807         do {
808                 igotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL,
809                     NFSV4ROOTLOCKMUTEXPTR, NULL);
810         } while (igotlock == 0);
811         NFSUNLOCKV4ROOTMUTEX();
812
813         hp = NFSCLIENTHASH(clientid);
814         LIST_FOREACH(clp, hp, lc_hash) {
815                 if (clp->lc_clientid.lval[1] == clientid.lval[1])
816                         break;
817         }
818         if (clp == NULL) {
819                 NFSLOCKV4ROOTMUTEX();
820                 nfsv4_unlock(&nfsv4rootfs_lock, 1);
821                 NFSUNLOCKV4ROOTMUTEX();
822                 /* Just return ok, since it is gone. */
823                 goto out;
824         }
825
826         /*
827          * Free up all layouts on the clientid.  Should the client return the
828          * layouts?
829          */
830         nfsrv_freelayoutlist(clientid);
831
832         /* Scan for state on the clientid. */
833         for (i = 0; i < nfsrv_statehashsize; i++)
834                 if (!LIST_EMPTY(&clp->lc_stateid[i])) {
835                         NFSLOCKV4ROOTMUTEX();
836                         nfsv4_unlock(&nfsv4rootfs_lock, 1);
837                         NFSUNLOCKV4ROOTMUTEX();
838                         error = NFSERR_CLIENTIDBUSY;
839                         goto out;
840                 }
841         if (!LIST_EMPTY(&clp->lc_session) || !LIST_EMPTY(&clp->lc_deleg)) {
842                 NFSLOCKV4ROOTMUTEX();
843                 nfsv4_unlock(&nfsv4rootfs_lock, 1);
844                 NFSUNLOCKV4ROOTMUTEX();
845                 error = NFSERR_CLIENTIDBUSY;
846                 goto out;
847         }
848
849         /* Destroy the clientid and return ok. */
850         nfsrv_cleanclient(clp, p);
851         nfsrv_freedeleglist(&clp->lc_deleg);
852         nfsrv_freedeleglist(&clp->lc_olddeleg);
853         LIST_REMOVE(clp, lc_hash);
854         NFSLOCKV4ROOTMUTEX();
855         nfsv4_unlock(&nfsv4rootfs_lock, 1);
856         NFSUNLOCKV4ROOTMUTEX();
857         nfsrv_zapclient(clp, p);
858 out:
859         NFSEXITCODE2(error, nd);
860         return (error);
861 }
862
863 /*
864  * Called from the new nfssvc syscall to admin revoke a clientid.
865  * Returns 0 for success, error otherwise.
866  */
867 int
868 nfsrv_adminrevoke(struct nfsd_clid *revokep, NFSPROC_T *p)
869 {
870         struct nfsclient *clp = NULL;
871         int i, error = 0;
872         int gotit, igotlock;
873
874         /*
875          * First, lock out the nfsd so that state won't change while the
876          * revocation record is being written to the stable storage restart
877          * file.
878          */
879         NFSLOCKV4ROOTMUTEX();
880         do {
881                 igotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL,
882                     NFSV4ROOTLOCKMUTEXPTR, NULL);
883         } while (!igotlock);
884         NFSUNLOCKV4ROOTMUTEX();
885
886         /*
887          * Search for a match in the client list.
888          */
889         gotit = i = 0;
890         while (i < nfsrv_clienthashsize && !gotit) {
891             LIST_FOREACH(clp, &nfsclienthash[i], lc_hash) {
892                 if (revokep->nclid_idlen == clp->lc_idlen &&
893                     !NFSBCMP(revokep->nclid_id, clp->lc_id, clp->lc_idlen)) {
894                         gotit = 1;
895                         break;
896                 }
897             }
898             i++;
899         }
900         if (!gotit) {
901                 NFSLOCKV4ROOTMUTEX();
902                 nfsv4_unlock(&nfsv4rootfs_lock, 0);
903                 NFSUNLOCKV4ROOTMUTEX();
904                 error = EPERM;
905                 goto out;
906         }
907
908         /*
909          * Now, write out the revocation record
910          */
911         nfsrv_writestable(clp->lc_id, clp->lc_idlen, NFSNST_REVOKE, p);
912         nfsrv_backupstable();
913
914         /*
915          * and clear out the state, marking the clientid revoked.
916          */
917         clp->lc_flags &= ~LCL_CALLBACKSON;
918         clp->lc_flags |= LCL_ADMINREVOKED;
919         nfsrv_cleanclient(clp, p);
920         nfsrv_freedeleglist(&clp->lc_deleg);
921         nfsrv_freedeleglist(&clp->lc_olddeleg);
922         NFSLOCKV4ROOTMUTEX();
923         nfsv4_unlock(&nfsv4rootfs_lock, 0);
924         NFSUNLOCKV4ROOTMUTEX();
925
926 out:
927         NFSEXITCODE(error);
928         return (error);
929 }
930
931 /*
932  * Dump out stats for all clients. Called from nfssvc(2), that is used
933  * nfsstatsv1.
934  */
935 void
936 nfsrv_dumpclients(struct nfsd_dumpclients *dumpp, int maxcnt)
937 {
938         struct nfsclient *clp;
939         int i = 0, cnt = 0;
940
941         /*
942          * First, get a reference on the nfsv4rootfs_lock so that an
943          * exclusive lock cannot be acquired while dumping the clients.
944          */
945         NFSLOCKV4ROOTMUTEX();
946         nfsv4_getref(&nfsv4rootfs_lock, NULL, NFSV4ROOTLOCKMUTEXPTR, NULL);
947         NFSUNLOCKV4ROOTMUTEX();
948         NFSLOCKSTATE();
949         /*
950          * Rattle through the client lists until done.
951          */
952         while (i < nfsrv_clienthashsize && cnt < maxcnt) {
953             clp = LIST_FIRST(&nfsclienthash[i]);
954             while (clp != LIST_END(&nfsclienthash[i]) && cnt < maxcnt) {
955                 nfsrv_dumpaclient(clp, &dumpp[cnt]);
956                 cnt++;
957                 clp = LIST_NEXT(clp, lc_hash);
958             }
959             i++;
960         }
961         if (cnt < maxcnt)
962             dumpp[cnt].ndcl_clid.nclid_idlen = 0;
963         NFSUNLOCKSTATE();
964         NFSLOCKV4ROOTMUTEX();
965         nfsv4_relref(&nfsv4rootfs_lock);
966         NFSUNLOCKV4ROOTMUTEX();
967 }
968
969 /*
970  * Dump stats for a client. Must be called with the NFSSTATELOCK and spl'd.
971  */
972 static void
973 nfsrv_dumpaclient(struct nfsclient *clp, struct nfsd_dumpclients *dumpp)
974 {
975         struct nfsstate *stp, *openstp, *lckownstp;
976         struct nfslock *lop;
977         sa_family_t af;
978 #ifdef INET
979         struct sockaddr_in *rin;
980 #endif
981 #ifdef INET6
982         struct sockaddr_in6 *rin6;
983 #endif
984
985         dumpp->ndcl_nopenowners = dumpp->ndcl_nlockowners = 0;
986         dumpp->ndcl_nopens = dumpp->ndcl_nlocks = 0;
987         dumpp->ndcl_ndelegs = dumpp->ndcl_nolddelegs = 0;
988         dumpp->ndcl_flags = clp->lc_flags;
989         dumpp->ndcl_clid.nclid_idlen = clp->lc_idlen;
990         NFSBCOPY(clp->lc_id, dumpp->ndcl_clid.nclid_id, clp->lc_idlen);
991         af = clp->lc_req.nr_nam->sa_family;
992         dumpp->ndcl_addrfam = af;
993         switch (af) {
994 #ifdef INET
995         case AF_INET:
996                 rin = (struct sockaddr_in *)clp->lc_req.nr_nam;
997                 dumpp->ndcl_cbaddr.sin_addr = rin->sin_addr;
998                 break;
999 #endif
1000 #ifdef INET6
1001         case AF_INET6:
1002                 rin6 = (struct sockaddr_in6 *)clp->lc_req.nr_nam;
1003                 dumpp->ndcl_cbaddr.sin6_addr = rin6->sin6_addr;
1004                 break;
1005 #endif
1006         }
1007
1008         /*
1009          * Now, scan the state lists and total up the opens and locks.
1010          */
1011         LIST_FOREACH(stp, &clp->lc_open, ls_list) {
1012             dumpp->ndcl_nopenowners++;
1013             LIST_FOREACH(openstp, &stp->ls_open, ls_list) {
1014                 dumpp->ndcl_nopens++;
1015                 LIST_FOREACH(lckownstp, &openstp->ls_open, ls_list) {
1016                     dumpp->ndcl_nlockowners++;
1017                     LIST_FOREACH(lop, &lckownstp->ls_lock, lo_lckowner) {
1018                         dumpp->ndcl_nlocks++;
1019                     }
1020                 }
1021             }
1022         }
1023
1024         /*
1025          * and the delegation lists.
1026          */
1027         LIST_FOREACH(stp, &clp->lc_deleg, ls_list) {
1028             dumpp->ndcl_ndelegs++;
1029         }
1030         LIST_FOREACH(stp, &clp->lc_olddeleg, ls_list) {
1031             dumpp->ndcl_nolddelegs++;
1032         }
1033 }
1034
1035 /*
1036  * Dump out lock stats for a file.
1037  */
1038 void
1039 nfsrv_dumplocks(vnode_t vp, struct nfsd_dumplocks *ldumpp, int maxcnt,
1040     NFSPROC_T *p)
1041 {
1042         struct nfsstate *stp;
1043         struct nfslock *lop;
1044         int cnt = 0;
1045         struct nfslockfile *lfp;
1046         sa_family_t af;
1047 #ifdef INET
1048         struct sockaddr_in *rin;
1049 #endif
1050 #ifdef INET6
1051         struct sockaddr_in6 *rin6;
1052 #endif
1053         int ret;
1054         fhandle_t nfh;
1055
1056         ret = nfsrv_getlockfh(vp, 0, NULL, &nfh, p);
1057         /*
1058          * First, get a reference on the nfsv4rootfs_lock so that an
1059          * exclusive lock on it cannot be acquired while dumping the locks.
1060          */
1061         NFSLOCKV4ROOTMUTEX();
1062         nfsv4_getref(&nfsv4rootfs_lock, NULL, NFSV4ROOTLOCKMUTEXPTR, NULL);
1063         NFSUNLOCKV4ROOTMUTEX();
1064         NFSLOCKSTATE();
1065         if (!ret)
1066                 ret = nfsrv_getlockfile(0, NULL, &lfp, &nfh, 0);
1067         if (ret) {
1068                 ldumpp[0].ndlck_clid.nclid_idlen = 0;
1069                 NFSUNLOCKSTATE();
1070                 NFSLOCKV4ROOTMUTEX();
1071                 nfsv4_relref(&nfsv4rootfs_lock);
1072                 NFSUNLOCKV4ROOTMUTEX();
1073                 return;
1074         }
1075
1076         /*
1077          * For each open share on file, dump it out.
1078          */
1079         stp = LIST_FIRST(&lfp->lf_open);
1080         while (stp != LIST_END(&lfp->lf_open) && cnt < maxcnt) {
1081                 ldumpp[cnt].ndlck_flags = stp->ls_flags;
1082                 ldumpp[cnt].ndlck_stateid.seqid = stp->ls_stateid.seqid;
1083                 ldumpp[cnt].ndlck_stateid.other[0] = stp->ls_stateid.other[0];
1084                 ldumpp[cnt].ndlck_stateid.other[1] = stp->ls_stateid.other[1];
1085                 ldumpp[cnt].ndlck_stateid.other[2] = stp->ls_stateid.other[2];
1086                 ldumpp[cnt].ndlck_owner.nclid_idlen =
1087                     stp->ls_openowner->ls_ownerlen;
1088                 NFSBCOPY(stp->ls_openowner->ls_owner,
1089                     ldumpp[cnt].ndlck_owner.nclid_id,
1090                     stp->ls_openowner->ls_ownerlen);
1091                 ldumpp[cnt].ndlck_clid.nclid_idlen = stp->ls_clp->lc_idlen;
1092                 NFSBCOPY(stp->ls_clp->lc_id, ldumpp[cnt].ndlck_clid.nclid_id,
1093                     stp->ls_clp->lc_idlen);
1094                 af = stp->ls_clp->lc_req.nr_nam->sa_family;
1095                 ldumpp[cnt].ndlck_addrfam = af;
1096                 switch (af) {
1097 #ifdef INET
1098                 case AF_INET:
1099                         rin = (struct sockaddr_in *)stp->ls_clp->lc_req.nr_nam;
1100                         ldumpp[cnt].ndlck_cbaddr.sin_addr = rin->sin_addr;
1101                         break;
1102 #endif
1103 #ifdef INET6
1104                 case AF_INET6:
1105                         rin6 = (struct sockaddr_in6 *)
1106                             stp->ls_clp->lc_req.nr_nam;
1107                         ldumpp[cnt].ndlck_cbaddr.sin6_addr = rin6->sin6_addr;
1108                         break;
1109 #endif
1110                 }
1111                 stp = LIST_NEXT(stp, ls_file);
1112                 cnt++;
1113         }
1114
1115         /*
1116          * and all locks.
1117          */
1118         lop = LIST_FIRST(&lfp->lf_lock);
1119         while (lop != LIST_END(&lfp->lf_lock) && cnt < maxcnt) {
1120                 stp = lop->lo_stp;
1121                 ldumpp[cnt].ndlck_flags = lop->lo_flags;
1122                 ldumpp[cnt].ndlck_first = lop->lo_first;
1123                 ldumpp[cnt].ndlck_end = lop->lo_end;
1124                 ldumpp[cnt].ndlck_stateid.seqid = stp->ls_stateid.seqid;
1125                 ldumpp[cnt].ndlck_stateid.other[0] = stp->ls_stateid.other[0];
1126                 ldumpp[cnt].ndlck_stateid.other[1] = stp->ls_stateid.other[1];
1127                 ldumpp[cnt].ndlck_stateid.other[2] = stp->ls_stateid.other[2];
1128                 ldumpp[cnt].ndlck_owner.nclid_idlen = stp->ls_ownerlen;
1129                 NFSBCOPY(stp->ls_owner, ldumpp[cnt].ndlck_owner.nclid_id,
1130                     stp->ls_ownerlen);
1131                 ldumpp[cnt].ndlck_clid.nclid_idlen = stp->ls_clp->lc_idlen;
1132                 NFSBCOPY(stp->ls_clp->lc_id, ldumpp[cnt].ndlck_clid.nclid_id,
1133                     stp->ls_clp->lc_idlen);
1134                 af = stp->ls_clp->lc_req.nr_nam->sa_family;
1135                 ldumpp[cnt].ndlck_addrfam = af;
1136                 switch (af) {
1137 #ifdef INET
1138                 case AF_INET:
1139                         rin = (struct sockaddr_in *)stp->ls_clp->lc_req.nr_nam;
1140                         ldumpp[cnt].ndlck_cbaddr.sin_addr = rin->sin_addr;
1141                         break;
1142 #endif
1143 #ifdef INET6
1144                 case AF_INET6:
1145                         rin6 = (struct sockaddr_in6 *)
1146                             stp->ls_clp->lc_req.nr_nam;
1147                         ldumpp[cnt].ndlck_cbaddr.sin6_addr = rin6->sin6_addr;
1148                         break;
1149 #endif
1150                 }
1151                 lop = LIST_NEXT(lop, lo_lckfile);
1152                 cnt++;
1153         }
1154
1155         /*
1156          * and the delegations.
1157          */
1158         stp = LIST_FIRST(&lfp->lf_deleg);
1159         while (stp != LIST_END(&lfp->lf_deleg) && cnt < maxcnt) {
1160                 ldumpp[cnt].ndlck_flags = stp->ls_flags;
1161                 ldumpp[cnt].ndlck_stateid.seqid = stp->ls_stateid.seqid;
1162                 ldumpp[cnt].ndlck_stateid.other[0] = stp->ls_stateid.other[0];
1163                 ldumpp[cnt].ndlck_stateid.other[1] = stp->ls_stateid.other[1];
1164                 ldumpp[cnt].ndlck_stateid.other[2] = stp->ls_stateid.other[2];
1165                 ldumpp[cnt].ndlck_owner.nclid_idlen = 0;
1166                 ldumpp[cnt].ndlck_clid.nclid_idlen = stp->ls_clp->lc_idlen;
1167                 NFSBCOPY(stp->ls_clp->lc_id, ldumpp[cnt].ndlck_clid.nclid_id,
1168                     stp->ls_clp->lc_idlen);
1169                 af = stp->ls_clp->lc_req.nr_nam->sa_family;
1170                 ldumpp[cnt].ndlck_addrfam = af;
1171                 switch (af) {
1172 #ifdef INET
1173                 case AF_INET:
1174                         rin = (struct sockaddr_in *)stp->ls_clp->lc_req.nr_nam;
1175                         ldumpp[cnt].ndlck_cbaddr.sin_addr = rin->sin_addr;
1176                         break;
1177 #endif
1178 #ifdef INET6
1179                 case AF_INET6:
1180                         rin6 = (struct sockaddr_in6 *)
1181                             stp->ls_clp->lc_req.nr_nam;
1182                         ldumpp[cnt].ndlck_cbaddr.sin6_addr = rin6->sin6_addr;
1183                         break;
1184 #endif
1185                 }
1186                 stp = LIST_NEXT(stp, ls_file);
1187                 cnt++;
1188         }
1189
1190         /*
1191          * If list isn't full, mark end of list by setting the client name
1192          * to zero length.
1193          */
1194         if (cnt < maxcnt)
1195                 ldumpp[cnt].ndlck_clid.nclid_idlen = 0;
1196         NFSUNLOCKSTATE();
1197         NFSLOCKV4ROOTMUTEX();
1198         nfsv4_relref(&nfsv4rootfs_lock);
1199         NFSUNLOCKV4ROOTMUTEX();
1200 }
1201
1202 /*
1203  * Server timer routine. It can scan any linked list, so long
1204  * as it holds the spin/mutex lock and there is no exclusive lock on
1205  * nfsv4rootfs_lock.
1206  * (For OpenBSD, a kthread is ok. For FreeBSD, I think it is ok
1207  *  to do this from a callout, since the spin locks work. For
1208  *  Darwin, I'm not sure what will work correctly yet.)
1209  * Should be called once per second.
1210  */
1211 void
1212 nfsrv_servertimer(void)
1213 {
1214         struct nfsclient *clp, *nclp;
1215         struct nfsstate *stp, *nstp;
1216         int got_ref, i;
1217
1218         /*
1219          * Make sure nfsboottime is set. This is used by V3 as well
1220          * as V4. Note that nfsboottime is not nfsrvboottime, which is
1221          * only used by the V4 server for leases.
1222          */
1223         if (nfsboottime.tv_sec == 0)
1224                 NFSSETBOOTTIME(nfsboottime);
1225
1226         /*
1227          * If server hasn't started yet, just return.
1228          */
1229         NFSLOCKSTATE();
1230         if (nfsrv_stablefirst.nsf_eograce == 0) {
1231                 NFSUNLOCKSTATE();
1232                 return;
1233         }
1234         if (!(nfsrv_stablefirst.nsf_flags & NFSNSF_UPDATEDONE)) {
1235                 if (!(nfsrv_stablefirst.nsf_flags & NFSNSF_GRACEOVER) &&
1236                     NFSD_MONOSEC > nfsrv_stablefirst.nsf_eograce)
1237                         nfsrv_stablefirst.nsf_flags |=
1238                             (NFSNSF_GRACEOVER | NFSNSF_NEEDLOCK);
1239                 NFSUNLOCKSTATE();
1240                 return;
1241         }
1242
1243         /*
1244          * Try and get a reference count on the nfsv4rootfs_lock so that
1245          * no nfsd thread can acquire an exclusive lock on it before this
1246          * call is done. If it is already exclusively locked, just return.
1247          */
1248         NFSLOCKV4ROOTMUTEX();
1249         got_ref = nfsv4_getref_nonblock(&nfsv4rootfs_lock);
1250         NFSUNLOCKV4ROOTMUTEX();
1251         if (got_ref == 0) {
1252                 NFSUNLOCKSTATE();
1253                 return;
1254         }
1255
1256         /*
1257          * For each client...
1258          */
1259         for (i = 0; i < nfsrv_clienthashsize; i++) {
1260             clp = LIST_FIRST(&nfsclienthash[i]);
1261             while (clp != LIST_END(&nfsclienthash[i])) {
1262                 nclp = LIST_NEXT(clp, lc_hash);
1263                 if (!(clp->lc_flags & LCL_EXPIREIT)) {
1264                     if (((clp->lc_expiry + NFSRV_STALELEASE) < NFSD_MONOSEC
1265                          && ((LIST_EMPTY(&clp->lc_deleg)
1266                               && LIST_EMPTY(&clp->lc_open)) ||
1267                              nfsrv_clients > nfsrv_clienthighwater)) ||
1268                         (clp->lc_expiry + NFSRV_MOULDYLEASE) < NFSD_MONOSEC ||
1269                         (clp->lc_expiry < NFSD_MONOSEC &&
1270                          (nfsrv_openpluslock * 10 / 9) > nfsrv_v4statelimit)) {
1271                         /*
1272                          * Lease has expired several nfsrv_lease times ago:
1273                          * PLUS
1274                          *    - no state is associated with it
1275                          *    OR
1276                          *    - above high water mark for number of clients
1277                          *      (nfsrv_clienthighwater should be large enough
1278                          *       that this only occurs when clients fail to
1279                          *       use the same nfs_client_id4.id. Maybe somewhat
1280                          *       higher that the maximum number of clients that
1281                          *       will mount this server?)
1282                          * OR
1283                          * Lease has expired a very long time ago
1284                          * OR
1285                          * Lease has expired PLUS the number of opens + locks
1286                          * has exceeded 90% of capacity
1287                          *
1288                          * --> Mark for expiry. The actual expiry will be done
1289                          *     by an nfsd sometime soon.
1290                          */
1291                         clp->lc_flags |= LCL_EXPIREIT;
1292                         nfsrv_stablefirst.nsf_flags |=
1293                             (NFSNSF_NEEDLOCK | NFSNSF_EXPIREDCLIENT);
1294                     } else {
1295                         /*
1296                          * If there are no opens, increment no open tick cnt
1297                          * If time exceeds NFSNOOPEN, mark it to be thrown away
1298                          * otherwise, if there is an open, reset no open time
1299                          * Hopefully, this will avoid excessive re-creation
1300                          * of open owners and subsequent open confirms.
1301                          */
1302                         stp = LIST_FIRST(&clp->lc_open);
1303                         while (stp != LIST_END(&clp->lc_open)) {
1304                                 nstp = LIST_NEXT(stp, ls_list);
1305                                 if (LIST_EMPTY(&stp->ls_open)) {
1306                                         stp->ls_noopens++;
1307                                         if (stp->ls_noopens > NFSNOOPEN ||
1308                                             (nfsrv_openpluslock * 2) >
1309                                             nfsrv_v4statelimit)
1310                                                 nfsrv_stablefirst.nsf_flags |=
1311                                                         NFSNSF_NOOPENS;
1312                                 } else {
1313                                         stp->ls_noopens = 0;
1314                                 }
1315                                 stp = nstp;
1316                         }
1317                     }
1318                 }
1319                 clp = nclp;
1320             }
1321         }
1322         NFSUNLOCKSTATE();
1323         NFSLOCKV4ROOTMUTEX();
1324         nfsv4_relref(&nfsv4rootfs_lock);
1325         NFSUNLOCKV4ROOTMUTEX();
1326 }
1327
1328 /*
1329  * The following set of functions free up the various data structures.
1330  */
1331 /*
1332  * Clear out all open/lock state related to this nfsclient.
1333  * Caller must hold an exclusive lock on nfsv4rootfs_lock, so that
1334  * there are no other active nfsd threads.
1335  */
1336 void
1337 nfsrv_cleanclient(struct nfsclient *clp, NFSPROC_T *p)
1338 {
1339         struct nfsstate *stp, *nstp;
1340         struct nfsdsession *sep, *nsep;
1341
1342         LIST_FOREACH_SAFE(stp, &clp->lc_open, ls_list, nstp)
1343                 nfsrv_freeopenowner(stp, 1, p);
1344         if ((clp->lc_flags & LCL_ADMINREVOKED) == 0)
1345                 LIST_FOREACH_SAFE(sep, &clp->lc_session, sess_list, nsep)
1346                         (void)nfsrv_freesession(sep, NULL);
1347 }
1348
1349 /*
1350  * Free a client that has been cleaned. It should also already have been
1351  * removed from the lists.
1352  * (Just to be safe w.r.t. newnfs_disconnect(), call this function when
1353  *  softclock interrupts are enabled.)
1354  */
1355 void
1356 nfsrv_zapclient(struct nfsclient *clp, NFSPROC_T *p)
1357 {
1358
1359 #ifdef notyet
1360         if ((clp->lc_flags & (LCL_GSS | LCL_CALLBACKSON)) ==
1361              (LCL_GSS | LCL_CALLBACKSON) &&
1362             (clp->lc_hand.nfsh_flag & NFSG_COMPLETE) &&
1363             clp->lc_handlelen > 0) {
1364                 clp->lc_hand.nfsh_flag &= ~NFSG_COMPLETE;
1365                 clp->lc_hand.nfsh_flag |= NFSG_DESTROYED;
1366                 (void) nfsrv_docallback(clp, NFSV4PROC_CBNULL,
1367                         NULL, 0, NULL, NULL, NULL, 0, p);
1368         }
1369 #endif
1370         newnfs_disconnect(&clp->lc_req);
1371         free(clp->lc_req.nr_nam, M_SONAME);
1372         NFSFREEMUTEX(&clp->lc_req.nr_mtx);
1373         free(clp->lc_stateid, M_NFSDCLIENT);
1374         free(clp, M_NFSDCLIENT);
1375         NFSLOCKSTATE();
1376         nfsstatsv1.srvclients--;
1377         nfsrv_openpluslock--;
1378         nfsrv_clients--;
1379         NFSUNLOCKSTATE();
1380 }
1381
1382 /*
1383  * Free a list of delegation state structures.
1384  * (This function will also free all nfslockfile structures that no
1385  *  longer have associated state.)
1386  */
1387 void
1388 nfsrv_freedeleglist(struct nfsstatehead *sthp)
1389 {
1390         struct nfsstate *stp, *nstp;
1391
1392         LIST_FOREACH_SAFE(stp, sthp, ls_list, nstp) {
1393                 nfsrv_freedeleg(stp);
1394         }
1395         LIST_INIT(sthp);
1396 }
1397
1398 /*
1399  * Free up a delegation.
1400  */
1401 static void
1402 nfsrv_freedeleg(struct nfsstate *stp)
1403 {
1404         struct nfslockfile *lfp;
1405
1406         LIST_REMOVE(stp, ls_hash);
1407         LIST_REMOVE(stp, ls_list);
1408         LIST_REMOVE(stp, ls_file);
1409         if ((stp->ls_flags & NFSLCK_DELEGWRITE) != 0)
1410                 nfsrv_writedelegcnt--;
1411         lfp = stp->ls_lfp;
1412         if (LIST_EMPTY(&lfp->lf_open) &&
1413             LIST_EMPTY(&lfp->lf_lock) && LIST_EMPTY(&lfp->lf_deleg) &&
1414             LIST_EMPTY(&lfp->lf_locallock) && LIST_EMPTY(&lfp->lf_rollback) &&
1415             lfp->lf_usecount == 0 &&
1416             nfsv4_testlock(&lfp->lf_locallock_lck) == 0)
1417                 nfsrv_freenfslockfile(lfp);
1418         free(stp, M_NFSDSTATE);
1419         nfsstatsv1.srvdelegates--;
1420         nfsrv_openpluslock--;
1421         nfsrv_delegatecnt--;
1422 }
1423
1424 /*
1425  * This function frees an open owner and all associated opens.
1426  */
1427 static void
1428 nfsrv_freeopenowner(struct nfsstate *stp, int cansleep, NFSPROC_T *p)
1429 {
1430         struct nfsstate *nstp, *tstp;
1431
1432         LIST_REMOVE(stp, ls_list);
1433         /*
1434          * Now, free all associated opens.
1435          */
1436         nstp = LIST_FIRST(&stp->ls_open);
1437         while (nstp != LIST_END(&stp->ls_open)) {
1438                 tstp = nstp;
1439                 nstp = LIST_NEXT(nstp, ls_list);
1440                 (void) nfsrv_freeopen(tstp, NULL, cansleep, p);
1441         }
1442         if (stp->ls_op)
1443                 nfsrvd_derefcache(stp->ls_op);
1444         free(stp, M_NFSDSTATE);
1445         nfsstatsv1.srvopenowners--;
1446         nfsrv_openpluslock--;
1447 }
1448
1449 /*
1450  * This function frees an open (nfsstate open structure) with all associated
1451  * lock_owners and locks. It also frees the nfslockfile structure iff there
1452  * are no other opens on the file.
1453  * Returns 1 if it free'd the nfslockfile, 0 otherwise.
1454  */
1455 static int
1456 nfsrv_freeopen(struct nfsstate *stp, vnode_t vp, int cansleep, NFSPROC_T *p)
1457 {
1458         struct nfsstate *nstp, *tstp;
1459         struct nfslockfile *lfp;
1460         int ret;
1461
1462         LIST_REMOVE(stp, ls_hash);
1463         LIST_REMOVE(stp, ls_list);
1464         LIST_REMOVE(stp, ls_file);
1465
1466         lfp = stp->ls_lfp;
1467         /*
1468          * Now, free all lockowners associated with this open.
1469          */
1470         LIST_FOREACH_SAFE(tstp, &stp->ls_open, ls_list, nstp)
1471                 nfsrv_freelockowner(tstp, vp, cansleep, p);
1472
1473         /*
1474          * The nfslockfile is freed here if there are no locks
1475          * associated with the open.
1476          * If there are locks associated with the open, the
1477          * nfslockfile structure can be freed via nfsrv_freelockowner().
1478          * Acquire the state mutex to avoid races with calls to
1479          * nfsrv_getlockfile().
1480          */
1481         if (cansleep != 0)
1482                 NFSLOCKSTATE();
1483         if (lfp != NULL && LIST_EMPTY(&lfp->lf_open) &&
1484             LIST_EMPTY(&lfp->lf_deleg) && LIST_EMPTY(&lfp->lf_lock) &&
1485             LIST_EMPTY(&lfp->lf_locallock) && LIST_EMPTY(&lfp->lf_rollback) &&
1486             lfp->lf_usecount == 0 &&
1487             (cansleep != 0 || nfsv4_testlock(&lfp->lf_locallock_lck) == 0)) {
1488                 nfsrv_freenfslockfile(lfp);
1489                 ret = 1;
1490         } else
1491                 ret = 0;
1492         if (cansleep != 0)
1493                 NFSUNLOCKSTATE();
1494         free(stp, M_NFSDSTATE);
1495         nfsstatsv1.srvopens--;
1496         nfsrv_openpluslock--;
1497         return (ret);
1498 }
1499
1500 /*
1501  * Frees a lockowner and all associated locks.
1502  */
1503 static void
1504 nfsrv_freelockowner(struct nfsstate *stp, vnode_t vp, int cansleep,
1505     NFSPROC_T *p)
1506 {
1507
1508         LIST_REMOVE(stp, ls_hash);
1509         LIST_REMOVE(stp, ls_list);
1510         nfsrv_freeallnfslocks(stp, vp, cansleep, p);
1511         if (stp->ls_op)
1512                 nfsrvd_derefcache(stp->ls_op);
1513         free(stp, M_NFSDSTATE);
1514         nfsstatsv1.srvlockowners--;
1515         nfsrv_openpluslock--;
1516 }
1517
1518 /*
1519  * Free all the nfs locks on a lockowner.
1520  */
1521 static void
1522 nfsrv_freeallnfslocks(struct nfsstate *stp, vnode_t vp, int cansleep,
1523     NFSPROC_T *p)
1524 {
1525         struct nfslock *lop, *nlop;
1526         struct nfsrollback *rlp, *nrlp;
1527         struct nfslockfile *lfp = NULL;
1528         int gottvp = 0;
1529         vnode_t tvp = NULL;
1530         uint64_t first, end;
1531
1532         if (vp != NULL)
1533                 ASSERT_VOP_UNLOCKED(vp, "nfsrv_freeallnfslocks: vnode locked");
1534         lop = LIST_FIRST(&stp->ls_lock);
1535         while (lop != LIST_END(&stp->ls_lock)) {
1536                 nlop = LIST_NEXT(lop, lo_lckowner);
1537                 /*
1538                  * Since all locks should be for the same file, lfp should
1539                  * not change.
1540                  */
1541                 if (lfp == NULL)
1542                         lfp = lop->lo_lfp;
1543                 else if (lfp != lop->lo_lfp)
1544                         panic("allnfslocks");
1545                 /*
1546                  * If vp is NULL and cansleep != 0, a vnode must be acquired
1547                  * from the file handle. This only occurs when called from
1548                  * nfsrv_cleanclient().
1549                  */
1550                 if (gottvp == 0) {
1551                         if (nfsrv_dolocallocks == 0)
1552                                 tvp = NULL;
1553                         else if (vp == NULL && cansleep != 0) {
1554                                 tvp = nfsvno_getvp(&lfp->lf_fh);
1555                                 if (tvp != NULL)
1556                                         NFSVOPUNLOCK(tvp);
1557                         } else
1558                                 tvp = vp;
1559                         gottvp = 1;
1560                 }
1561
1562                 if (tvp != NULL) {
1563                         if (cansleep == 0)
1564                                 panic("allnfs2");
1565                         first = lop->lo_first;
1566                         end = lop->lo_end;
1567                         nfsrv_freenfslock(lop);
1568                         nfsrv_localunlock(tvp, lfp, first, end, p);
1569                         LIST_FOREACH_SAFE(rlp, &lfp->lf_rollback, rlck_list,
1570                             nrlp)
1571                                 free(rlp, M_NFSDROLLBACK);
1572                         LIST_INIT(&lfp->lf_rollback);
1573                 } else
1574                         nfsrv_freenfslock(lop);
1575                 lop = nlop;
1576         }
1577         if (vp == NULL && tvp != NULL)
1578                 vrele(tvp);
1579 }
1580
1581 /*
1582  * Free an nfslock structure.
1583  */
1584 static void
1585 nfsrv_freenfslock(struct nfslock *lop)
1586 {
1587
1588         if (lop->lo_lckfile.le_prev != NULL) {
1589                 LIST_REMOVE(lop, lo_lckfile);
1590                 nfsstatsv1.srvlocks--;
1591                 nfsrv_openpluslock--;
1592         }
1593         LIST_REMOVE(lop, lo_lckowner);
1594         free(lop, M_NFSDLOCK);
1595 }
1596
1597 /*
1598  * This function frees an nfslockfile structure.
1599  */
1600 static void
1601 nfsrv_freenfslockfile(struct nfslockfile *lfp)
1602 {
1603
1604         LIST_REMOVE(lfp, lf_hash);
1605         free(lfp, M_NFSDLOCKFILE);
1606 }
1607
1608 /*
1609  * This function looks up an nfsstate structure via stateid.
1610  */
1611 static int
1612 nfsrv_getstate(struct nfsclient *clp, nfsv4stateid_t *stateidp, __unused u_int32_t flags,
1613     struct nfsstate **stpp)
1614 {
1615         struct nfsstate *stp;
1616         struct nfsstatehead *hp;
1617         int error = 0;
1618
1619         *stpp = NULL;
1620         hp = NFSSTATEHASH(clp, *stateidp);
1621         LIST_FOREACH(stp, hp, ls_hash) {
1622                 if (!NFSBCMP(stp->ls_stateid.other, stateidp->other,
1623                         NFSX_STATEIDOTHER))
1624                         break;
1625         }
1626
1627         /*
1628          * If no state id in list, return NFSERR_BADSTATEID.
1629          */
1630         if (stp == LIST_END(hp)) {
1631                 error = NFSERR_BADSTATEID;
1632                 goto out;
1633         }
1634         *stpp = stp;
1635
1636 out:
1637         NFSEXITCODE(error);
1638         return (error);
1639 }
1640
1641 /*
1642  * This function gets an nfsstate structure via owner string.
1643  */
1644 static void
1645 nfsrv_getowner(struct nfsstatehead *hp, struct nfsstate *new_stp,
1646     struct nfsstate **stpp)
1647 {
1648         struct nfsstate *stp;
1649
1650         *stpp = NULL;
1651         LIST_FOREACH(stp, hp, ls_list) {
1652                 if (new_stp->ls_ownerlen == stp->ls_ownerlen &&
1653                   !NFSBCMP(new_stp->ls_owner,stp->ls_owner,stp->ls_ownerlen)) {
1654                         *stpp = stp;
1655                         return;
1656                 }
1657         }
1658 }
1659
1660 /*
1661  * Lock control function called to update lock status.
1662  * Returns 0 upon success, -1 if there is no lock and the flags indicate
1663  * that one isn't to be created and an NFSERR_xxx for other errors.
1664  * The structures new_stp and new_lop are passed in as pointers that should
1665  * be set to NULL if the structure is used and shouldn't be free'd.
1666  * For the NFSLCK_TEST and NFSLCK_CHECK cases, the structures are
1667  * never used and can safely be allocated on the stack. For all other
1668  * cases, *new_stpp and *new_lopp should be malloc'd before the call,
1669  * in case they are used.
1670  */
1671 int
1672 nfsrv_lockctrl(vnode_t vp, struct nfsstate **new_stpp,
1673     struct nfslock **new_lopp, struct nfslockconflict *cfp,
1674     nfsquad_t clientid, nfsv4stateid_t *stateidp,
1675     __unused struct nfsexstuff *exp,
1676     struct nfsrv_descript *nd, NFSPROC_T *p)
1677 {
1678         struct nfslock *lop;
1679         struct nfsstate *new_stp = *new_stpp;
1680         struct nfslock *new_lop = *new_lopp;
1681         struct nfsstate *tstp, *mystp, *nstp;
1682         int specialid = 0;
1683         struct nfslockfile *lfp;
1684         struct nfslock *other_lop = NULL;
1685         struct nfsstate *stp, *lckstp = NULL;
1686         struct nfsclient *clp = NULL;
1687         u_int32_t bits;
1688         int error = 0, haslock = 0, ret, reterr;
1689         int getlckret, delegation = 0, filestruct_locked, vnode_unlocked = 0;
1690         fhandle_t nfh;
1691         uint64_t first, end;
1692         uint32_t lock_flags;
1693
1694         if (new_stp->ls_flags & (NFSLCK_CHECK | NFSLCK_SETATTR)) {
1695                 /*
1696                  * Note the special cases of "all 1s" or "all 0s" stateids and
1697                  * let reads with all 1s go ahead.
1698                  */
1699                 if (new_stp->ls_stateid.seqid == 0x0 &&
1700                     new_stp->ls_stateid.other[0] == 0x0 &&
1701                     new_stp->ls_stateid.other[1] == 0x0 &&
1702                     new_stp->ls_stateid.other[2] == 0x0)
1703                         specialid = 1;
1704                 else if (new_stp->ls_stateid.seqid == 0xffffffff &&
1705                     new_stp->ls_stateid.other[0] == 0xffffffff &&
1706                     new_stp->ls_stateid.other[1] == 0xffffffff &&
1707                     new_stp->ls_stateid.other[2] == 0xffffffff)
1708                         specialid = 2;
1709         }
1710
1711         /*
1712          * Check for restart conditions (client and server).
1713          */
1714         error = nfsrv_checkrestart(clientid, new_stp->ls_flags,
1715             &new_stp->ls_stateid, specialid);
1716         if (error)
1717                 goto out;
1718
1719         /*
1720          * Check for state resource limit exceeded.
1721          */
1722         if ((new_stp->ls_flags & NFSLCK_LOCK) &&
1723             nfsrv_openpluslock > nfsrv_v4statelimit) {
1724                 error = NFSERR_RESOURCE;
1725                 goto out;
1726         }
1727
1728         /*
1729          * For the lock case, get another nfslock structure,
1730          * just in case we need it.
1731          * Malloc now, before we start sifting through the linked lists,
1732          * in case we have to wait for memory.
1733          */
1734 tryagain:
1735         if (new_stp->ls_flags & NFSLCK_LOCK)
1736                 other_lop = malloc(sizeof (struct nfslock),
1737                     M_NFSDLOCK, M_WAITOK);
1738         filestruct_locked = 0;
1739         reterr = 0;
1740         lfp = NULL;
1741
1742         /*
1743          * Get the lockfile structure for CFH now, so we can do a sanity
1744          * check against the stateid, before incrementing the seqid#, since
1745          * we want to return NFSERR_BADSTATEID on failure and the seqid#
1746          * shouldn't be incremented for this case.
1747          * If nfsrv_getlockfile() returns -1, it means "not found", which
1748          * will be handled later.
1749          * If we are doing Lock/LockU and local locking is enabled, sleep
1750          * lock the nfslockfile structure.
1751          */
1752         getlckret = nfsrv_getlockfh(vp, new_stp->ls_flags, NULL, &nfh, p);
1753         NFSLOCKSTATE();
1754         if (getlckret == 0) {
1755                 if ((new_stp->ls_flags & (NFSLCK_LOCK | NFSLCK_UNLOCK)) != 0 &&
1756                     nfsrv_dolocallocks != 0 && nd->nd_repstat == 0) {
1757                         getlckret = nfsrv_getlockfile(new_stp->ls_flags, NULL,
1758                             &lfp, &nfh, 1);
1759                         if (getlckret == 0)
1760                                 filestruct_locked = 1;
1761                 } else
1762                         getlckret = nfsrv_getlockfile(new_stp->ls_flags, NULL,
1763                             &lfp, &nfh, 0);
1764         }
1765         if (getlckret != 0 && getlckret != -1)
1766                 reterr = getlckret;
1767
1768         if (filestruct_locked != 0) {
1769                 LIST_INIT(&lfp->lf_rollback);
1770                 if ((new_stp->ls_flags & NFSLCK_LOCK)) {
1771                         /*
1772                          * For local locking, do the advisory locking now, so
1773                          * that any conflict can be detected. A failure later
1774                          * can be rolled back locally. If an error is returned,
1775                          * struct nfslockfile has been unlocked and any local
1776                          * locking rolled back.
1777                          */
1778                         NFSUNLOCKSTATE();
1779                         if (vnode_unlocked == 0) {
1780                                 ASSERT_VOP_ELOCKED(vp, "nfsrv_lockctrl1");
1781                                 vnode_unlocked = 1;
1782                                 NFSVOPUNLOCK(vp);
1783                         }
1784                         reterr = nfsrv_locallock(vp, lfp,
1785                             (new_lop->lo_flags & (NFSLCK_READ | NFSLCK_WRITE)),
1786                             new_lop->lo_first, new_lop->lo_end, cfp, p);
1787                         NFSLOCKSTATE();
1788                 }
1789         }
1790
1791         if (specialid == 0) {
1792             if (new_stp->ls_flags & NFSLCK_TEST) {
1793                 /*
1794                  * RFC 3530 does not list LockT as an op that renews a
1795                  * lease, but the consensus seems to be that it is ok
1796                  * for a server to do so.
1797                  */
1798                 error = nfsrv_getclient(clientid, CLOPS_RENEW, &clp, NULL,
1799                     (nfsquad_t)((u_quad_t)0), 0, nd, p);
1800
1801                 /*
1802                  * Since NFSERR_EXPIRED, NFSERR_ADMINREVOKED are not valid
1803                  * error returns for LockT, just go ahead and test for a lock,
1804                  * since there are no locks for this client, but other locks
1805                  * can conflict. (ie. same client will always be false)
1806                  */
1807                 if (error == NFSERR_EXPIRED || error == NFSERR_ADMINREVOKED)
1808                     error = 0;
1809                 lckstp = new_stp;
1810             } else {
1811               error = nfsrv_getclient(clientid, CLOPS_RENEW, &clp, NULL,
1812                 (nfsquad_t)((u_quad_t)0), 0, nd, p);
1813               if (error == 0)
1814                 /*
1815                  * Look up the stateid
1816                  */
1817                 error = nfsrv_getstate(clp, &new_stp->ls_stateid,
1818                   new_stp->ls_flags, &stp);
1819               /*
1820                * do some sanity checks for an unconfirmed open or a
1821                * stateid that refers to the wrong file, for an open stateid
1822                */
1823               if (error == 0 && (stp->ls_flags & NFSLCK_OPEN) &&
1824                   ((stp->ls_openowner->ls_flags & NFSLCK_NEEDSCONFIRM) ||
1825                    (getlckret == 0 && stp->ls_lfp != lfp))){
1826                       /*
1827                        * NFSLCK_SETATTR should return OK rather than NFSERR_BADSTATEID
1828                        * The only exception is using SETATTR with SIZE.
1829                        * */
1830                     if ((new_stp->ls_flags &
1831                          (NFSLCK_SETATTR | NFSLCK_CHECK)) != NFSLCK_SETATTR)
1832                              error = NFSERR_BADSTATEID;
1833               }
1834               
1835                 if (error == 0 &&
1836                   (stp->ls_flags & (NFSLCK_DELEGREAD | NFSLCK_DELEGWRITE)) &&
1837                   getlckret == 0 && stp->ls_lfp != lfp)
1838                         error = NFSERR_BADSTATEID;
1839
1840               /*
1841                * If the lockowner stateid doesn't refer to the same file,
1842                * I believe that is considered ok, since some clients will
1843                * only create a single lockowner and use that for all locks
1844                * on all files.
1845                * For now, log it as a diagnostic, instead of considering it
1846                * a BadStateid.
1847                */
1848               if (error == 0 && (stp->ls_flags &
1849                   (NFSLCK_OPEN | NFSLCK_DELEGREAD | NFSLCK_DELEGWRITE)) == 0 &&
1850                   getlckret == 0 && stp->ls_lfp != lfp) {
1851 #ifdef DIAGNOSTIC
1852                   printf("Got a lock statid for different file open\n");
1853 #endif
1854                   /*
1855                   error = NFSERR_BADSTATEID;
1856                   */
1857               }
1858
1859               if (error == 0) {
1860                     if (new_stp->ls_flags & NFSLCK_OPENTOLOCK) {
1861                         /*
1862                          * If haslock set, we've already checked the seqid.
1863                          */
1864                         if (!haslock) {
1865                             if (stp->ls_flags & NFSLCK_OPEN)
1866                                 error = nfsrv_checkseqid(nd, new_stp->ls_seq,
1867                                     stp->ls_openowner, new_stp->ls_op);
1868                             else
1869                                 error = NFSERR_BADSTATEID;
1870                         }
1871                         if (!error)
1872                             nfsrv_getowner(&stp->ls_open, new_stp, &lckstp);
1873                         if (lckstp) {
1874                             /*
1875                              * For NFSv4.1 and NFSv4.2 allow an
1876                              * open_to_lock_owner when the lock_owner already
1877                              * exists.  Just clear NFSLCK_OPENTOLOCK so that
1878                              * a new lock_owner will not be created.
1879                              * RFC7530 states that the error for NFSv4.0
1880                              * is NFS4ERR_BAD_SEQID.
1881                              */
1882                             if ((nd->nd_flag & ND_NFSV41) != 0)
1883                                 new_stp->ls_flags &= ~NFSLCK_OPENTOLOCK;
1884                             else
1885                                 error = NFSERR_BADSEQID;
1886                         } else
1887                             lckstp = new_stp;
1888                     } else if (new_stp->ls_flags&(NFSLCK_LOCK|NFSLCK_UNLOCK)) {
1889                         /*
1890                          * If haslock set, ditto above.
1891                          */
1892                         if (!haslock) {
1893                             if (stp->ls_flags & NFSLCK_OPEN)
1894                                 error = NFSERR_BADSTATEID;
1895                             else
1896                                 error = nfsrv_checkseqid(nd, new_stp->ls_seq,
1897                                     stp, new_stp->ls_op);
1898                         }
1899                         lckstp = stp;
1900                     } else {
1901                         lckstp = stp;
1902                     }
1903               }
1904               /*
1905                * If the seqid part of the stateid isn't the same, return
1906                * NFSERR_OLDSTATEID for cases other than I/O Ops.
1907                * For I/O Ops, only return NFSERR_OLDSTATEID if
1908                * nfsrv_returnoldstateid is set. (The consensus on the email
1909                * list was that most clients would prefer to not receive
1910                * NFSERR_OLDSTATEID for I/O Ops, but the RFC suggests that that
1911                * is what will happen, so I use the nfsrv_returnoldstateid to
1912                * allow for either server configuration.)
1913                */
1914               if (!error && stp->ls_stateid.seqid!=new_stp->ls_stateid.seqid &&
1915                   (((nd->nd_flag & ND_NFSV41) == 0 &&
1916                    (!(new_stp->ls_flags & NFSLCK_CHECK) ||
1917                     nfsrv_returnoldstateid)) ||
1918                    ((nd->nd_flag & ND_NFSV41) != 0 &&
1919                     new_stp->ls_stateid.seqid != 0)))
1920                     error = NFSERR_OLDSTATEID;
1921             }
1922         }
1923
1924         /*
1925          * Now we can check for grace.
1926          */
1927         if (!error)
1928                 error = nfsrv_checkgrace(nd, clp, new_stp->ls_flags);
1929         if ((new_stp->ls_flags & NFSLCK_RECLAIM) && !error &&
1930                 nfsrv_checkstable(clp))
1931                 error = NFSERR_NOGRACE;
1932         /*
1933          * If we successfully Reclaimed state, note that.
1934          */
1935         if ((new_stp->ls_flags & NFSLCK_RECLAIM) && !error)
1936                 nfsrv_markstable(clp);
1937
1938         /*
1939          * At this point, either error == NFSERR_BADSTATEID or the
1940          * seqid# has been updated, so we can return any error.
1941          * If error == 0, there may be an error in:
1942          *    nd_repstat - Set by the calling function.
1943          *    reterr - Set above, if getting the nfslockfile structure
1944          *       or acquiring the local lock failed.
1945          *    (If both of these are set, nd_repstat should probably be
1946          *     returned, since that error was detected before this
1947          *     function call.)
1948          */
1949         if (error != 0 || nd->nd_repstat != 0 || reterr != 0) {
1950                 if (error == 0) {
1951                         if (nd->nd_repstat != 0)
1952                                 error = nd->nd_repstat;
1953                         else
1954                                 error = reterr;
1955                 }
1956                 if (filestruct_locked != 0) {
1957                         /* Roll back local locks. */
1958                         NFSUNLOCKSTATE();
1959                         if (vnode_unlocked == 0) {
1960                                 ASSERT_VOP_ELOCKED(vp, "nfsrv_lockctrl2");
1961                                 vnode_unlocked = 1;
1962                                 NFSVOPUNLOCK(vp);
1963                         }
1964                         nfsrv_locallock_rollback(vp, lfp, p);
1965                         NFSLOCKSTATE();
1966                         nfsrv_unlocklf(lfp);
1967                 }
1968                 NFSUNLOCKSTATE();
1969                 goto out;
1970         }
1971
1972         /*
1973          * Check the nfsrv_getlockfile return.
1974          * Returned -1 if no structure found.
1975          */
1976         if (getlckret == -1) {
1977                 error = NFSERR_EXPIRED;
1978                 /*
1979                  * Called from lockt, so no lock is OK.
1980                  */
1981                 if (new_stp->ls_flags & NFSLCK_TEST) {
1982                         error = 0;
1983                 } else if (new_stp->ls_flags &
1984                     (NFSLCK_CHECK | NFSLCK_SETATTR)) {
1985                         /*
1986                          * Called to check for a lock, OK if the stateid is all
1987                          * 1s or all 0s, but there should be an nfsstate
1988                          * otherwise.
1989                          * (ie. If there is no open, I'll assume no share
1990                          *  deny bits.)
1991                          */
1992                         if (specialid)
1993                                 error = 0;
1994                         else
1995                                 error = NFSERR_BADSTATEID;
1996                 }
1997                 NFSUNLOCKSTATE();
1998                 goto out;
1999         }
2000
2001         /*
2002          * For NFSLCK_CHECK and NFSLCK_LOCK, test for a share conflict.
2003          * For NFSLCK_CHECK, allow a read if write access is granted,
2004          * but check for a deny. For NFSLCK_LOCK, require correct access,
2005          * which implies a conflicting deny can't exist.
2006          */
2007         if (new_stp->ls_flags & (NFSLCK_CHECK | NFSLCK_LOCK)) {
2008             /*
2009              * Four kinds of state id:
2010              * - specialid (all 0s or all 1s), only for NFSLCK_CHECK
2011              * - stateid for an open
2012              * - stateid for a delegation
2013              * - stateid for a lock owner
2014              */
2015             if (!specialid) {
2016                 if (stp->ls_flags & (NFSLCK_DELEGREAD | NFSLCK_DELEGWRITE)) {
2017                     delegation = 1;
2018                     mystp = stp;
2019                     nfsrv_delaydelegtimeout(stp);
2020                 } else if (stp->ls_flags & NFSLCK_OPEN) {
2021                     mystp = stp;
2022                 } else {
2023                     mystp = stp->ls_openstp;
2024                 }
2025                 /*
2026                  * If locking or checking, require correct access
2027                  * bit set.
2028                  */
2029                 if (((new_stp->ls_flags & NFSLCK_LOCK) &&
2030                      !((new_lop->lo_flags >> NFSLCK_LOCKSHIFT) &
2031                        mystp->ls_flags & NFSLCK_ACCESSBITS)) ||
2032                     ((new_stp->ls_flags & (NFSLCK_CHECK|NFSLCK_READACCESS)) ==
2033                       (NFSLCK_CHECK | NFSLCK_READACCESS) &&
2034                      !(mystp->ls_flags & NFSLCK_READACCESS) &&
2035                      nfsrv_allowreadforwriteopen == 0) ||
2036                     ((new_stp->ls_flags & (NFSLCK_CHECK|NFSLCK_WRITEACCESS)) ==
2037                       (NFSLCK_CHECK | NFSLCK_WRITEACCESS) &&
2038                      !(mystp->ls_flags & NFSLCK_WRITEACCESS))) {
2039                         if (filestruct_locked != 0) {
2040                                 /* Roll back local locks. */
2041                                 NFSUNLOCKSTATE();
2042                                 if (vnode_unlocked == 0) {
2043                                         ASSERT_VOP_ELOCKED(vp,
2044                                             "nfsrv_lockctrl3");
2045                                         vnode_unlocked = 1;
2046                                         NFSVOPUNLOCK(vp);
2047                                 }
2048                                 nfsrv_locallock_rollback(vp, lfp, p);
2049                                 NFSLOCKSTATE();
2050                                 nfsrv_unlocklf(lfp);
2051                         }
2052                         NFSUNLOCKSTATE();
2053                         error = NFSERR_OPENMODE;
2054                         goto out;
2055                 }
2056             } else
2057                 mystp = NULL;
2058             if ((new_stp->ls_flags & NFSLCK_CHECK) && !delegation) {
2059                 /*
2060                  * Check for a conflicting deny bit.
2061                  */
2062                 LIST_FOREACH(tstp, &lfp->lf_open, ls_file) {
2063                     if (tstp != mystp) {
2064                         bits = tstp->ls_flags;
2065                         bits >>= NFSLCK_SHIFT;
2066                         if (new_stp->ls_flags & bits & NFSLCK_ACCESSBITS) {
2067                             KASSERT(vnode_unlocked == 0,
2068                                 ("nfsrv_lockctrl: vnode unlocked1"));
2069                             ret = nfsrv_clientconflict(tstp->ls_clp, &haslock,
2070                                 vp, p);
2071                             if (ret == 1) {
2072                                 /*
2073                                 * nfsrv_clientconflict unlocks state
2074                                  * when it returns non-zero.
2075                                  */
2076                                 lckstp = NULL;
2077                                 goto tryagain;
2078                             }
2079                             if (ret == 0)
2080                                 NFSUNLOCKSTATE();
2081                             if (ret == 2)
2082                                 error = NFSERR_PERM;
2083                             else
2084                                 error = NFSERR_OPENMODE;
2085                             goto out;
2086                         }
2087                     }
2088                 }
2089
2090                 /* We're outta here */
2091                 NFSUNLOCKSTATE();
2092                 goto out;
2093             }
2094         }
2095
2096         /*
2097          * For setattr, just get rid of all the Delegations for other clients.
2098          */
2099         if (new_stp->ls_flags & NFSLCK_SETATTR) {
2100                 KASSERT(vnode_unlocked == 0,
2101                     ("nfsrv_lockctrl: vnode unlocked2"));
2102                 ret = nfsrv_cleandeleg(vp, lfp, clp, &haslock, p);
2103                 if (ret) {
2104                         /*
2105                          * nfsrv_cleandeleg() unlocks state when it
2106                          * returns non-zero.
2107                          */
2108                         if (ret == -1) {
2109                                 lckstp = NULL;
2110                                 goto tryagain;
2111                         }
2112                         error = ret;
2113                         goto out;
2114                 }
2115                 if (!(new_stp->ls_flags & NFSLCK_CHECK) ||
2116                     (LIST_EMPTY(&lfp->lf_open) && LIST_EMPTY(&lfp->lf_lock) &&
2117                      LIST_EMPTY(&lfp->lf_deleg))) {
2118                         NFSUNLOCKSTATE();
2119                         goto out;
2120                 }
2121         }
2122
2123         /*
2124          * Check for a conflicting delegation. If one is found, call
2125          * nfsrv_delegconflict() to handle it. If the v4root lock hasn't
2126          * been set yet, it will get the lock. Otherwise, it will recall
2127          * the delegation. Then, we try try again...
2128          * I currently believe the conflict algorithm to be:
2129          * For Lock Ops (Lock/LockT/LockU)
2130          * - there is a conflict iff a different client has a write delegation
2131          * For Reading (Read Op)
2132          * - there is a conflict iff a different client has a write delegation
2133          *   (the specialids are always a different client)
2134          * For Writing (Write/Setattr of size)
2135          * - there is a conflict if a different client has any delegation
2136          * - there is a conflict if the same client has a read delegation
2137          *   (I don't understand why this isn't allowed, but that seems to be
2138          *    the current consensus?)
2139          */
2140         tstp = LIST_FIRST(&lfp->lf_deleg);
2141         while (tstp != LIST_END(&lfp->lf_deleg)) {
2142             nstp = LIST_NEXT(tstp, ls_file);
2143             if ((((new_stp->ls_flags&(NFSLCK_LOCK|NFSLCK_UNLOCK|NFSLCK_TEST))||
2144                  ((new_stp->ls_flags & NFSLCK_CHECK) &&
2145                   (new_lop->lo_flags & NFSLCK_READ))) &&
2146                   clp != tstp->ls_clp &&
2147                  (tstp->ls_flags & NFSLCK_DELEGWRITE)) ||
2148                  ((new_stp->ls_flags & NFSLCK_CHECK) &&
2149                    (new_lop->lo_flags & NFSLCK_WRITE) &&
2150                   (clp != tstp->ls_clp ||
2151                    (tstp->ls_flags & NFSLCK_DELEGREAD)))) {
2152                 ret = 0;
2153                 if (filestruct_locked != 0) {
2154                         /* Roll back local locks. */
2155                         NFSUNLOCKSTATE();
2156                         if (vnode_unlocked == 0) {
2157                                 ASSERT_VOP_ELOCKED(vp, "nfsrv_lockctrl4");
2158                                 NFSVOPUNLOCK(vp);
2159                         }
2160                         nfsrv_locallock_rollback(vp, lfp, p);
2161                         NFSLOCKSTATE();
2162                         nfsrv_unlocklf(lfp);
2163                         NFSUNLOCKSTATE();
2164                         NFSVOPLOCK(vp, LK_EXCLUSIVE | LK_RETRY);
2165                         vnode_unlocked = 0;
2166                         if (VN_IS_DOOMED(vp))
2167                                 ret = NFSERR_SERVERFAULT;
2168                         NFSLOCKSTATE();
2169                 }
2170                 if (ret == 0)
2171                         ret = nfsrv_delegconflict(tstp, &haslock, p, vp);
2172                 if (ret) {
2173                     /*
2174                      * nfsrv_delegconflict unlocks state when it
2175                      * returns non-zero, which it always does.
2176                      */
2177                     if (other_lop) {
2178                         free(other_lop, M_NFSDLOCK);
2179                         other_lop = NULL;
2180                     }
2181                     if (ret == -1) {
2182                         lckstp = NULL;
2183                         goto tryagain;
2184                     }
2185                     error = ret;
2186                     goto out;
2187                 }
2188                 /* Never gets here. */
2189             }
2190             tstp = nstp;
2191         }
2192
2193         /*
2194          * Handle the unlock case by calling nfsrv_updatelock().
2195          * (Should I have done some access checking above for unlock? For now,
2196          *  just let it happen.)
2197          */
2198         if (new_stp->ls_flags & NFSLCK_UNLOCK) {
2199                 first = new_lop->lo_first;
2200                 end = new_lop->lo_end;
2201                 nfsrv_updatelock(stp, new_lopp, &other_lop, lfp);
2202                 stateidp->seqid = ++(stp->ls_stateid.seqid);
2203                 if ((nd->nd_flag & ND_NFSV41) != 0 && stateidp->seqid == 0)
2204                         stateidp->seqid = stp->ls_stateid.seqid = 1;
2205                 stateidp->other[0] = stp->ls_stateid.other[0];
2206                 stateidp->other[1] = stp->ls_stateid.other[1];
2207                 stateidp->other[2] = stp->ls_stateid.other[2];
2208                 if (filestruct_locked != 0) {
2209                         NFSUNLOCKSTATE();
2210                         if (vnode_unlocked == 0) {
2211                                 ASSERT_VOP_ELOCKED(vp, "nfsrv_lockctrl5");
2212                                 vnode_unlocked = 1;
2213                                 NFSVOPUNLOCK(vp);
2214                         }
2215                         /* Update the local locks. */
2216                         nfsrv_localunlock(vp, lfp, first, end, p);
2217                         NFSLOCKSTATE();
2218                         nfsrv_unlocklf(lfp);
2219                 }
2220                 NFSUNLOCKSTATE();
2221                 goto out;
2222         }
2223
2224         /*
2225          * Search for a conflicting lock. A lock conflicts if:
2226          * - the lock range overlaps and
2227          * - at least one lock is a write lock and
2228          * - it is not owned by the same lock owner
2229          */
2230         if (!delegation) {
2231           LIST_FOREACH(lop, &lfp->lf_lock, lo_lckfile) {
2232             if (new_lop->lo_end > lop->lo_first &&
2233                 new_lop->lo_first < lop->lo_end &&
2234                 (new_lop->lo_flags == NFSLCK_WRITE ||
2235                  lop->lo_flags == NFSLCK_WRITE) &&
2236                 lckstp != lop->lo_stp &&
2237                 (clp != lop->lo_stp->ls_clp ||
2238                  lckstp->ls_ownerlen != lop->lo_stp->ls_ownerlen ||
2239                  NFSBCMP(lckstp->ls_owner, lop->lo_stp->ls_owner,
2240                     lckstp->ls_ownerlen))) {
2241                 if (other_lop) {
2242                     free(other_lop, M_NFSDLOCK);
2243                     other_lop = NULL;
2244                 }
2245                 if (vnode_unlocked != 0)
2246                     ret = nfsrv_clientconflict(lop->lo_stp->ls_clp, &haslock,
2247                         NULL, p);
2248                 else
2249                     ret = nfsrv_clientconflict(lop->lo_stp->ls_clp, &haslock,
2250                         vp, p);
2251                 if (ret == 1) {
2252                     if (filestruct_locked != 0) {
2253                         if (vnode_unlocked == 0) {
2254                                 ASSERT_VOP_ELOCKED(vp, "nfsrv_lockctrl6");
2255                                 NFSVOPUNLOCK(vp);
2256                         }
2257                         /* Roll back local locks. */
2258                         nfsrv_locallock_rollback(vp, lfp, p);
2259                         NFSLOCKSTATE();
2260                         nfsrv_unlocklf(lfp);
2261                         NFSUNLOCKSTATE();
2262                         NFSVOPLOCK(vp, LK_EXCLUSIVE | LK_RETRY);
2263                         vnode_unlocked = 0;
2264                         if (VN_IS_DOOMED(vp)) {
2265                                 error = NFSERR_SERVERFAULT;
2266                                 goto out;
2267                         }
2268                     }
2269                     /*
2270                      * nfsrv_clientconflict() unlocks state when it
2271                      * returns non-zero.
2272                      */
2273                     lckstp = NULL;
2274                     goto tryagain;
2275                 }
2276                 /*
2277                  * Found a conflicting lock, so record the conflict and
2278                  * return the error.
2279                  */
2280                 if (cfp != NULL && ret == 0) {
2281                     cfp->cl_clientid.lval[0]=lop->lo_stp->ls_stateid.other[0];
2282                     cfp->cl_clientid.lval[1]=lop->lo_stp->ls_stateid.other[1];
2283                     cfp->cl_first = lop->lo_first;
2284                     cfp->cl_end = lop->lo_end;
2285                     cfp->cl_flags = lop->lo_flags;
2286                     cfp->cl_ownerlen = lop->lo_stp->ls_ownerlen;
2287                     NFSBCOPY(lop->lo_stp->ls_owner, cfp->cl_owner,
2288                         cfp->cl_ownerlen);
2289                 }
2290                 if (ret == 2)
2291                     error = NFSERR_PERM;
2292                 else if (new_stp->ls_flags & NFSLCK_RECLAIM)
2293                     error = NFSERR_RECLAIMCONFLICT;
2294                 else if (new_stp->ls_flags & NFSLCK_CHECK)
2295                     error = NFSERR_LOCKED;
2296                 else
2297                     error = NFSERR_DENIED;
2298                 if (filestruct_locked != 0 && ret == 0) {
2299                         /* Roll back local locks. */
2300                         NFSUNLOCKSTATE();
2301                         if (vnode_unlocked == 0) {
2302                                 ASSERT_VOP_ELOCKED(vp, "nfsrv_lockctrl7");
2303                                 vnode_unlocked = 1;
2304                                 NFSVOPUNLOCK(vp);
2305                         }
2306                         nfsrv_locallock_rollback(vp, lfp, p);
2307                         NFSLOCKSTATE();
2308                         nfsrv_unlocklf(lfp);
2309                 }
2310                 if (ret == 0)
2311                         NFSUNLOCKSTATE();
2312                 goto out;
2313             }
2314           }
2315         }
2316
2317         /*
2318          * We only get here if there was no lock that conflicted.
2319          */
2320         if (new_stp->ls_flags & (NFSLCK_TEST | NFSLCK_CHECK)) {
2321                 NFSUNLOCKSTATE();
2322                 goto out;
2323         }
2324
2325         /*
2326          * We only get here when we are creating or modifying a lock.
2327          * There are two variants:
2328          * - exist_lock_owner where lock_owner exists
2329          * - open_to_lock_owner with new lock_owner
2330          */
2331         first = new_lop->lo_first;
2332         end = new_lop->lo_end;
2333         lock_flags = new_lop->lo_flags;
2334         if (!(new_stp->ls_flags & NFSLCK_OPENTOLOCK)) {
2335                 nfsrv_updatelock(lckstp, new_lopp, &other_lop, lfp);
2336                 stateidp->seqid = ++(lckstp->ls_stateid.seqid);
2337                 if ((nd->nd_flag & ND_NFSV41) != 0 && stateidp->seqid == 0)
2338                         stateidp->seqid = lckstp->ls_stateid.seqid = 1;
2339                 stateidp->other[0] = lckstp->ls_stateid.other[0];
2340                 stateidp->other[1] = lckstp->ls_stateid.other[1];
2341                 stateidp->other[2] = lckstp->ls_stateid.other[2];
2342         } else {
2343                 /*
2344                  * The new open_to_lock_owner case.
2345                  * Link the new nfsstate into the lists.
2346                  */
2347                 new_stp->ls_seq = new_stp->ls_opentolockseq;
2348                 nfsrvd_refcache(new_stp->ls_op);
2349                 stateidp->seqid = new_stp->ls_stateid.seqid = 1;
2350                 stateidp->other[0] = new_stp->ls_stateid.other[0] =
2351                     clp->lc_clientid.lval[0];
2352                 stateidp->other[1] = new_stp->ls_stateid.other[1] =
2353                     clp->lc_clientid.lval[1];
2354                 stateidp->other[2] = new_stp->ls_stateid.other[2] =
2355                     nfsrv_nextstateindex(clp);
2356                 new_stp->ls_clp = clp;
2357                 LIST_INIT(&new_stp->ls_lock);
2358                 new_stp->ls_openstp = stp;
2359                 new_stp->ls_lfp = lfp;
2360                 nfsrv_insertlock(new_lop, (struct nfslock *)new_stp, new_stp,
2361                     lfp);
2362                 LIST_INSERT_HEAD(NFSSTATEHASH(clp, new_stp->ls_stateid),
2363                     new_stp, ls_hash);
2364                 LIST_INSERT_HEAD(&stp->ls_open, new_stp, ls_list);
2365                 *new_lopp = NULL;
2366                 *new_stpp = NULL;
2367                 nfsstatsv1.srvlockowners++;
2368                 nfsrv_openpluslock++;
2369         }
2370         if (filestruct_locked != 0) {
2371                 NFSUNLOCKSTATE();
2372                 nfsrv_locallock_commit(lfp, lock_flags, first, end);
2373                 NFSLOCKSTATE();
2374                 nfsrv_unlocklf(lfp);
2375         }
2376         NFSUNLOCKSTATE();
2377
2378 out:
2379         if (haslock) {
2380                 NFSLOCKV4ROOTMUTEX();
2381                 nfsv4_unlock(&nfsv4rootfs_lock, 1);
2382                 NFSUNLOCKV4ROOTMUTEX();
2383         }
2384         if (vnode_unlocked != 0) {
2385                 NFSVOPLOCK(vp, LK_EXCLUSIVE | LK_RETRY);
2386                 if (error == 0 && VN_IS_DOOMED(vp))
2387                         error = NFSERR_SERVERFAULT;
2388         }
2389         if (other_lop)
2390                 free(other_lop, M_NFSDLOCK);
2391         NFSEXITCODE2(error, nd);
2392         return (error);
2393 }
2394
2395 /*
2396  * Check for state errors for Open.
2397  * repstat is passed back out as an error if more critical errors
2398  * are not detected.
2399  */
2400 int
2401 nfsrv_opencheck(nfsquad_t clientid, nfsv4stateid_t *stateidp,
2402     struct nfsstate *new_stp, vnode_t vp, struct nfsrv_descript *nd,
2403     NFSPROC_T *p, int repstat)
2404 {
2405         struct nfsstate *stp, *nstp;
2406         struct nfsclient *clp;
2407         struct nfsstate *ownerstp;
2408         struct nfslockfile *lfp, *new_lfp;
2409         int error = 0, haslock = 0, ret, readonly = 0, getfhret = 0;
2410
2411         if ((new_stp->ls_flags & NFSLCK_SHAREBITS) == NFSLCK_READACCESS)
2412                 readonly = 1;
2413         /*
2414          * Check for restart conditions (client and server).
2415          */
2416         error = nfsrv_checkrestart(clientid, new_stp->ls_flags,
2417                 &new_stp->ls_stateid, 0);
2418         if (error)
2419                 goto out;
2420
2421         /*
2422          * Check for state resource limit exceeded.
2423          * Technically this should be SMP protected, but the worst
2424          * case error is "out by one or two" on the count when it
2425          * returns NFSERR_RESOURCE and the limit is just a rather
2426          * arbitrary high water mark, so no harm is done.
2427          */
2428         if (nfsrv_openpluslock > nfsrv_v4statelimit) {
2429                 error = NFSERR_RESOURCE;
2430                 goto out;
2431         }
2432
2433 tryagain:
2434         new_lfp = malloc(sizeof (struct nfslockfile),
2435             M_NFSDLOCKFILE, M_WAITOK);
2436         if (vp)
2437                 getfhret = nfsrv_getlockfh(vp, new_stp->ls_flags, new_lfp,
2438                     NULL, p);
2439         NFSLOCKSTATE();
2440         /*
2441          * Get the nfsclient structure.
2442          */
2443         error = nfsrv_getclient(clientid, CLOPS_RENEW, &clp, NULL,
2444             (nfsquad_t)((u_quad_t)0), 0, nd, p);
2445
2446         /*
2447          * Look up the open owner. See if it needs confirmation and
2448          * check the seq#, as required.
2449          */
2450         if (!error)
2451                 nfsrv_getowner(&clp->lc_open, new_stp, &ownerstp);
2452
2453         if (!error && ownerstp) {
2454                 error = nfsrv_checkseqid(nd, new_stp->ls_seq, ownerstp,
2455                     new_stp->ls_op);
2456                 /*
2457                  * If the OpenOwner hasn't been confirmed, assume the
2458                  * old one was a replay and this one is ok.
2459                  * See: RFC3530 Sec. 14.2.18.
2460                  */
2461                 if (error == NFSERR_BADSEQID &&
2462                     (ownerstp->ls_flags & NFSLCK_NEEDSCONFIRM))
2463                         error = 0;
2464         }
2465
2466         /*
2467          * Check for grace.
2468          */
2469         if (!error)
2470                 error = nfsrv_checkgrace(nd, clp, new_stp->ls_flags);
2471         if ((new_stp->ls_flags & NFSLCK_RECLAIM) && !error &&
2472                 nfsrv_checkstable(clp))
2473                 error = NFSERR_NOGRACE;
2474
2475         /*
2476          * If none of the above errors occurred, let repstat be
2477          * returned.
2478          */
2479         if (repstat && !error)
2480                 error = repstat;
2481         if (error) {
2482                 NFSUNLOCKSTATE();
2483                 if (haslock) {
2484                         NFSLOCKV4ROOTMUTEX();
2485                         nfsv4_unlock(&nfsv4rootfs_lock, 1);
2486                         NFSUNLOCKV4ROOTMUTEX();
2487                 }
2488                 free(new_lfp, M_NFSDLOCKFILE);
2489                 goto out;
2490         }
2491
2492         /*
2493          * If vp == NULL, the file doesn't exist yet, so return ok.
2494          * (This always happens on the first pass, so haslock must be 0.)
2495          */
2496         if (vp == NULL) {
2497                 NFSUNLOCKSTATE();
2498                 free(new_lfp, M_NFSDLOCKFILE);
2499                 goto out;
2500         }
2501
2502         /*
2503          * Get the structure for the underlying file.
2504          */
2505         if (getfhret)
2506                 error = getfhret;
2507         else
2508                 error = nfsrv_getlockfile(new_stp->ls_flags, &new_lfp, &lfp,
2509                     NULL, 0);
2510         if (new_lfp)
2511                 free(new_lfp, M_NFSDLOCKFILE);
2512         if (error) {
2513                 NFSUNLOCKSTATE();
2514                 if (haslock) {
2515                         NFSLOCKV4ROOTMUTEX();
2516                         nfsv4_unlock(&nfsv4rootfs_lock, 1);
2517                         NFSUNLOCKV4ROOTMUTEX();
2518                 }
2519                 goto out;
2520         }
2521
2522         /*
2523          * Search for a conflicting open/share.
2524          */
2525         if (new_stp->ls_flags & NFSLCK_DELEGCUR) {
2526             /*
2527              * For Delegate_Cur, search for the matching Delegation,
2528              * which indicates no conflict.
2529              * An old delegation should have been recovered by the
2530              * client doing a Claim_DELEGATE_Prev, so I won't let
2531              * it match and return NFSERR_EXPIRED. Should I let it
2532              * match?
2533              */
2534             LIST_FOREACH(stp, &lfp->lf_deleg, ls_file) {
2535                 if (!(stp->ls_flags & NFSLCK_OLDDELEG) &&
2536                     (((nd->nd_flag & ND_NFSV41) != 0 &&
2537                     stateidp->seqid == 0) ||
2538                     stateidp->seqid == stp->ls_stateid.seqid) &&
2539                     !NFSBCMP(stateidp->other, stp->ls_stateid.other,
2540                           NFSX_STATEIDOTHER))
2541                         break;
2542             }
2543             if (stp == LIST_END(&lfp->lf_deleg) ||
2544                 ((new_stp->ls_flags & NFSLCK_WRITEACCESS) &&
2545                  (stp->ls_flags & NFSLCK_DELEGREAD))) {
2546                 NFSUNLOCKSTATE();
2547                 if (haslock) {
2548                         NFSLOCKV4ROOTMUTEX();
2549                         nfsv4_unlock(&nfsv4rootfs_lock, 1);
2550                         NFSUNLOCKV4ROOTMUTEX();
2551                 }
2552                 error = NFSERR_EXPIRED;
2553                 goto out;
2554             }
2555         }
2556
2557         /*
2558          * Check for access/deny bit conflicts. I check for the same
2559          * owner as well, in case the client didn't bother.
2560          */
2561         LIST_FOREACH(stp, &lfp->lf_open, ls_file) {
2562                 if (!(new_stp->ls_flags & NFSLCK_DELEGCUR) &&
2563                     (((new_stp->ls_flags & NFSLCK_ACCESSBITS) &
2564                       ((stp->ls_flags>>NFSLCK_SHIFT) & NFSLCK_ACCESSBITS))||
2565                      ((stp->ls_flags & NFSLCK_ACCESSBITS) &
2566                       ((new_stp->ls_flags>>NFSLCK_SHIFT)&NFSLCK_ACCESSBITS)))){
2567                         ret = nfsrv_clientconflict(stp->ls_clp,&haslock,vp,p);
2568                         if (ret == 1) {
2569                                 /*
2570                                  * nfsrv_clientconflict() unlocks
2571                                  * state when it returns non-zero.
2572                                  */
2573                                 goto tryagain;
2574                         }
2575                         if (ret == 2)
2576                                 error = NFSERR_PERM;
2577                         else if (new_stp->ls_flags & NFSLCK_RECLAIM)
2578                                 error = NFSERR_RECLAIMCONFLICT;
2579                         else
2580                                 error = NFSERR_SHAREDENIED;
2581                         if (ret == 0)
2582                                 NFSUNLOCKSTATE();
2583                         if (haslock) {
2584                                 NFSLOCKV4ROOTMUTEX();
2585                                 nfsv4_unlock(&nfsv4rootfs_lock, 1);
2586                                 NFSUNLOCKV4ROOTMUTEX();
2587                         }
2588                         goto out;
2589                 }
2590         }
2591
2592         /*
2593          * Check for a conflicting delegation. If one is found, call
2594          * nfsrv_delegconflict() to handle it. If the v4root lock hasn't
2595          * been set yet, it will get the lock. Otherwise, it will recall
2596          * the delegation. Then, we try try again...
2597          * (If NFSLCK_DELEGCUR is set, it has a delegation, so there
2598          *  isn't a conflict.)
2599          * I currently believe the conflict algorithm to be:
2600          * For Open with Read Access and Deny None
2601          * - there is a conflict iff a different client has a write delegation
2602          * For Open with other Write Access or any Deny except None
2603          * - there is a conflict if a different client has any delegation
2604          * - there is a conflict if the same client has a read delegation
2605          *   (The current consensus is that this last case should be
2606          *    considered a conflict since the client with a read delegation
2607          *    could have done an Open with ReadAccess and WriteDeny
2608          *    locally and then not have checked for the WriteDeny.)
2609          * Don't check for a Reclaim, since that will be dealt with
2610          * by nfsrv_openctrl().
2611          */
2612         if (!(new_stp->ls_flags &
2613                 (NFSLCK_DELEGPREV | NFSLCK_DELEGCUR | NFSLCK_RECLAIM))) {
2614             stp = LIST_FIRST(&lfp->lf_deleg);
2615             while (stp != LIST_END(&lfp->lf_deleg)) {
2616                 nstp = LIST_NEXT(stp, ls_file);
2617                 if ((readonly && stp->ls_clp != clp &&
2618                        (stp->ls_flags & NFSLCK_DELEGWRITE)) ||
2619                     (!readonly && (stp->ls_clp != clp ||
2620                          (stp->ls_flags & NFSLCK_DELEGREAD)))) {
2621                         ret = nfsrv_delegconflict(stp, &haslock, p, vp);
2622                         if (ret) {
2623                             /*
2624                              * nfsrv_delegconflict() unlocks state
2625                              * when it returns non-zero.
2626                              */
2627                             if (ret == -1)
2628                                 goto tryagain;
2629                             error = ret;
2630                             goto out;
2631                         }
2632                 }
2633                 stp = nstp;
2634             }
2635         }
2636         NFSUNLOCKSTATE();
2637         if (haslock) {
2638                 NFSLOCKV4ROOTMUTEX();
2639                 nfsv4_unlock(&nfsv4rootfs_lock, 1);
2640                 NFSUNLOCKV4ROOTMUTEX();
2641         }
2642
2643 out:
2644         NFSEXITCODE2(error, nd);
2645         return (error);
2646 }
2647
2648 /*
2649  * Open control function to create/update open state for an open.
2650  */
2651 int
2652 nfsrv_openctrl(struct nfsrv_descript *nd, vnode_t vp,
2653     struct nfsstate **new_stpp, nfsquad_t clientid, nfsv4stateid_t *stateidp,
2654     nfsv4stateid_t *delegstateidp, u_int32_t *rflagsp, struct nfsexstuff *exp,
2655     NFSPROC_T *p, u_quad_t filerev)
2656 {
2657         struct nfsstate *new_stp = *new_stpp;
2658         struct nfsstate *stp, *nstp;
2659         struct nfsstate *openstp = NULL, *new_open, *ownerstp, *new_deleg;
2660         struct nfslockfile *lfp, *new_lfp;
2661         struct nfsclient *clp;
2662         int error = 0, haslock = 0, ret, delegate = 1, writedeleg = 1;
2663         int readonly = 0, cbret = 1, getfhret = 0;
2664         int gotstate = 0, len = 0;
2665         u_char *clidp = NULL;
2666
2667         if ((new_stp->ls_flags & NFSLCK_SHAREBITS) == NFSLCK_READACCESS)
2668                 readonly = 1;
2669         /*
2670          * Check for restart conditions (client and server).
2671          * (Paranoia, should have been detected by nfsrv_opencheck().)
2672          * If an error does show up, return NFSERR_EXPIRED, since the
2673          * the seqid# has already been incremented.
2674          */
2675         error = nfsrv_checkrestart(clientid, new_stp->ls_flags,
2676             &new_stp->ls_stateid, 0);
2677         if (error) {
2678                 printf("Nfsd: openctrl unexpected restart err=%d\n",
2679                     error);
2680                 error = NFSERR_EXPIRED;
2681                 goto out;
2682         }
2683
2684         clidp = malloc(NFSV4_OPAQUELIMIT, M_TEMP, M_WAITOK);
2685 tryagain:
2686         new_lfp = malloc(sizeof (struct nfslockfile),
2687             M_NFSDLOCKFILE, M_WAITOK);
2688         new_open = malloc(sizeof (struct nfsstate),
2689             M_NFSDSTATE, M_WAITOK);
2690         new_deleg = malloc(sizeof (struct nfsstate),
2691             M_NFSDSTATE, M_WAITOK);
2692         getfhret = nfsrv_getlockfh(vp, new_stp->ls_flags, new_lfp,
2693             NULL, p);
2694         NFSLOCKSTATE();
2695         /*
2696          * Get the client structure. Since the linked lists could be changed
2697          * by other nfsd processes if this process does a tsleep(), one of
2698          * two things must be done.
2699          * 1 - don't tsleep()
2700          * or
2701          * 2 - get the nfsv4_lock() { indicated by haslock == 1 }
2702          *     before using the lists, since this lock stops the other
2703          *     nfsd. This should only be used for rare cases, since it
2704          *     essentially single threads the nfsd.
2705          *     At this time, it is only done for cases where the stable
2706          *     storage file must be written prior to completion of state
2707          *     expiration.
2708          */
2709         error = nfsrv_getclient(clientid, CLOPS_RENEW, &clp, NULL,
2710             (nfsquad_t)((u_quad_t)0), 0, nd, p);
2711         if (!error && (clp->lc_flags & LCL_NEEDSCBNULL) &&
2712             clp->lc_program) {
2713                 /*
2714                  * This happens on the first open for a client
2715                  * that supports callbacks.
2716                  */
2717                 NFSUNLOCKSTATE();
2718                 /*
2719                  * Although nfsrv_docallback() will sleep, clp won't
2720                  * go away, since they are only removed when the
2721                  * nfsv4_lock() has blocked the nfsd threads. The
2722                  * fields in clp can change, but having multiple
2723                  * threads do this Null callback RPC should be
2724                  * harmless.
2725                  */
2726                 cbret = nfsrv_docallback(clp, NFSV4PROC_CBNULL,
2727                     NULL, 0, NULL, NULL, NULL, 0, p);
2728                 NFSLOCKSTATE();
2729                 clp->lc_flags &= ~LCL_NEEDSCBNULL;
2730                 if (!cbret)
2731                         clp->lc_flags |= LCL_CALLBACKSON;
2732         }
2733
2734         /*
2735          * Look up the open owner. See if it needs confirmation and
2736          * check the seq#, as required.
2737          */
2738         if (!error)
2739                 nfsrv_getowner(&clp->lc_open, new_stp, &ownerstp);
2740
2741         if (error) {
2742                 NFSUNLOCKSTATE();
2743                 printf("Nfsd: openctrl unexpected state err=%d\n",
2744                         error);
2745                 free(new_lfp, M_NFSDLOCKFILE);
2746                 free(new_open, M_NFSDSTATE);
2747                 free(new_deleg, M_NFSDSTATE);
2748                 if (haslock) {
2749                         NFSLOCKV4ROOTMUTEX();
2750                         nfsv4_unlock(&nfsv4rootfs_lock, 1);
2751                         NFSUNLOCKV4ROOTMUTEX();
2752                 }
2753                 error = NFSERR_EXPIRED;
2754                 goto out;
2755         }
2756
2757         if (new_stp->ls_flags & NFSLCK_RECLAIM)
2758                 nfsrv_markstable(clp);
2759
2760         /*
2761          * Get the structure for the underlying file.
2762          */
2763         if (getfhret)
2764                 error = getfhret;
2765         else
2766                 error = nfsrv_getlockfile(new_stp->ls_flags, &new_lfp, &lfp,
2767                     NULL, 0);
2768         if (new_lfp)
2769                 free(new_lfp, M_NFSDLOCKFILE);
2770         if (error) {
2771                 NFSUNLOCKSTATE();
2772                 printf("Nfsd openctrl unexpected getlockfile err=%d\n",
2773                     error);
2774                 free(new_open, M_NFSDSTATE);
2775                 free(new_deleg, M_NFSDSTATE);
2776                 if (haslock) {
2777                         NFSLOCKV4ROOTMUTEX();
2778                         nfsv4_unlock(&nfsv4rootfs_lock, 1);
2779                         NFSUNLOCKV4ROOTMUTEX();
2780                 }
2781                 goto out;
2782         }
2783
2784         /*
2785          * Search for a conflicting open/share.
2786          */
2787         if (new_stp->ls_flags & NFSLCK_DELEGCUR) {
2788             /*
2789              * For Delegate_Cur, search for the matching Delegation,
2790              * which indicates no conflict.
2791              * An old delegation should have been recovered by the
2792              * client doing a Claim_DELEGATE_Prev, so I won't let
2793              * it match and return NFSERR_EXPIRED. Should I let it
2794              * match?
2795              */
2796             LIST_FOREACH(stp, &lfp->lf_deleg, ls_file) {
2797                 if (!(stp->ls_flags & NFSLCK_OLDDELEG) &&
2798                     (((nd->nd_flag & ND_NFSV41) != 0 &&
2799                     stateidp->seqid == 0) ||
2800                     stateidp->seqid == stp->ls_stateid.seqid) &&
2801                     !NFSBCMP(stateidp->other, stp->ls_stateid.other,
2802                         NFSX_STATEIDOTHER))
2803                         break;
2804             }
2805             if (stp == LIST_END(&lfp->lf_deleg) ||
2806                 ((new_stp->ls_flags & NFSLCK_WRITEACCESS) &&
2807                  (stp->ls_flags & NFSLCK_DELEGREAD))) {
2808                 NFSUNLOCKSTATE();
2809                 printf("Nfsd openctrl unexpected expiry\n");
2810                 free(new_open, M_NFSDSTATE);
2811                 free(new_deleg, M_NFSDSTATE);
2812                 if (haslock) {
2813                         NFSLOCKV4ROOTMUTEX();
2814                         nfsv4_unlock(&nfsv4rootfs_lock, 1);
2815                         NFSUNLOCKV4ROOTMUTEX();
2816                 }
2817                 error = NFSERR_EXPIRED;
2818                 goto out;
2819             }
2820
2821             /*
2822              * Don't issue a Delegation, since one already exists and
2823              * delay delegation timeout, as required.
2824              */
2825             delegate = 0;
2826             nfsrv_delaydelegtimeout(stp);
2827         }
2828
2829         /*
2830          * Check for access/deny bit conflicts. I also check for the
2831          * same owner, since the client might not have bothered to check.
2832          * Also, note an open for the same file and owner, if found,
2833          * which is all we do here for Delegate_Cur, since conflict
2834          * checking is already done.
2835          */
2836         LIST_FOREACH(stp, &lfp->lf_open, ls_file) {
2837                 if (ownerstp && stp->ls_openowner == ownerstp)
2838                         openstp = stp;
2839                 if (!(new_stp->ls_flags & NFSLCK_DELEGCUR)) {
2840                     /*
2841                      * If another client has the file open, the only
2842                      * delegation that can be issued is a Read delegation
2843                      * and only if it is a Read open with Deny none.
2844                      */
2845                     if (clp != stp->ls_clp) {
2846                         if ((stp->ls_flags & NFSLCK_SHAREBITS) ==
2847                             NFSLCK_READACCESS)
2848                             writedeleg = 0;
2849                         else
2850                             delegate = 0;
2851                     }
2852                     if(((new_stp->ls_flags & NFSLCK_ACCESSBITS) &
2853                         ((stp->ls_flags>>NFSLCK_SHIFT) & NFSLCK_ACCESSBITS))||
2854                        ((stp->ls_flags & NFSLCK_ACCESSBITS) &
2855                         ((new_stp->ls_flags>>NFSLCK_SHIFT)&NFSLCK_ACCESSBITS))){
2856                         ret = nfsrv_clientconflict(stp->ls_clp,&haslock,vp,p);
2857                         if (ret == 1) {
2858                                 /*
2859                                  * nfsrv_clientconflict() unlocks state
2860                                  * when it returns non-zero.
2861                                  */
2862                                 free(new_open, M_NFSDSTATE);
2863                                 free(new_deleg, M_NFSDSTATE);
2864                                 openstp = NULL;
2865                                 goto tryagain;
2866                         }
2867                         if (ret == 2)
2868                                 error = NFSERR_PERM;
2869                         else if (new_stp->ls_flags & NFSLCK_RECLAIM)
2870                                 error = NFSERR_RECLAIMCONFLICT;
2871                         else
2872                                 error = NFSERR_SHAREDENIED;
2873                         if (ret == 0)
2874                                 NFSUNLOCKSTATE();
2875                         if (haslock) {
2876                                 NFSLOCKV4ROOTMUTEX();
2877                                 nfsv4_unlock(&nfsv4rootfs_lock, 1);
2878                                 NFSUNLOCKV4ROOTMUTEX();
2879                         }
2880                         free(new_open, M_NFSDSTATE);
2881                         free(new_deleg, M_NFSDSTATE);
2882                         printf("nfsd openctrl unexpected client cnfl\n");
2883                         goto out;
2884                     }
2885                 }
2886         }
2887
2888         /*
2889          * Check for a conflicting delegation. If one is found, call
2890          * nfsrv_delegconflict() to handle it. If the v4root lock hasn't
2891          * been set yet, it will get the lock. Otherwise, it will recall
2892          * the delegation. Then, we try try again...
2893          * (If NFSLCK_DELEGCUR is set, it has a delegation, so there
2894          *  isn't a conflict.)
2895          * I currently believe the conflict algorithm to be:
2896          * For Open with Read Access and Deny None
2897          * - there is a conflict iff a different client has a write delegation
2898          * For Open with other Write Access or any Deny except None
2899          * - there is a conflict if a different client has any delegation
2900          * - there is a conflict if the same client has a read delegation
2901          *   (The current consensus is that this last case should be
2902          *    considered a conflict since the client with a read delegation
2903          *    could have done an Open with ReadAccess and WriteDeny
2904          *    locally and then not have checked for the WriteDeny.)
2905          */
2906         if (!(new_stp->ls_flags & (NFSLCK_DELEGPREV | NFSLCK_DELEGCUR))) {
2907             stp = LIST_FIRST(&lfp->lf_deleg);
2908             while (stp != LIST_END(&lfp->lf_deleg)) {
2909                 nstp = LIST_NEXT(stp, ls_file);
2910                 if (stp->ls_clp != clp && (stp->ls_flags & NFSLCK_DELEGREAD))
2911                         writedeleg = 0;
2912                 else
2913                         delegate = 0;
2914                 if ((readonly && stp->ls_clp != clp &&
2915                        (stp->ls_flags & NFSLCK_DELEGWRITE)) ||
2916                     (!readonly && (stp->ls_clp != clp ||
2917                          (stp->ls_flags & NFSLCK_DELEGREAD)))) {
2918                     if (new_stp->ls_flags & NFSLCK_RECLAIM) {
2919                         delegate = 2;
2920                     } else {
2921                         ret = nfsrv_delegconflict(stp, &haslock, p, vp);
2922                         if (ret) {
2923                             /*
2924                              * nfsrv_delegconflict() unlocks state
2925                              * when it returns non-zero.
2926                              */
2927                             printf("Nfsd openctrl unexpected deleg cnfl\n");
2928                             free(new_open, M_NFSDSTATE);
2929                             free(new_deleg, M_NFSDSTATE);
2930                             if (ret == -1) {
2931                                 openstp = NULL;
2932                                 goto tryagain;
2933                             }
2934                             error = ret;
2935                             goto out;
2936                         }
2937                     }
2938                 }
2939                 stp = nstp;
2940             }
2941         }
2942
2943         /*
2944          * We only get here if there was no open that conflicted.
2945          * If an open for the owner exists, or in the access/deny bits.
2946          * Otherwise it is a new open. If the open_owner hasn't been
2947          * confirmed, replace the open with the new one needing confirmation,
2948          * otherwise add the open.
2949          */
2950         if (new_stp->ls_flags & NFSLCK_DELEGPREV) {
2951             /*
2952              * Handle NFSLCK_DELEGPREV by searching the old delegations for
2953              * a match. If found, just move the old delegation to the current
2954              * delegation list and issue open. If not found, return
2955              * NFSERR_EXPIRED.
2956              */
2957             LIST_FOREACH(stp, &clp->lc_olddeleg, ls_list) {
2958                 if (stp->ls_lfp == lfp) {
2959                     /* Found it */
2960                     if (stp->ls_clp != clp)
2961                         panic("olddeleg clp");
2962                     LIST_REMOVE(stp, ls_list);
2963                     LIST_REMOVE(stp, ls_hash);
2964                     stp->ls_flags &= ~NFSLCK_OLDDELEG;
2965                     stp->ls_stateid.seqid = delegstateidp->seqid = 1;
2966                     stp->ls_stateid.other[0] = delegstateidp->other[0] =
2967                         clp->lc_clientid.lval[0];
2968                     stp->ls_stateid.other[1] = delegstateidp->other[1] =
2969                         clp->lc_clientid.lval[1];
2970                     stp->ls_stateid.other[2] = delegstateidp->other[2] =
2971                         nfsrv_nextstateindex(clp);
2972                     stp->ls_compref = nd->nd_compref;
2973                     LIST_INSERT_HEAD(&clp->lc_deleg, stp, ls_list);
2974                     LIST_INSERT_HEAD(NFSSTATEHASH(clp,
2975                         stp->ls_stateid), stp, ls_hash);
2976                     if (stp->ls_flags & NFSLCK_DELEGWRITE)
2977                         *rflagsp |= NFSV4OPEN_WRITEDELEGATE;
2978                     else
2979                         *rflagsp |= NFSV4OPEN_READDELEGATE;
2980                     clp->lc_delegtime = NFSD_MONOSEC +
2981                         nfsrv_lease + NFSRV_LEASEDELTA;
2982
2983                     /*
2984                      * Now, do the associated open.
2985                      */
2986                     new_open->ls_stateid.seqid = 1;
2987                     new_open->ls_stateid.other[0] = clp->lc_clientid.lval[0];
2988                     new_open->ls_stateid.other[1] = clp->lc_clientid.lval[1];
2989                     new_open->ls_stateid.other[2] = nfsrv_nextstateindex(clp);
2990                     new_open->ls_flags = (new_stp->ls_flags&NFSLCK_DENYBITS)|
2991                         NFSLCK_OPEN;
2992                     if (stp->ls_flags & NFSLCK_DELEGWRITE)
2993                         new_open->ls_flags |= (NFSLCK_READACCESS |
2994                             NFSLCK_WRITEACCESS);
2995                     else
2996                         new_open->ls_flags |= NFSLCK_READACCESS;
2997                     new_open->ls_uid = new_stp->ls_uid;
2998                     new_open->ls_lfp = lfp;
2999                     new_open->ls_clp = clp;
3000                     LIST_INIT(&new_open->ls_open);
3001                     LIST_INSERT_HEAD(&lfp->lf_open, new_open, ls_file);
3002                     LIST_INSERT_HEAD(NFSSTATEHASH(clp, new_open->ls_stateid),
3003                         new_open, ls_hash);
3004                     /*
3005                      * and handle the open owner
3006                      */
3007                     if (ownerstp) {
3008                         new_open->ls_openowner = ownerstp;
3009                         LIST_INSERT_HEAD(&ownerstp->ls_open,new_open,ls_list);
3010                     } else {
3011                         new_open->ls_openowner = new_stp;
3012                         new_stp->ls_flags = 0;
3013                         nfsrvd_refcache(new_stp->ls_op);
3014                         new_stp->ls_noopens = 0;
3015                         LIST_INIT(&new_stp->ls_open);
3016                         LIST_INSERT_HEAD(&new_stp->ls_open, new_open, ls_list);
3017                         LIST_INSERT_HEAD(&clp->lc_open, new_stp, ls_list);
3018                         *new_stpp = NULL;
3019                         nfsstatsv1.srvopenowners++;
3020                         nfsrv_openpluslock++;
3021                     }
3022                     openstp = new_open;
3023                     new_open = NULL;
3024                     nfsstatsv1.srvopens++;
3025                     nfsrv_openpluslock++;
3026                     break;
3027                 }
3028             }
3029             if (stp == LIST_END(&clp->lc_olddeleg))
3030                 error = NFSERR_EXPIRED;
3031         } else if (new_stp->ls_flags & (NFSLCK_DELEGREAD | NFSLCK_DELEGWRITE)) {
3032             /*
3033              * Scan to see that no delegation for this client and file
3034              * doesn't already exist.
3035              * There also shouldn't yet be an Open for this file and
3036              * openowner.
3037              */
3038             LIST_FOREACH(stp, &lfp->lf_deleg, ls_file) {
3039                 if (stp->ls_clp == clp)
3040                     break;
3041             }
3042             if (stp == LIST_END(&lfp->lf_deleg) && openstp == NULL) {
3043                 /*
3044                  * This is the Claim_Previous case with a delegation
3045                  * type != Delegate_None.
3046                  */
3047                 /*
3048                  * First, add the delegation. (Although we must issue the
3049                  * delegation, we can also ask for an immediate return.)
3050                  */
3051                 new_deleg->ls_stateid.seqid = delegstateidp->seqid = 1;
3052                 new_deleg->ls_stateid.other[0] = delegstateidp->other[0] =
3053                     clp->lc_clientid.lval[0];
3054                 new_deleg->ls_stateid.other[1] = delegstateidp->other[1] =
3055                     clp->lc_clientid.lval[1];
3056                 new_deleg->ls_stateid.other[2] = delegstateidp->other[2] =
3057                     nfsrv_nextstateindex(clp);
3058                 if (new_stp->ls_flags & NFSLCK_DELEGWRITE) {
3059                     new_deleg->ls_flags = (NFSLCK_DELEGWRITE |
3060                         NFSLCK_READACCESS | NFSLCK_WRITEACCESS);
3061                     *rflagsp |= NFSV4OPEN_WRITEDELEGATE;
3062                     nfsrv_writedelegcnt++;
3063                 } else {
3064                     new_deleg->ls_flags = (NFSLCK_DELEGREAD |
3065                         NFSLCK_READACCESS);
3066                     *rflagsp |= NFSV4OPEN_READDELEGATE;
3067                 }
3068                 new_deleg->ls_uid = new_stp->ls_uid;
3069                 new_deleg->ls_lfp = lfp;
3070                 new_deleg->ls_clp = clp;
3071                 new_deleg->ls_filerev = filerev;
3072                 new_deleg->ls_compref = nd->nd_compref;
3073                 LIST_INSERT_HEAD(&lfp->lf_deleg, new_deleg, ls_file);
3074                 LIST_INSERT_HEAD(NFSSTATEHASH(clp,
3075                     new_deleg->ls_stateid), new_deleg, ls_hash);
3076                 LIST_INSERT_HEAD(&clp->lc_deleg, new_deleg, ls_list);
3077                 new_deleg = NULL;
3078                 if (delegate == 2 || nfsrv_issuedelegs == 0 ||
3079                     (clp->lc_flags & (LCL_CALLBACKSON | LCL_CBDOWN)) !=
3080                      LCL_CALLBACKSON ||
3081                     NFSRV_V4DELEGLIMIT(nfsrv_delegatecnt) ||
3082                     !NFSVNO_DELEGOK(vp))
3083                     *rflagsp |= NFSV4OPEN_RECALL;
3084                 nfsstatsv1.srvdelegates++;
3085                 nfsrv_openpluslock++;
3086                 nfsrv_delegatecnt++;
3087
3088                 /*
3089                  * Now, do the associated open.
3090                  */
3091                 new_open->ls_stateid.seqid = 1;
3092                 new_open->ls_stateid.other[0] = clp->lc_clientid.lval[0];
3093                 new_open->ls_stateid.other[1] = clp->lc_clientid.lval[1];
3094                 new_open->ls_stateid.other[2] = nfsrv_nextstateindex(clp);
3095                 new_open->ls_flags = (new_stp->ls_flags & NFSLCK_DENYBITS) |
3096                     NFSLCK_OPEN;
3097                 if (new_stp->ls_flags & NFSLCK_DELEGWRITE)
3098                         new_open->ls_flags |= (NFSLCK_READACCESS |
3099                             NFSLCK_WRITEACCESS);
3100                 else
3101                         new_open->ls_flags |= NFSLCK_READACCESS;
3102                 new_open->ls_uid = new_stp->ls_uid;
3103                 new_open->ls_lfp = lfp;
3104                 new_open->ls_clp = clp;
3105                 LIST_INIT(&new_open->ls_open);
3106                 LIST_INSERT_HEAD(&lfp->lf_open, new_open, ls_file);
3107                 LIST_INSERT_HEAD(NFSSTATEHASH(clp, new_open->ls_stateid),
3108                    new_open, ls_hash);
3109                 /*
3110                  * and handle the open owner
3111                  */
3112                 if (ownerstp) {
3113                     new_open->ls_openowner = ownerstp;
3114                     LIST_INSERT_HEAD(&ownerstp->ls_open, new_open, ls_list);
3115                 } else {
3116                     new_open->ls_openowner = new_stp;
3117                     new_stp->ls_flags = 0;
3118                     nfsrvd_refcache(new_stp->ls_op);
3119                     new_stp->ls_noopens = 0;
3120                     LIST_INIT(&new_stp->ls_open);
3121                     LIST_INSERT_HEAD(&new_stp->ls_open, new_open, ls_list);
3122                     LIST_INSERT_HEAD(&clp->lc_open, new_stp, ls_list);
3123                     *new_stpp = NULL;
3124                     nfsstatsv1.srvopenowners++;
3125                     nfsrv_openpluslock++;
3126                 }
3127                 openstp = new_open;
3128                 new_open = NULL;
3129                 nfsstatsv1.srvopens++;
3130                 nfsrv_openpluslock++;
3131             } else {
3132                 error = NFSERR_RECLAIMCONFLICT;
3133             }
3134         } else if (ownerstp) {
3135                 if (ownerstp->ls_flags & NFSLCK_NEEDSCONFIRM) {
3136                     /* Replace the open */
3137                     if (ownerstp->ls_op)
3138                         nfsrvd_derefcache(ownerstp->ls_op);
3139                     ownerstp->ls_op = new_stp->ls_op;
3140                     nfsrvd_refcache(ownerstp->ls_op);
3141                     ownerstp->ls_seq = new_stp->ls_seq;
3142                     *rflagsp |= NFSV4OPEN_RESULTCONFIRM;
3143                     stp = LIST_FIRST(&ownerstp->ls_open);
3144                     stp->ls_flags = (new_stp->ls_flags & NFSLCK_SHAREBITS) |
3145                         NFSLCK_OPEN;
3146                     stp->ls_stateid.seqid = 1;
3147                     stp->ls_uid = new_stp->ls_uid;
3148                     if (lfp != stp->ls_lfp) {
3149                         LIST_REMOVE(stp, ls_file);
3150                         LIST_INSERT_HEAD(&lfp->lf_open, stp, ls_file);
3151                         stp->ls_lfp = lfp;
3152                     }
3153                     openstp = stp;
3154                 } else if (openstp) {
3155                     openstp->ls_flags |= (new_stp->ls_flags & NFSLCK_SHAREBITS);
3156                     openstp->ls_stateid.seqid++;
3157                     if ((nd->nd_flag & ND_NFSV41) != 0 &&
3158                         openstp->ls_stateid.seqid == 0)
3159                         openstp->ls_stateid.seqid = 1;
3160
3161                     /*
3162                      * This is where we can choose to issue a delegation.
3163                      */
3164                     if ((new_stp->ls_flags & NFSLCK_WANTNODELEG) != 0)
3165                         *rflagsp |= NFSV4OPEN_WDNOTWANTED;
3166                     else if (nfsrv_issuedelegs == 0)
3167                         *rflagsp |= NFSV4OPEN_WDSUPPFTYPE;
3168                     else if (NFSRV_V4DELEGLIMIT(nfsrv_delegatecnt))
3169                         *rflagsp |= NFSV4OPEN_WDRESOURCE;
3170                     else if (delegate == 0 || writedeleg == 0 ||
3171                         NFSVNO_EXRDONLY(exp) || (readonly != 0 &&
3172                         nfsrv_writedelegifpos == 0) ||
3173                         !NFSVNO_DELEGOK(vp) ||
3174                         (new_stp->ls_flags & NFSLCK_WANTRDELEG) != 0 ||
3175                         (clp->lc_flags & (LCL_CALLBACKSON | LCL_CBDOWN)) !=
3176                          LCL_CALLBACKSON)
3177                         *rflagsp |= NFSV4OPEN_WDCONTENTION;
3178                     else {
3179                         new_deleg->ls_stateid.seqid = delegstateidp->seqid = 1;
3180                         new_deleg->ls_stateid.other[0] = delegstateidp->other[0]
3181                             = clp->lc_clientid.lval[0];
3182                         new_deleg->ls_stateid.other[1] = delegstateidp->other[1]
3183                             = clp->lc_clientid.lval[1];
3184                         new_deleg->ls_stateid.other[2] = delegstateidp->other[2]
3185                             = nfsrv_nextstateindex(clp);
3186                         new_deleg->ls_flags = (NFSLCK_DELEGWRITE |
3187                             NFSLCK_READACCESS | NFSLCK_WRITEACCESS);
3188                         *rflagsp |= NFSV4OPEN_WRITEDELEGATE;
3189                         new_deleg->ls_uid = new_stp->ls_uid;
3190                         new_deleg->ls_lfp = lfp;
3191                         new_deleg->ls_clp = clp;
3192                         new_deleg->ls_filerev = filerev;
3193                         new_deleg->ls_compref = nd->nd_compref;
3194                         nfsrv_writedelegcnt++;
3195                         LIST_INSERT_HEAD(&lfp->lf_deleg, new_deleg, ls_file);
3196                         LIST_INSERT_HEAD(NFSSTATEHASH(clp,
3197                             new_deleg->ls_stateid), new_deleg, ls_hash);
3198                         LIST_INSERT_HEAD(&clp->lc_deleg, new_deleg, ls_list);
3199                         new_deleg = NULL;
3200                         nfsstatsv1.srvdelegates++;
3201                         nfsrv_openpluslock++;
3202                         nfsrv_delegatecnt++;
3203                     }
3204                 } else {
3205                     new_open->ls_stateid.seqid = 1;
3206                     new_open->ls_stateid.other[0] = clp->lc_clientid.lval[0];
3207                     new_open->ls_stateid.other[1] = clp->lc_clientid.lval[1];
3208                     new_open->ls_stateid.other[2] = nfsrv_nextstateindex(clp);
3209                     new_open->ls_flags = (new_stp->ls_flags & NFSLCK_SHAREBITS)|
3210                         NFSLCK_OPEN;
3211                     new_open->ls_uid = new_stp->ls_uid;
3212                     new_open->ls_openowner = ownerstp;
3213                     new_open->ls_lfp = lfp;
3214                     new_open->ls_clp = clp;
3215                     LIST_INIT(&new_open->ls_open);
3216                     LIST_INSERT_HEAD(&lfp->lf_open, new_open, ls_file);
3217                     LIST_INSERT_HEAD(&ownerstp->ls_open, new_open, ls_list);
3218                     LIST_INSERT_HEAD(NFSSTATEHASH(clp, new_open->ls_stateid),
3219                         new_open, ls_hash);
3220                     openstp = new_open;
3221                     new_open = NULL;
3222                     nfsstatsv1.srvopens++;
3223                     nfsrv_openpluslock++;
3224
3225                     /*
3226                      * This is where we can choose to issue a delegation.
3227                      */
3228                     if ((new_stp->ls_flags & NFSLCK_WANTNODELEG) != 0)
3229                         *rflagsp |= NFSV4OPEN_WDNOTWANTED;
3230                     else if (nfsrv_issuedelegs == 0)
3231                         *rflagsp |= NFSV4OPEN_WDSUPPFTYPE;
3232                     else if (NFSRV_V4DELEGLIMIT(nfsrv_delegatecnt))
3233                         *rflagsp |= NFSV4OPEN_WDRESOURCE;
3234                     else if (delegate == 0 || (writedeleg == 0 &&
3235                         readonly == 0) || !NFSVNO_DELEGOK(vp) ||
3236                         (clp->lc_flags & (LCL_CALLBACKSON | LCL_CBDOWN)) !=
3237                          LCL_CALLBACKSON)
3238                         *rflagsp |= NFSV4OPEN_WDCONTENTION;
3239                     else {
3240                         new_deleg->ls_stateid.seqid = delegstateidp->seqid = 1;
3241                         new_deleg->ls_stateid.other[0] = delegstateidp->other[0]
3242                             = clp->lc_clientid.lval[0];
3243                         new_deleg->ls_stateid.other[1] = delegstateidp->other[1]
3244                             = clp->lc_clientid.lval[1];
3245                         new_deleg->ls_stateid.other[2] = delegstateidp->other[2]
3246                             = nfsrv_nextstateindex(clp);
3247                         if (writedeleg && !NFSVNO_EXRDONLY(exp) &&
3248                             (nfsrv_writedelegifpos || !readonly) &&
3249                             (new_stp->ls_flags & NFSLCK_WANTRDELEG) == 0) {
3250                             new_deleg->ls_flags = (NFSLCK_DELEGWRITE |
3251                                 NFSLCK_READACCESS | NFSLCK_WRITEACCESS);
3252                             *rflagsp |= NFSV4OPEN_WRITEDELEGATE;
3253                             nfsrv_writedelegcnt++;
3254                         } else {
3255                             new_deleg->ls_flags = (NFSLCK_DELEGREAD |
3256                                 NFSLCK_READACCESS);
3257                             *rflagsp |= NFSV4OPEN_READDELEGATE;
3258                         }
3259                         new_deleg->ls_uid = new_stp->ls_uid;
3260                         new_deleg->ls_lfp = lfp;
3261                         new_deleg->ls_clp = clp;
3262                         new_deleg->ls_filerev = filerev;
3263                         new_deleg->ls_compref = nd->nd_compref;
3264                         LIST_INSERT_HEAD(&lfp->lf_deleg, new_deleg, ls_file);
3265                         LIST_INSERT_HEAD(NFSSTATEHASH(clp,
3266                             new_deleg->ls_stateid), new_deleg, ls_hash);
3267                         LIST_INSERT_HEAD(&clp->lc_deleg, new_deleg, ls_list);
3268                         new_deleg = NULL;
3269                         nfsstatsv1.srvdelegates++;
3270                         nfsrv_openpluslock++;
3271                         nfsrv_delegatecnt++;
3272                     }
3273                 }
3274         } else {
3275                 /*
3276                  * New owner case. Start the open_owner sequence with a
3277                  * Needs confirmation (unless a reclaim) and hang the
3278                  * new open off it.
3279                  */
3280                 new_open->ls_stateid.seqid = 1;
3281                 new_open->ls_stateid.other[0] = clp->lc_clientid.lval[0];
3282                 new_open->ls_stateid.other[1] = clp->lc_clientid.lval[1];
3283                 new_open->ls_stateid.other[2] = nfsrv_nextstateindex(clp);
3284                 new_open->ls_flags = (new_stp->ls_flags & NFSLCK_SHAREBITS) |
3285                     NFSLCK_OPEN;
3286                 new_open->ls_uid = new_stp->ls_uid;
3287                 LIST_INIT(&new_open->ls_open);
3288                 new_open->ls_openowner = new_stp;
3289                 new_open->ls_lfp = lfp;
3290                 new_open->ls_clp = clp;
3291                 LIST_INSERT_HEAD(&lfp->lf_open, new_open, ls_file);
3292                 if (new_stp->ls_flags & NFSLCK_RECLAIM) {
3293                         new_stp->ls_flags = 0;
3294                 } else if ((nd->nd_flag & ND_NFSV41) != 0) {
3295                         /* NFSv4.1 never needs confirmation. */
3296                         new_stp->ls_flags = 0;
3297
3298                         /*
3299                          * This is where we can choose to issue a delegation.
3300                          */
3301                         if (delegate && nfsrv_issuedelegs &&
3302                             (writedeleg || readonly) &&
3303                             (clp->lc_flags & (LCL_CALLBACKSON | LCL_CBDOWN)) ==
3304                              LCL_CALLBACKSON &&
3305                             !NFSRV_V4DELEGLIMIT(nfsrv_delegatecnt) &&
3306                             NFSVNO_DELEGOK(vp) &&
3307                             ((nd->nd_flag & ND_NFSV41) == 0 ||
3308                              (new_stp->ls_flags & NFSLCK_WANTNODELEG) == 0)) {
3309                                 new_deleg->ls_stateid.seqid =
3310                                     delegstateidp->seqid = 1;
3311                                 new_deleg->ls_stateid.other[0] =
3312                                     delegstateidp->other[0]
3313                                     = clp->lc_clientid.lval[0];
3314                                 new_deleg->ls_stateid.other[1] =
3315                                     delegstateidp->other[1]
3316                                     = clp->lc_clientid.lval[1];
3317                                 new_deleg->ls_stateid.other[2] =
3318                                     delegstateidp->other[2]
3319                                     = nfsrv_nextstateindex(clp);
3320                                 if (writedeleg && !NFSVNO_EXRDONLY(exp) &&
3321                                     (nfsrv_writedelegifpos || !readonly) &&
3322                                     ((nd->nd_flag & ND_NFSV41) == 0 ||
3323                                      (new_stp->ls_flags & NFSLCK_WANTRDELEG) ==
3324                                      0)) {
3325                                         new_deleg->ls_flags =
3326                                             (NFSLCK_DELEGWRITE |
3327                                              NFSLCK_READACCESS |
3328                                              NFSLCK_WRITEACCESS);
3329                                         *rflagsp |= NFSV4OPEN_WRITEDELEGATE;
3330                                         nfsrv_writedelegcnt++;
3331                                 } else {
3332                                         new_deleg->ls_flags =
3333                                             (NFSLCK_DELEGREAD |
3334                                              NFSLCK_READACCESS);
3335                                         *rflagsp |= NFSV4OPEN_READDELEGATE;
3336                                 }
3337                                 new_deleg->ls_uid = new_stp->ls_uid;
3338                                 new_deleg->ls_lfp = lfp;
3339                                 new_deleg->ls_clp = clp;
3340                                 new_deleg->ls_filerev = filerev;
3341                                 new_deleg->ls_compref = nd->nd_compref;
3342                                 LIST_INSERT_HEAD(&lfp->lf_deleg, new_deleg,
3343                                     ls_file);
3344                                 LIST_INSERT_HEAD(NFSSTATEHASH(clp,
3345                                     new_deleg->ls_stateid), new_deleg, ls_hash);
3346                                 LIST_INSERT_HEAD(&clp->lc_deleg, new_deleg,
3347                                     ls_list);
3348                                 new_deleg = NULL;
3349                                 nfsstatsv1.srvdelegates++;
3350                                 nfsrv_openpluslock++;
3351                                 nfsrv_delegatecnt++;
3352                         }
3353                         /*
3354                          * Since NFSv4.1 never does an OpenConfirm, the first
3355                          * open state will be acquired here.
3356                          */
3357                         if (!(clp->lc_flags & LCL_STAMPEDSTABLE)) {
3358                                 clp->lc_flags |= LCL_STAMPEDSTABLE;
3359                                 len = clp->lc_idlen;
3360                                 NFSBCOPY(clp->lc_id, clidp, len);
3361                                 gotstate = 1;
3362                         }
3363                 } else {
3364                         *rflagsp |= NFSV4OPEN_RESULTCONFIRM;
3365                         new_stp->ls_flags = NFSLCK_NEEDSCONFIRM;
3366                 }
3367                 nfsrvd_refcache(new_stp->ls_op);
3368                 new_stp->ls_noopens = 0;
3369                 LIST_INIT(&new_stp->ls_open);
3370                 LIST_INSERT_HEAD(&new_stp->ls_open, new_open, ls_list);
3371                 LIST_INSERT_HEAD(&clp->lc_open, new_stp, ls_list);
3372                 LIST_INSERT_HEAD(NFSSTATEHASH(clp, new_open->ls_stateid),
3373                     new_open, ls_hash);
3374                 openstp = new_open;
3375                 new_open = NULL;
3376                 *new_stpp = NULL;
3377                 nfsstatsv1.srvopens++;
3378                 nfsrv_openpluslock++;
3379                 nfsstatsv1.srvopenowners++;
3380                 nfsrv_openpluslock++;
3381         }
3382         if (!error) {
3383                 stateidp->seqid = openstp->ls_stateid.seqid;
3384                 stateidp->other[0] = openstp->ls_stateid.other[0];
3385                 stateidp->other[1] = openstp->ls_stateid.other[1];
3386                 stateidp->other[2] = openstp->ls_stateid.other[2];
3387         }
3388         NFSUNLOCKSTATE();
3389         if (haslock) {
3390                 NFSLOCKV4ROOTMUTEX();
3391                 nfsv4_unlock(&nfsv4rootfs_lock, 1);
3392                 NFSUNLOCKV4ROOTMUTEX();
3393         }
3394         if (new_open)
3395                 free(new_open, M_NFSDSTATE);
3396         if (new_deleg)
3397                 free(new_deleg, M_NFSDSTATE);
3398
3399         /*
3400          * If the NFSv4.1 client just acquired its first open, write a timestamp
3401          * to the stable storage file.
3402          */
3403         if (gotstate != 0) {
3404                 nfsrv_writestable(clidp, len, NFSNST_NEWSTATE, p);
3405                 nfsrv_backupstable();
3406         }
3407
3408 out:
3409         free(clidp, M_TEMP);
3410         NFSEXITCODE2(error, nd);
3411         return (error);
3412 }
3413
3414 /*
3415  * Open update. Does the confirm, downgrade and close.
3416  */
3417 int
3418 nfsrv_openupdate(vnode_t vp, struct nfsstate *new_stp, nfsquad_t clientid,
3419     nfsv4stateid_t *stateidp, struct nfsrv_descript *nd, NFSPROC_T *p,
3420     int *retwriteaccessp)
3421 {
3422         struct nfsstate *stp;
3423         struct nfsclient *clp;
3424         struct nfslockfile *lfp;
3425         u_int32_t bits;
3426         int error = 0, gotstate = 0, len = 0;
3427         u_char *clidp = NULL;
3428
3429         /*
3430          * Check for restart conditions (client and server).
3431          */
3432         error = nfsrv_checkrestart(clientid, new_stp->ls_flags,
3433             &new_stp->ls_stateid, 0);
3434         if (error)
3435                 goto out;
3436
3437         clidp = malloc(NFSV4_OPAQUELIMIT, M_TEMP, M_WAITOK);
3438         NFSLOCKSTATE();
3439         /*
3440          * Get the open structure via clientid and stateid.
3441          */
3442         error = nfsrv_getclient(clientid, CLOPS_RENEW, &clp, NULL,
3443             (nfsquad_t)((u_quad_t)0), 0, nd, p);
3444         if (!error)
3445                 error = nfsrv_getstate(clp, &new_stp->ls_stateid,
3446                     new_stp->ls_flags, &stp);
3447
3448         /*
3449          * Sanity check the open.
3450          */
3451         if (!error && (!(stp->ls_flags & NFSLCK_OPEN) ||
3452                 (!(new_stp->ls_flags & NFSLCK_CONFIRM) &&
3453                  (stp->ls_openowner->ls_flags & NFSLCK_NEEDSCONFIRM)) ||
3454                 ((new_stp->ls_flags & NFSLCK_CONFIRM) &&
3455                  (!(stp->ls_openowner->ls_flags & NFSLCK_NEEDSCONFIRM)))))
3456                 error = NFSERR_BADSTATEID;
3457
3458         if (!error)
3459                 error = nfsrv_checkseqid(nd, new_stp->ls_seq,
3460                     stp->ls_openowner, new_stp->ls_op);
3461         if (!error && stp->ls_stateid.seqid != new_stp->ls_stateid.seqid &&
3462             (((nd->nd_flag & ND_NFSV41) == 0 &&
3463               !(new_stp->ls_flags & NFSLCK_CONFIRM)) ||
3464              ((nd->nd_flag & ND_NFSV41) != 0 &&
3465               new_stp->ls_stateid.seqid != 0)))
3466                 error = NFSERR_OLDSTATEID;
3467         if (!error && vnode_vtype(vp) != VREG) {
3468                 if (vnode_vtype(vp) == VDIR)
3469                         error = NFSERR_ISDIR;
3470                 else
3471                         error = NFSERR_INVAL;
3472         }
3473
3474         if (error) {
3475                 /*
3476                  * If a client tries to confirm an Open with a bad
3477                  * seqid# and there are no byte range locks or other Opens
3478                  * on the openowner, just throw it away, so the next use of the
3479                  * openowner will start a fresh seq#.
3480                  */
3481                 if (error == NFSERR_BADSEQID &&
3482                     (new_stp->ls_flags & NFSLCK_CONFIRM) &&
3483                     nfsrv_nootherstate(stp))
3484                         nfsrv_freeopenowner(stp->ls_openowner, 0, p);
3485                 NFSUNLOCKSTATE();
3486                 goto out;
3487         }
3488
3489         /*
3490          * Set the return stateid.
3491          */
3492         stateidp->seqid = stp->ls_stateid.seqid + 1;
3493         if ((nd->nd_flag & ND_NFSV41) != 0 && stateidp->seqid == 0)
3494                 stateidp->seqid = 1;
3495         stateidp->other[0] = stp->ls_stateid.other[0];
3496         stateidp->other[1] = stp->ls_stateid.other[1];
3497         stateidp->other[2] = stp->ls_stateid.other[2];
3498         /*
3499          * Now, handle the three cases.
3500          */
3501         if (new_stp->ls_flags & NFSLCK_CONFIRM) {
3502                 /*
3503                  * If the open doesn't need confirmation, it seems to me that
3504                  * there is a client error, but I'll just log it and keep going?
3505                  */
3506                 if (!(stp->ls_openowner->ls_flags & NFSLCK_NEEDSCONFIRM))
3507                         printf("Nfsv4d: stray open confirm\n");
3508                 stp->ls_openowner->ls_flags = 0;
3509                 stp->ls_stateid.seqid++;
3510                 if ((nd->nd_flag & ND_NFSV41) != 0 &&
3511                     stp->ls_stateid.seqid == 0)
3512                         stp->ls_stateid.seqid = 1;
3513                 if (!(clp->lc_flags & LCL_STAMPEDSTABLE)) {
3514                         clp->lc_flags |= LCL_STAMPEDSTABLE;
3515                         len = clp->lc_idlen;
3516                         NFSBCOPY(clp->lc_id, clidp, len);
3517                         gotstate = 1;
3518                 }
3519                 NFSUNLOCKSTATE();
3520         } else if (new_stp->ls_flags & NFSLCK_CLOSE) {
3521                 lfp = stp->ls_lfp;
3522                 if (retwriteaccessp != NULL) {
3523                         if ((stp->ls_flags & NFSLCK_WRITEACCESS) != 0)
3524                                 *retwriteaccessp = 1;
3525                         else
3526                                 *retwriteaccessp = 0;
3527                 }
3528                 if (nfsrv_dolocallocks != 0 && !LIST_EMPTY(&stp->ls_open)) {
3529                         /* Get the lf lock */
3530                         nfsrv_locklf(lfp);
3531                         NFSUNLOCKSTATE();
3532                         ASSERT_VOP_ELOCKED(vp, "nfsrv_openupdate");
3533                         NFSVOPUNLOCK(vp);
3534                         if (nfsrv_freeopen(stp, vp, 1, p) == 0) {
3535                                 NFSLOCKSTATE();
3536                                 nfsrv_unlocklf(lfp);
3537                                 NFSUNLOCKSTATE();
3538                         }
3539                         NFSVOPLOCK(vp, LK_EXCLUSIVE | LK_RETRY);
3540                 } else {
3541                         (void) nfsrv_freeopen(stp, NULL, 0, p);
3542                         NFSUNLOCKSTATE();
3543                 }
3544         } else {
3545                 /*
3546                  * Update the share bits, making sure that the new set are a
3547                  * subset of the old ones.
3548                  */
3549                 bits = (new_stp->ls_flags & NFSLCK_SHAREBITS);
3550                 if (~(stp->ls_flags) & bits) {
3551                         NFSUNLOCKSTATE();
3552                         error = NFSERR_INVAL;
3553                         goto out;
3554                 }
3555                 stp->ls_flags = (bits | NFSLCK_OPEN);
3556                 stp->ls_stateid.seqid++;
3557                 if ((nd->nd_flag & ND_NFSV41) != 0 &&
3558                     stp->ls_stateid.seqid == 0)
3559                         stp->ls_stateid.seqid = 1;
3560                 NFSUNLOCKSTATE();
3561         }
3562
3563         /*
3564          * If the client just confirmed its first open, write a timestamp
3565          * to the stable storage file.
3566          */
3567         if (gotstate != 0) {
3568                 nfsrv_writestable(clidp, len, NFSNST_NEWSTATE, p);
3569                 nfsrv_backupstable();
3570         }
3571
3572 out:
3573         free(clidp, M_TEMP);
3574         NFSEXITCODE2(error, nd);
3575         return (error);
3576 }
3577
3578 /*
3579  * Delegation update. Does the purge and return.
3580  */
3581 int
3582 nfsrv_delegupdate(struct nfsrv_descript *nd, nfsquad_t clientid,
3583     nfsv4stateid_t *stateidp, vnode_t vp, int op, struct ucred *cred,
3584     NFSPROC_T *p, int *retwriteaccessp)
3585 {
3586         struct nfsstate *stp;
3587         struct nfsclient *clp;
3588         int error = 0;
3589         fhandle_t fh;
3590
3591         /*
3592          * Do a sanity check against the file handle for DelegReturn.
3593          */
3594         if (vp) {
3595                 error = nfsvno_getfh(vp, &fh, p);
3596                 if (error)
3597                         goto out;
3598         }
3599         /*
3600          * Check for restart conditions (client and server).
3601          */
3602         if (op == NFSV4OP_DELEGRETURN)
3603                 error = nfsrv_checkrestart(clientid, NFSLCK_DELEGRETURN,
3604                         stateidp, 0);
3605         else
3606                 error = nfsrv_checkrestart(clientid, NFSLCK_DELEGPURGE,
3607                         stateidp, 0);
3608
3609         NFSLOCKSTATE();
3610         /*
3611          * Get the open structure via clientid and stateid.
3612          */
3613         if (!error)
3614             error = nfsrv_getclient(clientid, CLOPS_RENEW, &clp, NULL,
3615                 (nfsquad_t)((u_quad_t)0), 0, nd, p);
3616         if (error) {
3617                 if (error == NFSERR_CBPATHDOWN)
3618                         error = 0;
3619                 if (error == NFSERR_STALECLIENTID && op == NFSV4OP_DELEGRETURN)
3620                         error = NFSERR_STALESTATEID;
3621         }
3622         if (!error && op == NFSV4OP_DELEGRETURN) {
3623             error = nfsrv_getstate(clp, stateidp, NFSLCK_DELEGRETURN, &stp);
3624             if (!error && stp->ls_stateid.seqid != stateidp->seqid &&
3625                 ((nd->nd_flag & ND_NFSV41) == 0 || stateidp->seqid != 0))
3626                 error = NFSERR_OLDSTATEID;
3627         }
3628         /*
3629          * NFSERR_EXPIRED means that the state has gone away,
3630          * so Delegations have been purged. Just return ok.
3631          */
3632         if (error == NFSERR_EXPIRED && op == NFSV4OP_DELEGPURGE) {
3633                 NFSUNLOCKSTATE();
3634                 error = 0;
3635                 goto out;
3636         }
3637         if (error) {
3638                 NFSUNLOCKSTATE();
3639                 goto out;
3640         }
3641
3642         if (op == NFSV4OP_DELEGRETURN) {
3643                 if (NFSBCMP((caddr_t)&fh, (caddr_t)&stp->ls_lfp->lf_fh,
3644                     sizeof (fhandle_t))) {
3645                         NFSUNLOCKSTATE();
3646                         error = NFSERR_BADSTATEID;
3647                         goto out;
3648                 }
3649                 if (retwriteaccessp != NULL) {
3650                         if ((stp->ls_flags & NFSLCK_DELEGWRITE) != 0)
3651                                 *retwriteaccessp = 1;
3652                         else
3653                                 *retwriteaccessp = 0;
3654                 }
3655                 nfsrv_freedeleg(stp);
3656         } else {
3657                 nfsrv_freedeleglist(&clp->lc_olddeleg);
3658         }
3659         NFSUNLOCKSTATE();
3660         error = 0;
3661
3662 out:
3663         NFSEXITCODE(error);
3664         return (error);
3665 }
3666
3667 /*
3668  * Release lock owner.
3669  */
3670 int
3671 nfsrv_releaselckown(struct nfsstate *new_stp, nfsquad_t clientid,
3672     NFSPROC_T *p)
3673 {
3674         struct nfsstate *stp, *nstp, *openstp, *ownstp;
3675         struct nfsclient *clp;
3676         int error = 0;
3677
3678         /*
3679          * Check for restart conditions (client and server).
3680          */
3681         error = nfsrv_checkrestart(clientid, new_stp->ls_flags,
3682             &new_stp->ls_stateid, 0);
3683         if (error)
3684                 goto out;
3685
3686         NFSLOCKSTATE();
3687         /*
3688          * Get the lock owner by name.
3689          */
3690         error = nfsrv_getclient(clientid, CLOPS_RENEW, &clp, NULL,
3691             (nfsquad_t)((u_quad_t)0), 0, NULL, p);
3692         if (error) {
3693                 NFSUNLOCKSTATE();
3694                 goto out;
3695         }
3696         LIST_FOREACH(ownstp, &clp->lc_open, ls_list) {
3697             LIST_FOREACH(openstp, &ownstp->ls_open, ls_list) {
3698                 stp = LIST_FIRST(&openstp->ls_open);
3699                 while (stp != LIST_END(&openstp->ls_open)) {
3700                     nstp = LIST_NEXT(stp, ls_list);
3701                     /*
3702                      * If the owner matches, check for locks and
3703                      * then free or return an error.
3704                      */
3705                     if (stp->ls_ownerlen == new_stp->ls_ownerlen &&
3706                         !NFSBCMP(stp->ls_owner, new_stp->ls_owner,
3707                          stp->ls_ownerlen)){
3708                         if (LIST_EMPTY(&stp->ls_lock)) {
3709                             nfsrv_freelockowner(stp, NULL, 0, p);
3710                         } else {
3711                             NFSUNLOCKSTATE();
3712                             error = NFSERR_LOCKSHELD;
3713                             goto out;
3714                         }
3715                     }
3716                     stp = nstp;
3717                 }
3718             }
3719         }
3720         NFSUNLOCKSTATE();
3721
3722 out:
3723         NFSEXITCODE(error);
3724         return (error);
3725 }
3726
3727 /*
3728  * Get the file handle for a lock structure.
3729  */
3730 static int
3731 nfsrv_getlockfh(vnode_t vp, u_short flags, struct nfslockfile *new_lfp,
3732     fhandle_t *nfhp, NFSPROC_T *p)
3733 {
3734         fhandle_t *fhp = NULL;
3735         int error;
3736
3737         /*
3738          * For lock, use the new nfslock structure, otherwise just
3739          * a fhandle_t on the stack.
3740          */
3741         if (flags & NFSLCK_OPEN) {
3742                 KASSERT(new_lfp != NULL, ("nfsrv_getlockfh: new_lfp NULL"));
3743                 fhp = &new_lfp->lf_fh;
3744         } else if (nfhp) {
3745                 fhp = nfhp;
3746         } else {
3747                 panic("nfsrv_getlockfh");
3748         }
3749         error = nfsvno_getfh(vp, fhp, p);
3750         NFSEXITCODE(error);
3751         return (error);
3752 }
3753
3754 /*
3755  * Get an nfs lock structure. Allocate one, as required, and return a
3756  * pointer to it.
3757  * Returns an NFSERR_xxx upon failure or -1 to indicate no current lock.
3758  */
3759 static int
3760 nfsrv_getlockfile(u_short flags, struct nfslockfile **new_lfpp,
3761     struct nfslockfile **lfpp, fhandle_t *nfhp, int lockit)
3762 {
3763         struct nfslockfile *lfp;
3764         fhandle_t *fhp = NULL, *tfhp;
3765         struct nfslockhashhead *hp;
3766         struct nfslockfile *new_lfp = NULL;
3767
3768         /*
3769          * For lock, use the new nfslock structure, otherwise just
3770          * a fhandle_t on the stack.
3771          */
3772         if (flags & NFSLCK_OPEN) {
3773                 new_lfp = *new_lfpp;
3774                 fhp = &new_lfp->lf_fh;
3775         } else if (nfhp) {
3776                 fhp = nfhp;
3777         } else {
3778                 panic("nfsrv_getlockfile");
3779         }
3780
3781         hp = NFSLOCKHASH(fhp);
3782         LIST_FOREACH(lfp, hp, lf_hash) {
3783                 tfhp = &lfp->lf_fh;
3784                 if (NFSVNO_CMPFH(fhp, tfhp)) {
3785                         if (lockit)
3786                                 nfsrv_locklf(lfp);
3787                         *lfpp = lfp;
3788                         return (0);
3789                 }
3790         }
3791         if (!(flags & NFSLCK_OPEN))
3792                 return (-1);
3793
3794         /*
3795          * No match, so chain the new one into the list.
3796          */
3797         LIST_INIT(&new_lfp->lf_open);
3798         LIST_INIT(&new_lfp->lf_lock);
3799         LIST_INIT(&new_lfp->lf_deleg);
3800         LIST_INIT(&new_lfp->lf_locallock);
3801         LIST_INIT(&new_lfp->lf_rollback);
3802         new_lfp->lf_locallock_lck.nfslock_usecnt = 0;
3803         new_lfp->lf_locallock_lck.nfslock_lock = 0;
3804         new_lfp->lf_usecount = 0;
3805         LIST_INSERT_HEAD(hp, new_lfp, lf_hash);
3806         *lfpp = new_lfp;
3807         *new_lfpp = NULL;
3808         return (0);
3809 }
3810
3811 /*
3812  * This function adds a nfslock lock structure to the list for the associated
3813  * nfsstate and nfslockfile structures. It will be inserted after the
3814  * entry pointed at by insert_lop.
3815  */
3816 static void
3817 nfsrv_insertlock(struct nfslock *new_lop, struct nfslock *insert_lop,
3818     struct nfsstate *stp, struct nfslockfile *lfp)
3819 {
3820         struct nfslock *lop, *nlop;
3821
3822         new_lop->lo_stp = stp;
3823         new_lop->lo_lfp = lfp;
3824
3825         if (stp != NULL) {
3826                 /* Insert in increasing lo_first order */
3827                 lop = LIST_FIRST(&lfp->lf_lock);
3828                 if (lop == LIST_END(&lfp->lf_lock) ||
3829                     new_lop->lo_first <= lop->lo_first) {
3830                         LIST_INSERT_HEAD(&lfp->lf_lock, new_lop, lo_lckfile);
3831                 } else {
3832                         nlop = LIST_NEXT(lop, lo_lckfile);
3833                         while (nlop != LIST_END(&lfp->lf_lock) &&
3834                                nlop->lo_first < new_lop->lo_first) {
3835                                 lop = nlop;
3836                                 nlop = LIST_NEXT(lop, lo_lckfile);
3837                         }
3838                         LIST_INSERT_AFTER(lop, new_lop, lo_lckfile);
3839                 }
3840         } else {
3841                 new_lop->lo_lckfile.le_prev = NULL;     /* list not used */
3842         }
3843
3844         /*
3845          * Insert after insert_lop, which is overloaded as stp or lfp for
3846          * an empty list.
3847          */
3848         if (stp == NULL && (struct nfslockfile *)insert_lop == lfp)
3849                 LIST_INSERT_HEAD(&lfp->lf_locallock, new_lop, lo_lckowner);
3850         else if ((struct nfsstate *)insert_lop == stp)
3851                 LIST_INSERT_HEAD(&stp->ls_lock, new_lop, lo_lckowner);
3852         else
3853                 LIST_INSERT_AFTER(insert_lop, new_lop, lo_lckowner);
3854         if (stp != NULL) {
3855                 nfsstatsv1.srvlocks++;
3856                 nfsrv_openpluslock++;
3857         }
3858 }
3859
3860 /*
3861  * This function updates the locking for a lock owner and given file. It
3862  * maintains a list of lock ranges ordered on increasing file offset that
3863  * are NFSLCK_READ or NFSLCK_WRITE and non-overlapping (aka POSIX style).
3864  * It always adds new_lop to the list and sometimes uses the one pointed
3865  * at by other_lopp.
3866  */
3867 static void
3868 nfsrv_updatelock(struct nfsstate *stp, struct nfslock **new_lopp,
3869     struct nfslock **other_lopp, struct nfslockfile *lfp)
3870 {
3871         struct nfslock *new_lop = *new_lopp;
3872         struct nfslock *lop, *tlop, *ilop;
3873         struct nfslock *other_lop = *other_lopp;
3874         int unlock = 0, myfile = 0;
3875         u_int64_t tmp;
3876
3877         /*
3878          * Work down the list until the lock is merged.
3879          */
3880         if (new_lop->lo_flags & NFSLCK_UNLOCK)
3881                 unlock = 1;
3882         if (stp != NULL) {
3883                 ilop = (struct nfslock *)stp;
3884                 lop = LIST_FIRST(&stp->ls_lock);
3885         } else {
3886                 ilop = (struct nfslock *)lfp;
3887                 lop = LIST_FIRST(&lfp->lf_locallock);
3888         }
3889         while (lop != NULL) {
3890             /*
3891              * Only check locks for this file that aren't before the start of
3892              * new lock's range.
3893              */
3894             if (lop->lo_lfp == lfp) {
3895               myfile = 1;
3896               if (lop->lo_end >= new_lop->lo_first) {
3897                 if (new_lop->lo_end < lop->lo_first) {
3898                         /*
3899                          * If the new lock ends before the start of the
3900                          * current lock's range, no merge, just insert
3901                          * the new lock.
3902                          */
3903                         break;
3904                 }
3905                 if (new_lop->lo_flags == lop->lo_flags ||
3906                     (new_lop->lo_first <= lop->lo_first &&
3907                      new_lop->lo_end >= lop->lo_end)) {
3908                         /*
3909                          * This lock can be absorbed by the new lock/unlock.
3910                          * This happens when it covers the entire range
3911                          * of the old lock or is contiguous
3912                          * with the old lock and is of the same type or an
3913                          * unlock.
3914                          */
3915                         if (lop->lo_first < new_lop->lo_first)
3916                                 new_lop->lo_first = lop->lo_first;
3917                         if (lop->lo_end > new_lop->lo_end)
3918                                 new_lop->lo_end = lop->lo_end;
3919                         tlop = lop;
3920                         lop = LIST_NEXT(lop, lo_lckowner);
3921                         nfsrv_freenfslock(tlop);
3922                         continue;
3923                 }
3924
3925                 /*
3926                  * All these cases are for contiguous locks that are not the
3927                  * same type, so they can't be merged.
3928                  */
3929                 if (new_lop->lo_first <= lop->lo_first) {
3930                         /*
3931                          * This case is where the new lock overlaps with the
3932                          * first part of the old lock. Move the start of the
3933                          * old lock to just past the end of the new lock. The
3934                          * new lock will be inserted in front of the old, since
3935                          * ilop hasn't been updated. (We are done now.)
3936                          */
3937                         lop->lo_first = new_lop->lo_end;
3938                         break;
3939                 }
3940                 if (new_lop->lo_end >= lop->lo_end) {
3941                         /*
3942                          * This case is where the new lock overlaps with the
3943                          * end of the old lock's range. Move the old lock's
3944                          * end to just before the new lock's first and insert
3945                          * the new lock after the old lock.
3946                          * Might not be done yet, since the new lock could
3947                          * overlap further locks with higher ranges.
3948                          */
3949                         lop->lo_end = new_lop->lo_first;
3950                         ilop = lop;
3951                         lop = LIST_NEXT(lop, lo_lckowner);
3952                         continue;
3953                 }
3954                 /*
3955                  * The final case is where the new lock's range is in the
3956                  * middle of the current lock's and splits the current lock
3957                  * up. Use *other_lopp to handle the second part of the
3958                  * split old lock range. (We are done now.)
3959                  * For unlock, we use new_lop as other_lop and tmp, since
3960                  * other_lop and new_lop are the same for this case.
3961                  * We noted the unlock case above, so we don't need
3962                  * new_lop->lo_flags any longer.
3963                  */
3964                 tmp = new_lop->lo_first;
3965                 if (other_lop == NULL) {
3966                         if (!unlock)
3967                                 panic("nfsd srv update unlock");
3968                         other_lop = new_lop;
3969                         *new_lopp = NULL;
3970                 }
3971                 other_lop->lo_first = new_lop->lo_end;
3972                 other_lop->lo_end = lop->lo_end;
3973                 other_lop->lo_flags = lop->lo_flags;
3974                 other_lop->lo_stp = stp;
3975                 other_lop->lo_lfp = lfp;
3976                 lop->lo_end = tmp;
3977                 nfsrv_insertlock(other_lop, lop, stp, lfp);
3978                 *other_lopp = NULL;
3979                 ilop = lop;
3980                 break;
3981               }
3982             }
3983             ilop = lop;
3984             lop = LIST_NEXT(lop, lo_lckowner);
3985             if (myfile && (lop == NULL || lop->lo_lfp != lfp))
3986                 break;
3987         }
3988
3989         /*
3990          * Insert the new lock in the list at the appropriate place.
3991          */
3992         if (!unlock) {
3993                 nfsrv_insertlock(new_lop, ilop, stp, lfp);
3994                 *new_lopp = NULL;
3995         }
3996 }
3997
3998 /*
3999  * This function handles sequencing of locks, etc.
4000  * It returns an error that indicates what the caller should do.
4001  */
4002 static int
4003 nfsrv_checkseqid(struct nfsrv_descript *nd, u_int32_t seqid,
4004     struct nfsstate *stp, struct nfsrvcache *op)
4005 {
4006         int error = 0;
4007
4008         if ((nd->nd_flag & ND_NFSV41) != 0)
4009                 /* NFSv4.1 ignores the open_seqid and lock_seqid. */
4010                 goto out;
4011         if (op != nd->nd_rp)
4012                 panic("nfsrvstate checkseqid");
4013         if (!(op->rc_flag & RC_INPROG))
4014                 panic("nfsrvstate not inprog");
4015         if (stp->ls_op && stp->ls_op->rc_refcnt <= 0) {
4016                 printf("refcnt=%d\n", stp->ls_op->rc_refcnt);
4017                 panic("nfsrvstate op refcnt");
4018         }
4019         if ((stp->ls_seq + 1) == seqid) {
4020                 if (stp->ls_op)
4021                         nfsrvd_derefcache(stp->ls_op);
4022                 stp->ls_op = op;
4023                 nfsrvd_refcache(op);
4024                 stp->ls_seq = seqid;
4025                 goto out;
4026         } else if (stp->ls_seq == seqid && stp->ls_op &&
4027                 op->rc_xid == stp->ls_op->rc_xid &&
4028                 op->rc_refcnt == 0 &&
4029                 op->rc_reqlen == stp->ls_op->rc_reqlen &&
4030                 op->rc_cksum == stp->ls_op->rc_cksum) {
4031                 if (stp->ls_op->rc_flag & RC_INPROG) {
4032                         error = NFSERR_DONTREPLY;
4033                         goto out;
4034                 }
4035                 nd->nd_rp = stp->ls_op;
4036                 nd->nd_rp->rc_flag |= RC_INPROG;
4037                 nfsrvd_delcache(op);
4038                 error = NFSERR_REPLYFROMCACHE;
4039                 goto out;
4040         }
4041         error = NFSERR_BADSEQID;
4042
4043 out:
4044         NFSEXITCODE2(error, nd);
4045         return (error);
4046 }
4047
4048 /*
4049  * Get the client ip address for callbacks. If the strings can't be parsed,
4050  * just set lc_program to 0 to indicate no callbacks are possible.
4051  * (For cases where the address can't be parsed or is 0.0.0.0.0.0, set
4052  *  the address to the client's transport address. This won't be used
4053  *  for callbacks, but can be printed out by nfsstats for info.)
4054  * Return error if the xdr can't be parsed, 0 otherwise.
4055  */
4056 int
4057 nfsrv_getclientipaddr(struct nfsrv_descript *nd, struct nfsclient *clp)
4058 {
4059         u_int32_t *tl;
4060         u_char *cp, *cp2;
4061         int i, j, maxalen = 0, minalen = 0;
4062         sa_family_t af;
4063 #ifdef INET
4064         struct sockaddr_in *rin = NULL, *sin;
4065 #endif
4066 #ifdef INET6
4067         struct sockaddr_in6 *rin6 = NULL, *sin6;
4068 #endif
4069         u_char *addr;
4070         int error = 0, cantparse = 0;
4071         union {
4072                 in_addr_t ival;
4073                 u_char cval[4];
4074         } ip;
4075         union {
4076                 in_port_t sval;
4077                 u_char cval[2];
4078         } port;
4079
4080         /* 8 is the maximum length of the port# string. */
4081         addr = malloc(INET6_ADDRSTRLEN + 8, M_TEMP, M_WAITOK);
4082         clp->lc_req.nr_client = NULL;
4083         clp->lc_req.nr_lock = 0;
4084         af = AF_UNSPEC;
4085         NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
4086         i = fxdr_unsigned(int, *tl);
4087         if (i >= 3 && i <= 4) {
4088                 error = nfsrv_mtostr(nd, addr, i);
4089                 if (error)
4090                         goto nfsmout;
4091 #ifdef INET
4092                 if (!strcmp(addr, "tcp")) {
4093                         clp->lc_flags |= LCL_TCPCALLBACK;
4094                         clp->lc_req.nr_sotype = SOCK_STREAM;
4095                         clp->lc_req.nr_soproto = IPPROTO_TCP;
4096                         af = AF_INET;
4097                 } else if (!strcmp(addr, "udp")) {
4098                         clp->lc_req.nr_sotype = SOCK_DGRAM;
4099                         clp->lc_req.nr_soproto = IPPROTO_UDP;
4100                         af = AF_INET;
4101                 }
4102 #endif
4103 #ifdef INET6
4104                 if (af == AF_UNSPEC) {
4105                         if (!strcmp(addr, "tcp6")) {
4106                                 clp->lc_flags |= LCL_TCPCALLBACK;
4107                                 clp->lc_req.nr_sotype = SOCK_STREAM;
4108                                 clp->lc_req.nr_soproto = IPPROTO_TCP;
4109                                 af = AF_INET6;
4110                         } else if (!strcmp(addr, "udp6")) {
4111                                 clp->lc_req.nr_sotype = SOCK_DGRAM;
4112                                 clp->lc_req.nr_soproto = IPPROTO_UDP;
4113                                 af = AF_INET6;
4114                         }
4115                 }
4116 #endif
4117                 if (af == AF_UNSPEC) {
4118                         cantparse = 1;
4119                 }
4120         } else {
4121                 cantparse = 1;
4122                 if (i > 0) {
4123                         error = nfsm_advance(nd, NFSM_RNDUP(i), -1);
4124                         if (error)
4125                                 goto nfsmout;
4126                 }
4127         }
4128         /*
4129          * The caller has allocated clp->lc_req.nr_nam to be large enough
4130          * for either AF_INET or AF_INET6 and zeroed out the contents.
4131          * maxalen is set to the maximum length of the host IP address string
4132          * plus 8 for the maximum length of the port#.
4133          * minalen is set to the minimum length of the host IP address string
4134          * plus 4 for the minimum length of the port#.
4135          * These lengths do not include NULL termination,
4136          * so INET[6]_ADDRSTRLEN - 1 is used in the calculations.
4137          */
4138         switch (af) {
4139 #ifdef INET
4140         case AF_INET:
4141                 rin = (struct sockaddr_in *)clp->lc_req.nr_nam;
4142                 rin->sin_family = AF_INET;
4143                 rin->sin_len = sizeof(struct sockaddr_in);
4144                 maxalen = INET_ADDRSTRLEN - 1 + 8;
4145                 minalen = 7 + 4;
4146                 break;
4147 #endif
4148 #ifdef INET6
4149         case AF_INET6:
4150                 rin6 = (struct sockaddr_in6 *)clp->lc_req.nr_nam;
4151                 rin6->sin6_family = AF_INET6;
4152                 rin6->sin6_len = sizeof(struct sockaddr_in6);
4153                 maxalen = INET6_ADDRSTRLEN - 1 + 8;
4154                 minalen = 3 + 4;
4155                 break;
4156 #endif
4157         }
4158         NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
4159         i = fxdr_unsigned(int, *tl);
4160         if (i < 0) {
4161                 error = NFSERR_BADXDR;
4162                 goto nfsmout;
4163         } else if (i == 0) {
4164                 cantparse = 1;
4165         } else if (!cantparse && i <= maxalen && i >= minalen) {
4166                 error = nfsrv_mtostr(nd, addr, i);
4167                 if (error)
4168                         goto nfsmout;
4169
4170                 /*
4171                  * Parse out the address fields. We expect 6 decimal numbers
4172                  * separated by '.'s for AF_INET and two decimal numbers
4173                  * preceeded by '.'s for AF_INET6.
4174                  */
4175                 cp = NULL;
4176                 switch (af) {
4177 #ifdef INET6
4178                 /*
4179                  * For AF_INET6, first parse the host address.
4180                  */
4181                 case AF_INET6:
4182                         cp = strchr(addr, '.');
4183                         if (cp != NULL) {
4184                                 *cp++ = '\0';
4185                                 if (inet_pton(af, addr, &rin6->sin6_addr) == 1)
4186                                         i = 4;
4187                                 else {
4188                                         cp = NULL;
4189                                         cantparse = 1;
4190                                 }
4191                         }
4192                         break;
4193 #endif
4194 #ifdef INET
4195                 case AF_INET:
4196                         cp = addr;
4197                         i = 0;
4198                         break;
4199 #endif
4200                 }
4201                 while (cp != NULL && *cp && i < 6) {
4202                         cp2 = cp;
4203                         while (*cp2 && *cp2 != '.')
4204                                 cp2++;
4205                         if (*cp2)
4206                                 *cp2++ = '\0';
4207                         else if (i != 5) {
4208                                 cantparse = 1;
4209                                 break;
4210                         }
4211                         j = nfsrv_getipnumber(cp);
4212                         if (j >= 0) {
4213                                 if (i < 4)
4214                                         ip.cval[3 - i] = j;
4215                                 else
4216                                         port.cval[5 - i] = j;
4217                         } else {
4218                                 cantparse = 1;
4219                                 break;
4220                         }
4221                         cp = cp2;
4222                         i++;
4223                 }
4224                 if (!cantparse) {
4225                         /*
4226                          * The host address INADDR_ANY is (mis)used to indicate
4227                          * "there is no valid callback address".
4228                          */
4229                         switch (af) {
4230 #ifdef INET6
4231                         case AF_INET6:
4232                                 if (!IN6_ARE_ADDR_EQUAL(&rin6->sin6_addr,
4233                                     &in6addr_any))
4234                                         rin6->sin6_port = htons(port.sval);
4235                                 else
4236                                         cantparse = 1;
4237                                 break;
4238 #endif
4239 #ifdef INET
4240                         case AF_INET:
4241                                 if (ip.ival != INADDR_ANY) {
4242                                         rin->sin_addr.s_addr = htonl(ip.ival);
4243                                         rin->sin_port = htons(port.sval);
4244                                 } else {
4245                                         cantparse = 1;
4246                                 }
4247                                 break;
4248 #endif
4249                         }
4250                 }
4251         } else {
4252                 cantparse = 1;
4253                 if (i > 0) {
4254                         error = nfsm_advance(nd, NFSM_RNDUP(i), -1);
4255                         if (error)
4256                                 goto nfsmout;
4257                 }
4258         }
4259         if (cantparse) {
4260                 switch (nd->nd_nam->sa_family) {
4261 #ifdef INET
4262                 case AF_INET:
4263                         sin = (struct sockaddr_in *)nd->nd_nam;
4264                         rin = (struct sockaddr_in *)clp->lc_req.nr_nam;
4265                         rin->sin_family = AF_INET;
4266                         rin->sin_len = sizeof(struct sockaddr_in);
4267                         rin->sin_addr.s_addr = sin->sin_addr.s_addr;
4268                         rin->sin_port = 0x0;
4269                         break;
4270 #endif
4271 #ifdef INET6
4272                 case AF_INET6:
4273                         sin6 = (struct sockaddr_in6 *)nd->nd_nam;
4274                         rin6 = (struct sockaddr_in6 *)clp->lc_req.nr_nam;
4275                         rin6->sin6_family = AF_INET6;
4276                         rin6->sin6_len = sizeof(struct sockaddr_in6);
4277                         rin6->sin6_addr = sin6->sin6_addr;
4278                         rin6->sin6_port = 0x0;
4279                         break;
4280 #endif
4281                 }
4282                 clp->lc_program = 0;
4283         }
4284 nfsmout:
4285         free(addr, M_TEMP);
4286         NFSEXITCODE2(error, nd);
4287         return (error);
4288 }
4289
4290 /*
4291  * Turn a string of up to three decimal digits into a number. Return -1 upon
4292  * error.
4293  */
4294 static int
4295 nfsrv_getipnumber(u_char *cp)
4296 {
4297         int i = 0, j = 0;
4298
4299         while (*cp) {
4300                 if (j > 2 || *cp < '0' || *cp > '9')
4301                         return (-1);
4302                 i *= 10;
4303                 i += (*cp - '0');
4304                 cp++;
4305                 j++;
4306         }
4307         if (i < 256)
4308                 return (i);
4309         return (-1);
4310 }
4311
4312 /*
4313  * This function checks for restart conditions.
4314  */
4315 static int
4316 nfsrv_checkrestart(nfsquad_t clientid, u_int32_t flags,
4317     nfsv4stateid_t *stateidp, int specialid)
4318 {
4319         int ret = 0;
4320
4321         /*
4322          * First check for a server restart. Open, LockT, ReleaseLockOwner
4323          * and DelegPurge have a clientid, the rest a stateid.
4324          */
4325         if (flags &
4326             (NFSLCK_OPEN | NFSLCK_TEST | NFSLCK_RELEASE | NFSLCK_DELEGPURGE)) {
4327                 if (clientid.lval[0] != nfsrvboottime) {
4328                         ret = NFSERR_STALECLIENTID;
4329                         goto out;
4330                 }
4331         } else if (stateidp->other[0] != nfsrvboottime &&
4332                 specialid == 0) {
4333                 ret = NFSERR_STALESTATEID;
4334                 goto out;
4335         }
4336
4337         /*
4338          * Read, Write, Setattr and LockT can return NFSERR_GRACE and do
4339          * not use a lock/open owner seqid#, so the check can be done now.
4340          * (The others will be checked, as required, later.)
4341          */
4342         if (!(flags & (NFSLCK_CHECK | NFSLCK_TEST)))
4343                 goto out;
4344
4345         NFSLOCKSTATE();
4346         ret = nfsrv_checkgrace(NULL, NULL, flags);
4347         NFSUNLOCKSTATE();
4348
4349 out:
4350         NFSEXITCODE(ret);
4351         return (ret);
4352 }
4353
4354 /*
4355  * Check for grace.
4356  */
4357 static int
4358 nfsrv_checkgrace(struct nfsrv_descript *nd, struct nfsclient *clp,
4359     u_int32_t flags)
4360 {
4361         int error = 0, notreclaimed;
4362         struct nfsrv_stable *sp;
4363
4364         if ((nfsrv_stablefirst.nsf_flags & (NFSNSF_UPDATEDONE |
4365              NFSNSF_GRACEOVER)) == 0) {
4366                 /*
4367                  * First, check to see if all of the clients have done a
4368                  * ReclaimComplete.  If so, grace can end now.
4369                  */
4370                 notreclaimed = 0;
4371                 LIST_FOREACH(sp, &nfsrv_stablefirst.nsf_head, nst_list) {
4372                         if ((sp->nst_flag & NFSNST_RECLAIMED) == 0) {
4373                                 notreclaimed = 1;
4374                                 break;
4375                         }
4376                 }
4377                 if (notreclaimed == 0)
4378                         nfsrv_stablefirst.nsf_flags |= (NFSNSF_GRACEOVER |
4379                             NFSNSF_NEEDLOCK);
4380         }
4381
4382         if ((nfsrv_stablefirst.nsf_flags & NFSNSF_GRACEOVER) != 0) {
4383                 if (flags & NFSLCK_RECLAIM) {
4384                         error = NFSERR_NOGRACE;
4385                         goto out;
4386                 }
4387         } else {
4388                 if (!(flags & NFSLCK_RECLAIM)) {
4389                         error = NFSERR_GRACE;
4390                         goto out;
4391                 }
4392                 if (nd != NULL && clp != NULL &&
4393                     (nd->nd_flag & ND_NFSV41) != 0 &&
4394                     (clp->lc_flags & LCL_RECLAIMCOMPLETE) != 0) {
4395                         error = NFSERR_NOGRACE;
4396                         goto out;
4397                 }
4398
4399                 /*
4400                  * If grace is almost over and we are still getting Reclaims,
4401                  * extend grace a bit.
4402                  */
4403                 if ((NFSD_MONOSEC + NFSRV_LEASEDELTA) >
4404                     nfsrv_stablefirst.nsf_eograce)
4405                         nfsrv_stablefirst.nsf_eograce = NFSD_MONOSEC +
4406                                 NFSRV_LEASEDELTA;
4407         }
4408
4409 out:
4410         NFSEXITCODE(error);
4411         return (error);
4412 }
4413
4414 /*
4415  * Do a server callback.
4416  * The "trunc" argument is slightly overloaded and refers to different
4417  * boolean arguments for CBRECALL and CBLAYOUTRECALL.
4418  */
4419 static int
4420 nfsrv_docallback(struct nfsclient *clp, int procnum, nfsv4stateid_t *stateidp,
4421     int trunc, fhandle_t *fhp, struct nfsvattr *nap, nfsattrbit_t *attrbitp,
4422     int laytype, NFSPROC_T *p)
4423 {
4424         struct mbuf *m;
4425         u_int32_t *tl;
4426         struct nfsrv_descript *nd;
4427         struct ucred *cred;
4428         int error = 0;
4429         u_int32_t callback;
4430         struct nfsdsession *sep = NULL;
4431         uint64_t tval;
4432         bool dotls;
4433
4434         nd = malloc(sizeof(*nd), M_TEMP, M_WAITOK | M_ZERO);
4435         cred = newnfs_getcred();
4436         NFSLOCKSTATE(); /* mostly for lc_cbref++ */
4437         if (clp->lc_flags & LCL_NEEDSCONFIRM) {
4438                 NFSUNLOCKSTATE();
4439                 panic("docallb");
4440         }
4441         clp->lc_cbref++;
4442
4443         /*
4444          * Fill the callback program# and version into the request
4445          * structure for newnfs_connect() to use.
4446          */
4447         clp->lc_req.nr_prog = clp->lc_program;
4448 #ifdef notnow
4449         if ((clp->lc_flags & LCL_NFSV41) != 0)
4450                 clp->lc_req.nr_vers = NFSV41_CBVERS;
4451         else
4452 #endif
4453                 clp->lc_req.nr_vers = NFSV4_CBVERS;
4454
4455         /*
4456          * First, fill in some of the fields of nd and cr.
4457          */
4458         nd->nd_flag = ND_NFSV4;
4459         if (clp->lc_flags & LCL_GSS)
4460                 nd->nd_flag |= ND_KERBV;
4461         if ((clp->lc_flags & LCL_NFSV41) != 0)
4462                 nd->nd_flag |= ND_NFSV41;
4463         if ((clp->lc_flags & LCL_NFSV42) != 0)
4464                 nd->nd_flag |= ND_NFSV42;
4465         nd->nd_repstat = 0;
4466         cred->cr_uid = clp->lc_uid;
4467         cred->cr_gid = clp->lc_gid;
4468         callback = clp->lc_callback;
4469         NFSUNLOCKSTATE();
4470         cred->cr_ngroups = 1;
4471
4472         /*
4473          * Get the first mbuf for the request.
4474          */
4475         MGET(m, M_WAITOK, MT_DATA);
4476         m->m_len = 0;
4477         nd->nd_mreq = nd->nd_mb = m;
4478         nd->nd_bpos = mtod(m, caddr_t);
4479
4480         /*
4481          * and build the callback request.
4482          */
4483         if (procnum == NFSV4OP_CBGETATTR) {
4484                 nd->nd_procnum = NFSV4PROC_CBCOMPOUND;
4485                 error = nfsrv_cbcallargs(nd, clp, callback, NFSV4OP_CBGETATTR,
4486                     "CB Getattr", &sep);
4487                 if (error != 0) {
4488                         m_freem(nd->nd_mreq);
4489                         goto errout;
4490                 }
4491                 (void)nfsm_fhtom(nd, (u_int8_t *)fhp, NFSX_MYFH, 0);
4492                 (void)nfsrv_putattrbit(nd, attrbitp);
4493         } else if (procnum == NFSV4OP_CBRECALL) {
4494                 nd->nd_procnum = NFSV4PROC_CBCOMPOUND;
4495                 error = nfsrv_cbcallargs(nd, clp, callback, NFSV4OP_CBRECALL,
4496                     "CB Recall", &sep);
4497                 if (error != 0) {
4498                         m_freem(nd->nd_mreq);
4499                         goto errout;
4500                 }
4501                 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED + NFSX_STATEID);
4502                 *tl++ = txdr_unsigned(stateidp->seqid);
4503                 NFSBCOPY((caddr_t)stateidp->other, (caddr_t)tl,
4504                     NFSX_STATEIDOTHER);
4505                 tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED);
4506                 if (trunc)
4507                         *tl = newnfs_true;
4508                 else
4509                         *tl = newnfs_false;
4510                 (void)nfsm_fhtom(nd, (u_int8_t *)fhp, NFSX_MYFH, 0);
4511         } else if (procnum == NFSV4OP_CBLAYOUTRECALL) {
4512                 NFSD_DEBUG(4, "docallback layout recall\n");
4513                 nd->nd_procnum = NFSV4PROC_CBCOMPOUND;
4514                 error = nfsrv_cbcallargs(nd, clp, callback,
4515                     NFSV4OP_CBLAYOUTRECALL, "CB Reclayout", &sep);
4516                 NFSD_DEBUG(4, "aft cbcallargs=%d\n", error);
4517                 if (error != 0) {
4518                         m_freem(nd->nd_mreq);
4519                         goto errout;
4520                 }
4521                 NFSM_BUILD(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
4522                 *tl++ = txdr_unsigned(laytype);
4523                 *tl++ = txdr_unsigned(NFSLAYOUTIOMODE_ANY);
4524                 if (trunc)
4525                         *tl++ = newnfs_true;
4526                 else
4527                         *tl++ = newnfs_false;
4528                 *tl = txdr_unsigned(NFSV4LAYOUTRET_FILE);
4529                 nfsm_fhtom(nd, (uint8_t *)fhp, NFSX_MYFH, 0);
4530                 NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_HYPER + NFSX_STATEID);
4531                 tval = 0;
4532                 txdr_hyper(tval, tl); tl += 2;
4533                 tval = UINT64_MAX;
4534                 txdr_hyper(tval, tl); tl += 2;
4535                 *tl++ = txdr_unsigned(stateidp->seqid);
4536                 NFSBCOPY(stateidp->other, tl, NFSX_STATEIDOTHER);
4537                 tl += (NFSX_STATEIDOTHER / NFSX_UNSIGNED);
4538                 NFSD_DEBUG(4, "aft args\n");
4539         } else if (procnum == NFSV4PROC_CBNULL) {
4540                 nd->nd_procnum = NFSV4PROC_CBNULL;
4541                 if ((clp->lc_flags & LCL_NFSV41) != 0) {
4542                         error = nfsv4_getcbsession(clp, &sep);
4543                         if (error != 0) {
4544                                 m_freem(nd->nd_mreq);
4545                                 goto errout;
4546                         }
4547                 }
4548         } else {
4549                 error = NFSERR_SERVERFAULT;
4550                 m_freem(nd->nd_mreq);
4551                 goto errout;
4552         }
4553
4554         /*
4555          * Call newnfs_connect(), as required, and then newnfs_request().
4556          */
4557         dotls = false;
4558         if ((clp->lc_flags & LCL_TLSCB) != 0)
4559                 dotls = true;
4560         (void) newnfs_sndlock(&clp->lc_req.nr_lock);
4561         if (clp->lc_req.nr_client == NULL) {
4562                 if ((clp->lc_flags & LCL_NFSV41) != 0) {
4563                         error = ECONNREFUSED;
4564                         nfsrv_freesession(sep, NULL);
4565                 } else if (nd->nd_procnum == NFSV4PROC_CBNULL)
4566                         error = newnfs_connect(NULL, &clp->lc_req, cred,
4567                             NULL, 1, dotls);
4568                 else
4569                         error = newnfs_connect(NULL, &clp->lc_req, cred,
4570                             NULL, 3, dotls);
4571         }
4572         newnfs_sndunlock(&clp->lc_req.nr_lock);
4573         NFSD_DEBUG(4, "aft sndunlock=%d\n", error);
4574         if (!error) {
4575                 if ((nd->nd_flag & ND_NFSV41) != 0) {
4576                         KASSERT(sep != NULL, ("sep NULL"));
4577                         if (sep->sess_cbsess.nfsess_xprt != NULL)
4578                                 error = newnfs_request(nd, NULL, clp,
4579                                     &clp->lc_req, NULL, NULL, cred,
4580                                     clp->lc_program, clp->lc_req.nr_vers, NULL,
4581                                     1, NULL, &sep->sess_cbsess);
4582                         else {
4583                                 /*
4584                                  * This should probably never occur, but if a
4585                                  * client somehow does an RPC without a
4586                                  * SequenceID Op that causes a callback just
4587                                  * after the nfsd threads have been terminated
4588                                  * and restared we could conceivably get here
4589                                  * without a backchannel xprt.
4590                                  */
4591                                 printf("nfsrv_docallback: no xprt\n");
4592                                 error = ECONNREFUSED;
4593                         }
4594                         NFSD_DEBUG(4, "aft newnfs_request=%d\n", error);
4595                         nfsrv_freesession(sep, NULL);
4596                 } else
4597                         error = newnfs_request(nd, NULL, clp, &clp->lc_req,
4598                             NULL, NULL, cred, clp->lc_program,
4599                             clp->lc_req.nr_vers, NULL, 1, NULL, NULL);
4600         }
4601 errout:
4602         NFSFREECRED(cred);
4603
4604         /*
4605          * If error is set here, the Callback path isn't working
4606          * properly, so twiddle the appropriate LCL_ flags.
4607          * (nd_repstat != 0 indicates the Callback path is working,
4608          *  but the callback failed on the client.)
4609          */
4610         if (error) {
4611                 /*
4612                  * Mark the callback pathway down, which disabled issuing
4613                  * of delegations and gets Renew to return NFSERR_CBPATHDOWN.
4614                  */
4615                 NFSLOCKSTATE();
4616                 clp->lc_flags |= LCL_CBDOWN;
4617                 NFSUNLOCKSTATE();
4618         } else {
4619                 /*
4620                  * Callback worked. If the callback path was down, disable
4621                  * callbacks, so no more delegations will be issued. (This
4622                  * is done on the assumption that the callback pathway is
4623                  * flakey.)
4624                  */
4625                 NFSLOCKSTATE();
4626                 if (clp->lc_flags & LCL_CBDOWN)
4627                         clp->lc_flags &= ~(LCL_CBDOWN | LCL_CALLBACKSON);
4628                 NFSUNLOCKSTATE();
4629                 if (nd->nd_repstat) {
4630                         error = nd->nd_repstat;
4631                         NFSD_DEBUG(1, "nfsrv_docallback op=%d err=%d\n",
4632                             procnum, error);
4633                 } else if (error == 0 && procnum == NFSV4OP_CBGETATTR)
4634                         error = nfsv4_loadattr(nd, NULL, nap, NULL, NULL, 0,
4635                             NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL,
4636                             p, NULL);
4637                 m_freem(nd->nd_mrep);
4638         }
4639         NFSLOCKSTATE();
4640         clp->lc_cbref--;
4641         if ((clp->lc_flags & LCL_WAKEUPWANTED) && clp->lc_cbref == 0) {
4642                 clp->lc_flags &= ~LCL_WAKEUPWANTED;
4643                 wakeup(clp);
4644         }
4645         NFSUNLOCKSTATE();
4646
4647         free(nd, M_TEMP);
4648         NFSEXITCODE(error);
4649         return (error);
4650 }
4651
4652 /*
4653  * Set up the compound RPC for the callback.
4654  */
4655 static int
4656 nfsrv_cbcallargs(struct nfsrv_descript *nd, struct nfsclient *clp,
4657     uint32_t callback, int op, const char *optag, struct nfsdsession **sepp)
4658 {
4659         uint32_t *tl;
4660         int error, len;
4661
4662         len = strlen(optag);
4663         (void)nfsm_strtom(nd, optag, len);
4664         NFSM_BUILD(tl, uint32_t *, 4 * NFSX_UNSIGNED);
4665         if ((nd->nd_flag & ND_NFSV41) != 0) {
4666                 if ((nd->nd_flag & ND_NFSV42) != 0)
4667                         *tl++ = txdr_unsigned(NFSV42_MINORVERSION);
4668                 else
4669                         *tl++ = txdr_unsigned(NFSV41_MINORVERSION);
4670                 *tl++ = txdr_unsigned(callback);
4671                 *tl++ = txdr_unsigned(2);
4672                 *tl = txdr_unsigned(NFSV4OP_CBSEQUENCE);
4673                 error = nfsv4_setcbsequence(nd, clp, 1, sepp);
4674                 if (error != 0)
4675                         return (error);
4676                 NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
4677                 *tl = txdr_unsigned(op);
4678         } else {
4679                 *tl++ = txdr_unsigned(NFSV4_MINORVERSION);
4680                 *tl++ = txdr_unsigned(callback);
4681                 *tl++ = txdr_unsigned(1);
4682                 *tl = txdr_unsigned(op);
4683         }
4684         return (0);
4685 }
4686
4687 /*
4688  * Return the next index# for a clientid. Mostly just increment and return
4689  * the next one, but... if the 32bit unsigned does actually wrap around,
4690  * it should be rebooted.
4691  * At an average rate of one new client per second, it will wrap around in
4692  * approximately 136 years. (I think the server will have been shut
4693  * down or rebooted before then.)
4694  */
4695 static u_int32_t
4696 nfsrv_nextclientindex(void)
4697 {
4698         static u_int32_t client_index = 0;
4699
4700         client_index++;
4701         if (client_index != 0)
4702                 return (client_index);
4703
4704         printf("%s: out of clientids\n", __func__);
4705         return (client_index);
4706 }
4707
4708 /*
4709  * Return the next index# for a stateid. Mostly just increment and return
4710  * the next one, but... if the 32bit unsigned does actually wrap around
4711  * (will a BSD server stay up that long?), find
4712  * new start and end values.
4713  */
4714 static u_int32_t
4715 nfsrv_nextstateindex(struct nfsclient *clp)
4716 {
4717         struct nfsstate *stp;
4718         int i;
4719         u_int32_t canuse, min_index, max_index;
4720
4721         if (!(clp->lc_flags & LCL_INDEXNOTOK)) {
4722                 clp->lc_stateindex++;
4723                 if (clp->lc_stateindex != clp->lc_statemaxindex)
4724                         return (clp->lc_stateindex);
4725         }
4726
4727         /*
4728          * Yuck, we've hit the end.
4729          * Look for a new min and max.
4730          */
4731         min_index = 0;
4732         max_index = 0xffffffff;
4733         for (i = 0; i < nfsrv_statehashsize; i++) {
4734             LIST_FOREACH(stp, &clp->lc_stateid[i], ls_hash) {
4735                 if (stp->ls_stateid.other[2] > 0x80000000) {
4736                     if (stp->ls_stateid.other[2] < max_index)
4737                         max_index = stp->ls_stateid.other[2];
4738                 } else {
4739                     if (stp->ls_stateid.other[2] > min_index)
4740                         min_index = stp->ls_stateid.other[2];
4741                 }
4742             }
4743         }
4744
4745         /*
4746          * Yikes, highly unlikely, but I'll handle it anyhow.
4747          */
4748         if (min_index == 0x80000000 && max_index == 0x80000001) {
4749             canuse = 0;
4750             /*
4751              * Loop around until we find an unused entry. Return that
4752              * and set LCL_INDEXNOTOK, so the search will continue next time.
4753              * (This is one of those rare cases where a goto is the
4754              *  cleanest way to code the loop.)
4755              */
4756 tryagain:
4757             for (i = 0; i < nfsrv_statehashsize; i++) {
4758                 LIST_FOREACH(stp, &clp->lc_stateid[i], ls_hash) {
4759                     if (stp->ls_stateid.other[2] == canuse) {
4760                         canuse++;
4761                         goto tryagain;
4762                     }
4763                 }
4764             }
4765             clp->lc_flags |= LCL_INDEXNOTOK;
4766             return (canuse);
4767         }
4768
4769         /*
4770          * Ok to start again from min + 1.
4771          */
4772         clp->lc_stateindex = min_index + 1;
4773         clp->lc_statemaxindex = max_index;
4774         clp->lc_flags &= ~LCL_INDEXNOTOK;
4775         return (clp->lc_stateindex);
4776 }
4777
4778 /*
4779  * The following functions handle the stable storage file that deals with
4780  * the edge conditions described in RFC3530 Sec. 8.6.3.
4781  * The file is as follows:
4782  * - a single record at the beginning that has the lease time of the
4783  *   previous server instance (before the last reboot) and the nfsrvboottime
4784  *   values for the previous server boots.
4785  *   These previous boot times are used to ensure that the current
4786  *   nfsrvboottime does not, somehow, get set to a previous one.
4787  *   (This is important so that Stale ClientIDs and StateIDs can
4788  *    be recognized.)
4789  *   The number of previous nfsvrboottime values precedes the list.
4790  * - followed by some number of appended records with:
4791  *   - client id string
4792  *   - flag that indicates it is a record revoking state via lease
4793  *     expiration or similar
4794  *     OR has successfully acquired state.
4795  * These structures vary in length, with the client string at the end, up
4796  * to NFSV4_OPAQUELIMIT in size.
4797  *
4798  * At the end of the grace period, the file is truncated, the first
4799  * record is rewritten with updated information and any acquired state
4800  * records for successful reclaims of state are written.
4801  *
4802  * Subsequent records are appended when the first state is issued to
4803  * a client and when state is revoked for a client.
4804  *
4805  * When reading the file in, state issued records that come later in
4806  * the file override older ones, since the append log is in cronological order.
4807  * If, for some reason, the file can't be read, the grace period is
4808  * immediately terminated and all reclaims get NFSERR_NOGRACE.
4809  */
4810
4811 /*
4812  * Read in the stable storage file. Called by nfssvc() before the nfsd
4813  * processes start servicing requests.
4814  */
4815 void
4816 nfsrv_setupstable(NFSPROC_T *p)
4817 {
4818         struct nfsrv_stablefirst *sf = &nfsrv_stablefirst;
4819         struct nfsrv_stable *sp, *nsp;
4820         struct nfst_rec *tsp;
4821         int error, i, tryagain;
4822         off_t off = 0;
4823         ssize_t aresid, len;
4824
4825         /*
4826          * If NFSNSF_UPDATEDONE is set, this is a restart of the nfsds without
4827          * a reboot, so state has not been lost.
4828          */
4829         if (sf->nsf_flags & NFSNSF_UPDATEDONE)
4830                 return;
4831         /*
4832          * Set Grace over just until the file reads successfully.
4833          */
4834         nfsrvboottime = time_second;
4835         LIST_INIT(&sf->nsf_head);
4836         sf->nsf_flags = (NFSNSF_GRACEOVER | NFSNSF_NEEDLOCK);
4837         sf->nsf_eograce = NFSD_MONOSEC + NFSRV_LEASEDELTA;
4838         if (sf->nsf_fp == NULL)
4839                 return;
4840         error = NFSD_RDWR(UIO_READ, NFSFPVNODE(sf->nsf_fp),
4841             (caddr_t)&sf->nsf_rec, sizeof (struct nfsf_rec), off, UIO_SYSSPACE,
4842             0, NFSFPCRED(sf->nsf_fp), &aresid, p);
4843         if (error || aresid || sf->nsf_numboots == 0 ||
4844                 sf->nsf_numboots > NFSNSF_MAXNUMBOOTS)
4845                 return;
4846
4847         /*
4848          * Now, read in the boottimes.
4849          */
4850         sf->nsf_bootvals = (time_t *)malloc((sf->nsf_numboots + 1) *
4851                 sizeof (time_t), M_TEMP, M_WAITOK);
4852         off = sizeof (struct nfsf_rec);
4853         error = NFSD_RDWR(UIO_READ, NFSFPVNODE(sf->nsf_fp),
4854             (caddr_t)sf->nsf_bootvals, sf->nsf_numboots * sizeof (time_t), off,
4855             UIO_SYSSPACE, 0, NFSFPCRED(sf->nsf_fp), &aresid, p);
4856         if (error || aresid) {
4857                 free(sf->nsf_bootvals, M_TEMP);
4858                 sf->nsf_bootvals = NULL;
4859                 return;
4860         }
4861
4862         /*
4863          * Make sure this nfsrvboottime is different from all recorded
4864          * previous ones.
4865          */
4866         do {
4867                 tryagain = 0;
4868                 for (i = 0; i < sf->nsf_numboots; i++) {
4869                         if (nfsrvboottime == sf->nsf_bootvals[i]) {
4870                                 nfsrvboottime++;
4871                                 tryagain = 1;
4872                                 break;
4873                         }
4874                 }
4875         } while (tryagain);
4876
4877         sf->nsf_flags |= NFSNSF_OK;
4878         off += (sf->nsf_numboots * sizeof (time_t));
4879
4880         /*
4881          * Read through the file, building a list of records for grace
4882          * checking.
4883          * Each record is between sizeof (struct nfst_rec) and
4884          * sizeof (struct nfst_rec) + NFSV4_OPAQUELIMIT - 1
4885          * and is actually sizeof (struct nfst_rec) + nst_len - 1.
4886          */
4887         tsp = (struct nfst_rec *)malloc(sizeof (struct nfst_rec) +
4888                 NFSV4_OPAQUELIMIT - 1, M_TEMP, M_WAITOK);
4889         do {
4890             error = NFSD_RDWR(UIO_READ, NFSFPVNODE(sf->nsf_fp),
4891                 (caddr_t)tsp, sizeof (struct nfst_rec) + NFSV4_OPAQUELIMIT - 1,
4892                 off, UIO_SYSSPACE, 0, NFSFPCRED(sf->nsf_fp), &aresid, p);
4893             len = (sizeof (struct nfst_rec) + NFSV4_OPAQUELIMIT - 1) - aresid;
4894             if (error || (len > 0 && (len < sizeof (struct nfst_rec) ||
4895                 len < (sizeof (struct nfst_rec) + tsp->len - 1)))) {
4896                 /*
4897                  * Yuck, the file has been corrupted, so just return
4898                  * after clearing out any restart state, so the grace period
4899                  * is over.
4900                  */
4901                 LIST_FOREACH_SAFE(sp, &sf->nsf_head, nst_list, nsp) {
4902                         LIST_REMOVE(sp, nst_list);
4903                         free(sp, M_TEMP);
4904                 }
4905                 free(tsp, M_TEMP);
4906                 sf->nsf_flags &= ~NFSNSF_OK;
4907                 free(sf->nsf_bootvals, M_TEMP);
4908                 sf->nsf_bootvals = NULL;
4909                 return;
4910             }
4911             if (len > 0) {
4912                 off += sizeof (struct nfst_rec) + tsp->len - 1;
4913                 /*
4914                  * Search the list for a matching client.
4915                  */
4916                 LIST_FOREACH(sp, &sf->nsf_head, nst_list) {
4917                         if (tsp->len == sp->nst_len &&
4918                             !NFSBCMP(tsp->client, sp->nst_client, tsp->len))
4919                                 break;
4920                 }
4921                 if (sp == LIST_END(&sf->nsf_head)) {
4922                         sp = (struct nfsrv_stable *)malloc(tsp->len +
4923                                 sizeof (struct nfsrv_stable) - 1, M_TEMP,
4924                                 M_WAITOK);
4925                         NFSBCOPY((caddr_t)tsp, (caddr_t)&sp->nst_rec,
4926                                 sizeof (struct nfst_rec) + tsp->len - 1);
4927                         LIST_INSERT_HEAD(&sf->nsf_head, sp, nst_list);
4928                 } else {
4929                         if (tsp->flag == NFSNST_REVOKE)
4930                                 sp->nst_flag |= NFSNST_REVOKE;
4931                         else
4932                                 /*
4933                                  * A subsequent timestamp indicates the client
4934                                  * did a setclientid/confirm and any previous
4935                                  * revoke is no longer relevant.
4936                                  */
4937                                 sp->nst_flag &= ~NFSNST_REVOKE;
4938                 }
4939             }
4940         } while (len > 0);
4941         free(tsp, M_TEMP);
4942         sf->nsf_flags = NFSNSF_OK;
4943         sf->nsf_eograce = NFSD_MONOSEC + sf->nsf_lease +
4944                 NFSRV_LEASEDELTA;
4945 }
4946
4947 /*
4948  * Update the stable storage file, now that the grace period is over.
4949  */
4950 void
4951 nfsrv_updatestable(NFSPROC_T *p)
4952 {
4953         struct nfsrv_stablefirst *sf = &nfsrv_stablefirst;
4954         struct nfsrv_stable *sp, *nsp;
4955         int i;
4956         struct nfsvattr nva;
4957         vnode_t vp;
4958 #if defined(__FreeBSD_version) && (__FreeBSD_version >= 500000)
4959         mount_t mp = NULL;
4960 #endif
4961         int error;
4962
4963         if (sf->nsf_fp == NULL || (sf->nsf_flags & NFSNSF_UPDATEDONE))
4964                 return;
4965         sf->nsf_flags |= NFSNSF_UPDATEDONE;
4966         /*
4967          * Ok, we need to rewrite the stable storage file.
4968          * - truncate to 0 length
4969          * - write the new first structure
4970          * - loop through the data structures, writing out any that
4971          *   have timestamps older than the old boot
4972          */
4973         if (sf->nsf_bootvals) {
4974                 sf->nsf_numboots++;
4975                 for (i = sf->nsf_numboots - 2; i >= 0; i--)
4976                         sf->nsf_bootvals[i + 1] = sf->nsf_bootvals[i];
4977         } else {
4978                 sf->nsf_numboots = 1;
4979                 sf->nsf_bootvals = (time_t *)malloc(sizeof (time_t),
4980                         M_TEMP, M_WAITOK);
4981         }
4982         sf->nsf_bootvals[0] = nfsrvboottime;
4983         sf->nsf_lease = nfsrv_lease;
4984         NFSVNO_ATTRINIT(&nva);
4985         NFSVNO_SETATTRVAL(&nva, size, 0);
4986         vp = NFSFPVNODE(sf->nsf_fp);
4987         vn_start_write(vp, &mp, V_WAIT);
4988         if (NFSVOPLOCK(vp, LK_EXCLUSIVE) == 0) {
4989                 error = nfsvno_setattr(vp, &nva, NFSFPCRED(sf->nsf_fp), p,
4990                     NULL);
4991                 NFSVOPUNLOCK(vp);
4992         } else
4993                 error = EPERM;
4994         vn_finished_write(mp);
4995         if (!error)
4996             error = NFSD_RDWR(UIO_WRITE, vp,
4997                 (caddr_t)&sf->nsf_rec, sizeof (struct nfsf_rec), (off_t)0,
4998                 UIO_SYSSPACE, IO_SYNC, NFSFPCRED(sf->nsf_fp), NULL, p);
4999         if (!error)
5000             error = NFSD_RDWR(UIO_WRITE, vp,
5001                 (caddr_t)sf->nsf_bootvals,
5002                 sf->nsf_numboots * sizeof (time_t),
5003                 (off_t)(sizeof (struct nfsf_rec)),
5004                 UIO_SYSSPACE, IO_SYNC, NFSFPCRED(sf->nsf_fp), NULL, p);
5005         free(sf->nsf_bootvals, M_TEMP);
5006         sf->nsf_bootvals = NULL;
5007         if (error) {
5008                 sf->nsf_flags &= ~NFSNSF_OK;
5009                 printf("EEK! Can't write NfsV4 stable storage file\n");
5010                 return;
5011         }
5012         sf->nsf_flags |= NFSNSF_OK;
5013
5014         /*
5015          * Loop through the list and write out timestamp records for
5016          * any clients that successfully reclaimed state.
5017          */
5018         LIST_FOREACH_SAFE(sp, &sf->nsf_head, nst_list, nsp) {
5019                 if (sp->nst_flag & NFSNST_GOTSTATE) {
5020                         nfsrv_writestable(sp->nst_client, sp->nst_len,
5021                                 NFSNST_NEWSTATE, p);
5022                         sp->nst_clp->lc_flags |= LCL_STAMPEDSTABLE;
5023                 }
5024                 LIST_REMOVE(sp, nst_list);
5025                 free(sp, M_TEMP);
5026         }
5027         nfsrv_backupstable();
5028 }
5029
5030 /*
5031  * Append a record to the stable storage file.
5032  */
5033 void
5034 nfsrv_writestable(u_char *client, int len, int flag, NFSPROC_T *p)
5035 {
5036         struct nfsrv_stablefirst *sf = &nfsrv_stablefirst;
5037         struct nfst_rec *sp;
5038         int error;
5039
5040         if (!(sf->nsf_flags & NFSNSF_OK) || sf->nsf_fp == NULL)
5041                 return;
5042         sp = (struct nfst_rec *)malloc(sizeof (struct nfst_rec) +
5043                 len - 1, M_TEMP, M_WAITOK);
5044         sp->len = len;
5045         NFSBCOPY(client, sp->client, len);
5046         sp->flag = flag;
5047         error = NFSD_RDWR(UIO_WRITE, NFSFPVNODE(sf->nsf_fp),
5048             (caddr_t)sp, sizeof (struct nfst_rec) + len - 1, (off_t)0,
5049             UIO_SYSSPACE, (IO_SYNC | IO_APPEND), NFSFPCRED(sf->nsf_fp), NULL, p);
5050         free(sp, M_TEMP);
5051         if (error) {
5052                 sf->nsf_flags &= ~NFSNSF_OK;
5053                 printf("EEK! Can't write NfsV4 stable storage file\n");
5054         }
5055 }
5056
5057 /*
5058  * This function is called during the grace period to mark a client
5059  * that successfully reclaimed state.
5060  */
5061 static void
5062 nfsrv_markstable(struct nfsclient *clp)
5063 {
5064         struct nfsrv_stable *sp;
5065
5066         /*
5067          * First find the client structure.
5068          */
5069         LIST_FOREACH(sp, &nfsrv_stablefirst.nsf_head, nst_list) {
5070                 if (sp->nst_len == clp->lc_idlen &&
5071                     !NFSBCMP(sp->nst_client, clp->lc_id, sp->nst_len))
5072                         break;
5073         }
5074         if (sp == LIST_END(&nfsrv_stablefirst.nsf_head))
5075                 return;
5076
5077         /*
5078          * Now, just mark it and set the nfsclient back pointer.
5079          */
5080         sp->nst_flag |= NFSNST_GOTSTATE;
5081         sp->nst_clp = clp;
5082 }
5083
5084 /*
5085  * This function is called when a NFSv4.1 client does a ReclaimComplete.
5086  * Very similar to nfsrv_markstable(), except for the flag being set.
5087  */
5088 static void
5089 nfsrv_markreclaim(struct nfsclient *clp)
5090 {
5091         struct nfsrv_stable *sp;
5092
5093         /*
5094          * First find the client structure.
5095          */
5096         LIST_FOREACH(sp, &nfsrv_stablefirst.nsf_head, nst_list) {
5097                 if (sp->nst_len == clp->lc_idlen &&
5098                     !NFSBCMP(sp->nst_client, clp->lc_id, sp->nst_len))
5099                         break;
5100         }
5101         if (sp == LIST_END(&nfsrv_stablefirst.nsf_head))
5102                 return;
5103
5104         /*
5105          * Now, just set the flag.
5106          */
5107         sp->nst_flag |= NFSNST_RECLAIMED;
5108 }
5109
5110 /*
5111  * This function is called for a reclaim, to see if it gets grace.
5112  * It returns 0 if a reclaim is allowed, 1 otherwise.
5113  */
5114 static int
5115 nfsrv_checkstable(struct nfsclient *clp)
5116 {
5117         struct nfsrv_stable *sp;
5118
5119         /*
5120          * First, find the entry for the client.
5121          */
5122         LIST_FOREACH(sp, &nfsrv_stablefirst.nsf_head, nst_list) {
5123                 if (sp->nst_len == clp->lc_idlen &&
5124                     !NFSBCMP(sp->nst_client, clp->lc_id, sp->nst_len))
5125                         break;
5126         }
5127
5128         /*
5129          * If not in the list, state was revoked or no state was issued
5130          * since the previous reboot, a reclaim is denied.
5131          */
5132         if (sp == LIST_END(&nfsrv_stablefirst.nsf_head) ||
5133             (sp->nst_flag & NFSNST_REVOKE) ||
5134             !(nfsrv_stablefirst.nsf_flags & NFSNSF_OK))
5135                 return (1);
5136         return (0);
5137 }
5138
5139 /*
5140  * Test for and try to clear out a conflicting client. This is called by
5141  * nfsrv_lockctrl() and nfsrv_openctrl() when conflicts with other clients
5142  * a found.
5143  * The trick here is that it can't revoke a conflicting client with an
5144  * expired lease unless it holds the v4root lock, so...
5145  * If no v4root lock, get the lock and return 1 to indicate "try again".
5146  * Return 0 to indicate the conflict can't be revoked and 1 to indicate
5147  * the revocation worked and the conflicting client is "bye, bye", so it
5148  * can be tried again.
5149  * Return 2 to indicate that the vnode is VIRF_DOOMED after NFSVOPLOCK().
5150  * Unlocks State before a non-zero value is returned.
5151  */
5152 static int
5153 nfsrv_clientconflict(struct nfsclient *clp, int *haslockp, vnode_t vp,
5154     NFSPROC_T *p)
5155 {
5156         int gotlock, lktype = 0;
5157
5158         /*
5159          * If lease hasn't expired, we can't fix it.
5160          */
5161         if (clp->lc_expiry >= NFSD_MONOSEC ||
5162             !(nfsrv_stablefirst.nsf_flags & NFSNSF_UPDATEDONE))
5163                 return (0);
5164         if (*haslockp == 0) {
5165                 NFSUNLOCKSTATE();
5166                 if (vp != NULL) {
5167                         lktype = NFSVOPISLOCKED(vp);
5168                         NFSVOPUNLOCK(vp);
5169                 }
5170                 NFSLOCKV4ROOTMUTEX();
5171                 nfsv4_relref(&nfsv4rootfs_lock);
5172                 do {
5173                         gotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL,
5174                             NFSV4ROOTLOCKMUTEXPTR, NULL);
5175                 } while (!gotlock);
5176                 NFSUNLOCKV4ROOTMUTEX();
5177                 *haslockp = 1;
5178                 if (vp != NULL) {
5179                         NFSVOPLOCK(vp, lktype | LK_RETRY);
5180                         if (VN_IS_DOOMED(vp))
5181                                 return (2);
5182                 }
5183                 return (1);
5184         }
5185         NFSUNLOCKSTATE();
5186
5187         /*
5188          * Ok, we can expire the conflicting client.
5189          */
5190         nfsrv_writestable(clp->lc_id, clp->lc_idlen, NFSNST_REVOKE, p);
5191         nfsrv_backupstable();
5192         nfsrv_cleanclient(clp, p);
5193         nfsrv_freedeleglist(&clp->lc_deleg);
5194         nfsrv_freedeleglist(&clp->lc_olddeleg);
5195         LIST_REMOVE(clp, lc_hash);
5196         nfsrv_zapclient(clp, p);
5197         return (1);
5198 }
5199
5200 /*
5201  * Resolve a delegation conflict.
5202  * Returns 0 to indicate the conflict was resolved without sleeping.
5203  * Return -1 to indicate that the caller should check for conflicts again.
5204  * Return > 0 for an error that should be returned, normally NFSERR_DELAY.
5205  *
5206  * Also, manipulate the nfsv4root_lock, as required. It isn't changed
5207  * for a return of 0, since there was no sleep and it could be required
5208  * later. It is released for a return of NFSERR_DELAY, since the caller
5209  * will return that error. It is released when a sleep was done waiting
5210  * for the delegation to be returned or expire (so that other nfsds can
5211  * handle ops). Then, it must be acquired for the write to stable storage.
5212  * (This function is somewhat similar to nfsrv_clientconflict(), but
5213  *  the semantics differ in a couple of subtle ways. The return of 0
5214  *  indicates the conflict was resolved without sleeping here, not
5215  *  that the conflict can't be resolved and the handling of nfsv4root_lock
5216  *  differs, as noted above.)
5217  * Unlocks State before returning a non-zero value.
5218  */
5219 static int
5220 nfsrv_delegconflict(struct nfsstate *stp, int *haslockp, NFSPROC_T *p,
5221     vnode_t vp)
5222 {
5223         struct nfsclient *clp = stp->ls_clp;
5224         int gotlock, error, lktype = 0, retrycnt, zapped_clp;
5225         nfsv4stateid_t tstateid;
5226         fhandle_t tfh;
5227
5228         /*
5229          * If the conflict is with an old delegation...
5230          */
5231         if (stp->ls_flags & NFSLCK_OLDDELEG) {
5232                 /*
5233                  * You can delete it, if it has expired.
5234                  */
5235                 if (clp->lc_delegtime < NFSD_MONOSEC) {
5236                         nfsrv_freedeleg(stp);
5237                         NFSUNLOCKSTATE();
5238                         error = -1;
5239                         goto out;
5240                 }
5241                 NFSUNLOCKSTATE();
5242                 /*
5243                  * During this delay, the old delegation could expire or it
5244                  * could be recovered by the client via an Open with
5245                  * CLAIM_DELEGATE_PREV.
5246                  * Release the nfsv4root_lock, if held.
5247                  */
5248                 if (*haslockp) {
5249                         *haslockp = 0;
5250                         NFSLOCKV4ROOTMUTEX();
5251                         nfsv4_unlock(&nfsv4rootfs_lock, 1);
5252                         NFSUNLOCKV4ROOTMUTEX();
5253                 }
5254                 error = NFSERR_DELAY;
5255                 goto out;
5256         }
5257
5258         /*
5259          * It's a current delegation, so:
5260          * - check to see if the delegation has expired
5261          *   - if so, get the v4root lock and then expire it
5262          */
5263         if (!(stp->ls_flags & NFSLCK_DELEGRECALL)) {
5264                 /*
5265                  * - do a recall callback, since not yet done
5266                  * For now, never allow truncate to be set. To use
5267                  * truncate safely, it must be guaranteed that the
5268                  * Remove, Rename or Setattr with size of 0 will
5269                  * succeed and that would require major changes to
5270                  * the VFS/Vnode OPs.
5271                  * Set the expiry time large enough so that it won't expire
5272                  * until after the callback, then set it correctly, once
5273                  * the callback is done. (The delegation will now time
5274                  * out whether or not the Recall worked ok. The timeout
5275                  * will be extended when ops are done on the delegation
5276                  * stateid, up to the timelimit.)
5277                  */
5278                 stp->ls_delegtime = NFSD_MONOSEC + (2 * nfsrv_lease) +
5279                     NFSRV_LEASEDELTA;
5280                 stp->ls_delegtimelimit = NFSD_MONOSEC + (6 * nfsrv_lease) +
5281                     NFSRV_LEASEDELTA;
5282                 stp->ls_flags |= NFSLCK_DELEGRECALL;
5283
5284                 /*
5285                  * Loop NFSRV_CBRETRYCNT times while the CBRecall replies
5286                  * NFSERR_BADSTATEID or NFSERR_BADHANDLE. This is done
5287                  * in order to try and avoid a race that could happen
5288                  * when a CBRecall request passed the Open reply with
5289                  * the delegation in it when transitting the network.
5290                  * Since nfsrv_docallback will sleep, don't use stp after
5291                  * the call.
5292                  */
5293                 NFSBCOPY((caddr_t)&stp->ls_stateid, (caddr_t)&tstateid,
5294                     sizeof (tstateid));
5295                 NFSBCOPY((caddr_t)&stp->ls_lfp->lf_fh, (caddr_t)&tfh,
5296                     sizeof (tfh));
5297                 NFSUNLOCKSTATE();
5298                 if (*haslockp) {
5299                         *haslockp = 0;
5300                         NFSLOCKV4ROOTMUTEX();
5301                         nfsv4_unlock(&nfsv4rootfs_lock, 1);
5302                         NFSUNLOCKV4ROOTMUTEX();
5303                 }
5304                 retrycnt = 0;
5305                 do {
5306                     error = nfsrv_docallback(clp, NFSV4OP_CBRECALL,
5307                         &tstateid, 0, &tfh, NULL, NULL, 0, p);
5308                     retrycnt++;
5309                 } while ((error == NFSERR_BADSTATEID ||
5310                     error == NFSERR_BADHANDLE) && retrycnt < NFSV4_CBRETRYCNT);
5311                 error = NFSERR_DELAY;
5312                 goto out;
5313         }
5314
5315         if (clp->lc_expiry >= NFSD_MONOSEC &&
5316             stp->ls_delegtime >= NFSD_MONOSEC) {
5317                 NFSUNLOCKSTATE();
5318                 /*
5319                  * A recall has been done, but it has not yet expired.
5320                  * So, RETURN_DELAY.
5321                  */
5322                 if (*haslockp) {
5323                         *haslockp = 0;
5324                         NFSLOCKV4ROOTMUTEX();
5325                         nfsv4_unlock(&nfsv4rootfs_lock, 1);
5326                         NFSUNLOCKV4ROOTMUTEX();
5327                 }
5328                 error = NFSERR_DELAY;
5329                 goto out;
5330         }
5331
5332         /*
5333          * If we don't yet have the lock, just get it and then return,
5334          * since we need that before deleting expired state, such as
5335          * this delegation.
5336          * When getting the lock, unlock the vnode, so other nfsds that
5337          * are in progress, won't get stuck waiting for the vnode lock.
5338          */
5339         if (*haslockp == 0) {
5340                 NFSUNLOCKSTATE();
5341                 if (vp != NULL) {
5342                         lktype = NFSVOPISLOCKED(vp);
5343                         NFSVOPUNLOCK(vp);
5344                 }
5345                 NFSLOCKV4ROOTMUTEX();
5346                 nfsv4_relref(&nfsv4rootfs_lock);
5347                 do {
5348                         gotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL,
5349                             NFSV4ROOTLOCKMUTEXPTR, NULL);
5350                 } while (!gotlock);
5351                 NFSUNLOCKV4ROOTMUTEX();
5352                 *haslockp = 1;
5353                 if (vp != NULL) {
5354                         NFSVOPLOCK(vp, lktype | LK_RETRY);
5355                         if (VN_IS_DOOMED(vp)) {
5356                                 *haslockp = 0;
5357                                 NFSLOCKV4ROOTMUTEX();
5358                                 nfsv4_unlock(&nfsv4rootfs_lock, 1);
5359                                 NFSUNLOCKV4ROOTMUTEX();
5360                                 error = NFSERR_PERM;
5361                                 goto out;
5362                         }
5363                 }
5364                 error = -1;
5365                 goto out;
5366         }
5367
5368         NFSUNLOCKSTATE();
5369         /*
5370          * Ok, we can delete the expired delegation.
5371          * First, write the Revoke record to stable storage and then
5372          * clear out the conflict.
5373          * Since all other nfsd threads are now blocked, we can safely
5374          * sleep without the state changing.
5375          */
5376         nfsrv_writestable(clp->lc_id, clp->lc_idlen, NFSNST_REVOKE, p);
5377         nfsrv_backupstable();
5378         if (clp->lc_expiry < NFSD_MONOSEC) {
5379                 nfsrv_cleanclient(clp, p);
5380                 nfsrv_freedeleglist(&clp->lc_deleg);
5381                 nfsrv_freedeleglist(&clp->lc_olddeleg);
5382                 LIST_REMOVE(clp, lc_hash);
5383                 zapped_clp = 1;
5384         } else {
5385                 nfsrv_freedeleg(stp);
5386                 zapped_clp = 0;
5387         }
5388         if (zapped_clp)
5389                 nfsrv_zapclient(clp, p);
5390         error = -1;
5391
5392 out:
5393         NFSEXITCODE(error);
5394         return (error);
5395 }
5396
5397 /*
5398  * Check for a remove allowed, if remove is set to 1 and get rid of
5399  * delegations.
5400  */
5401 int
5402 nfsrv_checkremove(vnode_t vp, int remove, struct nfsrv_descript *nd,
5403     nfsquad_t clientid, NFSPROC_T *p)
5404 {
5405         struct nfsclient *clp;
5406         struct nfsstate *stp;
5407         struct nfslockfile *lfp;
5408         int error, haslock = 0;
5409         fhandle_t nfh;
5410
5411         clp = NULL;
5412         /*
5413          * First, get the lock file structure.
5414          * (A return of -1 means no associated state, so remove ok.)
5415          */
5416         error = nfsrv_getlockfh(vp, NFSLCK_CHECK, NULL, &nfh, p);
5417 tryagain:
5418         NFSLOCKSTATE();
5419         if (error == 0 && clientid.qval != 0)
5420                 error = nfsrv_getclient(clientid, CLOPS_RENEW, &clp, NULL,
5421                     (nfsquad_t)((u_quad_t)0), 0, nd, p);
5422         if (!error)
5423                 error = nfsrv_getlockfile(NFSLCK_CHECK, NULL, &lfp, &nfh, 0);
5424         if (error) {
5425                 NFSUNLOCKSTATE();
5426                 if (haslock) {
5427                         NFSLOCKV4ROOTMUTEX();
5428                         nfsv4_unlock(&nfsv4rootfs_lock, 1);
5429                         NFSUNLOCKV4ROOTMUTEX();
5430                 }
5431                 if (error == -1)
5432                         error = 0;
5433                 goto out;
5434         }
5435
5436         /*
5437          * Now, we must Recall any delegations.
5438          */
5439         error = nfsrv_cleandeleg(vp, lfp, clp, &haslock, p);
5440         if (error) {
5441                 /*
5442                  * nfsrv_cleandeleg() unlocks state for non-zero
5443                  * return.
5444                  */
5445                 if (error == -1)
5446                         goto tryagain;
5447                 if (haslock) {
5448                         NFSLOCKV4ROOTMUTEX();
5449                         nfsv4_unlock(&nfsv4rootfs_lock, 1);
5450                         NFSUNLOCKV4ROOTMUTEX();
5451                 }
5452                 goto out;
5453         }
5454
5455         /*
5456          * Now, look for a conflicting open share.
5457          */
5458         if (remove) {
5459                 /*
5460                  * If the entry in the directory was the last reference to the
5461                  * corresponding filesystem object, the object can be destroyed
5462                  * */
5463                 if(lfp->lf_usecount>1)
5464                         LIST_FOREACH(stp, &lfp->lf_open, ls_file) {
5465                                 if (stp->ls_flags & NFSLCK_WRITEDENY) {
5466                                         error = NFSERR_FILEOPEN;
5467                                         break;
5468                                 }
5469                         }
5470         }
5471
5472         NFSUNLOCKSTATE();
5473         if (haslock) {
5474                 NFSLOCKV4ROOTMUTEX();
5475                 nfsv4_unlock(&nfsv4rootfs_lock, 1);
5476                 NFSUNLOCKV4ROOTMUTEX();
5477         }
5478
5479 out:
5480         NFSEXITCODE(error);
5481         return (error);
5482 }
5483
5484 /*
5485  * Clear out all delegations for the file referred to by lfp.
5486  * May return NFSERR_DELAY, if there will be a delay waiting for
5487  * delegations to expire.
5488  * Returns -1 to indicate it slept while recalling a delegation.
5489  * This function has the side effect of deleting the nfslockfile structure,
5490  * if it no longer has associated state and didn't have to sleep.
5491  * Unlocks State before a non-zero value is returned.
5492  */
5493 static int
5494 nfsrv_cleandeleg(vnode_t vp, struct nfslockfile *lfp,
5495     struct nfsclient *clp, int *haslockp, NFSPROC_T *p)
5496 {
5497         struct nfsstate *stp, *nstp;
5498         int ret = 0;
5499
5500         stp = LIST_FIRST(&lfp->lf_deleg);
5501         while (stp != LIST_END(&lfp->lf_deleg)) {
5502                 nstp = LIST_NEXT(stp, ls_file);
5503                 if (stp->ls_clp != clp) {
5504                         ret = nfsrv_delegconflict(stp, haslockp, p, vp);
5505                         if (ret) {
5506                                 /*
5507                                  * nfsrv_delegconflict() unlocks state
5508                                  * when it returns non-zero.
5509                                  */
5510                                 goto out;
5511                         }
5512                 }
5513                 stp = nstp;
5514         }
5515 out:
5516         NFSEXITCODE(ret);
5517         return (ret);
5518 }
5519
5520 /*
5521  * There are certain operations that, when being done outside of NFSv4,
5522  * require that any NFSv4 delegation for the file be recalled.
5523  * This function is to be called for those cases:
5524  * VOP_RENAME() - When a delegation is being recalled for any reason,
5525  *      the client may have to do Opens against the server, using the file's
5526  *      final component name. If the file has been renamed on the server,
5527  *      that component name will be incorrect and the Open will fail.
5528  * VOP_REMOVE() - Theoretically, a client could Open a file after it has
5529  *      been removed on the server, if there is a delegation issued to
5530  *      that client for the file. I say "theoretically" since clients
5531  *      normally do an Access Op before the Open and that Access Op will
5532  *      fail with ESTALE. Note that NFSv2 and 3 don't even do Opens, so
5533  *      they will detect the file's removal in the same manner. (There is
5534  *      one case where RFC3530 allows a client to do an Open without first
5535  *      doing an Access Op, which is passage of a check against the ACE
5536  *      returned with a Write delegation, but current practice is to ignore
5537  *      the ACE and always do an Access Op.)
5538  *      Since the functions can only be called with an unlocked vnode, this
5539  *      can't be done at this time.
5540  * VOP_ADVLOCK() - When a client holds a delegation, it can issue byte range
5541  *      locks locally in the client, which are not visible to the server. To
5542  *      deal with this, issuing of delegations for a vnode must be disabled
5543  *      and all delegations for the vnode recalled. This is done via the
5544  *      second function, using the VV_DISABLEDELEG vflag on the vnode.
5545  */
5546 void
5547 nfsd_recalldelegation(vnode_t vp, NFSPROC_T *p)
5548 {
5549         time_t starttime;
5550         int error;
5551
5552         /*
5553          * First, check to see if the server is currently running and it has
5554          * been called for a regular file when issuing delegations.
5555          */
5556         if (newnfs_numnfsd == 0 || vp->v_type != VREG ||
5557             nfsrv_issuedelegs == 0)
5558                 return;
5559
5560         KASSERT((NFSVOPISLOCKED(vp) != LK_EXCLUSIVE), ("vp %p is locked", vp));
5561         /*
5562          * First, get a reference on the nfsv4rootfs_lock so that an
5563          * exclusive lock cannot be acquired by another thread.
5564          */
5565         NFSLOCKV4ROOTMUTEX();
5566         nfsv4_getref(&nfsv4rootfs_lock, NULL, NFSV4ROOTLOCKMUTEXPTR, NULL);
5567         NFSUNLOCKV4ROOTMUTEX();
5568
5569         /*
5570          * Now, call nfsrv_checkremove() in a loop while it returns
5571          * NFSERR_DELAY. Return upon any other error or when timed out.
5572          */
5573         starttime = NFSD_MONOSEC;
5574         do {
5575                 if (NFSVOPLOCK(vp, LK_EXCLUSIVE) == 0) {
5576                         error = nfsrv_checkremove(vp, 0, NULL,
5577                             (nfsquad_t)((u_quad_t)0), p);
5578                         NFSVOPUNLOCK(vp);
5579                 } else
5580                         error = EPERM;
5581                 if (error == NFSERR_DELAY) {
5582                         if (NFSD_MONOSEC - starttime > NFS_REMOVETIMEO)
5583                                 break;
5584                         /* Sleep for a short period of time */
5585                         (void) nfs_catnap(PZERO, 0, "nfsremove");
5586                 }
5587         } while (error == NFSERR_DELAY);
5588         NFSLOCKV4ROOTMUTEX();
5589         nfsv4_relref(&nfsv4rootfs_lock);
5590         NFSUNLOCKV4ROOTMUTEX();
5591 }
5592
5593 void
5594 nfsd_disabledelegation(vnode_t vp, NFSPROC_T *p)
5595 {
5596
5597 #ifdef VV_DISABLEDELEG
5598         /*
5599          * First, flag issuance of delegations disabled.
5600          */
5601         atomic_set_long(&vp->v_vflag, VV_DISABLEDELEG);
5602 #endif
5603
5604         /*
5605          * Then call nfsd_recalldelegation() to get rid of all extant
5606          * delegations.
5607          */
5608         nfsd_recalldelegation(vp, p);
5609 }
5610
5611 /*
5612  * Check for conflicting locks, etc. and then get rid of delegations.
5613  * (At one point I thought that I should get rid of delegations for any
5614  *  Setattr, since it could potentially disallow the I/O op (read or write)
5615  *  allowed by the delegation. However, Setattr Ops that aren't changing
5616  *  the size get a stateid of all 0s, so you can't tell if it is a delegation
5617  *  for the same client or a different one, so I decided to only get rid
5618  *  of delegations for other clients when the size is being changed.)
5619  * In general, a Setattr can disable NFS I/O Ops that are outstanding, such
5620  * as Write backs, even if there is no delegation, so it really isn't any
5621  * different?)
5622  */
5623 int
5624 nfsrv_checksetattr(vnode_t vp, struct nfsrv_descript *nd,
5625     nfsv4stateid_t *stateidp, struct nfsvattr *nvap, nfsattrbit_t *attrbitp,
5626     struct nfsexstuff *exp, NFSPROC_T *p)
5627 {
5628         struct nfsstate st, *stp = &st;
5629         struct nfslock lo, *lop = &lo;
5630         int error = 0;
5631         nfsquad_t clientid;
5632
5633         if (NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_SIZE)) {
5634                 stp->ls_flags = (NFSLCK_CHECK | NFSLCK_WRITEACCESS);
5635                 lop->lo_first = nvap->na_size;
5636         } else {
5637                 stp->ls_flags = 0;
5638                 lop->lo_first = 0;
5639         }
5640         if (NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_OWNER) ||
5641             NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_OWNERGROUP) ||
5642             NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_MODE) ||
5643             NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_ACL))
5644                 stp->ls_flags |= NFSLCK_SETATTR;
5645         if (stp->ls_flags == 0)
5646                 goto out;
5647         lop->lo_end = NFS64BITSSET;
5648         lop->lo_flags = NFSLCK_WRITE;
5649         stp->ls_ownerlen = 0;
5650         stp->ls_op = NULL;
5651         stp->ls_uid = nd->nd_cred->cr_uid;
5652         stp->ls_stateid.seqid = stateidp->seqid;
5653         clientid.lval[0] = stp->ls_stateid.other[0] = stateidp->other[0];
5654         clientid.lval[1] = stp->ls_stateid.other[1] = stateidp->other[1];
5655         stp->ls_stateid.other[2] = stateidp->other[2];
5656         error = nfsrv_lockctrl(vp, &stp, &lop, NULL, clientid,
5657             stateidp, exp, nd, p);
5658
5659 out:
5660         NFSEXITCODE2(error, nd);
5661         return (error);
5662 }
5663
5664 /*
5665  * Check for a write delegation and do a CBGETATTR if there is one, updating
5666  * the attributes, as required.
5667  * Should I return an error if I can't get the attributes? (For now, I'll
5668  * just return ok.
5669  */
5670 int
5671 nfsrv_checkgetattr(struct nfsrv_descript *nd, vnode_t vp,
5672     struct nfsvattr *nvap, nfsattrbit_t *attrbitp, NFSPROC_T *p)
5673 {
5674         struct nfsstate *stp;
5675         struct nfslockfile *lfp;
5676         struct nfsclient *clp;
5677         struct nfsvattr nva;
5678         fhandle_t nfh;
5679         int error = 0;
5680         nfsattrbit_t cbbits;
5681         u_quad_t delegfilerev;
5682
5683         NFSCBGETATTR_ATTRBIT(attrbitp, &cbbits);
5684         if (!NFSNONZERO_ATTRBIT(&cbbits))
5685                 goto out;
5686         if (nfsrv_writedelegcnt == 0)
5687                 goto out;
5688
5689         /*
5690          * Get the lock file structure.
5691          * (A return of -1 means no associated state, so return ok.)
5692          */
5693         error = nfsrv_getlockfh(vp, NFSLCK_CHECK, NULL, &nfh, p);
5694         NFSLOCKSTATE();
5695         if (!error)
5696                 error = nfsrv_getlockfile(NFSLCK_CHECK, NULL, &lfp, &nfh, 0);
5697         if (error) {
5698                 NFSUNLOCKSTATE();
5699                 if (error == -1)
5700                         error = 0;
5701                 goto out;
5702         }
5703
5704         /*
5705          * Now, look for a write delegation.
5706          */
5707         LIST_FOREACH(stp, &lfp->lf_deleg, ls_file) {
5708                 if (stp->ls_flags & NFSLCK_DELEGWRITE)
5709                         break;
5710         }
5711         if (stp == LIST_END(&lfp->lf_deleg)) {
5712                 NFSUNLOCKSTATE();
5713                 goto out;
5714         }
5715         clp = stp->ls_clp;
5716
5717         /* If the clientid is not confirmed, ignore the delegation. */
5718         if (clp->lc_flags & LCL_NEEDSCONFIRM) {
5719                 NFSUNLOCKSTATE();
5720                 goto out;
5721         }
5722
5723         delegfilerev = stp->ls_filerev;
5724         /*
5725          * If the Write delegation was issued as a part of this Compound RPC
5726          * or if we have an Implied Clientid (used in a previous Op in this
5727          * compound) and it is the client the delegation was issued to,
5728          * just return ok.
5729          * I also assume that it is from the same client iff the network
5730          * host IP address is the same as the callback address. (Not
5731          * exactly correct by the RFC, but avoids a lot of Getattr
5732          * callbacks.)
5733          */
5734         if (nd->nd_compref == stp->ls_compref ||
5735             ((nd->nd_flag & ND_IMPLIEDCLID) &&
5736              clp->lc_clientid.qval == nd->nd_clientid.qval) ||
5737              nfsaddr2_match(clp->lc_req.nr_nam, nd->nd_nam)) {
5738                 NFSUNLOCKSTATE();
5739                 goto out;
5740         }
5741
5742         /*
5743          * We are now done with the delegation state structure,
5744          * so the statelock can be released and we can now tsleep().
5745          */
5746
5747         /*
5748          * Now, we must do the CB Getattr callback, to see if Change or Size
5749          * has changed.
5750          */
5751         if (clp->lc_expiry >= NFSD_MONOSEC) {
5752                 NFSUNLOCKSTATE();
5753                 NFSVNO_ATTRINIT(&nva);
5754                 nva.na_filerev = NFS64BITSSET;
5755                 error = nfsrv_docallback(clp, NFSV4OP_CBGETATTR, NULL,
5756                     0, &nfh, &nva, &cbbits, 0, p);
5757                 if (!error) {
5758                         if ((nva.na_filerev != NFS64BITSSET &&
5759                             nva.na_filerev > delegfilerev) ||
5760                             (NFSVNO_ISSETSIZE(&nva) &&
5761                              nva.na_size != nvap->na_size)) {
5762                                 error = nfsvno_updfilerev(vp, nvap, nd, p);
5763                                 if (NFSVNO_ISSETSIZE(&nva))
5764                                         nvap->na_size = nva.na_size;
5765                         }
5766                 } else
5767                         error = 0;      /* Ignore callback errors for now. */
5768         } else {
5769                 NFSUNLOCKSTATE();
5770         }
5771
5772 out:
5773         NFSEXITCODE2(error, nd);
5774         return (error);
5775 }
5776
5777 /*
5778  * This function looks for openowners that haven't had any opens for
5779  * a while and throws them away. Called by an nfsd when NFSNSF_NOOPENS
5780  * is set.
5781  */
5782 void
5783 nfsrv_throwawayopens(NFSPROC_T *p)
5784 {
5785         struct nfsclient *clp, *nclp;
5786         struct nfsstate *stp, *nstp;
5787         int i;
5788
5789         NFSLOCKSTATE();
5790         nfsrv_stablefirst.nsf_flags &= ~NFSNSF_NOOPENS;
5791         /*
5792          * For each client...
5793          */
5794         for (i = 0; i < nfsrv_clienthashsize; i++) {
5795             LIST_FOREACH_SAFE(clp, &nfsclienthash[i], lc_hash, nclp) {
5796                 LIST_FOREACH_SAFE(stp, &clp->lc_open, ls_list, nstp) {
5797                         if (LIST_EMPTY(&stp->ls_open) &&
5798                             (stp->ls_noopens > NFSNOOPEN ||
5799                              (nfsrv_openpluslock * 2) >
5800                              nfsrv_v4statelimit))
5801                                 nfsrv_freeopenowner(stp, 0, p);
5802                 }
5803             }
5804         }
5805         NFSUNLOCKSTATE();
5806 }
5807
5808 /*
5809  * This function checks to see if the credentials are the same.
5810  * Returns 1 for not same, 0 otherwise.
5811  */
5812 static int
5813 nfsrv_notsamecredname(struct nfsrv_descript *nd, struct nfsclient *clp)
5814 {
5815
5816         if (nd->nd_flag & ND_GSS) {
5817                 if (!(clp->lc_flags & LCL_GSS))
5818                         return (1);
5819                 if (clp->lc_flags & LCL_NAME) {
5820                         if (nd->nd_princlen != clp->lc_namelen ||
5821                             NFSBCMP(nd->nd_principal, clp->lc_name,
5822                                 clp->lc_namelen))
5823                                 return (1);
5824                         else
5825                                 return (0);
5826                 }
5827                 if (nd->nd_cred->cr_uid == clp->lc_uid)
5828                         return (0);
5829                 else
5830                         return (1);
5831         } else if (clp->lc_flags & LCL_GSS)
5832                 return (1);
5833         /*
5834          * For AUTH_SYS, allow the same uid or root. (This is underspecified
5835          * in RFC3530, which talks about principals, but doesn't say anything
5836          * about uids for AUTH_SYS.)
5837          */
5838         if (nd->nd_cred->cr_uid == clp->lc_uid || nd->nd_cred->cr_uid == 0)
5839                 return (0);
5840         else
5841                 return (1);
5842 }
5843
5844 /*
5845  * Calculate the lease expiry time.
5846  */
5847 static time_t
5848 nfsrv_leaseexpiry(void)
5849 {
5850
5851         if (nfsrv_stablefirst.nsf_eograce > NFSD_MONOSEC)
5852                 return (NFSD_MONOSEC + 2 * (nfsrv_lease + NFSRV_LEASEDELTA));
5853         return (NFSD_MONOSEC + nfsrv_lease + NFSRV_LEASEDELTA);
5854 }
5855
5856 /*
5857  * Delay the delegation timeout as far as ls_delegtimelimit, as required.
5858  */
5859 static void
5860 nfsrv_delaydelegtimeout(struct nfsstate *stp)
5861 {
5862
5863         if ((stp->ls_flags & NFSLCK_DELEGRECALL) == 0)
5864                 return;
5865
5866         if ((stp->ls_delegtime + 15) > NFSD_MONOSEC &&
5867             stp->ls_delegtime < stp->ls_delegtimelimit) {
5868                 stp->ls_delegtime += nfsrv_lease;
5869                 if (stp->ls_delegtime > stp->ls_delegtimelimit)
5870                         stp->ls_delegtime = stp->ls_delegtimelimit;
5871         }
5872 }
5873
5874 /*
5875  * This function checks to see if there is any other state associated
5876  * with the openowner for this Open.
5877  * It returns 1 if there is no other state, 0 otherwise.
5878  */
5879 static int
5880 nfsrv_nootherstate(struct nfsstate *stp)
5881 {
5882         struct nfsstate *tstp;
5883
5884         LIST_FOREACH(tstp, &stp->ls_openowner->ls_open, ls_list) {
5885                 if (tstp != stp || !LIST_EMPTY(&tstp->ls_lock))
5886                         return (0);
5887         }
5888         return (1);
5889 }
5890
5891 /*
5892  * Create a list of lock deltas (changes to local byte range locking
5893  * that can be rolled back using the list) and apply the changes via
5894  * nfsvno_advlock(). Optionally, lock the list. It is expected that either
5895  * the rollback or update function will be called after this.
5896  * It returns an error (and rolls back, as required), if any nfsvno_advlock()
5897  * call fails. If it returns an error, it will unlock the list.
5898  */
5899 static int
5900 nfsrv_locallock(vnode_t vp, struct nfslockfile *lfp, int flags,
5901     uint64_t first, uint64_t end, struct nfslockconflict *cfp, NFSPROC_T *p)
5902 {
5903         struct nfslock *lop, *nlop;
5904         int error = 0;
5905
5906         /* Loop through the list of locks. */
5907         lop = LIST_FIRST(&lfp->lf_locallock);
5908         while (first < end && lop != NULL) {
5909                 nlop = LIST_NEXT(lop, lo_lckowner);
5910                 if (first >= lop->lo_end) {
5911                         /* not there yet */
5912                         lop = nlop;
5913                 } else if (first < lop->lo_first) {
5914                         /* new one starts before entry in list */
5915                         if (end <= lop->lo_first) {
5916                                 /* no overlap between old and new */
5917                                 error = nfsrv_dolocal(vp, lfp, flags,
5918                                     NFSLCK_UNLOCK, first, end, cfp, p);
5919                                 if (error != 0)
5920                                         break;
5921                                 first = end;
5922                         } else {
5923                                 /* handle fragment overlapped with new one */
5924                                 error = nfsrv_dolocal(vp, lfp, flags,
5925                                     NFSLCK_UNLOCK, first, lop->lo_first, cfp,
5926                                     p);
5927                                 if (error != 0)
5928                                         break;
5929                                 first = lop->lo_first;
5930                         }
5931                 } else {
5932                         /* new one overlaps this entry in list */
5933                         if (end <= lop->lo_end) {
5934                                 /* overlaps all of new one */
5935                                 error = nfsrv_dolocal(vp, lfp, flags,
5936                                     lop->lo_flags, first, end, cfp, p);
5937                                 if (error != 0)
5938                                         break;
5939                                 first = end;
5940                         } else {
5941                                 /* handle fragment overlapped with new one */
5942                                 error = nfsrv_dolocal(vp, lfp, flags,
5943                                     lop->lo_flags, first, lop->lo_end, cfp, p);
5944                                 if (error != 0)
5945                                         break;
5946                                 first = lop->lo_end;
5947                                 lop = nlop;
5948                         }
5949                 }
5950         }
5951         if (first < end && error == 0)
5952                 /* handle fragment past end of list */
5953                 error = nfsrv_dolocal(vp, lfp, flags, NFSLCK_UNLOCK, first,
5954                     end, cfp, p);
5955
5956         NFSEXITCODE(error);
5957         return (error);
5958 }
5959
5960 /*
5961  * Local lock unlock. Unlock all byte ranges that are no longer locked
5962  * by NFSv4. To do this, unlock any subranges of first-->end that
5963  * do not overlap with the byte ranges of any lock in the lfp->lf_lock
5964  * list. This list has all locks for the file held by other
5965  * <clientid, lockowner> tuples. The list is ordered by increasing
5966  * lo_first value, but may have entries that overlap each other, for
5967  * the case of read locks.
5968  */
5969 static void
5970 nfsrv_localunlock(vnode_t vp, struct nfslockfile *lfp, uint64_t init_first,
5971     uint64_t init_end, NFSPROC_T *p)
5972 {
5973         struct nfslock *lop;
5974         uint64_t first, end, prevfirst __unused;
5975
5976         first = init_first;
5977         end = init_end;
5978         while (first < init_end) {
5979                 /* Loop through all nfs locks, adjusting first and end */
5980                 prevfirst = 0;
5981                 LIST_FOREACH(lop, &lfp->lf_lock, lo_lckfile) {
5982                         KASSERT(prevfirst <= lop->lo_first,
5983                             ("nfsv4 locks out of order"));
5984                         KASSERT(lop->lo_first < lop->lo_end,
5985                             ("nfsv4 bogus lock"));
5986                         prevfirst = lop->lo_first;
5987                         if (first >= lop->lo_first &&
5988                             first < lop->lo_end)
5989                                 /*
5990                                  * Overlaps with initial part, so trim
5991                                  * off that initial part by moving first past
5992                                  * it.
5993                                  */
5994                                 first = lop->lo_end;
5995                         else if (end > lop->lo_first &&
5996                             lop->lo_first > first) {
5997                                 /*
5998                                  * This lock defines the end of the
5999                                  * segment to unlock, so set end to the
6000                                  * start of it and break out of the loop.
6001                                  */
6002                                 end = lop->lo_first;
6003                                 break;
6004                         }
6005                         if (first >= end)
6006                                 /*
6007                                  * There is no segment left to do, so
6008                                  * break out of this loop and then exit
6009                                  * the outer while() since first will be set
6010                                  * to end, which must equal init_end here.
6011                                  */
6012                                 break;
6013                 }
6014                 if (first < end) {
6015                         /* Unlock this segment */
6016                         (void) nfsrv_dolocal(vp, lfp, NFSLCK_UNLOCK,
6017                             NFSLCK_READ, first, end, NULL, p);
6018                         nfsrv_locallock_commit(lfp, NFSLCK_UNLOCK,
6019                             first, end);
6020                 }
6021                 /*
6022                  * Now move past this segment and look for any further
6023                  * segment in the range, if there is one.
6024                  */
6025                 first = end;
6026                 end = init_end;
6027         }
6028 }
6029
6030 /*
6031  * Do the local lock operation and update the rollback list, as required.
6032  * Perform the rollback and return the error if nfsvno_advlock() fails.
6033  */
6034 static int
6035 nfsrv_dolocal(vnode_t vp, struct nfslockfile *lfp, int flags, int oldflags,
6036     uint64_t first, uint64_t end, struct nfslockconflict *cfp, NFSPROC_T *p)
6037 {
6038         struct nfsrollback *rlp;
6039         int error = 0, ltype, oldltype;
6040
6041         if (flags & NFSLCK_WRITE)
6042                 ltype = F_WRLCK;
6043         else if (flags & NFSLCK_READ)
6044                 ltype = F_RDLCK;
6045         else
6046                 ltype = F_UNLCK;
6047         if (oldflags & NFSLCK_WRITE)
6048                 oldltype = F_WRLCK;
6049         else if (oldflags & NFSLCK_READ)
6050                 oldltype = F_RDLCK;
6051         else
6052                 oldltype = F_UNLCK;
6053         if (ltype == oldltype || (oldltype == F_WRLCK && ltype == F_RDLCK))
6054                 /* nothing to do */
6055                 goto out;
6056         error = nfsvno_advlock(vp, ltype, first, end, p);
6057         if (error != 0) {
6058                 if (cfp != NULL) {
6059                         cfp->cl_clientid.lval[0] = 0;
6060                         cfp->cl_clientid.lval[1] = 0;
6061                         cfp->cl_first = 0;
6062                         cfp->cl_end = NFS64BITSSET;
6063                         cfp->cl_flags = NFSLCK_WRITE;
6064                         cfp->cl_ownerlen = 5;
6065                         NFSBCOPY("LOCAL", cfp->cl_owner, 5);
6066                 }
6067                 nfsrv_locallock_rollback(vp, lfp, p);
6068         } else if (ltype != F_UNLCK) {
6069                 rlp = malloc(sizeof (struct nfsrollback), M_NFSDROLLBACK,
6070                     M_WAITOK);
6071                 rlp->rlck_first = first;
6072                 rlp->rlck_end = end;
6073                 rlp->rlck_type = oldltype;
6074                 LIST_INSERT_HEAD(&lfp->lf_rollback, rlp, rlck_list);
6075         }
6076
6077 out:
6078         NFSEXITCODE(error);
6079         return (error);
6080 }
6081
6082 /*
6083  * Roll back local lock changes and free up the rollback list.
6084  */
6085 static void
6086 nfsrv_locallock_rollback(vnode_t vp, struct nfslockfile *lfp, NFSPROC_T *p)
6087 {
6088         struct nfsrollback *rlp, *nrlp;
6089
6090         LIST_FOREACH_SAFE(rlp, &lfp->lf_rollback, rlck_list, nrlp) {
6091                 (void) nfsvno_advlock(vp, rlp->rlck_type, rlp->rlck_first,
6092                     rlp->rlck_end, p);
6093                 free(rlp, M_NFSDROLLBACK);
6094         }
6095         LIST_INIT(&lfp->lf_rollback);
6096 }
6097
6098 /*
6099  * Update local lock list and delete rollback list (ie now committed to the
6100  * local locks). Most of the work is done by the internal function.
6101  */
6102 static void
6103 nfsrv_locallock_commit(struct nfslockfile *lfp, int flags, uint64_t first,
6104     uint64_t end)
6105 {
6106         struct nfsrollback *rlp, *nrlp;
6107         struct nfslock *new_lop, *other_lop;
6108
6109         new_lop = malloc(sizeof (struct nfslock), M_NFSDLOCK, M_WAITOK);
6110         if (flags & (NFSLCK_READ | NFSLCK_WRITE))
6111                 other_lop = malloc(sizeof (struct nfslock), M_NFSDLOCK,
6112                     M_WAITOK);
6113         else
6114                 other_lop = NULL;
6115         new_lop->lo_flags = flags;
6116         new_lop->lo_first = first;
6117         new_lop->lo_end = end;
6118         nfsrv_updatelock(NULL, &new_lop, &other_lop, lfp);
6119         if (new_lop != NULL)
6120                 free(new_lop, M_NFSDLOCK);
6121         if (other_lop != NULL)
6122                 free(other_lop, M_NFSDLOCK);
6123
6124         /* and get rid of the rollback list */
6125         LIST_FOREACH_SAFE(rlp, &lfp->lf_rollback, rlck_list, nrlp)
6126                 free(rlp, M_NFSDROLLBACK);
6127         LIST_INIT(&lfp->lf_rollback);
6128 }
6129
6130 /*
6131  * Lock the struct nfslockfile for local lock updating.
6132  */
6133 static void
6134 nfsrv_locklf(struct nfslockfile *lfp)
6135 {
6136         int gotlock;
6137
6138         /* lf_usecount ensures *lfp won't be free'd */
6139         lfp->lf_usecount++;
6140         do {
6141                 gotlock = nfsv4_lock(&lfp->lf_locallock_lck, 1, NULL,
6142                     NFSSTATEMUTEXPTR, NULL);
6143         } while (gotlock == 0);
6144         lfp->lf_usecount--;
6145 }
6146
6147 /*
6148  * Unlock the struct nfslockfile after local lock updating.
6149  */
6150 static void
6151 nfsrv_unlocklf(struct nfslockfile *lfp)
6152 {
6153
6154         nfsv4_unlock(&lfp->lf_locallock_lck, 0);
6155 }
6156
6157 /*
6158  * Clear out all state for the NFSv4 server.
6159  * Must be called by a thread that can sleep when no nfsds are running.
6160  */
6161 void
6162 nfsrv_throwawayallstate(NFSPROC_T *p)
6163 {
6164         struct nfsclient *clp, *nclp;
6165         struct nfslockfile *lfp, *nlfp;
6166         int i;
6167
6168         /*
6169          * For each client, clean out the state and then free the structure.
6170          */
6171         for (i = 0; i < nfsrv_clienthashsize; i++) {
6172                 LIST_FOREACH_SAFE(clp, &nfsclienthash[i], lc_hash, nclp) {
6173                         nfsrv_cleanclient(clp, p);
6174                         nfsrv_freedeleglist(&clp->lc_deleg);
6175                         nfsrv_freedeleglist(&clp->lc_olddeleg);
6176                         free(clp->lc_stateid, M_NFSDCLIENT);
6177                         free(clp, M_NFSDCLIENT);
6178                 }
6179         }
6180
6181         /*
6182          * Also, free up any remaining lock file structures.
6183          */
6184         for (i = 0; i < nfsrv_lockhashsize; i++) {
6185                 LIST_FOREACH_SAFE(lfp, &nfslockhash[i], lf_hash, nlfp) {
6186                         printf("nfsd unload: fnd a lock file struct\n");
6187                         nfsrv_freenfslockfile(lfp);
6188                 }
6189         }
6190
6191         /* And get rid of the deviceid structures and layouts. */
6192         nfsrv_freealllayoutsanddevids();
6193 }
6194
6195 /*
6196  * Check the sequence# for the session and slot provided as an argument.
6197  * Also, renew the lease if the session will return NFS_OK.
6198  */
6199 int
6200 nfsrv_checksequence(struct nfsrv_descript *nd, uint32_t sequenceid,
6201     uint32_t *highest_slotidp, uint32_t *target_highest_slotidp, int cache_this,
6202     uint32_t *sflagsp, NFSPROC_T *p)
6203 {
6204         struct nfsdsession *sep;
6205         struct nfssessionhash *shp;
6206         int error;
6207         SVCXPRT *savxprt;
6208
6209         shp = NFSSESSIONHASH(nd->nd_sessionid);
6210         NFSLOCKSESSION(shp);
6211         sep = nfsrv_findsession(nd->nd_sessionid);
6212         if (sep == NULL) {
6213                 NFSUNLOCKSESSION(shp);
6214                 return (NFSERR_BADSESSION);
6215         }
6216         error = nfsv4_seqsession(sequenceid, nd->nd_slotid, *highest_slotidp,
6217             sep->sess_slots, NULL, NFSV4_SLOTS - 1);
6218         if (error != 0) {
6219                 NFSUNLOCKSESSION(shp);
6220                 return (error);
6221         }
6222         if (cache_this != 0)
6223                 nd->nd_flag |= ND_SAVEREPLY;
6224         /* Renew the lease. */
6225         sep->sess_clp->lc_expiry = nfsrv_leaseexpiry();
6226         nd->nd_clientid.qval = sep->sess_clp->lc_clientid.qval;
6227         nd->nd_flag |= ND_IMPLIEDCLID;
6228
6229         /* Save maximum request and reply sizes. */
6230         nd->nd_maxreq = sep->sess_maxreq;
6231         nd->nd_maxresp = sep->sess_maxresp;
6232
6233         /*
6234          * If this session handles the backchannel, save the nd_xprt for this
6235          * RPC, since this is the one being used.
6236          * RFC-5661 specifies that the fore channel will be implicitly
6237          * bound by a Sequence operation.  However, since some NFSv4.1 clients
6238          * erroneously assumed that the back channel would be implicitly
6239          * bound as well, do the implicit binding unless a
6240          * BindConnectiontoSession has already been done on the session.
6241          */
6242         savxprt = NULL;
6243         if (sep->sess_clp->lc_req.nr_client != NULL &&
6244             sep->sess_cbsess.nfsess_xprt != nd->nd_xprt &&
6245             (sep->sess_crflags & NFSV4CRSESS_CONNBACKCHAN) != 0 &&
6246             (sep->sess_clp->lc_flags & LCL_DONEBINDCONN) == 0) {
6247                 NFSD_DEBUG(2,
6248                     "nfsrv_checksequence: implicit back channel bind\n");
6249                 savxprt = sep->sess_cbsess.nfsess_xprt;
6250                 SVC_ACQUIRE(nd->nd_xprt);
6251                 nd->nd_xprt->xp_p2 =
6252                     sep->sess_clp->lc_req.nr_client->cl_private;
6253                 nd->nd_xprt->xp_idletimeout = 0;        /* Disable timeout. */
6254                 sep->sess_cbsess.nfsess_xprt = nd->nd_xprt;
6255         }
6256
6257         *sflagsp = 0;
6258         if (sep->sess_clp->lc_req.nr_client == NULL)
6259                 *sflagsp |= NFSV4SEQ_CBPATHDOWN;
6260         NFSUNLOCKSESSION(shp);
6261         if (savxprt != NULL)
6262                 SVC_RELEASE(savxprt);
6263         if (error == NFSERR_EXPIRED) {
6264                 *sflagsp |= NFSV4SEQ_EXPIREDALLSTATEREVOKED;
6265                 error = 0;
6266         } else if (error == NFSERR_ADMINREVOKED) {
6267                 *sflagsp |= NFSV4SEQ_ADMINSTATEREVOKED;
6268                 error = 0;
6269         }
6270         *highest_slotidp = *target_highest_slotidp = NFSV4_SLOTS - 1;
6271         return (0);
6272 }
6273
6274 /*
6275  * Check/set reclaim complete for this session/clientid.
6276  */
6277 int
6278 nfsrv_checkreclaimcomplete(struct nfsrv_descript *nd, int onefs)
6279 {
6280         struct nfsdsession *sep;
6281         struct nfssessionhash *shp;
6282         int error = 0;
6283
6284         shp = NFSSESSIONHASH(nd->nd_sessionid);
6285         NFSLOCKSTATE();
6286         NFSLOCKSESSION(shp);
6287         sep = nfsrv_findsession(nd->nd_sessionid);
6288         if (sep == NULL) {
6289                 NFSUNLOCKSESSION(shp);
6290                 NFSUNLOCKSTATE();
6291                 return (NFSERR_BADSESSION);
6292         }
6293
6294         if (onefs != 0)
6295                 sep->sess_clp->lc_flags |= LCL_RECLAIMONEFS;
6296                 /* Check to see if reclaim complete has already happened. */
6297         else if ((sep->sess_clp->lc_flags & LCL_RECLAIMCOMPLETE) != 0)
6298                 error = NFSERR_COMPLETEALREADY;
6299         else {
6300                 sep->sess_clp->lc_flags |= LCL_RECLAIMCOMPLETE;
6301                 nfsrv_markreclaim(sep->sess_clp);
6302         }
6303         NFSUNLOCKSESSION(shp);
6304         NFSUNLOCKSTATE();
6305         return (error);
6306 }
6307
6308 /*
6309  * Cache the reply in a session slot.
6310  */
6311 void
6312 nfsrv_cache_session(struct nfsrv_descript *nd, struct mbuf **m)
6313 {
6314         struct nfsdsession *sep;
6315         struct nfssessionhash *shp;
6316         char *buf, *cp;
6317 #ifdef INET
6318         struct sockaddr_in *sin;
6319 #endif
6320 #ifdef INET6
6321         struct sockaddr_in6 *sin6;
6322 #endif
6323
6324         shp = NFSSESSIONHASH(nd->nd_sessionid);
6325         NFSLOCKSESSION(shp);
6326         sep = nfsrv_findsession(nd->nd_sessionid);
6327         if (sep == NULL) {
6328                 NFSUNLOCKSESSION(shp);
6329                 if ((nfsrv_stablefirst.nsf_flags & NFSNSF_GRACEOVER) != 0) {
6330                         buf = malloc(INET6_ADDRSTRLEN, M_TEMP, M_WAITOK);
6331                         switch (nd->nd_nam->sa_family) {
6332 #ifdef INET
6333                         case AF_INET:
6334                                 sin = (struct sockaddr_in *)nd->nd_nam;
6335                                 cp = inet_ntop(sin->sin_family,
6336                                     &sin->sin_addr.s_addr, buf,
6337                                     INET6_ADDRSTRLEN);
6338                                 break;
6339 #endif
6340 #ifdef INET6
6341                         case AF_INET6:
6342                                 sin6 = (struct sockaddr_in6 *)nd->nd_nam;
6343                                 cp = inet_ntop(sin6->sin6_family,
6344                                     &sin6->sin6_addr, buf, INET6_ADDRSTRLEN);
6345                                 break;
6346 #endif
6347                         default:
6348                                 cp = NULL;
6349                         }
6350                         if (cp != NULL)
6351                                 printf("nfsrv_cache_session: no session "
6352                                     "IPaddr=%s\n", cp);
6353                         else
6354                                 printf("nfsrv_cache_session: no session\n");
6355                         free(buf, M_TEMP);
6356                 }
6357                 m_freem(*m);
6358                 return;
6359         }
6360         nfsv4_seqsess_cacherep(nd->nd_slotid, sep->sess_slots, nd->nd_repstat,
6361             m);
6362         NFSUNLOCKSESSION(shp);
6363 }
6364
6365 /*
6366  * Search for a session that matches the sessionid.
6367  */
6368 static struct nfsdsession *
6369 nfsrv_findsession(uint8_t *sessionid)
6370 {
6371         struct nfsdsession *sep;
6372         struct nfssessionhash *shp;
6373
6374         shp = NFSSESSIONHASH(sessionid);
6375         LIST_FOREACH(sep, &shp->list, sess_hash) {
6376                 if (!NFSBCMP(sessionid, sep->sess_sessionid, NFSX_V4SESSIONID))
6377                         break;
6378         }
6379         return (sep);
6380 }
6381
6382 /*
6383  * Destroy a session.
6384  */
6385 int
6386 nfsrv_destroysession(struct nfsrv_descript *nd, uint8_t *sessionid)
6387 {
6388         int error, igotlock, samesess;
6389
6390         samesess = 0;
6391         if (!NFSBCMP(sessionid, nd->nd_sessionid, NFSX_V4SESSIONID) &&
6392             (nd->nd_flag & ND_HASSEQUENCE) != 0) {
6393                 samesess = 1;
6394                 if ((nd->nd_flag & ND_LASTOP) == 0)
6395                         return (NFSERR_BADSESSION);
6396         }
6397
6398         /* Lock out other nfsd threads */
6399         NFSLOCKV4ROOTMUTEX();
6400         nfsv4_relref(&nfsv4rootfs_lock);
6401         do {
6402                 igotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL,
6403                     NFSV4ROOTLOCKMUTEXPTR, NULL);
6404         } while (igotlock == 0);
6405         NFSUNLOCKV4ROOTMUTEX();
6406
6407         error = nfsrv_freesession(NULL, sessionid);
6408         if (error == 0 && samesess != 0)
6409                 nd->nd_flag &= ~ND_HASSEQUENCE;
6410
6411         NFSLOCKV4ROOTMUTEX();
6412         nfsv4_unlock(&nfsv4rootfs_lock, 1);
6413         NFSUNLOCKV4ROOTMUTEX();
6414         return (error);
6415 }
6416
6417 /*
6418  * Bind a connection to a session.
6419  * For now, only certain variants are supported, since the current session
6420  * structure can only handle a single backchannel entry, which will be
6421  * applied to all connections if it is set.
6422  */
6423 int
6424 nfsrv_bindconnsess(struct nfsrv_descript *nd, uint8_t *sessionid, int *foreaftp)
6425 {
6426         struct nfssessionhash *shp;
6427         struct nfsdsession *sep;
6428         struct nfsclient *clp;
6429         SVCXPRT *savxprt;
6430         int error;
6431
6432         error = 0;
6433         savxprt = NULL;
6434         shp = NFSSESSIONHASH(sessionid);
6435         NFSLOCKSTATE();
6436         NFSLOCKSESSION(shp);
6437         sep = nfsrv_findsession(sessionid);
6438         if (sep != NULL) {
6439                 clp = sep->sess_clp;
6440                 if (*foreaftp == NFSCDFC4_BACK ||
6441                     *foreaftp == NFSCDFC4_BACK_OR_BOTH ||
6442                     *foreaftp == NFSCDFC4_FORE_OR_BOTH) {
6443                         /* Try to set up a backchannel. */
6444                         if (clp->lc_req.nr_client == NULL) {
6445                                 NFSD_DEBUG(2, "nfsrv_bindconnsess: acquire "
6446                                     "backchannel\n");
6447                                 clp->lc_req.nr_client = (struct __rpc_client *)
6448                                     clnt_bck_create(nd->nd_xprt->xp_socket,
6449                                     sep->sess_cbprogram, NFSV4_CBVERS);
6450                         }
6451                         if (clp->lc_req.nr_client != NULL) {
6452                                 NFSD_DEBUG(2, "nfsrv_bindconnsess: set up "
6453                                     "backchannel\n");
6454                                 savxprt = sep->sess_cbsess.nfsess_xprt;
6455                                 SVC_ACQUIRE(nd->nd_xprt);
6456                                 nd->nd_xprt->xp_p2 =
6457                                     clp->lc_req.nr_client->cl_private;
6458                                 /* Disable idle timeout. */
6459                                 nd->nd_xprt->xp_idletimeout = 0;
6460                                 sep->sess_cbsess.nfsess_xprt = nd->nd_xprt;
6461                                 sep->sess_crflags |= NFSV4CRSESS_CONNBACKCHAN;
6462                                 clp->lc_flags |= LCL_DONEBINDCONN;
6463                                 if (*foreaftp == NFSCDFS4_BACK)
6464                                         *foreaftp = NFSCDFS4_BACK;
6465                                 else
6466                                         *foreaftp = NFSCDFS4_BOTH;
6467                         } else if (*foreaftp != NFSCDFC4_BACK) {
6468                                 NFSD_DEBUG(2, "nfsrv_bindconnsess: can't set "
6469                                     "up backchannel\n");
6470                                 sep->sess_crflags &= ~NFSV4CRSESS_CONNBACKCHAN;
6471                                 clp->lc_flags |= LCL_DONEBINDCONN;
6472                                 *foreaftp = NFSCDFS4_FORE;
6473                         } else {
6474                                 error = NFSERR_NOTSUPP;
6475                                 printf("nfsrv_bindconnsess: Can't add "
6476                                     "backchannel\n");
6477                         }
6478                 } else {
6479                         NFSD_DEBUG(2, "nfsrv_bindconnsess: Set forechannel\n");
6480                         clp->lc_flags |= LCL_DONEBINDCONN;
6481                         *foreaftp = NFSCDFS4_FORE;
6482                 }
6483         } else
6484                 error = NFSERR_BADSESSION;
6485         NFSUNLOCKSESSION(shp);
6486         NFSUNLOCKSTATE();
6487         if (savxprt != NULL)
6488                 SVC_RELEASE(savxprt);
6489         return (error);
6490 }
6491
6492 /*
6493  * Free up a session structure.
6494  */
6495 static int
6496 nfsrv_freesession(struct nfsdsession *sep, uint8_t *sessionid)
6497 {
6498         struct nfssessionhash *shp;
6499         int i;
6500
6501         NFSLOCKSTATE();
6502         if (sep == NULL) {
6503                 shp = NFSSESSIONHASH(sessionid);
6504                 NFSLOCKSESSION(shp);
6505                 sep = nfsrv_findsession(sessionid);
6506         } else {
6507                 shp = NFSSESSIONHASH(sep->sess_sessionid);
6508                 NFSLOCKSESSION(shp);
6509         }
6510         if (sep != NULL) {
6511                 sep->sess_refcnt--;
6512                 if (sep->sess_refcnt > 0) {
6513                         NFSUNLOCKSESSION(shp);
6514                         NFSUNLOCKSTATE();
6515                         return (NFSERR_BACKCHANBUSY);
6516                 }
6517                 LIST_REMOVE(sep, sess_hash);
6518                 LIST_REMOVE(sep, sess_list);
6519         }
6520         NFSUNLOCKSESSION(shp);
6521         NFSUNLOCKSTATE();
6522         if (sep == NULL)
6523                 return (NFSERR_BADSESSION);
6524         for (i = 0; i < NFSV4_SLOTS; i++)
6525                 if (sep->sess_slots[i].nfssl_reply != NULL)
6526                         m_freem(sep->sess_slots[i].nfssl_reply);
6527         if (sep->sess_cbsess.nfsess_xprt != NULL)
6528                 SVC_RELEASE(sep->sess_cbsess.nfsess_xprt);
6529         free(sep, M_NFSDSESSION);
6530         return (0);
6531 }
6532
6533 /*
6534  * Free a stateid.
6535  * RFC5661 says that it should fail when there are associated opens, locks
6536  * or delegations. Since stateids represent opens, I don't see how you can
6537  * free an open stateid (it will be free'd when closed), so this function
6538  * only works for lock stateids (freeing the lock_owner) or delegations.
6539  */
6540 int
6541 nfsrv_freestateid(struct nfsrv_descript *nd, nfsv4stateid_t *stateidp,
6542     NFSPROC_T *p)
6543 {
6544         struct nfsclient *clp;
6545         struct nfsstate *stp;
6546         int error;
6547
6548         NFSLOCKSTATE();
6549         /*
6550          * Look up the stateid
6551          */
6552         error = nfsrv_getclient((nfsquad_t)((u_quad_t)0), CLOPS_RENEW, &clp,
6553             NULL, (nfsquad_t)((u_quad_t)0), 0, nd, p);
6554         if (error == 0) {
6555                 /* First, check for a delegation. */
6556                 LIST_FOREACH(stp, &clp->lc_deleg, ls_list) {
6557                         if (!NFSBCMP(stp->ls_stateid.other, stateidp->other,
6558                             NFSX_STATEIDOTHER))
6559                                 break;
6560                 }
6561                 if (stp != NULL) {
6562                         nfsrv_freedeleg(stp);
6563                         NFSUNLOCKSTATE();
6564                         return (error);
6565                 }
6566         }
6567         /* Not a delegation, try for a lock_owner. */
6568         if (error == 0)
6569                 error = nfsrv_getstate(clp, stateidp, 0, &stp);
6570         if (error == 0 && ((stp->ls_flags & (NFSLCK_OPEN | NFSLCK_DELEGREAD |
6571             NFSLCK_DELEGWRITE)) != 0 || (stp->ls_flags & NFSLCK_LOCK) == 0))
6572                 /* Not a lock_owner stateid. */
6573                 error = NFSERR_LOCKSHELD;
6574         if (error == 0 && !LIST_EMPTY(&stp->ls_lock))
6575                 error = NFSERR_LOCKSHELD;
6576         if (error == 0)
6577                 nfsrv_freelockowner(stp, NULL, 0, p);
6578         NFSUNLOCKSTATE();
6579         return (error);
6580 }
6581
6582 /*
6583  * Test a stateid.
6584  */
6585 int
6586 nfsrv_teststateid(struct nfsrv_descript *nd, nfsv4stateid_t *stateidp,
6587     NFSPROC_T *p)
6588 {
6589         struct nfsclient *clp;
6590         struct nfsstate *stp;
6591         int error;
6592
6593         NFSLOCKSTATE();
6594         /*
6595          * Look up the stateid
6596          */
6597         error = nfsrv_getclient((nfsquad_t)((u_quad_t)0), CLOPS_RENEW, &clp,
6598             NULL, (nfsquad_t)((u_quad_t)0), 0, nd, p);
6599         if (error == 0)
6600                 error = nfsrv_getstate(clp, stateidp, 0, &stp);
6601         if (error == 0 && stateidp->seqid != 0 &&
6602             SEQ_LT(stateidp->seqid, stp->ls_stateid.seqid))
6603                 error = NFSERR_OLDSTATEID;
6604         NFSUNLOCKSTATE();
6605         return (error);
6606 }
6607
6608 /*
6609  * Generate the xdr for an NFSv4.1 CBSequence Operation.
6610  */
6611 static int
6612 nfsv4_setcbsequence(struct nfsrv_descript *nd, struct nfsclient *clp,
6613     int dont_replycache, struct nfsdsession **sepp)
6614 {
6615         struct nfsdsession *sep;
6616         uint32_t *tl, slotseq = 0;
6617         int maxslot, slotpos;
6618         uint8_t sessionid[NFSX_V4SESSIONID];
6619         int error;
6620
6621         error = nfsv4_getcbsession(clp, sepp);
6622         if (error != 0)
6623                 return (error);
6624         sep = *sepp;
6625         (void)nfsv4_sequencelookup(NULL, &sep->sess_cbsess, &slotpos, &maxslot,
6626             &slotseq, sessionid);
6627         KASSERT(maxslot >= 0, ("nfsv4_setcbsequence neg maxslot"));
6628
6629         /* Build the Sequence arguments. */
6630         NFSM_BUILD(tl, uint32_t *, NFSX_V4SESSIONID + 5 * NFSX_UNSIGNED);
6631         bcopy(sessionid, tl, NFSX_V4SESSIONID);
6632         tl += NFSX_V4SESSIONID / NFSX_UNSIGNED;
6633         nd->nd_slotseq = tl;
6634         *tl++ = txdr_unsigned(slotseq);
6635         *tl++ = txdr_unsigned(slotpos);
6636         *tl++ = txdr_unsigned(maxslot);
6637         if (dont_replycache == 0)
6638                 *tl++ = newnfs_true;
6639         else
6640                 *tl++ = newnfs_false;
6641         *tl = 0;                        /* No referring call list, for now. */
6642         nd->nd_flag |= ND_HASSEQUENCE;
6643         return (0);
6644 }
6645
6646 /*
6647  * Get a session for the callback.
6648  */
6649 static int
6650 nfsv4_getcbsession(struct nfsclient *clp, struct nfsdsession **sepp)
6651 {
6652         struct nfsdsession *sep;
6653
6654         NFSLOCKSTATE();
6655         LIST_FOREACH(sep, &clp->lc_session, sess_list) {
6656                 if ((sep->sess_crflags & NFSV4CRSESS_CONNBACKCHAN) != 0)
6657                         break;
6658         }
6659         if (sep == NULL) {
6660                 NFSUNLOCKSTATE();
6661                 return (NFSERR_BADSESSION);
6662         }
6663         sep->sess_refcnt++;
6664         *sepp = sep;
6665         NFSUNLOCKSTATE();
6666         return (0);
6667 }
6668
6669 /*
6670  * Free up all backchannel xprts.  This needs to be done when the nfsd threads
6671  * exit, since those transports will all be going away.
6672  * This is only called after all the nfsd threads are done performing RPCs,
6673  * so locking shouldn't be an issue.
6674  */
6675 void
6676 nfsrv_freeallbackchannel_xprts(void)
6677 {
6678         struct nfsdsession *sep;
6679         struct nfsclient *clp;
6680         SVCXPRT *xprt;
6681         int i;
6682
6683         for (i = 0; i < nfsrv_clienthashsize; i++) {
6684                 LIST_FOREACH(clp, &nfsclienthash[i], lc_hash) {
6685                         LIST_FOREACH(sep, &clp->lc_session, sess_list) {
6686                                 xprt = sep->sess_cbsess.nfsess_xprt;
6687                                 sep->sess_cbsess.nfsess_xprt = NULL;
6688                                 if (xprt != NULL)
6689                                         SVC_RELEASE(xprt);
6690                         }
6691                 }
6692         }
6693 }
6694
6695 /*
6696  * Do a layout commit.  Actually just call nfsrv_updatemdsattr().
6697  * I have no idea if the rest of these arguments will ever be useful?
6698  */
6699 int
6700 nfsrv_layoutcommit(struct nfsrv_descript *nd, vnode_t vp, int layouttype,
6701     int hasnewoff, uint64_t newoff, uint64_t offset, uint64_t len,
6702     int hasnewmtime, struct timespec *newmtimep, int reclaim,
6703     nfsv4stateid_t *stateidp, int maxcnt, char *layp, int *hasnewsizep,
6704     uint64_t *newsizep, struct ucred *cred, NFSPROC_T *p)
6705 {
6706         struct nfsvattr na;
6707         int error;
6708
6709         error = nfsrv_updatemdsattr(vp, &na, p);
6710         if (error == 0) {
6711                 *hasnewsizep = 1;
6712                 *newsizep = na.na_size;
6713         }
6714         return (error);
6715 }
6716
6717 /*
6718  * Try and get a layout.
6719  */
6720 int
6721 nfsrv_layoutget(struct nfsrv_descript *nd, vnode_t vp, struct nfsexstuff *exp,
6722     int layouttype, int *iomode, uint64_t *offset, uint64_t *len,
6723     uint64_t minlen, nfsv4stateid_t *stateidp, int maxcnt, int *retonclose,
6724     int *layoutlenp, char *layp, struct ucred *cred, NFSPROC_T *p)
6725 {
6726         struct nfslayouthash *lhyp;
6727         struct nfslayout *lyp;
6728         char *devid;
6729         fhandle_t fh, *dsfhp;
6730         int error, mirrorcnt;
6731
6732         if (nfsrv_devidcnt == 0)
6733                 return (NFSERR_UNKNLAYOUTTYPE);
6734
6735         if (*offset != 0)
6736                 printf("nfsrv_layoutget: off=%ju len=%ju\n", (uintmax_t)*offset,
6737                     (uintmax_t)*len);
6738         error = nfsvno_getfh(vp, &fh, p);
6739         NFSD_DEBUG(4, "layoutget getfh=%d\n", error);
6740         if (error != 0)
6741                 return (error);
6742
6743         /*
6744          * For now, all layouts are for entire files.
6745          * Only issue Read/Write layouts if requested for a non-readonly fs.
6746          */
6747         if (NFSVNO_EXRDONLY(exp)) {
6748                 if (*iomode == NFSLAYOUTIOMODE_RW)
6749                         return (NFSERR_LAYOUTTRYLATER);
6750                 *iomode = NFSLAYOUTIOMODE_READ;
6751         }
6752         if (*iomode != NFSLAYOUTIOMODE_RW)
6753                 *iomode = NFSLAYOUTIOMODE_READ;
6754
6755         /*
6756          * Check to see if a write layout can be issued for this file.
6757          * This is used during mirror recovery to avoid RW layouts being
6758          * issued for a file while it is being copied to the recovered
6759          * mirror.
6760          */
6761         if (*iomode == NFSLAYOUTIOMODE_RW && nfsrv_dontlayout(&fh) != 0)
6762                 return (NFSERR_LAYOUTTRYLATER);
6763
6764         *retonclose = 0;
6765         *offset = 0;
6766         *len = UINT64_MAX;
6767
6768         /* First, see if a layout already exists and return if found. */
6769         lhyp = NFSLAYOUTHASH(&fh);
6770         NFSLOCKLAYOUT(lhyp);
6771         error = nfsrv_findlayout(&nd->nd_clientid, &fh, layouttype, p, &lyp);
6772         NFSD_DEBUG(4, "layoutget findlay=%d\n", error);
6773         /*
6774          * Not sure if the seqid must be the same, so I won't check it.
6775          */
6776         if (error == 0 && (stateidp->other[0] != lyp->lay_stateid.other[0] ||
6777             stateidp->other[1] != lyp->lay_stateid.other[1] ||
6778             stateidp->other[2] != lyp->lay_stateid.other[2])) {
6779                 if ((lyp->lay_flags & NFSLAY_CALLB) == 0) {
6780                         NFSUNLOCKLAYOUT(lhyp);
6781                         NFSD_DEBUG(1, "ret bad stateid\n");
6782                         return (NFSERR_BADSTATEID);
6783                 }
6784                 /*
6785                  * I believe we get here because there is a race between
6786                  * the client processing the CBLAYOUTRECALL and the layout
6787                  * being deleted here on the server.
6788                  * The client has now done a LayoutGet with a non-layout
6789                  * stateid, as it would when there is no layout.
6790                  * As such, free this layout and set error == NFSERR_BADSTATEID
6791                  * so the code below will create a new layout structure as
6792                  * would happen if no layout was found.
6793                  * "lyp" will be set before being used below, but set it NULL
6794                  * as a safety belt.
6795                  */
6796                 nfsrv_freelayout(&lhyp->list, lyp);
6797                 lyp = NULL;
6798                 error = NFSERR_BADSTATEID;
6799         }
6800         if (error == 0) {
6801                 if (lyp->lay_layoutlen > maxcnt) {
6802                         NFSUNLOCKLAYOUT(lhyp);
6803                         NFSD_DEBUG(1, "ret layout too small\n");
6804                         return (NFSERR_TOOSMALL);
6805                 }
6806                 if (*iomode == NFSLAYOUTIOMODE_RW)
6807                         lyp->lay_flags |= NFSLAY_RW;
6808                 else
6809                         lyp->lay_flags |= NFSLAY_READ;
6810                 NFSBCOPY(lyp->lay_xdr, layp, lyp->lay_layoutlen);
6811                 *layoutlenp = lyp->lay_layoutlen;
6812                 if (++lyp->lay_stateid.seqid == 0)
6813                         lyp->lay_stateid.seqid = 1;
6814                 stateidp->seqid = lyp->lay_stateid.seqid;
6815                 NFSUNLOCKLAYOUT(lhyp);
6816                 NFSD_DEBUG(4, "ret fnd layout\n");
6817                 return (0);
6818         }
6819         NFSUNLOCKLAYOUT(lhyp);
6820
6821         /* Find the device id and file handle. */
6822         dsfhp = malloc(sizeof(fhandle_t) * NFSDEV_MAXMIRRORS, M_TEMP, M_WAITOK);
6823         devid = malloc(NFSX_V4DEVICEID * NFSDEV_MAXMIRRORS, M_TEMP, M_WAITOK);
6824         error = nfsrv_dsgetdevandfh(vp, p, &mirrorcnt, dsfhp, devid);
6825         NFSD_DEBUG(4, "layoutget devandfh=%d\n", error);
6826         if (error == 0) {
6827                 if (layouttype == NFSLAYOUT_NFSV4_1_FILES) {
6828                         if (NFSX_V4FILELAYOUT > maxcnt)
6829                                 error = NFSERR_TOOSMALL;
6830                         else
6831                                 lyp = nfsrv_filelayout(nd, *iomode, &fh, dsfhp,
6832                                     devid, vp->v_mount->mnt_stat.f_fsid);
6833                 } else {
6834                         if (NFSX_V4FLEXLAYOUT(mirrorcnt) > maxcnt)
6835                                 error = NFSERR_TOOSMALL;
6836                         else
6837                                 lyp = nfsrv_flexlayout(nd, *iomode, mirrorcnt,
6838                                     &fh, dsfhp, devid,
6839                                     vp->v_mount->mnt_stat.f_fsid);
6840                 }
6841         }
6842         free(dsfhp, M_TEMP);
6843         free(devid, M_TEMP);
6844         if (error != 0)
6845                 return (error);
6846
6847         /*
6848          * Now, add this layout to the list.
6849          */
6850         error = nfsrv_addlayout(nd, &lyp, stateidp, layp, layoutlenp, p);
6851         NFSD_DEBUG(4, "layoutget addl=%d\n", error);
6852         /*
6853          * The lyp will be set to NULL by nfsrv_addlayout() if it
6854          * linked the new structure into the lists.
6855          */
6856         free(lyp, M_NFSDSTATE);
6857         return (error);
6858 }
6859
6860 /*
6861  * Generate a File Layout.
6862  */
6863 static struct nfslayout *
6864 nfsrv_filelayout(struct nfsrv_descript *nd, int iomode, fhandle_t *fhp,
6865     fhandle_t *dsfhp, char *devid, fsid_t fs)
6866 {
6867         uint32_t *tl;
6868         struct nfslayout *lyp;
6869         uint64_t pattern_offset;
6870
6871         lyp = malloc(sizeof(struct nfslayout) + NFSX_V4FILELAYOUT, M_NFSDSTATE,
6872             M_WAITOK | M_ZERO);
6873         lyp->lay_type = NFSLAYOUT_NFSV4_1_FILES;
6874         if (iomode == NFSLAYOUTIOMODE_RW)
6875                 lyp->lay_flags = NFSLAY_RW;
6876         else
6877                 lyp->lay_flags = NFSLAY_READ;
6878         NFSBCOPY(fhp, &lyp->lay_fh, sizeof(*fhp));
6879         lyp->lay_clientid.qval = nd->nd_clientid.qval;
6880         lyp->lay_fsid = fs;
6881
6882         /* Fill in the xdr for the files layout. */
6883         tl = (uint32_t *)lyp->lay_xdr;
6884         NFSBCOPY(devid, tl, NFSX_V4DEVICEID);           /* Device ID. */
6885         tl += (NFSX_V4DEVICEID / NFSX_UNSIGNED);
6886
6887         /*
6888          * Make the stripe size as many 64K blocks as will fit in the stripe
6889          * mask. Since there is only one stripe, the stripe size doesn't really
6890          * matter, except that the Linux client will only handle an exact
6891          * multiple of their PAGE_SIZE (usually 4K).  I chose 64K as a value
6892          * that should cover most/all arches w.r.t. PAGE_SIZE.
6893          */
6894         *tl++ = txdr_unsigned(NFSFLAYUTIL_STRIPE_MASK & ~0xffff);
6895         *tl++ = 0;                                      /* 1st stripe index. */
6896         pattern_offset = 0;
6897         txdr_hyper(pattern_offset, tl); tl += 2;        /* Pattern offset. */
6898         *tl++ = txdr_unsigned(1);                       /* 1 file handle. */
6899         *tl++ = txdr_unsigned(NFSX_V4PNFSFH);
6900         NFSBCOPY(dsfhp, tl, sizeof(*dsfhp));
6901         lyp->lay_layoutlen = NFSX_V4FILELAYOUT;
6902         return (lyp);
6903 }
6904
6905 #define FLEX_OWNERID    "999"
6906 #define FLEX_UID0       "0"
6907 /*
6908  * Generate a Flex File Layout.
6909  * The FLEX_OWNERID can be any string of 3 decimal digits. Although this
6910  * string goes on the wire, it isn't supposed to be used by the client,
6911  * since this server uses tight coupling.
6912  * Although not recommended by the spec., if vfs.nfsd.flexlinuxhack=1 use
6913  * a string of "0". This works around the Linux Flex File Layout driver bug
6914  * which uses the synthetic uid/gid strings for the "tightly coupled" case.
6915  */
6916 static struct nfslayout *
6917 nfsrv_flexlayout(struct nfsrv_descript *nd, int iomode, int mirrorcnt,
6918     fhandle_t *fhp, fhandle_t *dsfhp, char *devid, fsid_t fs)
6919 {
6920         uint32_t *tl;
6921         struct nfslayout *lyp;
6922         uint64_t lenval;
6923         int i;
6924
6925         lyp = malloc(sizeof(struct nfslayout) + NFSX_V4FLEXLAYOUT(mirrorcnt),
6926             M_NFSDSTATE, M_WAITOK | M_ZERO);
6927         lyp->lay_type = NFSLAYOUT_FLEXFILE;
6928         if (iomode == NFSLAYOUTIOMODE_RW)
6929                 lyp->lay_flags = NFSLAY_RW;
6930         else
6931                 lyp->lay_flags = NFSLAY_READ;
6932         NFSBCOPY(fhp, &lyp->lay_fh, sizeof(*fhp));
6933         lyp->lay_clientid.qval = nd->nd_clientid.qval;
6934         lyp->lay_fsid = fs;
6935         lyp->lay_mirrorcnt = mirrorcnt;
6936
6937         /* Fill in the xdr for the files layout. */
6938         tl = (uint32_t *)lyp->lay_xdr;
6939         lenval = 0;
6940         txdr_hyper(lenval, tl); tl += 2;                /* Stripe unit. */
6941         *tl++ = txdr_unsigned(mirrorcnt);               /* # of mirrors. */
6942         for (i = 0; i < mirrorcnt; i++) {
6943                 *tl++ = txdr_unsigned(1);               /* One stripe. */
6944                 NFSBCOPY(devid, tl, NFSX_V4DEVICEID);   /* Device ID. */
6945                 tl += (NFSX_V4DEVICEID / NFSX_UNSIGNED);
6946                 devid += NFSX_V4DEVICEID;
6947                 *tl++ = txdr_unsigned(1);               /* Efficiency. */
6948                 *tl++ = 0;                              /* Proxy Stateid. */
6949                 *tl++ = 0x55555555;
6950                 *tl++ = 0x55555555;
6951                 *tl++ = 0x55555555;
6952                 *tl++ = txdr_unsigned(1);               /* 1 file handle. */
6953                 *tl++ = txdr_unsigned(NFSX_V4PNFSFH);
6954                 NFSBCOPY(dsfhp, tl, sizeof(*dsfhp));
6955                 tl += (NFSM_RNDUP(NFSX_V4PNFSFH) / NFSX_UNSIGNED);
6956                 dsfhp++;
6957                 if (nfsrv_flexlinuxhack != 0) {
6958                         *tl++ = txdr_unsigned(strlen(FLEX_UID0));
6959                         *tl = 0;                /* 0 pad string. */
6960                         NFSBCOPY(FLEX_UID0, tl++, strlen(FLEX_UID0));
6961                         *tl++ = txdr_unsigned(strlen(FLEX_UID0));
6962                         *tl = 0;                /* 0 pad string. */
6963                         NFSBCOPY(FLEX_UID0, tl++, strlen(FLEX_UID0));
6964                 } else {
6965                         *tl++ = txdr_unsigned(strlen(FLEX_OWNERID));
6966                         NFSBCOPY(FLEX_OWNERID, tl++, NFSX_UNSIGNED);
6967                         *tl++ = txdr_unsigned(strlen(FLEX_OWNERID));
6968                         NFSBCOPY(FLEX_OWNERID, tl++, NFSX_UNSIGNED);
6969                 }
6970         }
6971         *tl++ = txdr_unsigned(0);               /* ff_flags. */
6972         *tl = txdr_unsigned(60);                /* Status interval hint. */
6973         lyp->lay_layoutlen = NFSX_V4FLEXLAYOUT(mirrorcnt);
6974         return (lyp);
6975 }
6976
6977 /*
6978  * Parse and process Flex File errors returned via LayoutReturn.
6979  */
6980 static void
6981 nfsrv_flexlayouterr(struct nfsrv_descript *nd, uint32_t *layp, int maxcnt,
6982     NFSPROC_T *p)
6983 {
6984         uint32_t *tl;
6985         int cnt, errcnt, i, j, opnum, stat;
6986         char devid[NFSX_V4DEVICEID];
6987
6988         tl = layp;
6989         cnt = fxdr_unsigned(int, *tl++);
6990         NFSD_DEBUG(4, "flexlayouterr cnt=%d\n", cnt);
6991         for (i = 0; i < cnt; i++) {
6992                 /* Skip offset, length and stateid for now. */
6993                 tl += (4 + NFSX_STATEID / NFSX_UNSIGNED);
6994                 errcnt = fxdr_unsigned(int, *tl++);
6995                 NFSD_DEBUG(4, "flexlayouterr errcnt=%d\n", errcnt);
6996                 for (j = 0; j < errcnt; j++) {
6997                         NFSBCOPY(tl, devid, NFSX_V4DEVICEID);
6998                         tl += (NFSX_V4DEVICEID / NFSX_UNSIGNED);
6999                         stat = fxdr_unsigned(int, *tl++);
7000                         opnum = fxdr_unsigned(int, *tl++);
7001                         NFSD_DEBUG(4, "flexlayouterr op=%d stat=%d\n", opnum,
7002                             stat);
7003                         /*
7004                          * Except for NFSERR_ACCES and NFSERR_STALE errors,
7005                          * disable the mirror.
7006                          */
7007                         if (stat != NFSERR_ACCES && stat != NFSERR_STALE)
7008                                 nfsrv_delds(devid, p);
7009                 }
7010         }
7011 }
7012
7013 /*
7014  * This function removes all flex file layouts which has a mirror with
7015  * a device id that matches the argument.
7016  * Called when the DS represented by the device id has failed.
7017  */
7018 void
7019 nfsrv_flexmirrordel(char *devid, NFSPROC_T *p)
7020 {
7021         uint32_t *tl;
7022         struct nfslayout *lyp, *nlyp;
7023         struct nfslayouthash *lhyp;
7024         struct nfslayouthead loclyp;
7025         int i, j;
7026
7027         NFSD_DEBUG(4, "flexmirrordel\n");
7028         /* Move all layouts found onto a local list. */
7029         TAILQ_INIT(&loclyp);
7030         for (i = 0; i < nfsrv_layouthashsize; i++) {
7031                 lhyp = &nfslayouthash[i];
7032                 NFSLOCKLAYOUT(lhyp);
7033                 TAILQ_FOREACH_SAFE(lyp, &lhyp->list, lay_list, nlyp) {
7034                         if (lyp->lay_type == NFSLAYOUT_FLEXFILE &&
7035                             lyp->lay_mirrorcnt > 1) {
7036                                 NFSD_DEBUG(4, "possible match\n");
7037                                 tl = lyp->lay_xdr;
7038                                 tl += 3;
7039                                 for (j = 0; j < lyp->lay_mirrorcnt; j++) {
7040                                         tl++;
7041                                         if (NFSBCMP(devid, tl, NFSX_V4DEVICEID)
7042                                             == 0) {
7043                                                 /* Found one. */
7044                                                 NFSD_DEBUG(4, "fnd one\n");
7045                                                 TAILQ_REMOVE(&lhyp->list, lyp,
7046                                                     lay_list);
7047                                                 TAILQ_INSERT_HEAD(&loclyp, lyp,
7048                                                     lay_list);
7049                                                 break;
7050                                         }
7051                                         tl += (NFSX_V4DEVICEID / NFSX_UNSIGNED +
7052                                             NFSM_RNDUP(NFSX_V4PNFSFH) /
7053                                             NFSX_UNSIGNED + 11 * NFSX_UNSIGNED);
7054                                 }
7055                         }
7056                 }
7057                 NFSUNLOCKLAYOUT(lhyp);
7058         }
7059
7060         /* Now, try to do a Layout recall for each one found. */
7061         TAILQ_FOREACH_SAFE(lyp, &loclyp, lay_list, nlyp) {
7062                 NFSD_DEBUG(4, "do layout recall\n");
7063                 /*
7064                  * The layout stateid.seqid needs to be incremented
7065                  * before doing a LAYOUT_RECALL callback.
7066                  */
7067                 if (++lyp->lay_stateid.seqid == 0)
7068                         lyp->lay_stateid.seqid = 1;
7069                 nfsrv_recalllayout(lyp->lay_clientid, &lyp->lay_stateid,
7070                     &lyp->lay_fh, lyp, 1, lyp->lay_type, p);
7071                 nfsrv_freelayout(&loclyp, lyp);
7072         }
7073 }
7074
7075 /*
7076  * Do a recall callback to the client for this layout.
7077  */
7078 static int
7079 nfsrv_recalllayout(nfsquad_t clid, nfsv4stateid_t *stateidp, fhandle_t *fhp,
7080     struct nfslayout *lyp, int changed, int laytype, NFSPROC_T *p)
7081 {
7082         struct nfsclient *clp;
7083         int error;
7084
7085         NFSD_DEBUG(4, "nfsrv_recalllayout\n");
7086         error = nfsrv_getclient(clid, 0, &clp, NULL, (nfsquad_t)((u_quad_t)0),
7087             0, NULL, p);
7088         NFSD_DEBUG(4, "aft nfsrv_getclient=%d\n", error);
7089         if (error != 0) {
7090                 printf("nfsrv_recalllayout: getclient err=%d\n", error);
7091                 return (error);
7092         }
7093         if ((clp->lc_flags & LCL_NFSV41) != 0) {
7094                 error = nfsrv_docallback(clp, NFSV4OP_CBLAYOUTRECALL,
7095                     stateidp, changed, fhp, NULL, NULL, laytype, p);
7096                 /* If lyp != NULL, handle an error return here. */
7097                 if (error != 0 && lyp != NULL) {
7098                         NFSDRECALLLOCK();
7099                         /*
7100                          * Mark it returned, since no layout recall
7101                          * has been done.
7102                          * All errors seem to be non-recoverable, although
7103                          * NFSERR_NOMATCHLAYOUT is a normal event.
7104                          */
7105                         if ((lyp->lay_flags & NFSLAY_RECALL) != 0) {
7106                                 lyp->lay_flags |= NFSLAY_RETURNED;
7107                                 wakeup(lyp);
7108                         }
7109                         NFSDRECALLUNLOCK();
7110                         if (error != NFSERR_NOMATCHLAYOUT)
7111                                 printf("nfsrv_recalllayout: err=%d\n", error);
7112                 }
7113         } else
7114                 printf("nfsrv_recalllayout: clp not NFSv4.1\n");
7115         return (error);
7116 }
7117
7118 /*
7119  * Find a layout to recall when we exceed our high water mark.
7120  */
7121 void
7122 nfsrv_recalloldlayout(NFSPROC_T *p)
7123 {
7124         struct nfslayouthash *lhyp;
7125         struct nfslayout *lyp;
7126         nfsquad_t clientid;
7127         nfsv4stateid_t stateid;
7128         fhandle_t fh;
7129         int error, laytype = 0, ret;
7130
7131         lhyp = &nfslayouthash[arc4random() % nfsrv_layouthashsize];
7132         NFSLOCKLAYOUT(lhyp);
7133         TAILQ_FOREACH_REVERSE(lyp, &lhyp->list, nfslayouthead, lay_list) {
7134                 if ((lyp->lay_flags & NFSLAY_CALLB) == 0) {
7135                         lyp->lay_flags |= NFSLAY_CALLB;
7136                         /*
7137                          * The layout stateid.seqid needs to be incremented
7138                          * before doing a LAYOUT_RECALL callback.
7139                          */
7140                         if (++lyp->lay_stateid.seqid == 0)
7141                                 lyp->lay_stateid.seqid = 1;
7142                         clientid = lyp->lay_clientid;
7143                         stateid = lyp->lay_stateid;
7144                         NFSBCOPY(&lyp->lay_fh, &fh, sizeof(fh));
7145                         laytype = lyp->lay_type;
7146                         break;
7147                 }
7148         }
7149         NFSUNLOCKLAYOUT(lhyp);
7150         if (lyp != NULL) {
7151                 error = nfsrv_recalllayout(clientid, &stateid, &fh, NULL, 0,
7152                     laytype, p);
7153                 if (error != 0 && error != NFSERR_NOMATCHLAYOUT)
7154                         NFSD_DEBUG(4, "recallold=%d\n", error);
7155                 if (error != 0) {
7156                         NFSLOCKLAYOUT(lhyp);
7157                         /*
7158                          * Since the hash list was unlocked, we need to
7159                          * find it again.
7160                          */
7161                         ret = nfsrv_findlayout(&clientid, &fh, laytype, p,
7162                             &lyp);
7163                         if (ret == 0 &&
7164                             (lyp->lay_flags & NFSLAY_CALLB) != 0 &&
7165                             lyp->lay_stateid.other[0] == stateid.other[0] &&
7166                             lyp->lay_stateid.other[1] == stateid.other[1] &&
7167                             lyp->lay_stateid.other[2] == stateid.other[2]) {
7168                                 /*
7169                                  * The client no longer knows this layout, so
7170                                  * it can be free'd now.
7171                                  */
7172                                 if (error == NFSERR_NOMATCHLAYOUT)
7173                                         nfsrv_freelayout(&lhyp->list, lyp);
7174                                 else {
7175                                         /*
7176                                          * Leave it to be tried later by
7177                                          * clearing NFSLAY_CALLB and moving
7178                                          * it to the head of the list, so it
7179                                          * won't be tried again for a while.
7180                                          */
7181                                         lyp->lay_flags &= ~NFSLAY_CALLB;
7182                                         TAILQ_REMOVE(&lhyp->list, lyp,
7183                                             lay_list);
7184                                         TAILQ_INSERT_HEAD(&lhyp->list, lyp,
7185                                             lay_list);
7186                                 }
7187                         }
7188                         NFSUNLOCKLAYOUT(lhyp);
7189                 }
7190         }
7191 }
7192
7193 /*
7194  * Try and return layout(s).
7195  */
7196 int
7197 nfsrv_layoutreturn(struct nfsrv_descript *nd, vnode_t vp,
7198     int layouttype, int iomode, uint64_t offset, uint64_t len, int reclaim,
7199     int kind, nfsv4stateid_t *stateidp, int maxcnt, uint32_t *layp, int *fndp,
7200     struct ucred *cred, NFSPROC_T *p)
7201 {
7202         struct nfsvattr na;
7203         struct nfslayouthash *lhyp;
7204         struct nfslayout *lyp;
7205         fhandle_t fh;
7206         int error = 0;
7207
7208         *fndp = 0;
7209         if (kind == NFSV4LAYOUTRET_FILE) {
7210                 error = nfsvno_getfh(vp, &fh, p);
7211                 if (error == 0) {
7212                         error = nfsrv_updatemdsattr(vp, &na, p);
7213                         if (error != 0)
7214                                 printf("nfsrv_layoutreturn: updatemdsattr"
7215                                     " failed=%d\n", error);
7216                 }
7217                 if (error == 0) {
7218                         if (reclaim == newnfs_true) {
7219                                 error = nfsrv_checkgrace(NULL, NULL,
7220                                     NFSLCK_RECLAIM);
7221                                 if (error != NFSERR_NOGRACE)
7222                                         error = 0;
7223                                 return (error);
7224                         }
7225                         lhyp = NFSLAYOUTHASH(&fh);
7226                         NFSDRECALLLOCK();
7227                         NFSLOCKLAYOUT(lhyp);
7228                         error = nfsrv_findlayout(&nd->nd_clientid, &fh,
7229                             layouttype, p, &lyp);
7230                         NFSD_DEBUG(4, "layoutret findlay=%d\n", error);
7231                         if (error == 0 &&
7232                             stateidp->other[0] == lyp->lay_stateid.other[0] &&
7233                             stateidp->other[1] == lyp->lay_stateid.other[1] &&
7234                             stateidp->other[2] == lyp->lay_stateid.other[2]) {
7235                                 NFSD_DEBUG(4, "nfsrv_layoutreturn: stateid %d"
7236                                     " %x %x %x laystateid %d %x %x %x"
7237                                     " off=%ju len=%ju flgs=0x%x\n",
7238                                     stateidp->seqid, stateidp->other[0],
7239                                     stateidp->other[1], stateidp->other[2],
7240                                     lyp->lay_stateid.seqid,
7241                                     lyp->lay_stateid.other[0],
7242                                     lyp->lay_stateid.other[1],
7243                                     lyp->lay_stateid.other[2],
7244                                     (uintmax_t)offset, (uintmax_t)len,
7245                                     lyp->lay_flags);
7246                                 if (++lyp->lay_stateid.seqid == 0)
7247                                         lyp->lay_stateid.seqid = 1;
7248                                 stateidp->seqid = lyp->lay_stateid.seqid;
7249                                 if (offset == 0 && len == UINT64_MAX) {
7250                                         if ((iomode & NFSLAYOUTIOMODE_READ) !=
7251                                             0)
7252                                                 lyp->lay_flags &= ~NFSLAY_READ;
7253                                         if ((iomode & NFSLAYOUTIOMODE_RW) != 0)
7254                                                 lyp->lay_flags &= ~NFSLAY_RW;
7255                                         if ((lyp->lay_flags & (NFSLAY_READ |
7256                                             NFSLAY_RW)) == 0)
7257                                                 nfsrv_freelayout(&lhyp->list,
7258                                                     lyp);
7259                                         else
7260                                                 *fndp = 1;
7261                                 } else
7262                                         *fndp = 1;
7263                         }
7264                         NFSUNLOCKLAYOUT(lhyp);
7265                         /* Search the nfsrv_recalllist for a match. */
7266                         TAILQ_FOREACH(lyp, &nfsrv_recalllisthead, lay_list) {
7267                                 if (NFSBCMP(&lyp->lay_fh, &fh,
7268                                     sizeof(fh)) == 0 &&
7269                                     lyp->lay_clientid.qval ==
7270                                     nd->nd_clientid.qval &&
7271                                     stateidp->other[0] ==
7272                                     lyp->lay_stateid.other[0] &&
7273                                     stateidp->other[1] ==
7274                                     lyp->lay_stateid.other[1] &&
7275                                     stateidp->other[2] ==
7276                                     lyp->lay_stateid.other[2]) {
7277                                         lyp->lay_flags |= NFSLAY_RETURNED;
7278                                         wakeup(lyp);
7279                                         error = 0;
7280                                 }
7281                         }
7282                         NFSDRECALLUNLOCK();
7283                 }
7284                 if (layouttype == NFSLAYOUT_FLEXFILE)
7285                         nfsrv_flexlayouterr(nd, layp, maxcnt, p);
7286         } else if (kind == NFSV4LAYOUTRET_FSID)
7287                 nfsrv_freelayouts(&nd->nd_clientid,
7288                     &vp->v_mount->mnt_stat.f_fsid, layouttype, iomode);
7289         else if (kind == NFSV4LAYOUTRET_ALL)
7290                 nfsrv_freelayouts(&nd->nd_clientid, NULL, layouttype, iomode);
7291         else
7292                 error = NFSERR_INVAL;
7293         if (error == -1)
7294                 error = 0;
7295         return (error);
7296 }
7297
7298 /*
7299  * Look for an existing layout.
7300  */
7301 static int
7302 nfsrv_findlayout(nfsquad_t *clientidp, fhandle_t *fhp, int laytype,
7303     NFSPROC_T *p, struct nfslayout **lypp)
7304 {
7305         struct nfslayouthash *lhyp;
7306         struct nfslayout *lyp;
7307         int ret;
7308
7309         *lypp = NULL;
7310         ret = 0;
7311         lhyp = NFSLAYOUTHASH(fhp);
7312         TAILQ_FOREACH(lyp, &lhyp->list, lay_list) {
7313                 if (NFSBCMP(&lyp->lay_fh, fhp, sizeof(*fhp)) == 0 &&
7314                     lyp->lay_clientid.qval == clientidp->qval &&
7315                     lyp->lay_type == laytype)
7316                         break;
7317         }
7318         if (lyp != NULL)
7319                 *lypp = lyp;
7320         else
7321                 ret = -1;
7322         return (ret);
7323 }
7324
7325 /*
7326  * Add the new layout, as required.
7327  */
7328 static int
7329 nfsrv_addlayout(struct nfsrv_descript *nd, struct nfslayout **lypp,
7330     nfsv4stateid_t *stateidp, char *layp, int *layoutlenp, NFSPROC_T *p)
7331 {
7332         struct nfsclient *clp;
7333         struct nfslayouthash *lhyp;
7334         struct nfslayout *lyp, *nlyp;
7335         fhandle_t *fhp;
7336         int error;
7337
7338         KASSERT((nd->nd_flag & ND_IMPLIEDCLID) != 0,
7339             ("nfsrv_layoutget: no nd_clientid\n"));
7340         lyp = *lypp;
7341         fhp = &lyp->lay_fh;
7342         NFSLOCKSTATE();
7343         error = nfsrv_getclient((nfsquad_t)((u_quad_t)0), CLOPS_RENEW, &clp,
7344             NULL, (nfsquad_t)((u_quad_t)0), 0, nd, p);
7345         if (error != 0) {
7346                 NFSUNLOCKSTATE();
7347                 return (error);
7348         }
7349         lyp->lay_stateid.seqid = stateidp->seqid = 1;
7350         lyp->lay_stateid.other[0] = stateidp->other[0] =
7351             clp->lc_clientid.lval[0];
7352         lyp->lay_stateid.other[1] = stateidp->other[1] =
7353             clp->lc_clientid.lval[1];
7354         lyp->lay_stateid.other[2] = stateidp->other[2] =
7355             nfsrv_nextstateindex(clp);
7356         NFSUNLOCKSTATE();
7357
7358         lhyp = NFSLAYOUTHASH(fhp);
7359         NFSLOCKLAYOUT(lhyp);
7360         TAILQ_FOREACH(nlyp, &lhyp->list, lay_list) {
7361                 if (NFSBCMP(&nlyp->lay_fh, fhp, sizeof(*fhp)) == 0 &&
7362                     nlyp->lay_clientid.qval == nd->nd_clientid.qval)
7363                         break;
7364         }
7365         if (nlyp != NULL) {
7366                 /* A layout already exists, so use it. */
7367                 nlyp->lay_flags |= (lyp->lay_flags & (NFSLAY_READ | NFSLAY_RW));
7368                 NFSBCOPY(nlyp->lay_xdr, layp, nlyp->lay_layoutlen);
7369                 *layoutlenp = nlyp->lay_layoutlen;
7370                 if (++nlyp->lay_stateid.seqid == 0)
7371                         nlyp->lay_stateid.seqid = 1;
7372                 stateidp->seqid = nlyp->lay_stateid.seqid;
7373                 stateidp->other[0] = nlyp->lay_stateid.other[0];
7374                 stateidp->other[1] = nlyp->lay_stateid.other[1];
7375                 stateidp->other[2] = nlyp->lay_stateid.other[2];
7376                 NFSUNLOCKLAYOUT(lhyp);
7377                 return (0);
7378         }
7379
7380         /* Insert the new layout in the lists. */
7381         *lypp = NULL;
7382         atomic_add_int(&nfsrv_layoutcnt, 1);
7383         NFSBCOPY(lyp->lay_xdr, layp, lyp->lay_layoutlen);
7384         *layoutlenp = lyp->lay_layoutlen;
7385         TAILQ_INSERT_HEAD(&lhyp->list, lyp, lay_list);
7386         NFSUNLOCKLAYOUT(lhyp);
7387         return (0);
7388 }
7389
7390 /*
7391  * Get the devinfo for a deviceid.
7392  */
7393 int
7394 nfsrv_getdevinfo(char *devid, int layouttype, uint32_t *maxcnt,
7395     uint32_t *notify, int *devaddrlen, char **devaddr)
7396 {
7397         struct nfsdevice *ds;
7398
7399         if ((layouttype != NFSLAYOUT_NFSV4_1_FILES && layouttype !=
7400              NFSLAYOUT_FLEXFILE) ||
7401             (nfsrv_maxpnfsmirror > 1 && layouttype == NFSLAYOUT_NFSV4_1_FILES))
7402                 return (NFSERR_UNKNLAYOUTTYPE);
7403
7404         /*
7405          * Now, search for the device id.  Note that the structures won't go
7406          * away, but the order changes in the list.  As such, the lock only
7407          * needs to be held during the search through the list.
7408          */
7409         NFSDDSLOCK();
7410         TAILQ_FOREACH(ds, &nfsrv_devidhead, nfsdev_list) {
7411                 if (NFSBCMP(devid, ds->nfsdev_deviceid, NFSX_V4DEVICEID) == 0 &&
7412                     ds->nfsdev_nmp != NULL)
7413                         break;
7414         }
7415         NFSDDSUNLOCK();
7416         if (ds == NULL)
7417                 return (NFSERR_NOENT);
7418
7419         /* If the correct nfsdev_XXXXaddrlen is > 0, we have the device info. */
7420         *devaddrlen = 0;
7421         if (layouttype == NFSLAYOUT_NFSV4_1_FILES) {
7422                 *devaddrlen = ds->nfsdev_fileaddrlen;
7423                 *devaddr = ds->nfsdev_fileaddr;
7424         } else if (layouttype == NFSLAYOUT_FLEXFILE) {
7425                 *devaddrlen = ds->nfsdev_flexaddrlen;
7426                 *devaddr = ds->nfsdev_flexaddr;
7427         }
7428         if (*devaddrlen == 0)
7429                 return (NFSERR_UNKNLAYOUTTYPE);
7430
7431         /*
7432          * The XDR overhead is 3 unsigned values: layout_type,
7433          * length_of_address and notify bitmap.
7434          * If the notify array is changed to not all zeros, the
7435          * count of unsigned values must be increased.
7436          */
7437         if (*maxcnt > 0 && *maxcnt < NFSM_RNDUP(*devaddrlen) +
7438             3 * NFSX_UNSIGNED) {
7439                 *maxcnt = NFSM_RNDUP(*devaddrlen) + 3 * NFSX_UNSIGNED;
7440                 return (NFSERR_TOOSMALL);
7441         }
7442         return (0);
7443 }
7444
7445 /*
7446  * Free a list of layout state structures.
7447  */
7448 static void
7449 nfsrv_freelayoutlist(nfsquad_t clientid)
7450 {
7451         struct nfslayouthash *lhyp;
7452         struct nfslayout *lyp, *nlyp;
7453         int i;
7454
7455         for (i = 0; i < nfsrv_layouthashsize; i++) {
7456                 lhyp = &nfslayouthash[i];
7457                 NFSLOCKLAYOUT(lhyp);
7458                 TAILQ_FOREACH_SAFE(lyp, &lhyp->list, lay_list, nlyp) {
7459                         if (lyp->lay_clientid.qval == clientid.qval)
7460                                 nfsrv_freelayout(&lhyp->list, lyp);
7461                 }
7462                 NFSUNLOCKLAYOUT(lhyp);
7463         }
7464 }
7465
7466 /*
7467  * Free up a layout.
7468  */
7469 static void
7470 nfsrv_freelayout(struct nfslayouthead *lhp, struct nfslayout *lyp)
7471 {
7472
7473         NFSD_DEBUG(4, "Freelayout=%p\n", lyp);
7474         atomic_add_int(&nfsrv_layoutcnt, -1);
7475         TAILQ_REMOVE(lhp, lyp, lay_list);
7476         free(lyp, M_NFSDSTATE);
7477 }
7478
7479 /*
7480  * Free up a device id.
7481  */
7482 void
7483 nfsrv_freeonedevid(struct nfsdevice *ds)
7484 {
7485         int i;
7486
7487         atomic_add_int(&nfsrv_devidcnt, -1);
7488         vrele(ds->nfsdev_dvp);
7489         for (i = 0; i < nfsrv_dsdirsize; i++)
7490                 if (ds->nfsdev_dsdir[i] != NULL)
7491                         vrele(ds->nfsdev_dsdir[i]);
7492         free(ds->nfsdev_fileaddr, M_NFSDSTATE);
7493         free(ds->nfsdev_flexaddr, M_NFSDSTATE);
7494         free(ds->nfsdev_host, M_NFSDSTATE);
7495         free(ds, M_NFSDSTATE);
7496 }
7497
7498 /*
7499  * Free up a device id and its mirrors.
7500  */
7501 static void
7502 nfsrv_freedevid(struct nfsdevice *ds)
7503 {
7504
7505         TAILQ_REMOVE(&nfsrv_devidhead, ds, nfsdev_list);
7506         nfsrv_freeonedevid(ds);
7507 }
7508
7509 /*
7510  * Free all layouts and device ids.
7511  * Done when the nfsd threads are shut down since there may be a new
7512  * modified device id list created when the nfsd is restarted.
7513  */
7514 void
7515 nfsrv_freealllayoutsanddevids(void)
7516 {
7517         struct nfsdontlist *mrp, *nmrp;
7518         struct nfslayout *lyp, *nlyp;
7519
7520         /* Get rid of the deviceid structures. */
7521         nfsrv_freealldevids();
7522         TAILQ_INIT(&nfsrv_devidhead);
7523         nfsrv_devidcnt = 0;
7524
7525         /* Get rid of all layouts. */
7526         nfsrv_freealllayouts();
7527
7528         /* Get rid of any nfsdontlist entries. */
7529         LIST_FOREACH_SAFE(mrp, &nfsrv_dontlisthead, nfsmr_list, nmrp)
7530                 free(mrp, M_NFSDSTATE);
7531         LIST_INIT(&nfsrv_dontlisthead);
7532         nfsrv_dontlistlen = 0;
7533
7534         /* Free layouts in the recall list. */
7535         TAILQ_FOREACH_SAFE(lyp, &nfsrv_recalllisthead, lay_list, nlyp)
7536                 nfsrv_freelayout(&nfsrv_recalllisthead, lyp);
7537         TAILQ_INIT(&nfsrv_recalllisthead);
7538 }
7539
7540 /*
7541  * Free layouts that match the arguments.
7542  */
7543 static void
7544 nfsrv_freelayouts(nfsquad_t *clid, fsid_t *fs, int laytype, int iomode)
7545 {
7546         struct nfslayouthash *lhyp;
7547         struct nfslayout *lyp, *nlyp;
7548         int i;
7549
7550         for (i = 0; i < nfsrv_layouthashsize; i++) {
7551                 lhyp = &nfslayouthash[i];
7552                 NFSLOCKLAYOUT(lhyp);
7553                 TAILQ_FOREACH_SAFE(lyp, &lhyp->list, lay_list, nlyp) {
7554                         if (clid->qval != lyp->lay_clientid.qval)
7555                                 continue;
7556                         if (fs != NULL && fsidcmp(fs, &lyp->lay_fsid) != 0)
7557                                 continue;
7558                         if (laytype != lyp->lay_type)
7559                                 continue;
7560                         if ((iomode & NFSLAYOUTIOMODE_READ) != 0)
7561                                 lyp->lay_flags &= ~NFSLAY_READ;
7562                         if ((iomode & NFSLAYOUTIOMODE_RW) != 0)
7563                                 lyp->lay_flags &= ~NFSLAY_RW;
7564                         if ((lyp->lay_flags & (NFSLAY_READ | NFSLAY_RW)) == 0)
7565                                 nfsrv_freelayout(&lhyp->list, lyp);
7566                 }
7567                 NFSUNLOCKLAYOUT(lhyp);
7568         }
7569 }
7570
7571 /*
7572  * Free all layouts for the argument file.
7573  */
7574 void
7575 nfsrv_freefilelayouts(fhandle_t *fhp)
7576 {
7577         struct nfslayouthash *lhyp;
7578         struct nfslayout *lyp, *nlyp;
7579
7580         lhyp = NFSLAYOUTHASH(fhp);
7581         NFSLOCKLAYOUT(lhyp);
7582         TAILQ_FOREACH_SAFE(lyp, &lhyp->list, lay_list, nlyp) {
7583                 if (NFSBCMP(&lyp->lay_fh, fhp, sizeof(*fhp)) == 0)
7584                         nfsrv_freelayout(&lhyp->list, lyp);
7585         }
7586         NFSUNLOCKLAYOUT(lhyp);
7587 }
7588
7589 /*
7590  * Free all layouts.
7591  */
7592 static void
7593 nfsrv_freealllayouts(void)
7594 {
7595         struct nfslayouthash *lhyp;
7596         struct nfslayout *lyp, *nlyp;
7597         int i;
7598
7599         for (i = 0; i < nfsrv_layouthashsize; i++) {
7600                 lhyp = &nfslayouthash[i];
7601                 NFSLOCKLAYOUT(lhyp);
7602                 TAILQ_FOREACH_SAFE(lyp, &lhyp->list, lay_list, nlyp)
7603                         nfsrv_freelayout(&lhyp->list, lyp);
7604                 NFSUNLOCKLAYOUT(lhyp);
7605         }
7606 }
7607
7608 /*
7609  * Look up the mount path for the DS server.
7610  */
7611 static int
7612 nfsrv_setdsserver(char *dspathp, char *mdspathp, NFSPROC_T *p,
7613     struct nfsdevice **dsp)
7614 {
7615         struct nameidata nd;
7616         struct nfsdevice *ds;
7617         struct mount *mp;
7618         int error, i;
7619         char *dsdirpath;
7620         size_t dsdirsize;
7621
7622         NFSD_DEBUG(4, "setdssrv path=%s\n", dspathp);
7623         *dsp = NULL;
7624         NDINIT(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF, UIO_SYSSPACE,
7625             dspathp, p);
7626         error = namei(&nd);
7627         NFSD_DEBUG(4, "lookup=%d\n", error);
7628         if (error != 0)
7629                 return (error);
7630         if (nd.ni_vp->v_type != VDIR) {
7631                 vput(nd.ni_vp);
7632                 NFSD_DEBUG(4, "dspath not dir\n");
7633                 return (ENOTDIR);
7634         }
7635         if (strcmp(nd.ni_vp->v_mount->mnt_vfc->vfc_name, "nfs") != 0) {
7636                 vput(nd.ni_vp);
7637                 NFSD_DEBUG(4, "dspath not an NFS mount\n");
7638                 return (ENXIO);
7639         }
7640
7641         /*
7642          * Allocate a DS server structure with the NFS mounted directory
7643          * vnode reference counted, so that a non-forced dismount will
7644          * fail with EBUSY.
7645          * This structure is always linked into the list, even if an error
7646          * is being returned.  The caller will free the entire list upon
7647          * an error return.
7648          */
7649         *dsp = ds = malloc(sizeof(*ds) + nfsrv_dsdirsize * sizeof(vnode_t),
7650             M_NFSDSTATE, M_WAITOK | M_ZERO);
7651         ds->nfsdev_dvp = nd.ni_vp;
7652         ds->nfsdev_nmp = VFSTONFS(nd.ni_vp->v_mount);
7653         NFSVOPUNLOCK(nd.ni_vp);
7654
7655         dsdirsize = strlen(dspathp) + 16;
7656         dsdirpath = malloc(dsdirsize, M_TEMP, M_WAITOK);
7657         /* Now, create the DS directory structures. */
7658         for (i = 0; i < nfsrv_dsdirsize; i++) {
7659                 snprintf(dsdirpath, dsdirsize, "%s/ds%d", dspathp, i);
7660                 NDINIT(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF,
7661                     UIO_SYSSPACE, dsdirpath, p);
7662                 error = namei(&nd);
7663                 NFSD_DEBUG(4, "dsdirpath=%s lookup=%d\n", dsdirpath, error);
7664                 if (error != 0)
7665                         break;
7666                 if (nd.ni_vp->v_type != VDIR) {
7667                         vput(nd.ni_vp);
7668                         error = ENOTDIR;
7669                         NFSD_DEBUG(4, "dsdirpath not a VDIR\n");
7670                         break;
7671                 }
7672                 if (strcmp(nd.ni_vp->v_mount->mnt_vfc->vfc_name, "nfs") != 0) {
7673                         vput(nd.ni_vp);
7674                         error = ENXIO;
7675                         NFSD_DEBUG(4, "dsdirpath not an NFS mount\n");
7676                         break;
7677                 }
7678                 ds->nfsdev_dsdir[i] = nd.ni_vp;
7679                 NFSVOPUNLOCK(nd.ni_vp);
7680         }
7681         free(dsdirpath, M_TEMP);
7682
7683         if (strlen(mdspathp) > 0) {
7684                 /*
7685                  * This DS stores file for a specific MDS exported file
7686                  * system.
7687                  */
7688                 NDINIT(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF,
7689                     UIO_SYSSPACE, mdspathp, p);
7690                 error = namei(&nd);
7691                 NFSD_DEBUG(4, "mds lookup=%d\n", error);
7692                 if (error != 0)
7693                         goto out;
7694                 if (nd.ni_vp->v_type != VDIR) {
7695                         vput(nd.ni_vp);
7696                         error = ENOTDIR;
7697                         NFSD_DEBUG(4, "mdspath not dir\n");
7698                         goto out;
7699                 }
7700                 mp = nd.ni_vp->v_mount;
7701                 if ((mp->mnt_flag & MNT_EXPORTED) == 0) {
7702                         vput(nd.ni_vp);
7703                         error = ENXIO;
7704                         NFSD_DEBUG(4, "mdspath not an exported fs\n");
7705                         goto out;
7706                 }
7707                 ds->nfsdev_mdsfsid = mp->mnt_stat.f_fsid;
7708                 ds->nfsdev_mdsisset = 1;
7709                 vput(nd.ni_vp);
7710         }
7711
7712 out:
7713         TAILQ_INSERT_TAIL(&nfsrv_devidhead, ds, nfsdev_list);
7714         atomic_add_int(&nfsrv_devidcnt, 1);
7715         return (error);
7716 }
7717
7718 /*
7719  * Look up the mount path for the DS server and delete it.
7720  */
7721 int
7722 nfsrv_deldsserver(int op, char *dspathp, NFSPROC_T *p)
7723 {
7724         struct mount *mp;
7725         struct nfsmount *nmp;
7726         struct nfsdevice *ds;
7727         int error;
7728
7729         NFSD_DEBUG(4, "deldssrv path=%s\n", dspathp);
7730         /*
7731          * Search for the path in the mount list.  Avoid looking the path
7732          * up, since this mount point may be hung, with associated locked
7733          * vnodes, etc.
7734          * Set NFSMNTP_CANCELRPCS so that any forced dismount will be blocked
7735          * until this completes.
7736          * As noted in the man page, this should be done before any forced
7737          * dismount on the mount point, but at least the handshake on
7738          * NFSMNTP_CANCELRPCS should make it safe.
7739          */
7740         error = 0;
7741         ds = NULL;
7742         nmp = NULL;
7743         mtx_lock(&mountlist_mtx);
7744         TAILQ_FOREACH(mp, &mountlist, mnt_list) {
7745                 if (strcmp(mp->mnt_stat.f_mntonname, dspathp) == 0 &&
7746                     strcmp(mp->mnt_stat.f_fstypename, "nfs") == 0 &&
7747                     mp->mnt_data != NULL) {
7748                         nmp = VFSTONFS(mp);
7749                         NFSLOCKMNT(nmp);
7750                         if ((nmp->nm_privflag & (NFSMNTP_FORCEDISM |
7751                              NFSMNTP_CANCELRPCS)) == 0) {
7752                                 nmp->nm_privflag |= NFSMNTP_CANCELRPCS;
7753                                 NFSUNLOCKMNT(nmp);
7754                         } else {
7755                                 NFSUNLOCKMNT(nmp);
7756                                 nmp = NULL;
7757                         }
7758                         break;
7759                 }
7760         }
7761         mtx_unlock(&mountlist_mtx);
7762
7763         if (nmp != NULL) {
7764                 ds = nfsrv_deldsnmp(op, nmp, p);
7765                 NFSD_DEBUG(4, "deldsnmp=%p\n", ds);
7766                 if (ds != NULL) {
7767                         nfsrv_killrpcs(nmp);
7768                         NFSD_DEBUG(4, "aft killrpcs\n");
7769                 } else
7770                         error = ENXIO;
7771                 NFSLOCKMNT(nmp);
7772                 nmp->nm_privflag &= ~NFSMNTP_CANCELRPCS;
7773                 wakeup(nmp);
7774                 NFSUNLOCKMNT(nmp);
7775         } else
7776                 error = EINVAL;
7777         return (error);
7778 }
7779
7780 /*
7781  * Search for and remove a DS entry which matches the "nmp" argument.
7782  * The nfsdevice structure pointer is returned so that the caller can
7783  * free it via nfsrv_freeonedevid().
7784  * For the forced case, do not try to do LayoutRecalls, since the server
7785  * must be shut down now anyhow.
7786  */
7787 struct nfsdevice *
7788 nfsrv_deldsnmp(int op, struct nfsmount *nmp, NFSPROC_T *p)
7789 {
7790         struct nfsdevice *fndds;
7791
7792         NFSD_DEBUG(4, "deldsdvp\n");
7793         NFSDDSLOCK();
7794         if (op == PNFSDOP_FORCEDELDS)
7795                 fndds = nfsv4_findmirror(nmp);
7796         else
7797                 fndds = nfsrv_findmirroredds(nmp);
7798         if (fndds != NULL)
7799                 nfsrv_deleteds(fndds);
7800         NFSDDSUNLOCK();
7801         if (fndds != NULL) {
7802                 if (op != PNFSDOP_FORCEDELDS)
7803                         nfsrv_flexmirrordel(fndds->nfsdev_deviceid, p);
7804                 printf("pNFS server: mirror %s failed\n", fndds->nfsdev_host);
7805         }
7806         return (fndds);
7807 }
7808
7809 /*
7810  * Similar to nfsrv_deldsnmp(), except that the DS is indicated by deviceid.
7811  * This function also calls nfsrv_killrpcs() to unblock RPCs on the mount
7812  * point.
7813  * Also, returns an error instead of the nfsdevice found.
7814  */
7815 int
7816 nfsrv_delds(char *devid, NFSPROC_T *p)
7817 {
7818         struct nfsdevice *ds, *fndds;
7819         struct nfsmount *nmp;
7820         int fndmirror;
7821
7822         NFSD_DEBUG(4, "delds\n");
7823         /*
7824          * Search the DS server list for a match with devid.
7825          * Remove the DS entry if found and there is a mirror.
7826          */
7827         fndds = NULL;
7828         nmp = NULL;
7829         fndmirror = 0;
7830         NFSDDSLOCK();
7831         TAILQ_FOREACH(ds, &nfsrv_devidhead, nfsdev_list) {
7832                 if (NFSBCMP(ds->nfsdev_deviceid, devid, NFSX_V4DEVICEID) == 0 &&
7833                     ds->nfsdev_nmp != NULL) {
7834                         NFSD_DEBUG(4, "fnd main ds\n");
7835                         fndds = ds;
7836                         break;
7837                 }
7838         }
7839         if (fndds == NULL) {
7840                 NFSDDSUNLOCK();
7841                 return (ENXIO);
7842         }
7843         if (fndds->nfsdev_mdsisset == 0 && nfsrv_faildscnt > 0)
7844                 fndmirror = 1;
7845         else if (fndds->nfsdev_mdsisset != 0) {
7846                 /* For the fsid is set case, search for a mirror. */
7847                 TAILQ_FOREACH(ds, &nfsrv_devidhead, nfsdev_list) {
7848                         if (ds != fndds && ds->nfsdev_nmp != NULL &&
7849                             ds->nfsdev_mdsisset != 0 &&
7850                             fsidcmp(&ds->nfsdev_mdsfsid,
7851                             &fndds->nfsdev_mdsfsid) == 0) {
7852                                 fndmirror = 1;
7853                                 break;
7854                         }
7855                 }
7856         }
7857         if (fndmirror != 0) {
7858                 nmp = fndds->nfsdev_nmp;
7859                 NFSLOCKMNT(nmp);
7860                 if ((nmp->nm_privflag & (NFSMNTP_FORCEDISM |
7861                      NFSMNTP_CANCELRPCS)) == 0) {
7862                         nmp->nm_privflag |= NFSMNTP_CANCELRPCS;
7863                         NFSUNLOCKMNT(nmp);
7864                         nfsrv_deleteds(fndds);
7865                 } else {
7866                         NFSUNLOCKMNT(nmp);
7867                         nmp = NULL;
7868                 }
7869         }
7870         NFSDDSUNLOCK();
7871         if (nmp != NULL) {
7872                 nfsrv_flexmirrordel(fndds->nfsdev_deviceid, p);
7873                 printf("pNFS server: mirror %s failed\n", fndds->nfsdev_host);
7874                 nfsrv_killrpcs(nmp);
7875                 NFSLOCKMNT(nmp);
7876                 nmp->nm_privflag &= ~NFSMNTP_CANCELRPCS;
7877                 wakeup(nmp);
7878                 NFSUNLOCKMNT(nmp);
7879                 return (0);
7880         }
7881         return (ENXIO);
7882 }
7883
7884 /*
7885  * Mark a DS as disabled by setting nfsdev_nmp = NULL.
7886  */
7887 static void
7888 nfsrv_deleteds(struct nfsdevice *fndds)
7889 {
7890
7891         NFSD_DEBUG(4, "deleteds: deleting a mirror\n");
7892         fndds->nfsdev_nmp = NULL;
7893         if (fndds->nfsdev_mdsisset == 0)
7894                 nfsrv_faildscnt--;
7895 }
7896
7897 /*
7898  * Fill in the addr structures for the File and Flex File layouts.
7899  */
7900 static void
7901 nfsrv_allocdevid(struct nfsdevice *ds, char *addr, char *dnshost)
7902 {
7903         uint32_t *tl;
7904         char *netprot;
7905         int addrlen;
7906         static uint64_t new_devid = 0;
7907
7908         if (strchr(addr, ':') != NULL)
7909                 netprot = "tcp6";
7910         else
7911                 netprot = "tcp";
7912
7913         /* Fill in the device id. */
7914         NFSBCOPY(&nfsdev_time, ds->nfsdev_deviceid, sizeof(nfsdev_time));
7915         new_devid++;
7916         NFSBCOPY(&new_devid, &ds->nfsdev_deviceid[sizeof(nfsdev_time)],
7917             sizeof(new_devid));
7918
7919         /*
7920          * Fill in the file addr (actually the nfsv4_file_layout_ds_addr4
7921          * as defined in RFC5661) in XDR.
7922          */
7923         addrlen = NFSM_RNDUP(strlen(addr)) + NFSM_RNDUP(strlen(netprot)) +
7924             6 * NFSX_UNSIGNED;
7925         NFSD_DEBUG(4, "hn=%s addr=%s netprot=%s\n", dnshost, addr, netprot);
7926         ds->nfsdev_fileaddrlen = addrlen;
7927         tl = malloc(addrlen, M_NFSDSTATE, M_WAITOK | M_ZERO);
7928         ds->nfsdev_fileaddr = (char *)tl;
7929         *tl++ = txdr_unsigned(1);               /* One stripe with index 0. */
7930         *tl++ = 0;
7931         *tl++ = txdr_unsigned(1);               /* One multipath list */
7932         *tl++ = txdr_unsigned(1);               /* with one entry in it. */
7933         /* The netaddr for this one entry. */
7934         *tl++ = txdr_unsigned(strlen(netprot));
7935         NFSBCOPY(netprot, tl, strlen(netprot));
7936         tl += (NFSM_RNDUP(strlen(netprot)) / NFSX_UNSIGNED);
7937         *tl++ = txdr_unsigned(strlen(addr));
7938         NFSBCOPY(addr, tl, strlen(addr));
7939
7940         /*
7941          * Fill in the flex file addr (actually the ff_device_addr4
7942          * as defined for Flexible File Layout) in XDR.
7943          */
7944         addrlen = NFSM_RNDUP(strlen(addr)) + NFSM_RNDUP(strlen(netprot)) +
7945             14 * NFSX_UNSIGNED;
7946         ds->nfsdev_flexaddrlen = addrlen;
7947         tl = malloc(addrlen, M_NFSDSTATE, M_WAITOK | M_ZERO);
7948         ds->nfsdev_flexaddr = (char *)tl;
7949         *tl++ = txdr_unsigned(1);               /* One multipath entry. */
7950         /* The netaddr for this one entry. */
7951         *tl++ = txdr_unsigned(strlen(netprot));
7952         NFSBCOPY(netprot, tl, strlen(netprot));
7953         tl += (NFSM_RNDUP(strlen(netprot)) / NFSX_UNSIGNED);
7954         *tl++ = txdr_unsigned(strlen(addr));
7955         NFSBCOPY(addr, tl, strlen(addr));
7956         tl += (NFSM_RNDUP(strlen(addr)) / NFSX_UNSIGNED);
7957         *tl++ = txdr_unsigned(2);               /* Two NFS Versions. */
7958         *tl++ = txdr_unsigned(NFS_VER4);        /* NFSv4. */
7959         *tl++ = txdr_unsigned(NFSV42_MINORVERSION); /* Minor version 2. */
7960         *tl++ = txdr_unsigned(NFS_SRVMAXIO);    /* DS max rsize. */
7961         *tl++ = txdr_unsigned(NFS_SRVMAXIO);    /* DS max wsize. */
7962         *tl++ = newnfs_true;                    /* Tightly coupled. */
7963         *tl++ = txdr_unsigned(NFS_VER4);        /* NFSv4. */
7964         *tl++ = txdr_unsigned(NFSV41_MINORVERSION); /* Minor version 1. */
7965         *tl++ = txdr_unsigned(NFS_SRVMAXIO);    /* DS max rsize. */
7966         *tl++ = txdr_unsigned(NFS_SRVMAXIO);    /* DS max wsize. */
7967         *tl = newnfs_true;                      /* Tightly coupled. */
7968
7969         ds->nfsdev_hostnamelen = strlen(dnshost);
7970         ds->nfsdev_host = malloc(ds->nfsdev_hostnamelen + 1, M_NFSDSTATE,
7971             M_WAITOK);
7972         NFSBCOPY(dnshost, ds->nfsdev_host, ds->nfsdev_hostnamelen + 1);
7973 }
7974
7975 /*
7976  * Create the device id list.
7977  * Return 0 if the nfsd threads are to run and ENXIO if the "-p" argument
7978  * is misconfigured.
7979  */
7980 int
7981 nfsrv_createdevids(struct nfsd_nfsd_args *args, NFSPROC_T *p)
7982 {
7983         struct nfsdevice *ds;
7984         char *addrp, *dnshostp, *dspathp, *mdspathp;
7985         int error, i;
7986
7987         addrp = args->addr;
7988         dnshostp = args->dnshost;
7989         dspathp = args->dspath;
7990         mdspathp = args->mdspath;
7991         nfsrv_maxpnfsmirror = args->mirrorcnt;
7992         if (addrp == NULL || dnshostp == NULL || dspathp == NULL ||
7993             mdspathp == NULL)
7994                 return (0);
7995
7996         /*
7997          * Loop around for each nul-terminated string in args->addr,
7998          * args->dnshost, args->dnspath and args->mdspath.
7999          */
8000         while (addrp < (args->addr + args->addrlen) &&
8001             dnshostp < (args->dnshost + args->dnshostlen) &&
8002             dspathp < (args->dspath + args->dspathlen) &&
8003             mdspathp < (args->mdspath + args->mdspathlen)) {
8004                 error = nfsrv_setdsserver(dspathp, mdspathp, p, &ds);
8005                 if (error != 0) {
8006                         /* Free all DS servers. */
8007                         nfsrv_freealldevids();
8008                         nfsrv_devidcnt = 0;
8009                         return (ENXIO);
8010                 }
8011                 nfsrv_allocdevid(ds, addrp, dnshostp);
8012                 addrp += (strlen(addrp) + 1);
8013                 dnshostp += (strlen(dnshostp) + 1);
8014                 dspathp += (strlen(dspathp) + 1);
8015                 mdspathp += (strlen(mdspathp) + 1);
8016         }
8017         if (nfsrv_devidcnt < nfsrv_maxpnfsmirror) {
8018                 /* Free all DS servers. */
8019                 nfsrv_freealldevids();
8020                 nfsrv_devidcnt = 0;
8021                 nfsrv_maxpnfsmirror = 1;
8022                 return (ENXIO);
8023         }
8024         /* We can fail at most one less DS than the mirror level. */
8025         nfsrv_faildscnt = nfsrv_maxpnfsmirror - 1;
8026
8027         /*
8028          * Allocate the nfslayout hash table now, since this is a pNFS server.
8029          * Make it 1% of the high water mark and at least 100.
8030          */
8031         if (nfslayouthash == NULL) {
8032                 nfsrv_layouthashsize = nfsrv_layouthighwater / 100;
8033                 if (nfsrv_layouthashsize < 100)
8034                         nfsrv_layouthashsize = 100;
8035                 nfslayouthash = mallocarray(nfsrv_layouthashsize,
8036                     sizeof(struct nfslayouthash), M_NFSDSESSION, M_WAITOK |
8037                     M_ZERO);
8038                 for (i = 0; i < nfsrv_layouthashsize; i++) {
8039                         mtx_init(&nfslayouthash[i].mtx, "nfslm", NULL, MTX_DEF);
8040                         TAILQ_INIT(&nfslayouthash[i].list);
8041                 }
8042         }
8043         return (0);
8044 }
8045
8046 /*
8047  * Free all device ids.
8048  */
8049 static void
8050 nfsrv_freealldevids(void)
8051 {
8052         struct nfsdevice *ds, *nds;
8053
8054         TAILQ_FOREACH_SAFE(ds, &nfsrv_devidhead, nfsdev_list, nds)
8055                 nfsrv_freedevid(ds);
8056 }
8057
8058 /*
8059  * Check to see if there is a Read/Write Layout plus either:
8060  * - A Write Delegation
8061  * or
8062  * - An Open with Write_access.
8063  * Return 1 if this is the case and 0 otherwise.
8064  * This function is used by nfsrv_proxyds() to decide if doing a Proxy
8065  * Getattr RPC to the Data Server (DS) is necessary.
8066  */
8067 #define NFSCLIDVECSIZE  6
8068 int
8069 nfsrv_checkdsattr(vnode_t vp, NFSPROC_T *p)
8070 {
8071         fhandle_t fh, *tfhp;
8072         struct nfsstate *stp;
8073         struct nfslayout *lyp;
8074         struct nfslayouthash *lhyp;
8075         struct nfslockhashhead *hp;
8076         struct nfslockfile *lfp;
8077         nfsquad_t clid[NFSCLIDVECSIZE];
8078         int clidcnt, ret;
8079
8080         ret = nfsvno_getfh(vp, &fh, p);
8081         if (ret != 0)
8082                 return (0);
8083
8084         /* First check for a Read/Write Layout. */
8085         clidcnt = 0;
8086         lhyp = NFSLAYOUTHASH(&fh);
8087         NFSLOCKLAYOUT(lhyp);
8088         TAILQ_FOREACH(lyp, &lhyp->list, lay_list) {
8089                 if (NFSBCMP(&lyp->lay_fh, &fh, sizeof(fh)) == 0 &&
8090                     ((lyp->lay_flags & NFSLAY_RW) != 0 ||
8091                      ((lyp->lay_flags & NFSLAY_READ) != 0 &&
8092                       nfsrv_pnfsatime != 0))) {
8093                         if (clidcnt < NFSCLIDVECSIZE)
8094                                 clid[clidcnt].qval = lyp->lay_clientid.qval;
8095                         clidcnt++;
8096                 }
8097         }
8098         NFSUNLOCKLAYOUT(lhyp);
8099         if (clidcnt == 0) {
8100                 /* None found, so return 0. */
8101                 return (0);
8102         }
8103
8104         /* Get the nfslockfile for this fh. */
8105         NFSLOCKSTATE();
8106         hp = NFSLOCKHASH(&fh);
8107         LIST_FOREACH(lfp, hp, lf_hash) {
8108                 tfhp = &lfp->lf_fh;
8109                 if (NFSVNO_CMPFH(&fh, tfhp))
8110                         break;
8111         }
8112         if (lfp == NULL) {
8113                 /* None found, so return 0. */
8114                 NFSUNLOCKSTATE();
8115                 return (0);
8116         }
8117
8118         /* Now, look for a Write delegation for this clientid. */
8119         LIST_FOREACH(stp, &lfp->lf_deleg, ls_file) {
8120                 if ((stp->ls_flags & NFSLCK_DELEGWRITE) != 0 &&
8121                     nfsrv_fndclid(clid, stp->ls_clp->lc_clientid, clidcnt) != 0)
8122                         break;
8123         }
8124         if (stp != NULL) {
8125                 /* Found one, so return 1. */
8126                 NFSUNLOCKSTATE();
8127                 return (1);
8128         }
8129
8130         /* No Write delegation, so look for an Open with Write_access. */
8131         LIST_FOREACH(stp, &lfp->lf_open, ls_file) {
8132                 KASSERT((stp->ls_flags & NFSLCK_OPEN) != 0,
8133                     ("nfsrv_checkdsattr: Non-open in Open list\n"));
8134                 if ((stp->ls_flags & NFSLCK_WRITEACCESS) != 0 &&
8135                     nfsrv_fndclid(clid, stp->ls_clp->lc_clientid, clidcnt) != 0)
8136                         break;
8137         }
8138         NFSUNLOCKSTATE();
8139         if (stp != NULL)
8140                 return (1);
8141         return (0);
8142 }
8143
8144 /*
8145  * Look for a matching clientid in the vector. Return 1 if one might match.
8146  */
8147 static int
8148 nfsrv_fndclid(nfsquad_t *clidvec, nfsquad_t clid, int clidcnt)
8149 {
8150         int i;
8151
8152         /* If too many for the vector, return 1 since there might be a match. */
8153         if (clidcnt > NFSCLIDVECSIZE)
8154                 return (1);
8155
8156         for (i = 0; i < clidcnt; i++)
8157                 if (clidvec[i].qval == clid.qval)
8158                         return (1);
8159         return (0);
8160 }
8161
8162 /*
8163  * Check the don't list for "vp" and see if issuing an rw layout is allowed.
8164  * Return 1 if issuing an rw layout isn't allowed, 0 otherwise.
8165  */
8166 static int
8167 nfsrv_dontlayout(fhandle_t *fhp)
8168 {
8169         struct nfsdontlist *mrp;
8170         int ret;
8171
8172         if (nfsrv_dontlistlen == 0)
8173                 return (0);
8174         ret = 0;
8175         NFSDDONTLISTLOCK();
8176         LIST_FOREACH(mrp, &nfsrv_dontlisthead, nfsmr_list) {
8177                 if (NFSBCMP(fhp, &mrp->nfsmr_fh, sizeof(*fhp)) == 0 &&
8178                     (mrp->nfsmr_flags & NFSMR_DONTLAYOUT) != 0) {
8179                         ret = 1;
8180                         break;
8181                 }
8182         }
8183         NFSDDONTLISTUNLOCK();
8184         return (ret);
8185 }
8186
8187 #define PNFSDS_COPYSIZ  65536
8188 /*
8189  * Create a new file on a DS and copy the contents of an extant DS file to it.
8190  * This can be used for recovery of a DS file onto a recovered DS.
8191  * The steps are:
8192  * - When called, the MDS file's vnode is locked, blocking LayoutGet operations.
8193  * - Disable issuing of read/write layouts for the file via the nfsdontlist,
8194  *   so that they will be disabled after the MDS file's vnode is unlocked.
8195  * - Set up the nfsrv_recalllist so that recall of read/write layouts can
8196  *   be done.
8197  * - Unlock the MDS file's vnode, so that the client(s) can perform proxied
8198  *   writes, LayoutCommits and LayoutReturns for the file when completing the
8199  *   LayoutReturn requested by the LayoutRecall callback.
8200  * - Issue a LayoutRecall callback for all read/write layouts and wait for
8201  *   them to be returned. (If the LayoutRecall callback replies
8202  *   NFSERR_NOMATCHLAYOUT, they are gone and no LayoutReturn is needed.)
8203  * - Exclusively lock the MDS file's vnode.  This ensures that no proxied
8204  *   writes are in progress or can occur during the DS file copy.
8205  *   It also blocks Setattr operations.
8206  * - Create the file on the recovered mirror.
8207  * - Copy the file from the operational DS.
8208  * - Copy any ACL from the MDS file to the new DS file.
8209  * - Set the modify time of the new DS file to that of the MDS file.
8210  * - Update the extended attribute for the MDS file.
8211  * - Enable issuing of rw layouts by deleting the nfsdontlist entry.
8212  * - The caller will unlock the MDS file's vnode allowing operations
8213  *   to continue normally, since it is now on the mirror again.
8214  */
8215 int
8216 nfsrv_copymr(vnode_t vp, vnode_t fvp, vnode_t dvp, struct nfsdevice *ds,
8217     struct pnfsdsfile *pf, struct pnfsdsfile *wpf, int mirrorcnt,
8218     struct ucred *cred, NFSPROC_T *p)
8219 {
8220         struct nfsdontlist *mrp, *nmrp;
8221         struct nfslayouthash *lhyp;
8222         struct nfslayout *lyp, *nlyp;
8223         struct nfslayouthead thl;
8224         struct mount *mp, *tvmp;
8225         struct acl *aclp;
8226         struct vattr va;
8227         struct timespec mtime;
8228         fhandle_t fh;
8229         vnode_t tvp;
8230         off_t rdpos, wrpos;
8231         ssize_t aresid;
8232         char *dat;
8233         int didprintf, ret, retacl, xfer;
8234
8235         ASSERT_VOP_LOCKED(fvp, "nfsrv_copymr fvp");
8236         ASSERT_VOP_LOCKED(vp, "nfsrv_copymr vp");
8237         /*
8238          * Allocate a nfsdontlist entry and set the NFSMR_DONTLAYOUT flag
8239          * so that no more RW layouts will get issued.
8240          */
8241         ret = nfsvno_getfh(vp, &fh, p);
8242         if (ret != 0) {
8243                 NFSD_DEBUG(4, "nfsrv_copymr: getfh=%d\n", ret);
8244                 return (ret);
8245         }
8246         nmrp = malloc(sizeof(*nmrp), M_NFSDSTATE, M_WAITOK);
8247         nmrp->nfsmr_flags = NFSMR_DONTLAYOUT;
8248         NFSBCOPY(&fh, &nmrp->nfsmr_fh, sizeof(fh));
8249         NFSDDONTLISTLOCK();
8250         LIST_FOREACH(mrp, &nfsrv_dontlisthead, nfsmr_list) {
8251                 if (NFSBCMP(&fh, &mrp->nfsmr_fh, sizeof(fh)) == 0)
8252                         break;
8253         }
8254         if (mrp == NULL) {
8255                 LIST_INSERT_HEAD(&nfsrv_dontlisthead, nmrp, nfsmr_list);
8256                 mrp = nmrp;
8257                 nmrp = NULL;
8258                 nfsrv_dontlistlen++;
8259                 NFSD_DEBUG(4, "nfsrv_copymr: in dontlist\n");
8260         } else {
8261                 NFSDDONTLISTUNLOCK();
8262                 free(nmrp, M_NFSDSTATE);
8263                 NFSD_DEBUG(4, "nfsrv_copymr: dup dontlist\n");
8264                 return (ENXIO);
8265         }
8266         NFSDDONTLISTUNLOCK();
8267
8268         /*
8269          * Search for all RW layouts for this file.  Move them to the
8270          * recall list, so they can be recalled and their return noted.
8271          */
8272         lhyp = NFSLAYOUTHASH(&fh);
8273         NFSDRECALLLOCK();
8274         NFSLOCKLAYOUT(lhyp);
8275         TAILQ_FOREACH_SAFE(lyp, &lhyp->list, lay_list, nlyp) {
8276                 if (NFSBCMP(&lyp->lay_fh, &fh, sizeof(fh)) == 0 &&
8277                     (lyp->lay_flags & NFSLAY_RW) != 0) {
8278                         TAILQ_REMOVE(&lhyp->list, lyp, lay_list);
8279                         TAILQ_INSERT_HEAD(&nfsrv_recalllisthead, lyp, lay_list);
8280                         lyp->lay_trycnt = 0;
8281                 }
8282         }
8283         NFSUNLOCKLAYOUT(lhyp);
8284         NFSDRECALLUNLOCK();
8285
8286         ret = 0;
8287         mp = tvmp = NULL;
8288         didprintf = 0;
8289         TAILQ_INIT(&thl);
8290         /* Unlock the MDS vp, so that a LayoutReturn can be done on it. */
8291         NFSVOPUNLOCK(vp);
8292         /* Now, do a recall for all layouts not yet recalled. */
8293 tryagain:
8294         NFSDRECALLLOCK();
8295         TAILQ_FOREACH(lyp, &nfsrv_recalllisthead, lay_list) {
8296                 if (NFSBCMP(&lyp->lay_fh, &fh, sizeof(fh)) == 0 &&
8297                     (lyp->lay_flags & NFSLAY_RECALL) == 0) {
8298                         lyp->lay_flags |= NFSLAY_RECALL;
8299                         /*
8300                          * The layout stateid.seqid needs to be incremented
8301                          * before doing a LAYOUT_RECALL callback.
8302                          */
8303                         if (++lyp->lay_stateid.seqid == 0)
8304                                 lyp->lay_stateid.seqid = 1;
8305                         NFSDRECALLUNLOCK();
8306                         nfsrv_recalllayout(lyp->lay_clientid, &lyp->lay_stateid,
8307                             &lyp->lay_fh, lyp, 0, lyp->lay_type, p);
8308                         NFSD_DEBUG(4, "nfsrv_copymr: recalled layout\n");
8309                         goto tryagain;
8310                 }
8311         }
8312
8313         /* Now wait for them to be returned. */
8314 tryagain2:
8315         TAILQ_FOREACH(lyp, &nfsrv_recalllisthead, lay_list) {
8316                 if (NFSBCMP(&lyp->lay_fh, &fh, sizeof(fh)) == 0) {
8317                         if ((lyp->lay_flags & NFSLAY_RETURNED) != 0) {
8318                                 TAILQ_REMOVE(&nfsrv_recalllisthead, lyp,
8319                                     lay_list);
8320                                 TAILQ_INSERT_HEAD(&thl, lyp, lay_list);
8321                                 NFSD_DEBUG(4,
8322                                     "nfsrv_copymr: layout returned\n");
8323                         } else {
8324                                 lyp->lay_trycnt++;
8325                                 ret = mtx_sleep(lyp, NFSDRECALLMUTEXPTR,
8326                                     PVFS | PCATCH, "nfsmrl", hz);
8327                                 NFSD_DEBUG(4, "nfsrv_copymr: aft sleep=%d\n",
8328                                     ret);
8329                                 if (ret == EINTR || ret == ERESTART)
8330                                         break;
8331                                 if ((lyp->lay_flags & NFSLAY_RETURNED) == 0) {
8332                                         /*
8333                                          * Give up after 60sec and return
8334                                          * ENXIO, failing the copymr.
8335                                          * This layout will remain on the
8336                                          * recalllist.  It can only be cleared
8337                                          * by restarting the nfsd.
8338                                          * This seems the safe way to handle
8339                                          * it, since it cannot be safely copied
8340                                          * with an outstanding RW layout.
8341                                          */
8342                                         if (lyp->lay_trycnt >= 60) {
8343                                                 ret = ENXIO;
8344                                                 break;
8345                                         }
8346                                         if (didprintf == 0) {
8347                                                 printf("nfsrv_copymr: layout "
8348                                                     "not returned\n");
8349                                                 didprintf = 1;
8350                                         }
8351                                 }
8352                         }
8353                         goto tryagain2;
8354                 }
8355         }
8356         NFSDRECALLUNLOCK();
8357         /* We can now get rid of the layouts that have been returned. */
8358         TAILQ_FOREACH_SAFE(lyp, &thl, lay_list, nlyp)
8359                 nfsrv_freelayout(&thl, lyp);
8360
8361         /*
8362          * Do the vn_start_write() calls here, before the MDS vnode is
8363          * locked and the tvp is created (locked) in the NFS file system
8364          * that dvp is in.
8365          * For tvmp, this probably isn't necessary, since it will be an
8366          * NFS mount and they are not suspendable at this time.
8367          */
8368         if (ret == 0)
8369                 ret = vn_start_write(vp, &mp, V_WAIT | PCATCH);
8370         if (ret == 0) {
8371                 tvmp = dvp->v_mount;
8372                 ret = vn_start_write(NULL, &tvmp, V_WAIT | PCATCH);
8373         }
8374
8375         /*
8376          * LK_EXCLUSIVE lock the MDS vnode, so that any
8377          * proxied writes through the MDS will be blocked until we have
8378          * completed the copy and update of the extended attributes.
8379          * This will also ensure that any attributes and ACL will not be
8380          * changed until the copy is complete.
8381          */
8382         NFSVOPLOCK(vp, LK_EXCLUSIVE | LK_RETRY);
8383         if (ret == 0 && VN_IS_DOOMED(vp)) {
8384                 NFSD_DEBUG(4, "nfsrv_copymr: lk_exclusive doomed\n");
8385                 ret = ESTALE;
8386         }
8387
8388         /* Create the data file on the recovered DS. */
8389         if (ret == 0)
8390                 ret = nfsrv_createdsfile(vp, &fh, pf, dvp, ds, cred, p, &tvp);
8391
8392         /* Copy the DS file, if created successfully. */
8393         if (ret == 0) {
8394                 /*
8395                  * Get any NFSv4 ACL on the MDS file, so that it can be set
8396                  * on the new DS file.
8397                  */
8398                 aclp = acl_alloc(M_WAITOK | M_ZERO);
8399                 retacl = VOP_GETACL(vp, ACL_TYPE_NFS4, aclp, cred, p);
8400                 if (retacl != 0 && retacl != ENOATTR)
8401                         NFSD_DEBUG(1, "nfsrv_copymr: vop_getacl=%d\n", retacl);
8402                 dat = malloc(PNFSDS_COPYSIZ, M_TEMP, M_WAITOK);
8403                 /* Malloc a block of 0s used to check for holes. */
8404                 if (nfsrv_zeropnfsdat == NULL)
8405                         nfsrv_zeropnfsdat = malloc(PNFSDS_COPYSIZ, M_TEMP,
8406                             M_WAITOK | M_ZERO);
8407                 rdpos = wrpos = 0;
8408                 ret = VOP_GETATTR(fvp, &va, cred);
8409                 aresid = 0;
8410                 while (ret == 0 && aresid == 0) {
8411                         ret = vn_rdwr(UIO_READ, fvp, dat, PNFSDS_COPYSIZ,
8412                             rdpos, UIO_SYSSPACE, IO_NODELOCKED, cred, NULL,
8413                             &aresid, p);
8414                         xfer = PNFSDS_COPYSIZ - aresid;
8415                         if (ret == 0 && xfer > 0) {
8416                                 rdpos += xfer;
8417                                 /*
8418                                  * Skip the write for holes, except for the
8419                                  * last block.
8420                                  */
8421                                 if (xfer < PNFSDS_COPYSIZ || rdpos ==
8422                                     va.va_size || NFSBCMP(dat,
8423                                     nfsrv_zeropnfsdat, PNFSDS_COPYSIZ) != 0)
8424                                         ret = vn_rdwr(UIO_WRITE, tvp, dat, xfer,
8425                                             wrpos, UIO_SYSSPACE, IO_NODELOCKED,
8426                                             cred, NULL, NULL, p);
8427                                 if (ret == 0)
8428                                         wrpos += xfer;
8429                         }
8430                 }
8431
8432                 /* If there is an ACL and the copy succeeded, set the ACL. */
8433                 if (ret == 0 && retacl == 0) {
8434                         ret = VOP_SETACL(tvp, ACL_TYPE_NFS4, aclp, cred, p);
8435                         /*
8436                          * Don't consider these as errors, since VOP_GETACL()
8437                          * can return an ACL when they are not actually
8438                          * supported.  For example, for UFS, VOP_GETACL()
8439                          * will return a trivial ACL based on the uid/gid/mode
8440                          * when there is no ACL on the file.
8441                          * This case should be recognized as a trivial ACL
8442                          * by UFS's VOP_SETACL() and succeed, but...
8443                          */
8444                         if (ret == ENOATTR || ret == EOPNOTSUPP || ret == EPERM)
8445                                 ret = 0;
8446                 }
8447
8448                 if (ret == 0)
8449                         ret = VOP_FSYNC(tvp, MNT_WAIT, p);
8450
8451                 /* Set the DS data file's modify time that of the MDS file. */
8452                 if (ret == 0)
8453                         ret = VOP_GETATTR(vp, &va, cred);
8454                 if (ret == 0) {
8455                         mtime = va.va_mtime;
8456                         VATTR_NULL(&va);
8457                         va.va_mtime = mtime;
8458                         ret = VOP_SETATTR(tvp, &va, cred);
8459                 }
8460
8461                 vput(tvp);
8462                 acl_free(aclp);
8463                 free(dat, M_TEMP);
8464         }
8465         if (tvmp != NULL)
8466                 vn_finished_write(tvmp);
8467
8468         /* Update the extended attributes for the newly created DS file. */
8469         if (ret == 0)
8470                 ret = vn_extattr_set(vp, IO_NODELOCKED,
8471                     EXTATTR_NAMESPACE_SYSTEM, "pnfsd.dsfile",
8472                     sizeof(*wpf) * mirrorcnt, (char *)wpf, p);
8473         if (mp != NULL)
8474                 vn_finished_write(mp);
8475
8476         /* Get rid of the dontlist entry, so that Layouts can be issued. */
8477         NFSDDONTLISTLOCK();
8478         LIST_REMOVE(mrp, nfsmr_list);
8479         NFSDDONTLISTUNLOCK();
8480         free(mrp, M_NFSDSTATE);
8481         return (ret);
8482 }
8483
8484 /*
8485  * Create a data storage file on the recovered DS.
8486  */
8487 static int
8488 nfsrv_createdsfile(vnode_t vp, fhandle_t *fhp, struct pnfsdsfile *pf,
8489     vnode_t dvp, struct nfsdevice *ds, struct ucred *cred, NFSPROC_T *p,
8490     vnode_t *tvpp)
8491 {
8492         struct vattr va, nva;
8493         int error;
8494
8495         /* Make data file name based on FH. */
8496         error = VOP_GETATTR(vp, &va, cred);
8497         if (error == 0) {
8498                 /* Set the attributes for "vp" to Setattr the DS vp. */
8499                 VATTR_NULL(&nva);
8500                 nva.va_uid = va.va_uid;
8501                 nva.va_gid = va.va_gid;
8502                 nva.va_mode = va.va_mode;
8503                 nva.va_size = 0;
8504                 VATTR_NULL(&va);
8505                 va.va_type = VREG;
8506                 va.va_mode = nva.va_mode;
8507                 NFSD_DEBUG(4, "nfsrv_dscreatefile: dvp=%p pf=%p\n", dvp, pf);
8508                 error = nfsrv_dscreate(dvp, &va, &nva, fhp, pf, NULL,
8509                     pf->dsf_filename, cred, p, tvpp);
8510         }
8511         return (error);
8512 }
8513
8514 /*
8515  * Look up the MDS file shared locked, and then get the extended attribute
8516  * to find the extant DS file to be copied to the new mirror.
8517  * If successful, *vpp is set to the MDS file's vp and *nvpp is
8518  * set to a DS data file for the MDS file, both exclusively locked.
8519  * The "buf" argument has the pnfsdsfile structure from the MDS file
8520  * in it and buflen is set to its length.
8521  */
8522 int
8523 nfsrv_mdscopymr(char *mdspathp, char *dspathp, char *curdspathp, char *buf,
8524     int *buflenp, char *fname, NFSPROC_T *p, struct vnode **vpp,
8525     struct vnode **nvpp, struct pnfsdsfile **pfp, struct nfsdevice **dsp,
8526     struct nfsdevice **fdsp)
8527 {
8528         struct nameidata nd;
8529         struct vnode *vp, *curvp;
8530         struct pnfsdsfile *pf;
8531         struct nfsmount *nmp, *curnmp;
8532         int dsdir, error, mirrorcnt, ippos;
8533
8534         vp = NULL;
8535         curvp = NULL;
8536         curnmp = NULL;
8537         *dsp = NULL;
8538         *fdsp = NULL;
8539         if (dspathp == NULL && curdspathp != NULL)
8540                 return (EPERM);
8541
8542         /*
8543          * Look up the MDS file shared locked.  The lock will be upgraded
8544          * to an exclusive lock after any rw layouts have been returned.
8545          */
8546         NFSD_DEBUG(4, "mdsopen path=%s\n", mdspathp);
8547         NDINIT(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF, UIO_SYSSPACE,
8548             mdspathp, p);
8549         error = namei(&nd);
8550         NFSD_DEBUG(4, "lookup=%d\n", error);
8551         if (error != 0)
8552                 return (error);
8553         if (nd.ni_vp->v_type != VREG) {
8554                 vput(nd.ni_vp);
8555                 NFSD_DEBUG(4, "mdspath not reg\n");
8556                 return (EISDIR);
8557         }
8558         vp = nd.ni_vp;
8559
8560         if (curdspathp != NULL) {
8561                 /*
8562                  * Look up the current DS path and find the nfsdev structure for
8563                  * it.
8564                  */
8565                 NFSD_DEBUG(4, "curmdsdev path=%s\n", curdspathp);
8566                 NDINIT(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF,
8567                     UIO_SYSSPACE, curdspathp, p);
8568                 error = namei(&nd);
8569                 NFSD_DEBUG(4, "ds lookup=%d\n", error);
8570                 if (error != 0) {
8571                         vput(vp);
8572                         return (error);
8573                 }
8574                 if (nd.ni_vp->v_type != VDIR) {
8575                         vput(nd.ni_vp);
8576                         vput(vp);
8577                         NFSD_DEBUG(4, "curdspath not dir\n");
8578                         return (ENOTDIR);
8579                 }
8580                 if (strcmp(nd.ni_vp->v_mount->mnt_vfc->vfc_name, "nfs") != 0) {
8581                         vput(nd.ni_vp);
8582                         vput(vp);
8583                         NFSD_DEBUG(4, "curdspath not an NFS mount\n");
8584                         return (ENXIO);
8585                 }
8586                 curnmp = VFSTONFS(nd.ni_vp->v_mount);
8587
8588                 /* Search the nfsdev list for a match. */
8589                 NFSDDSLOCK();
8590                 *fdsp = nfsv4_findmirror(curnmp);
8591                 NFSDDSUNLOCK();
8592                 if (*fdsp == NULL)
8593                         curnmp = NULL;
8594                 if (curnmp == NULL) {
8595                         vput(nd.ni_vp);
8596                         vput(vp);
8597                         NFSD_DEBUG(4, "mdscopymr: no current ds\n");
8598                         return (ENXIO);
8599                 }
8600                 curvp = nd.ni_vp;
8601         }
8602
8603         if (dspathp != NULL) {
8604                 /* Look up the nfsdev path and find the nfsdev structure. */
8605                 NFSD_DEBUG(4, "mdsdev path=%s\n", dspathp);
8606                 NDINIT(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF,
8607                     UIO_SYSSPACE, dspathp, p);
8608                 error = namei(&nd);
8609                 NFSD_DEBUG(4, "ds lookup=%d\n", error);
8610                 if (error != 0) {
8611                         vput(vp);
8612                         if (curvp != NULL)
8613                                 vput(curvp);
8614                         return (error);
8615                 }
8616                 if (nd.ni_vp->v_type != VDIR || nd.ni_vp == curvp) {
8617                         vput(nd.ni_vp);
8618                         vput(vp);
8619                         if (curvp != NULL)
8620                                 vput(curvp);
8621                         NFSD_DEBUG(4, "dspath not dir\n");
8622                         if (nd.ni_vp == curvp)
8623                                 return (EPERM);
8624                         return (ENOTDIR);
8625                 }
8626                 if (strcmp(nd.ni_vp->v_mount->mnt_vfc->vfc_name, "nfs") != 0) {
8627                         vput(nd.ni_vp);
8628                         vput(vp);
8629                         if (curvp != NULL)
8630                                 vput(curvp);
8631                         NFSD_DEBUG(4, "dspath not an NFS mount\n");
8632                         return (ENXIO);
8633                 }
8634                 nmp = VFSTONFS(nd.ni_vp->v_mount);
8635
8636                 /*
8637                  * Search the nfsdevice list for a match.  If curnmp == NULL,
8638                  * this is a recovery and there must be a mirror.
8639                  */
8640                 NFSDDSLOCK();
8641                 if (curnmp == NULL)
8642                         *dsp = nfsrv_findmirroredds(nmp);
8643                 else
8644                         *dsp = nfsv4_findmirror(nmp);
8645                 NFSDDSUNLOCK();
8646                 if (*dsp == NULL) {
8647                         vput(nd.ni_vp);
8648                         vput(vp);
8649                         if (curvp != NULL)
8650                                 vput(curvp);
8651                         NFSD_DEBUG(4, "mdscopymr: no ds\n");
8652                         return (ENXIO);
8653                 }
8654         } else {
8655                 nd.ni_vp = NULL;
8656                 nmp = NULL;
8657         }
8658
8659         /*
8660          * Get a vp for an available DS data file using the extended
8661          * attribute on the MDS file.
8662          * If there is a valid entry for the new DS in the extended attribute
8663          * on the MDS file (as checked via the nmp argument),
8664          * nfsrv_dsgetsockmnt() returns EEXIST, so no copying will occur.
8665          */
8666         error = nfsrv_dsgetsockmnt(vp, 0, buf, buflenp, &mirrorcnt, p,
8667             NULL, NULL, NULL, fname, nvpp, &nmp, curnmp, &ippos, &dsdir);
8668         if (curvp != NULL)
8669                 vput(curvp);
8670         if (nd.ni_vp == NULL) {
8671                 if (error == 0 && nmp != NULL) {
8672                         /* Search the nfsdev list for a match. */
8673                         NFSDDSLOCK();
8674                         *dsp = nfsrv_findmirroredds(nmp);
8675                         NFSDDSUNLOCK();
8676                 }
8677                 if (error == 0 && (nmp == NULL || *dsp == NULL)) {
8678                         if (nvpp != NULL && *nvpp != NULL) {
8679                                 vput(*nvpp);
8680                                 *nvpp = NULL;
8681                         }
8682                         error = ENXIO;
8683                 }
8684         } else
8685                 vput(nd.ni_vp);
8686
8687         /*
8688          * When dspathp != NULL and curdspathp == NULL, this is a recovery
8689          * and is only allowed if there is a 0.0.0.0 IP address entry.
8690          * When curdspathp != NULL, the ippos will be set to that entry.
8691          */
8692         if (error == 0 && dspathp != NULL && ippos == -1) {
8693                 if (nvpp != NULL && *nvpp != NULL) {
8694                         vput(*nvpp);
8695                         *nvpp = NULL;
8696                 }
8697                 error = ENXIO;
8698         }
8699         if (error == 0) {
8700                 *vpp = vp;
8701
8702                 pf = (struct pnfsdsfile *)buf;
8703                 if (ippos == -1) {
8704                         /* If no zeroip pnfsdsfile, add one. */
8705                         ippos = *buflenp / sizeof(*pf);
8706                         *buflenp += sizeof(*pf);
8707                         pf += ippos;
8708                         pf->dsf_dir = dsdir;
8709                         strlcpy(pf->dsf_filename, fname,
8710                             sizeof(pf->dsf_filename));
8711                 } else
8712                         pf += ippos;
8713                 *pfp = pf;
8714         } else
8715                 vput(vp);
8716         return (error);
8717 }
8718
8719 /*
8720  * Search for a matching pnfsd mirror device structure, base on the nmp arg.
8721  * Return one if found, NULL otherwise.
8722  */
8723 static struct nfsdevice *
8724 nfsrv_findmirroredds(struct nfsmount *nmp)
8725 {
8726         struct nfsdevice *ds, *fndds;
8727         int fndmirror;
8728
8729         mtx_assert(NFSDDSMUTEXPTR, MA_OWNED);
8730         /*
8731          * Search the DS server list for a match with nmp.
8732          * Remove the DS entry if found and there is a mirror.
8733          */
8734         fndds = NULL;
8735         fndmirror = 0;
8736         if (nfsrv_devidcnt == 0)
8737                 return (fndds);
8738         TAILQ_FOREACH(ds, &nfsrv_devidhead, nfsdev_list) {
8739                 if (ds->nfsdev_nmp == nmp) {
8740                         NFSD_DEBUG(4, "nfsrv_findmirroredds: fnd main ds\n");
8741                         fndds = ds;
8742                         break;
8743                 }
8744         }
8745         if (fndds == NULL)
8746                 return (fndds);
8747         if (fndds->nfsdev_mdsisset == 0 && nfsrv_faildscnt > 0)
8748                 fndmirror = 1;
8749         else if (fndds->nfsdev_mdsisset != 0) {
8750                 /* For the fsid is set case, search for a mirror. */
8751                 TAILQ_FOREACH(ds, &nfsrv_devidhead, nfsdev_list) {
8752                         if (ds != fndds && ds->nfsdev_nmp != NULL &&
8753                             ds->nfsdev_mdsisset != 0 &&
8754                             fsidcmp(&ds->nfsdev_mdsfsid,
8755                             &fndds->nfsdev_mdsfsid) == 0) {
8756                                 fndmirror = 1;
8757                                 break;
8758                         }
8759                 }
8760         }
8761         if (fndmirror == 0) {
8762                 NFSD_DEBUG(4, "nfsrv_findmirroredds: no mirror for DS\n");
8763                 return (NULL);
8764         }
8765         return (fndds);
8766 }