Skip to content
This repository was archived by the owner on Nov 8, 2023. It is now read-only.

Commit fe756ad

Browse files
committed
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
2 parents 20edcec + 69cba9d commit fe756ad

File tree

7 files changed

+43
-31
lines changed

7 files changed

+43
-31
lines changed

fs/smb/client/cifsglob.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -532,7 +532,7 @@ struct smb_version_operations {
532532
/* Check for STATUS_IO_TIMEOUT */
533533
bool (*is_status_io_timeout)(char *buf);
534534
/* 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);
536536
};
537537

538538
struct smb_version_values {

fs/smb/client/cifssmb.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3184,7 +3184,7 @@ int cifs_do_set_acl(const unsigned int xid, struct cifs_tcon *tcon,
31843184
param_offset = offsetof(struct smb_com_transaction2_spi_req,
31853185
InformationLevel) - 4;
31863186
offset = param_offset + params;
3187-
parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
3187+
parm_data = ((char *)pSMB) + sizeof(pSMB->hdr.smb_buf_length) + offset;
31883188
pSMB->ParameterOffset = cpu_to_le16(param_offset);
31893189

31903190
/* convert to on the wire format for POSIX ACL */

fs/smb/client/connect.c

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ extern bool disable_legacy_dialects;
6060
#define TLINK_IDLE_EXPIRE (600 * HZ)
6161

6262
/* Drop the connection to not overload the server */
63-
#define NUM_STATUS_IO_TIMEOUT 5
63+
#define MAX_STATUS_IO_TIMEOUT 5
6464

6565
static int ip_connect(struct TCP_Server_Info *server);
6666
static int generic_ip_connect(struct TCP_Server_Info *server);
@@ -1117,6 +1117,7 @@ cifs_demultiplex_thread(void *p)
11171117
struct mid_q_entry *mids[MAX_COMPOUND];
11181118
char *bufs[MAX_COMPOUND];
11191119
unsigned int noreclaim_flag, num_io_timeout = 0;
1120+
bool pending_reconnect = false;
11201121

11211122
noreclaim_flag = memalloc_noreclaim_save();
11221123
cifs_dbg(FYI, "Demultiplex PID: %d\n", task_pid_nr(current));
@@ -1156,6 +1157,8 @@ cifs_demultiplex_thread(void *p)
11561157
cifs_dbg(FYI, "RFC1002 header 0x%x\n", pdu_length);
11571158
if (!is_smb_response(server, buf[0]))
11581159
continue;
1160+
1161+
pending_reconnect = false;
11591162
next_pdu:
11601163
server->pdu_size = pdu_length;
11611164

@@ -1213,10 +1216,13 @@ cifs_demultiplex_thread(void *p)
12131216
if (server->ops->is_status_io_timeout &&
12141217
server->ops->is_status_io_timeout(buf)) {
12151218
num_io_timeout++;
1216-
if (num_io_timeout > NUM_STATUS_IO_TIMEOUT) {
1217-
cifs_reconnect(server, false);
1219+
if (num_io_timeout > MAX_STATUS_IO_TIMEOUT) {
1220+
cifs_server_dbg(VFS,
1221+
"Number of request timeouts exceeded %d. Reconnecting",
1222+
MAX_STATUS_IO_TIMEOUT);
1223+
1224+
pending_reconnect = true;
12181225
num_io_timeout = 0;
1219-
continue;
12201226
}
12211227
}
12221228

@@ -1226,9 +1232,14 @@ cifs_demultiplex_thread(void *p)
12261232
if (mids[i] != NULL) {
12271233
mids[i]->resp_buf_size = server->pdu_size;
12281234

1229-
if (bufs[i] && server->ops->is_network_name_deleted)
1230-
server->ops->is_network_name_deleted(bufs[i],
1231-
server);
1235+
if (bufs[i] != NULL) {
1236+
if (server->ops->is_network_name_deleted &&
1237+
server->ops->is_network_name_deleted(bufs[i],
1238+
server)) {
1239+
cifs_server_dbg(FYI,
1240+
"Share deleted. Reconnect needed");
1241+
}
1242+
}
12321243

12331244
if (!mids[i]->multiRsp || mids[i]->multiEnd)
12341245
mids[i]->callback(mids[i]);
@@ -1263,6 +1274,11 @@ cifs_demultiplex_thread(void *p)
12631274
buf = server->smallbuf;
12641275
goto next_pdu;
12651276
}
1277+
1278+
/* do this reconnect at the very end after processing all MIDs */
1279+
if (pending_reconnect)
1280+
cifs_reconnect(server, true);
1281+
12661282
} /* end while !EXITING */
12671283

12681284
/* buffer usually freed in free_mid - need to free it here on exit */

fs/smb/client/dfs.c

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,12 @@ static int get_session(struct cifs_mount_ctx *mnt_ctx, const char *full_path)
6666
return rc;
6767
}
6868

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+
*/
6975
static int add_root_smb_session(struct cifs_mount_ctx *mnt_ctx)
7076
{
7177
struct smb3_fs_context *ctx = mnt_ctx->fs_ctx;
@@ -80,11 +86,12 @@ static int add_root_smb_session(struct cifs_mount_ctx *mnt_ctx)
8086
INIT_LIST_HEAD(&root_ses->list);
8187

8288
spin_lock(&cifs_tcp_ses_lock);
83-
ses->ses_count++;
89+
cifs_smb_ses_inc_refcount(ses);
8490
spin_unlock(&cifs_tcp_ses_lock);
8591
root_ses->ses = ses;
8692
list_add_tail(&root_ses->list, &mnt_ctx->dfs_ses_list);
8793
}
94+
/* Select new DFS referral server so that new referrals go through it */
8895
ctx->dfs_root_ses = ses;
8996
return 0;
9097
}
@@ -242,7 +249,6 @@ static int __dfs_mount_share(struct cifs_mount_ctx *mnt_ctx)
242249
int dfs_mount_share(struct cifs_mount_ctx *mnt_ctx, bool *isdfs)
243250
{
244251
struct smb3_fs_context *ctx = mnt_ctx->fs_ctx;
245-
struct cifs_ses *ses;
246252
bool nodfs = ctx->nodfs;
247253
int rc;
248254

@@ -276,20 +282,8 @@ int dfs_mount_share(struct cifs_mount_ctx *mnt_ctx, bool *isdfs)
276282
}
277283

