Merge tag 'microblaze-3.17-rc2' of git://git.monstr.eu/linux-2.6-microblaze
[pandora-kernel.git] / fs / dcache.c
index 63d556c..d30ce69 100644 (file)
@@ -731,8 +731,6 @@ EXPORT_SYMBOL(dget_parent);
 /**
  * d_find_alias - grab a hashed alias of inode
  * @inode: inode in question
- * @want_discon:  flag, used by d_splice_alias, to request
- *          that only a DISCONNECTED alias be returned.
  *
  * If inode has a hashed alias, or is a directory and has any alias,
  * acquire the reference to alias and return it. Otherwise return NULL.
@@ -741,10 +739,9 @@ EXPORT_SYMBOL(dget_parent);
  * of a filesystem.
  *
  * If the inode has an IS_ROOT, DCACHE_DISCONNECTED alias, then prefer
- * any other hashed alias over that one unless @want_discon is set,
- * in which case only return an IS_ROOT, DCACHE_DISCONNECTED alias.
+ * any other hashed alias over that one.
  */
-static struct dentry *__d_find_alias(struct inode *inode, int want_discon)
+static struct dentry *__d_find_alias(struct inode *inode)
 {
        struct dentry *alias, *discon_alias;
 
@@ -756,7 +753,7 @@ again:
                        if (IS_ROOT(alias) &&
                            (alias->d_flags & DCACHE_DISCONNECTED)) {
                                discon_alias = alias;
-                       } else if (!want_discon) {
+                       } else {
                                __dget_dlock(alias);
                                spin_unlock(&alias->d_lock);
                                return alias;
@@ -768,12 +765,9 @@ again:
                alias = discon_alias;
                spin_lock(&alias->d_lock);
                if (S_ISDIR(inode->i_mode) || !d_unhashed(alias)) {
-                       if (IS_ROOT(alias) &&
-                           (alias->d_flags & DCACHE_DISCONNECTED)) {
-                               __dget_dlock(alias);
-                               spin_unlock(&alias->d_lock);
-                               return alias;
-                       }
+                       __dget_dlock(alias);
+                       spin_unlock(&alias->d_lock);
+                       return alias;
                }
                spin_unlock(&alias->d_lock);
                goto again;
@@ -787,7 +781,7 @@ struct dentry *d_find_alias(struct inode *inode)
 
        if (!hlist_empty(&inode->i_dentry)) {
                spin_lock(&inode->i_lock);
-               de = __d_find_alias(inode, 0);
+               de = __d_find_alias(inode);
                spin_unlock(&inode->i_lock);
        }
        return de;
@@ -1781,7 +1775,7 @@ struct dentry *d_find_any_alias(struct inode *inode)
 }
 EXPORT_SYMBOL(d_find_any_alias);
 
-struct dentry *__d_obtain_alias(struct inode *inode, int disconnected)
+static struct dentry *__d_obtain_alias(struct inode *inode, int disconnected)
 {
        static const struct qstr anonstring = QSTR_INIT("/", 1);
        struct dentry *tmp;
@@ -2712,6 +2706,11 @@ struct dentry *d_splice_alias(struct inode *inode, struct dentry *dentry)
                                dput(new);
                                return ERR_PTR(-EIO);
                        }
+                       if (d_ancestor(new, dentry)) {
+                               spin_unlock(&inode->i_lock);
+                               dput(new);
+                               return ERR_PTR(-EIO);
+                       }
                        write_seqlock(&rename_lock);
                        __d_materialise_dentry(dentry, new);
                        write_sequnlock(&rename_lock);
@@ -2765,7 +2764,7 @@ struct dentry *d_materialise_unique(struct dentry *dentry, struct inode *inode)
                struct dentry *alias;
 
                /* Does an aliased dentry already exist? */
-               alias = __d_find_alias(inode, 0);
+               alias = __d_find_alias(inode);
                if (alias) {
                        actual = alias;
                        write_seqlock(&rename_lock);