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/nfs/nfs_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 /*      $NetBSD: nfs_vfsops.c,v 1.145.2.1 2005/09/27 10:31:29 tron Exp $        */
    2 
    3 /*
    4  * Copyright (c) 1989, 1993, 1995
    5  *      The Regents of the University of California.  All rights reserved.
    6  *
    7  * This code is derived from software contributed to Berkeley by
    8  * Rick Macklem at The University of Guelph.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  * 3. Neither the name of the University nor the names of its contributors
   19  *    may be used to endorse or promote products derived from this software
   20  *    without specific prior written permission.
   21  *
   22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   32  * SUCH DAMAGE.
   33  *
   34  *      @(#)nfs_vfsops.c        8.12 (Berkeley) 5/20/95
   35  */
   36 
   37 #include <sys/cdefs.h>
   38 __KERNEL_RCSID(0, "$NetBSD: nfs_vfsops.c,v 1.145.2.1 2005/09/27 10:31:29 tron Exp $");
   39 
   40 #if defined(_KERNEL_OPT)
   41 #include "opt_compat_netbsd.h"
   42 #include "opt_nfs.h"
   43 #endif
   44 
   45 #include <sys/param.h>
   46 #include <sys/ioctl.h>
   47 #include <sys/signal.h>
   48 #include <sys/proc.h>
   49 #include <sys/namei.h>
   50 #include <sys/device.h>
   51 #include <sys/vnode.h>
   52 #include <sys/kernel.h>
   53 #include <sys/mount.h>
   54 #include <sys/buf.h>
   55 #include <sys/mbuf.h>
   56 #include <sys/dirent.h>
   57 #include <sys/socket.h>
   58 #include <sys/socketvar.h>
   59 #include <sys/sysctl.h>
   60 #include <sys/systm.h>
   61 
   62 #include <net/if.h>
   63 #include <net/route.h>
   64 #include <netinet/in.h>
   65 
   66 #include <nfs/rpcv2.h>
   67 #include <nfs/nfsproto.h>
   68 #include <nfs/nfsnode.h>
   69 #include <nfs/nfs.h>
   70 #include <nfs/nfsmount.h>
   71 #include <nfs/xdr_subs.h>
   72 #include <nfs/nfsm_subs.h>
   73 #include <nfs/nfsdiskless.h>
   74 #include <nfs/nqnfs.h>
   75 #include <nfs/nfs_var.h>
   76 
   77 extern struct nfsstats nfsstats;
   78 extern int nfs_ticks;
   79 
   80 MALLOC_DEFINE(M_NFSMNT, "NFS mount", "NFS mount structure");
   81 
   82 /*
   83  * nfs vfs operations.
   84  */
   85 
   86 extern const struct vnodeopv_desc nfsv2_vnodeop_opv_desc;
   87 extern const struct vnodeopv_desc spec_nfsv2nodeop_opv_desc;
   88 extern const struct vnodeopv_desc fifo_nfsv2nodeop_opv_desc;
   89 
   90 const struct vnodeopv_desc * const nfs_vnodeopv_descs[] = {
   91         &nfsv2_vnodeop_opv_desc,
   92         &spec_nfsv2nodeop_opv_desc,
   93         &fifo_nfsv2nodeop_opv_desc,
   94         NULL,
   95 };
   96 
   97 struct vfsops nfs_vfsops = {
   98         MOUNT_NFS,
   99         nfs_mount,
  100         nfs_start,
  101         nfs_unmount,
  102         nfs_root,
  103         nfs_quotactl,
  104         nfs_statvfs,
  105         nfs_sync,
  106         nfs_vget,
  107         nfs_fhtovp,
  108         nfs_vptofh,
  109         nfs_vfs_init,
  110         nfs_vfs_reinit,
  111         nfs_vfs_done,
  112         NULL,
  113         nfs_mountroot,
  114         nfs_checkexp,
  115         (int (*)(struct mount *, struct vnode *, struct timespec *)) eopnotsupp,
  116         vfs_stdextattrctl,
  117         nfs_vnodeopv_descs,
  118 };
  119 
  120 extern u_int32_t nfs_procids[NFS_NPROCS];
  121 extern u_int32_t nfs_prog, nfs_vers;
  122 
  123 static int nfs_mount_diskless __P((struct nfs_dlmount *, const char *,
  124     struct mount **, struct vnode **, struct proc *));
  125 
  126 /*
  127  * nfs statvfs call
  128  */
  129 int
  130 nfs_statvfs(mp, sbp, p)
  131         struct mount *mp;
  132         struct statvfs *sbp;
  133         struct proc *p;
  134 {
  135         struct vnode *vp;
  136         struct nfs_statfs *sfp;
  137         caddr_t cp;
  138         u_int32_t *tl;
  139         int32_t t1, t2;
  140         caddr_t bpos, dpos, cp2;
  141         struct nfsmount *nmp = VFSTONFS(mp);
  142         int error = 0, retattr;
  143 #ifdef NFS_V2_ONLY
  144         const int v3 = 0;
  145 #else
  146         int v3 = (nmp->nm_flag & NFSMNT_NFSV3);
  147 #endif
  148         struct mbuf *mreq, *mrep = NULL, *md, *mb;
  149         struct ucred *cred;
  150         u_quad_t tquad;
  151         struct nfsnode *np;
  152 
  153 #ifndef nolint
  154         sfp = (struct nfs_statfs *)0;
  155 #endif
  156         vp = nmp->nm_vnode;
  157         np = VTONFS(vp);
  158         cred = crget();
  159         cred->cr_ngroups = 0;
  160 #ifndef NFS_V2_ONLY
  161         if (v3 && (nmp->nm_iflag & NFSMNT_GOTFSINFO) == 0)
  162                 (void)nfs_fsinfo(nmp, vp, cred, p);
  163 #endif
  164         nfsstats.rpccnt[NFSPROC_FSSTAT]++;
  165         nfsm_reqhead(np, NFSPROC_FSSTAT, NFSX_FH(v3));
  166         nfsm_fhtom(np, v3);
  167         nfsm_request(np, NFSPROC_FSSTAT, p, cred);
  168         if (v3)
  169                 nfsm_postop_attr(vp, retattr, 0);
  170         if (error) {
  171                 if (mrep != NULL) {
  172                         if (mrep->m_next != NULL)
  173                                 printf("nfs_vfsops: nfs_statvfs would lose buffers\n");
  174                         m_freem(mrep);
  175                 }
  176                 goto nfsmout;
  177         }
  178         nfsm_dissect(sfp, struct nfs_statfs *, NFSX_STATFS(v3));
  179         sbp->f_flag = nmp->nm_flag;
  180         sbp->f_iosize = min(nmp->nm_rsize, nmp->nm_wsize);
  181         if (v3) {
  182                 sbp->f_frsize = sbp->f_bsize = NFS_FABLKSIZE;
  183                 tquad = fxdr_hyper(&sfp->sf_tbytes);
  184                 sbp->f_blocks = ((quad_t)tquad / (quad_t)NFS_FABLKSIZE);
  185                 tquad = fxdr_hyper(&sfp->sf_fbytes);
  186                 sbp->f_bfree = ((quad_t)tquad / (quad_t)NFS_FABLKSIZE);
  187                 tquad = fxdr_hyper(&sfp->sf_abytes);
  188                 tquad = ((quad_t)tquad / (quad_t)NFS_FABLKSIZE);
  189                 sbp->f_bresvd = sbp->f_bfree - tquad;
  190                 sbp->f_bavail = tquad;
  191 #ifdef COMPAT_20
  192                 /* Handle older NFS servers returning negative values */
  193                 if ((quad_t)sbp->f_bavail < 0)
  194                         sbp->f_bavail = 0;
  195 #endif
  196                 tquad = fxdr_hyper(&sfp->sf_tfiles);
  197                 sbp->f_files = tquad;
  198                 tquad = fxdr_hyper(&sfp->sf_ffiles);
  199                 sbp->f_ffree = tquad;
  200                 sbp->f_favail = tquad;
  201                 sbp->f_fresvd = 0;
  202                 sbp->f_namemax = MAXNAMLEN;
  203         } else {
  204                 sbp->f_bsize = NFS_FABLKSIZE;
  205                 sbp->f_frsize = fxdr_unsigned(int32_t, sfp->sf_bsize);
  206                 sbp->f_blocks = fxdr_unsigned(int32_t, sfp->sf_blocks);
  207                 sbp->f_bfree = fxdr_unsigned(int32_t, sfp->sf_bfree);
  208                 sbp->f_bavail = fxdr_unsigned(int32_t, sfp->sf_bavail);
  209                 sbp->f_fresvd = 0;
  210                 sbp->f_files = 0;
  211                 sbp->f_ffree = 0;
  212                 sbp->f_favail = 0;
  213                 sbp->f_fresvd = 0;
  214                 sbp->f_namemax = MAXNAMLEN;
  215         }
  216         copy_statvfs_info(sbp, mp);
  217         nfsm_reqdone;
  218         crfree(cred);
  219         return (error);
  220 }
  221 
  222 #ifndef NFS_V2_ONLY
  223 /*
  224  * nfs version 3 fsinfo rpc call
  225  */
  226 int
  227 nfs_fsinfo(nmp, vp, cred, p)
  228         struct nfsmount *nmp;
  229         struct vnode *vp;
  230         struct ucred *cred;
  231         struct proc *p;
  232 {
  233         struct nfsv3_fsinfo *fsp;
  234         caddr_t cp;
  235         int32_t t1, t2;
  236         u_int32_t *tl, pref, max;
  237         caddr_t bpos, dpos, cp2;
  238         int error = 0, retattr;
  239         struct mbuf *mreq, *mrep, *md, *mb;
  240         u_int64_t maxfsize;
  241         struct nfsnode *np = VTONFS(vp);
  242 
  243         nfsstats.rpccnt[NFSPROC_FSINFO]++;
  244         nfsm_reqhead(np, NFSPROC_FSINFO, NFSX_FH(1));
  245         nfsm_fhtom(np, 1);
  246         nfsm_request(np, NFSPROC_FSINFO, p, cred);
  247         nfsm_postop_attr(vp, retattr, 0);
  248         if (!error) {
  249                 nfsm_dissect(fsp, struct nfsv3_fsinfo *, NFSX_V3FSINFO);
  250                 pref = fxdr_unsigned(u_int32_t, fsp->fs_wtpref);
  251                 if ((nmp->nm_flag & NFSMNT_WSIZE) == 0 &&
  252                     pref < nmp->nm_wsize && pref >= NFS_FABLKSIZE)
  253                         nmp->nm_wsize = (pref + NFS_FABLKSIZE - 1) &
  254                                 ~(NFS_FABLKSIZE - 1);
  255                 max = fxdr_unsigned(u_int32_t, fsp->fs_wtmax);
  256                 if (max < nmp->nm_wsize && max > 0) {
  257                         nmp->nm_wsize = max & ~(NFS_FABLKSIZE - 1);
  258                         if (nmp->nm_wsize == 0)
  259                                 nmp->nm_wsize = max;
  260                 }
  261                 pref = fxdr_unsigned(u_int32_t, fsp->fs_rtpref);
  262                 if ((nmp->nm_flag & NFSMNT_RSIZE) == 0 &&
  263                     pref < nmp->nm_rsize && pref >= NFS_FABLKSIZE)
  264                         nmp->nm_rsize = (pref + NFS_FABLKSIZE - 1) &
  265                                 ~(NFS_FABLKSIZE - 1);
  266                 max = fxdr_unsigned(u_int32_t, fsp->fs_rtmax);
  267                 if (max < nmp->nm_rsize && max > 0) {
  268                         nmp->nm_rsize = max & ~(NFS_FABLKSIZE - 1);
  269                         if (nmp->nm_rsize == 0)
  270                                 nmp->nm_rsize = max;
  271                 }
  272                 pref = fxdr_unsigned(u_int32_t, fsp->fs_dtpref);
  273                 if (pref < nmp->nm_readdirsize && pref >= NFS_DIRFRAGSIZ)
  274                         nmp->nm_readdirsize = (pref + NFS_DIRFRAGSIZ - 1) &
  275                                 ~(NFS_DIRFRAGSIZ - 1);
  276                 if (max < nmp->nm_readdirsize && max > 0) {
  277                         nmp->nm_readdirsize = max & ~(NFS_DIRFRAGSIZ - 1);
  278                         if (nmp->nm_readdirsize == 0)
  279                                 nmp->nm_readdirsize = max;
  280                 }
  281                 /* XXX */
  282                 nmp->nm_maxfilesize = (u_int64_t)0x80000000 * DEV_BSIZE - 1;
  283                 maxfsize = fxdr_hyper(&fsp->fs_maxfilesize);
  284                 if (maxfsize > 0 && maxfsize < nmp->nm_maxfilesize)
  285                         nmp->nm_maxfilesize = maxfsize;
  286                 nmp->nm_mountp->mnt_fs_bshift =
  287                     ffs(MIN(nmp->nm_rsize, nmp->nm_wsize)) - 1;
  288                 nmp->nm_iflag |= NFSMNT_GOTFSINFO;
  289         }
  290         nfsm_reqdone;
  291         return (error);
  292 }
  293 #endif
  294 
  295 /*
  296  * Mount a remote root fs via. NFS.  It goes like this:
  297  * - Call nfs_boot_init() to fill in the nfs_diskless struct
  298  * - build the rootfs mount point and call mountnfs() to do the rest.
  299  */
  300 int
  301 nfs_mountroot()
  302 {
  303         struct nfs_diskless *nd;
  304         struct vattr attr;
  305         struct mount *mp;
  306         struct vnode *vp;
  307         struct proc *procp;
  308         long n;
  309         int error;
  310 
  311         procp = curproc; /* XXX */
  312 
  313         if (root_device->dv_class != DV_IFNET)
  314                 return (ENODEV);
  315 
  316         /*
  317          * XXX time must be non-zero when we init the interface or else
  318          * the arp code will wedge.  [Fixed now in if_ether.c]
  319          * However, the NFS attribute cache gives false "hits" when
  320          * time.tv_sec < NFS_ATTRTIMEO(nmp, np) so keep this in for now.
  321          */
  322         if (time.tv_sec < NFS_MAXATTRTIMO)
  323                 time.tv_sec = NFS_MAXATTRTIMO;
  324 
  325         /*
  326          * Call nfs_boot_init() to fill in the nfs_diskless struct.
  327          * Side effect:  Finds and configures a network interface.
  328          */
  329         nd = malloc(sizeof(*nd), M_NFSMNT, M_WAITOK);
  330         memset((caddr_t)nd, 0, sizeof(*nd));
  331         error = nfs_boot_init(nd, procp);
  332         if (error) {
  333                 free(nd, M_NFSMNT);
  334                 return (error);
  335         }
  336 
  337         /*
  338          * Create the root mount point.
  339          */
  340         error = nfs_mount_diskless(&nd->nd_root, "/", &mp, &vp, procp);
  341         if (error)
  342                 goto out;
  343         printf("root on %s\n", nd->nd_root.ndm_host);
  344 
  345         /*
  346          * Link it into the mount list.
  347          */
  348         simple_lock(&mountlist_slock);
  349         CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
  350         simple_unlock(&mountlist_slock);
  351         rootvp = vp;
  352         mp->mnt_vnodecovered = NULLVP;
  353         vfs_unbusy(mp);
  354 
  355         /* Get root attributes (for the time). */
  356         error = VOP_GETATTR(vp, &attr, procp->p_ucred, procp);
  357         if (error)
  358                 panic("nfs_mountroot: getattr for root");
  359         n = attr.va_atime.tv_sec;
  360 #ifdef  DEBUG
  361         printf("root time: 0x%lx\n", n);
  362 #endif
  363         setrootfstime(n);
  364 
  365 out:
  366         if (error)
  367                 nfs_boot_cleanup(nd, procp);
  368         free(nd, M_NFSMNT);
  369         return (error);
  370 }
  371 
  372 /*
  373  * Internal version of mount system call for diskless setup.
  374  * Separate function because we used to call it twice.
  375  * (once for root and once for swap)
  376  */
  377 static int
  378 nfs_mount_diskless(ndmntp, mntname, mpp, vpp, p)
  379         struct nfs_dlmount *ndmntp;
  380         const char *mntname;    /* mount point name */
  381         struct mount **mpp;
  382         struct vnode **vpp;
  383         struct proc *p;
  384 {
  385         struct mount *mp;
  386         struct mbuf *m;
  387         int error;
  388 
  389         vfs_rootmountalloc(MOUNT_NFS, (char *)mntname, &mp);
  390 
  391         mp->mnt_op = &nfs_vfsops;
  392 
  393         /*
  394          * Historical practice expects NFS root file systems to
  395          * be initially mounted r/w.
  396          */
  397         mp->mnt_flag &= ~MNT_RDONLY;
  398 
  399         /* Get mbuf for server sockaddr. */
  400         m = m_get(M_WAIT, MT_SONAME);
  401         if (m == NULL)
  402                 panic("nfs_mountroot: mget soname for %s", mntname);
  403         MCLAIM(m, &nfs_mowner);
  404         memcpy(mtod(m, caddr_t), (caddr_t)ndmntp->ndm_args.addr,
  405               (m->m_len = ndmntp->ndm_args.addr->sa_len));
  406 
  407         error = mountnfs(&ndmntp->ndm_args, mp, m, mntname,
  408                          ndmntp->ndm_args.hostname, vpp, p);
  409         if (error) {
  410                 mp->mnt_op->vfs_refcount--;
  411                 vfs_unbusy(mp);
  412                 printf("nfs_mountroot: mount %s failed: %d\n",
  413                        mntname, error);
  414                 free(mp, M_MOUNT);
  415         } else
  416                 *mpp = mp;
  417 
  418         return (error);
  419 }
  420 
  421 void
  422 nfs_decode_args(nmp, argp, p)
  423         struct nfsmount *nmp;
  424         struct nfs_args *argp;
  425         struct proc *p;
  426 {
  427         int s;
  428         int adjsock;
  429         int maxio;
  430 
  431         s = splsoftnet();
  432 
  433         /*
  434          * Silently clear NFSMNT_NOCONN if it's a TCP mount, it makes
  435          * no sense in that context.
  436          */
  437         if (argp->sotype == SOCK_STREAM)
  438                 argp->flags &= ~NFSMNT_NOCONN;
  439 
  440         /*
  441          * Cookie translation is not needed for v2, silently ignore it.
  442          */
  443         if ((argp->flags & (NFSMNT_XLATECOOKIE|NFSMNT_NFSV3)) ==
  444             NFSMNT_XLATECOOKIE)
  445                 argp->flags &= ~NFSMNT_XLATECOOKIE;
  446 
  447         /* Re-bind if rsrvd port requested and wasn't on one */
  448         adjsock = !(nmp->nm_flag & NFSMNT_RESVPORT)
  449                   && (argp->flags & NFSMNT_RESVPORT);
  450         /* Also re-bind if we're switching to/from a connected UDP socket */
  451         adjsock |= ((nmp->nm_flag & NFSMNT_NOCONN) !=
  452                     (argp->flags & NFSMNT_NOCONN));
  453 
  454         /* Update flags. */
  455         nmp->nm_flag = argp->flags;
  456         splx(s);
  457 
  458         if ((argp->flags & NFSMNT_TIMEO) && argp->timeo > 0) {
  459                 nmp->nm_timeo = (argp->timeo * NFS_HZ + 5) / 10;
  460                 if (nmp->nm_timeo < NFS_MINTIMEO)
  461                         nmp->nm_timeo = NFS_MINTIMEO;
  462                 else if (nmp->nm_timeo > NFS_MAXTIMEO)
  463                         nmp->nm_timeo = NFS_MAXTIMEO;
  464         }
  465 
  466         if ((argp->flags & NFSMNT_RETRANS) && argp->retrans > 1) {
  467                 nmp->nm_retry = argp->retrans;
  468                 if (nmp->nm_retry > NFS_MAXREXMIT)
  469                         nmp->nm_retry = NFS_MAXREXMIT;
  470         }
  471 
  472 #ifndef NFS_V2_ONLY
  473         if (argp->flags & NFSMNT_NFSV3) {
  474                 if (argp->sotype == SOCK_DGRAM)
  475                         maxio = NFS_MAXDGRAMDATA;
  476                 else
  477                         maxio = NFS_MAXDATA;
  478         } else
  479 #endif
  480                 maxio = NFS_V2MAXDATA;
  481 
  482         if ((argp->flags & NFSMNT_WSIZE) && argp->wsize > 0) {
  483                 int osize = nmp->nm_wsize;
  484                 nmp->nm_wsize = argp->wsize;
  485                 /* Round down to multiple of blocksize */
  486                 nmp->nm_wsize &= ~(NFS_FABLKSIZE - 1);
  487                 if (nmp->nm_wsize <= 0)
  488                         nmp->nm_wsize = NFS_FABLKSIZE;
  489                 adjsock |= (nmp->nm_wsize != osize);
  490         }
  491         if (nmp->nm_wsize > maxio)
  492                 nmp->nm_wsize = maxio;
  493         if (nmp->nm_wsize > MAXBSIZE)
  494                 nmp->nm_wsize = MAXBSIZE;
  495 
  496         if ((argp->flags & NFSMNT_RSIZE) && argp->rsize > 0) {
  497                 int osize = nmp->nm_rsize;
  498                 nmp->nm_rsize = argp->rsize;
  499                 /* Round down to multiple of blocksize */
  500                 nmp->nm_rsize &= ~(NFS_FABLKSIZE - 1);
  501                 if (nmp->nm_rsize <= 0)
  502                         nmp->nm_rsize = NFS_FABLKSIZE;
  503                 adjsock |= (nmp->nm_rsize != osize);
  504         }
  505         if (nmp->nm_rsize > maxio)
  506                 nmp->nm_rsize = maxio;
  507         if (nmp->nm_rsize > MAXBSIZE)
  508                 nmp->nm_rsize = MAXBSIZE;
  509 
  510         if ((argp->flags & NFSMNT_READDIRSIZE) && argp->readdirsize > 0) {
  511                 nmp->nm_readdirsize = argp->readdirsize;
  512                 /* Round down to multiple of minimum blocksize */
  513                 nmp->nm_readdirsize &= ~(NFS_DIRFRAGSIZ - 1);
  514                 if (nmp->nm_readdirsize < NFS_DIRFRAGSIZ)
  515                         nmp->nm_readdirsize = NFS_DIRFRAGSIZ;
  516                 /* Bigger than buffer size makes no sense */
  517                 if (nmp->nm_readdirsize > NFS_DIRBLKSIZ)
  518                         nmp->nm_readdirsize = NFS_DIRBLKSIZ;
  519         } else if (argp->flags & NFSMNT_RSIZE)
  520                 nmp->nm_readdirsize = nmp->nm_rsize;
  521 
  522         if (nmp->nm_readdirsize > maxio)
  523                 nmp->nm_readdirsize = maxio;
  524 
  525         if ((argp->flags & NFSMNT_MAXGRPS) && argp->maxgrouplist >= 0 &&
  526                 argp->maxgrouplist <= NFS_MAXGRPS)
  527                 nmp->nm_numgrps = argp->maxgrouplist;
  528         if ((argp->flags & NFSMNT_READAHEAD) && argp->readahead >= 0 &&
  529                 argp->readahead <= NFS_MAXRAHEAD)
  530                 nmp->nm_readahead = argp->readahead;
  531         if ((argp->flags & NFSMNT_LEASETERM) && argp->leaseterm >= 2 &&
  532                 argp->leaseterm <= NQ_MAXLEASE)
  533                 nmp->nm_leaseterm = argp->leaseterm;
  534         if ((argp->flags & NFSMNT_DEADTHRESH) && argp->deadthresh >= 1 &&
  535                 argp->deadthresh <= NQ_NEVERDEAD)
  536                 nmp->nm_deadthresh = argp->deadthresh;
  537 
  538         adjsock |= ((nmp->nm_sotype != argp->sotype) ||
  539                     (nmp->nm_soproto != argp->proto));
  540         nmp->nm_sotype = argp->sotype;
  541         nmp->nm_soproto = argp->proto;
  542 
  543         if (nmp->nm_so && adjsock) {
  544                 nfs_safedisconnect(nmp);
  545                 if (nmp->nm_sotype == SOCK_DGRAM)
  546                         while (nfs_connect(nmp, (struct nfsreq *)0, p)) {
  547                                 printf("nfs_args: retrying connect\n");
  548                                 (void) tsleep((caddr_t)&lbolt,
  549                                               PSOCK, "nfscn3", 0);
  550                         }
  551         }
  552 }
  553 
  554 /*
  555  * VFS Operations.
  556  *
  557  * mount system call
  558  * It seems a bit dumb to copyinstr() the host and path here and then
  559  * memcpy() them in mountnfs(), but I wanted to detect errors before
  560  * doing the sockargs() call because sockargs() allocates an mbuf and
  561  * an error after that means that I have to release the mbuf.
  562  */
  563 /* ARGSUSED */
  564 int
  565 nfs_mount(mp, path, data, ndp, p)
  566         struct mount *mp;
  567         const char *path;
  568         void *data;
  569         struct nameidata *ndp;
  570         struct proc *p;
  571 {
  572         int error;
  573         struct nfs_args args;
  574         struct mbuf *nam;
  575         struct nfsmount *nmp = VFSTONFS(mp);
  576         struct sockaddr *sa;
  577         struct vnode *vp;
  578         char *pth, *hst;
  579         size_t len;
  580         u_char *nfh;
  581 
  582         error = copyin(data, (caddr_t)&args, sizeof (struct nfs_args));
  583         if (error)
  584                 return (error);
  585 
  586         if (mp->mnt_flag & MNT_GETARGS) {
  587 
  588                 if (nmp == NULL)
  589                         return (EIO);
  590                 if (args.addr != NULL) {
  591                         sa = mtod(nmp->nm_nam, struct sockaddr *);
  592                         error = copyout(sa, args.addr, sa->sa_len);
  593                         if (error)
  594                                 return (error);
  595                         args.addrlen = sa->sa_len;
  596                 } else
  597                         args.addrlen = 0;
  598 
  599                 args.version = NFS_ARGSVERSION;
  600                 args.sotype = nmp->nm_sotype;
  601                 args.proto = nmp->nm_soproto;
  602                 args.fh = NULL;
  603                 args.fhsize = 0;
  604                 args.flags = nmp->nm_flag;
  605                 args.wsize = nmp->nm_wsize;
  606                 args.rsize = nmp->nm_rsize;
  607                 args.readdirsize = nmp->nm_readdirsize;
  608                 args.timeo = nmp->nm_timeo;
  609                 args.retrans = nmp->nm_retry;
  610                 args.maxgrouplist = nmp->nm_numgrps;
  611                 args.readahead = nmp->nm_readahead;
  612                 args.leaseterm = nmp->nm_leaseterm;
  613                 args.deadthresh = nmp->nm_deadthresh;
  614                 args.hostname = NULL;
  615                 return (copyout(&args, data, sizeof(args)));
  616         }
  617 
  618         if (args.version != NFS_ARGSVERSION)
  619                 return (EPROGMISMATCH);
  620 #ifdef NFS_V2_ONLY
  621         if (args.flags & NFSMNT_NQNFS)
  622                 return (EPROGUNAVAIL);
  623         if (args.flags & NFSMNT_NFSV3)
  624                 return (EPROGMISMATCH);
  625 #endif
  626         if (mp->mnt_flag & MNT_UPDATE) {
  627                 if (nmp == NULL)
  628                         return (EIO);
  629                 /*
  630                  * When doing an update, we can't change from or to
  631                  * v3 and/or nqnfs, or change cookie translation
  632                  */
  633                 args.flags = (args.flags &
  634                     ~(NFSMNT_NFSV3|NFSMNT_NQNFS|NFSMNT_XLATECOOKIE)) |
  635                     (nmp->nm_flag &
  636                         (NFSMNT_NFSV3|NFSMNT_NQNFS|NFSMNT_XLATECOOKIE));
  637                 nfs_decode_args(nmp, &args, p);
  638                 return (0);
  639         }
  640         if (args.fhsize < 0 || args.fhsize > NFSX_V3FHMAX)
  641                 return (EINVAL);
  642         MALLOC(nfh, u_char *, NFSX_V3FHMAX, M_TEMP, M_WAITOK);
  643         error = copyin((caddr_t)args.fh, (caddr_t)nfh, args.fhsize);
  644         if (error)
  645                 return (error);
  646         MALLOC(pth, char *, MNAMELEN, M_TEMP, M_WAITOK);
  647         error = copyinstr(path, pth, MNAMELEN - 1, &len);
  648         if (error)
  649                 goto free_nfh;
  650         memset(&pth[len], 0, MNAMELEN - len);
  651         MALLOC(hst, char *, MNAMELEN, M_TEMP, M_WAITOK);
  652         error = copyinstr(args.hostname, hst, MNAMELEN - 1, &len);
  653         if (error)
  654                 goto free_pth;
  655         memset(&hst[len], 0, MNAMELEN - len);
  656         /* sockargs() call must be after above copyin() calls */
  657         error = sockargs(&nam, (caddr_t)args.addr, args.addrlen, MT_SONAME);
  658         if (error)
  659                 goto free_hst;
  660         MCLAIM(nam, &nfs_mowner);
  661         args.fh = nfh;
  662         error = mountnfs(&args, mp, nam, pth, hst, &vp, p);
  663 
  664 free_hst:
  665         FREE(hst, M_TEMP);
  666 free_pth:
  667         FREE(pth, M_TEMP);
  668 free_nfh:
  669         FREE(nfh, M_TEMP);
  670 
  671         return (error);
  672 }
  673 
  674 /*
  675  * Common code for mount and mountroot
  676  */
  677 int
  678 mountnfs(argp, mp, nam, pth, hst, vpp, p)
  679         struct nfs_args *argp;
  680         struct mount *mp;
  681         struct mbuf *nam;
  682         const char *pth, *hst;
  683         struct vnode **vpp;
  684         struct proc *p;
  685 {
  686         struct nfsmount *nmp;
  687         struct nfsnode *np;
  688         int error;
  689         struct vattr *attrs;
  690         struct ucred *cr;
  691 
  692         /*
  693          * If the number of nfs iothreads to use has never
  694          * been set, create a reasonable number of them.
  695          */
  696 
  697         if (nfs_niothreads < 0) {
  698                 nfs_niothreads = NFS_DEFAULT_NIOTHREADS;
  699                 nfs_getset_niothreads(TRUE);
  700         }
  701 
  702         if (mp->mnt_flag & MNT_UPDATE) {
  703                 nmp = VFSTONFS(mp);
  704                 /* update paths, file handles, etc, here        XXX */
  705                 m_freem(nam);
  706                 return (0);
  707         } else {
  708                 MALLOC(nmp, struct nfsmount *, sizeof (struct nfsmount),
  709                     M_NFSMNT, M_WAITOK);
  710                 memset((caddr_t)nmp, 0, sizeof (struct nfsmount));
  711                 mp->mnt_data = nmp;
  712                 TAILQ_INIT(&nmp->nm_uidlruhead);
  713                 TAILQ_INIT(&nmp->nm_bufq);
  714                 lockinit(&nmp->nm_writeverflock, PRIBIO, "nfswverf", 0, 0);
  715                 simple_lock_init(&nmp->nm_slock);
  716         }
  717         vfs_getnewfsid(mp);
  718         nmp->nm_mountp = mp;
  719 
  720 #ifndef NFS_V2_ONLY
  721         if (argp->flags & NFSMNT_NQNFS)
  722                 mp->mnt_iflag |= IMNT_DTYPE;
  723 #endif
  724 
  725 #ifndef NFS_V2_ONLY
  726         if ((argp->flags & NFSMNT_NFSV3) == 0)
  727 #endif
  728                 /*
  729                  * V2 can only handle 32 bit filesizes. For v3, nfs_fsinfo
  730                  * will fill this in.
  731                  */
  732                 nmp->nm_maxfilesize = 0xffffffffLL;
  733 
  734         nmp->nm_timeo = NFS_TIMEO;
  735         nmp->nm_retry = NFS_RETRANS;
  736         nmp->nm_wsize = NFS_WSIZE;
  737         nmp->nm_rsize = NFS_RSIZE;
  738         nmp->nm_readdirsize = NFS_READDIRSIZE;
  739         nmp->nm_numgrps = NFS_MAXGRPS;
  740         nmp->nm_readahead = NFS_DEFRAHEAD;
  741         nmp->nm_leaseterm = NQ_DEFLEASE;
  742         nmp->nm_deadthresh = NQ_DEADTHRESH;
  743         CIRCLEQ_INIT(&nmp->nm_timerhead);
  744         nmp->nm_inprog = NULLVP;
  745         error = set_statvfs_info(pth, UIO_SYSSPACE, hst, UIO_SYSSPACE, mp, p);
  746         if (error)
  747                 goto bad;
  748         nmp->nm_nam = nam;
  749 
  750         /* Set up the sockets and per-host congestion */
  751         nmp->nm_sotype = argp->sotype;
  752         nmp->nm_soproto = argp->proto;
  753 
  754         nfs_decode_args(nmp, argp, p);
  755 
  756         mp->mnt_fs_bshift = ffs(MIN(nmp->nm_rsize, nmp->nm_wsize)) - 1;
  757         mp->mnt_dev_bshift = DEV_BSHIFT;
  758 
  759         /*
  760          * For Connection based sockets (TCP,...) defer the connect until
  761          * the first request, in case the server is not responding.
  762          */
  763         if (nmp->nm_sotype == SOCK_DGRAM &&
  764                 (error = nfs_connect(nmp, (struct nfsreq *)0, p)))
  765                 goto bad;
  766 
  767         /*
  768          * This is silly, but it has to be set so that vinifod() works.
  769          * We do not want to do an nfs_statvfs() here since we can get
  770          * stuck on a dead server and we are holding a lock on the mount
  771          * point.
  772          */
  773         mp->mnt_stat.f_iosize = NFS_MAXDGRAMDATA;
  774         error = nfs_nget(mp, (nfsfh_t *)argp->fh, argp->fhsize, &np);
  775         if (error)
  776                 goto bad;
  777         *vpp = NFSTOV(np);
  778         MALLOC(attrs, struct vattr *, sizeof(struct vattr), M_TEMP, M_WAITOK);
  779         VOP_GETATTR(*vpp, attrs, p->p_ucred, p);
  780         if ((nmp->nm_flag & NFSMNT_NFSV3) && ((*vpp)->v_type == VDIR)) {
  781                 cr = crget();
  782                 cr->cr_uid = attrs->va_uid;
  783                 cr->cr_gid = attrs->va_gid;
  784                 cr->cr_ngroups = 0;
  785                 nfs_cookieheuristic(*vpp, &nmp->nm_iflag, p, cr);
  786                 crfree(cr);
  787         }
  788         FREE(attrs, M_TEMP);
  789 
  790         /*
  791          * A reference count is needed on the nfsnode representing the
  792          * remote root.  If this object is not persistent, then backward
  793          * traversals of the mount point (i.e. "..") will not work if
  794          * the nfsnode gets flushed out of the cache. Ufs does not have
  795          * this problem, because one can identify root inodes by their
  796          * number == ROOTINO (2). So, just unlock, but no rele.
  797          */
  798 
  799         nmp->nm_vnode = *vpp;
  800         VOP_UNLOCK(*vpp, 0);
  801 
  802         return (0);
  803 bad:
  804         nfs_disconnect(nmp);
  805         free((caddr_t)nmp, M_NFSMNT);
  806         m_freem(nam);
  807         return (error);
  808 }
  809 
  810 /*
  811  * unmount system call
  812  */
  813 int
  814 nfs_unmount(mp, mntflags, p)
  815         struct mount *mp;
  816         int mntflags;
  817         struct proc *p;
  818 {
  819         struct nfsmount *nmp;
  820         struct vnode *vp;
  821         int error, flags = 0;
  822 
  823         if (mntflags & MNT_FORCE)
  824                 flags |= FORCECLOSE;
  825         nmp = VFSTONFS(mp);
  826         /*
  827          * Goes something like this..
  828          * - Check for activity on the root vnode (other than ourselves).
  829          * - Call vflush() to clear out vnodes for this file system,
  830          *   except for the root vnode.
  831          * - Decrement reference on the vnode representing remote root.
  832          * - Close the socket
  833          * - Free up the data structures
  834          */
  835         /*
  836          * We need to decrement the ref. count on the nfsnode representing
  837          * the remote root.  See comment in mountnfs().  The VFS unmount()
  838          * has done vput on this vnode, otherwise we would get deadlock!
  839          */
  840         vp = nmp->nm_vnode;
  841         error = vget(vp, LK_EXCLUSIVE | LK_RETRY);
  842         if (error != 0)
  843                 return error;
  844 
  845         if ((mntflags & MNT_FORCE) == 0 && vp->v_usecount > 2) {
  846                 vput(vp);
  847                 return (EBUSY);
  848         }
  849 
  850         /*
  851          * Must handshake with nqnfs_clientd() if it is active.
  852          */
  853         nmp->nm_iflag |= NFSMNT_DISMINPROG;
  854         while (nmp->nm_inprog != NULLVP)
  855                 (void) tsleep((caddr_t)&lbolt, PSOCK, "nfsdism", 0);
  856         error = vflush(mp, vp, flags);
  857         if (error) {
  858                 vput(vp);
  859                 nmp->nm_iflag &= ~NFSMNT_DISMINPROG;
  860                 return (error);
  861         }
  862 
  863         /*
  864          * We are now committed to the unmount; mark the mount structure
  865          * as doomed so that any sleepers kicked awake by nfs_disconnect
  866          * will go away cleanly.
  867          */
  868         nmp->nm_iflag |= NFSMNT_DISMNT;
  869 
  870         /*
  871          * There are two reference counts to get rid of here
  872          * (see comment in mountnfs()).
  873          */
  874         vrele(vp);
  875         vput(vp);
  876         vgone(vp);
  877         nfs_disconnect(nmp);
  878         m_freem(nmp->nm_nam);
  879 
  880         /*
  881          * For NQNFS, let the server daemon free the nfsmount structure.
  882          */
  883         if ((nmp->nm_flag & (NFSMNT_NQNFS | NFSMNT_KERB)) == 0)
  884                 free((caddr_t)nmp, M_NFSMNT);
  885         return (0);
  886 }
  887 
  888 /*
  889  * Return root of a filesystem
  890  */
  891 int
  892 nfs_root(mp, vpp)
  893         struct mount *mp;
  894         struct vnode **vpp;
  895 {
  896         struct vnode *vp;
  897         struct nfsmount *nmp;
  898         int error;
  899 
  900         nmp = VFSTONFS(mp);
  901         vp = nmp->nm_vnode;
  902         error = vget(vp, LK_EXCLUSIVE | LK_RETRY);
  903         if (error != 0)
  904                 return error;
  905         if (vp->v_type == VNON)
  906                 vp->v_type = VDIR;
  907         vp->v_flag = VROOT;
  908         *vpp = vp;
  909         return (0);
  910 }
  911 
  912 extern int syncprt;
  913 
  914 /*
  915  * Flush out the buffer cache
  916  */
  917 /* ARGSUSED */
  918 int
  919 nfs_sync(mp, waitfor, cred, p)
  920         struct mount *mp;
  921         int waitfor;
  922         struct ucred *cred;
  923         struct proc *p;
  924 {
  925         struct vnode *vp;
  926         int error, allerror = 0;
  927 
  928         /*
  929          * Force stale buffer cache information to be flushed.
  930          */
  931 loop:
  932         LIST_FOREACH(vp, &mp->mnt_vnodelist, v_mntvnodes) {
  933                 /*
  934                  * If the vnode that we are about to sync is no longer
  935                  * associated with this mount point, start over.
  936                  */
  937                 if (vp->v_mount != mp)
  938                         goto loop;
  939                 if (waitfor == MNT_LAZY || VOP_ISLOCKED(vp) ||
  940                     (LIST_EMPTY(&vp->v_dirtyblkhd) &&
  941                      vp->v_uobj.uo_npages == 0))
  942                         continue;
  943                 if (vget(vp, LK_EXCLUSIVE))
  944                         goto loop;
  945                 error = VOP_FSYNC(vp, cred,
  946                     waitfor == MNT_WAIT ? FSYNC_WAIT : 0, 0, 0, p);
  947                 if (error)
  948                         allerror = error;
  949                 vput(vp);
  950         }
  951         return (allerror);
  952 }
  953 
  954 /*
  955  * NFS flat namespace lookup.
  956  * Currently unsupported.
  957  */
  958 /* ARGSUSED */
  959 int
  960 nfs_vget(mp, ino, vpp)
  961         struct mount *mp;
  962         ino_t ino;
  963         struct vnode **vpp;
  964 {
  965 
  966         return (EOPNOTSUPP);
  967 }
  968 
  969 /*
  970  * Do that sysctl thang...
  971  */
  972 static int
  973 sysctl_vfs_nfs_iothreads(SYSCTLFN_ARGS)
  974 {
  975         int error;
  976 
  977         nfs_getset_niothreads(0);
  978         error = sysctl_lookup(SYSCTLFN_CALL(rnode));
  979         if (error || newp == NULL)
  980                 return (error);
  981         nfs_getset_niothreads(1);
  982 
  983         return (0);
  984 }
  985 
  986 SYSCTL_SETUP(sysctl_vfs_nfs_setup, "sysctl vfs.nfs subtree setup")
  987 {
  988 
  989         sysctl_createv(clog, 0, NULL, NULL,
  990                        CTLFLAG_PERMANENT,
  991                        CTLTYPE_NODE, "vfs", NULL,
  992                        NULL, 0, NULL, 0,
  993                        CTL_VFS, CTL_EOL);
  994         sysctl_createv(clog, 0, NULL, NULL,
  995                        CTLFLAG_PERMANENT,
  996                        CTLTYPE_NODE, "nfs",
  997                        SYSCTL_DESCR("NFS vfs options"),
  998                        NULL, 0, NULL, 0,
  999                        CTL_VFS, 2, CTL_EOL);
 1000         /*
 1001          * XXX the "2" above could be dynamic, thereby eliminating one
 1002          * more instance of the "number to vfs" mapping problem, but
 1003          * "2" is the order as taken from sys/mount.h
 1004          */
 1005 
 1006         sysctl_createv(clog, 0, NULL, NULL,
 1007                        CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
 1008                        CTLTYPE_STRUCT, "nfsstats",
 1009                        SYSCTL_DESCR("NFS operation statistics"),
 1010                        NULL, 0, &nfsstats, sizeof(nfsstats),
 1011                        CTL_VFS, 2, NFS_NFSSTATS, CTL_EOL);
 1012         sysctl_createv(clog, 0, NULL, NULL,
 1013                        CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
 1014                        CTLTYPE_INT, "iothreads",
 1015                        SYSCTL_DESCR("Number of NFS client processes desired"),
 1016                        sysctl_vfs_nfs_iothreads, 0, &nfs_niothreads, 0,
 1017                        CTL_VFS, 2, NFS_IOTHREADS, CTL_EOL);
 1018 }
 1019 
 1020 /*
 1021  * At this point, this should never happen
 1022  */
 1023 /* ARGSUSED */
 1024 int
 1025 nfs_fhtovp(mp, fhp, vpp)
 1026         struct mount *mp;
 1027         struct fid *fhp;
 1028         struct vnode **vpp;
 1029 {
 1030 
 1031         return (EINVAL);
 1032 }
 1033 
 1034 /* ARGSUSED */
 1035 int
 1036 nfs_checkexp(mp, nam, exflagsp, credanonp)
 1037         struct mount *mp;
 1038         struct mbuf *nam;
 1039         int *exflagsp;
 1040         struct ucred **credanonp;
 1041 {
 1042 
 1043         return (EINVAL);
 1044 }
 1045 
 1046 /*
 1047  * Vnode pointer to File handle, should never happen either
 1048  */
 1049 /* ARGSUSED */
 1050 int
 1051 nfs_vptofh(vp, fhp)
 1052         struct vnode *vp;
 1053         struct fid *fhp;
 1054 {
 1055 
 1056         return (EINVAL);
 1057 }
 1058 
 1059 /*
 1060  * Vfs start routine, a no-op.
 1061  */
 1062 /* ARGSUSED */
 1063 int
 1064 nfs_start(mp, flags, p)
 1065         struct mount *mp;
 1066         int flags;
 1067         struct proc *p;
 1068 {
 1069 
 1070         return (0);
 1071 }
 1072 
 1073 /*
 1074  * Do operations associated with quotas, not supported
 1075  */
 1076 /* ARGSUSED */
 1077 int
 1078 nfs_quotactl(mp, cmd, uid, arg, p)
 1079         struct mount *mp;
 1080         int cmd;
 1081         uid_t uid;
 1082         void *arg;
 1083         struct proc *p;
 1084 {
 1085 
 1086         return (EOPNOTSUPP);
 1087 }

Cache object: 84bf3866c320638289566705415d2e33


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