Commit c7b824c3 authored by Chuck Lever's avatar Chuck Lever

NFSD: Replace the "init once" mechanism

In a moment, the nfsd_file_hashtbl global will be replaced with an
rhashtable. Replace the one or two spots that need to check if the
hash table is available. We can easily reuse the SHUTDOWN flag for
this purpose.

Document that this mechanism relies on callers to hold the
nfsd_mutex to prevent init, shutdown, and purging to run
concurrently.
Reviewed-by: default avatarJeff Layton <jlayton@kernel.org>
Signed-off-by: default avatarChuck Lever <chuck.lever@oracle.com>
parent f0743c2b
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
#define NFSD_FILE_HASH_SIZE (1 << NFSD_FILE_HASH_BITS) #define NFSD_FILE_HASH_SIZE (1 << NFSD_FILE_HASH_BITS)
#define NFSD_LAUNDRETTE_DELAY (2 * HZ) #define NFSD_LAUNDRETTE_DELAY (2 * HZ)
#define NFSD_FILE_SHUTDOWN (1) #define NFSD_FILE_CACHE_UP (0)
/* We only care about NFSD_MAY_READ/WRITE for this cache */ /* We only care about NFSD_MAY_READ/WRITE for this cache */
#define NFSD_FILE_MAY_MASK (NFSD_MAY_READ|NFSD_MAY_WRITE) #define NFSD_FILE_MAY_MASK (NFSD_MAY_READ|NFSD_MAY_WRITE)
...@@ -59,7 +59,7 @@ static struct kmem_cache *nfsd_file_slab; ...@@ -59,7 +59,7 @@ static struct kmem_cache *nfsd_file_slab;
static struct kmem_cache *nfsd_file_mark_slab; static struct kmem_cache *nfsd_file_mark_slab;
static struct nfsd_fcache_bucket *nfsd_file_hashtbl; static struct nfsd_fcache_bucket *nfsd_file_hashtbl;
static struct list_lru nfsd_file_lru; static struct list_lru nfsd_file_lru;
static long nfsd_file_lru_flags; static unsigned long nfsd_file_flags;
static struct fsnotify_group *nfsd_file_fsnotify_group; static struct fsnotify_group *nfsd_file_fsnotify_group;
static atomic_long_t nfsd_filecache_count; static atomic_long_t nfsd_filecache_count;
static struct delayed_work nfsd_filecache_laundrette; static struct delayed_work nfsd_filecache_laundrette;
...@@ -67,9 +67,8 @@ static struct delayed_work nfsd_filecache_laundrette; ...@@ -67,9 +67,8 @@ static struct delayed_work nfsd_filecache_laundrette;
static void static void
nfsd_file_schedule_laundrette(void) nfsd_file_schedule_laundrette(void)
{ {
long count = atomic_long_read(&nfsd_filecache_count); if ((atomic_long_read(&nfsd_filecache_count) == 0) ||
test_bit(NFSD_FILE_CACHE_UP, &nfsd_file_flags) == 0)
if (count == 0 || test_bit(NFSD_FILE_SHUTDOWN, &nfsd_file_lru_flags))
return; return;
queue_delayed_work(system_wq, &nfsd_filecache_laundrette, queue_delayed_work(system_wq, &nfsd_filecache_laundrette,
...@@ -698,9 +697,8 @@ nfsd_file_cache_init(void) ...@@ -698,9 +697,8 @@ nfsd_file_cache_init(void)
int ret = -ENOMEM; int ret = -ENOMEM;
unsigned int i; unsigned int i;
clear_bit(NFSD_FILE_SHUTDOWN, &nfsd_file_lru_flags); lockdep_assert_held(&nfsd_mutex);
if (test_and_set_bit(NFSD_FILE_CACHE_UP, &nfsd_file_flags) == 1)
if (nfsd_file_hashtbl)
return 0; return 0;
nfsd_filecache_wq = alloc_workqueue("nfsd_filecache", 0, 0); nfsd_filecache_wq = alloc_workqueue("nfsd_filecache", 0, 0);
...@@ -786,8 +784,8 @@ nfsd_file_cache_init(void) ...@@ -786,8 +784,8 @@ nfsd_file_cache_init(void)
/* /*
* Note this can deadlock with nfsd_file_lru_cb. * Note this can deadlock with nfsd_file_lru_cb.
*/ */
void static void
nfsd_file_cache_purge(struct net *net) __nfsd_file_cache_purge(struct net *net)
{ {
unsigned int i; unsigned int i;
struct nfsd_file *nf; struct nfsd_file *nf;
...@@ -795,9 +793,6 @@ nfsd_file_cache_purge(struct net *net) ...@@ -795,9 +793,6 @@ nfsd_file_cache_purge(struct net *net)
LIST_HEAD(dispose); LIST_HEAD(dispose);
bool del; bool del;
if (!nfsd_file_hashtbl)
return;
for (i = 0; i < NFSD_FILE_HASH_SIZE; i++) { for (i = 0; i < NFSD_FILE_HASH_SIZE; i++) {
struct nfsd_fcache_bucket *nfb = &nfsd_file_hashtbl[i]; struct nfsd_fcache_bucket *nfb = &nfsd_file_hashtbl[i];
...@@ -858,6 +853,19 @@ nfsd_file_cache_start_net(struct net *net) ...@@ -858,6 +853,19 @@ nfsd_file_cache_start_net(struct net *net)
return nn->fcache_disposal ? 0 : -ENOMEM; return nn->fcache_disposal ? 0 : -ENOMEM;
} }
/**
* nfsd_file_cache_purge - Remove all cache items associated with @net
* @net: target net namespace
*
*/
void
nfsd_file_cache_purge(struct net *net)
{
lockdep_assert_held(&nfsd_mutex);
if (test_bit(NFSD_FILE_CACHE_UP, &nfsd_file_flags) == 1)
__nfsd_file_cache_purge(net);
}
void void
nfsd_file_cache_shutdown_net(struct net *net) nfsd_file_cache_shutdown_net(struct net *net)
{ {
...@@ -870,7 +878,9 @@ nfsd_file_cache_shutdown(void) ...@@ -870,7 +878,9 @@ nfsd_file_cache_shutdown(void)
{ {
int i; int i;
set_bit(NFSD_FILE_SHUTDOWN, &nfsd_file_lru_flags); lockdep_assert_held(&nfsd_mutex);
if (test_and_clear_bit(NFSD_FILE_CACHE_UP, &nfsd_file_flags) == 0)
return;
lease_unregister_notifier(&nfsd_file_lease_notifier); lease_unregister_notifier(&nfsd_file_lease_notifier);
unregister_shrinker(&nfsd_file_shrinker); unregister_shrinker(&nfsd_file_shrinker);
...@@ -879,7 +889,7 @@ nfsd_file_cache_shutdown(void) ...@@ -879,7 +889,7 @@ nfsd_file_cache_shutdown(void)
* calling nfsd_file_cache_purge * calling nfsd_file_cache_purge
*/ */
cancel_delayed_work_sync(&nfsd_filecache_laundrette); cancel_delayed_work_sync(&nfsd_filecache_laundrette);
nfsd_file_cache_purge(NULL); __nfsd_file_cache_purge(NULL);
list_lru_destroy(&nfsd_file_lru); list_lru_destroy(&nfsd_file_lru);
rcu_barrier(); rcu_barrier();
fsnotify_put_group(nfsd_file_fsnotify_group); fsnotify_put_group(nfsd_file_fsnotify_group);
...@@ -1143,7 +1153,7 @@ static int nfsd_file_cache_stats_show(struct seq_file *m, void *v) ...@@ -1143,7 +1153,7 @@ static int nfsd_file_cache_stats_show(struct seq_file *m, void *v)
* don't end up racing with server shutdown * don't end up racing with server shutdown
*/ */
mutex_lock(&nfsd_mutex); mutex_lock(&nfsd_mutex);
if (nfsd_file_hashtbl) { if (test_bit(NFSD_FILE_CACHE_UP, &nfsd_file_flags) == 1) {
for (i = 0; i < NFSD_FILE_HASH_SIZE; i++) { for (i = 0; i < NFSD_FILE_HASH_SIZE; i++) {
count += nfsd_file_hashtbl[i].nfb_count; count += nfsd_file_hashtbl[i].nfb_count;
longest = max(longest, nfsd_file_hashtbl[i].nfb_count); longest = max(longest, nfsd_file_hashtbl[i].nfb_count);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment