linux-cifs.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/3] cifs: do not share tcons with DFS
@ 2020-04-21  2:44 Paulo Alcantara
  2020-04-21  2:44 ` [PATCH 2/3] cifs: ensure correct super block for DFS reconnect Paulo Alcantara
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Paulo Alcantara @ 2020-04-21  2:44 UTC (permalink / raw)
  To: linux-cifs, smfrench, samba-technical; +Cc: Paulo Alcantara, Aurelien Aptel

This disables tcon re-use for DFS shares.

tcon->dfs_path stores the path that the tcon should connect to when
doing failing over.

If that tcon is used multiple times e.g. 2 mounts using it with
different prefixpath, each will need a different dfs_path but there is
only one tcon. The other solution would be to split the tcon in 2
tcons during failover but that is much harder.

Signed-off-by: Paulo Alcantara (SUSE) <pc@cjr.nz>
Reviewed-by: Aurelien Aptel <aaptel@suse.com>
---
 fs/cifs/connect.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 95b3ab0ca8c0..ac6d286fe79f 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -3373,7 +3373,7 @@ cifs_find_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
 	spin_lock(&cifs_tcp_ses_lock);
 	list_for_each(tmp, &ses->tcon_list) {
 		tcon = list_entry(tmp, struct cifs_tcon, tcon_list);
-		if (!match_tcon(tcon, volume_info))
+		if (!match_tcon(tcon, volume_info) || tcon->dfs_path)
 			continue;
 		++tcon->tc_count;
 		spin_unlock(&cifs_tcp_ses_lock);
-- 
2.26.0


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 2/3] cifs: ensure correct super block for DFS reconnect
  2020-04-21  2:44 [PATCH 1/3] cifs: do not share tcons with DFS Paulo Alcantara
@ 2020-04-21  2:44 ` Paulo Alcantara
  2020-04-21  2:44 ` [PATCH 3/3] cifs: fix uninitialised lease_key in open_shroot() Paulo Alcantara
  2020-04-21 10:48 ` [PATCH 1/3] cifs: do not share tcons with DFS ronnie sahlberg
  2 siblings, 0 replies; 4+ messages in thread
From: Paulo Alcantara @ 2020-04-21  2:44 UTC (permalink / raw)
  To: linux-cifs, smfrench, samba-technical; +Cc: Paulo Alcantara

We could not rely on TCP server pointer to determine which super block
to update the prefix path when reconnecting tcons since it might map
to different tcons that share same TCP connection.

Instead, walk through all cifs super blocks and compare their DFS full
paths with the tcon being updated to.

Signed-off-by: Paulo Alcantara (SUSE) <pc@cjr.nz>
---
 fs/cifs/misc.c | 71 ++++++++++++++++++++++++++++++++++++++------------
 1 file changed, 54 insertions(+), 17 deletions(-)

diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index a456febd4109..2d111b5a670c 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -1025,51 +1025,88 @@ int copy_path_name(char *dst, const char *src)
 }
 
 struct super_cb_data {
-	struct TCP_Server_Info *server;
+	void *data;
 	struct super_block *sb;
 };
 
-static void super_cb(struct super_block *sb, void *arg)
+static void tcp_super_cb(struct super_block *sb, void *arg)
 {
-	struct super_cb_data *d = arg;
+	struct super_cb_data *sd = arg;
+	struct TCP_Server_Info *server = sd->data;
 	struct cifs_sb_info *cifs_sb;
 	struct cifs_tcon *tcon;
 
-	if (d->sb)
+	if (sd->sb)
 		return;
 
 	cifs_sb = CIFS_SB(sb);
 	tcon = cifs_sb_master_tcon(cifs_sb);
-	if (tcon->ses->server == d->server)
-		d->sb = sb;
+	if (tcon->ses->server == server)
+		sd->sb = sb;
 }
 
