Skip to content

Commit 56221b4

Browse files
neilbrownchucklever
authored andcommitted
nfsd: filecache: don't repeatedly add/remove files on the lru list
There is no need to remove a file from the lru every time we access it, and then add it back. It is sufficient to set the REFERENCED flag every time we put the file. The order in the lru of REFERENCED files is largely irrelevant as they will all be moved to the end. With this patch, files are added only when they are allocated (if want_gc) and they are removed only by the list_lru_(shrink_)walk callback or when forcibly removing a file. This should reduce contention on the list_lru spinlock(s) and reduce memory traffic a little. Signed-off-by: NeilBrown <neilb@suse.de> Reviewed-by: Jeff Layton <jlayton@kernel.org> Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
1 parent 6491212 commit 56221b4

File tree

1 file changed

+17
-30
lines changed

1 file changed

+17
-30
lines changed

fs/nfsd/filecache.c

Lines changed: 17 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -319,15 +319,14 @@ nfsd_file_check_writeback(struct nfsd_file *nf)
319319
mapping_tagged(mapping, PAGECACHE_TAG_WRITEBACK);
320320
}
321321

322-
static bool nfsd_file_lru_add(struct nfsd_file *nf)
322+
static void nfsd_file_lru_add(struct nfsd_file *nf)
323323
{
324-
set_bit(NFSD_FILE_REFERENCED, &nf->nf_flags);
325-
set_bit(NFSD_FILE_RECENT, &nf->nf_flags);
326-
if (list_lru_add_obj(&nfsd_file_lru, &nf->nf_lru)) {
324+
refcount_inc(&nf->nf_ref);
325+
if (list_lru_add_obj(&nfsd_file_lru, &nf->nf_lru))
327326
trace_nfsd_file_lru_add(nf);
328-
return true;
329-
}
330-
return false;
327+
else
328+
WARN_ON(1);
329+
nfsd_file_schedule_laundrette();
331330
}
332331

333332
static bool nfsd_file_lru_remove(struct nfsd_file *nf)
@@ -363,16 +362,10 @@ nfsd_file_put(struct nfsd_file *nf)
363362

364363
if (test_bit(NFSD_FILE_GC, &nf->nf_flags) &&
365364
test_bit(NFSD_FILE_HASHED, &nf->nf_flags)) {
366-
/*
367-
* If this is the last reference (nf_ref == 1), then try to
368-
* transfer it to the LRU.
369-
*/
370-
if (refcount_dec_not_one(&nf->nf_ref))
371-
return;
372-
373-
if (nfsd_file_lru_add(nf))
374-
return;
365+
set_bit(NFSD_FILE_REFERENCED, &nf->nf_flags);
366+
set_bit(NFSD_FILE_RECENT, &nf->nf_flags);
375367
}
368+
376369
if (refcount_dec_and_test(&nf->nf_ref))
377370
nfsd_file_free(nf);
378371
}
@@ -516,13 +509,12 @@ nfsd_file_lru_cb(struct list_head *item, struct list_lru_one *lru,
516509
}
517510

518511
/*
519-
* Put the reference held on behalf of the LRU. If it wasn't the last
520-
* one, then just remove it from the LRU and ignore it.
512+
* Put the reference held on behalf of the LRU if it is the last
513+
* reference, else rotate.
521514
*/
522-
if (!refcount_dec_and_test(&nf->nf_ref)) {
515+
if (!refcount_dec_if_one(&nf->nf_ref)) {
523516
trace_nfsd_file_gc_in_use(nf);
524-
list_lru_isolate(lru, &nf->nf_lru);
525-
return LRU_REMOVED;
517+
return LRU_ROTATE;
526518
}
527519

528520
/* Refcount went to zero. Unhash it and queue it to the dispose list */
@@ -1062,16 +1054,8 @@ nfsd_file_do_acquire(struct svc_rqst *rqstp, struct net *net,
10621054
nf = nfsd_file_lookup_locked(net, current_cred(), inode, need, want_gc);
10631055
rcu_read_unlock();
10641056

1065-
if (nf) {
1066-
/*
1067-
* If the nf is on the LRU then it holds an extra reference
1068-
* that must be put if it's removed. It had better not be
1069-
* the last one however, since we should hold another.
1070-
*/
1071-
if (nfsd_file_lru_remove(nf))
1072-
refcount_dec(&nf->nf_ref);
1057+
if (nf)
10731058
goto wait_for_construction;
1074-
}
10751059

10761060
new = nfsd_file_alloc(net, inode, need, want_gc);
10771061
if (!new) {
@@ -1165,6 +1149,9 @@ nfsd_file_do_acquire(struct svc_rqst *rqstp, struct net *net,
11651149
*/
11661150
if (status != nfs_ok || inode->i_nlink == 0)
11671151
nfsd_file_unhash(nf);
1152+
else if (want_gc)
1153+
nfsd_file_lru_add(nf);
1154+
11681155
clear_and_wake_up_bit(NFSD_FILE_PENDING, &nf->nf_flags);
11691156
if (status == nfs_ok)
11701157
goto out;

0 commit comments

Comments
 (0)