1 /*
2  * linux/fs/nfsd/nfssvc.c
3  *
4  * Central processing for nfsd.
5  *
6  * Authors:	Olaf Kirch (okir@monad.swb.de)
7  *
8  * Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de>
9  */
10 
11 #define __NO_VERSION__
12 #include <linux/config.h>
13 #include <linux/module.h>
14 
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/slab.h>
23 #include <linux/smp.h>
24 #include <linux/smp_lock.h>
25 
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>
35 
36 #define NFSDDBG_FACILITY	NFSDDBG_SVC
37 #define NFSD_BUFSIZE		(1024 + NFSSVC_MAXBLKSIZE)
38 
39 /* these signals will be delivered to an nfsd thread
40  * when handling a request
41  */
42 #define ALLOWED_SIGS	(sigmask(SIGKILL))
43 /* these signals will be delivered to an nfsd thread
44  * when not handling a request. i.e. when waiting
45  */
46 #define SHUTDOWN_SIGS	(sigmask(SIGKILL) | sigmask(SIGHUP) | sigmask(SIGINT) | sigmask(SIGQUIT))
47 /* if the last thread dies with SIGHUP, then the exports table is
48  * left unchanged ( like 2.4-{0-9} ).  Any other signal will clear
49  * the exports table (like 2.2).
50  */
51 #define	SIG_NOCLEAN	SIGHUP
52 
53 extern struct svc_program	nfsd_program;
54 static void			nfsd(struct svc_rqst *rqstp);
55 struct timeval			nfssvc_boot;
56 static struct svc_serv 		*nfsd_serv;
57 static int			nfsd_busy;
58 static unsigned long		nfsd_last_call;
59 
60 struct nfsd_list {
61 	struct list_head 	list;
62 	struct task_struct	*task;
63 };
64 struct list_head nfsd_list = LIST_HEAD_INIT(nfsd_list);
65 
66 /*
67  * Maximum number of nfsd processes
68  */
69 #define	NFSD_MAXSERVS		8192
70 
71 int
nfsd_svc(unsigned short port,int nrservs)72 nfsd_svc(unsigned short port, int nrservs)
73 {
74 	int	error;
75 	int	none_left;
76 	struct list_head *victim;
77 
78 	dprintk("nfsd: creating service\n");
79 	error = -EINVAL;
80 	if (nrservs <= 0)
81 		nrservs = 0;
82 	if (nrservs > NFSD_MAXSERVS)
83 		nrservs = NFSD_MAXSERVS;
84 
85 	/* Readahead param cache - will no-op if it already exists */
86 	error =	nfsd_racache_init(2*nrservs);
87 	if (error<0)
88 		goto out;
89 	if (!nfsd_serv) {
90 		error = -ENOMEM;
91 		nfsd_serv = svc_create(&nfsd_program, NFSD_BUFSIZE, NFSSVC_XDRSIZE);
92 		if (nfsd_serv == NULL)
93 			goto out;
94 		error = svc_makesock(nfsd_serv, IPPROTO_UDP, port);
95 		if (error < 0)
96 			goto failure;
97 
98 #if CONFIG_NFSD_TCP
99 		error = svc_makesock(nfsd_serv, IPPROTO_TCP, port);
100 		if (error < 0)
101 			goto failure;
102 #endif
103 		do_gettimeofday(&nfssvc_boot);		/* record boot time */
104 	} else
105 		nfsd_serv->sv_nrthreads++;
106 	nrservs -= (nfsd_serv->sv_nrthreads-1);
107 	while (nrservs > 0) {
108 		nrservs--;
109 		error = svc_create_thread(nfsd, nfsd_serv);
110 		if (error < 0)
111 			break;
112 	}
113 	victim = nfsd_list.next;
114 	while (nrservs < 0 && victim != &nfsd_list) {
115 		struct nfsd_list *nl =
116 			list_entry(victim,struct nfsd_list, list);
117 		victim = victim->next;
118 		send_sig(SIG_NOCLEAN, nl->task, 1);
119 		nrservs++;
120 	}
121  failure:
122 	none_left = (nfsd_serv->sv_nrthreads == 1);
123 	svc_destroy(nfsd_serv);		/* Release server */
124 	if (none_left) {
125 		nfsd_serv = NULL;
126 		nfsd_racache_shutdown();
127 	}
128  out:
129 	return error;
130 }
131 
132 static inline void
update_thread_usage(int busy_threads)133 update_thread_usage(int busy_threads)
134 {
135 	unsigned long prev_call;
136 	unsigned long diff;
137 	int decile;
138 
139 	prev_call = nfsd_last_call;
140 	nfsd_last_call = jiffies;
141 	decile = busy_threads*10/nfsdstats.th_cnt;
142 	if (decile>0 && decile <= 10) {
143 		diff = nfsd_last_call - prev_call;
144 		if ( (nfsdstats.th_usage[decile-1] += diff) >= NFSD_USAGE_WRAP)
145 			nfsdstats.th_usage[decile-1] -= NFSD_USAGE_WRAP;
146 		if (decile == 10)
147 			nfsdstats.th_fullcnt++;
148 	}
149 }
150 
151 /*
152  * This is the NFS server kernel thread
153  */
154 static void
nfsd(struct svc_rqst * rqstp)155 nfsd(struct svc_rqst *rqstp)
156 {
157 	struct svc_serv	*serv = rqstp->rq_server;
158 	int		err;
159 	struct nfsd_list me;
160 
161 	/* Lock module and set up kernel thread */
162 	MOD_INC_USE_COUNT;
163 	lock_kernel();
164 	daemonize();
165 	sprintf(current->comm, "nfsd");
166 	current->rlim[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY;
167 
168 	nfsdstats.th_cnt++;
169 	/* Let svc_process check client's authentication. */
170 	rqstp->rq_auth = 1;
171 
172 	lockd_up();				/* start lockd */
173 
174 	me.task = current;
175 	list_add(&me.list, &nfsd_list);
176 
177 	/*
178 	 * The main request loop
179 	 */
180 	for (;;) {
181 		/* Block all but the shutdown signals */
182 		spin_lock_irq(&current->sigmask_lock);
183 		siginitsetinv(&current->blocked, SHUTDOWN_SIGS);
184 		recalc_sigpending(current);
185 		spin_unlock_irq(&current->sigmask_lock);
186 
187 		/*
188 		 * Find a socket with data available and call its
189 		 * recvfrom routine.
190 		 */
191 		while ((err = svc_recv(serv, rqstp,
192 				       5*60*HZ)) == -EAGAIN)
193 		    ;
194 		if (err < 0)
195 			break;
196 		update_thread_usage(nfsd_busy);
197 		nfsd_busy++;
198 
199 		/* Lock the export hash tables for reading. */
200 		exp_readlock();
201 
202 		/* Validate the client's address. This will also defeat
203 		 * port probes on port 2049 by unauthorized clients.
204 		 */
205 		rqstp->rq_client = exp_getclient(&rqstp->rq_addr);
206 		/* Process request with signals blocked.  */
207 		spin_lock_irq(&current->sigmask_lock);
208 		siginitsetinv(&current->blocked, ALLOWED_SIGS);
209 		recalc_sigpending(current);
210 		spin_unlock_irq(&current->sigmask_lock);
211 
212 		svc_process(serv, rqstp);
213 
214 		/* Unlock export hash tables */
215 		exp_unlock();
216 		update_thread_usage(nfsd_busy);
217 		nfsd_busy--;
218 	}
219 
220 	if (err != -EINTR) {
221 		printk(KERN_WARNING "nfsd: terminating on error %d\n", -err);
222 	} else {
223 		unsigned int	signo;
224 
225 		for (signo = 1; signo <= _NSIG; signo++)
226 			if (sigismember(&current->pending.signal, signo) &&
227 			    !sigismember(&current->blocked, signo))
228 				break;
229 		err = signo;
230 	}
231 
232 	/* Release lockd */
233 	lockd_down();
234 
235 	/* Check if this is last thread */
236 	if (serv->sv_nrthreads==1) {
237 
238 		printk(KERN_WARNING "nfsd: last server has exited\n");
239 		if (err != SIG_NOCLEAN) {
240 			printk(KERN_WARNING "nfsd: unexporting all filesystems\n");
241 			nfsd_export_shutdown();
242 		}
243 		nfsd_serv = NULL;
244 	        nfsd_racache_shutdown();	/* release read-ahead cache */
245 	}
246 	list_del(&me.list);
247 	nfsdstats.th_cnt --;
248 
249 	/* Release the thread */
250 	svc_exit_thread(rqstp);
251 
252 	/* Release module */
253 	MOD_DEC_USE_COUNT;
254 }
255 
256 static int
nfsd_dispatch(struct svc_rqst * rqstp,u32 * statp)257 nfsd_dispatch(struct svc_rqst *rqstp, u32 *statp)
258 {
259 	struct svc_procedure	*proc;
260 	kxdrproc_t		xdr;
261 	u32			nfserr;
262 
263 	dprintk("nfsd_dispatch: vers %d proc %d\n",
264 				rqstp->rq_vers, rqstp->rq_proc);
265 	proc = rqstp->rq_procinfo;
266 
267 	/* Check whether we have this call in the cache. */
268 	switch (nfsd_cache_lookup(rqstp, proc->pc_cachetype)) {
269 	case RC_INTR:
270 	case RC_DROPIT:
271 		return 0;
272 	case RC_REPLY:
273 		return 1;
274 	case RC_DOIT:;
275 		/* do it */
276 	}
277 
278 	/* Decode arguments */
279 	xdr = proc->pc_decode;
280 	if (xdr && !xdr(rqstp, rqstp->rq_argbuf.buf, rqstp->rq_argp)) {
281 		dprintk("nfsd: failed to decode arguments!\n");
282 		nfsd_cache_update(rqstp, RC_NOCACHE, NULL);
283 		*statp = rpc_garbage_args;
284 		return 1;
285 	}
286 
287 	/* Now call the procedure handler, and encode NFS status. */
288 	nfserr = proc->pc_func(rqstp, rqstp->rq_argp, rqstp->rq_resp);
289 	if (nfserr == nfserr_dropit) {
290 		dprintk("nfsd: Dropping request due to malloc failure!\n");
291 		nfsd_cache_update(rqstp, RC_NOCACHE, NULL);
292 		return 0;
293 	}
294 
295 	if (rqstp->rq_proc != 0)
296 		svc_putlong(&rqstp->rq_resbuf, nfserr);
297 
298 	/* Encode result.
299 	 * For NFSv2, additional info is never returned in case of an error.
300 	 */
301 	if (!(nfserr && rqstp->rq_vers == 2)) {
302 		xdr = proc->pc_encode;
303 		if (xdr && !xdr(rqstp, rqstp->rq_resbuf.buf, rqstp->rq_resp)) {
304 			/* Failed to encode result. Release cache entry */
305 			dprintk("nfsd: failed to encode result!\n");
306 			nfsd_cache_update(rqstp, RC_NOCACHE, NULL);
307 			*statp = rpc_system_err;
308 			return 1;
309 		}
310 	}
311 
312 	/* Store reply in cache. */
313 	nfsd_cache_update(rqstp, proc->pc_cachetype, statp + 1);
314 	return 1;
315 }
316 
317 static struct svc_version	nfsd_version2 = {
318 	2, 18, nfsd_procedures2, nfsd_dispatch
319 };
320 #ifdef CONFIG_NFSD_V3
321 static struct svc_version	nfsd_version3 = {
322 	3, 22, nfsd_procedures3, nfsd_dispatch
323 };
324 #endif
325 static struct svc_version *	nfsd_version[] = {
326 	NULL,
327 	NULL,
328 	&nfsd_version2,
329 #ifdef CONFIG_NFSD_V3
330 	&nfsd_version3,
331 #endif
332 };
333 
334 #define NFSD_NRVERS		(sizeof(nfsd_version)/sizeof(nfsd_version[0]))
335 struct svc_program		nfsd_program = {
336 	NFS_PROGRAM,		/* program number */
337 	2, NFSD_NRVERS-1,	/* version range */
338 	NFSD_NRVERS,		/* nr of entries in nfsd_version */
339 	nfsd_version,		/* version table */
340 	"nfsd",			/* program name */
341 	&nfsd_svcstats,		/* version table */
342 };
343