+ struct dentry *dentry = file->f_path.dentry;
+ struct vfsmount *mnt = file->f_path.mnt;
+ struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
+ struct dentry *cursor;
+ int status;
+
+ status = dcache_dir_open(inode, file);
+ if (status)
+ goto out;
+
+ cursor = file->private_data;
+ cursor->d_fsdata = NULL;
+
+ DPRINTK("file=%p dentry=%p %.*s",
+ file, dentry, dentry->d_name.len, dentry->d_name.name);
+
+ if (autofs4_oz_mode(sbi))
+ goto out;
+
+ if (autofs4_ispending(dentry)) {
+ DPRINTK("dentry busy");
+ dcache_dir_close(inode, file);
+ status = -EBUSY;
+ goto out;
+ }
+
+ status = -ENOENT;
+ if (!d_mountpoint(dentry) && dentry->d_op && dentry->d_op->d_revalidate) {
+ struct nameidata nd;
+ int empty, ret;
+
+ /* In case there are stale directory dentrys from a failed mount */
+ spin_lock(&dcache_lock);
+ empty = list_empty(&dentry->d_subdirs);
+ spin_unlock(&dcache_lock);
+
+ if (!empty)
+ d_invalidate(dentry);
+
+ nd.flags = LOOKUP_DIRECTORY;
+ ret = (dentry->d_op->d_revalidate)(dentry, &nd);
+
+ if (ret <= 0) {
+ if (ret < 0)
+ status = ret;
+ dcache_dir_close(inode, file);
+ goto out;
+ }
+ }
+
+ if (d_mountpoint(dentry)) {
+ struct file *fp = NULL;
+ struct vfsmount *fp_mnt = mntget(mnt);
+ struct dentry *fp_dentry = dget(dentry);
+
+ if (!autofs4_follow_mount(&fp_mnt, &fp_dentry)) {
+ dput(fp_dentry);
+ mntput(fp_mnt);
+ dcache_dir_close(inode, file);
+ goto out;
+ }
+
+ fp = dentry_open(fp_dentry, fp_mnt, file->f_flags);
+ status = PTR_ERR(fp);
+ if (IS_ERR(fp)) {
+ dcache_dir_close(inode, file);
+ goto out;
+ }
+ cursor->d_fsdata = fp;
+ }
+ return 0;
+out:
+ return status;
+}
+
+static int autofs4_dir_close(struct inode *inode, struct file *file)
+{
+ struct dentry *dentry = file->f_path.dentry;
+ struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
+ struct dentry *cursor = file->private_data;
+ int status = 0;