diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 77fc5e1..e8faa23 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -584,6 +584,9 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb) char *full_path = NULL; char *s, *p; char sep; + struct inode *dir, *phinode; + struct dentry *child; + struct cifs_fattr phfattr; full_path = cifs_build_path_to_root(vol, cifs_sb, cifs_sb_master_tcon(cifs_sb)); @@ -592,13 +595,13 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb) cifs_dbg(FYI, "Get root dentry for %s\n", full_path); + fill_phfattr(&phfattr, sb); sep = CIFS_DIR_SEP(cifs_sb); dentry = dget(sb->s_root); p = s = full_path; do { - struct inode *dir = dentry->d_inode; - struct dentry *child; + dir = dentry->d_inode; if (!dir) { dput(dentry); @@ -626,6 +629,16 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb) mutex_unlock(&dir->i_mutex); dput(dentry); dentry = child; + if (!IS_ERR(dentry)) { + if (*s) { + /* EACCESS on an intermediate dir */ + if (!dentry->d_inode) { + phinode = cifs_iget(sb, &phfattr); + if (phinode) + d_instantiate(dentry, phinode); + } + } + } } while (!IS_ERR(dentry)); kfree(full_path); return dentry; diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index aa33976..9a84e5c 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -498,4 +498,7 @@ void cifs_writedata_release(struct kref *refcount); int open_query_close_cifs_symlink(const unsigned char *path, char *pbuf, unsigned int *pbytes_read, struct cifs_sb_info *cifs_sb, unsigned int xid); + +extern void fill_phfattr(struct cifs_fattr *, struct super_block *); + #endif /* _CIFSPROTO_H */ diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 867b7cd..1b6b3d6 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -322,6 +322,22 @@ cifs_create_dfs_fattr(struct cifs_fattr *fattr, struct super_block *sb) fattr->cf_flags |= CIFS_FATTR_DFS_REFERRAL; } +void +fill_phfattr(struct cifs_fattr *cf, struct super_block *sb) +{ + struct cifs_sb_info *cifs_sb = CIFS_SB(sb); + + memset(cf, 0, sizeof(*cf)); + cf->cf_uniqueid = iunique(sb, ROOT_I); + cf->cf_nlink = 1; + cf->cf_atime = CURRENT_TIME; + cf->cf_ctime = CURRENT_TIME; + cf->cf_mtime = CURRENT_TIME; + cf->cf_mode = S_IFDIR | S_IXUGO | S_IRWXU; + cf->cf_uid = cifs_sb->mnt_uid; + cf->cf_gid = cifs_sb->mnt_gid; +} + static int cifs_get_file_info_unix(struct file *filp) {