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

Changed files
+78 -18
fs
+2 -1
fs/cifs/cifsglob.h
··· 1891 1891 /* 1892 1892 * This lock protects the cifs_tcp_ses_list, the list of smb sessions per 1893 1893 * 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, 1895 1896 * changes to the tcon->tidStatus should be done while holding this lock. 1896 1897 * generally the locks should be taken in order tcp_ses_lock before 1897 1898 * tcon->open_file_lock and that before file->file_info_lock since the
+6
fs/cifs/connect.c
··· 375 375 return rc; 376 376 } 377 377 378 + spin_lock(&cifs_tcp_ses_lock); 378 379 rc = cifs_convert_address((struct sockaddr *)&server->dstaddr, ipaddr, 379 380 strlen(ipaddr)); 381 + spin_unlock(&cifs_tcp_ses_lock); 380 382 kfree(ipaddr); 381 383 382 384 return !rc ? -1 : 0; ··· 3375 3373 spin_lock(&cifs_tcp_ses_lock); 3376 3374 list_for_each(tmp, &ses->tcon_list) { 3377 3375 tcon = list_entry(tmp, struct cifs_tcon, tcon_list); 3376 + #ifdef CONFIG_CIFS_DFS_UPCALL 3377 + if (tcon->dfs_path) 3378 + continue; 3379 + #endif 3378 3380 if (!match_tcon(tcon, volume_info)) 3379 3381 continue; 3380 3382 ++tcon->tc_count;
+65 -17
fs/cifs/misc.c
··· 1025 1025 } 1026 1026 1027 1027 struct super_cb_data { 1028 - struct TCP_Server_Info *server; 1028 + void *data; 1029 1029 struct super_block *sb; 1030 1030 }; 1031 1031 1032 - static void super_cb(struct super_block *sb, void *arg) 1032 + static void tcp_super_cb(struct super_block *sb, void *arg) 1033 1033 { 1034 - struct super_cb_data *d = arg; 1034 + struct super_cb_data *sd = arg; 1035 + struct TCP_Server_Info *server = sd->data; 1035 1036 struct cifs_sb_info *cifs_sb; 1036 1037 struct cifs_tcon *tcon; 1037 1038 1038 - if (d->sb) 1039 + if (sd->sb) 1039 1040 return; 1040 1041 1041 1042 cifs_sb = CIFS_SB(sb); 1042 1043 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; 1045 1046 } 1046 1047 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) 1048 1050 { 1049 - struct super_cb_data d = { 1050 - .server = server, 1051 + struct super_cb_data sd = { 1052 + .data = data, 1051 1053 .sb = NULL, 1052 1054 }; 1053 1055 1054 - iterate_supers_type(&cifs_fs_type, super_cb, &d); 1056 + iterate_supers_type(&cifs_fs_type, f, &sd); 1055 1057 1056 - if (unlikely(!d.sb)) 1057 - return ERR_PTR(-ENOENT); 1058 + if (!sd.sb) 1059 + return ERR_PTR(-EINVAL); 1058 1060 /* 1059 1061 * Grab an active reference in order to prevent automounts (DFS links) 1060 1062 * of expiring and then freeing up our cifs superblock pointer while 1061 1063 * we're doing failover. 1062 1064 */ 1063 - cifs_sb_active(d.sb); 1064 - return d.sb; 1065 + cifs_sb_active(sd.sb); 1066 + return sd.sb; 1065 1067 } 1066 1068 1067 - void cifs_put_tcp_super(struct super_block *sb) 1069 + static void __cifs_put_super(struct super_block *sb) 1068 1070 { 1069 1071 if (!IS_ERR_OR_NULL(sb)) 1070 1072 cifs_sb_deactive(sb); 1071 1073 } 1074 + 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 1072 1120 1073 1121 int update_super_prepath(struct cifs_tcon *tcon, const char *prefix, 1074 1122 size_t prefix_len) ··· 1125 1077 struct cifs_sb_info *cifs_sb; 1126 1078 int rc = 0; 1127 1079 1128 - sb = cifs_get_tcp_super(tcon->ses->server); 1080 + sb = cifs_get_tcon_super(tcon); 1129 1081 if (IS_ERR(sb)) 1130 1082 return PTR_ERR(sb); 1131 1083 ··· 1147 1099 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH; 1148 1100 1149 1101 out: 1150 - cifs_put_tcp_super(sb); 1102 + cifs_put_tcon_super(sb); 1151 1103 return rc; 1152 1104 }
+5
fs/cifs/smb2ops.c
··· 687 687 if (smb3_encryption_required(tcon)) 688 688 flags |= CIFS_TRANSFORM_REQ; 689 689 690 + if (!server->ops->new_lease_key) 691 + return -EIO; 692 + 693 + server->ops->new_lease_key(pfid); 694 + 690 695 memset(rqst, 0, sizeof(rqst)); 691 696 resp_buftype[0] = resp_buftype[1] = CIFS_NO_BUFFER; 692 697 memset(rsp_iov, 0, sizeof(rsp_iov));