|
14 | 14 | #include "cifspdu.h"
|
15 | 15 | #include "cifs_unicode.h"
|
16 | 16 | #include "fs_context.h"
|
| 17 | +#include "nterr.h" |
| 18 | +#include "smberr.h" |
17 | 19 |
|
18 | 20 | /*
|
19 | 21 | * 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,
|
1062 | 1064 | full_path, mode, dev);
|
1063 | 1065 | }
|
1064 | 1066 |
|
| 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 | + |
1065 | 1108 | struct smb_version_operations smb1_operations = {
|
1066 | 1109 | .send_cancel = send_nt_cancel,
|
1067 | 1110 | .compare_fids = cifs_compare_fids,
|
@@ -1146,6 +1189,7 @@ struct smb_version_operations smb1_operations = {
|
1146 | 1189 | .get_acl_by_fid = get_cifs_acl_by_fid,
|
1147 | 1190 | .set_acl = set_cifs_acl,
|
1148 | 1191 | .make_node = cifs_make_node,
|
| 1192 | + .is_network_name_deleted = cifs_is_network_name_deleted, |
1149 | 1193 | };
|
1150 | 1194 |
|
1151 | 1195 | struct smb_version_values smb1_values = {
|
|
0 commit comments