home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / sys / nfs / nfs_syscalls.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-05-20  |  9.0 KB  |  369 lines

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