take write_seqcount_invalidate() into __d_drop()
authorAl Viro <viro@zeniv.linux.org.uk>
Wed, 7 Mar 2018 05:49:10 +0000 (00:49 -0500)
committerAl Viro <viro@zeniv.linux.org.uk>
Mon, 12 Mar 2018 15:59:12 +0000 (11:59 -0400)
... and reorder it with making d_unhashed() true.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
fs/dcache.c

index 8945e6c..7897424 100644 (file)
@@ -470,30 +470,29 @@ static void dentry_lru_add(struct dentry *dentry)
  */
 static void ___d_drop(struct dentry *dentry)
 {
-       if (!d_unhashed(dentry)) {
-               struct hlist_bl_head *b;
-               /*
-                * Hashed dentries are normally on the dentry hashtable,
-                * with the exception of those newly allocated by
-                * d_obtain_root, which are always IS_ROOT:
-                */
-               if (unlikely(IS_ROOT(dentry)))
-                       b = &dentry->d_sb->s_roots;
-               else
-                       b = d_hash(dentry->d_name.hash);
+       struct hlist_bl_head *b;
+       /*
+        * Hashed dentries are normally on the dentry hashtable,
+        * with the exception of those newly allocated by
+        * d_obtain_root, which are always IS_ROOT:
+        */
+       if (unlikely(IS_ROOT(dentry)))
+               b = &dentry->d_sb->s_roots;
+       else
+               b = d_hash(dentry->d_name.hash);
 
-               hlist_bl_lock(b);
-               __hlist_bl_del(&dentry->d_hash);
-               hlist_bl_unlock(b);
-               /* After this call, in-progress rcu-walk path lookup will fail. */
-               write_seqcount_invalidate(&dentry->d_seq);
-       }
+       hlist_bl_lock(b);
+       __hlist_bl_del(&dentry->d_hash);
+       hlist_bl_unlock(b);
 }
 
 void __d_drop(struct dentry *dentry)
 {
-       ___d_drop(dentry);
-       dentry->d_hash.pprev = NULL;
+       if (!d_unhashed(dentry)) {
+               ___d_drop(dentry);
+               dentry->d_hash.pprev = NULL;
+               write_seqcount_invalidate(&dentry->d_seq);
+       }
 }
 EXPORT_SYMBOL(__d_drop);
 
@@ -2853,9 +2852,10 @@ 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);
+       if (!d_unhashed(dentry))
+               ___d_drop(dentry);
+       if (!d_unhashed(target))
+               ___d_drop(target);
 
        /* Switch the names.. */
        if (exchange)