Re: TCON reconnect during STATUS_NETWORK_NAME_DELETED

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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
>
>




[Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux