aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/nfssvc.c
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2013-01-17 16:15:55 -0500
committerJonathan Herman <hermanjl@cs.unc.edu>2013-01-17 16:15:55 -0500
commit8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch)
treea8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /fs/nfsd/nfssvc.c
parent406089d01562f1e2bf9f089fd7637009ebaad589 (diff)
Patched in Tegra support.
Diffstat (limited to 'fs/nfsd/nfssvc.c')
-rw-r--r--fs/nfsd/nfssvc.c273
1 files changed, 101 insertions, 172 deletions
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index cee62ab9d4a..dc5a1bf476b 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -8,7 +8,6 @@
8 8
9#include <linux/sched.h> 9#include <linux/sched.h>
10#include <linux/freezer.h> 10#include <linux/freezer.h>
11#include <linux/module.h>
12#include <linux/fs_struct.h> 11#include <linux/fs_struct.h>
13#include <linux/swap.h> 12#include <linux/swap.h>
14 13
@@ -21,19 +20,19 @@
21#include "nfsd.h" 20#include "nfsd.h"
22#include "cache.h" 21#include "cache.h"
23#include "vfs.h" 22#include "vfs.h"
24#include "netns.h"
25 23
26#define NFSDDBG_FACILITY NFSDDBG_SVC 24#define NFSDDBG_FACILITY NFSDDBG_SVC
27 25
28extern struct svc_program nfsd_program; 26extern struct svc_program nfsd_program;
29static int nfsd(void *vrqstp); 27static int nfsd(void *vrqstp);
28struct timeval nfssvc_boot;
30 29
31/* 30/*
32 * nfsd_mutex protects nn->nfsd_serv -- both the pointer itself and the members 31 * nfsd_mutex protects nfsd_serv -- both the pointer itself and the members
33 * of the svc_serv struct. In particular, ->sv_nrthreads but also to some 32 * of the svc_serv struct. In particular, ->sv_nrthreads but also to some
34 * extent ->sv_temp_socks and ->sv_permsocks. It also protects nfsdstats.th_cnt 33 * extent ->sv_temp_socks and ->sv_permsocks. It also protects nfsdstats.th_cnt
35 * 34 *
36 * If (out side the lock) nn->nfsd_serv is non-NULL, then it must point to a 35 * If (out side the lock) nfsd_serv is non-NULL, then it must point to a
37 * properly initialised 'struct svc_serv' with ->sv_nrthreads > 0. That number 36 * properly initialised 'struct svc_serv' with ->sv_nrthreads > 0. That number
38 * of nfsd threads must exist and each must listed in ->sp_all_threads in each 37 * of nfsd threads must exist and each must listed in ->sp_all_threads in each
39 * entry of ->sv_pools[]. 38 * entry of ->sv_pools[].
@@ -51,6 +50,7 @@ static int nfsd(void *vrqstp);
51 * nfsd_versions 50 * nfsd_versions
52 */ 51 */
53DEFINE_MUTEX(nfsd_mutex); 52DEFINE_MUTEX(nfsd_mutex);
53struct svc_serv *nfsd_serv;
54 54
55/* 55/*
56 * nfsd_drc_lock protects nfsd_drc_max_pages and nfsd_drc_pages_used. 56 * nfsd_drc_lock protects nfsd_drc_max_pages and nfsd_drc_pages_used.
@@ -171,32 +171,28 @@ int nfsd_minorversion(u32 minorversion, enum vers_op change)
171 */ 171 */
172#define NFSD_MAXSERVS 8192 172#define NFSD_MAXSERVS 8192
173 173
174int nfsd_nrthreads(struct net *net) 174int nfsd_nrthreads(void)
175{ 175{
176 int rv = 0; 176 int rv = 0;
177 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
178
179 mutex_lock(&nfsd_mutex); 177 mutex_lock(&nfsd_mutex);
180 if (nn->nfsd_serv) 178 if (nfsd_serv)
181 rv = nn->nfsd_serv->sv_nrthreads; 179 rv = nfsd_serv->sv_nrthreads;
182 mutex_unlock(&nfsd_mutex); 180 mutex_unlock(&nfsd_mutex);
183 return rv; 181 return rv;
184} 182}
185 183
186static int nfsd_init_socks(struct net *net) 184static int nfsd_init_socks(int port)
187{ 185{
188 int error; 186 int error;
189 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 187 if (!list_empty(&nfsd_serv->sv_permsocks))
190
191 if (!list_empty(&nn->nfsd_serv->sv_permsocks))
192 return 0; 188 return 0;
193 189
194 error = svc_create_xprt(nn->nfsd_serv, "udp", net, PF_INET, NFS_PORT, 190 error = svc_create_xprt(nfsd_serv, "udp", &init_net, PF_INET, port,
195 SVC_SOCK_DEFAULTS); 191 SVC_SOCK_DEFAULTS);
196 if (error < 0) 192 if (error < 0)
197 return error; 193 return error;
198 194
199 error = svc_create_xprt(nn->nfsd_serv, "tcp", net, PF_INET, NFS_PORT, 195 error = svc_create_xprt(nfsd_serv, "tcp", &init_net, PF_INET, port,
200 SVC_SOCK_DEFAULTS); 196 SVC_SOCK_DEFAULTS);
201 if (error < 0) 197 if (error < 0)
202 return error; 198 return error;
@@ -204,15 +200,14 @@ static int nfsd_init_socks(struct net *net)
204 return 0; 200 return 0;
205} 201}
206 202
207static int nfsd_users = 0; 203static bool nfsd_up = false;
208 204
209static int nfsd_startup_generic(int nrservs) 205static int nfsd_startup(unsigned short port, int nrservs)
210{ 206{
211 int ret; 207 int ret;
212 208
213 if (nfsd_users++) 209 if (nfsd_up)
214 return 0; 210 return 0;
215
216 /* 211 /*
217 * Readahead param cache - will no-op if it already exists. 212 * Readahead param cache - will no-op if it already exists.
218 * (Note therefore results will be suboptimal if number of 213 * (Note therefore results will be suboptimal if number of
@@ -221,85 +216,49 @@ static int nfsd_startup_generic(int nrservs)
221 ret = nfsd_racache_init(2*nrservs); 216 ret = nfsd_racache_init(2*nrservs);
222 if (ret) 217 if (ret)
223 return ret; 218 return ret;
224 ret = nfs4_state_start(); 219 ret = nfsd_init_socks(port);
225 if (ret) 220 if (ret)
226 goto out_racache; 221 goto out_racache;
227 return 0; 222 ret = lockd_up();
228
229out_racache:
230 nfsd_racache_shutdown();
231 return ret;
232}
233
234static void nfsd_shutdown_generic(void)
235{
236 if (--nfsd_users)
237 return;
238
239 nfs4_state_shutdown();
240 nfsd_racache_shutdown();
241}
242
243static int nfsd_startup_net(int nrservs, struct net *net)
244{
245 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
246 int ret;
247
248 if (nn->nfsd_net_up)
249 return 0;
250
251 ret = nfsd_startup_generic(nrservs);
252 if (ret) 223 if (ret)
253 return ret; 224 goto out_racache;
254 ret = nfsd_init_socks(net); 225 ret = nfs4_state_start();
255 if (ret)
256 goto out_socks;
257 ret = lockd_up(net);
258 if (ret)
259 goto out_socks;
260 ret = nfs4_state_start_net(net);
261 if (ret) 226 if (ret)
262 goto out_lockd; 227 goto out_lockd;
263 228 nfsd_up = true;
264 nn->nfsd_net_up = true;
265 return 0; 229 return 0;
266
267out_lockd: 230out_lockd:
268 lockd_down(net); 231 lockd_down();
269out_socks: 232out_racache:
270 nfsd_shutdown_generic(); 233 nfsd_racache_shutdown();
271 return ret; 234 return ret;
272} 235}
273 236
274static void nfsd_shutdown_net(struct net *net) 237static void nfsd_shutdown(void)
275{
276 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
277
278 nfs4_state_shutdown_net(net);
279 lockd_down(net);
280 nn->nfsd_net_up = false;
281 nfsd_shutdown_generic();
282}
283
284static void nfsd_last_thread(struct svc_serv *serv, struct net *net)
285{ 238{
286 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
287
288 /* 239 /*
289 * write_ports can create the server without actually starting 240 * write_ports can create the server without actually starting
290 * any threads--if we get shut down before any threads are 241 * any threads--if we get shut down before any threads are
291 * started, then nfsd_last_thread will be run before any of this 242 * started, then nfsd_last_thread will be run before any of this
292 * other initialization has been done. 243 * other initialization has been done.
293 */ 244 */
294 if (!nn->nfsd_net_up) 245 if (!nfsd_up)
295 return; 246 return;
296 nfsd_shutdown_net(net); 247 nfs4_state_shutdown();
248 lockd_down();
249 nfsd_racache_shutdown();
250 nfsd_up = false;
251}
297 252
298 svc_rpcb_cleanup(serv, net); 253static void nfsd_last_thread(struct svc_serv *serv)
254{
255 /* When last nfsd thread exits we need to do some clean-up */
256 nfsd_serv = NULL;
257 nfsd_shutdown();
299 258
300 printk(KERN_WARNING "nfsd: last server has exited, flushing export " 259 printk(KERN_WARNING "nfsd: last server has exited, flushing export "
301 "cache\n"); 260 "cache\n");
302 nfsd_export_flush(net); 261 nfsd_export_flush();
303} 262}
304 263
305void nfsd_reset_versions(void) 264void nfsd_reset_versions(void)
@@ -345,105 +304,76 @@ static void set_max_drc(void)
345 dprintk("%s nfsd_drc_max_mem %u \n", __func__, nfsd_drc_max_mem); 304 dprintk("%s nfsd_drc_max_mem %u \n", __func__, nfsd_drc_max_mem);
346} 305}
347 306
348static int nfsd_get_default_max_blksize(void) 307int nfsd_create_serv(void)
349{
350 struct sysinfo i;
351 unsigned long long target;
352 unsigned long ret;
353
354 si_meminfo(&i);
355 target = (i.totalram - i.totalhigh) << PAGE_SHIFT;
356 /*
357 * Aim for 1/4096 of memory per thread This gives 1MB on 4Gig
358 * machines, but only uses 32K on 128M machines. Bottom out at
359 * 8K on 32M and smaller. Of course, this is only a default.
360 */
361 target >>= 12;
362
363 ret = NFSSVC_MAXBLKSIZE;
364 while (ret > target && ret >= 8*1024*2)
365 ret /= 2;
366 return ret;
367}
368
369int nfsd_create_serv(struct net *net)
370{ 308{
371 int error; 309 int err = 0;
372 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
373 310
374 WARN_ON(!mutex_is_locked(&nfsd_mutex)); 311 WARN_ON(!mutex_is_locked(&nfsd_mutex));
375 if (nn->nfsd_serv) { 312 if (nfsd_serv) {
376 svc_get(nn->nfsd_serv); 313 svc_get(nfsd_serv);
377 return 0; 314 return 0;
378 } 315 }
379 if (nfsd_max_blksize == 0) 316 if (nfsd_max_blksize == 0) {
380 nfsd_max_blksize = nfsd_get_default_max_blksize(); 317 /* choose a suitable default */
318 struct sysinfo i;
319 si_meminfo(&i);
320 /* Aim for 1/4096 of memory per thread
321 * This gives 1MB on 4Gig machines
322 * But only uses 32K on 128M machines.
323 * Bottom out at 8K on 32M and smaller.
324 * Of course, this is only a default.
325 */
326 nfsd_max_blksize = NFSSVC_MAXBLKSIZE;
327 i.totalram <<= PAGE_SHIFT - 12;
328 while (nfsd_max_blksize > i.totalram &&
329 nfsd_max_blksize >= 8*1024*2)
330 nfsd_max_blksize /= 2;
331 }
381 nfsd_reset_versions(); 332 nfsd_reset_versions();
382 nn->nfsd_serv = svc_create_pooled(&nfsd_program, nfsd_max_blksize, 333
334 nfsd_serv = svc_create_pooled(&nfsd_program, nfsd_max_blksize,
383 nfsd_last_thread, nfsd, THIS_MODULE); 335 nfsd_last_thread, nfsd, THIS_MODULE);
384 if (nn->nfsd_serv == NULL) 336 if (nfsd_serv == NULL)
385 return -ENOMEM; 337 return -ENOMEM;
386 338
387 error = svc_bind(nn->nfsd_serv, net);
388 if (error < 0) {
389 svc_destroy(nn->nfsd_serv);
390 return error;
391 }
392
393 set_max_drc(); 339 set_max_drc();
394 do_gettimeofday(&nn->nfssvc_boot); /* record boot time */ 340 do_gettimeofday(&nfssvc_boot); /* record boot time */
395 return 0; 341 return err;
396} 342}
397 343
398int nfsd_nrpools(struct net *net) 344int nfsd_nrpools(void)
399{ 345{
400 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 346 if (nfsd_serv == NULL)
401
402 if (nn->nfsd_serv == NULL)
403 return 0; 347 return 0;
404 else 348 else
405 return nn->nfsd_serv->sv_nrpools; 349 return nfsd_serv->sv_nrpools;
406} 350}
407 351
408int nfsd_get_nrthreads(int n, int *nthreads, struct net *net) 352int nfsd_get_nrthreads(int n, int *nthreads)
409{ 353{
410 int i = 0; 354 int i = 0;
411 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
412 355
413 if (nn->nfsd_serv != NULL) { 356 if (nfsd_serv != NULL) {
414 for (i = 0; i < nn->nfsd_serv->sv_nrpools && i < n; i++) 357 for (i = 0; i < nfsd_serv->sv_nrpools && i < n; i++)
415 nthreads[i] = nn->nfsd_serv->sv_pools[i].sp_nrthreads; 358 nthreads[i] = nfsd_serv->sv_pools[i].sp_nrthreads;
416 } 359 }
417 360
418 return 0; 361 return 0;
419} 362}
420 363
421void nfsd_destroy(struct net *net) 364int nfsd_set_nrthreads(int n, int *nthreads)
422{
423 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
424 int destroy = (nn->nfsd_serv->sv_nrthreads == 1);
425
426 if (destroy)
427 svc_shutdown_net(nn->nfsd_serv, net);
428 svc_destroy(nn->nfsd_serv);
429 if (destroy)
430 nn->nfsd_serv = NULL;
431}
432
433int nfsd_set_nrthreads(int n, int *nthreads, struct net *net)
434{ 365{
435 int i = 0; 366 int i = 0;
436 int tot = 0; 367 int tot = 0;
437 int err = 0; 368 int err = 0;
438 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
439 369
440 WARN_ON(!mutex_is_locked(&nfsd_mutex)); 370 WARN_ON(!mutex_is_locked(&nfsd_mutex));
441 371
442 if (nn->nfsd_serv == NULL || n <= 0) 372 if (nfsd_serv == NULL || n <= 0)
443 return 0; 373 return 0;
444 374
445 if (n > nn->nfsd_serv->sv_nrpools) 375 if (n > nfsd_serv->sv_nrpools)
446 n = nn->nfsd_serv->sv_nrpools; 376 n = nfsd_serv->sv_nrpools;
447 377
448 /* enforce a global maximum number of threads */ 378 /* enforce a global maximum number of threads */
449 tot = 0; 379 tot = 0;
@@ -473,14 +403,15 @@ int nfsd_set_nrthreads(int n, int *nthreads, struct net *net)
473 nthreads[0] = 1; 403 nthreads[0] = 1;
474 404
475 /* apply the new numbers */ 405 /* apply the new numbers */
476 svc_get(nn->nfsd_serv); 406 svc_get(nfsd_serv);
477 for (i = 0; i < n; i++) { 407 for (i = 0; i < n; i++) {
478 err = svc_set_num_threads(nn->nfsd_serv, &nn->nfsd_serv->sv_pools[i], 408 err = svc_set_num_threads(nfsd_serv, &nfsd_serv->sv_pools[i],
479 nthreads[i]); 409 nthreads[i]);
480 if (err) 410 if (err)
481 break; 411 break;
482 } 412 }
483 nfsd_destroy(net); 413 svc_destroy(nfsd_serv);
414
484 return err; 415 return err;
485} 416}
486 417
@@ -490,11 +421,10 @@ int nfsd_set_nrthreads(int n, int *nthreads, struct net *net)
490 * this is the first time nrservs is nonzero. 421 * this is the first time nrservs is nonzero.
491 */ 422 */
492int 423int
493nfsd_svc(int nrservs, struct net *net) 424nfsd_svc(unsigned short port, int nrservs)
494{ 425{
495 int error; 426 int error;
496 bool nfsd_up_before; 427 bool nfsd_up_before;
497 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
498 428
499 mutex_lock(&nfsd_mutex); 429 mutex_lock(&nfsd_mutex);
500 dprintk("nfsd: creating service\n"); 430 dprintk("nfsd: creating service\n");
@@ -503,31 +433,31 @@ nfsd_svc(int nrservs, struct net *net)
503 if (nrservs > NFSD_MAXSERVS) 433 if (nrservs > NFSD_MAXSERVS)
504 nrservs = NFSD_MAXSERVS; 434 nrservs = NFSD_MAXSERVS;
505 error = 0; 435 error = 0;
506 if (nrservs == 0 && nn->nfsd_serv == NULL) 436 if (nrservs == 0 && nfsd_serv == NULL)
507 goto out; 437 goto out;
508 438
509 error = nfsd_create_serv(net); 439 error = nfsd_create_serv();
510 if (error) 440 if (error)
511 goto out; 441 goto out;
512 442
513 nfsd_up_before = nn->nfsd_net_up; 443 nfsd_up_before = nfsd_up;
514 444
515 error = nfsd_startup_net(nrservs, net); 445 error = nfsd_startup(port, nrservs);
516 if (error) 446 if (error)
517 goto out_destroy; 447 goto out_destroy;
518 error = svc_set_num_threads(nn->nfsd_serv, NULL, nrservs); 448 error = svc_set_num_threads(nfsd_serv, NULL, nrservs);
519 if (error) 449 if (error)
520 goto out_shutdown; 450 goto out_shutdown;
521 /* We are holding a reference to nn->nfsd_serv which 451 /* We are holding a reference to nfsd_serv which
522 * we don't want to count in the return value, 452 * we don't want to count in the return value,
523 * so subtract 1 453 * so subtract 1
524 */ 454 */
525 error = nn->nfsd_serv->sv_nrthreads - 1; 455 error = nfsd_serv->sv_nrthreads - 1;
526out_shutdown: 456out_shutdown:
527 if (error < 0 && !nfsd_up_before) 457 if (error < 0 && !nfsd_up_before)
528 nfsd_shutdown_net(net); 458 nfsd_shutdown();
529out_destroy: 459out_destroy:
530 nfsd_destroy(net); /* Release server */ 460 svc_destroy(nfsd_serv); /* Release server */
531out: 461out:
532 mutex_unlock(&nfsd_mutex); 462 mutex_unlock(&nfsd_mutex);
533 return error; 463 return error;
@@ -541,9 +471,7 @@ static int
541nfsd(void *vrqstp) 471nfsd(void *vrqstp)
542{ 472{
543 struct svc_rqst *rqstp = (struct svc_rqst *) vrqstp; 473 struct svc_rqst *rqstp = (struct svc_rqst *) vrqstp;
544 struct svc_xprt *perm_sock = list_entry(rqstp->rq_server->sv_permsocks.next, typeof(struct svc_xprt), xpt_list); 474 int err, preverr = 0;
545 struct net *net = perm_sock->xpt_net;
546 int err;
547 475
548 /* Lock module and set up kernel thread */ 476 /* Lock module and set up kernel thread */
549 mutex_lock(&nfsd_mutex); 477 mutex_lock(&nfsd_mutex);
@@ -590,6 +518,16 @@ nfsd(void *vrqstp)
590 ; 518 ;
591 if (err == -EINTR) 519 if (err == -EINTR)
592 break; 520 break;
521 else if (err < 0) {
522 if (err != preverr) {
523 printk(KERN_WARNING "%s: unexpected error "
524 "from svc_recv (%d)\n", __func__, -err);
525 preverr = err;
526 }
527 schedule_timeout_uninterruptible(HZ);
528 continue;
529 }
530
593 validate_process_creds(); 531 validate_process_creds();
594 svc_process(rqstp); 532 svc_process(rqstp);
595 validate_process_creds(); 533 validate_process_creds();
@@ -602,13 +540,9 @@ nfsd(void *vrqstp)
602 nfsdstats.th_cnt --; 540 nfsdstats.th_cnt --;
603 541
604out: 542out:
605 rqstp->rq_server = NULL;
606
607 /* Release the thread */ 543 /* Release the thread */
608 svc_exit_thread(rqstp); 544 svc_exit_thread(rqstp);
609 545
610 nfsd_destroy(net);
611
612 /* Release module */ 546 /* Release module */
613 mutex_unlock(&nfsd_mutex); 547 mutex_unlock(&nfsd_mutex);
614 module_put_and_exit(0); 548 module_put_and_exit(0);
@@ -696,24 +630,21 @@ nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
696 } 630 }
697 631
698 /* Store reply in cache. */ 632 /* Store reply in cache. */
699 nfsd_cache_update(rqstp, rqstp->rq_cachetype, statp + 1); 633 nfsd_cache_update(rqstp, proc->pc_cachetype, statp + 1);
700 return 1; 634 return 1;
701} 635}
702 636
703int nfsd_pool_stats_open(struct inode *inode, struct file *file) 637int nfsd_pool_stats_open(struct inode *inode, struct file *file)
704{ 638{
705 int ret; 639 int ret;
706 struct net *net = &init_net;
707 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
708
709 mutex_lock(&nfsd_mutex); 640 mutex_lock(&nfsd_mutex);
710 if (nn->nfsd_serv == NULL) { 641 if (nfsd_serv == NULL) {
711 mutex_unlock(&nfsd_mutex); 642 mutex_unlock(&nfsd_mutex);
712 return -ENODEV; 643 return -ENODEV;
713 } 644 }
714 /* bump up the psudo refcount while traversing */ 645 /* bump up the psudo refcount while traversing */
715 svc_get(nn->nfsd_serv); 646 svc_get(nfsd_serv);
716 ret = svc_pool_stats_open(nn->nfsd_serv, file); 647 ret = svc_pool_stats_open(nfsd_serv, file);
717 mutex_unlock(&nfsd_mutex); 648 mutex_unlock(&nfsd_mutex);
718 return ret; 649 return ret;
719} 650}
@@ -721,11 +652,9 @@ int nfsd_pool_stats_open(struct inode *inode, struct file *file)
721int nfsd_pool_stats_release(struct inode *inode, struct file *file) 652int nfsd_pool_stats_release(struct inode *inode, struct file *file)
722{ 653{
723 int ret = seq_release(inode, file); 654 int ret = seq_release(inode, file);
724 struct net *net = &init_net;
725
726 mutex_lock(&nfsd_mutex); 655 mutex_lock(&nfsd_mutex);
727 /* this function really, really should have been called svc_put() */ 656 /* this function really, really should have been called svc_put() */
728 nfsd_destroy(net); 657 svc_destroy(nfsd_serv);
729 mutex_unlock(&nfsd_mutex); 658 mutex_unlock(&nfsd_mutex);
730 return ret; 659 return ret;
731} 660}