Merge 4.14.34 into android-4.14
[GitHub/moto-9609/android_kernel_motorola_exynos9610.git] / fs / dcache.c
index a6e06761da4af44d124dd8caf2b6bea2ba9e5a07..801179170794863348cc0e9f0d582f73089d03e0 100644 (file)
@@ -468,9 +468,11 @@ static void dentry_lru_add(struct dentry *dentry)
  * d_drop() is used mainly for stuff that wants to invalidate a dentry for some
  * reason (NFS timeouts or autofs deletes).
  *
- * __d_drop requires dentry->d_lock.
+ * __d_drop requires dentry->d_lock
+ * ___d_drop doesn't mark dentry as "unhashed"
+ *   (dentry->d_hash.pprev will be LIST_POISON2, not NULL).
  */
-void __d_drop(struct dentry *dentry)
+static void ___d_drop(struct dentry *dentry)
 {
        if (!d_unhashed(dentry)) {
                struct hlist_bl_head *b;
@@ -486,12 +488,17 @@ void __d_drop(struct dentry *dentry)
 
                hlist_bl_lock(b);
                __hlist_bl_del(&dentry->d_hash);
-               dentry->d_hash.pprev = NULL;
                hlist_bl_unlock(b);
                /* After this call, in-progress rcu-walk path lookup will fail. */
                write_seqcount_invalidate(&dentry->d_seq);
        }
 }
+
+void __d_drop(struct dentry *dentry)
+{
+       ___d_drop(dentry);
+       dentry->d_hash.pprev = NULL;
+}
 EXPORT_SYMBOL(__d_drop);
 
 void d_drop(struct dentry *dentry)
@@ -2386,7 +2393,7 @@ EXPORT_SYMBOL(d_delete);
 static void __d_rehash(struct dentry *entry)
 {
        struct hlist_bl_head *b = d_hash(entry->d_name.hash);
-       BUG_ON(!d_unhashed(entry));
+
        hlist_bl_lock(b);
        hlist_bl_add_head_rcu(&entry->d_hash, b);
        hlist_bl_unlock(b);
@@ -2821,9 +2828,9 @@ static void __d_move(struct dentry *dentry, struct dentry *target,
        write_seqcount_begin_nested(&target->d_seq, DENTRY_D_LOCK_NESTED);
 
        /* unhash both */
-       /* __d_drop does write_seqcount_barrier, but they're OK to nest. */
-       __d_drop(dentry);
-       __d_drop(target);
+       /* ___d_drop does write_seqcount_barrier, but they're OK to nest. */
+       ___d_drop(dentry);
+       ___d_drop(target);
 
        /* Switch the names.. */
        if (exchange)
@@ -2835,6 +2842,8 @@ static void __d_move(struct dentry *dentry, struct dentry *target,
        __d_rehash(dentry);
        if (exchange)
                __d_rehash(target);
+       else
+               target->d_hash.pprev = NULL;
 
        /* ... and switch them in the tree */
        if (IS_ROOT(dentry)) {