The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/fs/nfsserver/nfs_nfsdstate.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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