Skip to content

Commit d4fb4bf

Browse files
committed
Merge tag '5.7-rc2-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6
Pull cifs fixes from Steve French: "Five cifs/smb3 fixes:two for DFS reconnect failover, one lease fix for stable and the others to fix a missing spinlock during reconnect" * tag '5.7-rc2-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6: cifs: fix uninitialised lease_key in open_shroot() cifs: ensure correct super block for DFS reconnect cifs: do not share tcons with DFS cifs: minor update to comments around the cifs_tcp_ses_lock mutex cifs: protect updating server->dstaddr with a spinlock
2 parents e9a61af + 0fe0781 commit d4fb4bf

File tree

4 files changed

+78
-18
lines changed

4 files changed

+78
-18
lines changed

fs/cifs/cifsglob.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1891,7 +1891,8 @@ GLOBAL_EXTERN struct list_head cifs_tcp_ses_list;
18911891
/*
18921892
* This lock protects the cifs_tcp_ses_list, the list of smb sessions per
18931893
* tcp session, and the list of tcon's per smb session. It also protects
1894-
* the reference counters for the server, smb session, and tcon. Finally,
1894+
* the reference counters for the server, smb session, and tcon. It also
1895+
* protects some fields in the TCP_Server_Info struct such as dstaddr. Finally,
18951896
* changes to the tcon->tidStatus should be done while holding this lock.
18961897
* generally the locks should be taken in order tcp_ses_lock before
18971898
* tcon->open_file_lock and that before file->file_info_lock since the

fs/cifs/connect.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,8 +375,10 @@ static int reconn_set_ipaddr(struct TCP_Server_Info *server)
375375
return rc;
376376
}
377377

378+
spin_lock(&cifs_tcp_ses_lock);
378379
rc = cifs_convert_address((struct sockaddr *)&server->dstaddr, ipaddr,
379380
strlen(ipaddr));
381+
spin_unlock(&cifs_tcp_ses_lock);
380382
kfree(ipaddr);
381383

382384
return !rc ? -1 : 0;
@@ -3373,6 +3375,10 @@ cifs_find_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
33733375
spin_lock(&cifs_tcp_ses_lock);
33743376
list_for_each(tmp, &ses->tcon_list) {
33753377
tcon = list_entry(tmp, struct cifs_tcon, tcon_list);
3378+
#ifdef CONFIG_CIFS_DFS_UPCALL
3379+
if (tcon->dfs_path)
3380+
continue;
3381+
#endif
33763382
if (!match_tcon(tcon, volume_info))
33773383
continue;
33783384
++tcon->tc_count;

fs/cifs/misc.c

Lines changed: 65 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1025,59 +1025,107 @@ int copy_path_name(char *dst, const char *src)
10251025
}
10261026

10271027
struct super_cb_data {
1028-
struct TCP_Server_Info *server;
1028+
void *data;
10291029
struct super_block *sb;
10301030
};
10311031

1032-
static void super_cb(struct super_block *sb, void *arg)
1032+
static void tcp_super_cb(struct super_block *sb, void *arg)
10331033
{
1034-
struct super_cb_data *d = arg;
1034+
struct super_cb_data *sd = arg;
1035+
struct TCP_Server_Info *server = sd->data;
10351036
struct cifs_sb_info *cifs_sb;
10361037
struct cifs_tcon *tcon;
10371038

1038-
if (d->sb)
1039+
if (sd->sb)
10391040
return;
10401041

10411042
cifs_sb = CIFS_SB(sb);
10421043
tcon = cifs_sb_master_tcon(cifs_sb);
1043-
if (tcon->ses->server == d->server)
1044-
d->sb = sb;
1044+
if (tcon->ses->server == server)
1045+
sd->sb = sb;
10451046
}
10461047

1047-
struct super_block *cifs_get_tcp_super(struct TCP_Server_Info *server)
1048+
static struct super_block *__cifs_get_super(void (*f)(struct super_block *, void *),
1049+
void *data)
10481050
{
1049-
struct super_cb_data d = {
1050-
.server = server,
1051+
struct super_cb_data sd = {
1052+
.data = data,
10511053
.sb = NULL,
10521054
};
10531055

1054-
iterate_supers_type(&cifs_fs_type, super_cb, &d);
1056+
iterate_supers_type(&cifs_fs_type, f, &sd);
10551057

1056-
if (unlikely(!d.sb))
1057-
return ERR_PTR(-ENOENT);
1058+
if (!sd.sb)
1059+
return ERR_PTR(-EINVAL);
10581060
/*
10591061
* Grab an active reference in order to prevent automounts (DFS links)
10601062
* of expiring and then freeing up our cifs superblock pointer while
10611063
* we're doing failover.
10621064
*/
1063-
cifs_sb_active(d.sb);
1064-
return d.sb;
1065+
cifs_sb_active(sd.sb);
1066+
return sd.sb;
10651067
}
10661068

