2 * linux/fs/nfsd/nfssvc.c 4 * Central processing for nfsd. 6 * Authors: Olaf Kirch (okir@monad.swb.de) 8 * Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de> 11 #define __NO_VERSION__ 12 #include <linux/config.h> 13 #include <linux/module.h> 15 #include <linux/sched.h> 16 #include <linux/errno.h> 17 #include <linux/nfs.h> 19 #include <linux/uio.h> 20 #include <linux/version.h> 21 #include <linux/unistd.h> 22 #include <linux/malloc.h> 23 #include <linux/smp.h> 24 #include <linux/smp_lock.h> 26 #include <linux/sunrpc/types.h> 27 #include <linux/sunrpc/stats.h> 28 #include <linux/sunrpc/svc.h> 29 #include <linux/sunrpc/svcsock.h> 30 #include <linux/nfsd/nfsd.h> 31 #include <linux/nfsd/stats.h> 32 #include <linux/nfsd/cache.h> 33 #include <linux/nfsd/xdr.h> 34 #include <linux/lockd/bind.h> 36 #define NFSDDBG_FACILITY NFSDDBG_SVC 37 #define NFSD_BUFSIZE (1024 + NFSSVC_MAXBLKSIZE) 38 #define BLOCKABLE_SIGS (~(_S(SIGKILL) | _S(SIGSTOP))) 39 #define SHUTDOWN_SIGS (_S(SIGKILL)|_S(SIGINT)|_S(SIGTERM)) 40 #define _S(sig) (1 << ((sig) - 1)) 42 externstruct svc_program nfsd_program
; 43 static voidnfsd(struct svc_rqst
*rqstp
); 44 struct timeval nfssvc_boot
= {0,0}; 47 * Make a socket for nfsd 50 nfsd_makesock(struct svc_serv
*serv
,int protocol
,unsigned short port
) 52 struct sockaddr_in sin
; 54 dprintk("nfsd: creating socket proto = %d\n", protocol
); 55 sin
.sin_family
= AF_INET
; 56 sin
.sin_addr
.s_addr
= INADDR_ANY
; 57 sin
.sin_port
=htons(port
); 58 returnsvc_create_socket(serv
, protocol
, &sin
); 62 nfsd_svc(unsigned short port
,int nrservs
) 64 struct svc_serv
* serv
; 67 dprintk("nfsd: creating service\n"); 70 if(nrservs
> NFSD_MAXSERVS
) 71 nrservs
= NFSD_MAXSERVS
; 73 serv
=svc_create(&nfsd_program
, NFSD_BUFSIZE
, NFSSVC_XDRSIZE
); 77 if((error
=nfsd_makesock(serv
, IPPROTO_UDP
, port
)) <0 78 || (error
=nfsd_makesock(serv
, IPPROTO_TCP
, port
)) <0) 82 error
=svc_create_thread(nfsd
, serv
); 88 svc_destroy(serv
);/* Release server */ 93 * This is the NFS server kernel thread 96 nfsd(struct svc_rqst
*rqstp
) 98 struct svc_serv
*serv
= rqstp
->rq_server
; 103 /* Lock module and set up kernel thread */ 108 sprintf(current
->comm
,"nfsd"); 110 oldumask
= current
->fs
->umask
;/* Set umask to 0. */ 111 current
->blocked
|= ~SHUTDOWN_SIGS
; 112 current
->fs
->umask
=0; 113 nfssvc_boot
= xtime
;/* record boot time */ 114 lockd_up();/* start lockd */ 117 * The main request loop 121 * Find a socket with data available and call its 124 while((err
=svc_recv(serv
, rqstp
)) == -EAGAIN
) 129 /* Lock the export hash tables for reading. */ 132 /* Validate the client's address. This will also defeat 133 * port probes on port 2049 by unauthorized clients. 135 rqstp
->rq_client
=exp_getclient(&rqstp
->rq_addr
); 136 if(!rqstp
->rq_client
) { 137 printk(KERN_WARNING
"nfsd: unauthenticated request " 139 ntohl(rqstp
->rq_addr
.sin_addr
.s_addr
), 140 ntohs(rqstp
->rq_addr
.sin_port
)); 142 serv
->sv_stats
->rpcbadclnt
++; 144 /* Process request with all signals blocked. */ 145 oldsigmask
= current
->blocked
; 146 current
->blocked
= BLOCKABLE_SIGS
; 147 svc_process(serv
, rqstp
); 148 current
->blocked
= oldsigmask
; 151 /* Unlock export hash tables */ 156 printk(KERN_WARNING
"nfsd: terminating on error %d\n", -err
); 160 for(signo
=0; signo
<32; signo
++) 161 if(current
->signal
& current
->blocked
& (1<<signo
)) 163 printk(KERN_WARNING
"nfsd: terminating on signal %d\n", signo
); 169 /* Destroy the thread */ 170 svc_exit_thread(rqstp
); 171 current
->fs
->umask
= oldumask
; 178 nfsd_dispatch(struct svc_rqst
*rqstp
, u32
*statp
) 180 struct svc_procedure
*proc
; 184 dprintk("nfsd_dispatch: proc %d\n", rqstp
->rq_proc
); 185 proc
= rqstp
->rq_procinfo
; 187 /* Check whether we have this call in the cache. */ 188 switch(nfsd_cache_lookup(rqstp
, proc
->pc_cachetype
)) { 198 /* Decode arguments */ 199 xdr
= proc
->pc_decode
; 200 if(xdr
&& !xdr(rqstp
, rqstp
->rq_argbuf
.buf
, rqstp
->rq_argp
)) { 201 dprintk("nfsd: failed to decode arguments!\n"); 202 nfsd_cache_update(rqstp
, RC_NOCACHE
, NULL
); 203 *statp
= rpc_garbage_args
; 207 /* Now call the procedure handler, and encode NFS status. */ 208 nfserr
= proc
->pc_func(rqstp
, rqstp
->rq_argp
, rqstp
->rq_resp
); 209 if(rqstp
->rq_proc
!=0) 210 svc_putlong(&rqstp
->rq_resbuf
, nfserr
); 213 * FIXME: Most NFSv3 calls return wcc data even when the call failed 215 xdr
= proc
->pc_encode
; 217 && !xdr(rqstp
, rqstp
->rq_resbuf
.buf
, rqstp
->rq_resp
)) { 218 /* Failed to encode result. Release cache entry */ 219 dprintk("nfsd: failed to encode result!\n"); 220 nfsd_cache_update(rqstp
, RC_NOCACHE
, NULL
); 221 *statp
= rpc_system_err
; 225 /* Store reply in cache. */ 226 nfsd_cache_update(rqstp
, proc
->pc_cachetype
, statp
+1); 230 static struct svc_version nfsd_version2
= { 231 2,18, nfsd_procedures2
, nfsd_dispatch
233 #ifdef CONFIG_NFSD_NFS3 234 static struct svc_version nfsd_version3
= { 235 3,23, nfsd_procedures3
, nfsd_dispatch
238 static struct svc_version
* nfsd_version
[] = { 242 #ifdef CONFIG_NFSD_NFS3 247 #define NFSD_NRVERS (sizeof(nfsd_version)/sizeof(nfsd_version[0])) 248 struct svc_program nfsd_program
= { 249 NFS_PROGRAM
,/* program number */ 250 2, NFSD_NRVERS
-1,/* version range */ 251 NFSD_NRVERS
,/* nr of entries in nfsd_version */ 252 nfsd_version
,/* version table */ 253 "nfsd",/* program name */ 254 &nfsd_svcstats
,/* version table */