root/nfs/nfs_vfsops.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. nfs_statfs
  2. nfs_fsinfo
  3. nfs_mountroot
  4. nfs_mount_diskless
  5. nfs_decode_args
  6. nfs_mount
  7. mountnfs
  8. nfs_unmount
  9. nfs_root
  10. nfs_sync
  11. nfs_vget
  12. nfs_sysctl
  13. nfs_fhtovp
  14. nfs_vptofh
  15. nfs_start
  16. nfs_quotactl
  17. nfs_checkexp

    1 /*      $OpenBSD: nfs_vfsops.c,v 1.66 2007/06/20 15:00:43 thib Exp $    */
    2 /*      $NetBSD: nfs_vfsops.c,v 1.46.4.1 1996/05/25 22:40:35 fvdl Exp $ */
    3 
    4 /*
    5  * Copyright (c) 1989, 1993, 1995
    6  *      The Regents of the University of California.  All rights reserved.
    7  *
    8  * This code is derived from software contributed to Berkeley by
    9  * Rick Macklem at The University of Guelph.
   10  *
   11  * Redistribution and use in source and binary forms, with or without
   12  * modification, are permitted provided that the following conditions
   13  * are met:
   14  * 1. Redistributions of source code must retain the above copyright
   15  *    notice, this list of conditions and the following disclaimer.
   16  * 2. Redistributions in binary form must reproduce the above copyright
   17  *    notice, this list of conditions and the following disclaimer in the
   18  *    documentation and/or other materials provided with the distribution.
   19  * 3. Neither the name of the University nor the names of its contributors
   20  *    may be used to endorse or promote products derived from this software
   21  *    without specific prior written permission.
   22  *
   23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   33  * SUCH DAMAGE.
   34  *
   35  *      @(#)nfs_vfsops.c        8.12 (Berkeley) 5/20/95
   36  */
   37 
   38 #include <sys/param.h>
   39 #include <sys/conf.h>
   40 #include <sys/ioctl.h>
   41 #include <sys/signal.h>
   42 #include <sys/proc.h>
   43 #include <sys/namei.h>
   44 #include <sys/vnode.h>
   45 #include <sys/kernel.h>
   46 #include <sys/mount.h>
   47 #include <sys/buf.h>
   48 #include <sys/mbuf.h>
   49 #include <sys/socket.h>
   50 #include <sys/socketvar.h>
   51 #include <sys/systm.h>
   52 #include <sys/sysctl.h>
   53 
   54 #include <net/if.h>
   55 #include <net/route.h>
   56 #include <netinet/in.h>
   57 
   58 #include <nfs/rpcv2.h>
   59 #include <nfs/nfsproto.h>
   60 #include <nfs/nfsnode.h>
   61 #include <nfs/nfs.h>
   62 #include <nfs/nfsmount.h>
   63 #include <nfs/xdr_subs.h>
   64 #include <nfs/nfsm_subs.h>
   65 #include <nfs/nfsdiskless.h>
   66 #include <nfs/nfs_var.h>
   67 
   68 #define NQ_DEADTHRESH   NQ_NEVERDEAD    /* Default nm_deadthresh */
   69 #define NQ_NEVERDEAD    9       /* Greater than max. nm_timeouts */
   70 
   71 extern struct nfsstats nfsstats;
   72 extern int nfs_ticks;
   73 extern u_int32_t nfs_procids[NFS_NPROCS];
   74 
   75 int             nfs_sysctl(int *, u_int, void *, size_t *, void *, size_t, struct proc *);
   76 int             nfs_checkexp(struct mount *, struct mbuf *, int *, struct ucred **);
   77 struct mount    *nfs_mount_diskless(struct nfs_dlmount *, char *, int);
   78 
   79 /*
   80  * nfs vfs operations.
   81  */
   82 const struct vfsops nfs_vfsops = {
   83         nfs_mount,
   84         nfs_start,
   85         nfs_unmount,
   86         nfs_root,
   87         nfs_quotactl,
   88         nfs_statfs,
   89         nfs_sync,
   90         nfs_vget,
   91         nfs_fhtovp,
   92         nfs_vptofh,
   93         nfs_vfs_init,
   94         nfs_sysctl,
   95         nfs_checkexp
   96 };
   97 
   98 #define TRUE    1
   99 #define FALSE   0
  100 
  101 /*
  102  * nfs statfs call
  103  */
  104 int
  105 nfs_statfs(mp, sbp, p)
  106         struct mount *mp;
  107         struct statfs *sbp;
  108         struct proc *p;
  109 {
  110         struct vnode *vp;
  111         struct nfs_statfs *sfp = NULL;
  112         caddr_t cp;
  113         u_int32_t *tl;
  114         int32_t t1, t2;
  115         caddr_t bpos, dpos, cp2;
  116         struct nfsmount *nmp = VFSTONFS(mp);
  117         int error = 0, v3 = (nmp->nm_flag & NFSMNT_NFSV3), retattr;
  118         struct mbuf *mreq, *mrep = NULL, *md, *mb, *mb2;
  119         struct ucred *cred;
  120         struct nfsnode *np;
  121         u_quad_t tquad;
  122 
  123         error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np);
  124         if (error)
  125                 return (error);
  126         vp = NFSTOV(np);
  127         cred = crget();
  128         cred->cr_ngroups = 0;
  129         if (v3 && (nmp->nm_flag & NFSMNT_GOTFSINFO) == 0)
  130                 (void)nfs_fsinfo(nmp, vp, cred, p);
  131         nfsstats.rpccnt[NFSPROC_FSSTAT]++;
  132         nfsm_reqhead(vp, NFSPROC_FSSTAT, NFSX_FH(v3));
  133         nfsm_fhtom(vp, v3);
  134         nfsm_request(vp, NFSPROC_FSSTAT, p, cred);
  135         if (v3)
  136                 nfsm_postop_attr(vp, retattr);
  137         if (error) {
  138                 if (mrep != NULL)
  139                         m_free(mrep);
  140                 goto nfsmout;
  141         }
  142         nfsm_dissect(sfp, struct nfs_statfs *, NFSX_STATFS(v3));
  143         sbp->f_flags = nmp->nm_flag;
  144         sbp->f_iosize = min(nmp->nm_rsize, nmp->nm_wsize);
  145         if (v3) {
  146                 sbp->f_bsize = NFS_FABLKSIZE;
  147                 tquad = fxdr_hyper(&sfp->sf_tbytes);
  148                 sbp->f_blocks = (u_int32_t)(tquad / (u_quad_t)NFS_FABLKSIZE);
  149                 tquad = fxdr_hyper(&sfp->sf_fbytes);
  150                 sbp->f_bfree = (u_int32_t)(tquad / (u_quad_t)NFS_FABLKSIZE);
  151                 tquad = fxdr_hyper(&sfp->sf_abytes);
  152                 sbp->f_bavail = (int32_t)((quad_t)tquad / (quad_t)NFS_FABLKSIZE);
  153                 sbp->f_files = (fxdr_unsigned(int32_t,
  154                     sfp->sf_tfiles.nfsuquad[1]) & 0x7fffffff);
  155                 sbp->f_ffree = (fxdr_unsigned(int32_t,
  156                     sfp->sf_ffiles.nfsuquad[1]) & 0x7fffffff);
  157         } else {
  158                 sbp->f_bsize = fxdr_unsigned(int32_t, sfp->sf_bsize);
  159                 sbp->f_blocks = fxdr_unsigned(int32_t, sfp->sf_blocks);
  160                 sbp->f_bfree = fxdr_unsigned(int32_t, sfp->sf_bfree);
  161                 sbp->f_bavail = fxdr_unsigned(int32_t, sfp->sf_bavail);
  162                 sbp->f_files = 0;
  163                 sbp->f_ffree = 0;
  164         }
  165         if (sbp != &mp->mnt_stat) {
  166                 bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
  167                 bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
  168                 bcopy(&mp->mnt_stat.mount_info.nfs_args,
  169                     &sbp->mount_info.nfs_args, sizeof(struct nfs_args));
  170         }
  171         strncpy(&sbp->f_fstypename[0], mp->mnt_vfc->vfc_name, MFSNAMELEN);
  172         nfsm_reqdone;
  173         vrele(vp);
  174         crfree(cred);
  175         return (error);
  176 }
  177 
  178 /*
  179  * nfs version 3 fsinfo rpc call
  180  */
  181 int
  182 nfs_fsinfo(nmp, vp, cred, p)
  183         struct nfsmount *nmp;
  184         struct vnode *vp;
  185         struct ucred *cred;
  186         struct proc *p;
  187 {
  188         struct nfsv3_fsinfo *fsp;
  189         caddr_t cp;
  190         int32_t t1, t2;
  191         u_int32_t *tl, pref, max;
  192         caddr_t bpos, dpos, cp2;
  193         int error = 0, retattr;
  194         struct mbuf *mreq, *mrep, *md, *mb, *mb2;
  195 
  196         nfsstats.rpccnt[NFSPROC_FSINFO]++;
  197         nfsm_reqhead(vp, NFSPROC_FSINFO, NFSX_FH(1));
  198         nfsm_fhtom(vp, 1);
  199         nfsm_request(vp, NFSPROC_FSINFO, p, cred);
  200         nfsm_postop_attr(vp, retattr);
  201         if (!error) {
  202                 nfsm_dissect(fsp, struct nfsv3_fsinfo *, NFSX_V3FSINFO);
  203                 pref = fxdr_unsigned(u_int32_t, fsp->fs_wtpref);
  204                 if (pref < nmp->nm_wsize)
  205                         nmp->nm_wsize = (pref + NFS_FABLKSIZE - 1) &
  206                                 ~(NFS_FABLKSIZE - 1);
  207                 max = fxdr_unsigned(u_int32_t, fsp->fs_wtmax);
  208                 if (max < nmp->nm_wsize) {
  209                         nmp->nm_wsize = max & ~(NFS_FABLKSIZE - 1);
  210                         if (nmp->nm_wsize == 0)
  211                                 nmp->nm_wsize = max;
  212                 }
  213                 pref = fxdr_unsigned(u_int32_t, fsp->fs_rtpref);
  214                 if (pref < nmp->nm_rsize)
  215                         nmp->nm_rsize = (pref + NFS_FABLKSIZE - 1) &
  216                                 ~(NFS_FABLKSIZE - 1);
  217                 max = fxdr_unsigned(u_int32_t, fsp->fs_rtmax);
  218                 if (max < nmp->nm_rsize) {
  219                         nmp->nm_rsize = max & ~(NFS_FABLKSIZE - 1);
  220                         if (nmp->nm_rsize == 0)
  221                                 nmp->nm_rsize = max;
  222                 }
  223                 pref = fxdr_unsigned(u_int32_t, fsp->fs_dtpref);
  224                 if (pref < nmp->nm_readdirsize)
  225                         nmp->nm_readdirsize = (pref + NFS_DIRBLKSIZ - 1) &
  226                                 ~(NFS_DIRBLKSIZ - 1);
  227                 if (max < nmp->nm_readdirsize) {
  228                         nmp->nm_readdirsize = max & ~(NFS_DIRBLKSIZ - 1);
  229                         if (nmp->nm_readdirsize == 0)
  230                                 nmp->nm_readdirsize = max;
  231                 }
  232                 nmp->nm_flag |= NFSMNT_GOTFSINFO;
  233         }
  234         nfsm_reqdone;
  235         return (error);
  236 }
  237 
  238 /*
  239  * Mount a remote root fs via. NFS.  It goes like this:
  240  * - Call nfs_boot_init() to fill in the nfs_diskless struct
  241  *   (using RARP, bootparam RPC, mountd RPC)
  242  * - hand craft the swap nfs vnode hanging off a fake mount point
  243  *      if swdevt[0].sw_dev == NODEV
  244  * - build the rootfs mount point and call mountnfs() to do the rest.
  245  */
  246 int
  247 nfs_mountroot()
  248 {
  249         struct nfs_diskless nd;
  250         struct vattr attr;
  251         struct mount *mp;
  252         struct vnode *vp;
  253         struct proc *procp;
  254         long n;
  255         int error;
  256 
  257         procp = curproc; /* XXX */
  258 
  259         /*
  260          * Call nfs_boot_init() to fill in the nfs_diskless struct.
  261          * Side effect:  Finds and configures a network interface.
  262          */
  263         bzero((caddr_t) &nd, sizeof(nd));
  264         nfs_boot_init(&nd, procp);
  265 
  266         /*
  267          * Create the root mount point.
  268          */
  269         if (nfs_boot_getfh(&nd.nd_boot, "root", &nd.nd_root, -1))
  270                 panic("nfs_mountroot: root");
  271         mp = nfs_mount_diskless(&nd.nd_root, "/", 0);
  272         nfs_root(mp, &rootvp);
  273         printf("root on %s\n", nd.nd_root.ndm_host);
  274 
  275         /*
  276          * Link it into the mount list.
  277          */
  278         CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
  279         vfs_unbusy(mp);
  280 
  281         /* Get root attributes (for the time). */
  282         error = VOP_GETATTR(rootvp, &attr, procp->p_ucred, procp);
  283         if (error) panic("nfs_mountroot: getattr for root");
  284         n = attr.va_atime.tv_sec;
  285 #ifdef  DEBUG
  286         printf("root time: 0x%lx\n", n);
  287 #endif
  288         inittodr(n);
  289 
  290 #ifdef notyet
  291         /* Set up swap credentials. */
  292         proc0.p_ucred->cr_uid = ntohl(nd.swap_ucred.cr_uid);
  293         proc0.p_ucred->cr_gid = ntohl(nd.swap_ucred.cr_gid);
  294         if ((proc0.p_ucred->cr_ngroups = ntohs(nd.swap_ucred.cr_ngroups)) >
  295                 NGROUPS)
  296                 proc0.p_ucred->cr_ngroups = NGROUPS;
  297         for (i = 0; i < proc0.p_ucred->cr_ngroups; i++)
  298             proc0.p_ucred->cr_groups[i] = ntohl(nd.swap_ucred.cr_groups[i]);
  299 #endif
  300 
  301         /*
  302          * "Mount" the swap device.
  303          *
  304          * On a "dataless" configuration (swap on disk) we will have:
  305          *      (swdevt[0].sw_dev != NODEV) identifying the swap device.
  306          */
  307         if (bdevvp(swapdev, &swapdev_vp))
  308                 panic("nfs_mountroot: can't setup swap vp");
  309         if (swdevt[0].sw_dev != NODEV) {
  310                 printf("swap on device 0x%x\n", swdevt[0].sw_dev);
  311                 return (0);
  312         }
  313 
  314         /*
  315          * If swapping to an nfs node:  (swdevt[0].sw_dev == NODEV)
  316          * Create a fake mount point just for the swap vnode so that the
  317          * swap file can be on a different server from the rootfs.
  318          *
  319          * Wait 5 retries, finally no swap is cool. -mickey
  320          */
  321         error = nfs_boot_getfh(&nd.nd_boot, "swap", &nd.nd_swap, 5);
  322         if (!error) {
  323                 mp = nfs_mount_diskless(&nd.nd_swap, "/swap", 0);
  324                 nfs_root(mp, &vp);
  325                 vfs_unbusy(mp);
  326 
  327                 /*
  328                  * Since the swap file is not the root dir of a file system,
  329                  * hack it to a regular file.
  330                  */
  331                 vp->v_type = VREG;
  332                 vp->v_flag = 0;
  333 
  334                 /* 
  335                  * Next line is a hack to make swapmount() work on NFS swap files. 
  336                  * XXX-smurph 
  337                  */ 
  338                 swdevt[0].sw_dev = NETDEV;
  339                 /* end hack */
  340                 swdevt[0].sw_vp = vp;
  341 
  342                 /*
  343                  * Find out how large the swap file is.
  344                  */
  345                 error = VOP_GETATTR(vp, &attr, procp->p_ucred, procp);
  346                 if (error)
  347                         printf("nfs_mountroot: getattr for swap\n");
  348                 n = (long) (attr.va_size >> DEV_BSHIFT);
  349 
  350                 printf("swap on %s\n", nd.nd_swap.ndm_host);
  351 #ifdef  DEBUG
  352                 printf("swap size: 0x%lx (blocks)\n", n);
  353 #endif
  354                 return (0);
  355         }
  356 
  357         printf("WARNING: no swap\n");
  358         swdevt[0].sw_dev = NODEV;
  359         swdevt[0].sw_vp = NULL;
  360 
  361         return (0);
  362 }
  363 
  364 /*
  365  * Internal version of mount system call for diskless setup.
  366  */
  367 struct mount *
  368 nfs_mount_diskless(ndmntp, mntname, mntflag)
  369         struct nfs_dlmount *ndmntp;
  370         char *mntname;
  371         int mntflag;
  372 {
  373         struct nfs_args args;
  374         struct mount *mp;
  375         struct mbuf *m;
  376         int error;
  377 
  378         if (vfs_rootmountalloc("nfs", mntname, &mp))
  379                 panic("nfs_mount_diskless: vfs_rootmountalloc failed");
  380         mp->mnt_flag |= mntflag;
  381 
  382         /* Initialize mount args. */
  383         bzero((caddr_t) &args, sizeof(args));
  384         args.addr     = (struct sockaddr *)&ndmntp->ndm_saddr;
  385         args.addrlen  = args.addr->sa_len;
  386         args.sotype   = SOCK_DGRAM;
  387         args.fh       = ndmntp->ndm_fh;
  388         args.fhsize   = NFSX_V2FH;
  389         args.hostname = ndmntp->ndm_host;
  390 
  391 #ifdef  NFS_BOOT_OPTIONS
  392         args.flags    |= NFS_BOOT_OPTIONS;
  393 #endif
  394 #ifdef  NFS_BOOT_RWSIZE
  395         /*
  396          * Reduce rsize,wsize for interfaces that consistently
  397          * drop fragments of long UDP messages.  (i.e. wd8003).
  398          * You can always change these later via remount.
  399          */
  400         args.flags   |= NFSMNT_WSIZE | NFSMNT_RSIZE;
  401         args.wsize    = NFS_BOOT_RWSIZE;
  402         args.rsize    = NFS_BOOT_RWSIZE;
  403 #endif
  404 
  405         /* Get mbuf for server sockaddr. */
  406         m = m_get(M_WAIT, MT_SONAME);
  407         bcopy((caddr_t)args.addr, mtod(m, caddr_t),
  408             (m->m_len = args.addr->sa_len));
  409 
  410         error = mountnfs(&args, mp, m, mntname, args.hostname);
  411         if (error)
  412                 panic("nfs_mountroot: mount %s failed: %d", mntname, error);
  413 
  414         return (mp);
  415 }
  416 
  417 void
  418 nfs_decode_args(nmp, argp, nargp)
  419         struct nfsmount *nmp;
  420         struct nfs_args *argp;
  421         struct nfs_args *nargp;
  422 {
  423         int s;
  424         int adjsock = 0;
  425         int maxio;
  426 
  427         s = splsoftnet();
  428 
  429 #if 0
  430         /* Re-bind if rsrvd port requested and wasn't on one */
  431         adjsock = !(nmp->nm_flag & NFSMNT_RESVPORT)
  432                   && (argp->flags & NFSMNT_RESVPORT);
  433 #endif
  434         /* Also re-bind if we're switching to/from a connected UDP socket */
  435         adjsock |= ((nmp->nm_flag & NFSMNT_NOCONN) !=
  436             (argp->flags & NFSMNT_NOCONN));
  437 
  438         /* Update flags atomically.  Don't change the lock bits. */
  439         nmp->nm_flag =
  440             (argp->flags & ~NFSMNT_INTERNAL) | (nmp->nm_flag & NFSMNT_INTERNAL);
  441         splx(s);
  442 
  443         if ((argp->flags & NFSMNT_TIMEO) && argp->timeo > 0) {
  444                 nmp->nm_timeo = (argp->timeo * NFS_HZ + 5) / 10;
  445                 if (nmp->nm_timeo < NFS_MINTIMEO)
  446                         nmp->nm_timeo = NFS_MINTIMEO;
  447                 else if (nmp->nm_timeo > NFS_MAXTIMEO)
  448                         nmp->nm_timeo = NFS_MAXTIMEO;
  449         }
  450 
  451         if ((argp->flags & NFSMNT_RETRANS) && argp->retrans > 1) {
  452                 nmp->nm_retry = argp->retrans;
  453                 if (nmp->nm_retry > NFS_MAXREXMIT)
  454                         nmp->nm_retry = NFS_MAXREXMIT;
  455         }
  456 
  457         if (argp->flags & NFSMNT_NFSV3) {
  458                 if (argp->sotype == SOCK_DGRAM)
  459                         maxio = NFS_MAXDGRAMDATA;
  460                 else
  461                         maxio = NFS_MAXDATA;
  462         } else
  463                 maxio = NFS_V2MAXDATA;
  464 
  465         if ((argp->flags & NFSMNT_WSIZE) && argp->wsize > 0) {
  466                 int osize = nmp->nm_wsize;
  467                 nmp->nm_wsize = argp->wsize;
  468                 /* Round down to multiple of blocksize */
  469                 nmp->nm_wsize &= ~(NFS_FABLKSIZE - 1);
  470                 if (nmp->nm_wsize <= 0)
  471                         nmp->nm_wsize = NFS_FABLKSIZE;
  472                 adjsock |= (nmp->nm_wsize != osize);
  473         }
  474         if (nmp->nm_wsize > maxio)
  475                 nmp->nm_wsize = maxio;
  476         if (nmp->nm_wsize > MAXBSIZE)
  477                 nmp->nm_wsize = MAXBSIZE;
  478 
  479         if ((argp->flags & NFSMNT_RSIZE) && argp->rsize > 0) {
  480                 int osize = nmp->nm_rsize;
  481                 nmp->nm_rsize = argp->rsize;
  482                 /* Round down to multiple of blocksize */
  483                 nmp->nm_rsize &= ~(NFS_FABLKSIZE - 1);
  484                 if (nmp->nm_rsize <= 0)
  485                         nmp->nm_rsize = NFS_FABLKSIZE;
  486                 adjsock |= (nmp->nm_rsize != osize);
  487         }
  488         if (nmp->nm_rsize > maxio)
  489                 nmp->nm_rsize = maxio;
  490         if (nmp->nm_rsize > MAXBSIZE)
  491                 nmp->nm_rsize = MAXBSIZE;
  492 
  493         if ((argp->flags & NFSMNT_READDIRSIZE) && argp->readdirsize > 0) {
  494                 nmp->nm_readdirsize = argp->readdirsize;
  495                 /* Round down to multiple of blocksize */
  496                 nmp->nm_readdirsize &= ~(NFS_DIRBLKSIZ - 1);
  497                 if (nmp->nm_readdirsize < NFS_DIRBLKSIZ)
  498                         nmp->nm_readdirsize = NFS_DIRBLKSIZ;
  499         } else if (argp->flags & NFSMNT_RSIZE)
  500                 nmp->nm_readdirsize = nmp->nm_rsize;
  501 
  502         if (nmp->nm_readdirsize > maxio)
  503                 nmp->nm_readdirsize = maxio;
  504 
  505         if ((argp->flags & NFSMNT_MAXGRPS) && argp->maxgrouplist >= 0 &&
  506                 argp->maxgrouplist <= NFS_MAXGRPS)
  507                 nmp->nm_numgrps = argp->maxgrouplist;
  508         if ((argp->flags & NFSMNT_READAHEAD) && argp->readahead >= 0 &&
  509                 argp->readahead <= NFS_MAXRAHEAD)
  510                 nmp->nm_readahead = argp->readahead;
  511         if ((argp->flags & NFSMNT_DEADTHRESH) && argp->deadthresh >= 1 &&
  512                 argp->deadthresh <= NQ_NEVERDEAD)
  513                 nmp->nm_deadthresh = argp->deadthresh;
  514         if (argp->flags & NFSMNT_ACREGMIN && argp->acregmin >= 0) {
  515                 if (argp->acregmin > 0xffff)
  516                         nmp->nm_acregmin = 0xffff;
  517                 else
  518                         nmp->nm_acregmin = argp->acregmin;
  519         }
  520         if (argp->flags & NFSMNT_ACREGMAX && argp->acregmax >= 0) {
  521                 if (argp->acregmax > 0xffff)
  522                         nmp->nm_acregmax = 0xffff;
  523                 else
  524                         nmp->nm_acregmax = argp->acregmax;
  525         }
  526         if (nmp->nm_acregmin > nmp->nm_acregmax)
  527           nmp->nm_acregmin = nmp->nm_acregmax;
  528 
  529         if (argp->flags & NFSMNT_ACDIRMIN && argp->acdirmin >= 0) {
  530                 if (argp->acdirmin > 0xffff)
  531                         nmp->nm_acdirmin = 0xffff;
  532                 else
  533                         nmp->nm_acdirmin = argp->acdirmin;
  534         }
  535         if (argp->flags & NFSMNT_ACDIRMAX && argp->acdirmax >= 0) {
  536                 if (argp->acdirmax > 0xffff)
  537                         nmp->nm_acdirmax = 0xffff;
  538                 else
  539                         nmp->nm_acdirmax = argp->acdirmax;
  540         }
  541         if (nmp->nm_acdirmin > nmp->nm_acdirmax)
  542           nmp->nm_acdirmin = nmp->nm_acdirmax;
  543 
  544         if (nmp->nm_so && adjsock) {
  545                 nfs_disconnect(nmp);
  546                 if (nmp->nm_sotype == SOCK_DGRAM)
  547                         while (nfs_connect(nmp, (struct nfsreq *)0)) {
  548                                 printf("nfs_args: retrying connect\n");
  549                                 (void) tsleep((caddr_t)&lbolt,
  550                                               PSOCK, "nfscon", 0);
  551                         }
  552         }
  553 
  554         /* Update nargp based on nmp */
  555         nargp->wsize = nmp->nm_wsize;
  556         nargp->rsize = nmp->nm_rsize;
  557         nargp->readdirsize = nmp->nm_readdirsize;
  558         nargp->timeo = nmp->nm_timeo;
  559         nargp->retrans = nmp->nm_retry;
  560         nargp->maxgrouplist = nmp->nm_numgrps;
  561         nargp->readahead = nmp->nm_readahead;
  562         nargp->deadthresh = nmp->nm_deadthresh;
  563         nargp->acregmin = nmp->nm_acregmin;
  564         nargp->acregmax = nmp->nm_acregmax;
  565         nargp->acdirmin = nmp->nm_acdirmin;
  566         nargp->acdirmax = nmp->nm_acdirmax;
  567 }
  568 
  569 /*
  570  * VFS Operations.
  571  *
  572  * mount system call
  573  * It seems a bit dumb to copyinstr() the host and path here and then
  574  * bcopy() them in mountnfs(), but I wanted to detect errors before
  575  * doing the sockargs() call because sockargs() allocates an mbuf and
  576  * an error after that means that I have to release the mbuf.
  577  */
  578 /* ARGSUSED */
  579 int
  580 nfs_mount(mp, path, data, ndp, p)
  581         struct mount *mp;
  582         const char *path;
  583         void *data;
  584         struct nameidata *ndp;
  585         struct proc *p;
  586 {
  587         int error;
  588         struct nfs_args args;
  589         struct mbuf *nam;
  590         char pth[MNAMELEN], hst[MNAMELEN];
  591         size_t len;
  592         u_char nfh[NFSX_V3FHMAX];
  593 
  594         error = copyin (data, &args, sizeof (args.version));
  595         if (error)
  596                 return (error);
  597         if (args.version == 3) {
  598                 error = copyin (data, (caddr_t)&args,
  599                                 sizeof (struct nfs_args3));
  600                 args.flags &= ~(NFSMNT_INTERNAL|NFSMNT_NOAC);
  601         }
  602         else if (args.version == NFS_ARGSVERSION) {
  603                 error = copyin(data, (caddr_t)&args, sizeof (struct nfs_args));
  604                 args.flags &= ~NFSMNT_NOAC; /* XXX - compatibility */
  605         }
  606         else
  607                 return (EPROGMISMATCH);
  608         if (error)
  609                 return (error);
  610 
  611         if ((args.flags & (NFSMNT_NFSV3|NFSMNT_RDIRPLUS)) == NFSMNT_RDIRPLUS)
  612                 return (EINVAL);
  613 
  614         if (nfs_niothreads < 0) {
  615                 nfs_niothreads = 4;
  616                 nfs_getset_niothreads(TRUE);
  617         }
  618 
  619         if (mp->mnt_flag & MNT_UPDATE) {
  620                 struct nfsmount *nmp = VFSTONFS(mp);
  621 
  622                 if (nmp == NULL)
  623                         return (EIO);
  624                 /*
  625                  * When doing an update, we can't change from or to
  626                  * v3.
  627                  */
  628                 args.flags = (args.flags & ~(NFSMNT_NFSV3)) |
  629                     (nmp->nm_flag & (NFSMNT_NFSV3));
  630                 nfs_decode_args(nmp, &args, &mp->mnt_stat.mount_info.nfs_args);
  631                 return (0);
  632         }
  633         if (args.fhsize < 0 || args.fhsize > NFSX_V3FHMAX)
  634                 return (EINVAL);
  635         error = copyin((caddr_t)args.fh, (caddr_t)nfh, args.fhsize);
  636         if (error)
  637                 return (error);
  638         error = copyinstr(path, pth, MNAMELEN-1, &len);
  639         if (error)
  640                 return (error);
  641         bzero(&pth[len], MNAMELEN - len);
  642         error = copyinstr(args.hostname, hst, MNAMELEN-1, &len);
  643         if (error)
  644                 return (error);
  645         bzero(&hst[len], MNAMELEN - len);
  646         /* sockargs() call must be after above copyin() calls */
  647         error = sockargs(&nam, args.addr, args.addrlen, MT_SONAME);
  648         if (error)
  649                 return (error);
  650         args.fh = nfh;
  651         error = mountnfs(&args, mp, nam, pth, hst);
  652         return (error);
  653 }
  654 
  655 /*
  656  * Common code for mount and mountroot
  657  */
  658 int
  659 mountnfs(argp, mp, nam, pth, hst)
  660         struct nfs_args *argp;
  661         struct mount *mp;
  662         struct mbuf *nam;
  663         char *pth, *hst;
  664 {
  665         struct nfsmount *nmp;
  666         int error;
  667 
  668         if (mp->mnt_flag & MNT_UPDATE) {
  669                 nmp = VFSTONFS(mp);
  670                 /* update paths, file handles, etc, here        XXX */
  671                 m_freem(nam);
  672                 return (0);
  673         } else {
  674                 MALLOC(nmp, struct nfsmount *, sizeof (struct nfsmount),
  675                     M_NFSMNT, M_WAITOK);
  676                 bzero((caddr_t)nmp, sizeof (struct nfsmount));
  677                 mp->mnt_data = (qaddr_t)nmp;
  678                 TAILQ_INIT(&nmp->nm_uidlruhead);
  679         }
  680 
  681         vfs_getnewfsid(mp);
  682         nmp->nm_mountp = mp;
  683         nmp->nm_timeo = NFS_TIMEO;
  684         nmp->nm_retry = NFS_RETRANS;
  685         nmp->nm_wsize = NFS_WSIZE;
  686         nmp->nm_rsize = NFS_RSIZE;
  687         nmp->nm_readdirsize = NFS_READDIRSIZE;
  688         nmp->nm_numgrps = NFS_MAXGRPS;
  689         nmp->nm_readahead = NFS_DEFRAHEAD;
  690         nmp->nm_deadthresh = NQ_DEADTHRESH;
  691         nmp->nm_fhsize = argp->fhsize;
  692         nmp->nm_acregmin = NFS_MINATTRTIMO;
  693         nmp->nm_acregmax = NFS_MAXATTRTIMO;
  694         nmp->nm_acdirmin = NFS_MINATTRTIMO;
  695         nmp->nm_acdirmax = NFS_MAXATTRTIMO;
  696         bcopy((caddr_t)argp->fh, (caddr_t)nmp->nm_fh, argp->fhsize);
  697         strncpy(&mp->mnt_stat.f_fstypename[0], mp->mnt_vfc->vfc_name, MFSNAMELEN);
  698         bcopy(hst, mp->mnt_stat.f_mntfromname, MNAMELEN);
  699         bcopy(pth, mp->mnt_stat.f_mntonname, MNAMELEN);
  700         bcopy(argp, &mp->mnt_stat.mount_info.nfs_args, sizeof(*argp));
  701         nmp->nm_nam = nam;
  702         nfs_decode_args(nmp, argp, &mp->mnt_stat.mount_info.nfs_args);
  703 
  704         /* Set up the sockets and per-host congestion */
  705         nmp->nm_sotype = argp->sotype;
  706         nmp->nm_soproto = argp->proto;
  707 
  708         /*
  709          * For Connection based sockets (TCP,...) defer the connect until
  710          * the first request, in case the server is not responding.
  711          */
  712         if (nmp->nm_sotype == SOCK_DGRAM &&
  713             (error = nfs_connect(nmp, (struct nfsreq *)0)))
  714                 goto bad;
  715 
  716         /*
  717          * This is silly, but it has to be set so that vinifod() works.
  718          * We do not want to do an nfs_statfs() here since we can get
  719          * stuck on a dead server and we are holding a lock on the mount
  720          * point.
  721          */
  722         mp->mnt_stat.f_iosize = NFS_MAXDGRAMDATA;
  723 
  724         return (0);
  725 bad:
  726         nfs_disconnect(nmp);
  727         free((caddr_t)nmp, M_NFSMNT);
  728         m_freem(nam);
  729         return (error);
  730 }
  731 
  732 /* unmount system call */
  733 int
  734 nfs_unmount(struct mount *mp, int mntflags, struct proc *p)
  735 {
  736         struct nfsmount *nmp;
  737         int error, flags;
  738 
  739         nmp = VFSTONFS(mp);
  740         flags = 0;
  741 
  742         if (mntflags & MNT_FORCE)
  743                 flags |= FORCECLOSE;
  744 
  745         error = vflush(mp, NULL, flags);
  746         if (error)
  747                 return (error);
  748 
  749         nfs_disconnect(nmp);
  750         m_freem(nmp->nm_nam);
  751         free(nmp, M_NFSMNT);
  752         return (0);
  753 }
  754 
  755 /*
  756  * Return root of a filesystem
  757  */
  758 int
  759 nfs_root(mp, vpp)
  760         struct mount *mp;
  761         struct vnode **vpp;
  762 {
  763         struct nfsmount *nmp;
  764         struct nfsnode *np;
  765         int error;
  766 
  767         nmp = VFSTONFS(mp);
  768         error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np);
  769         if (error)
  770                 return (error);
  771         *vpp = NFSTOV(np);
  772         return (0);
  773 }
  774 
  775 /*
  776  * Flush out the buffer cache
  777  */
  778 /* ARGSUSED */
  779 int
  780 nfs_sync(mp, waitfor, cred, p)
  781         struct mount *mp;
  782         int waitfor;
  783         struct ucred *cred;
  784         struct proc *p;
  785 {
  786         struct vnode *vp;
  787         int error, allerror = 0;
  788 
  789         /*
  790          * Don't traverse the vnode list if we want to skip all of them.
  791          */
  792         if (waitfor == MNT_LAZY)
  793                 return (allerror);
  794 
  795         /*
  796          * Force stale buffer cache information to be flushed.
  797          */
  798 loop:
  799         for (vp = LIST_FIRST(&mp->mnt_vnodelist); vp != NULL;
  800              vp = LIST_NEXT(vp, v_mntvnodes)) {
  801                 /*
  802                  * If the vnode that we are about to sync is no longer
  803                  * associated with this mount point, start over.
  804                  */
  805                 if (vp->v_mount != mp)
  806                         goto loop;
  807                 if (VOP_ISLOCKED(vp) || LIST_FIRST(&vp->v_dirtyblkhd) == NULL)
  808                         continue;
  809                 if (vget(vp, LK_EXCLUSIVE, p))
  810                         goto loop;
  811                 error = VOP_FSYNC(vp, cred, waitfor, p);
  812                 if (error)
  813                         allerror = error;
  814                 vput(vp);
  815         }
  816 
  817         return (allerror);
  818 }
  819 
  820 /*
  821  * NFS flat namespace lookup.
  822  * Currently unsupported.
  823  */
  824 /* ARGSUSED */
  825 int
  826 nfs_vget(mp, ino, vpp)
  827         struct mount *mp;
  828         ino_t ino;
  829         struct vnode **vpp;
  830 {
  831 
  832         return (EOPNOTSUPP);
  833 }
  834 
  835 /*
  836  * Do that sysctl thang...
  837  */
  838 int
  839 nfs_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
  840            size_t newlen, struct proc *p)
  841 {
  842         int rv;
  843 
  844         /*
  845          * All names at this level are terminal.
  846          */
  847         if(namelen > 1)
  848                 return ENOTDIR; /* overloaded */
  849 
  850         switch(name[0]) {
  851         case NFS_NFSSTATS:
  852                 if(!oldp) {
  853                         *oldlenp = sizeof nfsstats;
  854                         return 0;
  855                 }
  856 
  857                 if(*oldlenp < sizeof nfsstats) {
  858                         *oldlenp = sizeof nfsstats;
  859                         return ENOMEM;
  860                 }
  861 
  862                 rv = copyout(&nfsstats, oldp, sizeof nfsstats);
  863                 if(rv) return rv;
  864 
  865                 if(newp && newlen != sizeof nfsstats)
  866                         return EINVAL;
  867 
  868                 if(newp) {
  869                         return copyin(newp, &nfsstats, sizeof nfsstats);
  870                 }
  871                 return 0;
  872 
  873         case NFS_NIOTHREADS:
  874                 nfs_getset_niothreads(0);
  875 
  876                 rv = sysctl_int(oldp, oldlenp, newp, newlen, &nfs_niothreads);
  877                 if (newp)
  878                         nfs_getset_niothreads(1);
  879 
  880                 return rv;
  881 
  882         default:
  883                 return EOPNOTSUPP;
  884         }
  885 }
  886 
  887 
  888 /*
  889  * At this point, this should never happen
  890  */
  891 /* ARGSUSED */
  892 int
  893 nfs_fhtovp(mp, fhp, vpp)
  894         struct mount *mp;
  895         struct fid *fhp;
  896         struct vnode **vpp;
  897 {
  898 
  899         return (EINVAL);
  900 }
  901 
  902 /*
  903  * Vnode pointer to File handle, should never happen either
  904  */
  905 /* ARGSUSED */
  906 int
  907 nfs_vptofh(vp, fhp)
  908         struct vnode *vp;
  909         struct fid *fhp;
  910 {
  911 
  912         return (EINVAL);
  913 }
  914 
  915 /*
  916  * Vfs start routine, a no-op.
  917  */
  918 /* ARGSUSED */
  919 int
  920 nfs_start(mp, flags, p)
  921         struct mount *mp;
  922         int flags;
  923         struct proc *p;
  924 {
  925 
  926         return (0);
  927 }
  928 
  929 /*
  930  * Do operations associated with quotas, not supported
  931  */
  932 /* ARGSUSED */
  933 int
  934 nfs_quotactl(mp, cmd, uid, arg, p)
  935         struct mount *mp;
  936         int cmd;
  937         uid_t uid;
  938         caddr_t arg;
  939         struct proc *p;
  940 {
  941 
  942         return (EOPNOTSUPP);
  943 }
  944 
  945 /*
  946  * check export permission, not supported
  947  */
  948 /* ARGUSED */
  949 int
  950 nfs_checkexp(mp, nam, exflagsp, credanonp)
  951         struct mount *mp;
  952         struct mbuf *nam;
  953         int *exflagsp;
  954         struct ucred **credanonp;
  955 {
  956         return (EOPNOTSUPP);
  957 }
  958 

/* [<][>][^][v][top][bottom][index][help] */