diff options
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 06b2a26edfe0..e2c43464f237 100644 --- a/fs/nfsd/nfssvc.c +++ b/fs/nfsd/nfssvc.c | |||
@@ -180,15 +180,80 @@ int nfsd_nrthreads(void) | |||
180 | return rv; | 180 | return rv; |
181 | } | 181 | } |
182 | 182 | ||
183 | static int nfsd_init_socks(int port) | ||
184 | { | ||
185 | int error; | ||
186 | if (!list_empty(&nfsd_serv->sv_permsocks)) | ||
187 | return 0; | ||
188 | |||
189 | error = svc_create_xprt(nfsd_serv, "udp", PF_INET, port, | ||
190 | SVC_SOCK_DEFAULTS); | ||
191 | if (error < 0) | ||
192 | return error; | ||
193 | |||
194 | error = svc_create_xprt(nfsd_serv, "tcp", PF_INET, port, | ||
195 | SVC_SOCK_DEFAULTS); | ||
196 | if (error < 0) | ||
197 | return error; | ||
198 | |||
199 | return 0; | ||
200 | } | ||
201 | |||
202 | static bool nfsd_up = false; | ||
203 | |||
204 | static int nfsd_startup(unsigned short port, int nrservs) | ||
205 | { | ||
206 | int ret; | ||
207 | |||
208 | if (nfsd_up) | ||
209 | return 0; | ||
210 | /* | ||
211 | * Readahead param cache - will no-op if it already exists. | ||
212 | * (Note therefore results will be suboptimal if number of | ||
213 | * threads is modified after nfsd start.) | ||
214 | */ | ||
215 | ret = nfsd_racache_init(2*nrservs); | ||
216 | if (ret) | ||
217 | return ret; | ||
218 | ret = nfsd_init_socks(port); | ||
219 | if (ret) | ||
220 | goto out_racache; | ||
221 | ret = lockd_up(); | ||
222 | if (ret) | ||
223 | goto out_racache; | ||
224 | ret = nfs4_state_start(); | ||
225 | if (ret) | ||
226 | goto out_lockd; | ||
227 | nfsd_up = true; | ||
228 | return 0; | ||
229 | out_lockd: | ||
230 | lockd_down(); | ||
231 | out_racache: | ||
232 | nfsd_racache_shutdown(); | ||
233 | return ret; | ||
234 | } | ||
235 | |||
236 | static void nfsd_shutdown(void) | ||
237 | { | ||
238 | /* | ||
239 | * write_ports can create the server without actually starting | ||
240 | * any threads--if we get shut down before any threads are | ||
241 | * started, then nfsd_last_thread will be run before any of this | ||
242 | * other initialization has been done. | ||
243 | */ | ||
244 | if (!nfsd_up) | ||
245 | return; | ||
246 | nfs4_state_shutdown(); | ||
247 | lockd_down(); | ||
248 | nfsd_racache_shutdown(); | ||
249 | nfsd_up = false; | ||
250 | } | ||
251 | |||
183 | static void nfsd_last_thread(struct svc_serv *serv) | 252 | static void nfsd_last_thread(struct svc_serv *serv) |
184 | { | 253 | { |
185 | /* When last nfsd thread exits we need to do some clean-up */ | 254 | /* When last nfsd thread exits we need to do some clean-up */ |
186 | struct svc_xprt *xprt; | ||
187 | list_for_each_entry(xprt, &serv->sv_permsocks, xpt_list) | ||
188 | lockd_down(); | ||
189 | nfsd_serv = NULL; | 255 | nfsd_serv = NULL; |
190 | nfsd_racache_shutdown(); | 256 | nfsd_shutdown(); |
191 | nfs4_state_shutdown(); | ||
192 | 257 | ||
193 | printk(KERN_WARNING "nfsd: last server has exited, flushing export " | 258 | printk(KERN_WARNING "nfsd: last server has exited, flushing export " |
194 | "cache\n"); | 259 | "cache\n"); |
@@ -263,45 +328,18 @@ int nfsd_create_serv(void) | |||
263 | nfsd_max_blksize >= 8*1024*2) | 328 | nfsd_max_blksize >= 8*1024*2) |
264 | nfsd_max_blksize /= 2; | 329 | nfsd_max_blksize /= 2; |
265 | } | 330 | } |
331 | nfsd_reset_versions(); | ||
266 | 332 | ||
267 | nfsd_serv = svc_create_pooled(&nfsd_program, nfsd_max_blksize, | 333 | nfsd_serv = svc_create_pooled(&nfsd_program, nfsd_max_blksize, |
268 | nfsd_last_thread, nfsd, THIS_MODULE); | 334 | nfsd_last_thread, nfsd, THIS_MODULE); |
269 | if (nfsd_serv == NULL) | 335 | if (nfsd_serv == NULL) |
270 | err = -ENOMEM; | 336 | return -ENOMEM; |
271 | else | ||
272 | set_max_drc(); | ||
273 | 337 | ||
338 | set_max_drc(); | ||
274 | do_gettimeofday(&nfssvc_boot); /* record boot time */ | 339 | do_gettimeofday(&nfssvc_boot); /* record boot time */ |
275 | return err; | 340 | return err; |
276 | } | 341 | } |
277 | 342 | ||
278 | static int nfsd_init_socks(int port) | ||
279 | { | ||
280 | int error; | ||
281 | if (!list_empty(&nfsd_serv->sv_permsocks)) | ||
282 | return 0; | ||
283 | |||
284 | error = svc_create_xprt(nfsd_serv, "udp", PF_INET, port, | ||
285 | SVC_SOCK_DEFAULTS); | ||
286 | if (error < 0) | ||
287 | return error; | ||
288 | |||
289 | error = lockd_up(); | ||
290 | if (error < 0) | ||
291 | return error; | ||
292 | |||
293 | error = svc_create_xprt(nfsd_serv, "tcp", PF_INET, port, | ||
294 | SVC_SOCK_DEFAULTS); | ||
295 | if (error < 0) | ||
296 | return error; | ||
297 | |||
298 | error = lockd_up(); | ||
299 | if (error < 0) | ||
300 | return error; | ||
301 | |||
302 | return 0; | ||
303 | } | ||
304 | |||
305 | int nfsd_nrpools(void) | 343 | int nfsd_nrpools(void) |
306 | { | 344 | { |
307 | if (nfsd_serv == NULL) | 345 | if (nfsd_serv == NULL) |
@@ -376,10 +414,16 @@ int nfsd_set_nrthreads(int n, int *nthreads) | |||
376 | return err; | 414 | return err; |
377 | } | 415 | } |
378 | 416 | ||
417 | /* | ||
418 | * Adjust the number of threads and return the new number of threads. | ||
419 | * This is also the function that starts the server if necessary, if | ||
420 | * this is the first time nrservs is nonzero. | ||
421 | */ | ||
379 | int | 422 | int |
380 | nfsd_svc(unsigned short port, int nrservs) | 423 | nfsd_svc(unsigned short port, int nrservs) |
381 | { | 424 | { |
382 | int error; | 425 | int error; |
426 | bool nfsd_up_before; | ||
383 | 427 | ||
384 | mutex_lock(&nfsd_mutex); | 428 | mutex_lock(&nfsd_mutex); |
385 | dprintk("nfsd: creating service\n"); | 429 | dprintk("nfsd: creating service\n"); |
@@ -391,34 +435,29 @@ nfsd_svc(unsigned short port, int nrservs) | |||
391 | if (nrservs == 0 && nfsd_serv == NULL) | 435 | if (nrservs == 0 && nfsd_serv == NULL) |
392 | goto out; | 436 | goto out; |
393 | 437 | ||
394 | /* Readahead param cache - will no-op if it already exists */ | 438 | error = nfsd_create_serv(); |
395 | error = nfsd_racache_init(2*nrservs); | ||
396 | if (error<0) | ||
397 | goto out; | ||
398 | error = nfs4_state_start(); | ||
399 | if (error) | 439 | if (error) |
400 | goto out; | 440 | goto out; |
401 | 441 | ||
402 | nfsd_reset_versions(); | 442 | nfsd_up_before = nfsd_up; |
403 | |||
404 | error = nfsd_create_serv(); | ||
405 | 443 | ||
444 | error = nfsd_startup(port, nrservs); | ||
406 | if (error) | 445 | if (error) |
407 | goto out; | 446 | goto out_destroy; |
408 | error = nfsd_init_socks(port); | ||
409 | if (error) | ||
410 | goto failure; | ||
411 | |||
412 | error = svc_set_num_threads(nfsd_serv, NULL, nrservs); | 447 | error = svc_set_num_threads(nfsd_serv, NULL, nrservs); |
413 | if (error == 0) | 448 | if (error) |
414 | /* We are holding a reference to nfsd_serv which | 449 | goto out_shutdown; |
415 | * we don't want to count in the return value, | 450 | /* We are holding a reference to nfsd_serv which |
416 | * so subtract 1 | 451 | * we don't want to count in the return value, |
417 | */ | 452 | * so subtract 1 |
418 | error = nfsd_serv->sv_nrthreads - 1; | 453 | */ |
419 | failure: | 454 | error = nfsd_serv->sv_nrthreads - 1; |
455 | out_shutdown: | ||
456 | if (error < 0 && !nfsd_up_before) | ||
457 | nfsd_shutdown(); | ||
458 | out_destroy: | ||
420 | svc_destroy(nfsd_serv); /* Release server */ | 459 | svc_destroy(nfsd_serv); /* Release server */ |
421 | out: | 460 | out: |
422 | mutex_unlock(&nfsd_mutex); | 461 | mutex_unlock(&nfsd_mutex); |
423 | return error; | 462 | return error; |
424 | } | 463 | } |