Kirill Korotaev <dev@xxxxx> wrote:below
This patch fixes dcache race between shrink_dcache_XXX functions
and dput().
Example race scenario:
CPU 0 CPU 1
umount /dev/sda1
generic_shutdown_super shrink_dcache_memory()
shrink_dcache_parent dput dentry
select_parent prune_one_dentry()
<<<< child is dead, locks are released,
but parent is still referenced!!! >>>>
skip dentry->parent,
since it's d_count > 0
message: BUSY inodes after umount...
<<< parent is left on dentry_unused
list, referencing freed super block
We faced these messages about busy inodes constantly after some stress testing with mount/umount operations parrallel with some other activity.
This patch helped the problem.
The patch was heavilly tested on 2.6.8 during 2 months,
this forward-ported version boots and works ok as well.
You've provided no description of how the patch solves the problem.
/* dcache_lock protects shrinker's list */
static void shrink_dcache_racecheck(struct dentry *parent, int *racecheck)
{
struct super_block *sb;
struct dcache_shrinker *ds;
sb = parent->d_sb;
list_for_each_entry(ds, &sb->s_dshrinkers, list) {
/* is one of dcache shrinkers working on the dentry? */
if (ds->dentry == parent) {
*racecheck = 1;
break;
}
}
}
This all looks awfully hacky. Why is it done this way, and is there no
cleaner solution?