xref: /original-bsd/sys/nfs/nfs_syscalls.c (revision 23cd6db2)
1 /*
2  * Copyright (c) 1989 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Rick Macklem at The University of Guelph.
7  *
8  * Redistribution and use in source and binary forms are permitted
9  * provided that the above copyright notice and this paragraph are
10  * duplicated in all such forms and that any documentation,
11  * advertising materials, and other materials related to such
12  * distribution and use acknowledge that the software was developed
13  * by the University of California, Berkeley.  The name of the
14  * University may not be used to endorse or promote products derived
15  * from this software without specific prior written permission.
16  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19  *
20  *	@(#)nfs_syscalls.c	7.11 (Berkeley) 04/04/90
21  */
22 
23 #include "param.h"
24 #include "systm.h"
25 #include "user.h"
26 #include "kernel.h"
27 #include "file.h"
28 #include "stat.h"
29 #include "vnode.h"
30 #include "mount.h"
31 #include "proc.h"
32 #include "uio.h"
33 #include "malloc.h"
34 #include "buf.h"
35 #include "mbuf.h"
36 #include "socket.h"
37 #include "socketvar.h"
38 #include "nfsv2.h"
39 #include "nfs.h"
40 #include "nfsrvcache.h"
41 
42 /* Global defs. */
43 extern u_long nfs_prog, nfs_vers;
44 extern int (*nfsrv_procs[NFS_NPROCS])();
45 extern struct buf nfs_bqueue;
46 extern int nfs_asyncdaemons;
47 extern struct proc *nfs_iodwant[MAX_ASYNCDAEMON];
48 struct file *getsock();
49 
50 #define	TRUE	1
51 #define	FALSE	0
52 
53 /*
54  * NFS server system calls
55  * getfh() lives here too, but maybe should move to kern/vfs_syscalls.c
56  */
57 #define RETURN(value)	{ u.u_error = (value); return; }
58 
59 /*
60  * Get file handle system call
61  */
62 getfh()
63 {
64 	register struct a {
65 		char	*fname;
66 		fhandle_t *fhp;
67 	} *uap = (struct a *)u.u_ap;
68 	register struct nameidata *ndp = &u.u_nd;
69 	register struct vnode *vp;
70 	fhandle_t fh;
71 	int error;
72 
73 	/*
74 	 * Must be super user
75 	 */
76 	if (error = suser(u.u_cred, &u.u_acflag))
77 		RETURN (error);
78 	ndp->ni_nameiop = LOOKUP | LOCKLEAF | FOLLOW;
79 	ndp->ni_segflg = UIO_USERSPACE;
80 	ndp->ni_dirp = uap->fname;
81 	if (error = namei(ndp))
82 		RETURN (error);
83 	vp = ndp->ni_vp;
84 	bzero((caddr_t)&fh, sizeof(fh));
85 	fh.fh_fsid = vp->v_mount->m_stat.f_fsid;
86 	error = VFS_VPTOFH(vp, &fh.fh_fid);
87 	vput(vp);
88 	if (error)
89 		RETURN (error);
90 	error = copyout((caddr_t)&fh, (caddr_t)uap->fhp, sizeof (fh));
91 	RETURN (error);
92 }
93 
94 /*
95  * Nfs server psuedo system call for the nfsd's
96  * Never returns unless it fails or gets killed
97  */
98 nfssvc()
99 {
100 	register struct a {
101 		int s;
102 		u_long ormask;
103 		u_long matchbits;
104 	} *uap = (struct a *)u.u_ap;
105 	register struct mbuf *m;
106 	register int siz;
107 	register struct ucred *cr;
108 	struct file *fp;
109 	struct mbuf *mreq, *mrep, *nam, *md;
110 	struct socket *so;
111 	caddr_t dpos;
112 	int procid;
113 	u_long retxid;
114 	u_long msk, mtch;
115 	int repstat;
116 	int error;
117 
118 	/*
119 	 * Must be super user
120 	 */
121 	if (error = suser(u.u_cred, &u.u_acflag))
122 		RETURN (error);
123 	fp = getsock(uap->s, &error);
124 	if (fp == 0)
125 		RETURN (error);
126 	so = (struct socket *)fp->f_data;
127 	cr = u.u_cred = crcopy(u.u_cred);	/* Copy it so others don't see changes */
128 	msk = uap->ormask;
129 	mtch = uap->matchbits;
130 	/*
131 	 * Just loop around doin our stuff until SIGKILL
132 	 */
133 	for (;;) {
134 		if (error = nfs_getreq(so, nfs_prog, nfs_vers, NFS_NPROCS-1,
135 		   &nam, &mrep, &md, &dpos, &retxid, &procid, cr, msk, mtch)) {
136 			if (nam)
137 				m_freem(nam);
138 			if (error == ERESTART || error == EINTR)
139 				RETURN (EINTR);
140 			continue;
141 		}
142 		switch (nfsrv_getcache(nam, retxid, procid, &mreq)) {
143 		case RC_DOIT:
144 			if (error = (*(nfsrv_procs[procid]))(mrep, md, dpos,
145 				cr, retxid, &mreq, &repstat)) {
146 				nfsrv_updatecache(nam, retxid, procid,
147 					FALSE, repstat, mreq);
148 				m_freem(nam);
149 				nfsstats.srv_errs++;
150 				break;
151 			}
152 			nfsstats.srvrpccnt[procid]++;
153 			nfsrv_updatecache(nam, retxid, procid, TRUE,
154 				repstat, mreq);
155 			mrep = (struct mbuf *)0;
156 		case RC_REPLY:
157 			m = mreq;
158 			siz = 0;
159 			while (m) {
160 				siz += m->m_len;
161 				m = m->m_next;
162 			}
163 			if (siz <= 0 || siz > 9216) {
164 				printf("mbuf siz=%d\n",siz);
165 				panic("Bad nfs svc reply");
166 			}
167 			error = nfs_send(so, nam, mreq, 0, siz);
168 			m_freem(nam);
169 			if (mrep)
170 				m_freem(mrep);
171 			break;
172 		case RC_DROPIT:
173 			m_freem(mrep);
174 			m_freem(nam);
175 			break;
176 		};
177 	}
178 }
179 
180 /*
181  * Nfs pseudo system call for asynchronous i/o daemons.
182  * These babies just pretend to be disk interrupt service routines
183  * for client nfs. They are mainly here for read ahead/write behind.
184  * Never returns unless it fails or gets killed
185  */
186 async_daemon()
187 {
188 	register struct buf *bp, *dp;
189 	int error;
190 	int myiod;
191 
192 	/*
193 	 * Must be super user
194 	 */
195 	if (error = suser(u.u_cred, &u.u_acflag))
196 		RETURN (error);
197 	/*
198 	 * Assign my position or return error if too many already running
199 	 */
200 	if (nfs_asyncdaemons > MAX_ASYNCDAEMON)
201 		RETURN (EBUSY);
202 	myiod = nfs_asyncdaemons++;
203 	dp = &nfs_bqueue;
204 	/*
205 	 * Just loop around doin our stuff until SIGKILL
206 	 */
207 	for (;;) {
208 		while (dp->b_actf == NULL) {
209 			nfs_iodwant[myiod] = u.u_procp;
210 			if (error = tsleep((caddr_t)&nfs_iodwant[myiod],
211 			    PRIBIO | PCATCH, "nfsidl", 0))
212 				RETURN (error);
213 		}
214 		/* Take one off the end of the list */
215 		bp = dp->b_actl;
216 		if (bp->b_actl == dp) {
217 			dp->b_actf = dp->b_actl = (struct buf *)0;
218 		} else {
219 			dp->b_actl = bp->b_actl;
220 			bp->b_actl->b_actf = dp;
221 		}
222 		(void) nfs_doio(bp);
223 	}
224 }
225