Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag '6.5-rc1-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6

Pull smb client fixes from Steve French:

- Two reconnect fixes: important fix to address inFlight count to leak
(which can leak credits), and fix for better handling a deleted share

- DFS fix

- SMB1 cleanup fix

- deferred close fix

* tag '6.5-rc1-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6:
cifs: fix mid leak during reconnection after timeout threshold
cifs: is_network_name_deleted should return a bool
smb: client: fix missed ses refcounting
smb: client: Fix -Wstringop-overflow issues
cifs: if deferred close is disabled then close files immediately

+43 -31
+1 -1
fs/smb/client/cifsglob.h
··· 532 532 /* Check for STATUS_IO_TIMEOUT */ 533 533 bool (*is_status_io_timeout)(char *buf); 534 534 /* Check for STATUS_NETWORK_NAME_DELETED */ 535 - void (*is_network_name_deleted)(char *buf, struct TCP_Server_Info *srv); 535 + bool (*is_network_name_deleted)(char *buf, struct TCP_Server_Info *srv); 536 536 }; 537 537 538 538 struct smb_version_values {
+1 -1
fs/smb/client/cifssmb.c
··· 3184 3184 param_offset = offsetof(struct smb_com_transaction2_spi_req, 3185 3185 InformationLevel) - 4; 3186 3186 offset = param_offset + params; 3187 - parm_data = ((char *) &pSMB->hdr.Protocol) + offset; 3187 + parm_data = ((char *)pSMB) + sizeof(pSMB->hdr.smb_buf_length) + offset; 3188 3188 pSMB->ParameterOffset = cpu_to_le16(param_offset); 3189 3189 3190 3190 /* convert to on the wire format for POSIX ACL */
+23 -7
fs/smb/client/connect.c
··· 60 60 #define TLINK_IDLE_EXPIRE (600 * HZ) 61 61 62 62 /* Drop the connection to not overload the server */ 63 - #define NUM_STATUS_IO_TIMEOUT 5 63 + #define MAX_STATUS_IO_TIMEOUT 5 64 64 65 65 static int ip_connect(struct TCP_Server_Info *server); 66 66 static int generic_ip_connect(struct TCP_Server_Info *server); ··· 1117 1117 struct mid_q_entry *mids[MAX_COMPOUND]; 1118 1118 char *bufs[MAX_COMPOUND]; 1119 1119 unsigned int noreclaim_flag, num_io_timeout = 0; 1120 + bool pending_reconnect = false; 1120 1121 1121 1122 noreclaim_flag = memalloc_noreclaim_save(); 1122 1123 cifs_dbg(FYI, "Demultiplex PID: %d\n", task_pid_nr(current)); ··· 1157 1156 cifs_dbg(FYI, "RFC1002 header 0x%x\n", pdu_length); 1158 1157 if (!is_smb_response(server, buf[0])) 1159 1158 continue; 1159 + 1160 + pending_reconnect = false; 1160 1161 next_pdu: 1161 1162 server->pdu_size = pdu_length; 1162 1163 ··· 1216 1213 if (server->ops->is_status_io_timeout && 1217 1214 server->ops->is_status_io_timeout(buf)) { 1218 1215 num_io_timeout++; 1219 - if (num_io_timeout > NUM_STATUS_IO_TIMEOUT) { 1220 - cifs_reconnect(server, false); 1216 + if (num_io_timeout > MAX_STATUS_IO_TIMEOUT) { 1217 + cifs_server_dbg(VFS, 1218 + "Number of request timeouts exceeded %d. Reconnecting", 1219 + MAX_STATUS_IO_TIMEOUT); 1220 + 1221 + pending_reconnect = true; 1221 1222 num_io_timeout = 0; 1222 - continue; 1223 1223 } 1224 1224 } 1225 1225 ··· 1232 1226 if (mids[i] != NULL) { 1233 1227 mids[i]->resp_buf_size = server->pdu_size; 1234 1228 1235 - if (bufs[i] && server->ops->is_network_name_deleted) 1236 - server->ops->is_network_name_deleted(bufs[i], 1237 - server); 1229 + if (bufs[i] != NULL) { 1230 + if (server->ops->is_network_name_deleted && 1231 + server->ops->is_network_name_deleted(bufs[i], 1232 + server)) { 1233 + cifs_server_dbg(FYI, 1234 + "Share deleted. Reconnect needed"); 1235 + } 1236 + } 1238 1237 1239 1238 if (!mids[i]->multiRsp || mids[i]->multiEnd) 1240 1239 mids[i]->callback(mids[i]); ··· 1274 1263 buf = server->smallbuf; 1275 1264 goto next_pdu; 1276 1265 } 1266 + 1267 + /* do this reconnect at the very end after processing all MIDs */ 1268 + if (pending_reconnect) 1269 + cifs_reconnect(server, true); 1270 + 1277 1271 } /* end while !EXITING */ 1278 1272 1279 1273 /* buffer usually freed in free_mid - need to free it here on exit */
+10 -16
fs/smb/client/dfs.c
··· 66 66 return rc; 67 67 } 68 68 69 + /* 70 + * Track individual DFS referral servers used by new DFS mount. 71 + * 72 + * On success, their lifetime will be shared by final tcon (dfs_ses_list). 73 + * Otherwise, they will be put by dfs_put_root_smb_sessions() in cifs_mount(). 74 + */ 69 75 static int add_root_smb_session(struct cifs_mount_ctx *mnt_ctx) 70 76 { 71 77 struct smb3_fs_context *ctx = mnt_ctx->fs_ctx; ··· 86 80 INIT_LIST_HEAD(&root_ses->list); 87 81 88 82 spin_lock(&cifs_tcp_ses_lock); 89 - ses->ses_count++; 83 + cifs_smb_ses_inc_refcount(ses); 90 84 spin_unlock(&cifs_tcp_ses_lock); 91 85 root_ses->ses = ses; 92 86 list_add_tail(&root_ses->list, &mnt_ctx->dfs_ses_list); 93 87 } 88 + /* Select new DFS referral server so that new referrals go through it */ 94 89 ctx->dfs_root_ses = ses; 95 90 return 0; 96 91 } ··· 249 242 int dfs_mount_share(struct cifs_mount_ctx *mnt_ctx, bool *isdfs) 250 243 { 251 244 struct smb3_fs_context *ctx = mnt_ctx->fs_ctx; 252 - struct cifs_ses *ses; 253 245 bool nodfs = ctx->nodfs; 254 246 int rc; 255 247 ··· 282 276 } 283 277 284 278 *isdfs = true; 285 - /* 286 - * Prevent DFS root session of being put in the first call to 287 - * cifs_mount_put_conns(). If another DFS root server was not found 288 - * while chasing the referrals (@ctx->dfs_root_ses == @ses), then we 289 - * can safely put extra refcount of @ses. 290 - */ 291 - ses = mnt_ctx->ses; 292 - mnt_ctx->ses = NULL; 293 - mnt_ctx->server = NULL; 294 - rc = __dfs_mount_share(mnt_ctx); 295 - if (ses == ctx->dfs_root_ses) 296 - cifs_put_smb_ses(ses); 297 - 298 - return rc; 279 + add_root_smb_session(mnt_ctx); 280 + return __dfs_mount_share(mnt_ctx); 299 281 } 300 282 301 283 /* Update dfs referral path of superblock */
+2 -2
fs/smb/client/file.c
··· 1080 1080 cfile = file->private_data; 1081 1081 file->private_data = NULL; 1082 1082 dclose = kmalloc(sizeof(struct cifs_deferred_close), GFP_KERNEL); 1083 - if ((cinode->oplock == CIFS_CACHE_RHW_FLG) && 1084 - cinode->lease_granted && 1083 + if ((cifs_sb->ctx->closetimeo && cinode->oplock == CIFS_CACHE_RHW_FLG) 1084 + && cinode->lease_granted && 1085 1085 !test_bit(CIFS_INO_CLOSE_ON_LOCK, &cinode->flags) && 1086 1086 dclose) { 1087 1087 if (test_and_clear_bit(CIFS_INO_MODIFIED_ATTR, &cinode->flags)) {
+5 -3
fs/smb/client/smb2ops.c
··· 2395 2395 return false; 2396 2396 } 2397 2397 2398 - static void 2398 + static bool 2399 2399 smb2_is_network_name_deleted(char *buf, struct TCP_Server_Info *server) 2400 2400 { 2401 2401 struct smb2_hdr *shdr = (struct smb2_hdr *)buf; ··· 2404 2404 struct cifs_tcon *tcon; 2405 2405 2406 2406 if (shdr->Status != STATUS_NETWORK_NAME_DELETED) 2407 - return; 2407 + return false; 2408 2408 2409 2409 /* If server is a channel, select the primary channel */ 2410 2410 pserver = CIFS_SERVER_IS_CHAN(server) ? server->primary_server : server; ··· 2419 2419 spin_unlock(&cifs_tcp_ses_lock); 2420 2420 pr_warn_once("Server share %s deleted.\n", 2421 2421 tcon->tree_name); 2422 - return; 2422 + return true; 2423 2423 } 2424 2424 } 2425 2425 } 2426 2426 spin_unlock(&cifs_tcp_ses_lock); 2427 + 2428 + return false; 2427 2429 } 2428 2430 2429 2431 static int
+1 -1
fs/smb/client/smb2transport.c
··· 160 160 spin_unlock(&ses->ses_lock); 161 161 continue; 162 162 } 163 - ++ses->ses_count; 163 + cifs_smb_ses_inc_refcount(ses); 164 164 spin_unlock(&ses->ses_lock); 165 165 return ses; 166 166 }