Import 2.1.34
[davej-history.git] / fs / nfsd / nfssvc.c
bloba2cac539e18d37f35439214f464d0a2cfd52511a
1 /*
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>
9 */
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>
18 #include <linux/in.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
49 static int
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);
61 int
62 nfsd_svc(unsigned short port,int nrservs)
64 struct svc_serv * serv;
65 int error;
67 dprintk("nfsd: creating service\n");
68 if(nrservs <0)
69 return-EINVAL;
70 if(nrservs > NFSD_MAXSERVS)
71 nrservs = NFSD_MAXSERVS;
73 serv =svc_create(&nfsd_program, NFSD_BUFSIZE, NFSSVC_XDRSIZE);
74 if(serv == NULL)
75 return-ENOMEM;
77 if((error =nfsd_makesock(serv, IPPROTO_UDP, port)) <0
78 || (error =nfsd_makesock(serv, IPPROTO_TCP, port)) <0)
79 goto failure;
81 while(nrservs--) {
82 error =svc_create_thread(nfsd, serv);
83 if(error <0)
84 break;
87 failure:
88 svc_destroy(serv);/* Release server */
89 return error;
93 * This is the NFS server kernel thread
95 static void
96 nfsd(struct svc_rqst *rqstp)
98 struct svc_serv *serv = rqstp->rq_server;
99 sigset_t oldsigmask;
100 int oldumask, err;
102 lock_kernel();
103 /* Lock module and set up kernel thread */
104 MOD_INC_USE_COUNT;
105 exit_mm(current);
106 current->session =1;
107 current->pgrp =1;
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
122 * recvfrom routine.
124 while((err =svc_recv(serv, rqstp)) == -EAGAIN)
126 if(err <0)
127 break;
129 /* Lock the export hash tables for reading. */
130 exp_readlock();
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 "
138 "from (%08lx:%d)\n",
139 ntohl(rqstp->rq_addr.sin_addr.s_addr),
140 ntohs(rqstp->rq_addr.sin_port));
141 svc_drop(rqstp);
142 serv->sv_stats->rpcbadclnt++;
143 }else{
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 */
152 exp_unlock();
153 }while(err >=0);
155 if(err != -EINTR) {
156 printk(KERN_WARNING "nfsd: terminating on error %d\n", -err);
157 }else{
158 unsigned int signo;
160 for(signo =0; signo <32; signo++)
161 if(current->signal & current->blocked & (1<<signo))
162 break;
163 printk(KERN_WARNING "nfsd: terminating on signal %d\n", signo);
166 /* Release lockd */
167 lockd_down();
169 /* Destroy the thread */
170 svc_exit_thread(rqstp);
171 current->fs->umask = oldumask;
173 /* Release module */
174 MOD_DEC_USE_COUNT;
177 static int
178 nfsd_dispatch(struct svc_rqst *rqstp, u32 *statp)
180 struct svc_procedure *proc;
181 kxdrproc_t xdr;
182 u32 nfserr;
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)) {
189 case RC_INTR:
190 case RC_DROPIT:
191 return0;
192 case RC_REPLY:
193 return1;
194 case RC_DOIT:
195 /* do it */
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;
204 return1;
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);
212 /* Encode result.
213 * FIXME: Most NFSv3 calls return wcc data even when the call failed
215 xdr = proc->pc_encode;
216 if(!nfserr && xdr
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;
222 return1;
225 /* Store reply in cache. */
226 nfsd_cache_update(rqstp, proc->pc_cachetype, statp +1);
227 return1;
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
237 #endif
238 static struct svc_version * nfsd_version[] = {
239 NULL,
240 NULL,
241 &nfsd_version2,
242 #ifdef CONFIG_NFSD_NFS3
243 &nfsd_version3,
244 #endif
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 */
close