Blob Blame History Raw
From: Steve French <stfrench@microsoft.com>
Date: Wed, 11 Sep 2019 00:07:36 -0500
Subject: [PATCH] smb3: improve handling of share deleted (and share recreated)
Git-commit: 7dcc82c2dfd5f12eba19d19d39c50bff70b4f94a
References: bsc#1154355
Patch-mainline: v5.4-rc1

When a share is deleted, returning EIO is confusing and no useful
information is logged.  Improve the handling of this case by
at least logging a better error for this (and also mapping the error
differently to EREMCHG).  See e.g. the new messages that would be logged:

[55243.639530] server share \\192.168.1.219\scratch deleted
[55243.642568] CIFS VFS: \\192.168.1.219\scratch BAD_NETWORK_NAME: \\192.168.1.219\scratch

In addition for the case where a share is deleted and then recreated
with the same name, have now fixed that so it works. This is sometimes
done for example, because the admin had to move a share to a different,
bigger local drive when a share is running low on space.

Signed-off-by: Steve French <stfrench@microsoft.com>
Reviewed-by: Ronnie Sahlberg <lsahlber@redhat.com>
Acked-by: Aurelien Aptel <aaptel@suse.com>
---
 fs/cifs/smb2inode.c    |    6 ++++++
 fs/cifs/smb2maperror.c |    2 +-
 fs/cifs/smb2ops.c      |   13 ++++++++++++-
 fs/cifs/smb2pdu.c      |    5 +++++
 4 files changed, 24 insertions(+), 2 deletions(-)

--- a/fs/cifs/smb2inode.c
+++ b/fs/cifs/smb2inode.c
@@ -304,6 +304,12 @@ smb2_compound_op(const unsigned int xid,
 		cifsFileInfo_put(cfile);
 
 	SMB2_open_free(&rqst[0]);
+	if (rc == -EREMCHG) {
+		printk_once(KERN_WARNING "server share %s deleted\n",
+			    tcon->treeName);
+		tcon->need_reconnect = true;
+	}
+
 	switch (command) {
 	case SMB2_OP_QUERY_INFO:
 		if (rc == 0) {
--- a/fs/cifs/smb2maperror.c
+++ b/fs/cifs/smb2maperror.c
@@ -511,7 +511,7 @@ static const struct status_to_posix_erro
 	{STATUS_PRINT_QUEUE_FULL, -EIO, "STATUS_PRINT_QUEUE_FULL"},
 	{STATUS_NO_SPOOL_SPACE, -EIO, "STATUS_NO_SPOOL_SPACE"},
 	{STATUS_PRINT_CANCELLED, -EIO, "STATUS_PRINT_CANCELLED"},
-	{STATUS_NETWORK_NAME_DELETED, -EIO, "STATUS_NETWORK_NAME_DELETED"},
+	{STATUS_NETWORK_NAME_DELETED, -EREMCHG, "STATUS_NETWORK_NAME_DELETED"},
 	{STATUS_NETWORK_ACCESS_DENIED, -EACCES, "STATUS_NETWORK_ACCESS_DENIED"},
 	{STATUS_BAD_DEVICE_TYPE, -EIO, "STATUS_BAD_DEVICE_TYPE"},
 	{STATUS_BAD_NETWORK_NAME, -ENOENT, "STATUS_BAD_NETWORK_NAME"},
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -739,8 +739,14 @@ int open_shroot(unsigned int xid, struct
 
 	/* Cached root is still invalid, continue normaly */
 
-	if (rc)
+	if (rc) {
+		if (rc == -EREMCHG) {
+			tcon->need_reconnect = true;
+			printk_once(KERN_WARNING "server share %s deleted\n",
+				    tcon->treeName);
+		}
 		goto oshr_exit;
+	}
 
 	o_rsp = (struct smb2_create_rsp *)rsp_iov[0].iov_base;
 	oparms.fid->persistent_fid = o_rsp->PersistentFileId;
@@ -2214,6 +2220,11 @@ smb2_query_info_compound(const unsigned
 				resp_buftype, rsp_iov);
 	if (rc) {
 		free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base);
+		if (rc == -EREMCHG) {
+			tcon->need_reconnect = true;
+			printk_once(KERN_WARNING "server share %s deleted\n",
+				    tcon->treeName);
+		}
 		goto qic_exit;
 	}
 	*rsp = rsp_iov[1];
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -2593,6 +2593,11 @@ SMB2_open(const unsigned int xid, struct
 		}
 		trace_smb3_open_err(xid, tcon->tid, ses->Suid,
 				    oparms->create_options, oparms->desired_access, rc);
+		if (rc == -EREMCHG) {
+			printk_once(KERN_WARNING "server share %s deleted\n",
+				    tcon->treeName);
+			tcon->need_reconnect = true;
+		}
 		goto creat_exit;
 	} else
 		trace_smb3_open_done(xid, rsp->PersistentFileId, tcon->tid,