xref: /csrg-svn/sys/nfs/nfs_syscalls.c (revision 41398)
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*41398Smckusick  *	@(#)nfs_syscalls.c	7.13 (Berkeley) 05/04/90
2138414Smckusick  */
2238414Smckusick 
2338414Smckusick #include "param.h"
2438414Smckusick #include "systm.h"
2538414Smckusick #include "user.h"
2638414Smckusick #include "kernel.h"
2738414Smckusick #include "file.h"
2838414Smckusick #include "stat.h"
2938414Smckusick #include "vnode.h"
3038414Smckusick #include "mount.h"
3138414Smckusick #include "proc.h"
3238414Smckusick #include "uio.h"
3338414Smckusick #include "malloc.h"
3438884Smacklem #include "buf.h"
3538414Smckusick #include "mbuf.h"
3638414Smckusick #include "socket.h"
3738414Smckusick #include "socketvar.h"
3838414Smckusick #include "nfsv2.h"
3938414Smckusick #include "nfs.h"
4039756Smckusick #include "nfsrvcache.h"
4138414Smckusick 
4238414Smckusick /* Global defs. */
4338414Smckusick extern u_long nfs_prog, nfs_vers;
4438414Smckusick extern int (*nfsrv_procs[NFS_NPROCS])();
4538884Smacklem extern struct buf nfs_bqueue;
4639346Smckusick extern int nfs_asyncdaemons;
4739346Smckusick extern struct proc *nfs_iodwant[MAX_ASYNCDAEMON];
4838414Smckusick struct file *getsock();
4938414Smckusick 
5040252Smckusick #define	TRUE	1
5140252Smckusick #define	FALSE	0
5240252Smckusick 
5338414Smckusick /*
5438414Smckusick  * NFS server system calls
5538414Smckusick  * getfh() lives here too, but maybe should move to kern/vfs_syscalls.c
5638414Smckusick  */
5738414Smckusick #define RETURN(value)	{ u.u_error = (value); return; }
5838414Smckusick 
5938414Smckusick /*
6038414Smckusick  * Get file handle system call
6138414Smckusick  */
6238414Smckusick getfh()
6338414Smckusick {
6438414Smckusick 	register struct a {
6538414Smckusick 		char	*fname;
6638414Smckusick 		fhandle_t *fhp;
6738414Smckusick 	} *uap = (struct a *)u.u_ap;
6838414Smckusick 	register struct nameidata *ndp = &u.u_nd;
6938414Smckusick 	register struct vnode *vp;
7038414Smckusick 	fhandle_t fh;
7138414Smckusick 	int error;
7238414Smckusick 
7338414Smckusick 	/*
7438414Smckusick 	 * Must be super user
7538414Smckusick 	 */
7638414Smckusick 	if (error = suser(u.u_cred, &u.u_acflag))
7738414Smckusick 		RETURN (error);
7838414Smckusick 	ndp->ni_nameiop = LOOKUP | LOCKLEAF | FOLLOW;
7938414Smckusick 	ndp->ni_segflg = UIO_USERSPACE;
8038414Smckusick 	ndp->ni_dirp = uap->fname;
8138414Smckusick 	if (error = namei(ndp))
8238414Smckusick 		RETURN (error);
8338414Smckusick 	vp = ndp->ni_vp;
8438414Smckusick 	bzero((caddr_t)&fh, sizeof(fh));
85*41398Smckusick 	fh.fh_fsid = vp->v_mount->mnt_stat.f_fsid;
8638414Smckusick 	error = VFS_VPTOFH(vp, &fh.fh_fid);
8738414Smckusick 	vput(vp);
8838414Smckusick 	if (error)
8938414Smckusick 		RETURN (error);
9038414Smckusick 	error = copyout((caddr_t)&fh, (caddr_t)uap->fhp, sizeof (fh));
9138414Smckusick 	RETURN (error);
9238414Smckusick }
9338414Smckusick 
9438414Smckusick /*
9538414Smckusick  * Nfs server psuedo system call for the nfsd's
9638414Smckusick  * Never returns unless it fails or gets killed
9738414Smckusick  */
9838414Smckusick nfssvc()
9938414Smckusick {
10038414Smckusick 	register struct a {
10138414Smckusick 		int s;
10239756Smckusick 		u_long ormask;
10339756Smckusick 		u_long matchbits;
10438414Smckusick 	} *uap = (struct a *)u.u_ap;
10538414Smckusick 	register struct mbuf *m;
10638414Smckusick 	register int siz;
10738414Smckusick 	register struct ucred *cr;
10838414Smckusick 	struct file *fp;
10938414Smckusick 	struct mbuf *mreq, *mrep, *nam, *md;
11038414Smckusick 	struct socket *so;
11138414Smckusick 	caddr_t dpos;
11239494Smckusick 	int procid;
11338414Smckusick 	u_long retxid;
11439756Smckusick 	u_long msk, mtch;
11539756Smckusick 	int repstat;
11638414Smckusick 	int error;
11738414Smckusick 
11838414Smckusick 	/*
11938414Smckusick 	 * Must be super user
12038414Smckusick 	 */
12138414Smckusick 	if (error = suser(u.u_cred, &u.u_acflag))
12238414Smckusick 		RETURN (error);
12340762Skarels 	fp = getsock(uap->s, &error);
12438414Smckusick 	if (fp == 0)
12540762Skarels 		RETURN (error);
12638414Smckusick 	so = (struct socket *)fp->f_data;
12738414Smckusick 	cr = u.u_cred = crcopy(u.u_cred);	/* Copy it so others don't see changes */
12839756Smckusick 	msk = uap->ormask;
12939756Smckusick 	mtch = uap->matchbits;
13038414Smckusick 	/*
13139756Smckusick 	 * Just loop around doin our stuff until SIGKILL
13238414Smckusick 	 */
13338414Smckusick 	for (;;) {
13438414Smckusick 		if (error = nfs_getreq(so, nfs_prog, nfs_vers, NFS_NPROCS-1,
13539756Smckusick 		   &nam, &mrep, &md, &dpos, &retxid, &procid, cr, msk, mtch)) {
13640762Skarels 			if (nam)
13740762Skarels 				m_freem(nam);
13840762Skarels 			if (error == ERESTART || error == EINTR)
13940762Skarels 				RETURN (EINTR);
14038414Smckusick 			continue;
14138414Smckusick 		}
14239756Smckusick 		switch (nfsrv_getcache(nam, retxid, procid, &mreq)) {
14339756Smckusick 		case RC_DOIT:
14439756Smckusick 			if (error = (*(nfsrv_procs[procid]))(mrep, md, dpos,
14539756Smckusick 				cr, retxid, &mreq, &repstat)) {
14640252Smckusick 				nfsrv_updatecache(nam, retxid, procid,
14740252Smckusick 					FALSE, repstat, mreq);
14839756Smckusick 				m_freem(nam);
14939756Smckusick 				nfsstats.srv_errs++;
15039756Smckusick 				break;
15139756Smckusick 			}
15239756Smckusick 			nfsstats.srvrpccnt[procid]++;
15340252Smckusick 			nfsrv_updatecache(nam, retxid, procid, TRUE,
15440252Smckusick 				repstat, mreq);
15539756Smckusick 			mrep = (struct mbuf *)0;
15639756Smckusick 		case RC_REPLY:
15739756Smckusick 			m = mreq;
15839756Smckusick 			siz = 0;
15939756Smckusick 			while (m) {
16039756Smckusick 				siz += m->m_len;
16139756Smckusick 				m = m->m_next;
16239756Smckusick 			}
16339756Smckusick 			if (siz <= 0 || siz > 9216) {
16439756Smckusick 				printf("mbuf siz=%d\n",siz);
16539756Smckusick 				panic("Bad nfs svc reply");
16639756Smckusick 			}
16740119Smckusick 			error = nfs_send(so, nam, mreq, 0, siz);
16838414Smckusick 			m_freem(nam);
16939756Smckusick 			if (mrep)
17039756Smckusick 				m_freem(mrep);
17139756Smckusick 			break;
17239756Smckusick 		case RC_DROPIT:
17339756Smckusick 			m_freem(mrep);
17439756Smckusick 			m_freem(nam);
17539756Smckusick 			break;
17639756Smckusick 		};
17738414Smckusick 	}
17838414Smckusick }
17938884Smacklem 
18038884Smacklem /*
18138884Smacklem  * Nfs pseudo system call for asynchronous i/o daemons.
18238884Smacklem  * These babies just pretend to be disk interrupt service routines
18339346Smckusick  * for client nfs. They are mainly here for read ahead/write behind.
18438884Smacklem  * Never returns unless it fails or gets killed
18538884Smacklem  */
18638884Smacklem async_daemon()
18738884Smacklem {
18838884Smacklem 	register struct buf *bp, *dp;
18938884Smacklem 	int error;
19039346Smckusick 	int myiod;
19138884Smacklem 
19238884Smacklem 	/*
19338884Smacklem 	 * Must be super user
19438884Smacklem 	 */
19538884Smacklem 	if (error = suser(u.u_cred, &u.u_acflag))
19638884Smacklem 		RETURN (error);
19739346Smckusick 	/*
19839346Smckusick 	 * Assign my position or return error if too many already running
19939346Smckusick 	 */
20039346Smckusick 	if (nfs_asyncdaemons > MAX_ASYNCDAEMON)
20139346Smckusick 		RETURN (EBUSY);
20239346Smckusick 	myiod = nfs_asyncdaemons++;
20338884Smacklem 	dp = &nfs_bqueue;
20438884Smacklem 	/*
20539346Smckusick 	 * Just loop around doin our stuff until SIGKILL
20638884Smacklem 	 */
20738884Smacklem 	for (;;) {
20838884Smacklem 		while (dp->b_actf == NULL) {
20939346Smckusick 			nfs_iodwant[myiod] = u.u_procp;
21040762Skarels 			if (error = tsleep((caddr_t)&nfs_iodwant[myiod],
21141293Smckusick 			    PWAIT | PCATCH, "nfsidl", 0))
21240762Skarels 				RETURN (error);
21338884Smacklem 		}
21438884Smacklem 		/* Take one off the end of the list */
21538884Smacklem 		bp = dp->b_actl;
21638884Smacklem 		if (bp->b_actl == dp) {
21738884Smacklem 			dp->b_actf = dp->b_actl = (struct buf *)0;
21838884Smacklem 		} else {
21938884Smacklem 			dp->b_actl = bp->b_actl;
22038884Smacklem 			bp->b_actl->b_actf = dp;
22138884Smacklem 		}
22238884Smacklem 		(void) nfs_doio(bp);
22338884Smacklem 	}
22438884Smacklem }
225