xref: /csrg-svn/sys/nfs/nfs_vfsops.c (revision 38425)
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*38425Smckusick  *	@(#)nfs_vfsops.c	7.2 (Berkeley) 07/06/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"
29*38425Smckusick #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();
5338414Smckusick int nfs_unmount();
5438414Smckusick int nfs_root();
5538414Smckusick extern int nfs_statfs();
5638414Smckusick int nfs_sync();
5738414Smckusick int nfs_fhtovp();
5838414Smckusick int nfs_vptofh();
5938414Smckusick 
6038414Smckusick struct vfsops nfs_vfsops = {
6138414Smckusick 	nfs_mount,
6238414Smckusick 	nfs_unmount,
6338414Smckusick 	nfs_root,
6438414Smckusick 	nfs_statfs,
6538414Smckusick 	nfs_sync,
6638414Smckusick 	nfs_fhtovp,
6738414Smckusick 	nfs_vptofh,
6838414Smckusick };
6938414Smckusick 
7038414Smckusick extern struct nfsreq nfsreqh;
7138414Smckusick static long nfs_mntid;
7238414Smckusick 
7338414Smckusick /*
7438414Smckusick  * Called by vfs_mountroot when nfs is going to be mounted as root
7538414Smckusick  * Not Yet (By a LONG shot)
7638414Smckusick  */
7738414Smckusick nfs_mountroot()
7838414Smckusick {
7938414Smckusick 	return (ENODEV);
8038414Smckusick }
8138414Smckusick 
8238414Smckusick /*
8338414Smckusick  * VFS Operations.
8438414Smckusick  *
8538414Smckusick  * mount system call
8638414Smckusick  * It seems a bit dumb to copyinstr() the host and path here and then
8738414Smckusick  * bcopy() them in mountnfs(), but I wanted to detect errors before
8838414Smckusick  * doing the sockargs() call because sockargs() allocates an mbuf and
8938414Smckusick  * an error after that means that I have to release the mbuf.
9038414Smckusick  */
9138414Smckusick nfs_mount(mp, path, data, ndp)
9238414Smckusick 	struct mount *mp;
9338414Smckusick 	char *path;
9438414Smckusick 	caddr_t data;
9538414Smckusick 	struct nameidata *ndp;
9638414Smckusick {
9738414Smckusick 	int error;
9838414Smckusick 	struct nfs_args args;
9938414Smckusick 	struct mbuf *saddr;
10038414Smckusick 	char pth[MNAMELEN], hst[MNAMELEN];
10138414Smckusick 	int len;
10238414Smckusick 	nfsv2fh_t nfh;
10338414Smckusick 
10438414Smckusick 	if (error = copyin(data, (caddr_t)&args, sizeof (struct nfs_args)))
10538414Smckusick 		return (error);
10638414Smckusick 	if (error=copyin((caddr_t)args.fh, (caddr_t)&nfh, sizeof (nfsv2fh_t)))
10738414Smckusick 		return (error);
10838414Smckusick 	if (error = copyinstr(path, pth, MNAMELEN-1, &len))
10938414Smckusick 		return (error);
11038414Smckusick 	bzero(&pth[len], MNAMELEN-len);
11138414Smckusick 	if (error = copyinstr(args.hostname, hst, MNAMELEN-1, &len))
11238414Smckusick 		return (error);
11338414Smckusick 	bzero(&hst[len], MNAMELEN-len);
11438414Smckusick 	/* sockargs() call must be after above copyin() calls */
11538414Smckusick 	if (error = sockargs(&saddr, (caddr_t)args.addr,
11638414Smckusick 		sizeof (struct sockaddr_in), MT_SONAME))
11738414Smckusick 		return (error);
11838414Smckusick 	args.fh = &nfh;
11938414Smckusick 	error = mountnfs(&args, mp, saddr, pth, hst);
12038414Smckusick 	return (error);
12138414Smckusick }
12238414Smckusick 
12338414Smckusick /*
12438414Smckusick  * Common code for mount and mountroot
12538414Smckusick  */
12638414Smckusick mountnfs(argp, mp, saddr, pth, hst)
12738414Smckusick 	register struct nfs_args *argp;
12838414Smckusick 	register struct mount *mp;
12938414Smckusick 	register struct mbuf *saddr;
13038414Smckusick 	char *pth, *hst;
13138414Smckusick {
13238414Smckusick 	register struct nfsmount *nmp;
13338414Smckusick 	struct nfsnode *np;
134*38425Smckusick #ifdef notdef
13538414Smckusick 	struct statfs statf, *sbp;
136*38425Smckusick #endif
13738414Smckusick 	int error;
13838414Smckusick 
13938414Smckusick 	nmp = (struct nfsmount *)malloc(sizeof (struct nfsmount), M_NFSMNT,
14038414Smckusick 	    M_WAITOK);
14138414Smckusick 	mp->m_data = (qaddr_t)nmp;
14238414Smckusick 	mp->m_fsid.val[0] = ++nfs_mntid;
14338414Smckusick 	mp->m_fsid.val[1] = MOUNT_NFS;
14438414Smckusick 	nmp->nm_mountp = mp;
14538414Smckusick 	nmp->nm_flag = argp->flags;
14638414Smckusick 	nmp->nm_sockaddr = saddr;
14738414Smckusick 	/* Set up the sockets */
14838414Smckusick 	if (error = socreate(AF_INET, &nmp->nm_so, SOCK_DGRAM, 0))
14938414Smckusick 		goto bad;
15038414Smckusick 	if (error = soconnect(nmp->nm_so, saddr))
15138414Smckusick 		goto bad;
15238414Smckusick 	if ((argp->flags & NFSMNT_TIMEO) && argp->timeo >= 1)
15338414Smckusick 		nmp->nm_timeo = argp->timeo;
15438414Smckusick 	else
15538414Smckusick 		nmp->nm_timeo = NFS_TIMEO;
15638414Smckusick 	if ((argp->flags & NFSMNT_RETRANS) && argp->retrans > 0)
15738414Smckusick 		nmp->nm_retrans = argp->retrans;
15838414Smckusick 	else
15938414Smckusick 		nmp->nm_retrans = NFS_RETRANS;
16038414Smckusick 	if ((argp->flags & NFSMNT_WSIZE) &&
16138414Smckusick 	    argp->wsize <= NFS_MAXDATA && argp->wsize > 0 &&
16238414Smckusick 	   (argp->wsize & 0x1ff) == 0)
16338414Smckusick 		nmp->nm_wsize = argp->wsize;
16438414Smckusick 	else
16538414Smckusick 		nmp->nm_wsize = NFS_WSIZE;
16638414Smckusick 	if ((argp->flags & NFSMNT_RSIZE) &&
16738414Smckusick 	    argp->rsize <= NFS_MAXDATA && argp->rsize > 0 &&
16838414Smckusick 	   (argp->rsize & 0x1ff) == 0)
16938414Smckusick 		nmp->nm_rsize = argp->rsize;
17038414Smckusick 	else
17138414Smckusick 		nmp->nm_rsize = NFS_RSIZE;
17238414Smckusick 	bcopy((caddr_t)argp->fh, (caddr_t)&nmp->nm_fh, sizeof(nfsv2fh_t));
17338414Smckusick 	bcopy(pth, nmp->nm_path, MNAMELEN);
17438414Smckusick 	bcopy(hst, nmp->nm_host, MNAMELEN);
175*38425Smckusick #ifdef notdef
17638414Smckusick 	sbp = &statf;
17738414Smckusick 	/*
17838414Smckusick 	 * Kludge City...
17938414Smckusick 	 * To do an interruptable hard mount, turn it into a soft mount
18038414Smckusick 	 * with a retry limit of one and then repeat it so long as it
18138414Smckusick 	 * times out and there is no pending signal for the process.
18238414Smckusick 	 * It is tempting to just let nfs_statfs() sleep at positive
18338414Smckusick 	 * prio, but then you would long jump out without taking the
18438414Smckusick 	 * mount structure back out of the list.
18538414Smckusick 	 * NB: NFSMNT_INT must NEVER be set for nfs_mountroot(), since
18638414Smckusick 	 * the process context is not yet built!!
18738414Smckusick 	 */
18838414Smckusick 	if ((argp->flags && NFSMNT_INT) && (argp->flags & NFSMNT_SOFT) == 0) {
18938414Smckusick 		int savretrans;
19038414Smckusick 
19138414Smckusick 		nmp->nm_flag |= NFSMNT_SOFT;
19238414Smckusick 		savretrans = nmp->nm_retrans;
19338414Smckusick 		nmp->nm_retrans = 1;
19438414Smckusick 		do {
19538414Smckusick 			error = nfs_statfs(mp, sbp);
19638414Smckusick 		} while (error == ETIMEDOUT && (u.u_procp->p_sig &
19738414Smckusick 			(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGTERM)|
19838414Smckusick 			 sigmask(SIGKILL))) == 0);
19938414Smckusick 		nmp->nm_retrans = savretrans;
20038414Smckusick 		nmp->nm_flag &= ~NFSMNT_SOFT;
20138414Smckusick 		if (error)
20238414Smckusick 			goto bad;
20338414Smckusick 	} else if (error = nfs_statfs(mp, sbp))
20438414Smckusick 		goto bad;
20538414Smckusick 	mp->m_fsize = sbp->f_fsize;
20638414Smckusick 
20738414Smckusick 	/*
20838414Smckusick 	 * If the block size is not an exact multiple of CLBYTES
20938414Smckusick 	 * use CLBYTES so that paging in ZMAGIC executables doesn't
21038414Smckusick 	 * get sick. (It is used by vinitfod())
21138414Smckusick 	 */
21238414Smckusick 	if (sbp->f_bsize >= CLBYTES && claligned(sbp->f_bsize))
21338414Smckusick 		mp->m_bsize = sbp->f_bsize;
21438414Smckusick 	else
21538414Smckusick 		mp->m_bsize = CLBYTES;
216*38425Smckusick #else
217*38425Smckusick 	/*
218*38425Smckusick 	 * Set to CLBYTES so that vinifod() doesn't get confused.
219*38425Smckusick 	 * Actually any exact multiple of CLBYTES will do
220*38425Smckusick 	 */
221*38425Smckusick 	mp->m_bsize = mp->m_fsize = CLBYTES;
222*38425Smckusick #endif
22338414Smckusick 	return (0);
22438414Smckusick bad:
22538414Smckusick 	m_freem(saddr);
22638414Smckusick 	free((caddr_t)nmp, M_NFSMNT);
22738414Smckusick 	return (error);
22838414Smckusick }
22938414Smckusick 
23038414Smckusick /*
23138414Smckusick  * unmount system call
23238414Smckusick  */
23338414Smckusick nfs_unmount(mp, flags)
23438414Smckusick 	struct mount *mp;
23538414Smckusick 	int flags;
23638414Smckusick {
23738414Smckusick 	register struct nfsmount *nmp;
23838414Smckusick 	register struct nfsreq *rep;
23938414Smckusick 	struct nfsreq *rep2;
24038414Smckusick 	int error;
24138414Smckusick 	int s;
24238414Smckusick 
24338414Smckusick 	if (flags & MNT_FORCE)
24438414Smckusick 		return (EINVAL);
24538414Smckusick 	nmp = vfs_to_nfs(mp);
24638414Smckusick 	/*
24738414Smckusick 	 * Goes something like this..
24838414Smckusick 	 * - Call nfs_nflush() to clear out the nfsnode table
24938414Smckusick 	 * - Flush out lookup cache
25038414Smckusick 	 * - Close the socket
25138414Smckusick 	 * - Free up the data structures
25238414Smckusick 	 */
25338414Smckusick 	if (error = nfs_nflush(mp)) {
25438414Smckusick 		return (error);
25538414Smckusick 	}
25638414Smckusick 	/*
25738414Smckusick 	 * Scan the request list for any requests left hanging about
25838414Smckusick 	 */
25938414Smckusick 	s = splnet();
26038414Smckusick 	rep = nfsreqh.r_next;
26138414Smckusick 	while (rep) {
26238414Smckusick 		if (rep->r_mntp == nmp) {
26338414Smckusick 			rep->r_prev->r_next = rep2 = rep->r_next;
26438414Smckusick 			if (rep->r_next != NULL)
26538414Smckusick 				rep->r_next->r_prev = rep->r_prev;
26638414Smckusick 			m_freem(rep->r_mreq);
26738414Smckusick 			if (rep->r_mrep != NULL)
26838414Smckusick 				m_freem(rep->r_mrep);
26938414Smckusick 			free((caddr_t)rep, M_NFSREQ);
27038414Smckusick 			rep = rep2;
27138414Smckusick 		} else
27238414Smckusick 			rep = rep->r_next;
27338414Smckusick 	}
27438414Smckusick 	splx(s);
27538414Smckusick 	soclose(nmp->nm_so);
27638414Smckusick 	m_freem(nmp->nm_sockaddr);
27738414Smckusick 	free((caddr_t)nmp, M_NFSMNT);
27838414Smckusick 	return (0);
27938414Smckusick }
28038414Smckusick 
28138414Smckusick /*
28238414Smckusick  * Return root of a filesystem
28338414Smckusick  */
28438414Smckusick nfs_root(mp, vpp)
28538414Smckusick 	struct mount *mp;
28638414Smckusick 	struct vnode **vpp;
28738414Smckusick {
28838414Smckusick 	register struct vnode *vp;
28938414Smckusick 	struct nfsmount *nmp;
29038414Smckusick 	struct nfsnode *np;
29138414Smckusick 	int error;
29238414Smckusick 
29338414Smckusick 	nmp = vfs_to_nfs(mp);
29438414Smckusick 	if (error = nfs_nget(mp, &nmp->nm_fh, &np))
29538414Smckusick 		return (error);
29638414Smckusick 	vp = NFSTOV(np);
29738414Smckusick 	vp->v_type = VDIR;
29838414Smckusick 	vp->v_flag = VROOT;
29938414Smckusick 	*vpp = vp;
30038414Smckusick 	return (0);
30138414Smckusick }
30238414Smckusick 
30338414Smckusick /*
30438414Smckusick  * Since writes are synchronous, I think this is a no-op
30538414Smckusick  * Maybe write cache on nfs version 3 will require something ??
30638414Smckusick  */
30738414Smckusick nfs_sync(mp, waitfor)
30838414Smckusick 	struct mount *mp;
30938414Smckusick 	int waitfor;
31038414Smckusick {
31138414Smckusick 	return (0);
31238414Smckusick }
31338414Smckusick 
31438414Smckusick /*
31538414Smckusick  * At this point, this should never happen
31638414Smckusick  */
31738414Smckusick nfs_fhtovp(mp, fhp, vpp)
31838414Smckusick 	struct mount *mp;
31938414Smckusick 	struct fid *fhp;
32038414Smckusick 	struct vnode **vpp;
32138414Smckusick {
32238414Smckusick 	return (EINVAL);
32338414Smckusick }
32438414Smckusick 
32538414Smckusick /*
32638414Smckusick  * Vnode pointer to File handle, should never happen either
32738414Smckusick  */
32838414Smckusick nfs_vptofh(mp, fhp, vpp)
32938414Smckusick 	struct mount *mp;
33038414Smckusick 	struct fid *fhp;
33138414Smckusick 	struct vnode **vpp;
33238414Smckusick {
33338414Smckusick 	return (EINVAL);
33438414Smckusick }
335