Skip to content

Commit 9190cc0

Browse files
Paulo AlcantaraSteve French
authored andcommitted
smb: client: improve purging of cached referrals
Purge cached referrals that have a single target when reaching maximum of cache size as the client won't need them to failover. Otherwise remove oldest cache entry. Signed-off-by: Paulo Alcantara (Red Hat) <[email protected]> Signed-off-by: Steve French <[email protected]>
1 parent 242d23e commit 9190cc0

File tree

1 file changed

+15
-17
lines changed

1 file changed

+15
-17
lines changed

fs/smb/client/dfs_cache.c

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ static inline void free_tgts(struct cache_entry *ce)
126126

127127
static inline void flush_cache_ent(struct cache_entry *ce)
128128
{
129+
cifs_dbg(FYI, "%s: %s\n", __func__, ce->path);
129130
hlist_del_init(&ce->hlist);
130131
kfree(ce->path);
131132
free_tgts(ce);
@@ -441,34 +442,31 @@ static struct cache_entry *alloc_cache_entry(struct dfs_info3_param *refs, int n
441442
return ce;
442443
}
443444

444-
static void remove_oldest_entry_locked(void)
445+
/* Remove all referrals that have a single target or oldest entry */
446+
static void purge_cache(void)
445447
{
446448
int i;
447449
struct cache_entry *ce;
448-
struct cache_entry *to_del = NULL;
449-
450-
WARN_ON(!rwsem_is_locked(&htable_rw_lock));
450+
struct cache_entry *oldest = NULL;
451451

452452
for (i = 0; i < CACHE_HTABLE_SIZE; i++) {
453453
struct hlist_head *l = &cache_htable[i];
454+
struct hlist_node *n;
454455

455-
hlist_for_each_entry(ce, l, hlist) {
456+
hlist_for_each_entry_safe(ce, n, l, hlist) {
456457
if (hlist_unhashed(&ce->hlist))
457458
continue;
458-
if (!to_del || timespec64_compare(&ce->etime,
459-
&to_del->etime) < 0)
460-
to_del = ce;
459+
if (ce->numtgts == 1)
460+
flush_cache_ent(ce);
461+
else if (!oldest ||
462+
timespec64_compare(&ce->etime,
463+
&oldest->etime) < 0)
464+
oldest = ce;
461465
}
462466
}
463467

464-
if (!to_del) {
465-
cifs_dbg(FYI, "%s: no entry to remove\n", __func__);
466-
return;
467-
}
468-
469-
cifs_dbg(FYI, "%s: removing entry\n", __func__);
470-
dump_ce(to_del);
471-
flush_cache_ent(to_del);
468+
if (atomic_read(&cache_count) >= CACHE_MAX_ENTRIES && oldest)
469+
flush_cache_ent(oldest);
472470
}
473471

474472
/* Add a new DFS cache entry */
@@ -484,7 +482,7 @@ static struct cache_entry *add_cache_entry_locked(struct dfs_info3_param *refs,
484482

485483
if (atomic_read(&cache_count) >= CACHE_MAX_ENTRIES) {
486484
cifs_dbg(FYI, "%s: reached max cache size (%d)\n", __func__, CACHE_MAX_ENTRIES);
487-
remove_oldest_entry_locked();
485+
purge_cache();
488486
}
489487

490488
rc = cache_entry_hash(refs[0].path_name, strlen(refs[0].path_name), &hash);

0 commit comments

Comments
 (0)