Merge branch 'drm-next' of git://people.freedesktop.org/~airlied/linux
[cascardo/linux.git] / fs / cifs / readdir.c
index b30a4a6..65cf85d 100644 (file)
@@ -78,20 +78,34 @@ cifs_prime_dcache(struct dentry *parent, struct qstr *name,
 {
        struct dentry *dentry, *alias;
        struct inode *inode;
-       struct super_block *sb = d_inode(parent)->i_sb;
+       struct super_block *sb = parent->d_sb;
        struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
+       DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq);
 
        cifs_dbg(FYI, "%s: for %s\n", __func__, name->name);
 
        dentry = d_hash_and_lookup(parent, name);
+       if (!dentry) {
+               /*
+                * If we know that the inode will need to be revalidated
+                * immediately, then don't create a new dentry for it.
+                * We'll end up doing an on the wire call either way and
+                * this spares us an invalidation.
+                */
+               if (fattr->cf_flags & CIFS_FATTR_NEED_REVAL)
+                       return;
+retry:
+               dentry = d_alloc_parallel(parent, name, &wq);
+       }
        if (IS_ERR(dentry))
                return;
-
-       if (dentry) {
+       if (!d_in_lookup(dentry)) {
                inode = d_inode(dentry);
                if (inode) {
-                       if (d_mountpoint(dentry))
-                               goto out;
+                       if (d_mountpoint(dentry)) {
+                               dput(dentry);
+                               return;
+                       }
                        /*
                         * If we're generating inode numbers, then we don't
                         * want to clobber the existing one with the one that
@@ -106,33 +120,22 @@ cifs_prime_dcache(struct dentry *parent, struct qstr *name,
                            (inode->i_mode & S_IFMT) ==
                            (fattr->cf_mode & S_IFMT)) {
                                cifs_fattr_to_inode(inode, fattr);
-                               goto out;
+                               dput(dentry);
+                               return;
                        }
                }
                d_invalidate(dentry);
                dput(dentry);
+               goto retry;
+       } else {
+               inode = cifs_iget(sb, fattr);
+               if (!inode)
+                       inode = ERR_PTR(-ENOMEM);
+               alias = d_splice_alias(inode, dentry);
+               d_lookup_done(dentry);
+               if (alias && !IS_ERR(alias))
+                       dput(alias);
        }
-
-       /*
-        * If we know that the inode will need to be revalidated immediately,
-        * then don't create a new dentry for it. We'll end up doing an on
-        * the wire call either way and this spares us an invalidation.
-        */
-       if (fattr->cf_flags & CIFS_FATTR_NEED_REVAL)
-               return;
-
-       dentry = d_alloc(parent, name);
-       if (!dentry)
-               return;
-
-       inode = cifs_iget(sb, fattr);
-       if (!inode)
-               goto out;
-
-       alias = d_splice_alias(inode, dentry);
-       if (alias && !IS_ERR(alias))
-               dput(alias);
-out:
        dput(dentry);
 }
 
@@ -300,7 +303,7 @@ initiate_cifs_search(const unsigned int xid, struct file *file)
        cifsFile->invalidHandle = true;
        cifsFile->srch_inf.endOfSearch = false;
 
-       full_path = build_path_from_dentry(file->f_path.dentry);
+       full_path = build_path_from_dentry(file_dentry(file));
        if (full_path == NULL) {
                rc = -ENOMEM;
                goto error_exit;
@@ -759,7 +762,7 @@ static int cifs_filldir(char *find_entry, struct file *file,
                 */
                fattr.cf_flags |= CIFS_FATTR_NEED_REVAL;
 
-       cifs_prime_dcache(file->f_path.dentry, &name, &fattr);
+       cifs_prime_dcache(file_dentry(file), &name, &fattr);
 
        ino = cifs_uniqueid_to_ino_t(fattr.cf_uniqueid);
        return !dir_emit(ctx, name.name, name.len, ino, fattr.cf_dtype);