]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - fs/dcache.c
Merge tag 'scsi-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb...
[karo-tx-linux.git] / fs / dcache.c
index 19153a0a810c1d12de751d5d416a5c1b6fe8c9bb..fbfae008ba44e3e8223f42d4823cfeae2a673ac9 100644 (file)
@@ -675,11 +675,10 @@ EXPORT_SYMBOL(dget_parent);
 static struct dentry *__d_find_alias(struct inode *inode, int want_discon)
 {
        struct dentry *alias, *discon_alias;
-       struct hlist_node *p;
 
 again:
        discon_alias = NULL;
-       hlist_for_each_entry(alias, p, &inode->i_dentry, d_alias) {
+       hlist_for_each_entry(alias, &inode->i_dentry, d_alias) {
                spin_lock(&alias->d_lock);
                if (S_ISDIR(inode->i_mode) || !d_unhashed(alias)) {
                        if (IS_ROOT(alias) &&
@@ -730,10 +729,9 @@ EXPORT_SYMBOL(d_find_alias);
 void d_prune_aliases(struct inode *inode)
 {
        struct dentry *dentry;
-       struct hlist_node *p;
 restart:
        spin_lock(&inode->i_lock);
-       hlist_for_each_entry(dentry, p, &inode->i_dentry, d_alias) {
+       hlist_for_each_entry(dentry, &inode->i_dentry, d_alias) {
                spin_lock(&dentry->d_lock);
                if (!dentry->d_count) {
                        __dget_dlock(dentry);
@@ -1358,6 +1356,7 @@ void d_set_d_op(struct dentry *dentry, const struct dentry_operations *op)
        WARN_ON_ONCE(dentry->d_flags & (DCACHE_OP_HASH  |
                                DCACHE_OP_COMPARE       |
                                DCACHE_OP_REVALIDATE    |
+                               DCACHE_OP_WEAK_REVALIDATE       |
                                DCACHE_OP_DELETE ));
        dentry->d_op = op;
        if (!op)
@@ -1368,6 +1367,8 @@ void d_set_d_op(struct dentry *dentry, const struct dentry_operations *op)
                dentry->d_flags |= DCACHE_OP_COMPARE;
        if (op->d_revalidate)
                dentry->d_flags |= DCACHE_OP_REVALIDATE;
+       if (op->d_weak_revalidate)
+               dentry->d_flags |= DCACHE_OP_WEAK_REVALIDATE;
        if (op->d_delete)
                dentry->d_flags |= DCACHE_OP_DELETE;
        if (op->d_prune)
@@ -1440,14 +1441,13 @@ static struct dentry *__d_instantiate_unique(struct dentry *entry,
        int len = entry->d_name.len;
        const char *name = entry->d_name.name;
        unsigned int hash = entry->d_name.hash;
-       struct hlist_node *p;
 
        if (!inode) {
                __d_instantiate(entry, NULL);
                return NULL;
        }
 
-       hlist_for_each_entry(alias, p, &inode->i_dentry, d_alias) {
+       hlist_for_each_entry(alias, &inode->i_dentry, d_alias) {
                /*
                 * Don't need alias->d_lock here, because aliases with
                 * d_parent == entry->d_parent are not subject to name or
@@ -1672,7 +1672,6 @@ EXPORT_SYMBOL(d_splice_alias);
 struct dentry *d_add_ci(struct dentry *dentry, struct inode *inode,
                        struct qstr *name)
 {
-       int error;
        struct dentry *found;
        struct dentry *new;
 
@@ -1681,10 +1680,12 @@ struct dentry *d_add_ci(struct dentry *dentry, struct inode *inode,
         * if not go ahead and create it now.
         */
        found = d_hash_and_lookup(dentry->d_parent, name);
+       if (unlikely(IS_ERR(found)))
+               goto err_out;
        if (!found) {
                new = d_alloc(dentry->d_parent, name);
                if (!new) {
-                       error = -ENOMEM;
+                       found = ERR_PTR(-ENOMEM);
                        goto err_out;
                }
 
@@ -1725,7 +1726,7 @@ struct dentry *d_add_ci(struct dentry *dentry, struct inode *inode,
 
 err_out:
        iput(inode);
-       return ERR_PTR(error);
+       return found;
 }
 EXPORT_SYMBOL(d_add_ci);
 
@@ -1889,7 +1890,7 @@ seqretry:
  * dentry is returned. The caller must use dput to free the entry when it has
  * finished using it. %NULL is returned if the dentry does not exist.
  */
-struct dentry *d_lookup(struct dentry *parent, struct qstr *name)
+struct dentry *d_lookup(const struct dentry *parent, const struct qstr *name)
 {
        struct dentry *dentry;
        unsigned seq;
@@ -1919,7 +1920,7 @@ EXPORT_SYMBOL(d_lookup);
  *
  * __d_lookup callers must be commented.
  */
-struct dentry *__d_lookup(struct dentry *parent, struct qstr *name)
+struct dentry *__d_lookup(const struct dentry *parent, const struct qstr *name)
 {
        unsigned int len = name->len;
        unsigned int hash = name->hash;
@@ -1997,12 +1998,10 @@ next:
  * @dir: Directory to search in
  * @name: qstr of name we wish to find
  *
- * On hash failure or on lookup failure NULL is returned.
+ * On lookup failure NULL is returned; on bad name - ERR_PTR(-error)
  */
 struct dentry *d_hash_and_lookup(struct dentry *dir, struct qstr *name)
 {
-       struct dentry *dentry = NULL;
-
        /*
         * Check for a fs-specific hash function. Note that we must
         * calculate the standard hash first, as the d_op->d_hash()
@@ -2010,13 +2009,13 @@ struct dentry *d_hash_and_lookup(struct dentry *dir, struct qstr *name)
         */
        name->hash = full_name_hash(name->name, name->len);
        if (dir->d_flags & DCACHE_OP_HASH) {
-               if (dir->d_op->d_hash(dir, dir->d_inode, name) < 0)
-                       goto out;
+               int err = dir->d_op->d_hash(dir, dir->d_inode, name);
+               if (unlikely(err < 0))
+                       return ERR_PTR(err);
        }
-       dentry = d_lookup(dir, name);
-out:
-       return dentry;
+       return d_lookup(dir, name);
 }
+EXPORT_SYMBOL(d_hash_and_lookup);
 
 /**
  * d_validate - verify dentry provided from insecure source (deprecated)
@@ -2394,7 +2393,7 @@ out_err:
  */
 static void __d_materialise_dentry(struct dentry *dentry, struct dentry *anon)
 {
-       struct dentry *dparent, *aparent;
+       struct dentry *dparent;
 
        dentry_lock_for_move(anon, dentry);
 
@@ -2402,24 +2401,15 @@ static void __d_materialise_dentry(struct dentry *dentry, struct dentry *anon)
        write_seqcount_begin(&anon->d_seq);
 
        dparent = dentry->d_parent;
-       aparent = anon->d_parent;
 
        switch_names(dentry, anon);
        swap(dentry->d_name.hash, anon->d_name.hash);
 
-       dentry->d_parent = (aparent == anon) ? dentry : aparent;
-       list_del(&dentry->d_u.d_child);
-       if (!IS_ROOT(dentry))
-               list_add(&dentry->d_u.d_child, &dentry->d_parent->d_subdirs);
-       else
-               INIT_LIST_HEAD(&dentry->d_u.d_child);
-
-       anon->d_parent = (dparent == dentry) ? anon : dparent;
+       dentry->d_parent = dentry;
+       list_del_init(&dentry->d_u.d_child);
+       anon->d_parent = dparent;
        list_del(&anon->d_u.d_child);
-       if (!IS_ROOT(anon))
-               list_add(&anon->d_u.d_child, &anon->d_parent->d_subdirs);
-       else
-               INIT_LIST_HEAD(&anon->d_u.d_child);
+       list_add(&anon->d_u.d_child, &dparent->d_subdirs);
 
        write_seqcount_end(&dentry->d_seq);
        write_seqcount_end(&anon->d_seq);
@@ -2722,37 +2712,6 @@ char *d_path(const struct path *path, char *buf, int buflen)
 }
 EXPORT_SYMBOL(d_path);
 
-/**
- * d_path_with_unreachable - return the path of a dentry
- * @path: path to report
- * @buf: buffer to return value in
- * @buflen: buffer length
- *
- * The difference from d_path() is that this prepends "(unreachable)"
- * to paths which are unreachable from the current process' root.
- */
-char *d_path_with_unreachable(const struct path *path, char *buf, int buflen)
-{
-       char *res = buf + buflen;
-       struct path root;
-       int error;
-
-       if (path->dentry->d_op && path->dentry->d_op->d_dname)
-               return path->dentry->d_op->d_dname(path->dentry, buf, buflen);
-
-       get_fs_root(current->fs, &root);
-       write_seqlock(&rename_lock);
-       error = path_with_deleted(path, &root, &res, &buflen);
-       if (error > 0)
-               error = prepend_unreachable(&res, &buflen);
-       write_sequnlock(&rename_lock);
-       path_put(&root);
-       if (error)
-               res =  ERR_PTR(error);
-
-       return res;
-}
-
 /*
  * Helper function for dentry_operations.d_dname() members
  */
@@ -3035,7 +2994,7 @@ ino_t find_inode_number(struct dentry *dir, struct qstr *name)
        ino_t ino = 0;
 
        dentry = d_hash_and_lookup(dir, name);
-       if (dentry) {
+       if (!IS_ERR_OR_NULL(dentry)) {
                if (dentry->d_inode)
                        ino = dentry->d_inode->i_ino;
                dput(dentry);