diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 50fcb65920e8..fe99fb7307b2 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -504,6 +504,8 @@ struct smb_version_operations { loff_t (*llseek)(struct file *, struct cifs_tcon *, loff_t, int); /* Check for STATUS_IO_TIMEOUT */ bool (*is_status_io_timeout)(char *buf); + /* Check for STATUS_NETWORK_NAME_DELETED */ + void (*mark_tcon_reconnect) (char *buf, struct TCP_Server_Info *); ^^^ Let's follow the above style and name it is_network_name_deleted() }; struct smb_version_values { diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 10fe6d6d2dee..d4ffe2564e07 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -993,6 +993,8 @@ cifs_demultiplex_thread(void *p) if (mids[i] != NULL) { mids[i]->resp_buf_size = server->pdu_size; + server->ops->mark_tcon_reconnect(bufs[i], + server); How about SMB1? It doesn't have the callback, so it may fail here. Btw, I think is_status_io timeout should be called in this loop for every mid not outside the loop (sorry, missed that in the original review). Could you please fix that separately? if (!mids[i]->multiRsp || mids[i]->multiEnd) mids[i]->callback(mids[i]); diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c index f19274857292..23d238c0017a 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c @@ -2418,6 +2418,37 @@ smb2_is_status_io_timeout(char *buf) return false; } +static void +smb2_mark_tcon_reconnect(char *buf, struct TCP_Server_Info *server) +{ + struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf; + struct list_head *tmp, *tmp1; + struct cifs_ses *ses; + struct cifs_tcon *tcon; + bool find_tcon = false; + + spin_lock(&cifs_tcp_ses_lock); + list_for_each(tmp, &server->smb_ses_list) { Why looking for the TCON if in most cases Status is not STATUS_NETWORK_NAME_DELETED? If it is not, then the function should become a no-op and exit immediately. + ses = list_entry(tmp, struct cifs_ses, smb_ses_list); + list_for_each(tmp1, &ses->tcon_list) { + tcon = list_entry(tmp1, struct cifs_tcon, tcon_list); + if (tcon->tid == shdr->TreeId) { + find_tcon = true; + spin_unlock(&cifs_tcp_ses_lock); + goto reconnect; + } + } + } + spin_unlock(&cifs_tcp_ses_lock); + +reconnect: + if (find_tcon && (shdr->Status == STATUS_NETWORK_NAME_DELETED)) { + tcon->need_reconnect = true; this should happen under the locks - there is no guarantee that tcon is still valid outside the loop unless you take a reference which is not needed here. + pr_warn_once("Server share %s deleted.\n", + tcon->treeName); so, just printing logs should happen outside the locks. + } +} + static int smb2_oplock_response(struct cifs_tcon *tcon, struct cifs_fid *fid, struct cifsInodeInfo *cinode) @@ -4605,6 +4636,8 @@ static void smb2_decrypt_offload(struct work_struct *work) #ifdef CONFIG_CIFS_STATS2 mid->when_received = jiffies; #endif + dw->server->ops->mark_tcon_reconnect(dw->buf, + dw->server); mid->callback(mid); } else { spin_lock(&GlobalMid_Lock); @@ -5072,6 +5105,7 @@ struct smb_version_operations smb20_operations = { .fiemap = smb3_fiemap, .llseek = smb3_llseek, .is_status_io_timeout = smb2_is_status_io_timeout, + .mark_tcon_reconnect = smb2_mark_tcon_reconnect, }; struct smb_version_operations smb21_operations = { @@ -5173,6 +5207,7 @@ struct smb_version_operations smb21_operations = { .fiemap = smb3_fiemap, .llseek = smb3_llseek, .is_status_io_timeout = smb2_is_status_io_timeout, + .mark_tcon_reconnect = smb2_mark_tcon_reconnect, }; struct smb_version_operations smb30_operations = { @@ -5286,6 +5321,7 @@ struct smb_version_operations smb30_operations = { .fiemap = smb3_fiemap, .llseek = smb3_llseek, .is_status_io_timeout = smb2_is_status_io_timeout, + .mark_tcon_reconnect = smb2_mark_tcon_reconnect, }; struct smb_version_operations smb311_operations = { @@ -5399,6 +5435,7 @@ struct smb_version_operations smb311_operations = { .fiemap = smb3_fiemap, .llseek = smb3_llseek, .is_status_io_timeout = smb2_is_status_io_timeout, + .mark_tcon_reconnect = smb2_mark_tcon_reconnect, }; struct smb_version_values smb20_values = { -- 2.25.1 -- Best regards, Pavel Shilovsky вт, 16 февр. 2021 г. в 02:54, Rohith <rohiths.msft@xxxxxxxxx>: > > Hi All, > > > > During migration or soft delete/undelete, Application doing recursive IO’s will fail until tcon is reconnected or session is established again. > > > > Attached patch addresses above mentioned issue. So, applications will recover automatically once share is undeleted. > > > > Regards, > > Rohith > > > > Sent from Mail for Windows 10 > >