278284
*isdfs = true;
279-
/*
280-
* Prevent DFS root session of being put in the first call to
281-
* cifs_mount_put_conns(). If another DFS root server was not found
282-
* while chasing the referrals (@ctx->dfs_root_ses == @ses), then we
283-
* can safely put extra refcount of @ses.
284-
*/
285-
ses = mnt_ctx->ses;
286-
mnt_ctx->ses = NULL;
287-
mnt_ctx->server = NULL;
288-
rc = __dfs_mount_share(mnt_ctx);
289-
if (ses == ctx->dfs_root_ses)
290-
cifs_put_smb_ses(ses);
291-
292-
return rc;
285+
add_root_smb_session(mnt_ctx);
286+
return __dfs_mount_share(mnt_ctx);
293287
}
294288

295289
/* Update dfs referral path of superblock */

fs/smb/client/file.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1080,8 +1080,8 @@ int cifs_close(struct inode *inode, struct file *file)
10801080
cfile = file->private_data;
10811081
file->private_data = NULL;
10821082
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 &&
10851085
!test_bit(CIFS_INO_CLOSE_ON_LOCK, &cinode->flags) &&
10861086
dclose) {
10871087
if (test_and_clear_bit(CIFS_INO_MODIFIED_ATTR, &cinode->flags)) {

fs/smb/client/smb2ops.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2395,7 +2395,7 @@ smb2_is_status_io_timeout(char *buf)
23952395
return false;
23962396
}
23972397

2398-
static void
2398+
static bool
23992399
smb2_is_network_name_deleted(char *buf, struct TCP_Server_Info *server)
24002400
{
24012401
struct smb2_hdr *shdr = (struct smb2_hdr *)buf;
@@ -2404,7 +2404,7 @@ smb2_is_network_name_deleted(char *buf, struct TCP_Server_Info *server)
24042404
struct cifs_tcon *tcon;
24052405

24062406
if (shdr->Status != STATUS_NETWORK_NAME_DELETED)
2407-
return;
2407+
return false;
24082408

24092409
/* If server is a channel, select the primary channel */
24102410
pserver = CIFS_SERVER_IS_CHAN(server) ? server->primary_server : server;
@@ -2419,11 +2419,13 @@ smb2_is_network_name_deleted(char *buf, struct TCP_Server_Info *server)
24192419
spin_unlock(&cifs_tcp_ses_lock);
24202420
pr_warn_once("Server share %s deleted.\n",
24212421
tcon->tree_name);
2422-
return;
2422+
return true;
24232423
}
24242424
}
24252425
}
24262426
spin_unlock(&cifs_tcp_ses_lock);
2427+
2428+
return false;
24272429
}
24282430

24292431
static int

fs/smb/client/smb2transport.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ smb2_find_smb_ses_unlocked(struct TCP_Server_Info *server, __u64 ses_id)
160160
spin_unlock(&ses->ses_lock);
161161
continue;
162162
}
163-
++ses->ses_count;
163+
cifs_smb_ses_inc_refcount(ses);
164164
spin_unlock(&ses->ses_lock);
165165
return ses;
166166
}

0 commit comments

Comments
 (0)