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, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 * 36 * @(#)nfs_syscalls.c 7.26 (Berkeley) 4/16/91 37 * 38 * PATCHES MAGIC LEVEL PATCH THAT GOT US HERE 39 * -------------------- ----- ---------------------- 40 * CURRENT PATCH LEVEL: 1 00053 41 * -------------------- ----- ---------------------- 42 * 43 * 08 Sep 92 Rick "gopher I" Fix "reserved port" bug, fixed for 44 * AIX3.2 NFS clients 45 */ 46 47 #include "param.h" 48 #include "systm.h" 49 #include "kernel.h" 50 #include "file.h" 51 #include "stat.h" 52 #include "namei.h" 53 #include "vnode.h" 54 #include "mount.h" 55 #include "proc.h" 56 #include "malloc.h" 57 #include "buf.h" 58 #include "mbuf.h" 59 #include "socket.h" 60 #include "socketvar.h" 61 #include "domain.h" 62 #include "protosw.h" 63 64 #include "../netinet/in.h" 65 #include "../netinet/tcp.h" 66 67 #include "nfsv2.h" 68 #include "nfs.h" 69 #include "nfsrvcache.h" 70 71 /* Global defs. */ 72 extern u_long nfs_prog, nfs_vers; 73 extern int (*nfsrv_procs[NFS_NPROCS])(); 74 extern struct buf nfs_bqueue; 75 extern int nfs_numasync; 76 extern struct proc *nfs_iodwant[NFS_MAXASYNCDAEMON]; 77 extern int nfs_tcpnodelay; 78 struct mbuf *nfs_compress(); 79 80 #define TRUE 1 81 #define FALSE 0 82 83 static int nfs_asyncdaemon[NFS_MAXASYNCDAEMON]; 84 static int compressreply[NFS_NPROCS] = { 85 FALSE, 86 TRUE, 87 TRUE, 88 FALSE, 89 TRUE, 90 TRUE, 91 FALSE, 92 FALSE, 93 TRUE, 94 TRUE, 95 TRUE, 96 TRUE, 97 TRUE, 98 TRUE, 99 TRUE, 100 TRUE, 101 TRUE, 102 TRUE, 103 }; 104 105 #ifdef NFSCLIENT 106 107 /* 108 * NFS server system calls 109 * getfh() lives here too, but maybe should move to kern/vfs_syscalls.c 110 */ 111 112 /* 113 * Get file handle system call 114 */ 115 /* ARGSUSED */ 116 getfh(p, uap, retval) 117 struct proc *p; 118 register struct args { 119 char *fname; 120 fhandle_t *fhp; 121 } *uap; 122 int *retval; 123 { 124 register struct nameidata *ndp; 125 register struct vnode *vp; 126 fhandle_t fh; 127 int error; 128 struct nameidata nd; 129 130 /* 131 * Must be super user 132 */ 133 if (error = suser(p->p_ucred, &p->p_acflag)) 134 return (error); 135 ndp = &nd; 136 ndp->ni_nameiop = LOOKUP | LOCKLEAF | FOLLOW; 137 ndp->ni_segflg = UIO_USERSPACE; 138 ndp->ni_dirp = uap->fname; 139 if (error = namei(ndp, p)) 140 return (error); 141 vp = ndp->ni_vp; 142 bzero((caddr_t)&fh, sizeof(fh)); 143 fh.fh_fsid = vp->v_mount->mnt_stat.f_fsid; 144 error = VFS_VPTOFH(vp, &fh.fh_fid); 145 vput(vp); 146 if (error) 147 return (error); 148 error = copyout((caddr_t)&fh, (caddr_t)uap->fhp, sizeof (fh)); 149 return (error); 150 } 151 152 #endif /*NFSCLIENT*/ 153 154 #ifdef NFSSERVER 155 156 /* 157 * Nfs server psuedo system call for the nfsd's 158 * Never returns unless it fails or gets killed 159 */ 160 /* ARGSUSED */ 161 nfssvc(p, uap, retval) 162 struct proc *p; 163 register struct args { 164 int s; 165 caddr_t mskval; 166 int msklen; 167 caddr_t mtchval; 168 int mtchlen; 169 } *uap; 170 int *retval; 171 { 172 register struct mbuf *m; 173 register int siz; 174 register struct ucred *cr; 175 struct file *fp; 176 struct mbuf *mreq, *mrep, *nam, *md; 177 struct mbuf msk, mtch; 178 struct socket *so; 179 caddr_t dpos; 180 int procid, repstat, error, cacherep, wascomp; 181 u_long retxid; 182 183 /* 184 * Must be super user 185 */ 186 if (error = suser(p->p_ucred, &p->p_acflag)) 187 return (error); 188 if (error = getsock(p->p_fd, uap->s, &fp)) 189 return (error); 190 so = (struct socket *)fp->f_data; 191 if (sosendallatonce(so)) 192 siz = NFS_MAXPACKET; 193 else 194 siz = NFS_MAXPACKET + sizeof(u_long); 195 if (error = soreserve(so, siz, siz)) 196 goto bad; 197 if (error = sockargs(&nam, uap->mskval, uap->msklen, MT_SONAME)) 198 goto bad; 199 bcopy((caddr_t)nam, (caddr_t)&msk, sizeof (struct mbuf)); 200 msk.m_data = msk.m_dat; 201 m_freem(nam); 202 if (error = sockargs(&nam, uap->mtchval, uap->mtchlen, MT_SONAME)) 203 goto bad; 204 bcopy((caddr_t)nam, (caddr_t)&mtch, sizeof (struct mbuf)); 205 mtch.m_data = mtch.m_dat; 206 m_freem(nam); 207 208 /* Copy the cred so others don't see changes */ 209 cr = p->p_ucred = crcopy(p->p_ucred); 210 211 /* 212 * Set protocol specific options { for now TCP only } and 213 * reserve some space. For datagram sockets, this can get called 214 * repeatedly for the same socket, but that isn't harmful. 215 */ 216 if (so->so_proto->pr_flags & PR_CONNREQUIRED) { 217 MGET(m, M_WAIT, MT_SOOPTS); 218 *mtod(m, int *) = 1; 219 m->m_len = sizeof(int); 220 sosetopt(so, SOL_SOCKET, SO_KEEPALIVE, m); 221 } 222 if (so->so_proto->pr_domain->dom_family == AF_INET && 223 so->so_proto->pr_protocol == IPPROTO_TCP && 224 nfs_tcpnodelay) { 225 MGET(m, M_WAIT, MT_SOOPTS); 226 *mtod(m, int *) = 1; 227 m->m_len = sizeof(int); 228 sosetopt(so, IPPROTO_TCP, TCP_NODELAY, m); 229 } 230 so->so_rcv.sb_flags &= ~SB_NOINTR; 231 so->so_rcv.sb_timeo = 0; 232 so->so_snd.sb_flags &= ~SB_NOINTR; 233 so->so_snd.sb_timeo = 0; 234 235 /* 236 * Just loop around doin our stuff until SIGKILL 237 */ 238 for (;;) { 239 if (error = nfs_getreq(so, nfs_prog, nfs_vers, NFS_NPROCS-1, 240 &nam, &mrep, &md, &dpos, &retxid, &procid, cr, 241 /* 08 Sep 92*/ &msk, &mtch, &wascomp, &repstat)) { 242 if (nam) 243 m_freem(nam); 244 if (error == EPIPE || error == EINTR || 245 error == ERESTART) { 246 error = 0; 247 goto bad; 248 } 249 so->so_error = 0; 250 continue; 251 } 252 253 if (nam) 254 cacherep = nfsrv_getcache(nam, retxid, procid, &mreq); 255 else 256 cacherep = RC_DOIT; 257 switch (cacherep) { 258 case RC_DOIT: 259 if (error = (*(nfsrv_procs[procid]))(mrep, md, dpos, 260 cr, retxid, &mreq, &repstat, p)) { 261 nfsstats.srv_errs++; 262 if (nam) { 263 nfsrv_updatecache(nam, retxid, procid, 264 FALSE, repstat, mreq); 265 m_freem(nam); 266 } 267 break; 268 } 269 nfsstats.srvrpccnt[procid]++; 270 if (nam) 271 nfsrv_updatecache(nam, retxid, procid, TRUE, 272 repstat, mreq); 273 mrep = (struct mbuf *)0; 274 case RC_REPLY: 275 m = mreq; 276 siz = 0; 277 while (m) { 278 siz += m->m_len; 279 m = m->m_next; 280 } 281 if (siz <= 0 || siz > NFS_MAXPACKET) { 282 printf("mbuf siz=%d\n",siz); 283 panic("Bad nfs svc reply"); 284 } 285 mreq->m_pkthdr.len = siz; 286 mreq->m_pkthdr.rcvif = (struct ifnet *)0; 287 if (wascomp && compressreply[procid]) { 288 mreq = nfs_compress(mreq); 289 siz = mreq->m_pkthdr.len; 290 } 291 /* 292 * For non-atomic protocols, prepend a Sun RPC 293 * Record Mark. 294 */ 295 if (!sosendallatonce(so)) { 296 M_PREPEND(mreq, sizeof(u_long), M_WAIT); 297 *mtod(mreq, u_long *) = htonl(0x80000000 | siz); 298 } 299 error = nfs_send(so, nam, mreq, (struct nfsreq *)0); 300 if (nam) 301 m_freem(nam); 302 if (mrep) 303 m_freem(mrep); 304 if (error) { 305 if (error == EPIPE || error == EINTR || 306 error == ERESTART) 307 goto bad; 308 so->so_error = 0; 309 } 310 break; 311 case RC_DROPIT: 312 m_freem(mrep); 313 m_freem(nam); 314 break; 315 }; 316 } 317 bad: 318 return (error); 319 } 320 321 #endif /* NFSSERVER */ 322 323 #ifdef NFSCLIENT 324 325 /* 326 * Nfs pseudo system call for asynchronous i/o daemons. 327 * These babies just pretend to be disk interrupt service routines 328 * for client nfs. They are mainly here for read ahead/write behind. 329 * Never returns unless it fails or gets killed 330 */ 331 /* ARGSUSED */ 332 async_daemon(p, uap, retval) 333 struct proc *p; 334 struct args *uap; 335 int *retval; 336 { 337 register struct buf *bp, *dp; 338 register int i, myiod; 339 int error; 340 341 /* 342 * Must be super user 343 */ 344 if (error = suser(p->p_ucred, &p->p_acflag)) 345 return (error); 346 /* 347 * Assign my position or return error if too many already running 348 */ 349 myiod = -1; 350 for (i = 0; i < NFS_MAXASYNCDAEMON; i++) 351 if (nfs_asyncdaemon[i] == 0) { 352 nfs_asyncdaemon[i]++; 353 myiod = i; 354 break; 355 } 356 if (myiod == -1) 357 return (EBUSY); 358 nfs_numasync++; 359 dp = &nfs_bqueue; 360 /* 361 * Just loop around doin our stuff until SIGKILL 362 */ 363 for (;;) { 364 while (dp->b_actf == NULL && error == 0) { 365 nfs_iodwant[myiod] = p; 366 error = tsleep((caddr_t)&nfs_iodwant[myiod], 367 PWAIT | PCATCH, "nfsidl", 0); 368 nfs_iodwant[myiod] = (struct proc *)0; 369 } 370 while (dp->b_actf != NULL) { 371 /* Take one off the end of the list */ 372 bp = dp->b_actl; 373 if (bp->b_actl == dp) { 374 dp->b_actf = dp->b_actl = (struct buf *)0; 375 } else { 376 dp->b_actl = bp->b_actl; 377 bp->b_actl->b_actf = dp; 378 } 379 (void) nfs_doio(bp); 380 } 381 if (error) { 382 nfs_asyncdaemon[myiod] = 0; 383 nfs_numasync--; 384 return (error); 385 } 386 } 387 } 388 389 #endif /* NFSCLIENT*/ 390 391