-struct super_block *cifs_get_tcp_super(struct TCP_Server_Info *server)
+static struct super_block *__cifs_get_super(void (*f)(struct super_block *, void *),
+					    void *data)
 {
-	struct super_cb_data d = {
-		.server = server,
+	struct super_cb_data sd = {
+		.data = data,
 		.sb = NULL,
 	};
 
-	iterate_supers_type(&cifs_fs_type, super_cb, &d);
+	iterate_supers_type(&cifs_fs_type, f, &sd);
 
-	if (unlikely(!d.sb))
-		return ERR_PTR(-ENOENT);
+	if (!sd.sb)
+		return ERR_PTR(-EINVAL);
 	/*
 	 * Grab an active reference in order to prevent automounts (DFS links)
 	 * of expiring and then freeing up our cifs superblock pointer while
 	 * we're doing failover.
 	 */
-	cifs_sb_active(d.sb);
-	return d.sb;
+	cifs_sb_active(sd.sb);
+	return sd.sb;
 }
 
-void cifs_put_tcp_super(struct super_block *sb)
+static void __cifs_put_super(struct super_block *sb)
 {
 	if (!IS_ERR_OR_NULL(sb))
 		cifs_sb_deactive(sb);
 }
 
+struct super_block *cifs_get_tcp_super(struct TCP_Server_Info *server)
+{
+	return __cifs_get_super(tcp_super_cb, server);
+}
+
+void cifs_put_tcp_super(struct super_block *sb)
+{
+	__cifs_put_super(sb);
+}
+
+static void tcon_super_cb(struct super_block *sb, void *arg)
+{
+	struct super_cb_data *sd = arg;
+	struct cifs_tcon *tcon = sd->data;
+	struct cifs_sb_info *cifs_sb;
+
+	if (sd->sb)
+		return;
+
+	cifs_sb = CIFS_SB(sb);
+	if (tcon->dfs_path && cifs_sb->origin_fullpath &&
+	    !strcasecmp(tcon->dfs_path, cifs_sb->origin_fullpath))
+		sd->sb = sb;
+}
+
+static inline struct super_block *cifs_get_tcon_super(struct cifs_tcon *tcon)
+{
+	return __cifs_get_super(tcon_super_cb, tcon);
+}
+
+static inline void cifs_put_tcon_super(struct super_block *sb)
+{
+	__cifs_put_super(sb);
+}
+
 int update_super_prepath(struct cifs_tcon *tcon, const char *prefix,
 			 size_t prefix_len)
 {
@@ -1077,7 +1114,7 @@ int update_super_prepath(struct cifs_tcon *tcon, const char *prefix,
 	struct cifs_sb_info *cifs_sb;
 	int rc = 0;
 
-	sb = cifs_get_tcp_super(tcon->ses->server);
+	sb = cifs_get_tcon_super(tcon);
 	if (IS_ERR(sb))
 		return PTR_ERR(sb);
 
@@ -1099,6 +1136,6 @@ int update_super_prepath(struct cifs_tcon *tcon, const char *prefix,
 	cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH;
 
 out:
-	cifs_put_tcp_super(sb);
+	cifs_put_tcon_super(sb);
 	return rc;
 }
-- 
2.26.0


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 3/3] cifs: fix uninitialised lease_key in open_shroot()
  2020-04-21  2:44 [PATCH 1/3] cifs: do not share tcons with DFS Paulo Alcantara
  2020-04-21  2:44 ` [PATCH 2/3] cifs: ensure correct super block for DFS reconnect Paulo Alcantara
@ 2020-04-21  2:44 ` Paulo Alcantara
  2020-04-21 10:48 ` [PATCH 1/3] cifs: do not share tcons with DFS ronnie sahlberg
  2 siblings, 0 replies; 4+ messages in thread
From: Paulo Alcantara @ 2020-04-21  2:44 UTC (permalink / raw)
  To: linux-cifs, smfrench, samba-technical; +Cc: Paulo Alcantara

SMB2_open_init() expects a pre-initialised lease_key when opening a
file with a lease, so set pfid->lease_key prior to calling it in
open_shroot().

This issue was observed when performing some DFS failover tests and
the lease key was never randomly generated.

Signed-off-by: Paulo Alcantara (SUSE) <pc@cjr.nz>
---
 fs/cifs/smb2ops.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index b36c46f48705..f829f4165d38 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -687,6 +687,11 @@ int open_shroot(unsigned int xid, struct cifs_tcon *tcon,
 	if (smb3_encryption_required(tcon))
 		flags |= CIFS_TRANSFORM_REQ;
 
+	if (!server->ops->new_lease_key)
+		return -EIO;
+
+	server->ops->new_lease_key(pfid);
+
 	memset(rqst, 0, sizeof(rqst));
 	resp_buftype[0] = resp_buftype[1] = CIFS_NO_BUFFER;
 	memset(rsp_iov, 0, sizeof(rsp_iov));
-- 
2.26.0


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH 1/3] cifs: do not share tcons with DFS
  2020-04-21  2:44 [PATCH 1/3] cifs: do not share tcons with DFS Paulo Alcantara
  2020-04-21  2:44 ` [PATCH 2/3] cifs: ensure correct super block for DFS reconnect Paulo Alcantara
  2020-04-21  2:44 ` [PATCH 3/3] cifs: fix uninitialised lease_key in open_shroot() Paulo Alcantara
@ 2020-04-21 10:48 ` ronnie sahlberg
  2 siblings, 0 replies; 4+ messages in thread
From: ronnie sahlberg @ 2020-04-21 10:48 UTC (permalink / raw)
  To: Paulo Alcantara; +Cc: linux-cifs, Steve French, samba-technical, Aurelien Aptel

series looks good after initial review

Reviewed-by: Ronnie Sahlberg <lsahlber@redhat.com>


On Tue, Apr 21, 2020 at 12:45 PM Paulo Alcantara <pc@cjr.nz> wrote:
>
> This disables tcon re-use for DFS shares.
>
> tcon->dfs_path stores the path that the tcon should connect to when
> doing failing over.
>
> If that tcon is used multiple times e.g. 2 mounts using it with
> different prefixpath, each will need a different dfs_path but there is
> only one tcon. The other solution would be to split the tcon in 2
> tcons during failover but that is much harder.
>
> Signed-off-by: Paulo Alcantara (SUSE) <pc@cjr.nz>
> Reviewed-by: Aurelien Aptel <aaptel@suse.com>
> ---
>  fs/cifs/connect.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
> index 95b3ab0ca8c0..ac6d286fe79f 100644
> --- a/fs/cifs/connect.c
> +++ b/fs/cifs/connect.c
> @@ -3373,7 +3373,7 @@ cifs_find_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
>         spin_lock(&cifs_tcp_ses_lock);
>         list_for_each(tmp, &ses->tcon_list) {
>                 tcon = list_entry(tmp, struct cifs_tcon, tcon_list);
> -               if (!match_tcon(tcon, volume_info))
> +               if (!match_tcon(tcon, volume_info) || tcon->dfs_path)
>                         continue;
>                 ++tcon->tc_count;
>                 spin_unlock(&cifs_tcp_ses_lock);
> --
> 2.26.0
>

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2020-04-21 10:48 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-04-21  2:44 [PATCH 1/3] cifs: do not share tcons with DFS Paulo Alcantara
2020-04-21  2:44 ` [PATCH 2/3] cifs: ensure correct super block for DFS reconnect Paulo Alcantara
2020-04-21  2:44 ` [PATCH 3/3] cifs: fix uninitialised lease_key in open_shroot() Paulo Alcantara
2020-04-21 10:48 ` [PATCH 1/3] cifs: do not share tcons with DFS ronnie sahlberg

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).