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