* Copyright (c) 1989 The Regents of the University of California.
* This code is derived from software contributed to Berkeley by
* Rick Macklem at The University of Guelph.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* @(#)nfs_syscalls.c 7.26 (Berkeley) 4/16/91
#include "../netinet/in.h"
#include "../netinet/tcp.h"
extern u_long nfs_prog
, nfs_vers
;
extern int (*nfsrv_procs
[NFS_NPROCS
])();
extern struct buf nfs_bqueue
;
extern struct proc
*nfs_iodwant
[NFS_MAXASYNCDAEMON
];
extern int nfs_tcpnodelay
;
struct mbuf
*nfs_compress();
static int nfs_asyncdaemon
[NFS_MAXASYNCDAEMON
];
static int compressreply
[NFS_NPROCS
] = {
* NFS server system calls
* getfh() lives here too, but maybe should move to kern/vfs_syscalls.c
* Get file handle system call
register struct nameidata
*ndp
;
register struct vnode
*vp
;
if (error
= suser(p
->p_ucred
, &p
->p_acflag
))
ndp
->ni_nameiop
= LOOKUP
| LOCKLEAF
| FOLLOW
;
ndp
->ni_segflg
= UIO_USERSPACE
;
ndp
->ni_dirp
= uap
->fname
;
if (error
= namei(ndp
, p
))
bzero((caddr_t
)&fh
, sizeof(fh
));
fh
.fh_fsid
= vp
->v_mount
->mnt_stat
.f_fsid
;
error
= VFS_VPTOFH(vp
, &fh
.fh_fid
);
error
= copyout((caddr_t
)&fh
, (caddr_t
)uap
->fhp
, sizeof (fh
));
* Nfs server psuedo system call for the nfsd's
* Never returns unless it fails or gets killed
register struct ucred
*cr
;
struct mbuf
*mreq
, *mrep
, *nam
, *md
;
int procid
, repstat
, error
, cacherep
, wascomp
;
if (error
= suser(p
->p_ucred
, &p
->p_acflag
))
if (error
= getsock(p
->p_fd
, uap
->s
, &fp
))
so
= (struct socket
*)fp
->f_data
;
siz
= NFS_MAXPACKET
+ sizeof(u_long
);
if (error
= soreserve(so
, siz
, siz
))
if (error
= sockargs(&nam
, uap
->mskval
, uap
->msklen
, MT_SONAME
))
bcopy((caddr_t
)nam
, (caddr_t
)&msk
, sizeof (struct mbuf
));
if (error
= sockargs(&nam
, uap
->mtchval
, uap
->mtchlen
, MT_SONAME
))
bcopy((caddr_t
)nam
, (caddr_t
)&mtch
, sizeof (struct mbuf
));
mtch
.m_data
= mtch
.m_dat
;
/* Copy the cred so others don't see changes */
cr
= p
->p_ucred
= crcopy(p
->p_ucred
);
* Set protocol specific options { for now TCP only } and
* reserve some space. For datagram sockets, this can get called
* repeatedly for the same socket, but that isn't harmful.
if (so
->so_proto
->pr_flags
& PR_CONNREQUIRED
) {
MGET(m
, M_WAIT
, MT_SOOPTS
);
sosetopt(so
, SOL_SOCKET
, SO_KEEPALIVE
, m
);
if (so
->so_proto
->pr_domain
->dom_family
== AF_INET
&&
so
->so_proto
->pr_protocol
== IPPROTO_TCP
&&
MGET(m
, M_WAIT
, MT_SOOPTS
);
sosetopt(so
, IPPROTO_TCP
, TCP_NODELAY
, m
);
so
->so_rcv
.sb_flags
&= ~SB_NOINTR
;
so
->so_snd
.sb_flags
&= ~SB_NOINTR
;
* Just loop around doin our stuff until SIGKILL
if (error
= nfs_getreq(so
, nfs_prog
, nfs_vers
, NFS_NPROCS
-1,
&nam
, &mrep
, &md
, &dpos
, &retxid
, &procid
, cr
,
&msk
, &mtch
, &wascomp
)) {
if (error
== EPIPE
|| error
== EINTR
||
cacherep
= nfsrv_getcache(nam
, retxid
, procid
, &mreq
);
if (error
= (*(nfsrv_procs
[procid
]))(mrep
, md
, dpos
,
cr
, retxid
, &mreq
, &repstat
, p
)) {
nfsrv_updatecache(nam
, retxid
, procid
,
nfsstats
.srvrpccnt
[procid
]++;
nfsrv_updatecache(nam
, retxid
, procid
, TRUE
,
if (siz
<= 0 || siz
> NFS_MAXPACKET
) {
printf("mbuf siz=%d\n",siz
);
panic("Bad nfs svc reply");
mreq
->m_pkthdr
.len
= siz
;
mreq
->m_pkthdr
.rcvif
= (struct ifnet
*)0;
if (wascomp
&& compressreply
[procid
]) {
mreq
= nfs_compress(mreq
);
siz
= mreq
->m_pkthdr
.len
;
* For non-atomic protocols, prepend a Sun RPC
if (!sosendallatonce(so
)) {
M_PREPEND(mreq
, sizeof(u_long
), M_WAIT
);
*mtod(mreq
, u_long
*) = htonl(0x80000000 | siz
);
error
= nfs_send(so
, nam
, mreq
, (struct nfsreq
*)0);
if (error
== EPIPE
|| error
== EINTR
||
* Nfs pseudo system call for asynchronous i/o daemons.
* These babies just pretend to be disk interrupt service routines
* for client nfs. They are mainly here for read ahead/write behind.
* Never returns unless it fails or gets killed
async_daemon(p
, uap
, retval
)
register struct buf
*bp
, *dp
;
if (error
= suser(p
->p_ucred
, &p
->p_acflag
))
* Assign my position or return error if too many already running
for (i
= 0; i
< NFS_MAXASYNCDAEMON
; i
++)
if (nfs_asyncdaemon
[i
] == 0) {
* Just loop around doin our stuff until SIGKILL
while (dp
->b_actf
== NULL
&& error
== 0) {
error
= tsleep((caddr_t
)&nfs_iodwant
[myiod
],
PWAIT
| PCATCH
, "nfsidl", 0);
nfs_iodwant
[myiod
] = (struct proc
*)0;
while (dp
->b_actf
!= NULL
) {
/* Take one off the end of the list */
dp
->b_actf
= dp
->b_actl
= (struct buf
*)0;
nfs_asyncdaemon
[myiod
] = 0;