+/**
+ * d_add_ci - lookup or allocate new dentry with case-exact name
+ * @inode: the inode case-insensitive lookup has found
+ * @dentry: the negative dentry that was passed to the parent's lookup func
+ * @name: the case-exact name to be associated with the returned dentry
+ *
+ * This is to avoid filling the dcache with case-insensitive names to the
+ * same inode, only the actual correct case is stored in the dcache for
+ * case-insensitive filesystems.
+ *
+ * For a case-insensitive lookup match and if the the case-exact dentry
+ * already exists in in the dcache, use it and return it.
+ *
+ * If no entry exists with the exact case name, allocate new dentry with
+ * the exact case, and return the spliced entry.
+ */
+struct dentry *d_add_ci(struct dentry *dentry, struct inode *inode,
+ struct qstr *name)
+{
+ int error;
+ struct dentry *found;
+ struct dentry *new;
+
+ /*
+ * First check if a dentry matching the name already exists,
+ * if not go ahead and create it now.
+ */
+ found = d_hash_and_lookup(dentry->d_parent, name);
+ if (!found) {
+ new = d_alloc(dentry->d_parent, name);
+ if (!new) {
+ error = -ENOMEM;
+ goto err_out;
+ }
+
+ found = d_splice_alias(inode, new);
+ if (found) {
+ dput(new);
+ return found;
+ }
+ return new;
+ }
+
+ /*
+ * If a matching dentry exists, and it's not negative use it.
+ *
+ * Decrement the reference count to balance the iget() done
+ * earlier on.
+ */
+ if (found->d_inode) {
+ if (unlikely(found->d_inode != inode)) {
+ /* This can't happen because bad inodes are unhashed. */
+ BUG_ON(!is_bad_inode(inode));
+ BUG_ON(!is_bad_inode(found->d_inode));
+ }
+ iput(inode);
+ return found;
+ }
+
+ /*
+ * Negative dentry: instantiate it unless the inode is a directory and
+ * already has a dentry.
+ */
+ spin_lock(&dcache_lock);
+ if (!S_ISDIR(inode->i_mode) || list_empty(&inode->i_dentry)) {
+ __d_instantiate(found, inode);
+ spin_unlock(&dcache_lock);
+ security_d_instantiate(found, inode);
+ return found;
+ }
+
+ /*
+ * In case a directory already has a (disconnected) entry grab a
+ * reference to it, move it in place and use it.
+ */
+ new = list_entry(inode->i_dentry.next, struct dentry, d_alias);
+ dget_locked(new);
+ spin_unlock(&dcache_lock);
+ security_d_instantiate(found, inode);
+ d_move(new, found);
+ iput(inode);
+ dput(found);
+ return new;
+
+err_out:
+ iput(inode);
+ return ERR_PTR(error);
+}