On Tue, 13 Aug 2013, Yan, Zheng wrote: > From: "Yan, Zheng" <zheng.z.yan@xxxxxxxxx> > > The d_prune dentry operation is used to notify filesystem when VFS > about to prune a hashed dentry from the dcache. There are three > code paths that prune dentries: shrink_dcache_for_umount_subtree(), > prune_dcache_sb() and d_prune_aliases(). For the d_prune_aliases() > case, VFS unhashes the dentry first, then call the d_prune dentry > operation. This confuses ceph_d_prune() (ceph uses the d_prune > dentry operation to maintain a flag indicating whether the complete > contents of a directory are in the dcache, pruning unhashed dentry > does not affect dir's completeness) > > This patch fixes the issue by calling the d_prune dentry operation > in d_prune_aliases(), before unhashing the dentry. Also make VFS > only call the d_prune dentry operation for hashed dentry, to avoid > calling the d_prune dentry operation twice when dentry is pruned > by d_prune_aliases(). > > Signed-off-by: Yan, Zheng <zheng.z.yan@xxxxxxxxx> Reviewed-by: Sage Weil <sage@xxxxxxxxxxx> This is behaving well under my testing, seems to resolve the race we were encoutering before, and cleans up the d_prune semantics nicely IMO. Al, does this look okay to you? Thanks! sage > --- > fs/dcache.c | 13 +++++++++++-- > 1 file changed, 11 insertions(+), 2 deletions(-) > > diff --git a/fs/dcache.c b/fs/dcache.c > index 87bdb53..612e99b 100644 > --- a/fs/dcache.c > +++ b/fs/dcache.c > @@ -472,7 +472,7 @@ relock: > * inform the fs via d_prune that this dentry is about to be > * unhashed and destroyed. > */ > - if (dentry->d_flags & DCACHE_OP_PRUNE) > + if ((dentry->d_flags & DCACHE_OP_PRUNE) && !d_unhashed(dentry)) > dentry->d_op->d_prune(dentry); > > dentry_lru_del(dentry); > @@ -719,6 +719,14 @@ restart: > hlist_for_each_entry(dentry, &inode->i_dentry, d_alias) { > spin_lock(&dentry->d_lock); > if (!dentry->d_count) { > + /* > + * inform the fs via d_prune that this dentry > + * is about to be unhashed and destroyed. > + */ > + if ((dentry->d_flags & DCACHE_OP_PRUNE) && > + !d_unhashed(dentry)) > + dentry->d_op->d_prune(dentry); > + > __dget_dlock(dentry); > __d_drop(dentry); > spin_unlock(&dentry->d_lock); > @@ -907,7 +915,8 @@ static void shrink_dcache_for_umount_subtree(struct dentry *dentry) > * inform the fs that this dentry is about to be > * unhashed and destroyed. > */ > - if (dentry->d_flags & DCACHE_OP_PRUNE) > + if ((dentry->d_flags & DCACHE_OP_PRUNE) && > + !d_unhashed(dentry)) > dentry->d_op->d_prune(dentry); > > dentry_lru_del(dentry); > -- > 1.8.1.4 > > -- > To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in > the body of a message to majordomo@xxxxxxxxxxxxxxx > More majordomo info at http://vger.kernel.org/majordomo-info.html > > -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html