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/nfs4client/nfs4_vfsops.c

Version: -  FREEBSD  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-2  -  FREEBSD-11-1  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-4  -  FREEBSD-10-3  -  FREEBSD-10-2  -  FREEBSD-10-1  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-3  -  FREEBSD-9-2  -  FREEBSD-9-1  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-4  -  FREEBSD-8-3  -  FREEBSD-8-2  -  FREEBSD-8-1  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-4  -  FREEBSD-7-3  -  FREEBSD-7-2  -  FREEBSD-7-1  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-4  -  FREEBSD-6-3  -  FREEBSD-6-2  -  FREEBSD-6-1  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-5  -  FREEBSD-5-4  -  FREEBSD-5-3  -  FREEBSD-5-2  -  FREEBSD-5-1  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
SearchContext: -  none  -  3  -  10 

    1 /* $FreeBSD$ */
    2 /* $Id: nfs_vfsops.c,v 1.38 2003/11/05 14:59:01 rees Exp $ */
    3 
    4 /*-
    5  * copyright (c) 2003
    6  * the regents of the university of michigan
    7  * all rights reserved
    8  * 
    9  * permission is granted to use, copy, create derivative works and redistribute
   10  * this software and such derivative works for any purpose, so long as the name
   11  * of the university of michigan is not used in any advertising or publicity
   12  * pertaining to the use or distribution of this software without specific,
   13  * written prior authorization.  if the above copyright notice or any other
   14  * identification of the university of michigan is included in any copy of any
   15  * portion of this software, then the disclaimer below must also be included.
   16  * 
   17  * this software is provided as is, without representation from the university
   18  * of michigan as to its fitness for any purpose, and without warranty by the
   19  * university of michigan of any kind, either express or implied, including
   20  * without limitation the implied warranties of merchantability and fitness for
   21  * a particular purpose. the regents of the university of michigan shall not be
   22  * liable for any damages, including special, indirect, incidental, or
   23  * consequential damages, with respect to any claim arising out of or in
   24  * connection with the use of the software, even if it has been or is hereafter
   25  * advised of the possibility of such damages.
   26  */
   27 
   28 /*-
   29  * Copyright (c) 1989, 1993, 1995
   30  *      The Regents of the University of California.  All rights reserved.
   31  *
   32  * This code is derived from software contributed to Berkeley by
   33  * Rick Macklem at The University of Guelph.
   34  *
   35  * Redistribution and use in source and binary forms, with or without
   36  * modification, are permitted provided that the following conditions
   37  * are met:
   38  * 1. Redistributions of source code must retain the above copyright
   39  *    notice, this list of conditions and the following disclaimer.
   40  * 2. Redistributions in binary form must reproduce the above copyright
   41  *    notice, this list of conditions and the following disclaimer in the
   42  *    documentation and/or other materials provided with the distribution.
   43  * 4. Neither the name of the University nor the names of its contributors
   44  *    may be used to endorse or promote products derived from this software
   45  *    without specific prior written permission.
   46  *
   47  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   48  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   49  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   50  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   51  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   52  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   53  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   54  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   55  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   56  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   57  * SUCH DAMAGE.
   58  *
   59  *      @(#)nfs_vfsops.c        8.12 (Berkeley) 5/20/95
   60  */
   61 
   62 #include <sys/cdefs.h>
   63 __FBSDID("$FreeBSD$");
   64 
   65 #include "opt_bootp.h"
   66 #include "opt_nfsroot.h"
   67 
   68 #include <sys/param.h>
   69 #include <sys/systm.h>
   70 #include <sys/kernel.h>
   71 #include <sys/kthread.h>
   72 #include <sys/limits.h>
   73 #include <sys/lock.h>
   74 #include <sys/malloc.h>
   75 #include <sys/mbuf.h>
   76 #include <sys/module.h>
   77 #include <sys/mount.h>
   78 #include <sys/proc.h>
   79 #include <sys/socket.h>
   80 #include <sys/socketvar.h>
   81 #include <sys/sockio.h>
   82 #include <sys/sysctl.h>
   83 #include <sys/unistd.h>
   84 #include <sys/vnode.h>
   85 
   86 #include <vm/vm.h>
   87 #include <vm/vm_extern.h>
   88 #include <vm/uma.h>
   89 
   90 #include <net/if.h>
   91 #include <net/route.h>
   92 #include <netinet/in.h>
   93 #include <netinet/in_var.h>
   94 
   95 #include <rpc/rpcclnt.h>
   96 
   97 #include <nfs/rpcv2.h>
   98 #include <nfs/nfsproto.h>
   99 #include <nfsclient/nfs.h>
  100 #include <nfs4client/nfs4.h>
  101 #include <nfsclient/nfsnode.h>
  102 #include <nfsclient/nfsmount.h>
  103 #include <nfs/xdr_subs.h>
  104 #include <nfsclient/nfsm_subs.h>
  105 #include <nfsclient/nfsdiskless.h>
  106 
  107 #include <nfs4client/nfs4m_subs.h>
  108 #include <nfs4client/nfs4_vfs.h>
  109 
  110 #include <nfs4client/nfs4_dev.h>
  111 #include <nfs4client/nfs4_idmap.h>
  112 
  113 SYSCTL_NODE(_vfs, OID_AUTO, nfs4, CTLFLAG_RW, 0, "NFS4 filesystem");
  114 SYSCTL_STRUCT(_vfs_nfs4, NFS_NFSSTATS, nfsstats, CTLFLAG_RD,
  115         &nfsstats, nfsstats, "S,nfsstats");
  116 
  117 static void     nfs_decode_args(struct nfsmount *nmp, struct nfs_args *argp);
  118 static void     nfs4_daemon(void *arg);
  119 static int      mountnfs(struct nfs_args *, struct mount *,
  120                     struct sockaddr *, char *, char *, struct vnode **,
  121                     struct ucred *cred);
  122 static int      nfs4_do_setclientid(struct nfsmount *nmp, struct ucred *cred);
  123 static vfs_omount_t nfs_omount;
  124 static vfs_unmount_t nfs_unmount;
  125 static vfs_root_t nfs_root;
  126 static vfs_statfs_t nfs_statfs;
  127 static vfs_sync_t nfs_sync;
  128 
  129 /*
  130  * nfs vfs operations.
  131  */
  132 static struct vfsops nfs_vfsops = {
  133         .vfs_init =             nfs4_init,
  134         .vfs_omount =           nfs_omount,
  135         .vfs_root =             nfs_root,
  136         .vfs_statfs =           nfs_statfs,
  137         .vfs_sync =             nfs_sync,
  138         .vfs_uninit =           nfs4_uninit,
  139         .vfs_unmount =          nfs_unmount,
  140 };
  141 VFS_SET(nfs_vfsops, nfs4, VFCF_NETWORK);
  142 
  143 static struct nfs_rpcops nfs4_rpcops = {
  144         nfs4_readrpc,
  145         nfs4_writerpc,
  146         nfs4_writebp,
  147         nfs4_readlinkrpc,
  148         nfs4_invaldir,
  149         nfs4_commit,
  150 };
  151 
  152 /* So that loader and kldload(2) can find us, wherever we are.. */
  153 MODULE_VERSION(nfs4, 1);
  154 
  155 void            nfsargs_ntoh(struct nfs_args *);
  156 
  157 int
  158 nfs4_init(struct vfsconf *vfsp)
  159 {
  160 
  161         rpcclnt_init();
  162         nfs4dev_init();
  163         idmap_init();
  164         nfsm_v4init();
  165 
  166         return (0);
  167 }
  168 
  169 int
  170 nfs4_uninit(struct vfsconf *vfsp)
  171 {
  172 
  173         rpcclnt_uninit();
  174         nfs4dev_uninit();
  175         idmap_uninit();
  176 
  177         return (0);
  178 }
  179 
  180 /*
  181  * nfs statfs call
  182  */
  183 static int
  184 nfs_statfs(struct mount *mp, struct statfs *sbp, struct thread *td)
  185 {
  186         struct vnode *vp;
  187         struct nfs_statfs *sfp;
  188         caddr_t bpos, dpos;
  189         struct nfsmount *nmp = VFSTONFS(mp);
  190         int error = 0;
  191         struct mbuf *mreq, *mrep = NULL, *md, *mb;
  192         struct nfsnode *np;
  193         struct nfs4_compound cp;
  194         struct nfs4_oparg_getattr ga;
  195         struct nfsv4_fattr *fap = &ga.fa;
  196 
  197 #ifndef nolint
  198         sfp = NULL;
  199 #endif
  200         error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np);
  201         if (error)
  202                 return (error);
  203         vp = NFSTOV(np);
  204         nfsstats.rpccnt[NFSPROC_FSSTAT]++;
  205         mreq = nfsm_reqhead(vp, NFSV4PROC_COMPOUND, NFSX_FH(1));
  206         mb = mreq;
  207         bpos = mtod(mb, caddr_t);
  208 
  209         ga.bm = &nfsv4_fsattrbm;
  210         nfs_v4initcompound(&cp);
  211 
  212         nfsm_v4build_compound(&cp, "statfs()");
  213         nfsm_v4build_putfh(&cp, vp);
  214         nfsm_v4build_getattr(&cp, &ga);
  215         nfsm_v4build_finalize(&cp);
  216 
  217         nfsm_request(vp, NFSV4PROC_COMPOUND, td, td->td_ucred);
  218         if (error != 0)
  219                 goto nfsmout;
  220 
  221         nfsm_v4dissect_compound(&cp);
  222         nfsm_v4dissect_putfh(&cp);
  223         nfsm_v4dissect_getattr(&cp, &ga);
  224 
  225         nfs4_vfsop_statfs(fap, sbp, mp);
  226 
  227 nfsmout:
  228         error = nfs_v4postop(&cp, error);
  229 
  230         vput(vp);
  231         if (mrep != NULL)
  232                 m_freem(mrep);
  233 
  234         return (error);
  235 }
  236 
  237 static void
  238 nfs_decode_args(struct nfsmount *nmp, struct nfs_args *argp)
  239 {
  240         int s;
  241         int adjsock;
  242         int maxio;
  243 
  244         s = splnet();
  245         /*
  246          * Silently clear NFSMNT_NOCONN if it's a TCP mount, it makes
  247          * no sense in that context.
  248          */
  249         if (argp->sotype == SOCK_STREAM)
  250                 nmp->nm_flag &= ~NFSMNT_NOCONN;
  251 
  252         nmp->nm_flag &= ~NFSMNT_RDIRPLUS;
  253 
  254         /* Re-bind if rsrvd port requested and wasn't on one */
  255         adjsock = !(nmp->nm_flag & NFSMNT_RESVPORT)
  256                   && (argp->flags & NFSMNT_RESVPORT);
  257         /* Also re-bind if we're switching to/from a connected UDP socket */
  258         adjsock |= ((nmp->nm_flag & NFSMNT_NOCONN) !=
  259                     (argp->flags & NFSMNT_NOCONN));
  260 
  261         /* Update flags atomically.  Don't change the lock bits. */
  262         nmp->nm_flag = argp->flags | nmp->nm_flag;
  263         splx(s);
  264 
  265         if ((argp->flags & NFSMNT_TIMEO) && argp->timeo > 0) {
  266                 nmp->nm_timeo = (argp->timeo * NFS_HZ + 5) / 10;
  267                 if (nmp->nm_timeo < NFS_MINTIMEO)
  268                         nmp->nm_timeo = NFS_MINTIMEO;
  269                 else if (nmp->nm_timeo > NFS_MAXTIMEO)
  270                         nmp->nm_timeo = NFS_MAXTIMEO;
  271         }
  272 
  273         if ((argp->flags & NFSMNT_RETRANS) && argp->retrans > 1) {
  274                 nmp->nm_retry = argp->retrans;
  275                 if (nmp->nm_retry > NFS_MAXREXMIT)
  276                         nmp->nm_retry = NFS_MAXREXMIT;
  277         }
  278 
  279         if (argp->flags & NFSMNT_NFSV3) {
  280                 if (argp->sotype == SOCK_DGRAM)
  281                         maxio = NFS_MAXDGRAMDATA;
  282                 else
  283                         maxio = NFS_MAXDATA;
  284         } else
  285                 maxio = NFS_V2MAXDATA;
  286 
  287         if ((argp->flags & NFSMNT_WSIZE) && argp->wsize > 0) {
  288                 nmp->nm_wsize = argp->wsize;
  289                 /* Round down to multiple of blocksize */
  290                 nmp->nm_wsize &= ~(NFS_FABLKSIZE - 1);
  291                 if (nmp->nm_wsize <= 0)
  292                         nmp->nm_wsize = NFS_FABLKSIZE;
  293         }
  294         if (nmp->nm_wsize > maxio)
  295                 nmp->nm_wsize = maxio;
  296         if (nmp->nm_wsize > MAXBSIZE)
  297                 nmp->nm_wsize = MAXBSIZE;
  298 
  299         if ((argp->flags & NFSMNT_RSIZE) && argp->rsize > 0) {
  300                 nmp->nm_rsize = argp->rsize;
  301                 /* Round down to multiple of blocksize */
  302                 nmp->nm_rsize &= ~(NFS_FABLKSIZE - 1);
  303                 if (nmp->nm_rsize <= 0)
  304                         nmp->nm_rsize = NFS_FABLKSIZE;
  305         }
  306         if (nmp->nm_rsize > maxio)
  307                 nmp->nm_rsize = maxio;
  308         if (nmp->nm_rsize > MAXBSIZE)
  309                 nmp->nm_rsize = MAXBSIZE;
  310 
  311         if ((argp->flags & NFSMNT_READDIRSIZE) && argp->readdirsize > 0) {
  312                 nmp->nm_readdirsize = argp->readdirsize;
  313         }
  314         if (nmp->nm_readdirsize > maxio)
  315                 nmp->nm_readdirsize = maxio;
  316         if (nmp->nm_readdirsize > nmp->nm_rsize)
  317                 nmp->nm_readdirsize = nmp->nm_rsize;
  318 
  319         if ((argp->flags & NFSMNT_ACREGMIN) && argp->acregmin >= 0)
  320                 nmp->nm_acregmin = argp->acregmin;
  321         else
  322                 nmp->nm_acregmin = NFS_MINATTRTIMO;
  323         if ((argp->flags & NFSMNT_ACREGMAX) && argp->acregmax >= 0)
  324                 nmp->nm_acregmax = argp->acregmax;
  325         else
  326                 nmp->nm_acregmax = NFS_MAXATTRTIMO;
  327         if ((argp->flags & NFSMNT_ACDIRMIN) && argp->acdirmin >= 0)
  328                 nmp->nm_acdirmin = argp->acdirmin;
  329         else
  330                 nmp->nm_acdirmin = NFS_MINDIRATTRTIMO;
  331         if ((argp->flags & NFSMNT_ACDIRMAX) && argp->acdirmax >= 0)
  332                 nmp->nm_acdirmax = argp->acdirmax;
  333         else
  334                 nmp->nm_acdirmax = NFS_MAXDIRATTRTIMO;
  335         if (nmp->nm_acdirmin > nmp->nm_acdirmax)
  336                 nmp->nm_acdirmin = nmp->nm_acdirmax;
  337         if (nmp->nm_acregmin > nmp->nm_acregmax)
  338                 nmp->nm_acregmin = nmp->nm_acregmax;
  339 
  340         if ((argp->flags & NFSMNT_MAXGRPS) && argp->maxgrouplist >= 0) {
  341                 if (argp->maxgrouplist <= NFS_MAXGRPS)
  342                         nmp->nm_numgrps = argp->maxgrouplist;
  343                 else
  344                         nmp->nm_numgrps = NFS_MAXGRPS;
  345         }
  346         if ((argp->flags & NFSMNT_READAHEAD) && argp->readahead >= 0) {
  347                 if (argp->readahead <= NFS_MAXRAHEAD)
  348                         nmp->nm_readahead = argp->readahead;
  349                 else
  350                         nmp->nm_readahead = NFS_MAXRAHEAD;
  351         }
  352         if ((argp->flags & NFSMNT_DEADTHRESH) && argp->deadthresh >= 0) {
  353                 if (argp->deadthresh <= NFS_MAXDEADTHRESH)
  354                         nmp->nm_deadthresh = argp->deadthresh;
  355                 else
  356                         nmp->nm_deadthresh = NFS_MAXDEADTHRESH;
  357         }
  358 
  359         adjsock |= ((nmp->nm_sotype != argp->sotype) ||
  360                     (nmp->nm_soproto != argp->proto));
  361         nmp->nm_sotype = argp->sotype;
  362         nmp->nm_soproto = argp->proto;
  363 
  364         if (nmp->nm_rpcclnt.rc_so && adjsock) {
  365                 nfs_safedisconnect(nmp);
  366                 if (nmp->nm_sotype == SOCK_DGRAM) {
  367                         while (nfs4_connect(nmp)) {
  368                                 printf("nfs_args: retrying connect\n");
  369                                 (void) tsleep((caddr_t)&lbolt,
  370                                               PSOCK, "nfscon", 0);
  371                         }
  372                 }
  373         }
  374 }
  375 
  376 /*
  377  * VFS Operations.
  378  *
  379  * mount system call
  380  * It seems a bit dumb to copyinstr() the host and path here and then
  381  * bcopy() them in mountnfs(), but I wanted to detect errors before
  382  * doing the sockargs() call because sockargs() allocates an mbuf and
  383  * an error after that means that I have to release the mbuf.
  384  */
  385 /* ARGSUSED */
  386 static int
  387 nfs_omount(struct mount *mp, char *path, caddr_t data, struct thread *td)
  388 {
  389         int error;
  390         struct nfs_args args;
  391         struct sockaddr *nam;
  392         struct vnode *vp;
  393         char hst[MNAMELEN];
  394         size_t len;
  395 
  396         if (path == NULL) {
  397                 printf("NFSv4: nfs_mountroot not supported\n");
  398                 return EINVAL;
  399         }
  400         error = copyin(data, (caddr_t)&args, sizeof (struct nfs_args));
  401         if (error)
  402                 return (error);
  403         if (args.version != NFS_ARGSVERSION)
  404                 return (EPROGMISMATCH);
  405         if (mp->mnt_flag & MNT_UPDATE) {
  406                 struct nfsmount *nmp = VFSTONFS(mp);
  407 
  408                 if (nmp == NULL)
  409                         return (EIO);
  410                 /*
  411                  * When doing an update, we can't change from or to
  412                  * v3, switch lockd strategies or change cookie translation
  413                  */
  414                 args.flags = (args.flags &
  415                     ~(NFSMNT_NFSV3 | NFSMNT_NFSV4 | NFSMNT_NOLOCKD)) |
  416                     (nmp->nm_flag &
  417                         (NFSMNT_NFSV3 | NFSMNT_NFSV4 | NFSMNT_NOLOCKD));
  418                 nfs_decode_args(nmp, &args);
  419                 return (0);
  420         }
  421 
  422         if (error)
  423                 return (error);
  424         error = copyinstr(args.hostname, hst, MNAMELEN-1, &len);
  425         if (error)
  426                 return (error);
  427         bzero(&hst[len], MNAMELEN - len);
  428         /* sockargs() call must be after above copyin() calls */
  429         error = getsockaddr(&nam, (caddr_t)args.addr, args.addrlen);
  430         if (error)
  431                 return (error);
  432         error = mountnfs(&args, mp, nam, path, hst, &vp, td->td_ucred);
  433         return (error);
  434 }
  435 
  436 /*
  437  * renew should be done async
  438  * should re-scan mount queue each time
  439  */
  440 struct proc *nfs4_daemonproc;
  441 
  442 static int
  443 nfs4_do_renew(struct nfsmount *nmp, struct ucred *cred)
  444 {
  445         struct nfs4_compound cp;
  446         struct mbuf *mreq, *mrep = NULL, *md, *mb;
  447         caddr_t bpos, dpos;     
  448         int error;
  449 
  450         mreq = nfsm_reqhead(NULL, NFSV4PROC_COMPOUND, sizeof(uint64_t));
  451         mb = mreq;
  452         bpos = mtod(mb, caddr_t);
  453 
  454         nfs_v4initcompound(&cp);
  455 
  456         nfsm_v4build_compound(&cp, "nfs4_do_renew()");
  457         nfsm_v4build_renew(&cp, nmp->nm_clientid);
  458         nfsm_v4build_finalize(&cp);
  459 
  460         nfsm_request_mnt(nmp, NFSV4PROC_COMPOUND, curthread, cred);
  461         if (error != 0)
  462                 goto nfsmout;
  463 
  464         nfsm_v4dissect_compound(&cp);
  465         nfsm_v4dissect_renew(&cp);
  466         nmp->nm_last_renewal = time_second;
  467         return (0);
  468 
  469  nfsmout:
  470         error = nfs_v4postop(&cp, error);
  471 
  472         /* XXX */
  473         if (mrep != NULL)
  474                 m_freem(mrep);
  475         return (error);
  476 }
  477 
  478 static void
  479 nfs4_daemon(void *arg)
  480 {
  481         struct mount *mp;
  482         struct nfsmount *nmp;
  483         int nmounts;
  484 
  485         while (1) {
  486                 nmounts = 0;
  487                 mtx_lock(&mountlist_mtx);
  488                 TAILQ_FOREACH(mp, &mountlist, mnt_list) {
  489                         if (strcmp(mp->mnt_vfc->vfc_name, "nfs4") != 0)
  490                                 continue;
  491                         nmounts++;
  492                         nmp = VFSTONFS(mp);
  493                         if (time_second < nmp->nm_last_renewal + nmp->nm_lease_time - 4)
  494                                 continue;
  495                         mtx_unlock(&mountlist_mtx);
  496                         mtx_lock(&Giant);
  497                         nfs4_do_renew(nmp, (struct ucred *) arg);
  498                         mtx_unlock(&Giant);
  499                         mtx_lock(&mountlist_mtx);
  500                 }
  501                 mtx_unlock(&mountlist_mtx);
  502 
  503                 /* Must kill the daemon here, or module unload will cause a panic */
  504                 if (nmounts == 0) {
  505                         mtx_lock(&Giant);
  506                         nfs4_daemonproc = NULL;
  507                         mtx_unlock(&Giant);
  508                         printf("nfsv4 renewd exiting\n");
  509                         kthread_exit(0);
  510                 }
  511                 tsleep(&nfs4_daemonproc, PVFS, "nfs4", 2 * hz);
  512         }
  513 }
  514 
  515 /*
  516  * Common code for mount and mountroot
  517  */
  518 static int
  519 mountnfs(struct nfs_args *argp, struct mount *mp, struct sockaddr *nam,
  520     char *pth, char *hst, struct vnode **vpp, struct ucred *cred)
  521 {
  522         struct nfsmount *nmp;
  523         char *rpth, *cp1, *cp2;
  524         int nlkup = 0, error;
  525         struct nfs4_compound cp;
  526         struct mbuf *mreq, *mrep = NULL, *md, *mb;
  527         caddr_t bpos, dpos;     
  528         struct nfs4_oparg_lookup lkup;
  529         struct nfs4_oparg_getfh gfh;
  530         struct nfs4_oparg_getattr ga;
  531         struct thread *td = curthread; /* XXX */
  532 
  533         if (mp->mnt_flag & MNT_UPDATE) {
  534                 nmp = VFSTONFS(mp);
  535                 /* update paths, file handles, etc, here        XXX */
  536                 FREE(nam, M_SONAME);
  537                 return (0);
  538         } else {
  539                 nmp = uma_zalloc(nfsmount_zone, M_WAITOK);
  540                 bzero((caddr_t)nmp, sizeof (struct nfsmount));
  541                 TAILQ_INIT(&nmp->nm_bufq);
  542                 mp->mnt_data = (qaddr_t)nmp;
  543         }
  544 
  545         vfs_getnewfsid(mp);
  546         nmp->nm_mountp = mp;
  547         nmp->nm_maxfilesize = 0xffffffffLL;
  548         nmp->nm_timeo = NFS_TIMEO;
  549         nmp->nm_retry = NFS_RETRANS;
  550         nmp->nm_wsize = NFS_WSIZE;
  551         nmp->nm_rsize = NFS_RSIZE;
  552         nmp->nm_readdirsize = NFS_READDIRSIZE;
  553         nmp->nm_numgrps = NFS_MAXGRPS;
  554         nmp->nm_readahead = NFS_DEFRAHEAD;
  555         nmp->nm_deadthresh = NFS_MAXDEADTHRESH;
  556         bcopy(hst, mp->mnt_stat.f_mntfromname, MNAMELEN);
  557         bcopy(pth, mp->mnt_stat.f_mntonname, MNAMELEN);
  558         nmp->nm_nam = nam;
  559         /* Set up the sockets and per-host congestion */
  560         nmp->nm_sotype = argp->sotype;
  561         nmp->nm_soproto = argp->proto;
  562         nmp->nm_rpcops = &nfs4_rpcops;
  563         /* XXX */
  564         mp->mnt_stat.f_iosize = PAGE_SIZE;
  565 
  566         argp->flags |= (NFSMNT_NFSV3 | NFSMNT_NFSV4);
  567 
  568         nfs_decode_args(nmp, argp);
  569 
  570         if ((error = nfs4_connect(nmp)))
  571                 goto bad;
  572 
  573         mreq = nfsm_reqhead(NULL, NFSV4PROC_COMPOUND, NFSX_FH(1));
  574         mb = mreq;
  575         bpos = mtod(mb, caddr_t);
  576 
  577         ga.bm = &nfsv4_fsinfobm;
  578         nfs_v4initcompound(&cp);
  579 
  580         /* Get remote path */
  581         rpth = hst;
  582         strsep(&rpth, ":");
  583 
  584         nfsm_v4build_compound(&cp, "mountnfs()");
  585         nfsm_v4build_putrootfh(&cp);
  586         for (cp1 = rpth; cp1 && *cp1; cp1 = cp2)  {
  587                 while (*cp1 == '/')
  588                         cp1++;
  589                 if (!*cp1)
  590                         break;
  591                 for (cp2 = cp1; *cp2 && *cp2 != '/'; cp2++)
  592                         ;
  593                 lkup.name = cp1;
  594                 lkup.namelen = cp2 - cp1;
  595                 nfsm_v4build_lookup(&cp, &lkup);
  596                 nlkup++;
  597         }
  598         nfsm_v4build_getfh(&cp, &gfh);
  599         nfsm_v4build_getattr(&cp, &ga);
  600         nfsm_v4build_finalize(&cp);
  601 
  602         nfsm_request_mnt(nmp, NFSV4PROC_COMPOUND, td, cred);
  603         if (error != 0)
  604                 goto nfsmout;
  605 
  606         nfsm_v4dissect_compound(&cp);
  607         nfsm_v4dissect_putrootfh(&cp);
  608         while (nlkup--)
  609                 nfsm_v4dissect_lookup(&cp);
  610         nfsm_v4dissect_getfh(&cp, &gfh);
  611         nfsm_v4dissect_getattr(&cp, &ga);
  612 
  613         nfs4_vfsop_fsinfo(&ga.fa, nmp);
  614         nmp->nm_state |= NFSSTA_GOTFSINFO;
  615 
  616         /* Copy root fh into nfsmount. */
  617         nmp->nm_fhsize = gfh.fh_len;
  618         bcopy(&gfh.fh_val, nmp->nm_fh, nmp->nm_fhsize);
  619         nmp->nm_last_renewal = time_second;
  620 
  621         if ((error = nfs4_do_setclientid(nmp, cred)) != 0)
  622                 goto nfsmout;
  623 
  624         /* Start renewd if it isn't already running */
  625         if (nfs4_daemonproc == NULL)
  626                 kthread_create(nfs4_daemon, crdup(cred), &nfs4_daemonproc,
  627                                (RFPROC|RFMEM), 0, "nfs4rd");
  628 
  629         return (0);
  630  nfsmout:
  631         error = nfs_v4postop(&cp, error);
  632 
  633         /* XXX */
  634         if (mrep != NULL)
  635                 m_freem(mrep);
  636 bad:
  637         nfs_disconnect(nmp);
  638         uma_zfree(nfsmount_zone, nmp);
  639         FREE(nam, M_SONAME);
  640 
  641         return (error);
  642 }
  643 
  644 /*
  645  * unmount system call
  646  */
  647 static int
  648 nfs_unmount(struct mount *mp, int mntflags, struct thread *td)
  649 {
  650         struct nfsmount *nmp;
  651         int error, flags = 0;
  652 
  653         if (mntflags & MNT_FORCE)
  654                 flags |= FORCECLOSE;
  655         nmp = VFSTONFS(mp);
  656         /*
  657          * Goes something like this..
  658          * - Call vflush(, td) to clear out vnodes for this filesystem
  659          * - Close the socket
  660          * - Free up the data structures
  661          */
  662         /* In the forced case, cancel any outstanding requests. */
  663         if (flags & FORCECLOSE) {
  664                 error = nfs_nmcancelreqs(nmp);
  665                 if (error)
  666                         return (error);
  667                 nfs4dev_purge();
  668         }
  669 
  670         error = vflush(mp, 0, flags, td);
  671         if (error)
  672                 return (error);
  673 
  674         /*
  675          * We are now committed to the unmount.
  676          */
  677         nfs_disconnect(nmp);
  678         FREE(nmp->nm_nam, M_SONAME);
  679 
  680         /* XXX there's a race condition here for SMP */
  681         wakeup(&nfs4_daemonproc);
  682 
  683         uma_zfree(nfsmount_zone, nmp);
  684         return (0);
  685 }
  686 
  687 /*
  688  * Return root of a filesystem
  689  */
  690 static int
  691 nfs_root(struct mount *mp, struct vnode **vpp, struct thread *td)
  692 {
  693         struct vnode *vp;
  694         struct nfsmount *nmp;
  695         struct nfsnode *np;
  696         int error;
  697 
  698         nmp = VFSTONFS(mp);
  699         error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np);
  700         if (error)
  701                 return (error);
  702         vp = NFSTOV(np);
  703         if (vp->v_type == VNON)
  704             vp->v_type = VDIR;
  705         vp->v_vflag |= VV_ROOT;
  706         *vpp = vp;
  707 
  708         return (0);
  709 }
  710 
  711 /*
  712  * Flush out the buffer cache
  713  */
  714 /* ARGSUSED */
  715 static int
  716 nfs_sync(struct mount *mp, int waitfor, struct ucred *cred, struct thread *td)
  717 {
  718         struct vnode *vp, *nvp;
  719         int error, allerror = 0;
  720 
  721         /*
  722          * Force stale buffer cache information to be flushed.
  723          */
  724         MNT_ILOCK(mp);
  725 loop:
  726         MNT_VNODE_FOREACH(vp, mp, nvp) {
  727                 VI_LOCK(vp);
  728                 MNT_IUNLOCK(mp);
  729                 if (VOP_ISLOCKED(vp, NULL) || TAILQ_EMPTY(&vp->v_dirtyblkhd) ||
  730                     waitfor == MNT_LAZY) {
  731                         VI_UNLOCK(vp);
  732                         MNT_ILOCK(mp);
  733                         continue;
  734                 }
  735                 if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, td)) {
  736                         goto loop;
  737                 }
  738                 error = VOP_FSYNC(vp, cred, waitfor, td);
  739                 if (error)
  740                         allerror = error;
  741                 VOP_UNLOCK(vp, 0, td);
  742                 vrele(vp);
  743 
  744                 MNT_ILOCK(mp);
  745         }
  746         MNT_IUNLOCK(mp);
  747         return (allerror);
  748 }
  749 
  750 static int
  751 nfs4_do_setclientid(struct nfsmount *nmp, struct ucred *cred)
  752 {
  753         struct nfs4_oparg_setclientid scid;
  754         struct nfs4_compound cp;
  755         struct mbuf *mreq, *mrep = NULL, *md, *mb;
  756         caddr_t bpos, dpos;     
  757         struct route ro;
  758         char *ipsrc = NULL, uaddr[24], name[24];
  759         int try = 0;
  760         static unsigned long seq;
  761         int error;
  762 
  763 #ifndef NFS4_USE_RPCCLNT
  764         return (0);
  765 #endif
  766         if (nmp->nm_clientid) {
  767                 printf("nfs4_do_setclientid: already have clientid!\n");
  768                 error = 0;
  769                 goto nfsmout;
  770         }
  771 
  772         /* Try not to re-use clientids */
  773         if (seq == 0)
  774                 seq = time_second;
  775 
  776 #ifdef NFS4_USE_RPCCLNT
  777         scid.cb_netid = (nmp->nm_rpcclnt.rc_sotype == SOCK_STREAM) ? "tcp" : "udp";
  778 #endif
  779         scid.cb_netid = "tcp";
  780         scid.cb_netidlen = 3;
  781         scid.cb_prog = 0x1234; /* XXX */
  782 
  783         /* Do a route lookup to find our source address for talking to this server */
  784         bzero(&ro, sizeof ro);
  785 
  786 #ifdef NFS4_USE_RPCCLNT
  787         ro.ro_dst = *nmp->nm_rpcclnt.rc_name;
  788 #endif
  789         rtalloc(&ro);
  790         if (ro.ro_rt == NULL) {
  791                 error = EHOSTUNREACH;
  792                 goto nfsmout;
  793         }
  794         ipsrc = inet_ntoa(IA_SIN(ifatoia(ro.ro_rt->rt_ifa))->sin_addr);
  795         sprintf(uaddr, "%s.12.48", ipsrc);
  796         scid.cb_univaddr = uaddr;
  797         scid.cb_univaddrlen = strlen(uaddr);
  798         RTFREE(ro.ro_rt);
  799 
  800  try_again:
  801         sprintf(name, "%s-%d", ipsrc, (int) ((seq + try) % 1000000L));
  802         scid.namelen = strlen(name);
  803         scid.name = name;
  804         nfs_v4initcompound(&cp);
  805 
  806         mreq = nfsm_reqhead(NULL, NFSV4PROC_COMPOUND, NFSX_FH(1));
  807         mb = mreq;
  808         bpos = mtod(mb, caddr_t);
  809 
  810         nfsm_v4build_compound(&cp, "nfs4_do_setclientid()");
  811         nfsm_v4build_setclientid(&cp, &scid);
  812         nfsm_v4build_finalize(&cp);
  813 
  814         nfsm_request_mnt(nmp, NFSV4PROC_COMPOUND, curthread, cred);
  815         if (error != 0)
  816                 goto nfsmout;
  817 
  818         nfsm_v4dissect_compound(&cp);
  819         nfsm_v4dissect_setclientid(&cp, &scid);
  820         nmp->nm_clientid = scid.clientid;
  821 
  822         error = nfs_v4postop(&cp, error);
  823 
  824         /* Confirm */
  825         m_freem(mrep);
  826         mreq = nfsm_reqhead(NULL, NFSV4PROC_COMPOUND, NFSX_FH(1));
  827         mb = mreq;
  828         bpos = mtod(mb, caddr_t);
  829 
  830         nfs_v4initcompound(&cp);
  831 
  832         nfsm_v4build_compound(&cp, "nfs4_do_setclientid() (confirm)");
  833         nfsm_v4build_setclientid_confirm(&cp, &scid);
  834         nfsm_v4build_finalize(&cp);
  835 
  836         nfsm_request_mnt(nmp, NFSV4PROC_COMPOUND, curthread, cred);
  837         if (error != 0)
  838                 goto nfsmout;
  839 
  840         nfsm_v4dissect_compound(&cp);
  841         nfsm_v4dissect_setclientid_confirm(&cp);
  842 
  843  nfsmout:
  844         error = nfs_v4postop(&cp, error);
  845 
  846         if (mrep)
  847                 m_freem(mrep);
  848         if (error == NFSERR_CLID_INUSE && (++try < NFS4_SETCLIENTID_MAXTRIES))
  849                 goto try_again;
  850 
  851         return (error);
  852 }

Cache object: 4543f1f4c3c840acee55f9837609df52


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


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.