diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2009-08-09 15:14:27 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2009-08-09 15:14:27 -0400 |
commit | 5b7a1b9f9214cb89dd164b43ca3fab7af4058e06 (patch) | |
tree | f39343aeedb1973eddac30ef84ec1bbf73f1fe14 /net/sunrpc | |
parent | 2da8ca26c6bfad685bfddf39728eac1c83906aa9 (diff) |
SUNRPC: Ensure we initialise the cache_detail before creating procfs files
Also ensure that we destroy those files before we destroy the cache_detail.
Otherwise, user processes might attempt to write into uninitialised caches.
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'net/sunrpc')
-rw-r--r-- | net/sunrpc/cache.c | 30 |
1 files changed, 20 insertions, 10 deletions
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index 8ede4a6f384b..062d4f4307eb 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c | |||
@@ -347,13 +347,8 @@ static int create_cache_proc_entries(struct cache_detail *cd) | |||
347 | } | 347 | } |
348 | #endif | 348 | #endif |
349 | 349 | ||
350 | int cache_register(struct cache_detail *cd) | 350 | static void sunrpc_init_cache_detail(struct cache_detail *cd) |
351 | { | 351 | { |
352 | int ret; | ||
353 | |||
354 | ret = create_cache_proc_entries(cd); | ||
355 | if (ret) | ||
356 | return ret; | ||
357 | rwlock_init(&cd->hash_lock); | 352 | rwlock_init(&cd->hash_lock); |
358 | INIT_LIST_HEAD(&cd->queue); | 353 | INIT_LIST_HEAD(&cd->queue); |
359 | spin_lock(&cache_list_lock); | 354 | spin_lock(&cache_list_lock); |
@@ -367,11 +362,9 @@ int cache_register(struct cache_detail *cd) | |||
367 | 362 | ||
368 | /* start the cleaning process */ | 363 | /* start the cleaning process */ |
369 | schedule_delayed_work(&cache_cleaner, 0); | 364 | schedule_delayed_work(&cache_cleaner, 0); |
370 | return 0; | ||
371 | } | 365 | } |
372 | EXPORT_SYMBOL_GPL(cache_register); | ||
373 | 366 | ||
374 | void cache_unregister(struct cache_detail *cd) | 367 | static void sunrpc_destroy_cache_detail(struct cache_detail *cd) |
375 | { | 368 | { |
376 | cache_purge(cd); | 369 | cache_purge(cd); |
377 | spin_lock(&cache_list_lock); | 370 | spin_lock(&cache_list_lock); |
@@ -386,7 +379,6 @@ void cache_unregister(struct cache_detail *cd) | |||
386 | list_del_init(&cd->others); | 379 | list_del_init(&cd->others); |
387 | write_unlock(&cd->hash_lock); | 380 | write_unlock(&cd->hash_lock); |
388 | spin_unlock(&cache_list_lock); | 381 | spin_unlock(&cache_list_lock); |
389 | remove_cache_proc_entries(cd); | ||
390 | if (list_empty(&cache_list)) { | 382 | if (list_empty(&cache_list)) { |
391 | /* module must be being unloaded so its safe to kill the worker */ | 383 | /* module must be being unloaded so its safe to kill the worker */ |
392 | cancel_delayed_work_sync(&cache_cleaner); | 384 | cancel_delayed_work_sync(&cache_cleaner); |
@@ -395,6 +387,24 @@ void cache_unregister(struct cache_detail *cd) | |||
395 | out: | 387 | out: |
396 | printk(KERN_ERR "nfsd: failed to unregister %s cache\n", cd->name); | 388 | printk(KERN_ERR "nfsd: failed to unregister %s cache\n", cd->name); |
397 | } | 389 | } |
390 | |||
391 | int cache_register(struct cache_detail *cd) | ||
392 | { | ||
393 | int ret; | ||
394 | |||
395 | sunrpc_init_cache_detail(cd); | ||
396 | ret = create_cache_proc_entries(cd); | ||
397 | if (ret) | ||
398 | sunrpc_destroy_cache_detail(cd); | ||
399 | return ret; | ||
400 | } | ||
401 | EXPORT_SYMBOL_GPL(cache_register); | ||
402 | |||
403 | void cache_unregister(struct cache_detail *cd) | ||
404 | { | ||
405 | remove_cache_proc_entries(cd); | ||
406 | sunrpc_destroy_cache_detail(cd); | ||
407 | } | ||
398 | EXPORT_SYMBOL_GPL(cache_unregister); | 408 | EXPORT_SYMBOL_GPL(cache_unregister); |
399 | 409 | ||
400 | /* clean cache tries to find something to clean | 410 | /* clean cache tries to find something to clean |