Signed-off-by: Stefan Metzmacher <metze@xxxxxxxxx> --- fs/cifs/connect.c | 72 +++++++++++++++++++++++++++++++++++++++++++++ fs/cifs/smb2pdu.c | 72 --------------------------------------------- fs/cifs/smb2proto.h | 1 - 3 files changed, 72 insertions(+), 73 deletions(-) diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 6eca37924d9e..7f4be85b7cc9 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -714,6 +714,78 @@ cifs_echo_request(struct work_struct *work) queue_delayed_work(cifsiod_wq, &server->echo, server->echo_interval); } +static void cifs_reconnect_tcons(struct work_struct *work) +{ + struct TCP_Server_Info *server = container_of(work, + struct TCP_Server_Info, reconnect.work); + struct cifs_ses *ses; + struct cifs_tcon *tcon, *tcon2; + struct list_head tmp_list; + int tcon_exist = false; + int rc; + int resched = false; + + + /* Prevent simultaneous reconnects that can corrupt tcon->rlist list */ + mutex_lock(&server->reconnect_mutex); + + INIT_LIST_HEAD(&tmp_list); + cifs_dbg(FYI, "Need negotiate, reconnecting tcons\n"); + + spin_lock(&cifs_tcp_ses_lock); + list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) { + list_for_each_entry(tcon, &ses->tcon_list, tcon_list) { + if (tcon->need_reconnect || tcon->need_reopen_files) { + tcon->tc_count++; + list_add_tail(&tcon->rlist, &tmp_list); + tcon_exist = true; + } + } + /* + * IPC has the same lifetime as its session and uses its + * refcount. + */ + if (ses->tcon_ipc && ses->tcon_ipc->need_reconnect) { + list_add_tail(&ses->tcon_ipc->rlist, &tmp_list); + tcon_exist = true; + ses->ses_count++; + } + } + /* + * Get the reference to server struct to be sure that the last call of + * cifs_put_tcon() in the loop below won't release the server pointer. + */ + if (tcon_exist) + server->srv_count++; + + spin_unlock(&cifs_tcp_ses_lock); + + list_for_each_entry_safe(tcon, tcon2, &tmp_list, rlist) { + struct cifs_tcon_reconnect_params params = { + .start_timer = false, + }; + rc = cifs_tcon_reconnect(tcon, ¶ms); + if (!rc) + cifs_reopen_persistent_handles(tcon); + else + resched = true; + list_del_init(&tcon->rlist); + if (tcon->ipc) + cifs_put_smb_ses(tcon->ses); + else + cifs_put_tcon(tcon); + } + + cifs_dbg(FYI, "Reconnecting tcons finished\n"); + if (resched) + queue_delayed_work(cifsiod_wq, &server->reconnect, 2 * HZ); + mutex_unlock(&server->reconnect_mutex); + + /* now we can safely release srv struct */ + if (tcon_exist) + cifs_put_tcp_session(server, 1); +} + static bool allocate_buffers(struct TCP_Server_Info *server) { diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index 6f3c5eb62d51..b4446ecf4e97 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c @@ -3290,78 +3290,6 @@ smb2_echo_callback(struct mid_q_entry *mid) add_credits(server, &credits, CIFS_ECHO_OP); } -void cifs_reconnect_tcons(struct work_struct *work) -{ - struct TCP_Server_Info *server = container_of(work, - struct TCP_Server_Info, reconnect.work); - struct cifs_ses *ses; - struct cifs_tcon *tcon, *tcon2; - struct list_head tmp_list; - int tcon_exist = false; - int rc; - int resched = false; - - - /* Prevent simultaneous reconnects that can corrupt tcon->rlist list */ - mutex_lock(&server->reconnect_mutex); - - INIT_LIST_HEAD(&tmp_list); - cifs_dbg(FYI, "Need negotiate, reconnecting tcons\n"); - - spin_lock(&cifs_tcp_ses_lock); - list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) { - list_for_each_entry(tcon, &ses->tcon_list, tcon_list) { - if (tcon->need_reconnect || tcon->need_reopen_files) { - tcon->tc_count++; - list_add_tail(&tcon->rlist, &tmp_list); - tcon_exist = true; - } - } - /* - * IPC has the same lifetime as its session and uses its - * refcount. - */ - if (ses->tcon_ipc && ses->tcon_ipc->need_reconnect) { - list_add_tail(&ses->tcon_ipc->rlist, &tmp_list); - tcon_exist = true; - ses->ses_count++; - } - } - /* - * Get the reference to server struct to be sure that the last call of - * cifs_put_tcon() in the loop below won't release the server pointer. - */ - if (tcon_exist) - server->srv_count++; - - spin_unlock(&cifs_tcp_ses_lock); - - list_for_each_entry_safe(tcon, tcon2, &tmp_list, rlist) { - struct cifs_tcon_reconnect_params params = { - .start_timer = false, - }; - rc = cifs_tcon_reconnect(tcon, ¶ms); - if (!rc) - cifs_reopen_persistent_handles(tcon); - else - resched = true; - list_del_init(&tcon->rlist); - if (tcon->ipc) - cifs_put_smb_ses(tcon->ses); - else - cifs_put_tcon(tcon); - } - - cifs_dbg(FYI, "Reconnecting tcons finished\n"); - if (resched) - queue_delayed_work(cifsiod_wq, &server->reconnect, 2 * HZ); - mutex_unlock(&server->reconnect_mutex); - - /* now we can safely release srv struct */ - if (tcon_exist) - cifs_put_tcp_session(server, 1); -} - int SMB2_echo(struct TCP_Server_Info *server) { diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h index c52be13a374a..fbceb62d355d 100644 --- a/fs/cifs/smb2proto.h +++ b/fs/cifs/smb2proto.h @@ -116,7 +116,6 @@ extern int smb2_open_file(const unsigned int xid, extern int smb2_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock, const unsigned int xid); extern int smb2_push_mandatory_locks(struct cifsFileInfo *cfile); -extern void cifs_reconnect_tcons(struct work_struct *work); extern int smb3_crypto_aead_allocate(struct TCP_Server_Info *server); extern unsigned long smb_rqst_len(struct TCP_Server_Info *server, struct smb_rqst *rqst); -- 2.17.1