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)
39 #define ALLOWED_SIGS (sigmask(SIGKILL) | sigmask(SIGSTOP))
40 #define SHUTDOWN_SIGS (sigmask(SIGKILL) | sigmask(SIGINT) | sigmask(SIGTERM))
42 extern struct svc_program nfsd_program
;
43 static void nfsd(struct svc_rqst
*rqstp
);
44 struct timeval nfssvc_boot
= { 0, 0 };
45 static int nfsd_active
= 0;
48 nfsd_svc(unsigned short port
, int nrservs
)
50 struct svc_serv
* serv
;
53 dprintk("nfsd: creating service\n");
57 if (nrservs
> NFSD_MAXSERVS
)
58 nrservs
= NFSD_MAXSERVS
;
61 serv
= svc_create(&nfsd_program
, NFSD_BUFSIZE
, NFSSVC_XDRSIZE
);
65 if ((error
= svc_makesock(serv
, IPPROTO_UDP
, port
)) < 0
66 || (error
= svc_makesock(serv
, IPPROTO_TCP
, port
)) < 0)
70 error
= svc_create_thread(nfsd
, serv
);
76 svc_destroy(serv
); /* Release server */
82 * This is the NFS server kernel thread
85 nfsd(struct svc_rqst
*rqstp
)
87 struct svc_serv
*serv
= rqstp
->rq_server
;
90 /* Lock module and set up kernel thread */
96 sprintf(current
->comm
, "nfsd");
98 oldumask
= current
->fs
->umask
; /* Set umask to 0. */
99 current
->fs
->umask
= 0;
100 nfssvc_boot
= xtime
; /* record boot time */
102 lockd_up(); /* start lockd */
105 * The main request loop
108 /* Block all but the shutdown signals */
109 spin_lock_irq(¤t
->sigmask_lock
);
110 siginitsetinv(¤t
->blocked
, SHUTDOWN_SIGS
);
111 recalc_sigpending(current
);
112 spin_unlock_irq(¤t
->sigmask_lock
);
115 * Find a socket with data available and call its
118 while ((err
= svc_recv(serv
, rqstp
)) == -EAGAIN
)
123 /* Lock the export hash tables for reading. */
126 /* Validate the client's address. This will also defeat
127 * port probes on port 2049 by unauthorized clients.
129 rqstp
->rq_client
= exp_getclient(&rqstp
->rq_addr
);
130 if (!rqstp
->rq_client
) {
131 printk(KERN_WARNING
"nfsd: unauthenticated request "
133 ntohl(rqstp
->rq_addr
.sin_addr
.s_addr
),
134 ntohs(rqstp
->rq_addr
.sin_port
));
136 serv
->sv_stats
->rpcbadclnt
++;
138 /* Process request with signals blocked. */
139 spin_lock_irq(¤t
->sigmask_lock
);
140 siginitsetinv(¤t
->blocked
, ALLOWED_SIGS
);
141 recalc_sigpending(current
);
142 spin_unlock_irq(¤t
->sigmask_lock
);
144 svc_process(serv
, rqstp
);
147 /* Unlock export hash tables */
152 printk(KERN_WARNING
"nfsd: terminating on error %d\n", -err
);
156 for (signo
= 1; signo
<= _NSIG
; signo
++)
157 if (sigismember(¤t
->signal
, signo
) &&
158 !sigismember(¤t
->blocked
, signo
))
160 printk(KERN_WARNING
"nfsd: terminating on signal %d\n", signo
);
165 if (!--nfsd_active
) {
166 printk("nfsd: last server exiting\n");
167 /* revoke all exports */
168 nfsd_export_shutdown();
171 /* Destroy the thread */
172 svc_exit_thread(rqstp
);
173 current
->fs
->umask
= oldumask
;
180 nfsd_dispatch(struct svc_rqst
*rqstp
, u32
*statp
)
182 struct svc_procedure
*proc
;
186 dprintk("nfsd_dispatch: proc %d\n", rqstp
->rq_proc
);
187 proc
= rqstp
->rq_procinfo
;
189 /* Check whether we have this call in the cache. */
190 switch (nfsd_cache_lookup(rqstp
, proc
->pc_cachetype
)) {
200 /* Decode arguments */
201 xdr
= proc
->pc_decode
;
202 if (xdr
&& !xdr(rqstp
, rqstp
->rq_argbuf
.buf
, rqstp
->rq_argp
)) {
203 dprintk("nfsd: failed to decode arguments!\n");
204 nfsd_cache_update(rqstp
, RC_NOCACHE
, NULL
);
205 *statp
= rpc_garbage_args
;
209 /* Now call the procedure handler, and encode NFS status. */
210 nfserr
= proc
->pc_func(rqstp
, rqstp
->rq_argp
, rqstp
->rq_resp
);
211 if (rqstp
->rq_proc
!= 0)
212 svc_putlong(&rqstp
->rq_resbuf
, nfserr
);
215 * FIXME: Most NFSv3 calls return wcc data even when the call failed
217 xdr
= proc
->pc_encode
;
219 && !xdr(rqstp
, rqstp
->rq_resbuf
.buf
, rqstp
->rq_resp
)) {
220 /* Failed to encode result. Release cache entry */
221 dprintk("nfsd: failed to encode result!\n");
222 nfsd_cache_update(rqstp
, RC_NOCACHE
, NULL
);
223 *statp
= rpc_system_err
;
227 /* Store reply in cache. */
228 nfsd_cache_update(rqstp
, proc
->pc_cachetype
, statp
+ 1);
232 static struct svc_version nfsd_version2
= {
233 2, 18, nfsd_procedures2
, nfsd_dispatch
235 #ifdef CONFIG_NFSD_NFS3
236 static struct svc_version nfsd_version3
= {
237 3, 23, nfsd_procedures3
, nfsd_dispatch
240 static struct svc_version
* nfsd_version
[] = {
244 #ifdef CONFIG_NFSD_NFS3
249 #define NFSD_NRVERS (sizeof(nfsd_version)/sizeof(nfsd_version[0]))
250 struct svc_program nfsd_program
= {
251 NFS_PROGRAM
, /* program number */
252 2, NFSD_NRVERS
-1, /* version range */
253 NFSD_NRVERS
, /* nr of entries in nfsd_version */
254 nfsd_version
, /* version table */
255 "nfsd", /* program name */
256 &nfsd_svcstats
, /* version table */