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 * %sccs.include.redist.c% 9 * 10 * @(#)nfs_syscalls.c 7.26 (Berkeley) 04/16/91 11 */ 12 13 #include "param.h" 14 #include "systm.h" 15 #include "kernel.h" 16 #include "file.h" 17 #include "stat.h" 18 #include "namei.h" 19 #include "vnode.h" 20 #include "mount.h" 21 #include "proc.h" 22 #include "malloc.h" 23 #include "buf.h" 24 #include "mbuf.h" 25 #include "socket.h" 26 #include "socketvar.h" 27 #include "domain.h" 28 #include "protosw.h" 29 30 #include "../netinet/in.h" 31 #include "../netinet/tcp.h" 32 33 #include "nfsv2.h" 34 #include "nfs.h" 35 #include "nfsrvcache.h" 36 37 /* Global defs. */ 38 extern u_long nfs_prog, nfs_vers; 39 extern int (*nfsrv_procs[NFS_NPROCS])(); 40 extern struct buf nfs_bqueue; 41 extern int nfs_numasync; 42 extern struct proc *nfs_iodwant[NFS_MAXASYNCDAEMON]; 43 extern int nfs_tcpnodelay; 44 struct mbuf *nfs_compress(); 45 46 #define TRUE 1 47 #define FALSE 0 48 49 static int nfs_asyncdaemon[NFS_MAXASYNCDAEMON]; 50 static int compressreply[NFS_NPROCS] = { 51 FALSE, 52 TRUE, 53 TRUE, 54 FALSE, 55 TRUE, 56 TRUE, 57 FALSE, 58 FALSE, 59 TRUE, 60 TRUE, 61 TRUE, 62 TRUE, 63 TRUE, 64 TRUE, 65 TRUE, 66 TRUE, 67 TRUE, 68 TRUE, 69 }; 70 /* 71 * NFS server system calls 72 * getfh() lives here too, but maybe should move to kern/vfs_syscalls.c 73 */ 74 75 /* 76 * Get file handle system call 77 */ 78 /* ARGSUSED */ 79 getfh(p, uap, retval) 80 struct proc *p; 81 register struct args { 82 char *fname; 83 fhandle_t *fhp; 84 } *uap; 85 int *retval; 86 { 87 register struct nameidata *ndp; 88 register struct vnode *vp; 89 fhandle_t fh; 90 int error; 91 struct nameidata nd; 92 93 /* 94 * Must be super user 95 */ 96 if (error = suser(p->p_ucred, &p->p_acflag)) 97 return (error); 98 ndp = &nd; 99 ndp->ni_nameiop = LOOKUP | LOCKLEAF | FOLLOW; 100 ndp->ni_segflg = UIO_USERSPACE; 101 ndp->ni_dirp = uap->fname; 102 if (error = namei(ndp, p)) 103 return (error); 104 vp = ndp->ni_vp; 105 bzero((caddr_t)&fh, sizeof(fh)); 106 fh.fh_fsid = vp->v_mount->mnt_stat.f_fsid; 107 error = VFS_VPTOFH(vp, &fh.fh_fid); 108 vput(vp); 109 if (error) 110 return (error); 111 error = copyout((caddr_t)&fh, (caddr_t)uap->fhp, sizeof (fh)); 112 return (error); 113 } 114 115 /* 116 * Nfs server psuedo system call for the nfsd's 117 * Never returns unless it fails or gets killed 118 */ 119 /* ARGSUSED */ 120 nfssvc(p, uap, retval) 121 struct proc *p; 122 register struct args { 123 int s; 124 caddr_t mskval; 125 int msklen; 126 caddr_t mtchval; 127 int mtchlen; 128 } *uap; 129 int *retval; 130 { 131 register struct mbuf *m; 132 register int siz; 133 register struct ucred *cr; 134 struct file *fp; 135 struct mbuf *mreq, *mrep, *nam, *md; 136 struct mbuf msk, mtch; 137 struct socket *so; 138 caddr_t dpos; 139 int procid, repstat, error, cacherep, wascomp; 140 u_long retxid; 141 142 /* 143 * Must be super user 144 */ 145 if (error = suser(p->p_ucred, &p->p_acflag)) 146 return (error); 147 if (error = getsock(p->p_fd, uap->s, &fp)) 148 return (error); 149 so = (struct socket *)fp->f_data; 150 if (sosendallatonce(so)) 151 siz = NFS_MAXPACKET; 152 else 153 siz = NFS_MAXPACKET + sizeof(u_long); 154 if (error = soreserve(so, siz, siz)) 155 goto bad; 156 if (error = sockargs(&nam, uap->mskval, uap->msklen, MT_SONAME)) 157 goto bad; 158 bcopy((caddr_t)nam, (caddr_t)&msk, sizeof (struct mbuf)); 159 msk.m_data = msk.m_dat; 160 m_freem(nam); 161 if (error = sockargs(&nam, uap->mtchval, uap->mtchlen, MT_SONAME)) 162 goto bad; 163 bcopy((caddr_t)nam, (caddr_t)&mtch, sizeof (struct mbuf)); 164 mtch.m_data = mtch.m_dat; 165 m_freem(nam); 166 167 /* Copy the cred so others don't see changes */ 168 cr = p->p_ucred = crcopy(p->p_ucred); 169 170 /* 171 * Set protocol specific options { for now TCP only } and 172 * reserve some space. For datagram sockets, this can get called 173 * repeatedly for the same socket, but that isn't harmful. 174 */ 175 if (so->so_proto->pr_flags & PR_CONNREQUIRED) { 176 MGET(m, M_WAIT, MT_SOOPTS); 177 *mtod(m, int *) = 1; 178 m->m_len = sizeof(int); 179 sosetopt(so, SOL_SOCKET, SO_KEEPALIVE, m); 180 } 181 if (so->so_proto->pr_domain->dom_family == AF_INET && 182 so->so_proto->pr_protocol == IPPROTO_TCP && 183 nfs_tcpnodelay) { 184 MGET(m, M_WAIT, MT_SOOPTS); 185 *mtod(m, int *) = 1; 186 m->m_len = sizeof(int); 187 sosetopt(so, IPPROTO_TCP, TCP_NODELAY, m); 188 } 189 so->so_rcv.sb_flags &= ~SB_NOINTR; 190 so->so_rcv.sb_timeo = 0; 191 so->so_snd.sb_flags &= ~SB_NOINTR; 192 so->so_snd.sb_timeo = 0; 193 194 /* 195 * Just loop around doin our stuff until SIGKILL 196 */ 197 for (;;) { 198 if (error = nfs_getreq(so, nfs_prog, nfs_vers, NFS_NPROCS-1, 199 &nam, &mrep, &md, &dpos, &retxid, &procid, cr, 200 &msk, &mtch, &wascomp)) { 201 if (nam) 202 m_freem(nam); 203 if (error == EPIPE || error == EINTR || 204 error == ERESTART) { 205 error = 0; 206 goto bad; 207 } 208 so->so_error = 0; 209 continue; 210 } 211 212 if (nam) 213 cacherep = nfsrv_getcache(nam, retxid, procid, &mreq); 214 else 215 cacherep = RC_DOIT; 216 switch (cacherep) { 217 case RC_DOIT: 218 if (error = (*(nfsrv_procs[procid]))(mrep, md, dpos, 219 cr, retxid, &mreq, &repstat, p)) { 220 nfsstats.srv_errs++; 221 if (nam) { 222 nfsrv_updatecache(nam, retxid, procid, 223 FALSE, repstat, mreq); 224 m_freem(nam); 225 } 226 break; 227 } 228 nfsstats.srvrpccnt[procid]++; 229 if (nam) 230 nfsrv_updatecache(nam, retxid, procid, TRUE, 231 repstat, mreq); 232 mrep = (struct mbuf *)0; 233 case RC_REPLY: 234 m = mreq; 235 siz = 0; 236 while (m) { 237 siz += m->m_len; 238 m = m->m_next; 239 } 240 if (siz <= 0 || siz > NFS_MAXPACKET) { 241 printf("mbuf siz=%d\n",siz); 242 panic("Bad nfs svc reply"); 243 } 244 mreq->m_pkthdr.len = siz; 245 mreq->m_pkthdr.rcvif = (struct ifnet *)0; 246 if (wascomp && compressreply[procid]) { 247 mreq = nfs_compress(mreq); 248 siz = mreq->m_pkthdr.len; 249 } 250 /* 251 * For non-atomic protocols, prepend a Sun RPC 252 * Record Mark. 253 */ 254 if (!sosendallatonce(so)) { 255 M_PREPEND(mreq, sizeof(u_long), M_WAIT); 256 *mtod(mreq, u_long *) = htonl(0x80000000 | siz); 257 } 258 error = nfs_send(so, nam, mreq, (struct nfsreq *)0); 259 if (nam) 260 m_freem(nam); 261 if (mrep) 262 m_freem(mrep); 263 if (error) { 264 if (error == EPIPE || error == EINTR || 265 error == ERESTART) 266 goto bad; 267 so->so_error = 0; 268 } 269 break; 270 case RC_DROPIT: 271 m_freem(mrep); 272 m_freem(nam); 273 break; 274 }; 275 } 276 bad: 277 return (error); 278 } 279 280 /* 281 * Nfs pseudo system call for asynchronous i/o daemons. 282 * These babies just pretend to be disk interrupt service routines 283 * for client nfs. They are mainly here for read ahead/write behind. 284 * Never returns unless it fails or gets killed 285 */ 286 /* ARGSUSED */ 287 async_daemon(p, uap, retval) 288 struct proc *p; 289 struct args *uap; 290 int *retval; 291 { 292 register struct buf *bp, *dp; 293 register int i, myiod; 294 int error; 295 296 /* 297 * Must be super user 298 */ 299 if (error = suser(p->p_ucred, &p->p_acflag)) 300 return (error); 301 /* 302 * Assign my position or return error if too many already running 303 */ 304 myiod = -1; 305 for (i = 0; i < NFS_MAXASYNCDAEMON; i++) 306 if (nfs_asyncdaemon[i] == 0) { 307 nfs_asyncdaemon[i]++; 308 myiod = i; 309 break; 310 } 311 if (myiod == -1) 312 return (EBUSY); 313 nfs_numasync++; 314 dp = &nfs_bqueue; 315 /* 316 * Just loop around doin our stuff until SIGKILL 317 */ 318 for (;;) { 319 while (dp->b_actf == NULL && error == 0) { 320 nfs_iodwant[myiod] = p; 321 error = tsleep((caddr_t)&nfs_iodwant[myiod], 322 PWAIT | PCATCH, "nfsidl", 0); 323 nfs_iodwant[myiod] = (struct proc *)0; 324 } 325 while (dp->b_actf != NULL) { 326 /* Take one off the end of the list */ 327 bp = dp->b_actl; 328 if (bp->b_actl == dp) { 329 dp->b_actf = dp->b_actl = (struct buf *)0; 330 } else { 331 dp->b_actl = bp->b_actl; 332 bp->b_actl->b_actf = dp; 333 } 334 (void) nfs_doio(bp); 335 } 336 if (error) { 337 nfs_asyncdaemon[myiod] = 0; 338 nfs_numasync--; 339 return (error); 340 } 341 } 342 } 343