How does NFS handle this use case? On Tue, Nov 19, 2013 at 10:33 AM, <shirishpargaonkar@xxxxxxxxx> wrote: > From: Shirish Pargaonkar <shirishpargaonkar@xxxxxxxxx> > > > Allow cifs mounts for a prefixpath with intermediate paths without access, > so as to continue with the shared superblock model. > > For the intermediate path entries that do not allow access, create "placeholder" > inodes and instantiate dentries with those inodes. > If and when such a path entry becomes accessible it is filled with correct > info. > > Reference: Samba bugzilla 6950 > > Signed-off-by: Shirish Pargaonkar <spargaonkar@xxxxxxxx> > > --- > fs/cifs/cifsfs.c | 17 +++++++++++++++-- > fs/cifs/cifsproto.h | 3 +++ > fs/cifs/inode.c | 16 ++++++++++++++++ > 3 files changed, 34 insertions(+), 2 deletions(-) > > diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c > index 849f613..bce185c 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 36f9ebb..4f5a09a 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) > { > -- > 1.8.3.2 > -- Thanks, Steve -- To unsubscribe from this list: send the line "unsubscribe linux-cifs" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html