Skip to content

Commit bafc9b7

Browse files
ebiedermAl Viro
authored andcommitted
vfs: More precise tests in d_invalidate
The current comments in d_invalidate about what and why it is doing what it is doing are wildly off-base. Which is not surprising as the comments date back to last minute bug fix of the 2.2 kernel. The big fat lie of a comment said: If it's a directory, we can't drop it for fear of somebody re-populating it with children (even though dropping it would make it unreachable from that root, we still might repopulate it if it was a working directory or similar). [AV] What we really need to avoid is multiple dentry aliases of the same directory inode; on all filesystems that have ->d_revalidate() we either declare all positive dentries always valid (and thus never fed to d_invalidate()) or use d_materialise_unique() and/or d_splice_alias(), which take care of alias prevention. The current rules are: - To prevent mount point leaks dentries that are mount points or that have childrent that are mount points may not be be unhashed. - All dentries may be unhashed. - Directories may be rehashed with d_materialise_unique check_submounts_and_drop implements this already for well maintained remote filesystems so implement the current rules in d_invalidate by just calling check_submounts_and_drop. The one difference between d_invalidate and check_submounts_and_drop is that d_invalidate must respect it when a d_revalidate method has earlier called d_drop so preserve the d_unhashed check in d_invalidate. Reviewed-by: Miklos Szeredi <[email protected]> Signed-off-by: "Eric W. Biederman" <[email protected]> Signed-off-by: Al Viro <[email protected]>
1 parent 3ccb354 commit bafc9b7

File tree

1 file changed

+4
-34
lines changed

1 file changed

+4
-34
lines changed

fs/dcache.c

Lines changed: 4 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -650,9 +650,8 @@ EXPORT_SYMBOL(dput);
650650
* @dentry: dentry to invalidate
651651
*
652652
* Try to invalidate the dentry if it turns out to be
653-
* possible. If there are other dentries that can be
654-
* reached through this one we can't delete it and we
655-
* return -EBUSY. On success we return 0.
653+
* possible. If there are reasons not to delete it
654+
* return -EBUSY. On success return 0.
656655
*
657656
* no dcache lock.
658657
*/
@@ -667,38 +666,9 @@ int d_invalidate(struct dentry * dentry)
667666
spin_unlock(&dentry->d_lock);
668667
return 0;
669668
}
670-
/*
671-
* Check whether to do a partial shrink_dcache
672-
* to get rid of unused child entries.
673-
*/
674-
if (!list_empty(&dentry->d_subdirs)) {
675-
spin_unlock(&dentry->d_lock);
676-
shrink_dcache_parent(dentry);
677-
spin_lock(&dentry->d_lock);
678-
}
679-
680-
/*
681-
* Somebody else still using it?
682-
*
683-
* If it's a directory, we can't drop it
684-
* for fear of somebody re-populating it
685-
* with children (even though dropping it
686-
* would make it unreachable from the root,
687-
* we might still populate it if it was a
688-
* working directory or similar).
689-
* We also need to leave mountpoints alone,
690-
* directory or not.
691-
*/
692-
if (dentry->d_lockref.count > 1 && dentry->d_inode) {
693-
if (S_ISDIR(dentry->d_inode->i_mode) || d_mountpoint(dentry)) {
694-
spin_unlock(&dentry->d_lock);
695-
return -EBUSY;
696-
}
697-
}
698-
699-
__d_drop(dentry);
700669
spin_unlock(&dentry->d_lock);
701-
return 0;
670+
671+
return check_submounts_and_drop(dentry);
702672
}
703673
EXPORT_SYMBOL(d_invalidate);
704674

0 commit comments

Comments
 (0)