Message ID | 20191122153057.6608-7-pc@cjr.nz (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | DFS fixes | expand |
merged into cifs-2.6.git for-next On Fri, Nov 22, 2019 at 9:31 AM Paulo Alcantara (SUSE) <pc@cjr.nz> wrote: > > Make sure that DFS referrals are sent to newly resolved root targets > as in a multi tier DFS setup. > > Signed-off-by: Paulo Alcantara (SUSE) <pc@cjr.nz> > Link: https://lkml.kernel.org/r/05aa2995-e85e-0ff4-d003-5bb08bd17a22@canonical.com > Cc: stable@vger.kernel.org > Tested-by: Matthew Ruffell <matthew.ruffell@canonical.com> > --- > fs/cifs/connect.c | 32 ++++++++++++++++++++++---------- > 1 file changed, 22 insertions(+), 10 deletions(-) > > diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c > index 668d477cc9c7..86d98d73749d 100644 > --- a/fs/cifs/connect.c > +++ b/fs/cifs/connect.c > @@ -4776,6 +4776,17 @@ static int is_path_remote(struct cifs_sb_info *cifs_sb, struct smb_vol *vol, > } > > #ifdef CONFIG_CIFS_DFS_UPCALL > +static inline void set_root_tcon(struct cifs_sb_info *cifs_sb, > + struct cifs_tcon *tcon, > + struct cifs_tcon **root) > +{ > + spin_lock(&cifs_tcp_ses_lock); > + tcon->tc_count++; > + tcon->remap = cifs_remap(cifs_sb); > + spin_unlock(&cifs_tcp_ses_lock); > + *root = tcon; > +} > + > int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *vol) > { > int rc = 0; > @@ -4877,18 +4888,10 @@ int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *vol) > /* Cache out resolved root server */ > (void)dfs_cache_find(xid, ses, cifs_sb->local_nls, cifs_remap(cifs_sb), > root_path + 1, NULL, NULL); > - /* > - * Save root tcon for additional DFS requests to update or create a new > - * DFS cache entry, or even perform DFS failover. > - */ > - spin_lock(&cifs_tcp_ses_lock); > - tcon->tc_count++; > - tcon->dfs_path = root_path; > + kfree(root_path); > root_path = NULL; > - tcon->remap = cifs_remap(cifs_sb); > - spin_unlock(&cifs_tcp_ses_lock); > > - root_tcon = tcon; > + set_root_tcon(cifs_sb, tcon, &root_tcon); > > for (count = 1; ;) { > if (!rc && tcon) { > @@ -4925,6 +4928,15 @@ int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *vol) > mount_put_conns(cifs_sb, xid, server, ses, tcon); > rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses, > &tcon); > + /* > + * Ensure that DFS referrals go through new root server. > + */ > + if (!rc && tcon && > + (tcon->share_flags & (SHI1005_FLAGS_DFS | > + SHI1005_FLAGS_DFS_ROOT))) { > + cifs_put_tcon(root_tcon); > + set_root_tcon(cifs_sb, tcon, &root_tcon); > + } > } > if (rc) { > if (rc == -EACCES || rc == -EOPNOTSUPP) > -- > 2.24.0 >
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 668d477cc9c7..86d98d73749d 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -4776,6 +4776,17 @@ static int is_path_remote(struct cifs_sb_info *cifs_sb, struct smb_vol *vol, } #ifdef CONFIG_CIFS_DFS_UPCALL +static inline void set_root_tcon(struct cifs_sb_info *cifs_sb, + struct cifs_tcon *tcon, + struct cifs_tcon **root) +{ + spin_lock(&cifs_tcp_ses_lock); + tcon->tc_count++; + tcon->remap = cifs_remap(cifs_sb); + spin_unlock(&cifs_tcp_ses_lock); + *root = tcon; +} + int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *vol) { int rc = 0; @@ -4877,18 +4888,10 @@ int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *vol) /* Cache out resolved root server */ (void)dfs_cache_find(xid, ses, cifs_sb->local_nls, cifs_remap(cifs_sb), root_path + 1, NULL, NULL); - /* - * Save root tcon for additional DFS requests to update or create a new - * DFS cache entry, or even perform DFS failover. - */ - spin_lock(&cifs_tcp_ses_lock); - tcon->tc_count++; - tcon->dfs_path = root_path; + kfree(root_path); root_path = NULL; - tcon->remap = cifs_remap(cifs_sb); - spin_unlock(&cifs_tcp_ses_lock); - root_tcon = tcon; + set_root_tcon(cifs_sb, tcon, &root_tcon); for (count = 1; ;) { if (!rc && tcon) { @@ -4925,6 +4928,15 @@ int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *vol) mount_put_conns(cifs_sb, xid, server, ses, tcon); rc = mount_get_conns(vol, cifs_sb, &xid, &server, &ses, &tcon); + /* + * Ensure that DFS referrals go through new root server. + */ + if (!rc && tcon && + (tcon->share_flags & (SHI1005_FLAGS_DFS | + SHI1005_FLAGS_DFS_ROOT))) { + cifs_put_tcon(root_tcon); + set_root_tcon(cifs_sb, tcon, &root_tcon); + } } if (rc) { if (rc == -EACCES || rc == -EOPNOTSUPP)