| From 1b19453d1c6abcfa7c312ba6c9f11a277568fc94 Mon Sep 17 00:00:00 2001 |
| From: Jeff Layton <jlayton@primarydata.com> |
| Date: Thu, 5 Jun 2014 09:45:00 -0400 |
| Subject: nfsd: don't halt scanning the DRC LRU list when there's an |
| RC_INPROG entry |
| |
| From: Jeff Layton <jlayton@primarydata.com> |
| |
| commit 1b19453d1c6abcfa7c312ba6c9f11a277568fc94 upstream. |
| |
| Currently, the DRC cache pruner will stop scanning the list when it |
| hits an entry that is RC_INPROG. It's possible however for a call to |
| take a *very* long time. In that case, we don't want it to block other |
| entries from being pruned if they are expired or we need to trim the |
| cache to get back under the limit. |
| |
| Fix the DRC cache pruner to just ignore RC_INPROG entries. |
| |
| Signed-off-by: Jeff Layton <jlayton@primarydata.com> |
| Signed-off-by: J. Bruce Fields <bfields@redhat.com> |
| Cc: Joseph Salisbury <joseph.salisbury@canonical.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| fs/nfsd/nfscache.c | 17 ++++++++--------- |
| 1 file changed, 8 insertions(+), 9 deletions(-) |
| |
| --- a/fs/nfsd/nfscache.c |
| +++ b/fs/nfsd/nfscache.c |
| @@ -224,13 +224,6 @@ hash_refile(struct svc_cacherep *rp) |
| hlist_add_head(&rp->c_hash, cache_hash + hash_32(rp->c_xid, maskbits)); |
| } |
| |
| -static inline bool |
| -nfsd_cache_entry_expired(struct svc_cacherep *rp) |
| -{ |
| - return rp->c_state != RC_INPROG && |
| - time_after(jiffies, rp->c_timestamp + RC_EXPIRE); |
| -} |
| - |
| /* |
| * Walk the LRU list and prune off entries that are older than RC_EXPIRE. |
| * Also prune the oldest ones when the total exceeds the max number of entries. |
| @@ -242,8 +235,14 @@ prune_cache_entries(void) |
| long freed = 0; |
| |
| list_for_each_entry_safe(rp, tmp, &lru_head, c_lru) { |
| - if (!nfsd_cache_entry_expired(rp) && |
| - num_drc_entries <= max_drc_entries) |
| + /* |
| + * Don't free entries attached to calls that are still |
| + * in-progress, but do keep scanning the list. |
| + */ |
| + if (rp->c_state == RC_INPROG) |
| + continue; |
| + if (num_drc_entries <= max_drc_entries && |
| + time_before(jiffies, rp->c_timestamp + RC_EXPIRE)) |
| break; |
| nfsd_reply_cache_free_locked(rp); |
| freed++; |