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

Cache object: 13f34a5590faa5c018bbc9e0750b0461


[ 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.