Make hash_64() use a 64-bit multiply when appropriate
[pandora-kernel.git] / fs / namei.c
index 9eb787e..a996bb4 100644 (file)
@@ -1091,10 +1091,10 @@ int follow_down_one(struct path *path)
 }
 EXPORT_SYMBOL(follow_down_one);
 
-static inline bool managed_dentry_might_block(struct dentry *dentry)
+static inline int managed_dentry_rcu(struct dentry *dentry)
 {
-       return (dentry->d_flags & DCACHE_MANAGE_TRANSIT &&
-               dentry->d_op->d_manage(dentry, true) < 0);
+       return (dentry->d_flags & DCACHE_MANAGE_TRANSIT) ?
+               dentry->d_op->d_manage(dentry, true) : 0;
 }
 
 /*
@@ -1110,11 +1110,18 @@ static bool __follow_mount_rcu(struct nameidata *nd, struct path *path,
                 * Don't forget we might have a non-mountpoint managed dentry
                 * that wants to block transit.
                 */
-               if (unlikely(managed_dentry_might_block(path->dentry)))
+               switch (managed_dentry_rcu(path->dentry)) {
+               case -ECHILD:
+               default:
                        return false;
+               case -EISDIR:
+                       return true;
+               case 0:
+                       break;
+               }
 
                if (!d_mountpoint(path->dentry))
-                       return true;
+                       return !(path->dentry->d_flags & DCACHE_NEED_AUTOMOUNT);
 
                mounted = __lookup_mnt(path->mnt, path->dentry);
                if (!mounted)
@@ -1130,7 +1137,8 @@ static bool __follow_mount_rcu(struct nameidata *nd, struct path *path,
                 */
                *inode = path->dentry->d_inode;
        }
-       return read_seqretry(&mount_lock, nd->m_seq);
+       return read_seqretry(&mount_lock, nd->m_seq) &&
+               !(path->dentry->d_flags & DCACHE_NEED_AUTOMOUNT);
 }
 
 static int follow_dotdot_rcu(struct nameidata *nd)
@@ -1402,11 +1410,8 @@ static int lookup_fast(struct nameidata *nd,
                }
                path->mnt = mnt;
                path->dentry = dentry;
-               if (unlikely(!__follow_mount_rcu(nd, path, inode)))
-                       goto unlazy;
-               if (unlikely(path->dentry->d_flags & DCACHE_NEED_AUTOMOUNT))
-                       goto unlazy;
-               return 0;
+               if (likely(__follow_mount_rcu(nd, path, inode)))
+                       return 0;
 unlazy:
                if (unlazy_walk(nd, dentry))
                        return -ECHILD;
@@ -4019,7 +4024,7 @@ SYSCALL_DEFINE2(link, const char __user *, oldname, const char __user *, newname
  * The worst of all namespace operations - renaming directory. "Perverted"
  * doesn't even start to describe it. Somebody in UCB had a heck of a trip...
  * Problems:
- *     a) we can get into loop creation. Check is done in is_subdir().
+ *     a) we can get into loop creation.
  *     b) race potential - two innocent renames can create a loop together.
  *        That's where 4.4 screws up. Current fix: serialization on
  *        sb->s_vfs_rename_mutex. We might be more accurate, but that's another
@@ -4075,7 +4080,7 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
        if (error)
                return error;
 
-       if (!old_dir->i_op->rename)
+       if (!old_dir->i_op->rename && !old_dir->i_op->rename2)
                return -EPERM;
 
        if (flags && !old_dir->i_op->rename2)
@@ -4134,10 +4139,11 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
                if (error)
                        goto out;
        }
-       if (!flags) {
+       if (!old_dir->i_op->rename2) {
                error = old_dir->i_op->rename(old_dir, old_dentry,
                                              new_dir, new_dentry);
        } else {
+               WARN_ON(old_dir->i_op->rename != NULL);
                error = old_dir->i_op->rename2(old_dir, old_dentry,
                                               new_dir, new_dentry, flags);
        }