d_delete(): get rid of trylock loop
authorAl Viro <viro@zeniv.linux.org.uk>
Sat, 24 Feb 2018 02:02:31 +0000 (21:02 -0500)
committerAl Viro <viro@zeniv.linux.org.uk>
Mon, 12 Mar 2018 15:59:14 +0000 (11:59 -0400)
just grab ->i_lock first; we have a positive dentry, nothing's going
to happen to inode

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

index 01c0432ec83a26f333000b227aa110430f57998b..1684b6b262de4a15bd490491f4d8c9eaa94833ed 100644 (file)
@@ -2377,32 +2377,22 @@ EXPORT_SYMBOL(d_hash_and_lookup);
  
 void d_delete(struct dentry * dentry)
 {
-       struct inode *inode;
-       int isdir = 0;
+       struct inode *inode = dentry->d_inode;
+       int isdir = d_is_dir(dentry);
+
+       spin_lock(&inode->i_lock);
+       spin_lock(&dentry->d_lock);
        /*
         * Are we the only user?
         */
-again:
-       spin_lock(&dentry->d_lock);
-       inode = dentry->d_inode;
-       isdir = S_ISDIR(inode->i_mode);
        if (dentry->d_lockref.count == 1) {
-               if (!spin_trylock(&inode->i_lock)) {
-                       spin_unlock(&dentry->d_lock);
-                       cpu_relax();
-                       goto again;
-               }
                dentry->d_flags &= ~DCACHE_CANT_MOUNT;
                dentry_unlink_inode(dentry);
-               fsnotify_nameremove(dentry, isdir);
-               return;
-       }
-
-       if (!d_unhashed(dentry))
+       } else {
                __d_drop(dentry);
-
-       spin_unlock(&dentry->d_lock);
-
+               spin_unlock(&dentry->d_lock);
+               spin_unlock(&inode->i_lock);
+       }
        fsnotify_nameremove(dentry, isdir);
 }
 EXPORT_SYMBOL(d_delete);