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