Skip to content

Commit 28753e4

Browse files
paliSteve French
authored andcommitted
cifs: Implement is_network_name_deleted for SMB1
This change allows Linux SMB1 client to autoreconnect the share when it is modified on server by admin operation which removes and re-adds it. Implementation is reused from SMB2+ is_network_name_deleted callback. There are just adjusted checks for error codes and access to struct smb_hdr. Signed-off-by: Pali Rohár <pali@kernel.org> Signed-off-by: Steve French <stfrench@microsoft.com>
1 parent f83e10a commit 28753e4

File tree

1 file changed

+44
-0
lines changed

1 file changed

+44
-0
lines changed

fs/smb/client/smb1ops.c

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
#include "cifspdu.h"
1515
#include "cifs_unicode.h"
1616
#include "fs_context.h"
17+
#include "nterr.h"
18+
#include "smberr.h"
1719

1820
/*
1921
* An NT cancel request header looks just like the original request except:
@@ -1062,6 +1064,47 @@ cifs_make_node(unsigned int xid, struct inode *inode,
10621064
full_path, mode, dev);
10631065
}
10641066

1067+
static bool
1068+
cifs_is_network_name_deleted(char *buf, struct TCP_Server_Info *server)
1069+
{
1070+
struct smb_hdr *shdr = (struct smb_hdr *)buf;
1071+
struct TCP_Server_Info *pserver;
1072+
struct cifs_ses *ses;
1073+
struct cifs_tcon *tcon;
1074+
1075+
if (shdr->Flags2 & SMBFLG2_ERR_STATUS) {
1076+
if (shdr->Status.CifsError != cpu_to_le32(NT_STATUS_NETWORK_NAME_DELETED))
1077+
return false;
1078+
} else {
1079+
if (shdr->Status.DosError.ErrorClass != ERRSRV ||
1080+
shdr->Status.DosError.Error != cpu_to_le16(ERRinvtid))
1081+
return false;
1082+
}
1083+
1084+
/* If server is a channel, select the primary channel */
1085+
pserver = SERVER_IS_CHAN(server) ? server->primary_server : server;
1086+
1087+
spin_lock(&cifs_tcp_ses_lock);
1088+
list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) {
1089+
if (cifs_ses_exiting(ses))
1090+
continue;
1091+
list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
1092+
if (tcon->tid == shdr->Tid) {
1093+
spin_lock(&tcon->tc_lock);
1094+
tcon->need_reconnect = true;
1095+
spin_unlock(&tcon->tc_lock);
1096+
spin_unlock(&cifs_tcp_ses_lock);
1097+
pr_warn_once("Server share %s deleted.\n",
1098+
tcon->tree_name);
1099+
return true;
1100+
}
1101+
}
1102+
}
1103+
spin_unlock(&cifs_tcp_ses_lock);
1104+
1105+
return false;
1106+
}
1107+
10651108
struct smb_version_operations smb1_operations = {
10661109
.send_cancel = send_nt_cancel,
10671110
.compare_fids = cifs_compare_fids,
@@ -1146,6 +1189,7 @@ struct smb_version_operations smb1_operations = {
11461189
.get_acl_by_fid = get_cifs_acl_by_fid,
11471190
.set_acl = set_cifs_acl,
11481191
.make_node = cifs_make_node,
1192+
.is_network_name_deleted = cifs_is_network_name_deleted,
11491193
};
11501194

11511195
struct smb_version_values smb1_values = {

0 commit comments

Comments
 (0)