diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-07 14:24:41 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-07 14:24:41 -0700 |
commit | 0d9f9e122c74583de15a86d1c660c08dc298f2c8 (patch) | |
tree | a04ad387e231db43db112753fa2eae23754189a9 /fs/nfsd/nfssvc.c | |
parent | df44f9f4f9b5d362b5a2d1c8444fe7e6d4c42653 (diff) | |
parent | 998db52c03cd293d16a457f1b396cea932244147 (diff) |
Merge branch 'for-2.6.36' of git://linux-nfs.org/~bfields/linux
* 'for-2.6.36' of git://linux-nfs.org/~bfields/linux: (34 commits)
nfsd4: fix file open accounting for RDWR opens
nfsd: don't allow setting maxblksize after svc created
nfsd: initialize nfsd versions before creating svc
net: sunrpc: removed duplicated #include
nfsd41: Fix a crash when a callback is retried
nfsd: fix startup/shutdown order bug
nfsd: minor nfsd read api cleanup
gcc-4.6: nfsd: fix initialized but not read warnings
nfsd4: share file descriptors between stateid's
nfsd4: fix openmode checking on IO using lock stateid
nfsd4: miscellaneous process_open2 cleanup
nfsd4: don't pretend to support write delegations
nfsd: bypass readahead cache when have struct file
nfsd: minor nfsd_svc() cleanup
nfsd: move more into nfsd_startup()
nfsd: just keep single lockd reference for nfsd
nfsd: clean up nfsd_create_serv error handling
nfsd: fix error handling in __write_ports_addxprt
nfsd: fix error handling when starting nfsd with rpcbind down
nfsd4: fix v4 state shutdown error paths
...
Diffstat (limited to 'fs/nfsd/nfssvc.c')
-rw-r--r-- | fs/nfsd/nfssvc.c | 151 |
1 files changed, 95 insertions, 56 deletions
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c index 06b2a26edfe..e2c43464f23 100644 --- a/fs/nfsd/nfssvc.c +++ b/fs/nfsd/nfssvc.c @@ -180,15 +180,80 @@ int nfsd_nrthreads(void) return rv; } +static int nfsd_init_socks(int port) +{ + int error; + if (!list_empty(&nfsd_serv->sv_permsocks)) + return 0; + + error = svc_create_xprt(nfsd_serv, "udp", PF_INET, port, + SVC_SOCK_DEFAULTS); + if (error < 0) + return error; + + error = svc_create_xprt(nfsd_serv, "tcp", PF_INET, port, + SVC_SOCK_DEFAULTS); + if (error < 0) + return error; + + return 0; +} + +static bool nfsd_up = false; + +static int nfsd_startup(unsigned short port, int nrservs) +{ + int ret; + + if (nfsd_up) + return 0; + /* + * Readahead param cache - will no-op if it already exists. + * (Note therefore results will be suboptimal if number of + * threads is modified after nfsd start.) + */ + ret = nfsd_racache_init(2*nrservs); + if (ret) + return ret; + ret = nfsd_init_socks(port); + if (ret) + goto out_racache; + ret = lockd_up(); + if (ret) + goto out_racache; + ret = nfs4_state_start(); + if (ret) + goto out_lockd; + nfsd_up = true; + return 0; +out_lockd: + lockd_down(); +out_racache: + nfsd_racache_shutdown(); + return ret; +} + +static void nfsd_shutdown(void) +{ + /* + * write_ports can create the server without actually starting + * any threads--if we get shut down before any threads are + * started, then nfsd_last_thread will be run before any of this + * other initialization has been done. + */ + if (!nfsd_up) + return; + nfs4_state_shutdown(); + lockd_down(); + nfsd_racache_shutdown(); + nfsd_up = false; +} + static void nfsd_last_thread(struct svc_serv *serv) { /* When last nfsd thread exits we need to do some clean-up */ - struct svc_xprt *xprt; - list_for_each_entry(xprt, &serv->sv_permsocks, xpt_list) - lockd_down(); nfsd_serv = NULL; - nfsd_racache_shutdown(); - nfs4_state_shutdown(); + nfsd_shutdown(); printk(KERN_WARNING "nfsd: last server has exited, flushing export " "cache\n"); @@ -263,45 +328,18 @@ int nfsd_create_serv(void) nfsd_max_blksize >= 8*1024*2) nfsd_max_blksize /= 2; } + nfsd_reset_versions(); nfsd_serv = svc_create_pooled(&nfsd_program, nfsd_max_blksize, nfsd_last_thread, nfsd, THIS_MODULE); if (nfsd_serv == NULL) - err = -ENOMEM; - else - set_max_drc(); + return -ENOMEM; + set_max_drc(); do_gettimeofday(&nfssvc_boot); /* record boot time */ return err; } -static int nfsd_init_socks(int port) -{ - int error; - if (!list_empty(&nfsd_serv->sv_permsocks)) - return 0; - - error = svc_create_xprt(nfsd_serv, "udp", PF_INET, port, - SVC_SOCK_DEFAULTS); - if (error < 0) - return error; - - error = lockd_up(); - if (error < 0) - return error; - - error = svc_create_xprt(nfsd_serv, "tcp", PF_INET, port, - SVC_SOCK_DEFAULTS); - if (error < 0) - return error; - - error = lockd_up(); - if (error < 0) - return error; - - return 0; -} - int nfsd_nrpools(void) { if (nfsd_serv == NULL) @@ -376,10 +414,16 @@ int nfsd_set_nrthreads(int n, int *nthreads) return err; } +/* + * Adjust the number of threads and return the new number of threads. + * This is also the function that starts the server if necessary, if + * this is the first time nrservs is nonzero. + */ int nfsd_svc(unsigned short port, int nrservs) { int error; + bool nfsd_up_before; mutex_lock(&nfsd_mutex); dprintk("nfsd: creating service\n"); @@ -391,34 +435,29 @@ nfsd_svc(unsigned short port, int nrservs) if (nrservs == 0 && nfsd_serv == NULL) goto out; - /* Readahead param cache - will no-op if it already exists */ - error = nfsd_racache_init(2*nrservs); - if (error<0) - goto out; - error = nfs4_state_start(); + error = nfsd_create_serv(); if (error) goto out; - nfsd_reset_versions(); - - error = nfsd_create_serv(); + nfsd_up_before = nfsd_up; + error = nfsd_startup(port, nrservs); if (error) - goto out; - error = nfsd_init_socks(port); - if (error) - goto failure; - + goto out_destroy; error = svc_set_num_threads(nfsd_serv, NULL, nrservs); - if (error == 0) - /* We are holding a reference to nfsd_serv which - * we don't want to count in the return value, - * so subtract 1 - */ - error = nfsd_serv->sv_nrthreads - 1; - failure: + if (error) + goto out_shutdown; + /* We are holding a reference to nfsd_serv which + * we don't want to count in the return value, + * so subtract 1 + */ + error = nfsd_serv->sv_nrthreads - 1; +out_shutdown: + if (error < 0 && !nfsd_up_before) + nfsd_shutdown(); +out_destroy: svc_destroy(nfsd_serv); /* Release server */ - out: +out: mutex_unlock(&nfsd_mutex); return error; } |