summaryrefslogtreecommitdiff
path: root/fs/kernfs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/kernfs')
-rw-r--r--fs/kernfs/dir.c37
1 files changed, 13 insertions, 24 deletions
diff --git a/fs/kernfs/dir.c b/fs/kernfs/dir.c
index d33af95321fb..42c5b9f23b41 100644
--- a/fs/kernfs/dir.c
+++ b/fs/kernfs/dir.c
@@ -264,12 +264,6 @@ void kernfs_put(struct kernfs_node *kn)
}
EXPORT_SYMBOL_GPL(kernfs_put);
-static int kernfs_dop_delete(const struct dentry *dentry)
-{
- struct kernfs_node *kn = dentry->d_fsdata;
- return !(kn && !(kn->flags & KERNFS_REMOVED));
-}
-
static int kernfs_dop_revalidate(struct dentry *dentry, unsigned int flags)
{
struct kernfs_node *kn;
@@ -277,6 +271,10 @@ static int kernfs_dop_revalidate(struct dentry *dentry, unsigned int flags)
if (flags & LOOKUP_RCU)
return -ECHILD;
+ /* Always perform fresh lookup for negatives */
+ if (!dentry->d_inode)
+ goto out_bad_unlocked;
+
kn = dentry->d_fsdata;
mutex_lock(&kernfs_mutex);
@@ -301,22 +299,14 @@ static int kernfs_dop_revalidate(struct dentry *dentry, unsigned int flags)
out_valid:
return 1;
out_bad:
- /*
- * Remove the dentry from the dcache hashes.
- * If this is a deleted dentry we use d_drop instead of d_delete
- * so kernfs doesn't need to cope with negative dentries.
- *
- * If this is a dentry that has simply been renamed we
- * use d_drop to remove it from the dcache lookup on its
- * old parent. If this dentry persists later when a lookup
- * is performed at its new name the dentry will be readded
- * to the dcache hashes.
- */
mutex_unlock(&kernfs_mutex);
-
- /* If we have submounts we must allow the vfs caches
- * to lie about the state of the filesystem to prevent
- * leaks and other nasty things.
+out_bad_unlocked:
+ /*
+ * @dentry doesn't match the underlying kernfs node, drop the
+ * dentry and force lookup. If we have submounts we must allow the
+ * vfs caches to lie about the state of the filesystem to prevent
+ * leaks and other nasty things, so use check_submounts_and_drop()
+ * instead of d_drop().
*/
if (check_submounts_and_drop(dentry) != 0)
goto out_valid;
@@ -331,7 +321,6 @@ static void kernfs_dop_release(struct dentry *dentry)
const struct dentry_operations kernfs_dops = {
.d_revalidate = kernfs_dop_revalidate,
- .d_delete = kernfs_dop_delete,
.d_release = kernfs_dop_release,
};
@@ -682,7 +671,7 @@ static struct dentry *kernfs_iop_lookup(struct inode *dir,
struct dentry *dentry,
unsigned int flags)
{
- struct dentry *ret = NULL;
+ struct dentry *ret;
struct kernfs_node *parent = dentry->d_parent->d_fsdata;
struct kernfs_node *kn;
struct inode *inode;
@@ -697,7 +686,7 @@ static struct dentry *kernfs_iop_lookup(struct inode *dir,
/* no such entry */
if (!kn) {
- ret = ERR_PTR(-ENOENT);
+ ret = NULL;
goto out_unlock;
}
kernfs_get(kn);