1067-
void cifs_put_tcp_super(struct super_block *sb)
1069+
static void __cifs_put_super(struct super_block *sb)
10681070
{
10691071
if (!IS_ERR_OR_NULL(sb))
10701072
cifs_sb_deactive(sb);
10711073
}
10721074

1075+
struct super_block *cifs_get_tcp_super(struct TCP_Server_Info *server)
1076+
{
1077+
return __cifs_get_super(tcp_super_cb, server);
1078+
}
1079+
1080+
void cifs_put_tcp_super(struct super_block *sb)
1081+
{
1082+
__cifs_put_super(sb);
1083+
}
1084+
1085+
#ifdef CONFIG_CIFS_DFS_UPCALL
1086+
static void tcon_super_cb(struct super_block *sb, void *arg)
1087+
{
1088+
struct super_cb_data *sd = arg;
1089+
struct cifs_tcon *tcon = sd->data;
1090+
struct cifs_sb_info *cifs_sb;
1091+
1092+
if (sd->sb)
1093+
return;
1094+
1095+
cifs_sb = CIFS_SB(sb);
1096+
if (tcon->dfs_path && cifs_sb->origin_fullpath &&
1097+
!strcasecmp(tcon->dfs_path, cifs_sb->origin_fullpath))
1098+
sd->sb = sb;
1099+
}
1100+
1101+
static inline struct super_block *cifs_get_tcon_super(struct cifs_tcon *tcon)
1102+
{
1103+
return __cifs_get_super(tcon_super_cb, tcon);
1104+
}
1105+
1106+
static inline void cifs_put_tcon_super(struct super_block *sb)
1107+
{
1108+
__cifs_put_super(sb);
1109+
}
1110+
#else
1111+
static inline struct super_block *cifs_get_tcon_super(struct cifs_tcon *tcon)
1112+
{
1113+
return ERR_PTR(-EOPNOTSUPP);
1114+
}
1115+
1116+
static inline void cifs_put_tcon_super(struct super_block *sb)
1117+
{
1118+
}
1119+
#endif
1120+
10731121
int update_super_prepath(struct cifs_tcon *tcon, const char *prefix,
10741122
size_t prefix_len)
10751123
{
10761124
struct super_block *sb;
10771125
struct cifs_sb_info *cifs_sb;
10781126
int rc = 0;
10791127

1080-
sb = cifs_get_tcp_super(tcon->ses->server);
1128+
sb = cifs_get_tcon_super(tcon);
10811129
if (IS_ERR(sb))
10821130
return PTR_ERR(sb);
10831131

@@ -1099,6 +1147,6 @@ int update_super_prepath(struct cifs_tcon *tcon, const char *prefix,
10991147
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH;
11001148

11011149
out:
1102-
cifs_put_tcp_super(sb);
1150+
cifs_put_tcon_super(sb);
11031151
return rc;
11041152
}

fs/cifs/smb2ops.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -687,6 +687,11 @@ int open_shroot(unsigned int xid, struct cifs_tcon *tcon,
687687
if (smb3_encryption_required(tcon))
688688
flags |= CIFS_TRANSFORM_REQ;
689689

690+
if (!server->ops->new_lease_key)
691+
return -EIO;
692+
693+
server->ops->new_lease_key(pfid);
694+
690695
memset(rqst, 0, sizeof(rqst));
691696
resp_buftype[0] = resp_buftype[1] = CIFS_NO_BUFFER;
692697
memset(rsp_iov, 0, sizeof(rsp_iov));

0 commit comments

Comments
 (0)