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