Btrfs: fix deadlock caused by the race between relocation
[firefly-linux-kernel-4.4.55.git] / fs / ncpfs / dir.c
index e3e646b06404dbce84b78d6c1d9df302d0e33dc1..9c51f621e90105bad9481ab83272f57850c5d104 100644 (file)
@@ -1033,8 +1033,11 @@ static int ncp_rmdir(struct inode *dir, struct dentry *dentry)
        DPRINTK("ncp_rmdir: removing %s/%s\n",
                dentry->d_parent->d_name.name, dentry->d_name.name);
 
+       /*
+        * fail with EBUSY if there are still references to this
+        * directory.
+        */
        dentry_unhash(dentry);
-
        error = -EBUSY;
        if (!d_unhashed(dentry))
                goto out;
@@ -1141,8 +1144,16 @@ static int ncp_rename(struct inode *old_dir, struct dentry *old_dentry,
                old_dentry->d_parent->d_name.name, old_dentry->d_name.name,
                new_dentry->d_parent->d_name.name, new_dentry->d_name.name);
 
-       if (new_dentry->d_inode && S_ISDIR(new_dentry->d_inode->i_mode))
+       if (new_dentry->d_inode && S_ISDIR(new_dentry->d_inode->i_mode)) {
+               /*
+                * fail with EBUSY if there are still references to this
+                * directory.
+                */
                dentry_unhash(new_dentry);
+               error = -EBUSY;
+               if (!d_unhashed(new_dentry))
+                       goto out;
+       }
 
        ncp_age_dentry(server, old_dentry);
        ncp_age_dentry(server, new_dentry);