|
@@ -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);
|