Skip to content

Commit 1463b38

Browse files
neilbrownchucklever
authored andcommitted
NFSD: simplify per-net file cache management
We currently have a 'laundrette' for closing cached files - a different work-item for each network-namespace. These 'laundrettes' (aka struct nfsd_fcache_disposal) are currently on a list, and are freed using rcu. The list is not necessary as we have a per-namespace structure (struct nfsd_net) which can hold a link to the nfsd_fcache_disposal. The use of kfree_rcu is also unnecessary as the cache is cleaned of all files associated with a given namespace, and no new files can be added, before the nfsd_fcache_disposal is freed. So add a '->fcache_disposal' link to nfsd_net, and discard the list management and rcu usage. Signed-off-by: NeilBrown <neilb@suse.de> Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
1 parent 1e37d0e commit 1463b38

2 files changed

Lines changed: 17 additions & 61 deletions

File tree

fs/nfsd/filecache.c

Lines changed: 15 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,9 @@ struct nfsd_fcache_bucket {
4444
static DEFINE_PER_CPU(unsigned long, nfsd_file_cache_hits);
4545

4646
struct nfsd_fcache_disposal {
47-
struct list_head list;
4847
struct work_struct work;
49-
struct net *net;
5048
spinlock_t lock;
5149
struct list_head freeme;
52-
struct rcu_head rcu;
5350
};
5451

5552
static struct workqueue_struct *nfsd_filecache_wq __read_mostly;
@@ -62,8 +59,6 @@ static long nfsd_file_lru_flags;
6259
static struct fsnotify_group *nfsd_file_fsnotify_group;
6360
static atomic_long_t nfsd_filecache_count;
6461
static struct delayed_work nfsd_filecache_laundrette;
65-
static DEFINE_SPINLOCK(laundrette_lock);
66-
static LIST_HEAD(laundrettes);
6762

6863
static void nfsd_file_gc(void);
6964

@@ -367,19 +362,13 @@ nfsd_file_list_remove_disposal(struct list_head *dst,
367362
static void
368363
nfsd_file_list_add_disposal(struct list_head *files, struct net *net)
369364
{
370-
struct nfsd_fcache_disposal *l;
365+
struct nfsd_net *nn = net_generic(net, nfsd_net_id);
366+
struct nfsd_fcache_disposal *l = nn->fcache_disposal;
371367

372-
rcu_read_lock();
373-
list_for_each_entry_rcu(l, &laundrettes, list) {
374-
if (l->net == net) {
375-
spin_lock(&l->lock);
376-
list_splice_tail_init(files, &l->freeme);
377-
spin_unlock(&l->lock);
378-
queue_work(nfsd_filecache_wq, &l->work);
379-
break;
380-
}
381-
}
382-
rcu_read_unlock();
368+
spin_lock(&l->lock);
369+
list_splice_tail_init(files, &l->freeme);
370+
spin_unlock(&l->lock);
371+
queue_work(nfsd_filecache_wq, &l->work);
383372
}
384373

385374
static void
@@ -755,15 +744,14 @@ nfsd_file_cache_purge(struct net *net)
755744
}
756745

757746
static struct nfsd_fcache_disposal *
758-
nfsd_alloc_fcache_disposal(struct net *net)
747+
nfsd_alloc_fcache_disposal(void)
759748
{
760749
struct nfsd_fcache_disposal *l;
761750

762751
l = kmalloc(sizeof(*l), GFP_KERNEL);
763752
if (!l)
764753
return NULL;
765754
INIT_WORK(&l->work, nfsd_file_delayed_close);
766-
l->net = net;
767755
spin_lock_init(&l->lock);
768756
INIT_LIST_HEAD(&l->freeme);
769757
return l;
@@ -772,61 +760,27 @@ nfsd_alloc_fcache_disposal(struct net *net)
772760
static void
773761
nfsd_free_fcache_disposal(struct nfsd_fcache_disposal *l)
774762
{
775-
rcu_assign_pointer(l->net, NULL);
776763
cancel_work_sync(&l->work);
777764
nfsd_file_dispose_list(&l->freeme);
778-
kfree_rcu(l, rcu);
779-
}
780-
781-
static void
782-
nfsd_add_fcache_disposal(struct nfsd_fcache_disposal *l)
783-
{
784-
spin_lock(&laundrette_lock);
785-
list_add_tail_rcu(&l->list, &laundrettes);
786-
spin_unlock(&laundrette_lock);
787-
}
788-
789-
static void
790-
nfsd_del_fcache_disposal(struct nfsd_fcache_disposal *l)
791-
{
792-
spin_lock(&laundrette_lock);
793-
list_del_rcu(&l->list);
794-
spin_unlock(&laundrette_lock);
795-
}
796-
797-
static int
798-
nfsd_alloc_fcache_disposal_net(struct net *net)
799-
{
800-
struct nfsd_fcache_disposal *l;
801-
802-
l = nfsd_alloc_fcache_disposal(net);
803-
if (!l)
804-
return -ENOMEM;
805-
nfsd_add_fcache_disposal(l);
806-
return 0;
765+
kfree(l);
807766
}
808767

809768
static void
810769
nfsd_free_fcache_disposal_net(struct net *net)
811770
{
812-
struct nfsd_fcache_disposal *l;
771+
struct nfsd_net *nn = net_generic(net, nfsd_net_id);
772+
struct nfsd_fcache_disposal *l = nn->fcache_disposal;
813773

814-
rcu_read_lock();
815-
list_for_each_entry_rcu(l, &laundrettes, list) {
816-
if (l->net != net)
817-
continue;
818-
nfsd_del_fcache_disposal(l);
819-
rcu_read_unlock();
820-
nfsd_free_fcache_disposal(l);
821-
return;
822-
}
823-
rcu_read_unlock();
774+
nfsd_free_fcache_disposal(l);
824775
}
825776

826777
int
827778
nfsd_file_cache_start_net(struct net *net)
828779
{
829-
return nfsd_alloc_fcache_disposal_net(net);
780+
struct nfsd_net *nn = net_generic(net, nfsd_net_id);
781+
782+
nn->fcache_disposal = nfsd_alloc_fcache_disposal();
783+
return nn->fcache_disposal ? 0 : -ENOMEM;
830784
}
831785

832786
void

fs/nfsd/netns.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,8 @@ struct nfsd_net {
185185

186186
/* utsname taken from the process that starts the server */
187187
char nfsd_name[UNX_MAXNODENAME+1];
188+
189+
struct nfsd_fcache_disposal *fcache_disposal;
188190
};
189191

190192
/* Simple check to find out if a given net was properly initialized */

0 commit comments

Comments
 (0)