xref: /csrg-svn/sys/nfs/nfs_vfsops.c (revision 39669)
138414Smckusick /*
238414Smckusick  * Copyright (c) 1989 The Regents of the University of California.
338414Smckusick  * All rights reserved.
438414Smckusick  *
538414Smckusick  * This code is derived from software contributed to Berkeley by
638414Smckusick  * Rick Macklem at The University of Guelph.
738414Smckusick  *
838414Smckusick  * Redistribution and use in source and binary forms are permitted
938414Smckusick  * provided that the above copyright notice and this paragraph are
1038414Smckusick  * duplicated in all such forms and that any documentation,
1138414Smckusick  * advertising materials, and other materials related to such
1238414Smckusick  * distribution and use acknowledge that the software was developed
1338414Smckusick  * by the University of California, Berkeley.  The name of the
1438414Smckusick  * University may not be used to endorse or promote products derived
1538414Smckusick  * from this software without specific prior written permission.
1638414Smckusick  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1738414Smckusick  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1838414Smckusick  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1938414Smckusick  *
20*39669Smckusick  *	@(#)nfs_vfsops.c	7.10 (Berkeley) 11/30/89
2138414Smckusick  */
2238414Smckusick 
2338414Smckusick #include "param.h"
2438414Smckusick #include "signal.h"
2538414Smckusick #include "user.h"
2638414Smckusick #include "proc.h"
2738414Smckusick #include "uio.h"
2838414Smckusick #include "ucred.h"
2938425Smckusick #include "../ufs/dir.h"
3038414Smckusick #include "namei.h"
3138414Smckusick #include "vnode.h"
3238414Smckusick #include "mount.h"
3338414Smckusick #include "errno.h"
3438414Smckusick #include "malloc.h"
3538414Smckusick #include "mbuf.h"
3638414Smckusick #undef	m_data
3738414Smckusick #include "socket.h"
3838414Smckusick #include "socketvar.h"
3938414Smckusick #include "../netinet/in.h"
4038414Smckusick #include "nfsv2.h"
4138414Smckusick #include "nfsnode.h"
4238414Smckusick #include "nfsmount.h"
4338414Smckusick #include "nfs.h"
4438414Smckusick 
4538414Smckusick #ifndef shouldbe
4638414Smckusick #include "conf.h"
4738414Smckusick #endif
4838414Smckusick 
4938414Smckusick /*
5038414Smckusick  * nfs vfs operations.
5138414Smckusick  */
5238414Smckusick int nfs_mount();
5338874Smckusick int nfs_start();
5438414Smckusick int nfs_unmount();
5538414Smckusick int nfs_root();
5639443Smckusick int nfs_statfs();
5738414Smckusick int nfs_sync();
5838414Smckusick int nfs_fhtovp();
5938414Smckusick int nfs_vptofh();
6039443Smckusick int nfs_init();
6138414Smckusick 
6238414Smckusick struct vfsops nfs_vfsops = {
6338414Smckusick 	nfs_mount,
6438874Smckusick 	nfs_start,
6538414Smckusick 	nfs_unmount,
6638414Smckusick 	nfs_root,
6738414Smckusick 	nfs_statfs,
6838414Smckusick 	nfs_sync,
6938414Smckusick 	nfs_fhtovp,
7038414Smckusick 	nfs_vptofh,
7139443Smckusick 	nfs_init,
7238414Smckusick };
7338414Smckusick 
7438414Smckusick extern struct nfsreq nfsreqh;
7538414Smckusick static long nfs_mntid;
7638414Smckusick 
7738414Smckusick /*
7838414Smckusick  * Called by vfs_mountroot when nfs is going to be mounted as root
7938414Smckusick  * Not Yet (By a LONG shot)
8038414Smckusick  */
8138414Smckusick nfs_mountroot()
8238414Smckusick {
8338414Smckusick 	return (ENODEV);
8438414Smckusick }
8538414Smckusick 
8638414Smckusick /*
8738414Smckusick  * VFS Operations.
8838414Smckusick  *
8938414Smckusick  * mount system call
9038414Smckusick  * It seems a bit dumb to copyinstr() the host and path here and then
9138414Smckusick  * bcopy() them in mountnfs(), but I wanted to detect errors before
9238414Smckusick  * doing the sockargs() call because sockargs() allocates an mbuf and
9338414Smckusick  * an error after that means that I have to release the mbuf.
9438414Smckusick  */
9539494Smckusick /* ARGSUSED */
9638414Smckusick nfs_mount(mp, path, data, ndp)
9738414Smckusick 	struct mount *mp;
9838414Smckusick 	char *path;
9938414Smckusick 	caddr_t data;
10038414Smckusick 	struct nameidata *ndp;
10138414Smckusick {
10238414Smckusick 	int error;
10338414Smckusick 	struct nfs_args args;
10438414Smckusick 	struct mbuf *saddr;
10538414Smckusick 	char pth[MNAMELEN], hst[MNAMELEN];
10638414Smckusick 	int len;
10738414Smckusick 	nfsv2fh_t nfh;
10838414Smckusick 
10939460Smckusick 	if (mp->m_flag & M_UPDATE)
11039460Smckusick 		return (0);
11138414Smckusick 	if (error = copyin(data, (caddr_t)&args, sizeof (struct nfs_args)))
11238414Smckusick 		return (error);
11338414Smckusick 	if (error=copyin((caddr_t)args.fh, (caddr_t)&nfh, sizeof (nfsv2fh_t)))
11438414Smckusick 		return (error);
11538414Smckusick 	if (error = copyinstr(path, pth, MNAMELEN-1, &len))
11638414Smckusick 		return (error);
11738414Smckusick 	bzero(&pth[len], MNAMELEN-len);
11838414Smckusick 	if (error = copyinstr(args.hostname, hst, MNAMELEN-1, &len))
11938414Smckusick 		return (error);
12038414Smckusick 	bzero(&hst[len], MNAMELEN-len);
12138414Smckusick 	/* sockargs() call must be after above copyin() calls */
12238414Smckusick 	if (error = sockargs(&saddr, (caddr_t)args.addr,
12338414Smckusick 		sizeof (struct sockaddr_in), MT_SONAME))
12438414Smckusick 		return (error);
12538414Smckusick 	args.fh = &nfh;
12638414Smckusick 	error = mountnfs(&args, mp, saddr, pth, hst);
12738414Smckusick 	return (error);
12838414Smckusick }
12938414Smckusick 
13038414Smckusick /*
13138414Smckusick  * Common code for mount and mountroot
13238414Smckusick  */
13338414Smckusick mountnfs(argp, mp, saddr, pth, hst)
13438414Smckusick 	register struct nfs_args *argp;
13538414Smckusick 	register struct mount *mp;
13638414Smckusick 	register struct mbuf *saddr;
13738414Smckusick 	char *pth, *hst;
13838414Smckusick {
13938414Smckusick 	register struct nfsmount *nmp;
14038425Smckusick #ifdef notdef
14138414Smckusick 	struct statfs statf, *sbp;
14238425Smckusick #endif
14338414Smckusick 	int error;
14438414Smckusick 
14538414Smckusick 	nmp = (struct nfsmount *)malloc(sizeof (struct nfsmount), M_NFSMNT,
14638414Smckusick 	    M_WAITOK);
14738414Smckusick 	mp->m_data = (qaddr_t)nmp;
14838414Smckusick 	mp->m_fsid.val[0] = ++nfs_mntid;
14938414Smckusick 	mp->m_fsid.val[1] = MOUNT_NFS;
15038414Smckusick 	nmp->nm_mountp = mp;
15138414Smckusick 	nmp->nm_flag = argp->flags;
15238414Smckusick 	nmp->nm_sockaddr = saddr;
15338414Smckusick 	/* Set up the sockets */
15438414Smckusick 	if (error = socreate(AF_INET, &nmp->nm_so, SOCK_DGRAM, 0))
15538414Smckusick 		goto bad;
15638414Smckusick 	if (error = soconnect(nmp->nm_so, saddr))
15738414Smckusick 		goto bad;
15838414Smckusick 	if ((argp->flags & NFSMNT_TIMEO) && argp->timeo >= 1)
15938414Smckusick 		nmp->nm_timeo = argp->timeo;
16038414Smckusick 	else
16138414Smckusick 		nmp->nm_timeo = NFS_TIMEO;
16238414Smckusick 	if ((argp->flags & NFSMNT_RETRANS) && argp->retrans > 0)
16338414Smckusick 		nmp->nm_retrans = argp->retrans;
16438414Smckusick 	else
16538414Smckusick 		nmp->nm_retrans = NFS_RETRANS;
16638414Smckusick 	if ((argp->flags & NFSMNT_WSIZE) &&
16738414Smckusick 	    argp->wsize <= NFS_MAXDATA && argp->wsize > 0 &&
16838414Smckusick 	   (argp->wsize & 0x1ff) == 0)
16938414Smckusick 		nmp->nm_wsize = argp->wsize;
17038414Smckusick 	else
17138414Smckusick 		nmp->nm_wsize = NFS_WSIZE;
17238414Smckusick 	if ((argp->flags & NFSMNT_RSIZE) &&
17338414Smckusick 	    argp->rsize <= NFS_MAXDATA && argp->rsize > 0 &&
17438414Smckusick 	   (argp->rsize & 0x1ff) == 0)
17538414Smckusick 		nmp->nm_rsize = argp->rsize;
17638414Smckusick 	else
17738414Smckusick 		nmp->nm_rsize = NFS_RSIZE;
17838414Smckusick 	bcopy((caddr_t)argp->fh, (caddr_t)&nmp->nm_fh, sizeof(nfsv2fh_t));
17938414Smckusick 	bcopy(pth, nmp->nm_path, MNAMELEN);
18038414Smckusick 	bcopy(hst, nmp->nm_host, MNAMELEN);
18138425Smckusick #ifdef notdef
18238414Smckusick 	sbp = &statf;
18338414Smckusick 	/*
18438414Smckusick 	 * Kludge City...
18538414Smckusick 	 * To do an interruptable hard mount, turn it into a soft mount
18638414Smckusick 	 * with a retry limit of one and then repeat it so long as it
18738414Smckusick 	 * times out and there is no pending signal for the process.
18838414Smckusick 	 * It is tempting to just let nfs_statfs() sleep at positive
18938414Smckusick 	 * prio, but then you would long jump out without taking the
19038414Smckusick 	 * mount structure back out of the list.
19138414Smckusick 	 * NB: NFSMNT_INT must NEVER be set for nfs_mountroot(), since
19238414Smckusick 	 * the process context is not yet built!!
19338414Smckusick 	 */
19438414Smckusick 	if ((argp->flags && NFSMNT_INT) && (argp->flags & NFSMNT_SOFT) == 0) {
19538414Smckusick 		int savretrans;
19638414Smckusick 
19738414Smckusick 		nmp->nm_flag |= NFSMNT_SOFT;
19838414Smckusick 		savretrans = nmp->nm_retrans;
19938414Smckusick 		nmp->nm_retrans = 1;
20038414Smckusick 		do {
20138414Smckusick 			error = nfs_statfs(mp, sbp);
20238414Smckusick 		} while (error == ETIMEDOUT && (u.u_procp->p_sig &
20338414Smckusick 			(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGTERM)|
20438414Smckusick 			 sigmask(SIGKILL))) == 0);
20538414Smckusick 		nmp->nm_retrans = savretrans;
20638414Smckusick 		nmp->nm_flag &= ~NFSMNT_SOFT;
20738414Smckusick 		if (error)
20838414Smckusick 			goto bad;
20938414Smckusick 	} else if (error = nfs_statfs(mp, sbp))
21038414Smckusick 		goto bad;
21138414Smckusick 	mp->m_fsize = sbp->f_fsize;
21238414Smckusick 
21338414Smckusick 	/*
21438414Smckusick 	 * If the block size is not an exact multiple of CLBYTES
21538414Smckusick 	 * use CLBYTES so that paging in ZMAGIC executables doesn't
21638414Smckusick 	 * get sick. (It is used by vinitfod())
21738414Smckusick 	 */
21838414Smckusick 	if (sbp->f_bsize >= CLBYTES && claligned(sbp->f_bsize))
21938414Smckusick 		mp->m_bsize = sbp->f_bsize;
22038414Smckusick 	else
22138414Smckusick 		mp->m_bsize = CLBYTES;
22238425Smckusick #else
22338425Smckusick 	/*
22438425Smckusick 	 * Set to CLBYTES so that vinifod() doesn't get confused.
22538425Smckusick 	 * Actually any exact multiple of CLBYTES will do
22638425Smckusick 	 */
22738425Smckusick 	mp->m_bsize = mp->m_fsize = CLBYTES;
22838425Smckusick #endif
22938414Smckusick 	return (0);
23038414Smckusick bad:
23138414Smckusick 	m_freem(saddr);
23238414Smckusick 	free((caddr_t)nmp, M_NFSMNT);
23338414Smckusick 	return (error);
23438414Smckusick }
23538414Smckusick 
23638414Smckusick /*
23738414Smckusick  * unmount system call
23838414Smckusick  */
23938414Smckusick nfs_unmount(mp, flags)
24038414Smckusick 	struct mount *mp;
24138414Smckusick 	int flags;
24238414Smckusick {
24338414Smckusick 	register struct nfsmount *nmp;
24438414Smckusick 	register struct nfsreq *rep;
24538414Smckusick 	struct nfsreq *rep2;
24638414Smckusick 	int error;
24738414Smckusick 	int s;
24838414Smckusick 
24938414Smckusick 	if (flags & MNT_FORCE)
25038414Smckusick 		return (EINVAL);
25138414Smckusick 	nmp = vfs_to_nfs(mp);
25238414Smckusick 	/*
25338884Smacklem 	 * Clear out the buffer cache
25438884Smacklem 	 */
255*39669Smckusick 	mntflushbuf(mp, 0);
256*39669Smckusick 	if (mntinvalbuf(mp))
25738884Smacklem 		return (EBUSY);
25838884Smacklem 	/*
25938414Smckusick 	 * Goes something like this..
26039510Smckusick 	 * - Call vflush() to clear out vnodes for this file system
26138414Smckusick 	 * - Flush out lookup cache
26238414Smckusick 	 * - Close the socket
26338414Smckusick 	 * - Free up the data structures
26438414Smckusick 	 */
26539510Smckusick 	if (error = vflush(mp, (struct vnode *)0, flags))
26638414Smckusick 		return (error);
26738414Smckusick 	/*
26838414Smckusick 	 * Scan the request list for any requests left hanging about
26938414Smckusick 	 */
27038414Smckusick 	s = splnet();
27138414Smckusick 	rep = nfsreqh.r_next;
27239347Smckusick 	while (rep && rep != &nfsreqh) {
27338414Smckusick 		if (rep->r_mntp == nmp) {
27438414Smckusick 			rep->r_prev->r_next = rep2 = rep->r_next;
27539347Smckusick 			rep->r_next->r_prev = rep->r_prev;
27638414Smckusick 			m_freem(rep->r_mreq);
27738414Smckusick 			if (rep->r_mrep != NULL)
27838414Smckusick 				m_freem(rep->r_mrep);
27938414Smckusick 			free((caddr_t)rep, M_NFSREQ);
28038414Smckusick 			rep = rep2;
28138414Smckusick 		} else
28238414Smckusick 			rep = rep->r_next;
28338414Smckusick 	}
28438414Smckusick 	splx(s);
28538414Smckusick 	soclose(nmp->nm_so);
28638414Smckusick 	m_freem(nmp->nm_sockaddr);
28738414Smckusick 	free((caddr_t)nmp, M_NFSMNT);
28838414Smckusick 	return (0);
28938414Smckusick }
29038414Smckusick 
29138414Smckusick /*
29238414Smckusick  * Return root of a filesystem
29338414Smckusick  */
29438414Smckusick nfs_root(mp, vpp)
29538414Smckusick 	struct mount *mp;
29638414Smckusick 	struct vnode **vpp;
29738414Smckusick {
29838414Smckusick 	register struct vnode *vp;
29938414Smckusick 	struct nfsmount *nmp;
30038414Smckusick 	struct nfsnode *np;
30138414Smckusick 	int error;
30238414Smckusick 
30338414Smckusick 	nmp = vfs_to_nfs(mp);
30438414Smckusick 	if (error = nfs_nget(mp, &nmp->nm_fh, &np))
30538414Smckusick 		return (error);
30638414Smckusick 	vp = NFSTOV(np);
30738414Smckusick 	vp->v_type = VDIR;
30838414Smckusick 	vp->v_flag = VROOT;
30938414Smckusick 	*vpp = vp;
31038414Smckusick 	return (0);
31138414Smckusick }
31238414Smckusick 
31338884Smacklem extern int syncprt;
31438884Smacklem 
31538414Smckusick /*
31638884Smacklem  * Flush out the buffer cache
31738414Smckusick  */
31839494Smckusick /* ARGSUSED */
31938414Smckusick nfs_sync(mp, waitfor)
32038414Smckusick 	struct mount *mp;
32138414Smckusick 	int waitfor;
32238414Smckusick {
32338884Smacklem 	if (syncprt)
32438884Smacklem 		bufstats();
32538884Smacklem 	/*
32638884Smacklem 	 * Force stale buffer cache information to be flushed.
32738884Smacklem 	 */
328*39669Smckusick 	mntflushbuf(mp);
32938414Smckusick 	return (0);
33038414Smckusick }
33138414Smckusick 
33238414Smckusick /*
33338414Smckusick  * At this point, this should never happen
33438414Smckusick  */
33539494Smckusick /* ARGSUSED */
33638414Smckusick nfs_fhtovp(mp, fhp, vpp)
33738414Smckusick 	struct mount *mp;
33838414Smckusick 	struct fid *fhp;
33938414Smckusick 	struct vnode **vpp;
34038414Smckusick {
34139494Smckusick 
34238414Smckusick 	return (EINVAL);
34338414Smckusick }
34438414Smckusick 
34538414Smckusick /*
34638414Smckusick  * Vnode pointer to File handle, should never happen either
34738414Smckusick  */
34839494Smckusick /* ARGSUSED */
34938414Smckusick nfs_vptofh(mp, fhp, vpp)
35038414Smckusick 	struct mount *mp;
35138414Smckusick 	struct fid *fhp;
35238414Smckusick 	struct vnode **vpp;
35338414Smckusick {
35439494Smckusick 
35538414Smckusick 	return (EINVAL);
35638414Smckusick }
35738884Smacklem 
35838884Smacklem /*
35938884Smacklem  * Vfs start routine, a no-op.
36038884Smacklem  */
36139494Smckusick /* ARGSUSED */
36238884Smacklem nfs_start(mp, flags)
36338884Smacklem 	struct mount *mp;
36438884Smacklem 	int flags;
36538884Smacklem {
36639494Smckusick 
36738884Smacklem 	return (0);
36838884Smacklem }
369