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 /*
    2  * Copyright (c) 1989, 1993, 1995
    3  *      The Regents of the University of California.  All rights reserved.
    4  *
    5  * This code is derived from software contributed to Berkeley by
    6  * Rick Macklem at The University of Guelph.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  * 3. All advertising materials mentioning features or use of this software
   17  *    must display the following acknowledgement:
   18  *      This product includes software developed by the University of
   19  *      California, Berkeley and its contributors.
   20  * 4. Neither the name of the University nor the names of its contributors
   21  *    may be used to endorse or promote products derived from this software
   22  *    without specific prior written permission.
   23  *
   24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   34  * SUCH DAMAGE.
   35  *
   36  *      @(#)nfs_vfsops.c        8.12 (Berkeley) 5/20/95
   37  * $FreeBSD$
   38  */
   39 
   40 #include <sys/param.h>
   41 #include <sys/sockio.h>
   42 #include <sys/proc.h>
   43 #include <sys/vnode.h>
   44 #include <sys/kernel.h>
   45 #include <sys/sysctl.h>
   46 #include <sys/malloc.h>
   47 #include <sys/mount.h>
   48 #include <sys/mbuf.h>
   49 #include <sys/socket.h>
   50 #include <sys/socketvar.h>
   51 #include <sys/systm.h>
   52 
   53 #include <vm/vm.h>
   54 #include <vm/vm_extern.h>
   55 #include <vm/vm_zone.h>
   56 
   57 #include <net/if.h>
   58 #include <net/route.h>
   59 #include <netinet/in.h>
   60 
   61 #include <nfs/rpcv2.h>
   62 #include <nfs/nfsproto.h>
   63 #include <nfs/nfs.h>
   64 #include <nfs/nfsnode.h>
   65 #include <nfs/nfsmount.h>
   66 #include <nfs/xdr_subs.h>
   67 #include <nfs/nfsm_subs.h>
   68 #include <nfs/nfsdiskless.h>
   69 #include <nfs/nqnfs.h>
   70 
   71 extern int      nfs_mountroot __P((struct mount *mp));
   72 
   73 extern int      nfs_ticks;
   74 
   75 MALLOC_DEFINE(M_NFSREQ, "NFS req", "NFS request header");
   76 MALLOC_DEFINE(M_NFSBIGFH, "NFSV3 bigfh", "NFS version 3 file handle");
   77 MALLOC_DEFINE(M_NFSD, "NFS daemon", "Nfs server daemon structure");
   78 MALLOC_DEFINE(M_NFSDIROFF, "NFSV3 diroff", "NFS directory offset data");
   79 MALLOC_DEFINE(M_NFSRVDESC, "NFSV3 srvdesc", "NFS server socket descriptor");
   80 MALLOC_DEFINE(M_NFSUID, "NFS uid", "Nfs uid mapping structure");
   81 MALLOC_DEFINE(M_NQLEASE, "NQNFS Lease", "Nqnfs lease");
   82 MALLOC_DEFINE(M_NFSHASH, "NFS hash", "NFS hash tables");
   83 
   84 vm_zone_t nfsmount_zone;
   85 
   86 struct nfsstats nfsstats;
   87 SYSCTL_NODE(_vfs, OID_AUTO, nfs, CTLFLAG_RW, 0, "NFS filesystem");
   88 SYSCTL_STRUCT(_vfs_nfs, NFS_NFSSTATS, nfsstats, CTLFLAG_RD,
   89         &nfsstats, nfsstats, "");
   90 #ifdef NFS_DEBUG
   91 int nfs_debug;
   92 SYSCTL_INT(_vfs_nfs, OID_AUTO, debug, CTLFLAG_RW, &nfs_debug, 0, "");
   93 #endif
   94 
   95 static int      nfs_iosize __P((struct nfsmount *nmp));
   96 static void     nfs_decode_args __P((struct nfsmount *nmp,
   97                         struct nfs_args *argp));
   98 static int      mountnfs __P((struct nfs_args *,struct mount *,
   99                         struct sockaddr *,char *,char *,struct vnode **));
  100 static int      nfs_mount __P(( struct mount *mp, char *path, caddr_t data,
  101                         struct nameidata *ndp, struct proc *p));
  102 static int      nfs_start __P(( struct mount *mp, int flags,
  103                         struct proc *p));
  104 static int      nfs_unmount __P(( struct mount *mp, int mntflags,
  105                         struct proc *p));
  106 static int      nfs_root __P(( struct mount *mp, struct vnode **vpp));
  107 static int      nfs_quotactl __P(( struct mount *mp, int cmds, uid_t uid,
  108                         caddr_t arg, struct proc *p));
  109 static int      nfs_statfs __P(( struct mount *mp, struct statfs *sbp,
  110                         struct proc *p));
  111 static int      nfs_sync __P(( struct mount *mp, int waitfor,
  112                         struct ucred *cred, struct proc *p));
  113 static int      nfs_vptofh __P(( struct vnode *vp, struct fid *fhp));
  114 static int      nfs_fhtovp __P((struct mount *mp, struct fid *fhp,
  115                         struct sockaddr *nam, struct vnode **vpp,
  116                         int *exflagsp, struct ucred **credanonp));
  117 static int      nfs_vget __P((struct mount *, ino_t, struct vnode **));
  118 
  119 
  120 /*
  121  * nfs vfs operations.
  122  */
  123 static struct vfsops nfs_vfsops = {
  124         nfs_mount,
  125         nfs_start,
  126         nfs_unmount,
  127         nfs_root,
  128         nfs_quotactl,
  129         nfs_statfs,
  130         nfs_sync,
  131         nfs_vget,
  132         nfs_fhtovp,
  133         nfs_vptofh,
  134         nfs_init,
  135         nfs_uninit,
  136         &sysctl___vfs_nfs
  137 };
  138 VFS_SET(nfs_vfsops, nfs, VFCF_NETWORK);
  139 
  140 /*
  141  * This structure must be filled in by a primary bootstrap or bootstrap
  142  * server for a diskless/dataless machine. It is initialized below just
  143  * to ensure that it is allocated to initialized data (.data not .bss).
  144  */
  145 struct nfs_diskless nfs_diskless = { 0 };
  146 struct nfsv3_diskless nfsv3_diskless = { 0 };
  147 int nfs_diskless_valid = 0;
  148 
  149 SYSCTL_INT(_vfs_nfs, OID_AUTO, diskless_valid, CTLFLAG_RD, 
  150         &nfs_diskless_valid, 0, "");
  151 
  152 SYSCTL_STRING(_vfs_nfs, OID_AUTO, diskless_rootpath, CTLFLAG_RD,
  153         nfsv3_diskless.root_hostnam, 0, "");
  154 
  155 SYSCTL_OPAQUE(_vfs_nfs, OID_AUTO, diskless_rootaddr, CTLFLAG_RD,
  156         &nfsv3_diskless.root_saddr, sizeof nfsv3_diskless.root_saddr,
  157         "%Ssockaddr_in", "");
  158 
  159 SYSCTL_STRING(_vfs_nfs, OID_AUTO, diskless_swappath, CTLFLAG_RD,
  160         nfsv3_diskless.swap_hostnam, 0, "");
  161 
  162 SYSCTL_OPAQUE(_vfs_nfs, OID_AUTO, diskless_swapaddr, CTLFLAG_RD,
  163         &nfsv3_diskless.swap_saddr, sizeof nfsv3_diskless.swap_saddr, 
  164         "%Ssockaddr_in","");
  165 
  166 
  167 void nfsargs_ntoh __P((struct nfs_args *));
  168 static int nfs_mountdiskless __P((char *, char *, int,
  169                                   struct sockaddr_in *, struct nfs_args *,
  170                                   struct proc *, struct vnode **,
  171                                   struct mount **));
  172 static void nfs_convert_diskless __P((void));
  173 static void nfs_convert_oargs __P((struct nfs_args *args,
  174                                    struct onfs_args *oargs));
  175 
  176 static int
  177 nfs_iosize(nmp)
  178         struct nfsmount* nmp;
  179 {
  180         int iosize;
  181 
  182         /*
  183          * Calculate the size used for io buffers.  Use the larger
  184          * of the two sizes to minimise nfs requests but make sure
  185          * that it is at least one VM page to avoid wasting buffer
  186          * space.
  187          */
  188         iosize = max(nmp->nm_rsize, nmp->nm_wsize);
  189         if (iosize < PAGE_SIZE) iosize = PAGE_SIZE;
  190         return iosize;
  191 }
  192 
  193 static void
  194 nfs_convert_oargs(args, oargs)
  195         struct nfs_args *args;
  196         struct onfs_args *oargs;
  197 {
  198         args->version = NFS_ARGSVERSION;
  199         args->addr = oargs->addr;
  200         args->addrlen = oargs->addrlen;
  201         args->sotype = oargs->sotype;
  202         args->proto = oargs->proto;
  203         args->fh = oargs->fh;
  204         args->fhsize = oargs->fhsize;
  205         args->flags = oargs->flags;
  206         args->wsize = oargs->wsize;
  207         args->rsize = oargs->rsize;
  208         args->readdirsize = oargs->readdirsize;
  209         args->timeo = oargs->timeo;
  210         args->retrans = oargs->retrans;
  211         args->maxgrouplist = oargs->maxgrouplist;
  212         args->readahead = oargs->readahead;
  213         args->leaseterm = oargs->leaseterm;
  214         args->deadthresh = oargs->deadthresh;
  215         args->hostname = oargs->hostname;
  216 }
  217 
  218 static void
  219 nfs_convert_diskless()
  220 {
  221         bcopy(&nfs_diskless.myif, &nfsv3_diskless.myif,
  222                 sizeof(struct ifaliasreq));
  223         bcopy(&nfs_diskless.mygateway, &nfsv3_diskless.mygateway,
  224                 sizeof(struct sockaddr_in));
  225         nfs_convert_oargs(&nfsv3_diskless.swap_args,&nfs_diskless.swap_args);
  226         nfsv3_diskless.swap_fhsize = NFSX_V2FH;
  227         bcopy(nfs_diskless.swap_fh,nfsv3_diskless.swap_fh,NFSX_V2FH);
  228         bcopy(&nfs_diskless.swap_saddr,&nfsv3_diskless.swap_saddr,
  229                 sizeof(struct sockaddr_in));
  230         bcopy(nfs_diskless.swap_hostnam,nfsv3_diskless.swap_hostnam, MNAMELEN);
  231         nfsv3_diskless.swap_nblks = nfs_diskless.swap_nblks;
  232         bcopy(&nfs_diskless.swap_ucred, &nfsv3_diskless.swap_ucred,
  233                 sizeof(struct ucred));
  234         nfs_convert_oargs(&nfsv3_diskless.root_args,&nfs_diskless.root_args);
  235         nfsv3_diskless.root_fhsize = NFSX_V2FH;
  236         bcopy(nfs_diskless.root_fh,nfsv3_diskless.root_fh,NFSX_V2FH);
  237         bcopy(&nfs_diskless.root_saddr,&nfsv3_diskless.root_saddr,
  238                 sizeof(struct sockaddr_in));
  239         bcopy(nfs_diskless.root_hostnam,nfsv3_diskless.root_hostnam, MNAMELEN);
  240         nfsv3_diskless.root_time = nfs_diskless.root_time;
  241         bcopy(nfs_diskless.my_hostnam,nfsv3_diskless.my_hostnam,
  242                 MAXHOSTNAMELEN);
  243         nfs_diskless_valid = 3;
  244 }
  245 
  246 /*
  247  * nfs statfs call
  248  */
  249 int
  250 nfs_statfs(mp, sbp, p)
  251         struct mount *mp;
  252         register struct statfs *sbp;
  253         struct proc *p;
  254 {
  255         register struct vnode *vp;
  256         register struct nfs_statfs *sfp;
  257         register caddr_t cp;
  258         register u_int32_t *tl;
  259         register int32_t t1, t2;
  260         caddr_t bpos, dpos, cp2;
  261         struct nfsmount *nmp = VFSTONFS(mp);
  262         int error = 0, v3 = (nmp->nm_flag & NFSMNT_NFSV3), retattr;
  263         struct mbuf *mreq, *mrep, *md, *mb, *mb2;
  264         struct ucred *cred;
  265         struct nfsnode *np;
  266         u_quad_t tquad;
  267 
  268 #ifndef nolint
  269         sfp = (struct nfs_statfs *)0;
  270 #endif
  271         error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np);
  272         if (error)
  273                 return (error);
  274         vp = NFSTOV(np);
  275         cred = crget();
  276         cred->cr_ngroups = 1;
  277         if (v3 && (nmp->nm_state & NFSSTA_GOTFSINFO) == 0)
  278                 (void)nfs_fsinfo(nmp, vp, cred, p);
  279         nfsstats.rpccnt[NFSPROC_FSSTAT]++;
  280         nfsm_reqhead(vp, NFSPROC_FSSTAT, NFSX_FH(v3));
  281         nfsm_fhtom(vp, v3);
  282         nfsm_request(vp, NFSPROC_FSSTAT, p, cred);
  283         if (v3)
  284                 nfsm_postop_attr(vp, retattr);
  285         if (error) {
  286                 if (mrep != NULL)
  287                         m_free(mrep);
  288                 goto nfsmout;
  289         }
  290         nfsm_dissect(sfp, struct nfs_statfs *, NFSX_STATFS(v3));
  291         sbp->f_flags = nmp->nm_flag;
  292         sbp->f_iosize = nfs_iosize(nmp);
  293         if (v3) {
  294                 sbp->f_bsize = NFS_FABLKSIZE;
  295                 fxdr_hyper(&sfp->sf_tbytes, &tquad);
  296                 sbp->f_blocks = (long)(tquad / ((u_quad_t)NFS_FABLKSIZE));
  297                 fxdr_hyper(&sfp->sf_fbytes, &tquad);
  298                 sbp->f_bfree = (long)(tquad / ((u_quad_t)NFS_FABLKSIZE));
  299                 fxdr_hyper(&sfp->sf_abytes, &tquad);
  300                 sbp->f_bavail = (long)(tquad / ((u_quad_t)NFS_FABLKSIZE));
  301                 sbp->f_files = (fxdr_unsigned(int32_t,
  302                     sfp->sf_tfiles.nfsuquad[1]) & 0x7fffffff);
  303                 sbp->f_ffree = (fxdr_unsigned(int32_t,
  304                     sfp->sf_ffiles.nfsuquad[1]) & 0x7fffffff);
  305         } else {
  306                 sbp->f_bsize = fxdr_unsigned(int32_t, sfp->sf_bsize);
  307                 sbp->f_blocks = fxdr_unsigned(int32_t, sfp->sf_blocks);
  308                 sbp->f_bfree = fxdr_unsigned(int32_t, sfp->sf_bfree);
  309                 sbp->f_bavail = fxdr_unsigned(int32_t, sfp->sf_bavail);
  310                 sbp->f_files = 0;
  311                 sbp->f_ffree = 0;
  312         }
  313         if (sbp != &mp->mnt_stat) {
  314                 sbp->f_type = mp->mnt_vfc->vfc_typenum;
  315                 bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
  316                 bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
  317         }
  318         nfsm_reqdone;
  319         vput(vp);
  320         crfree(cred);
  321         return (error);
  322 }
  323 
  324 /*
  325  * nfs version 3 fsinfo rpc call
  326  */
  327 int
  328 nfs_fsinfo(nmp, vp, cred, p)
  329         register struct nfsmount *nmp;
  330         register struct vnode *vp;
  331         struct ucred *cred;
  332         struct proc *p;
  333 {
  334         register struct nfsv3_fsinfo *fsp;
  335         register caddr_t cp;
  336         register int32_t t1, t2;
  337         register u_int32_t *tl, pref, max;
  338         caddr_t bpos, dpos, cp2;
  339         int error = 0, retattr;
  340         struct mbuf *mreq, *mrep, *md, *mb, *mb2;
  341         u_int64_t maxfsize;
  342 
  343         nfsstats.rpccnt[NFSPROC_FSINFO]++;
  344         nfsm_reqhead(vp, NFSPROC_FSINFO, NFSX_FH(1));
  345         nfsm_fhtom(vp, 1);
  346         nfsm_request(vp, NFSPROC_FSINFO, p, cred);
  347         nfsm_postop_attr(vp, retattr);
  348         if (!error) {
  349                 nfsm_dissect(fsp, struct nfsv3_fsinfo *, NFSX_V3FSINFO);
  350                 pref = fxdr_unsigned(u_int32_t, fsp->fs_wtpref);
  351                 if (pref < nmp->nm_wsize && pref >= NFS_FABLKSIZE)
  352                         nmp->nm_wsize = (pref + NFS_FABLKSIZE - 1) &
  353                                 ~(NFS_FABLKSIZE - 1);
  354                 max = fxdr_unsigned(u_int32_t, fsp->fs_wtmax);
  355                 if (max < nmp->nm_wsize && max > 0) {
  356                         nmp->nm_wsize = max & ~(NFS_FABLKSIZE - 1);
  357                         if (nmp->nm_wsize == 0)
  358                                 nmp->nm_wsize = max;
  359                 }
  360                 pref = fxdr_unsigned(u_int32_t, fsp->fs_rtpref);
  361                 if (pref < nmp->nm_rsize && pref >= NFS_FABLKSIZE)
  362                         nmp->nm_rsize = (pref + NFS_FABLKSIZE - 1) &
  363                                 ~(NFS_FABLKSIZE - 1);
  364                 max = fxdr_unsigned(u_int32_t, fsp->fs_rtmax);
  365                 if (max < nmp->nm_rsize && max > 0) {
  366                         nmp->nm_rsize = max & ~(NFS_FABLKSIZE - 1);
  367                         if (nmp->nm_rsize == 0)
  368                                 nmp->nm_rsize = max;
  369                 }
  370                 pref = fxdr_unsigned(u_int32_t, fsp->fs_dtpref);
  371                 if (pref < nmp->nm_readdirsize && pref >= NFS_DIRBLKSIZ)
  372                         nmp->nm_readdirsize = (pref + NFS_DIRBLKSIZ - 1) &
  373                                 ~(NFS_DIRBLKSIZ - 1);
  374                 if (max < nmp->nm_readdirsize && max > 0) {
  375                         nmp->nm_readdirsize = max & ~(NFS_DIRBLKSIZ - 1);
  376                         if (nmp->nm_readdirsize == 0)
  377                                 nmp->nm_readdirsize = max;
  378                 }
  379                 fxdr_hyper(&fsp->fs_maxfilesize, &maxfsize);
  380                 if (maxfsize > 0 && maxfsize < nmp->nm_maxfilesize)
  381                         nmp->nm_maxfilesize = maxfsize;
  382                 nmp->nm_state |= NFSSTA_GOTFSINFO;
  383         }
  384         nfsm_reqdone;
  385         return (error);
  386 }
  387 
  388 /*
  389  * Mount a remote root fs via. nfs. This depends on the info in the
  390  * nfs_diskless structure that has been filled in properly by some primary
  391  * bootstrap.
  392  * It goes something like this:
  393  * - do enough of "ifconfig" by calling ifioctl() so that the system
  394  *   can talk to the server
  395  * - If nfs_diskless.mygateway is filled in, use that address as
  396  *   a default gateway.
  397  * - build the rootfs mount point and call mountnfs() to do the rest.
  398  */
  399 int
  400 nfs_mountroot(mp)
  401         struct mount *mp;
  402 {
  403         struct mount  *swap_mp;
  404         struct nfsv3_diskless *nd = &nfsv3_diskless;
  405         struct socket *so;
  406         struct vnode *vp;
  407         struct proc *p = curproc;               /* XXX */
  408         int error, i;
  409         u_long l;
  410         char buf[128];
  411 
  412         /*
  413          * XXX time must be non-zero when we init the interface or else
  414          * the arp code will wedge...
  415          */
  416         while (time_second == 0)
  417                 tsleep(&time_second, PZERO+8, "arpkludge", 10);
  418 
  419         if (nfs_diskless_valid==1) 
  420           nfs_convert_diskless();
  421 
  422         /*
  423          * XXX splnet, so networks will receive...
  424          */
  425         splnet();
  426 
  427 #ifdef notyet
  428         /* Set up swap credentials. */
  429         proc0.p_ucred->cr_uid = ntohl(nd->swap_ucred.cr_uid);
  430         proc0.p_ucred->cr_gid = ntohl(nd->swap_ucred.cr_gid);
  431         if ((proc0.p_ucred->cr_ngroups = ntohs(nd->swap_ucred.cr_ngroups)) >
  432                 NGROUPS)
  433                 proc0.p_ucred->cr_ngroups = NGROUPS;
  434         for (i = 0; i < proc0.p_ucred->cr_ngroups; i++)
  435             proc0.p_ucred->cr_groups[i] = ntohl(nd->swap_ucred.cr_groups[i]);
  436 #endif
  437 
  438         /*
  439          * Do enough of ifconfig(8) so that the critical net interface can
  440          * talk to the server.
  441          */
  442         error = socreate(nd->myif.ifra_addr.sa_family, &so, SOCK_DGRAM, 0, p);
  443         if (error)
  444                 panic("nfs_mountroot: socreate(%04x): %d",
  445                         nd->myif.ifra_addr.sa_family, error);
  446 
  447         /*
  448          * We might not have been told the right interface, so we pass
  449          * over the first ten interfaces of the same kind, until we get
  450          * one of them configured.
  451          */
  452 
  453         for (i = strlen(nd->myif.ifra_name) - 1;
  454                 nd->myif.ifra_name[i] >= '' &&
  455                 nd->myif.ifra_name[i] <= '9';
  456                 nd->myif.ifra_name[i] ++) {
  457                 error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, p);
  458                 if(!error)
  459                         break;
  460         }
  461         if (error)
  462                 panic("nfs_mountroot: SIOCAIFADDR: %d", error);
  463         soclose(so);
  464 
  465         /*
  466          * If the gateway field is filled in, set it as the default route.
  467          */
  468         if (nd->mygateway.sin_len != 0) {
  469                 struct sockaddr_in mask, sin;
  470 
  471                 bzero((caddr_t)&mask, sizeof(mask));
  472                 sin = mask;
  473                 sin.sin_family = AF_INET;
  474                 sin.sin_len = sizeof(sin);
  475                 error = rtrequest(RTM_ADD, (struct sockaddr *)&sin,
  476                     (struct sockaddr *)&nd->mygateway,
  477                     (struct sockaddr *)&mask,
  478                     RTF_UP | RTF_GATEWAY, (struct rtentry **)0);
  479                 if (error)
  480                         panic("nfs_mountroot: RTM_ADD: %d", error);
  481         }
  482 
  483         /*
  484          * Create the rootfs mount point.
  485          */
  486         nd->root_args.fh = nd->root_fh;
  487         nd->root_args.fhsize = nd->root_fhsize;
  488         l = ntohl(nd->root_saddr.sin_addr.s_addr);
  489         snprintf(buf, sizeof(buf), "%ld.%ld.%ld.%ld:%s",
  490                 (l >> 24) & 0xff, (l >> 16) & 0xff,
  491                 (l >>  8) & 0xff, (l >>  0) & 0xff,nd->root_hostnam);
  492         printf("NFS ROOT: %s\n",buf);
  493         if (error = nfs_mountdiskless(buf, "/", MNT_RDONLY,
  494             &nd->root_saddr, &nd->root_args, p, &vp, &mp)) {
  495                 if (swap_mp) {
  496                         mp->mnt_vfc->vfc_refcount--;
  497                         free(swap_mp, M_MOUNT);
  498                 }
  499                 return (error);
  500         }
  501 
  502         swap_mp = NULL;
  503         if (nd->swap_nblks) {
  504 
  505                 /* Convert to DEV_BSIZE instead of Kilobyte */
  506                 nd->swap_nblks *= 2;
  507 
  508                 /*
  509                  * Create a fake mount point just for the swap vnode so that the
  510                  * swap file can be on a different server from the rootfs.
  511                  */
  512                 nd->swap_args.fh = nd->swap_fh;
  513                 nd->swap_args.fhsize = nd->swap_fhsize;
  514                 l = ntohl(nd->swap_saddr.sin_addr.s_addr);
  515                 snprintf(buf, sizeof(buf), "%ld.%ld.%ld.%ld:%s",
  516                         (l >> 24) & 0xff, (l >> 16) & 0xff,
  517                         (l >>  8) & 0xff, (l >>  0) & 0xff,nd->swap_hostnam);
  518                 printf("NFS SWAP: %s\n",buf);
  519                 if (error = nfs_mountdiskless(buf, "/swap", 0,
  520                     &nd->swap_saddr, &nd->swap_args, p, &vp, &swap_mp))
  521                         return (error);
  522                 vfs_unbusy(swap_mp, p);
  523 
  524                 VTONFS(vp)->n_size = VTONFS(vp)->n_vattr.va_size = 
  525                                 nd->swap_nblks * DEV_BSIZE ;
  526                 
  527                 /*
  528                  * Since the swap file is not the root dir of a file system,
  529                  * hack it to a regular file.
  530                  */
  531                 vp->v_type = VREG;
  532                 vp->v_flag = 0;
  533                 VREF(vp);
  534                 swaponvp(p, vp, NODEV, nd->swap_nblks);
  535         }
  536 
  537         mp->mnt_flag |= MNT_ROOTFS;
  538         mp->mnt_vnodecovered = NULLVP;
  539         rootvp = vp;
  540         vfs_unbusy(mp, p);
  541 
  542         /*
  543          * This is not really an nfs issue, but it is much easier to
  544          * set hostname here and then let the "/etc/rc.xxx" files
  545          * mount the right /var based upon its preset value.
  546          */
  547         bcopy(nd->my_hostnam, hostname, MAXHOSTNAMELEN);
  548         hostname[MAXHOSTNAMELEN - 1] = '\0';
  549         for (i = 0; i < MAXHOSTNAMELEN; i++)
  550                 if (hostname[i] == '\0')
  551                         break;
  552         inittodr(ntohl(nd->root_time));
  553         return (0);
  554 }
  555 
  556 /*
  557  * Internal version of mount system call for diskless setup.
  558  */
  559 static int
  560 nfs_mountdiskless(path, which, mountflag, sin, args, p, vpp, mpp)
  561         char *path;
  562         char *which;
  563         int mountflag;
  564         struct sockaddr_in *sin;
  565         struct nfs_args *args;
  566         struct proc *p;
  567         struct vnode **vpp;
  568         struct mount **mpp;
  569 {
  570         struct mount *mp;
  571         struct sockaddr *nam;
  572         int error;
  573 
  574         mp = *mpp;
  575 
  576         if (!mp && (error = vfs_rootmountalloc("nfs", path, &mp))) {
  577                 printf("nfs_mountroot: NFS not configured");
  578                 return (error);
  579         }
  580 
  581         mp->mnt_kern_flag = 0;
  582         mp->mnt_flag = mountflag;
  583         nam = dup_sockaddr((struct sockaddr *)sin, 1);
  584         if (error = mountnfs(args, mp, nam, which, path, vpp)) {
  585                 printf("nfs_mountroot: mount %s on %s: %d", path, which, error);
  586                 mp->mnt_vfc->vfc_refcount--;
  587                 vfs_unbusy(mp, p);
  588                 free(mp, M_MOUNT);
  589                 FREE(nam, M_SONAME);
  590                 return (error);
  591         }
  592         (void) copystr(which, mp->mnt_stat.f_mntonname, MNAMELEN - 1, 0);
  593         *mpp = mp;
  594         return (0);
  595 }
  596 
  597 static void
  598 nfs_decode_args(nmp, argp)
  599         struct nfsmount *nmp;
  600         struct nfs_args *argp;
  601 {
  602         int s;
  603         int adjsock;
  604         int maxio;
  605 
  606         s = splnet();
  607         /*
  608          * Silently clear NFSMNT_NOCONN if it's a TCP mount, it makes
  609          * no sense in that context.
  610          */
  611         if (argp->sotype == SOCK_STREAM)
  612                 nmp->nm_flag &= ~NFSMNT_NOCONN;
  613 
  614         /* Also clear RDIRPLUS if not NFSv3, it crashes some servers */
  615         if ((argp->flags & NFSMNT_NFSV3) == 0)
  616                 nmp->nm_flag &= ~NFSMNT_RDIRPLUS;
  617 
  618         /* Re-bind if rsrvd port requested and wasn't on one */
  619         adjsock = !(nmp->nm_flag & NFSMNT_RESVPORT)
  620                   && (argp->flags & NFSMNT_RESVPORT);
  621         /* Also re-bind if we're switching to/from a connected UDP socket */
  622         adjsock |= ((nmp->nm_flag & NFSMNT_NOCONN) !=
  623                     (argp->flags & NFSMNT_NOCONN));
  624 
  625         /* Update flags atomically.  Don't change the lock bits. */
  626         nmp->nm_flag = argp->flags | nmp->nm_flag;
  627         splx(s);
  628 
  629         if ((argp->flags & NFSMNT_TIMEO) && argp->timeo > 0) {
  630                 nmp->nm_timeo = (argp->timeo * NFS_HZ + 5) / 10;
  631                 if (nmp->nm_timeo < NFS_MINTIMEO)
  632                         nmp->nm_timeo = NFS_MINTIMEO;
  633                 else if (nmp->nm_timeo > NFS_MAXTIMEO)
  634                         nmp->nm_timeo = NFS_MAXTIMEO;
  635         }
  636 
  637         if ((argp->flags & NFSMNT_RETRANS) && argp->retrans > 1) {
  638                 nmp->nm_retry = argp->retrans;
  639                 if (nmp->nm_retry > NFS_MAXREXMIT)
  640                         nmp->nm_retry = NFS_MAXREXMIT;
  641         }
  642 
  643         if (argp->flags & NFSMNT_NFSV3) {
  644                 if (argp->sotype == SOCK_DGRAM)
  645                         maxio = NFS_MAXDGRAMDATA;
  646                 else
  647                         maxio = NFS_MAXDATA;
  648         } else
  649                 maxio = NFS_V2MAXDATA;
  650 
  651         if ((argp->flags & NFSMNT_WSIZE) && argp->wsize > 0) {
  652                 nmp->nm_wsize = argp->wsize;
  653                 /* Round down to multiple of blocksize */
  654                 nmp->nm_wsize &= ~(NFS_FABLKSIZE - 1);
  655                 if (nmp->nm_wsize <= 0)
  656                         nmp->nm_wsize = NFS_FABLKSIZE;
  657         }
  658         if (nmp->nm_wsize > maxio)
  659                 nmp->nm_wsize = maxio;
  660         if (nmp->nm_wsize > MAXBSIZE)
  661                 nmp->nm_wsize = MAXBSIZE;
  662 
  663         if ((argp->flags & NFSMNT_RSIZE) && argp->rsize > 0) {
  664                 nmp->nm_rsize = argp->rsize;
  665                 /* Round down to multiple of blocksize */
  666                 nmp->nm_rsize &= ~(NFS_FABLKSIZE - 1);
  667                 if (nmp->nm_rsize <= 0)
  668                         nmp->nm_rsize = NFS_FABLKSIZE;
  669         }
  670         if (nmp->nm_rsize > maxio)
  671                 nmp->nm_rsize = maxio;
  672         if (nmp->nm_rsize > MAXBSIZE)
  673                 nmp->nm_rsize = MAXBSIZE;
  674 
  675         if ((argp->flags & NFSMNT_READDIRSIZE) && argp->readdirsize > 0) {
  676                 nmp->nm_readdirsize = argp->readdirsize;
  677         }
  678         if (nmp->nm_readdirsize > maxio)
  679                 nmp->nm_readdirsize = maxio;
  680         if (nmp->nm_readdirsize > nmp->nm_rsize)
  681                 nmp->nm_readdirsize = nmp->nm_rsize;
  682 
  683         if ((argp->flags & NFSMNT_ACREGMIN) && argp->acregmin >= 0)
  684                 nmp->nm_acregmin = argp->acregmin;
  685         else
  686                 nmp->nm_acregmin = NFS_MINATTRTIMO;
  687         if ((argp->flags & NFSMNT_ACREGMAX) && argp->acregmax >= 0)
  688                 nmp->nm_acregmax = argp->acregmax;
  689         else
  690                 nmp->nm_acregmax = NFS_MAXATTRTIMO;
  691         if ((argp->flags & NFSMNT_ACDIRMIN) && argp->acdirmin >= 0)
  692                 nmp->nm_acdirmin = argp->acdirmin;
  693         else
  694                 nmp->nm_acdirmin = NFS_MINDIRATTRTIMO;
  695         if ((argp->flags & NFSMNT_ACDIRMAX) && argp->acdirmax >= 0)
  696                 nmp->nm_acdirmax = argp->acdirmax;
  697         else
  698                 nmp->nm_acdirmax = NFS_MAXDIRATTRTIMO;
  699         if (nmp->nm_acdirmin > nmp->nm_acdirmax)
  700                 nmp->nm_acdirmin = nmp->nm_acdirmax;
  701         if (nmp->nm_acregmin > nmp->nm_acregmax)
  702                 nmp->nm_acregmin = nmp->nm_acregmax;
  703 
  704         if ((argp->flags & NFSMNT_MAXGRPS) && argp->maxgrouplist >= 0 &&
  705                 argp->maxgrouplist <= NFS_MAXGRPS)
  706                 nmp->nm_numgrps = argp->maxgrouplist;
  707         if ((argp->flags & NFSMNT_READAHEAD) && argp->readahead >= 0 &&
  708                 argp->readahead <= NFS_MAXRAHEAD)
  709                 nmp->nm_readahead = argp->readahead;
  710         if ((argp->flags & NFSMNT_LEASETERM) && argp->leaseterm >= 2 &&
  711                 argp->leaseterm <= NQ_MAXLEASE)
  712                 nmp->nm_leaseterm = argp->leaseterm;
  713         if ((argp->flags & NFSMNT_DEADTHRESH) && argp->deadthresh >= 1 &&
  714                 argp->deadthresh <= NQ_NEVERDEAD)
  715                 nmp->nm_deadthresh = argp->deadthresh;
  716 
  717         adjsock |= ((nmp->nm_sotype != argp->sotype) ||
  718                     (nmp->nm_soproto != argp->proto));
  719         nmp->nm_sotype = argp->sotype;
  720         nmp->nm_soproto = argp->proto;
  721 
  722         if (nmp->nm_so && adjsock) {
  723                 nfs_safedisconnect(nmp);
  724                 if (nmp->nm_sotype == SOCK_DGRAM)
  725                         while (nfs_connect(nmp, (struct nfsreq *)0)) {
  726                                 printf("nfs_args: retrying connect\n");
  727                                 (void) tsleep((caddr_t)&lbolt,
  728                                               PSOCK, "nfscon", 0);
  729                         }
  730         }
  731 }
  732 
  733 /*
  734  * VFS Operations.
  735  *
  736  * mount system call
  737  * It seems a bit dumb to copyinstr() the host and path here and then
  738  * bcopy() them in mountnfs(), but I wanted to detect errors before
  739  * doing the sockargs() call because sockargs() allocates an mbuf and
  740  * an error after that means that I have to release the mbuf.
  741  */
  742 /* ARGSUSED */
  743 static int
  744 nfs_mount(mp, path, data, ndp, p)
  745         struct mount *mp;
  746         char *path;
  747         caddr_t data;
  748         struct nameidata *ndp;
  749         struct proc *p;
  750 {
  751         int error;
  752         struct nfs_args args;
  753         struct sockaddr *nam;
  754         struct vnode *vp;
  755         char pth[MNAMELEN], hst[MNAMELEN];
  756         size_t len;
  757         u_char nfh[NFSX_V3FHMAX];
  758 
  759         if (path == NULL) {
  760                 nfs_mountroot(mp);
  761                 return (0);
  762         }
  763         error = copyin(data, (caddr_t)&args, sizeof (struct nfs_args));
  764         if (error)
  765                 return (error);
  766         if (args.version != NFS_ARGSVERSION) {
  767 #ifdef COMPAT_PRELITE2
  768                 /*
  769                  * If the argument version is unknown, then assume the
  770                  * caller is a pre-lite2 4.4BSD client and convert its
  771                  * arguments.
  772                  */
  773                 struct onfs_args oargs;
  774                 error = copyin(data, (caddr_t)&oargs, sizeof (struct onfs_args));
  775                 if (error)
  776                         return (error);
  777                 nfs_convert_oargs(&args,&oargs);
  778 #else /* !COMPAT_PRELITE2 */
  779                 return (EPROGMISMATCH);
  780 #endif /* COMPAT_PRELITE2 */
  781         }
  782         if (mp->mnt_flag & MNT_UPDATE) {
  783                 register struct nfsmount *nmp = VFSTONFS(mp);
  784 
  785                 if (nmp == NULL)
  786                         return (EIO);
  787                 /*
  788                  * When doing an update, we can't change from or to
  789                  * v3 and/or nqnfs, or change cookie translation
  790                  */
  791                 args.flags = (args.flags &
  792                     ~(NFSMNT_NFSV3|NFSMNT_NQNFS /*|NFSMNT_XLATECOOKIE*/)) |
  793                     (nmp->nm_flag &
  794                         (NFSMNT_NFSV3|NFSMNT_NQNFS /*|NFSMNT_XLATECOOKIE*/));
  795                 nfs_decode_args(nmp, &args);
  796                 return (0);
  797         }
  798         error = copyin((caddr_t)args.fh, (caddr_t)nfh, args.fhsize);
  799         if (error)
  800                 return (error);
  801         error = copyinstr(path, pth, MNAMELEN-1, &len);
  802         if (error)
  803                 return (error);
  804         bzero(&pth[len], MNAMELEN - len);
  805         error = copyinstr(args.hostname, hst, MNAMELEN-1, &len);
  806         if (error)
  807                 return (error);
  808         bzero(&hst[len], MNAMELEN - len);
  809         /* sockargs() call must be after above copyin() calls */
  810         error = getsockaddr(&nam, (caddr_t)args.addr, args.addrlen);
  811         if (error)
  812                 return (error);
  813         args.fh = nfh;
  814         error = mountnfs(&args, mp, nam, pth, hst, &vp);
  815         return (error);
  816 }
  817 
  818 /*
  819  * Common code for mount and mountroot
  820  */
  821 static int
  822 mountnfs(argp, mp, nam, pth, hst, vpp)
  823         register struct nfs_args *argp;
  824         register struct mount *mp;
  825         struct sockaddr *nam;
  826         char *pth, *hst;
  827         struct vnode **vpp;
  828 {
  829         register struct nfsmount *nmp;
  830         struct nfsnode *np;
  831         int error;
  832         struct vattr attrs;
  833 
  834         if (mp->mnt_flag & MNT_UPDATE) {
  835                 nmp = VFSTONFS(mp);
  836                 /* update paths, file handles, etc, here        XXX */
  837                 FREE(nam, M_SONAME);
  838                 return (0);
  839         } else {
  840                 nmp = zalloc(nfsmount_zone);
  841                 bzero((caddr_t)nmp, sizeof (struct nfsmount));
  842                 TAILQ_INIT(&nmp->nm_uidlruhead);
  843                 TAILQ_INIT(&nmp->nm_bufq);
  844                 mp->mnt_data = (qaddr_t)nmp;
  845         }
  846         vfs_getnewfsid(mp);
  847         nmp->nm_mountp = mp;
  848         if (argp->flags & NFSMNT_NQNFS)
  849                 /*
  850                  * We have to set mnt_maxsymlink to a non-zero value so
  851                  * that COMPAT_43 routines will know that we are setting
  852                  * the d_type field in directories (and can zero it for
  853                  * unsuspecting binaries).
  854                  */
  855                 mp->mnt_maxsymlinklen = 1;
  856 
  857         /*
  858          * V2 can only handle 32 bit filesizes.  A 4GB-1 limit may be too
  859          * high, depending on whether we end up with negative offsets in
  860          * the client or server somewhere.  2GB-1 may be safer.
  861          *
  862          * For V3, nfs_fsinfo will adjust this as necessary.  Assume maximum
  863          * that we can handle until we find out otherwise.
  864          * XXX Our "safe" limit on the client is what we can store in our
  865          * buffer cache using signed(!) block numbers.
  866          */
  867         if ((argp->flags & NFSMNT_NFSV3) == 0)
  868                 nmp->nm_maxfilesize = 0xffffffffLL;
  869         else
  870                 nmp->nm_maxfilesize = (u_int64_t)0x80000000 * DEV_BSIZE - 1;
  871 
  872         nmp->nm_timeo = NFS_TIMEO;
  873         nmp->nm_retry = NFS_RETRANS;
  874         nmp->nm_wsize = NFS_WSIZE;
  875         nmp->nm_rsize = NFS_RSIZE;
  876         nmp->nm_readdirsize = NFS_READDIRSIZE;
  877         nmp->nm_numgrps = NFS_MAXGRPS;
  878         nmp->nm_readahead = NFS_DEFRAHEAD;
  879         nmp->nm_leaseterm = NQ_DEFLEASE;
  880         nmp->nm_deadthresh = NQ_DEADTHRESH;
  881         CIRCLEQ_INIT(&nmp->nm_timerhead);
  882         nmp->nm_inprog = NULLVP;
  883         nmp->nm_fhsize = argp->fhsize;
  884         bcopy((caddr_t)argp->fh, (caddr_t)nmp->nm_fh, argp->fhsize);
  885         bcopy(hst, mp->mnt_stat.f_mntfromname, MNAMELEN);
  886         bcopy(pth, mp->mnt_stat.f_mntonname, MNAMELEN);
  887         nmp->nm_nam = nam;
  888         /* Set up the sockets and per-host congestion */
  889         nmp->nm_sotype = argp->sotype;
  890         nmp->nm_soproto = argp->proto;
  891 
  892         nfs_decode_args(nmp, argp);
  893 
  894         /*
  895          * For Connection based sockets (TCP,...) defer the connect until
  896          * the first request, in case the server is not responding.
  897          */
  898         if (nmp->nm_sotype == SOCK_DGRAM &&
  899                 (error = nfs_connect(nmp, (struct nfsreq *)0)))
  900                 goto bad;
  901 
  902         /*
  903          * This is silly, but it has to be set so that vinifod() works.
  904          * We do not want to do an nfs_statfs() here since we can get
  905          * stuck on a dead server and we are holding a lock on the mount
  906          * point.
  907          */
  908         mp->mnt_stat.f_iosize = nfs_iosize(nmp);
  909         /*
  910          * A reference count is needed on the nfsnode representing the
  911          * remote root.  If this object is not persistent, then backward
  912          * traversals of the mount point (i.e. "..") will not work if
  913          * the nfsnode gets flushed out of the cache. Ufs does not have
  914          * this problem, because one can identify root inodes by their
  915          * number == ROOTINO (2).
  916          */
  917         error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np);
  918         if (error)
  919                 goto bad;
  920         *vpp = NFSTOV(np);
  921 
  922         /*
  923          * Get file attributes for the mountpoint.  This has the side
  924          * effect of filling in (*vpp)->v_type with the correct value.
  925          */
  926         VOP_GETATTR(*vpp, &attrs, curproc->p_ucred, curproc);
  927 
  928         /*
  929          * Lose the lock but keep the ref.
  930          */
  931         VOP_UNLOCK(*vpp, 0, curproc);
  932 
  933         return (0);
  934 bad:
  935         nfs_disconnect(nmp);
  936         zfree(nfsmount_zone, nmp);
  937         FREE(nam, M_SONAME);
  938         return (error);
  939 }
  940 
  941 /*
  942  * unmount system call
  943  */
  944 static int
  945 nfs_unmount(mp, mntflags, p)
  946         struct mount *mp;
  947         int mntflags;
  948         struct proc *p;
  949 {
  950         register struct nfsmount *nmp;
  951         struct nfsnode *np;
  952         struct vnode *vp;
  953         int error, flags = 0;
  954 
  955         if (mntflags & MNT_FORCE)
  956                 flags |= FORCECLOSE;
  957         nmp = VFSTONFS(mp);
  958         /*
  959          * Goes something like this..
  960          * - Check for activity on the root vnode (other than ourselves).
  961          * - Call vflush() to clear out vnodes for this file system,
  962          *   except for the root vnode.
  963          * - Decrement reference on the vnode representing remote root.
  964          * - Close the socket
  965          * - Free up the data structures
  966          */
  967         /*
  968          * We need to decrement the ref. count on the nfsnode representing
  969          * the remote root.  See comment in mountnfs().  The VFS unmount()
  970          * has done vput on this vnode, otherwise we would get deadlock!
  971          */
  972         error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np);
  973         if (error)
  974                 return(error);
  975         vp = NFSTOV(np);
  976         if (vp->v_usecount > 2) {
  977                 vput(vp);
  978                 return (EBUSY);
  979         }
  980 
  981         /*
  982          * Must handshake with nqnfs_clientd() if it is active.
  983          */
  984         nmp->nm_state |= NFSSTA_DISMINPROG;
  985         while (nmp->nm_inprog != NULLVP)
  986                 (void) tsleep((caddr_t)&lbolt, PSOCK, "nfsdism", 0);
  987         error = vflush(mp, vp, flags);
  988         if (error) {
  989                 vput(vp);
  990                 nmp->nm_state &= ~NFSSTA_DISMINPROG;
  991                 return (error);
  992         }
  993 
  994         /*
  995          * We are now committed to the unmount.
  996          * For NQNFS, let the server daemon free the nfsmount structure.
  997          */
  998         if (nmp->nm_flag & (NFSMNT_NQNFS | NFSMNT_KERB))
  999                 nmp->nm_state |= NFSSTA_DISMNT;
 1000 
 1001         /*
 1002          * There are two reference counts and one lock to get rid of here.
 1003          */
 1004         vput(vp);
 1005         vrele(vp);
 1006         vgone(vp);
 1007         nfs_disconnect(nmp);
 1008         FREE(nmp->nm_nam, M_SONAME);
 1009 
 1010         if ((nmp->nm_flag & (NFSMNT_NQNFS | NFSMNT_KERB)) == 0)
 1011                 zfree(nfsmount_zone, nmp);
 1012         return (0);
 1013 }
 1014 
 1015 /*
 1016  * Return root of a filesystem
 1017  */
 1018 static int
 1019 nfs_root(mp, vpp)
 1020         struct mount *mp;
 1021         struct vnode **vpp;
 1022 {
 1023         register struct vnode *vp;
 1024         struct nfsmount *nmp;
 1025         struct nfsnode *np;
 1026         int error;
 1027 
 1028         nmp = VFSTONFS(mp);
 1029         error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np);
 1030         if (error)
 1031                 return (error);
 1032         vp = NFSTOV(np);
 1033         if (vp->v_type == VNON)
 1034             vp->v_type = VDIR;
 1035         vp->v_flag = VROOT;
 1036         *vpp = vp;
 1037         return (0);
 1038 }
 1039 
 1040 extern int syncprt;
 1041 
 1042 /*
 1043  * Flush out the buffer cache
 1044  */
 1045 /* ARGSUSED */
 1046 static int
 1047 nfs_sync(mp, waitfor, cred, p)
 1048         struct mount *mp;
 1049         int waitfor;
 1050         struct ucred *cred;
 1051         struct proc *p;
 1052 {
 1053         register struct vnode *vp;
 1054         int error, allerror = 0;
 1055 
 1056         /*
 1057          * Force stale buffer cache information to be flushed.
 1058          */
 1059 loop:
 1060         for (vp = mp->mnt_vnodelist.lh_first;
 1061              vp != NULL;
 1062              vp = vp->v_mntvnodes.le_next) {
 1063                 /*
 1064                  * If the vnode that we are about to sync is no longer
 1065                  * associated with this mount point, start over.
 1066                  */
 1067                 if (vp->v_mount != mp)
 1068                         goto loop;
 1069                 if (VOP_ISLOCKED(vp) || TAILQ_EMPTY(&vp->v_dirtyblkhd) ||
 1070                     waitfor == MNT_LAZY)
 1071                         continue;
 1072                 if (vget(vp, LK_EXCLUSIVE, p))
 1073                         goto loop;
 1074                 error = VOP_FSYNC(vp, cred, waitfor, p);
 1075                 if (error)
 1076                         allerror = error;
 1077                 vput(vp);
 1078         }
 1079         return (allerror);
 1080 }
 1081 
 1082 /*
 1083  * NFS flat namespace lookup.
 1084  * Currently unsupported.
 1085  */
 1086 /* ARGSUSED */
 1087 static int
 1088 nfs_vget(mp, ino, vpp)
 1089         struct mount *mp;
 1090         ino_t ino;
 1091         struct vnode **vpp;
 1092 {
 1093 
 1094         return (EOPNOTSUPP);
 1095 }
 1096 
 1097 /*
 1098  * At this point, this should never happen
 1099  */
 1100 /* ARGSUSED */
 1101 static int
 1102 nfs_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp)
 1103         register struct mount *mp;
 1104         struct fid *fhp;
 1105         struct sockaddr *nam;
 1106         struct vnode **vpp;
 1107         int *exflagsp;
 1108         struct ucred **credanonp;
 1109 {
 1110 
 1111         return (EINVAL);
 1112 }
 1113 
 1114 /*
 1115  * Vnode pointer to File handle, should never happen either
 1116  */
 1117 /* ARGSUSED */
 1118 static int
 1119 nfs_vptofh(vp, fhp)
 1120         struct vnode *vp;
 1121         struct fid *fhp;
 1122 {
 1123 
 1124         return (EINVAL);
 1125 }
 1126 
 1127 /*
 1128  * Vfs start routine, a no-op.
 1129  */
 1130 /* ARGSUSED */
 1131 static int
 1132 nfs_start(mp, flags, p)
 1133         struct mount *mp;
 1134         int flags;
 1135         struct proc *p;
 1136 {
 1137 
 1138         return (0);
 1139 }
 1140 
 1141 /*
 1142  * Do operations associated with quotas, not supported
 1143  */
 1144 /* ARGSUSED */
 1145 static int
 1146 nfs_quotactl(mp, cmd, uid, arg, p)
 1147         struct mount *mp;
 1148         int cmd;
 1149         uid_t uid;
 1150         caddr_t arg;
 1151         struct proc *p;
 1152 {
 1153 
 1154         return (EOPNOTSUPP);
 1155 }

Cache object: 2526a6bf856f4bbe59b4b98ed9dcb5d4


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