Skip to content

Commit 471a930

Browse files
kinglongmeeJ. Bruce Fields
authored andcommitted
SUNRPC: Drop all entries from cache_detail when cache_purge()
User always free the cache_detail after sunrpc_destroy_cache_detail(), so, it must cleanup up entries that left in the cache_detail, otherwise, NULL reference may be caused when using the left entries. Also, NeriBrown suggests "write a stand-alone cache_purge()." v3, move the cache_fresh_unlocked() out of write lock, v2, a stand-alone cache_purge(), not only for sunrpc_destroy_cache_detail Signed-off-by: Kinglong Mee <kinglongmee@gmail.com> Reviewed-by: NeilBrown <neilb@suse.com> Signed-off-by: J. Bruce Fields <bfields@redhat.com>
1 parent 81fa327 commit 471a930

File tree

1 file changed

+26
-15
lines changed

1 file changed

+26
-15
lines changed

net/sunrpc/cache.c

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -362,11 +362,6 @@ void sunrpc_destroy_cache_detail(struct cache_detail *cd)
362362
cache_purge(cd);
363363
spin_lock(&cache_list_lock);
364364
write_lock(&cd->hash_lock);
365-
if (cd->entries) {
366-
write_unlock(&cd->hash_lock);
367-
spin_unlock(&cache_list_lock);
368-
goto out;
369-
}
370365
if (current_detail == cd)
371366
current_detail = NULL;
372367
list_del_init(&cd->others);
@@ -376,9 +371,6 @@ void sunrpc_destroy_cache_detail(struct cache_detail *cd)
376371
/* module must be being unloaded so its safe to kill the worker */
377372
cancel_delayed_work_sync(&cache_cleaner);
378373
}
379-
return;
380-
out:
381-
printk(KERN_ERR "RPC: failed to unregister %s cache\n", cd->name);
382374
}
383375
EXPORT_SYMBOL_GPL(sunrpc_destroy_cache_detail);
384376

@@ -497,13 +489,32 @@ EXPORT_SYMBOL_GPL(cache_flush);
497489

498490
void cache_purge(struct cache_detail *detail)
499491
{
500-
time_t now = seconds_since_boot();
501-
if (detail->flush_time >= now)
502-
now = detail->flush_time + 1;
503-
/* 'now' is the maximum value any 'last_refresh' can have */
504-
detail->flush_time = now;
505-
detail->nextcheck = seconds_since_boot();
506-
cache_flush();
492+
struct cache_head *ch = NULL;
493+
struct hlist_head *head = NULL;
494+
struct hlist_node *tmp = NULL;
495+
int i = 0;
496+
497+
write_lock(&detail->hash_lock);
498+
if (!detail->entries) {
499+
write_unlock(&detail->hash_lock);
500+
return;
501+
}
502+
503+
dprintk("RPC: %d entries in %s cache\n", detail->entries, detail->name);
504+
for (i = 0; i < detail->hash_size; i++) {
505+
head = &detail->hash_table[i];
506+
hlist_for_each_entry_safe(ch, tmp, head, cache_list) {
507+
hlist_del_init(&ch->cache_list);
508+
detail->entries--;
509+
510+
set_bit(CACHE_CLEANED, &ch->flags);
511+
write_unlock(&detail->hash_lock);
512+
cache_fresh_unlocked(ch, detail);
513+
cache_put(ch, detail);
514+
write_lock(&detail->hash_lock);
515+
}
516+
}
517+
write_unlock(&detail->hash_lock);
507518
}
508519
EXPORT_SYMBOL_GPL(cache_purge);
509520

0 commit comments

Comments
 (0)