ocfs2: convert to idr_alloc()
[firefly-linux-kernel-4.4.55.git] / fs / dcache.c
index 19153a0a810c1d12de751d5d416a5c1b6fe8c9bb..68220dd0c135f0702ef3eb3b40012f3aa930b057 100644 (file)
@@ -1358,6 +1358,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 +1369,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)
@@ -1672,7 +1675,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 +1683,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 +1729,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 +1893,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 +1923,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 +2001,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 +2012,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 +2396,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 +2404,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 +2715,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 +2997,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);