2 * Copyright (c) 1989, 1993, 1995
3 * The Regents of the University of California. All rights reserved.
5 * This code is derived from software contributed to Berkeley by
6 * Rick Macklem at The University of Guelph.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
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.
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
36 * @(#)nfs_vfsops.c 8.12 (Berkeley) 5/20/95
37 * $Id: nfs_vfsops.c,v 1.51 1997/10/28 15:59:12 bde Exp $
40 #include <sys/param.h>
41 #include <sys/sockio.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>
49 #include <sys/socket.h>
50 #include <sys/socketvar.h>
51 #include <sys/systm.h>
54 #include <vm/vm_extern.h>
57 #include <net/route.h>
58 #include <netinet/in.h>
60 #include <nfs/rpcv2.h>
61 #include <nfs/nfsproto.h>
63 #include <nfs/nfsnode.h>
64 #include <nfs/nfsmount.h>
65 #include <nfs/xdr_subs.h>
66 #include <nfs/nfsm_subs.h>
67 #include <nfs/nfsdiskless.h>
68 #include <nfs/nqnfs.h>
70 extern int nfs_mountroot __P((struct mount *mp));
74 MALLOC_DEFINE(M_NFSREQ, "NFS req", "NFS request header");
75 MALLOC_DEFINE(M_NFSMNT, "NFS mount", "NFS mount structure");
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");
83 struct nfsstats nfsstats;
84 SYSCTL_NODE(_vfs, MOUNT_NFS, nfs, CTLFLAG_RW, 0, "NFS filesystem");
85 SYSCTL_STRUCT(_vfs_nfs, NFS_NFSSTATS, nfsstats, CTLFLAG_RD,
86 &nfsstats, nfsstats, "");
89 SYSCTL_INT(_vfs_nfs, OID_AUTO, debug, CTLFLAG_RW, &nfs_debug, 0, "");
92 static int nfs_iosize __P((struct nfsmount *nmp));
93 static int mountnfs __P((struct nfs_args *,struct mount *,
94 struct sockaddr *,char *,char *,struct vnode **));
95 static int nfs_mount __P(( struct mount *mp, char *path, caddr_t data,
96 struct nameidata *ndp, struct proc *p));
97 static int nfs_start __P(( struct mount *mp, int flags,
99 static int nfs_unmount __P(( struct mount *mp, int mntflags,
101 static int nfs_root __P(( struct mount *mp, struct vnode **vpp));
102 static int nfs_quotactl __P(( struct mount *mp, int cmds, uid_t uid,
103 caddr_t arg, struct proc *p));
104 static int nfs_statfs __P(( struct mount *mp, struct statfs *sbp,
106 static int nfs_sync __P(( struct mount *mp, int waitfor,
107 struct ucred *cred, struct proc *p));
108 static int nfs_vptofh __P(( struct vnode *vp, struct fid *fhp));
109 static int nfs_fhtovp __P((struct mount *mp, struct fid *fhp,
110 struct sockaddr *nam, struct vnode **vpp,
111 int *exflagsp, struct ucred **credanonp));
112 static int nfs_vget __P((struct mount *, ino_t, struct vnode **));
116 * nfs vfs operations.
118 static struct vfsops nfs_vfsops = {
131 VFS_SET(nfs_vfsops, nfs, MOUNT_NFS, VFCF_NETWORK);
134 * This structure must be filled in by a primary bootstrap or bootstrap
135 * server for a diskless/dataless machine. It is initialized below just
136 * to ensure that it is allocated to initialized data (.data not .bss).
138 struct nfs_diskless nfs_diskless = { 0 };
139 struct nfsv3_diskless nfsv3_diskless = { 0 };
140 int nfs_diskless_valid = 0;
142 SYSCTL_INT(_vfs_nfs, OID_AUTO, diskless_valid, CTLFLAG_RD,
143 &nfs_diskless_valid, 0, "");
145 SYSCTL_STRING(_vfs_nfs, OID_AUTO, diskless_rootpath, CTLFLAG_RD,
146 nfsv3_diskless.root_hostnam, 0, "");
148 SYSCTL_OPAQUE(_vfs_nfs, OID_AUTO, diskless_rootaddr, CTLFLAG_RD,
149 &nfsv3_diskless.root_saddr, sizeof nfsv3_diskless.root_saddr,
150 "%Ssockaddr_in", "");
152 SYSCTL_STRING(_vfs_nfs, OID_AUTO, diskless_swappath, CTLFLAG_RD,
153 nfsv3_diskless.swap_hostnam, 0, "");
155 SYSCTL_OPAQUE(_vfs_nfs, OID_AUTO, diskless_swapaddr, CTLFLAG_RD,
156 &nfsv3_diskless.swap_saddr, sizeof nfsv3_diskless.swap_saddr,
160 void nfsargs_ntoh __P((struct nfs_args *));
161 static int nfs_mountdiskless __P((char *, char *, int,
162 struct sockaddr_in *, struct nfs_args *,
163 struct proc *, struct vnode **,
165 void nfs_convert_diskless __P((void));
166 static void nfs_convert_oargs __P((struct nfs_args *args,
167 struct onfs_args *oargs));
169 static int nfs_iosize(nmp)
170 struct nfsmount* nmp;
175 * Calculate the size used for io buffers. Use the larger
176 * of the two sizes to minimise nfs requests but make sure
177 * that it is at least one VM page to avoid wasting buffer
180 iosize = max(nmp->nm_rsize, nmp->nm_wsize);
181 if (iosize < PAGE_SIZE) iosize = PAGE_SIZE;
185 static void nfs_convert_oargs(args,oargs)
186 struct nfs_args *args;
187 struct onfs_args *oargs;
189 args->version = NFS_ARGSVERSION;
190 args->addr = oargs->addr;
191 args->addrlen = oargs->addrlen;
192 args->sotype = oargs->sotype;
193 args->proto = oargs->proto;
194 args->fh = oargs->fh;
195 args->fhsize = oargs->fhsize;
196 args->flags = oargs->flags;
197 args->wsize = oargs->wsize;
198 args->rsize = oargs->rsize;
199 args->readdirsize = oargs->readdirsize;
200 args->timeo = oargs->timeo;
201 args->retrans = oargs->retrans;
202 args->maxgrouplist = oargs->maxgrouplist;
203 args->readahead = oargs->readahead;
204 args->leaseterm = oargs->leaseterm;
205 args->deadthresh = oargs->deadthresh;
206 args->hostname = oargs->hostname;
209 void nfs_convert_diskless()
211 bcopy(&nfs_diskless.myif, &nfsv3_diskless.myif,
212 sizeof(struct ifaliasreq));
213 bcopy(&nfs_diskless.mygateway, &nfsv3_diskless.mygateway,
214 sizeof(struct sockaddr_in));
215 nfs_convert_oargs(&nfsv3_diskless.swap_args,&nfs_diskless.swap_args);
216 nfsv3_diskless.swap_fhsize = NFSX_V2FH;
217 bcopy(nfs_diskless.swap_fh,nfsv3_diskless.swap_fh,NFSX_V2FH);
218 bcopy(&nfs_diskless.swap_saddr,&nfsv3_diskless.swap_saddr,
219 sizeof(struct sockaddr_in));
220 bcopy(nfs_diskless.swap_hostnam,nfsv3_diskless.swap_hostnam,
222 nfsv3_diskless.swap_nblks = nfs_diskless.swap_nblks;
223 bcopy(&nfs_diskless.swap_ucred, &nfsv3_diskless.swap_ucred,
224 sizeof(struct ucred));
225 nfs_convert_oargs(&nfsv3_diskless.root_args,&nfs_diskless.root_args);
226 nfsv3_diskless.root_fhsize = NFSX_V2FH;
227 bcopy(nfs_diskless.root_fh,nfsv3_diskless.root_fh,NFSX_V2FH);
228 bcopy(&nfs_diskless.root_saddr,&nfsv3_diskless.root_saddr,
229 sizeof(struct sockaddr_in));
230 bcopy(nfs_diskless.root_hostnam,nfsv3_diskless.root_hostnam,
232 nfsv3_diskless.root_time = nfs_diskless.root_time;
233 bcopy(nfs_diskless.my_hostnam,nfsv3_diskless.my_hostnam,
235 nfs_diskless_valid = 3;
242 nfs_statfs(mp, sbp, p)
244 register struct statfs *sbp;
247 register struct vnode *vp;
248 register struct nfs_statfs *sfp;
251 register long t1, t2;
252 caddr_t bpos, dpos, cp2;
253 struct nfsmount *nmp = VFSTONFS(mp);
254 int error = 0, v3 = (nmp->nm_flag & NFSMNT_NFSV3), retattr;
255 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
261 sfp = (struct nfs_statfs *)0;
263 error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np);
268 cred->cr_ngroups = 1;
269 if (v3 && (nmp->nm_flag & NFSMNT_GOTFSINFO) == 0)
270 (void)nfs_fsinfo(nmp, vp, cred, p);
271 nfsstats.rpccnt[NFSPROC_FSSTAT]++;
272 nfsm_reqhead(vp, NFSPROC_FSSTAT, NFSX_FH(v3));
274 nfsm_request(vp, NFSPROC_FSSTAT, p, cred);
276 nfsm_postop_attr(vp, retattr);
278 nfsm_dissect(sfp, struct nfs_statfs *, NFSX_STATFS(v3));
282 sbp->f_type = MOUNT_NFS;
283 sbp->f_flags = nmp->nm_flag;
284 sbp->f_iosize = nfs_iosize(nmp);
286 sbp->f_bsize = NFS_FABLKSIZE;
287 fxdr_hyper(&sfp->sf_tbytes, &tquad);
288 sbp->f_blocks = (long)(tquad / ((u_quad_t)NFS_FABLKSIZE));
289 fxdr_hyper(&sfp->sf_fbytes, &tquad);
290 sbp->f_bfree = (long)(tquad / ((u_quad_t)NFS_FABLKSIZE));
291 fxdr_hyper(&sfp->sf_abytes, &tquad);
292 sbp->f_bavail = (long)(tquad / ((u_quad_t)NFS_FABLKSIZE));
293 sbp->f_files = (fxdr_unsigned(long, sfp->sf_tfiles.nfsuquad[1])
295 sbp->f_ffree = (fxdr_unsigned(long, sfp->sf_ffiles.nfsuquad[1])
298 sbp->f_bsize = fxdr_unsigned(long, sfp->sf_bsize);
299 sbp->f_blocks = fxdr_unsigned(long, sfp->sf_blocks);
300 sbp->f_bfree = fxdr_unsigned(long, sfp->sf_bfree);
301 sbp->f_bavail = fxdr_unsigned(long, sfp->sf_bavail);
305 if (sbp != &mp->mnt_stat) {
306 bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
307 bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
316 * nfs version 3 fsinfo rpc call
319 nfs_fsinfo(nmp, vp, cred, p)
320 register struct nfsmount *nmp;
321 register struct vnode *vp;
325 register struct nfsv3_fsinfo *fsp;
327 register long t1, t2;
328 register u_long *tl, pref, max;
329 caddr_t bpos, dpos, cp2;
330 int error = 0, retattr;
331 struct mbuf *mreq, *mrep, *md, *mb, *mb2;
333 nfsstats.rpccnt[NFSPROC_FSINFO]++;
334 nfsm_reqhead(vp, NFSPROC_FSINFO, NFSX_FH(1));
336 nfsm_request(vp, NFSPROC_FSINFO, p, cred);
337 nfsm_postop_attr(vp, retattr);
339 nfsm_dissect(fsp, struct nfsv3_fsinfo *, NFSX_V3FSINFO);
340 pref = fxdr_unsigned(u_long, fsp->fs_wtpref);
341 if (pref < nmp->nm_wsize)
342 nmp->nm_wsize = (pref + NFS_FABLKSIZE - 1) &
343 ~(NFS_FABLKSIZE - 1);
344 max = fxdr_unsigned(u_long, fsp->fs_wtmax);
345 if (max < nmp->nm_wsize) {
346 nmp->nm_wsize = max & ~(NFS_FABLKSIZE - 1);
347 if (nmp->nm_wsize == 0)
350 pref = fxdr_unsigned(u_long, fsp->fs_rtpref);
351 if (pref < nmp->nm_rsize)
352 nmp->nm_rsize = (pref + NFS_FABLKSIZE - 1) &
353 ~(NFS_FABLKSIZE - 1);
354 max = fxdr_unsigned(u_long, fsp->fs_rtmax);
355 if (max < nmp->nm_rsize) {
356 nmp->nm_rsize = max & ~(NFS_FABLKSIZE - 1);
357 if (nmp->nm_rsize == 0)
360 pref = fxdr_unsigned(u_long, fsp->fs_dtpref);
361 if (pref < nmp->nm_readdirsize)
362 nmp->nm_readdirsize = pref;
363 if (max < nmp->nm_readdirsize) {
364 nmp->nm_readdirsize = max;
366 nmp->nm_flag |= NFSMNT_GOTFSINFO;
373 * Mount a remote root fs via. nfs. This depends on the info in the
374 * nfs_diskless structure that has been filled in properly by some primary
376 * It goes something like this:
377 * - do enough of "ifconfig" by calling ifioctl() so that the system
378 * can talk to the server
379 * - If nfs_diskless.mygateway is filled in, use that address as
381 * - build the rootfs mount point and call mountnfs() to do the rest.
387 struct mount *swap_mp;
388 struct nfsv3_diskless *nd = &nfsv3_diskless;
391 struct proc *p = curproc; /* XXX */
397 * XXX time must be non-zero when we init the interface or else
398 * the arp code will wedge...
400 if (time.tv_sec == 0)
403 if (nfs_diskless_valid==1)
404 nfs_convert_diskless();
407 * XXX splnet, so networks will receive...
412 /* Set up swap credentials. */
413 proc0.p_ucred->cr_uid = ntohl(nd->swap_ucred.cr_uid);
414 proc0.p_ucred->cr_gid = ntohl(nd->swap_ucred.cr_gid);
415 if ((proc0.p_ucred->cr_ngroups = ntohs(nd->swap_ucred.cr_ngroups)) >
417 proc0.p_ucred->cr_ngroups = NGROUPS;
418 for (i = 0; i < proc0.p_ucred->cr_ngroups; i++)
419 proc0.p_ucred->cr_groups[i] = ntohl(nd->swap_ucred.cr_groups[i]);
423 * Do enough of ifconfig(8) so that the critical net interface can
424 * talk to the server.
426 error = socreate(nd->myif.ifra_addr.sa_family, &so, SOCK_DGRAM, 0, p);
428 panic("nfs_mountroot: socreate(%04x): %d",
429 nd->myif.ifra_addr.sa_family, error);
432 * We might not have been told the right interface, so we pass
433 * over the first ten interfaces of the same kind, until we get
434 * one of them configured.
437 for (i = strlen(nd->myif.ifra_name) - 1;
438 nd->myif.ifra_name[i] >= '0' &&
439 nd->myif.ifra_name[i] <= '9';
440 nd->myif.ifra_name[i] ++) {
441 error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, p);
446 panic("nfs_mountroot: SIOCAIFADDR: %d", error);
450 * If the gateway field is filled in, set it as the default route.
452 if (nd->mygateway.sin_len != 0) {
453 struct sockaddr_in mask, sin;
455 bzero((caddr_t)&mask, sizeof(mask));
457 sin.sin_family = AF_INET;
458 sin.sin_len = sizeof(sin);
459 error = rtrequest(RTM_ADD, (struct sockaddr *)&sin,
460 (struct sockaddr *)&nd->mygateway,
461 (struct sockaddr *)&mask,
462 RTF_UP | RTF_GATEWAY, (struct rtentry **)0);
464 panic("nfs_mountroot: RTM_ADD: %d", error);
468 * Create the rootfs mount point.
470 nd->root_args.fh = nd->root_fh;
471 nd->root_args.fhsize = nd->root_fhsize;
472 l = ntohl(nd->root_saddr.sin_addr.s_addr);
473 sprintf(buf,"%ld.%ld.%ld.%ld:%s",
474 (l >> 24) & 0xff, (l >> 16) & 0xff,
475 (l >> 8) & 0xff, (l >> 0) & 0xff,nd->root_hostnam);
476 printf("NFS ROOT: %s\n",buf);
477 if (error = nfs_mountdiskless(buf, "/", MNT_RDONLY,
478 &nd->root_saddr, &nd->root_args, p, &vp, &mp)) {
480 mp->mnt_vfc->vfc_refcount--;
481 free(swap_mp, M_MOUNT);
487 if (nd->swap_nblks) {
489 /* Convert to DEV_BSIZE instead of Kilobyte */
493 * Create a fake mount point just for the swap vnode so that the
494 * swap file can be on a different server from the rootfs.
496 nd->swap_args.fh = nd->swap_fh;
497 nd->swap_args.fhsize = nd->swap_fhsize;
498 l = ntohl(nd->swap_saddr.sin_addr.s_addr);
499 sprintf(buf,"%ld.%ld.%ld.%ld:%s",
500 (l >> 24) & 0xff, (l >> 16) & 0xff,
501 (l >> 8) & 0xff, (l >> 0) & 0xff,nd->swap_hostnam);
502 printf("NFS SWAP: %s\n",buf);
503 if (error = nfs_mountdiskless(buf, "/swap", 0,
504 &nd->swap_saddr, &nd->swap_args, p, &vp, &swap_mp))
506 vfs_unbusy(swap_mp, p);
508 VTONFS(vp)->n_size = VTONFS(vp)->n_vattr.va_size =
509 nd->swap_nblks * DEV_BSIZE ;
512 * Since the swap file is not the root dir of a file system,
513 * hack it to a regular file.
518 swaponvp(p, vp, NODEV, nd->swap_nblks);
521 mp->mnt_flag |= MNT_ROOTFS;
522 mp->mnt_vnodecovered = NULLVP;
527 * This is not really an nfs issue, but it is much easier to
528 * set hostname here and then let the "/etc/rc.xxx" files
529 * mount the right /var based upon its preset value.
531 bcopy(nd->my_hostnam, hostname, MAXHOSTNAMELEN);
532 hostname[MAXHOSTNAMELEN - 1] = '\0';
533 for (i = 0; i < MAXHOSTNAMELEN; i++)
534 if (hostname[i] == '\0')
536 inittodr(ntohl(nd->root_time));
541 * Internal version of mount system call for diskless setup.
544 nfs_mountdiskless(path, which, mountflag, sin, args, p, vpp, mpp)
548 struct sockaddr_in *sin;
549 struct nfs_args *args;
555 struct sockaddr *nam;
560 if (!mp && (error = vfs_rootmountalloc("nfs", path, &mp))) {
561 printf("nfs_mountroot: NFS not configured");
565 mp->mnt_kern_flag = 0;
566 mp->mnt_flag = mountflag;
567 nam = dup_sockaddr((struct sockaddr *)sin, 1);
568 if (error = mountnfs(args, mp, nam, which, path, vpp)) {
569 printf("nfs_mountroot: mount %s on %s: %d", path, which, error);
570 mp->mnt_vfc->vfc_refcount--;
576 (void) copystr(which, mp->mnt_stat.f_mntonname, MNAMELEN - 1, 0);
585 * It seems a bit dumb to copyinstr() the host and path here and then
586 * bcopy() them in mountnfs(), but I wanted to detect errors before
587 * doing the sockargs() call because sockargs() allocates an mbuf and
588 * an error after that means that I have to release the mbuf.
592 nfs_mount(mp, path, data, ndp, p)
596 struct nameidata *ndp;
600 struct nfs_args args;
601 struct sockaddr *nam;
603 char pth[MNAMELEN], hst[MNAMELEN];
605 u_char nfh[NFSX_V3FHMAX];
611 error = copyin(data, (caddr_t)&args, sizeof (struct nfs_args));
614 if (args.version != NFS_ARGSVERSION) {
615 #ifndef NO_COMPAT_PRELITE2
617 * If the argument version is unknown, then assume the
618 * caller is a pre-lite2 4.4BSD client and convert its
621 struct onfs_args oargs;
622 error = copyin(data, (caddr_t)&oargs, sizeof (struct onfs_args));
625 nfs_convert_oargs(&args,&oargs);
626 #else /* NO_COMPAT_PRELITE2 */
627 return (EPROGMISMATCH);
628 #endif /* !NO_COMPAT_PRELITE2 */
630 error = copyin((caddr_t)args.fh, (caddr_t)nfh, args.fhsize);
633 error = copyinstr(path, pth, MNAMELEN-1, &len);
636 bzero(&pth[len], MNAMELEN - len);
637 error = copyinstr(args.hostname, hst, MNAMELEN-1, &len);
640 bzero(&hst[len], MNAMELEN - len);
641 /* sockargs() call must be after above copyin() calls */
642 error = getsockaddr(&nam, (caddr_t)args.addr, args.addrlen);
646 error = mountnfs(&args, mp, nam, pth, hst, &vp);
651 * Common code for mount and mountroot
654 mountnfs(argp, mp, nam, pth, hst, vpp)
655 register struct nfs_args *argp;
656 register struct mount *mp;
657 struct sockaddr *nam;
661 register struct nfsmount *nmp;
666 if (mp->mnt_flag & MNT_UPDATE) {
668 /* update paths, file handles, etc, here XXX */
672 MALLOC(nmp, struct nfsmount *, sizeof (struct nfsmount),
674 bzero((caddr_t)nmp, sizeof (struct nfsmount));
675 TAILQ_INIT(&nmp->nm_uidlruhead);
676 TAILQ_INIT(&nmp->nm_bufq);
677 mp->mnt_data = (qaddr_t)nmp;
681 nmp->nm_flag = argp->flags;
682 if (nmp->nm_flag & NFSMNT_NQNFS)
684 * We have to set mnt_maxsymlink to a non-zero value so
685 * that COMPAT_43 routines will know that we are setting
686 * the d_type field in directories (and can zero it for
687 * unsuspecting binaries).
689 mp->mnt_maxsymlinklen = 1;
690 nmp->nm_timeo = NFS_TIMEO;
691 nmp->nm_retry = NFS_RETRANS;
692 nmp->nm_wsize = NFS_WSIZE;
693 nmp->nm_rsize = NFS_RSIZE;
694 nmp->nm_readdirsize = NFS_READDIRSIZE;
695 nmp->nm_numgrps = NFS_MAXGRPS;
696 nmp->nm_readahead = NFS_DEFRAHEAD;
697 nmp->nm_leaseterm = NQ_DEFLEASE;
698 nmp->nm_deadthresh = NQ_DEADTHRESH;
699 CIRCLEQ_INIT(&nmp->nm_timerhead);
700 nmp->nm_inprog = NULLVP;
701 nmp->nm_fhsize = argp->fhsize;
702 bcopy((caddr_t)argp->fh, (caddr_t)nmp->nm_fh, argp->fhsize);
703 bcopy(hst, mp->mnt_stat.f_mntfromname, MNAMELEN);
704 bcopy(pth, mp->mnt_stat.f_mntonname, MNAMELEN);
708 * Silently clear NFSMNT_NOCONN if it's a TCP mount, it makes
709 * no sense in that context.
711 if (argp->sotype == SOCK_STREAM)
712 argp->flags &= ~NFSMNT_NOCONN;
714 if ((argp->flags & NFSMNT_TIMEO) && argp->timeo > 0) {
715 nmp->nm_timeo = (argp->timeo * NFS_HZ + 5) / 10;
716 if (nmp->nm_timeo < NFS_MINTIMEO)
717 nmp->nm_timeo = NFS_MINTIMEO;
718 else if (nmp->nm_timeo > NFS_MAXTIMEO)
719 nmp->nm_timeo = NFS_MAXTIMEO;
722 if ((argp->flags & NFSMNT_RETRANS) && argp->retrans > 1) {
723 nmp->nm_retry = argp->retrans;
724 if (nmp->nm_retry > NFS_MAXREXMIT)
725 nmp->nm_retry = NFS_MAXREXMIT;
728 if (argp->flags & NFSMNT_NFSV3) {
729 if (argp->sotype == SOCK_DGRAM)
730 maxio = NFS_MAXDGRAMDATA;
734 maxio = NFS_V2MAXDATA;
736 if ((argp->flags & NFSMNT_WSIZE) && argp->wsize > 0) {
737 nmp->nm_wsize = argp->wsize;
738 /* Round down to multiple of blocksize */
739 nmp->nm_wsize &= ~(NFS_FABLKSIZE - 1);
740 if (nmp->nm_wsize <= 0)
741 nmp->nm_wsize = NFS_FABLKSIZE;
743 if (nmp->nm_wsize > maxio)
744 nmp->nm_wsize = maxio;
745 if (nmp->nm_wsize > MAXBSIZE)
746 nmp->nm_wsize = MAXBSIZE;
748 if ((argp->flags & NFSMNT_RSIZE) && argp->rsize > 0) {
749 nmp->nm_rsize = argp->rsize;
750 /* Round down to multiple of blocksize */
751 nmp->nm_rsize &= ~(NFS_FABLKSIZE - 1);
752 if (nmp->nm_rsize <= 0)
753 nmp->nm_rsize = NFS_FABLKSIZE;
755 if (nmp->nm_rsize > maxio)
756 nmp->nm_rsize = maxio;
757 if (nmp->nm_rsize > MAXBSIZE)
758 nmp->nm_rsize = MAXBSIZE;
760 if ((argp->flags & NFSMNT_READDIRSIZE) && argp->readdirsize > 0) {
761 nmp->nm_readdirsize = argp->readdirsize;
763 if (nmp->nm_readdirsize > maxio)
764 nmp->nm_readdirsize = maxio;
765 if (nmp->nm_readdirsize > nmp->nm_rsize)
766 nmp->nm_readdirsize = nmp->nm_rsize;
768 if ((argp->flags & NFSMNT_MAXGRPS) && argp->maxgrouplist >= 0 &&
769 argp->maxgrouplist <= NFS_MAXGRPS)
770 nmp->nm_numgrps = argp->maxgrouplist;
771 if ((argp->flags & NFSMNT_READAHEAD) && argp->readahead >= 0 &&
772 argp->readahead <= NFS_MAXRAHEAD)
773 nmp->nm_readahead = argp->readahead;
774 if ((argp->flags & NFSMNT_LEASETERM) && argp->leaseterm >= 2 &&
775 argp->leaseterm <= NQ_MAXLEASE)
776 nmp->nm_leaseterm = argp->leaseterm;
777 if ((argp->flags & NFSMNT_DEADTHRESH) && argp->deadthresh >= 1 &&
778 argp->deadthresh <= NQ_NEVERDEAD)
779 nmp->nm_deadthresh = argp->deadthresh;
780 /* Set up the sockets and per-host congestion */
781 nmp->nm_sotype = argp->sotype;
782 nmp->nm_soproto = argp->proto;
785 * For Connection based sockets (TCP,...) defer the connect until
786 * the first request, in case the server is not responding.
788 if (nmp->nm_sotype == SOCK_DGRAM &&
789 (error = nfs_connect(nmp, (struct nfsreq *)0)))
793 * This is silly, but it has to be set so that vinifod() works.
794 * We do not want to do an nfs_statfs() here since we can get
795 * stuck on a dead server and we are holding a lock on the mount
798 mp->mnt_stat.f_iosize = nfs_iosize(nmp);
800 * A reference count is needed on the nfsnode representing the
801 * remote root. If this object is not persistent, then backward
802 * traversals of the mount point (i.e. "..") will not work if
803 * the nfsnode gets flushed out of the cache. Ufs does not have
804 * this problem, because one can identify root inodes by their
805 * number == ROOTINO (2).
807 error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np);
813 * Get file attributes for the mountpoint. This has the side
814 * effect of filling in (*vpp)->v_type with the correct value.
816 VOP_GETATTR(*vpp, &attrs, curproc->p_ucred, curproc);
819 * Lose the lock but keep the ref.
821 VOP_UNLOCK(*vpp, 0, curproc);
826 free((caddr_t)nmp, M_NFSMNT);
832 * unmount system call
835 nfs_unmount(mp, mntflags, p)
840 register struct nfsmount *nmp;
843 int error, flags = 0;
845 if (mntflags & MNT_FORCE)
849 * Goes something like this..
850 * - Check for activity on the root vnode (other than ourselves).
851 * - Call vflush() to clear out vnodes for this file system,
852 * except for the root vnode.
853 * - Decrement reference on the vnode representing remote root.
855 * - Free up the data structures
858 * We need to decrement the ref. count on the nfsnode representing
859 * the remote root. See comment in mountnfs(). The VFS unmount()
860 * has done vput on this vnode, otherwise we would get deadlock!
862 error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np);
866 if (vp->v_usecount > 2) {
872 * Must handshake with nqnfs_clientd() if it is active.
874 nmp->nm_flag |= NFSMNT_DISMINPROG;
875 while (nmp->nm_inprog != NULLVP)
876 (void) tsleep((caddr_t)&lbolt, PSOCK, "nfsdism", 0);
877 error = vflush(mp, vp, flags);
880 nmp->nm_flag &= ~NFSMNT_DISMINPROG;
885 * We are now committed to the unmount.
886 * For NQNFS, let the server daemon free the nfsmount structure.
888 if (nmp->nm_flag & (NFSMNT_NQNFS | NFSMNT_KERB))
889 nmp->nm_flag |= NFSMNT_DISMNT;
892 * There are two reference counts and one lock to get rid of here.
898 FREE(nmp->nm_nam, M_SONAME);
900 if ((nmp->nm_flag & (NFSMNT_NQNFS | NFSMNT_KERB)) == 0)
901 free((caddr_t)nmp, M_NFSMNT);
906 * Return root of a filesystem
913 register struct vnode *vp;
914 struct nfsmount *nmp;
919 error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np);
923 if (vp->v_type == VNON)
933 * Flush out the buffer cache
937 nfs_sync(mp, waitfor, cred, p)
943 register struct vnode *vp;
944 int error, allerror = 0;
947 * Force stale buffer cache information to be flushed.
950 for (vp = mp->mnt_vnodelist.lh_first;
952 vp = vp->v_mntvnodes.le_next) {
954 * If the vnode that we are about to sync is no longer
955 * associated with this mount point, start over.
957 if (vp->v_mount != mp)
959 if (VOP_ISLOCKED(vp) || vp->v_dirtyblkhd.lh_first == NULL)
961 if (vget(vp, LK_EXCLUSIVE, p))
963 error = VOP_FSYNC(vp, cred, waitfor, p);
972 * NFS flat namespace lookup.
973 * Currently unsupported.
977 nfs_vget(mp, ino, vpp)
987 * At this point, this should never happen
991 nfs_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp)
992 register struct mount *mp;
994 struct sockaddr *nam;
997 struct ucred **credanonp;
1004 * Vnode pointer to File handle, should never happen either
1017 * Vfs start routine, a no-op.
1021 nfs_start(mp, flags, p)
1031 * Do operations associated with quotas, not supported
1035 nfs_quotactl(mp, cmd, uid, arg, p)
1043 return (EOPNOTSUPP);