cifs_swn.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Witness Service client for CIFS
  4. *
  5. * Copyright (c) 2020 Samuel Cabrero <[email protected]>
  6. */
  7. #include <linux/kref.h>
  8. #include <net/genetlink.h>
  9. #include <uapi/linux/cifs/cifs_netlink.h>
  10. #include "cifs_swn.h"
  11. #include "cifsglob.h"
  12. #include "cifsproto.h"
  13. #include "fscache.h"
  14. #include "cifs_debug.h"
  15. #include "netlink.h"
  16. static DEFINE_IDR(cifs_swnreg_idr);
  17. static DEFINE_MUTEX(cifs_swnreg_idr_mutex);
  18. struct cifs_swn_reg {
  19. int id;
  20. struct kref ref_count;
  21. const char *net_name;
  22. const char *share_name;
  23. bool net_name_notify;
  24. bool share_name_notify;
  25. bool ip_notify;
  26. struct cifs_tcon *tcon;
  27. };
  28. static int cifs_swn_auth_info_krb(struct cifs_tcon *tcon, struct sk_buff *skb)
  29. {
  30. int ret;
  31. ret = nla_put_flag(skb, CIFS_GENL_ATTR_SWN_KRB_AUTH);
  32. if (ret < 0)
  33. return ret;
  34. return 0;
  35. }
  36. static int cifs_swn_auth_info_ntlm(struct cifs_tcon *tcon, struct sk_buff *skb)
  37. {
  38. int ret;
  39. if (tcon->ses->user_name != NULL) {
  40. ret = nla_put_string(skb, CIFS_GENL_ATTR_SWN_USER_NAME, tcon->ses->user_name);
  41. if (ret < 0)
  42. return ret;
  43. }
  44. if (tcon->ses->password != NULL) {
  45. ret = nla_put_string(skb, CIFS_GENL_ATTR_SWN_PASSWORD, tcon->ses->password);
  46. if (ret < 0)
  47. return ret;
  48. }
  49. if (tcon->ses->domainName != NULL) {
  50. ret = nla_put_string(skb, CIFS_GENL_ATTR_SWN_DOMAIN_NAME, tcon->ses->domainName);
  51. if (ret < 0)
  52. return ret;
  53. }
  54. return 0;
  55. }
  56. /*
  57. * Sends a register message to the userspace daemon based on the registration.
  58. * The authentication information to connect to the witness service is bundled
  59. * into the message.
  60. */
  61. static int cifs_swn_send_register_message(struct cifs_swn_reg *swnreg)
  62. {
  63. struct sk_buff *skb;
  64. struct genlmsghdr *hdr;
  65. enum securityEnum authtype;
  66. struct sockaddr_storage *addr;
  67. int ret;
  68. skb = genlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
  69. if (skb == NULL) {
  70. ret = -ENOMEM;
  71. goto fail;
  72. }
  73. hdr = genlmsg_put(skb, 0, 0, &cifs_genl_family, 0, CIFS_GENL_CMD_SWN_REGISTER);
  74. if (hdr == NULL) {
  75. ret = -ENOMEM;
  76. goto nlmsg_fail;
  77. }
  78. ret = nla_put_u32(skb, CIFS_GENL_ATTR_SWN_REGISTRATION_ID, swnreg->id);
  79. if (ret < 0)
  80. goto nlmsg_fail;
  81. ret = nla_put_string(skb, CIFS_GENL_ATTR_SWN_NET_NAME, swnreg->net_name);
  82. if (ret < 0)
  83. goto nlmsg_fail;
  84. ret = nla_put_string(skb, CIFS_GENL_ATTR_SWN_SHARE_NAME, swnreg->share_name);
  85. if (ret < 0)
  86. goto nlmsg_fail;
  87. /*
  88. * If there is an address stored use it instead of the server address, because we are
  89. * in the process of reconnecting to it after a share has been moved or we have been
  90. * told to switch to it (client move message). In these cases we unregister from the
  91. * server address and register to the new address when we receive the notification.
  92. */
  93. if (swnreg->tcon->ses->server->use_swn_dstaddr)
  94. addr = &swnreg->tcon->ses->server->swn_dstaddr;
  95. else
  96. addr = &swnreg->tcon->ses->server->dstaddr;
  97. ret = nla_put(skb, CIFS_GENL_ATTR_SWN_IP, sizeof(struct sockaddr_storage), addr);
  98. if (ret < 0)
  99. goto nlmsg_fail;
  100. if (swnreg->net_name_notify) {
  101. ret = nla_put_flag(skb, CIFS_GENL_ATTR_SWN_NET_NAME_NOTIFY);
  102. if (ret < 0)
  103. goto nlmsg_fail;
  104. }
  105. if (swnreg->share_name_notify) {
  106. ret = nla_put_flag(skb, CIFS_GENL_ATTR_SWN_SHARE_NAME_NOTIFY);
  107. if (ret < 0)
  108. goto nlmsg_fail;
  109. }
  110. if (swnreg->ip_notify) {
  111. ret = nla_put_flag(skb, CIFS_GENL_ATTR_SWN_IP_NOTIFY);
  112. if (ret < 0)
  113. goto nlmsg_fail;
  114. }
  115. authtype = cifs_select_sectype(swnreg->tcon->ses->server, swnreg->tcon->ses->sectype);
  116. switch (authtype) {
  117. case Kerberos:
  118. ret = cifs_swn_auth_info_krb(swnreg->tcon, skb);
  119. if (ret < 0) {
  120. cifs_dbg(VFS, "%s: Failed to get kerberos auth info: %d\n", __func__, ret);
  121. goto nlmsg_fail;
  122. }
  123. break;
  124. case NTLMv2:
  125. case RawNTLMSSP:
  126. ret = cifs_swn_auth_info_ntlm(swnreg->tcon, skb);
  127. if (ret < 0) {
  128. cifs_dbg(VFS, "%s: Failed to get NTLM auth info: %d\n", __func__, ret);
  129. goto nlmsg_fail;
  130. }
  131. break;
  132. default:
  133. cifs_dbg(VFS, "%s: secType %d not supported!\n", __func__, authtype);
  134. ret = -EINVAL;
  135. goto nlmsg_fail;
  136. }
  137. genlmsg_end(skb, hdr);
  138. genlmsg_multicast(&cifs_genl_family, skb, 0, CIFS_GENL_MCGRP_SWN, GFP_ATOMIC);
  139. cifs_dbg(FYI, "%s: Message to register for network name %s with id %d sent\n", __func__,
  140. swnreg->net_name, swnreg->id);
  141. return 0;
  142. nlmsg_fail:
  143. genlmsg_cancel(skb, hdr);
  144. nlmsg_free(skb);
  145. fail:
  146. return ret;
  147. }
  148. /*
  149. * Sends an uregister message to the userspace daemon based on the registration
  150. */
  151. static int cifs_swn_send_unregister_message(struct cifs_swn_reg *swnreg)
  152. {
  153. struct sk_buff *skb;
  154. struct genlmsghdr *hdr;
  155. int ret;
  156. skb = genlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
  157. if (skb == NULL)
  158. return -ENOMEM;
  159. hdr = genlmsg_put(skb, 0, 0, &cifs_genl_family, 0, CIFS_GENL_CMD_SWN_UNREGISTER);
  160. if (hdr == NULL) {
  161. ret = -ENOMEM;
  162. goto nlmsg_fail;
  163. }
  164. ret = nla_put_u32(skb, CIFS_GENL_ATTR_SWN_REGISTRATION_ID, swnreg->id);
  165. if (ret < 0)
  166. goto nlmsg_fail;
  167. ret = nla_put_string(skb, CIFS_GENL_ATTR_SWN_NET_NAME, swnreg->net_name);
  168. if (ret < 0)
  169. goto nlmsg_fail;
  170. ret = nla_put_string(skb, CIFS_GENL_ATTR_SWN_SHARE_NAME, swnreg->share_name);
  171. if (ret < 0)
  172. goto nlmsg_fail;
  173. ret = nla_put(skb, CIFS_GENL_ATTR_SWN_IP, sizeof(struct sockaddr_storage),
  174. &swnreg->tcon->ses->server->dstaddr);
  175. if (ret < 0)
  176. goto nlmsg_fail;
  177. if (swnreg->net_name_notify) {
  178. ret = nla_put_flag(skb, CIFS_GENL_ATTR_SWN_NET_NAME_NOTIFY);
  179. if (ret < 0)
  180. goto nlmsg_fail;
  181. }
  182. if (swnreg->share_name_notify) {
  183. ret = nla_put_flag(skb, CIFS_GENL_ATTR_SWN_SHARE_NAME_NOTIFY);
  184. if (ret < 0)
  185. goto nlmsg_fail;
  186. }
  187. if (swnreg->ip_notify) {
  188. ret = nla_put_flag(skb, CIFS_GENL_ATTR_SWN_IP_NOTIFY);
  189. if (ret < 0)
  190. goto nlmsg_fail;
  191. }
  192. genlmsg_end(skb, hdr);
  193. genlmsg_multicast(&cifs_genl_family, skb, 0, CIFS_GENL_MCGRP_SWN, GFP_ATOMIC);
  194. cifs_dbg(FYI, "%s: Message to unregister for network name %s with id %d sent\n", __func__,
  195. swnreg->net_name, swnreg->id);
  196. return 0;
  197. nlmsg_fail:
  198. genlmsg_cancel(skb, hdr);
  199. nlmsg_free(skb);
  200. return ret;
  201. }
  202. /*
  203. * Try to find a matching registration for the tcon's server name and share name.
  204. * Calls to this function must be protected by cifs_swnreg_idr_mutex.
  205. * TODO Try to avoid memory allocations
  206. */
  207. static struct cifs_swn_reg *cifs_find_swn_reg(struct cifs_tcon *tcon)
  208. {
  209. struct cifs_swn_reg *swnreg;
  210. int id;
  211. const char *share_name;
  212. const char *net_name;
  213. net_name = extract_hostname(tcon->tree_name);
  214. if (IS_ERR(net_name)) {
  215. int ret;
  216. ret = PTR_ERR(net_name);
  217. cifs_dbg(VFS, "%s: failed to extract host name from target '%s': %d\n",
  218. __func__, tcon->tree_name, ret);
  219. return ERR_PTR(-EINVAL);
  220. }
  221. share_name = extract_sharename(tcon->tree_name);
  222. if (IS_ERR(share_name)) {
  223. int ret;
  224. ret = PTR_ERR(share_name);
  225. cifs_dbg(VFS, "%s: failed to extract share name from target '%s': %d\n",
  226. __func__, tcon->tree_name, ret);
  227. kfree(net_name);
  228. return ERR_PTR(-EINVAL);
  229. }
  230. idr_for_each_entry(&cifs_swnreg_idr, swnreg, id) {
  231. if (strcasecmp(swnreg->net_name, net_name) != 0
  232. || strcasecmp(swnreg->share_name, share_name) != 0) {
  233. continue;
  234. }
  235. cifs_dbg(FYI, "Existing swn registration for %s:%s found\n", swnreg->net_name,
  236. swnreg->share_name);
  237. kfree(net_name);
  238. kfree(share_name);
  239. return swnreg;
  240. }
  241. kfree(net_name);
  242. kfree(share_name);
  243. return ERR_PTR(-EEXIST);
  244. }
  245. /*
  246. * Get a registration for the tcon's server and share name, allocating a new one if it does not
  247. * exists
  248. */
  249. static struct cifs_swn_reg *cifs_get_swn_reg(struct cifs_tcon *tcon)
  250. {
  251. struct cifs_swn_reg *reg = NULL;
  252. int ret;
  253. mutex_lock(&cifs_swnreg_idr_mutex);
  254. /* Check if we are already registered for this network and share names */
  255. reg = cifs_find_swn_reg(tcon);
  256. if (!IS_ERR(reg)) {
  257. kref_get(&reg->ref_count);
  258. mutex_unlock(&cifs_swnreg_idr_mutex);
  259. return reg;
  260. } else if (PTR_ERR(reg) != -EEXIST) {
  261. mutex_unlock(&cifs_swnreg_idr_mutex);
  262. return reg;
  263. }
  264. reg = kmalloc(sizeof(struct cifs_swn_reg), GFP_ATOMIC);
  265. if (reg == NULL) {
  266. mutex_unlock(&cifs_swnreg_idr_mutex);
  267. return ERR_PTR(-ENOMEM);
  268. }
  269. kref_init(&reg->ref_count);
  270. reg->id = idr_alloc(&cifs_swnreg_idr, reg, 1, 0, GFP_ATOMIC);
  271. if (reg->id < 0) {
  272. cifs_dbg(FYI, "%s: failed to allocate registration id\n", __func__);
  273. ret = reg->id;
  274. goto fail;
  275. }
  276. reg->net_name = extract_hostname(tcon->tree_name);
  277. if (IS_ERR(reg->net_name)) {
  278. ret = PTR_ERR(reg->net_name);
  279. cifs_dbg(VFS, "%s: failed to extract host name from target: %d\n", __func__, ret);
  280. goto fail_idr;
  281. }
  282. reg->share_name = extract_sharename(tcon->tree_name);
  283. if (IS_ERR(reg->share_name)) {
  284. ret = PTR_ERR(reg->share_name);
  285. cifs_dbg(VFS, "%s: failed to extract share name from target: %d\n", __func__, ret);
  286. goto fail_net_name;
  287. }
  288. reg->net_name_notify = true;
  289. reg->share_name_notify = true;
  290. reg->ip_notify = (tcon->capabilities & SMB2_SHARE_CAP_SCALEOUT);
  291. reg->tcon = tcon;
  292. mutex_unlock(&cifs_swnreg_idr_mutex);
  293. return reg;
  294. fail_net_name:
  295. kfree(reg->net_name);
  296. fail_idr:
  297. idr_remove(&cifs_swnreg_idr, reg->id);
  298. fail:
  299. kfree(reg);
  300. mutex_unlock(&cifs_swnreg_idr_mutex);
  301. return ERR_PTR(ret);
  302. }
  303. static void cifs_swn_reg_release(struct kref *ref)
  304. {
  305. struct cifs_swn_reg *swnreg = container_of(ref, struct cifs_swn_reg, ref_count);
  306. int ret;
  307. ret = cifs_swn_send_unregister_message(swnreg);
  308. if (ret < 0)
  309. cifs_dbg(VFS, "%s: Failed to send unregister message: %d\n", __func__, ret);
  310. idr_remove(&cifs_swnreg_idr, swnreg->id);
  311. kfree(swnreg->net_name);
  312. kfree(swnreg->share_name);
  313. kfree(swnreg);
  314. }
  315. static void cifs_put_swn_reg(struct cifs_swn_reg *swnreg)
  316. {
  317. mutex_lock(&cifs_swnreg_idr_mutex);
  318. kref_put(&swnreg->ref_count, cifs_swn_reg_release);
  319. mutex_unlock(&cifs_swnreg_idr_mutex);
  320. }
  321. static int cifs_swn_resource_state_changed(struct cifs_swn_reg *swnreg, const char *name, int state)
  322. {
  323. switch (state) {
  324. case CIFS_SWN_RESOURCE_STATE_UNAVAILABLE:
  325. cifs_dbg(FYI, "%s: resource name '%s' become unavailable\n", __func__, name);
  326. cifs_signal_cifsd_for_reconnect(swnreg->tcon->ses->server, true);
  327. break;
  328. case CIFS_SWN_RESOURCE_STATE_AVAILABLE:
  329. cifs_dbg(FYI, "%s: resource name '%s' become available\n", __func__, name);
  330. cifs_signal_cifsd_for_reconnect(swnreg->tcon->ses->server, true);
  331. break;
  332. case CIFS_SWN_RESOURCE_STATE_UNKNOWN:
  333. cifs_dbg(FYI, "%s: resource name '%s' changed to unknown state\n", __func__, name);
  334. break;
  335. }
  336. return 0;
  337. }
  338. static bool cifs_sockaddr_equal(struct sockaddr_storage *addr1, struct sockaddr_storage *addr2)
  339. {
  340. if (addr1->ss_family != addr2->ss_family)
  341. return false;
  342. if (addr1->ss_family == AF_INET) {
  343. return (memcmp(&((const struct sockaddr_in *)addr1)->sin_addr,
  344. &((const struct sockaddr_in *)addr2)->sin_addr,
  345. sizeof(struct in_addr)) == 0);
  346. }
  347. if (addr1->ss_family == AF_INET6) {
  348. return (memcmp(&((const struct sockaddr_in6 *)addr1)->sin6_addr,
  349. &((const struct sockaddr_in6 *)addr2)->sin6_addr,
  350. sizeof(struct in6_addr)) == 0);
  351. }
  352. return false;
  353. }
  354. static int cifs_swn_store_swn_addr(const struct sockaddr_storage *new,
  355. const struct sockaddr_storage *old,
  356. struct sockaddr_storage *dst)
  357. {
  358. __be16 port = cpu_to_be16(CIFS_PORT);
  359. if (old->ss_family == AF_INET) {
  360. struct sockaddr_in *ipv4 = (struct sockaddr_in *)old;
  361. port = ipv4->sin_port;
  362. } else if (old->ss_family == AF_INET6) {
  363. struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)old;
  364. port = ipv6->sin6_port;
  365. }
  366. if (new->ss_family == AF_INET) {
  367. struct sockaddr_in *ipv4 = (struct sockaddr_in *)new;
  368. ipv4->sin_port = port;
  369. } else if (new->ss_family == AF_INET6) {
  370. struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)new;
  371. ipv6->sin6_port = port;
  372. }
  373. *dst = *new;
  374. return 0;
  375. }
  376. static int cifs_swn_reconnect(struct cifs_tcon *tcon, struct sockaddr_storage *addr)
  377. {
  378. int ret = 0;
  379. /* Store the reconnect address */
  380. cifs_server_lock(tcon->ses->server);
  381. if (cifs_sockaddr_equal(&tcon->ses->server->dstaddr, addr))
  382. goto unlock;
  383. ret = cifs_swn_store_swn_addr(addr, &tcon->ses->server->dstaddr,
  384. &tcon->ses->server->swn_dstaddr);
  385. if (ret < 0) {
  386. cifs_dbg(VFS, "%s: failed to store address: %d\n", __func__, ret);
  387. goto unlock;
  388. }
  389. tcon->ses->server->use_swn_dstaddr = true;
  390. /*
  391. * Unregister to stop receiving notifications for the old IP address.
  392. */
  393. ret = cifs_swn_unregister(tcon);
  394. if (ret < 0) {
  395. cifs_dbg(VFS, "%s: Failed to unregister for witness notifications: %d\n",
  396. __func__, ret);
  397. goto unlock;
  398. }
  399. /*
  400. * And register to receive notifications for the new IP address now that we have
  401. * stored the new address.
  402. */
  403. ret = cifs_swn_register(tcon);
  404. if (ret < 0) {
  405. cifs_dbg(VFS, "%s: Failed to register for witness notifications: %d\n",
  406. __func__, ret);
  407. goto unlock;
  408. }
  409. cifs_signal_cifsd_for_reconnect(tcon->ses->server, false);
  410. unlock:
  411. cifs_server_unlock(tcon->ses->server);
  412. return ret;
  413. }
  414. static int cifs_swn_client_move(struct cifs_swn_reg *swnreg, struct sockaddr_storage *addr)
  415. {
  416. struct sockaddr_in *ipv4 = (struct sockaddr_in *)addr;
  417. struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)addr;
  418. if (addr->ss_family == AF_INET)
  419. cifs_dbg(FYI, "%s: move to %pI4\n", __func__, &ipv4->sin_addr);
  420. else if (addr->ss_family == AF_INET6)
  421. cifs_dbg(FYI, "%s: move to %pI6\n", __func__, &ipv6->sin6_addr);
  422. return cifs_swn_reconnect(swnreg->tcon, addr);
  423. }
  424. int cifs_swn_notify(struct sk_buff *skb, struct genl_info *info)
  425. {
  426. struct cifs_swn_reg *swnreg;
  427. char name[256];
  428. int type;
  429. if (info->attrs[CIFS_GENL_ATTR_SWN_REGISTRATION_ID]) {
  430. int swnreg_id;
  431. swnreg_id = nla_get_u32(info->attrs[CIFS_GENL_ATTR_SWN_REGISTRATION_ID]);
  432. mutex_lock(&cifs_swnreg_idr_mutex);
  433. swnreg = idr_find(&cifs_swnreg_idr, swnreg_id);
  434. mutex_unlock(&cifs_swnreg_idr_mutex);
  435. if (swnreg == NULL) {
  436. cifs_dbg(FYI, "%s: registration id %d not found\n", __func__, swnreg_id);
  437. return -EINVAL;
  438. }
  439. } else {
  440. cifs_dbg(FYI, "%s: missing registration id attribute\n", __func__);
  441. return -EINVAL;
  442. }
  443. if (info->attrs[CIFS_GENL_ATTR_SWN_NOTIFICATION_TYPE]) {
  444. type = nla_get_u32(info->attrs[CIFS_GENL_ATTR_SWN_NOTIFICATION_TYPE]);
  445. } else {
  446. cifs_dbg(FYI, "%s: missing notification type attribute\n", __func__);
  447. return -EINVAL;
  448. }
  449. switch (type) {
  450. case CIFS_SWN_NOTIFICATION_RESOURCE_CHANGE: {
  451. int state;
  452. if (info->attrs[CIFS_GENL_ATTR_SWN_RESOURCE_NAME]) {
  453. nla_strscpy(name, info->attrs[CIFS_GENL_ATTR_SWN_RESOURCE_NAME],
  454. sizeof(name));
  455. } else {
  456. cifs_dbg(FYI, "%s: missing resource name attribute\n", __func__);
  457. return -EINVAL;
  458. }
  459. if (info->attrs[CIFS_GENL_ATTR_SWN_RESOURCE_STATE]) {
  460. state = nla_get_u32(info->attrs[CIFS_GENL_ATTR_SWN_RESOURCE_STATE]);
  461. } else {
  462. cifs_dbg(FYI, "%s: missing resource state attribute\n", __func__);
  463. return -EINVAL;
  464. }
  465. return cifs_swn_resource_state_changed(swnreg, name, state);
  466. }
  467. case CIFS_SWN_NOTIFICATION_CLIENT_MOVE: {
  468. struct sockaddr_storage addr;
  469. if (info->attrs[CIFS_GENL_ATTR_SWN_IP]) {
  470. nla_memcpy(&addr, info->attrs[CIFS_GENL_ATTR_SWN_IP], sizeof(addr));
  471. } else {
  472. cifs_dbg(FYI, "%s: missing IP address attribute\n", __func__);
  473. return -EINVAL;
  474. }
  475. return cifs_swn_client_move(swnreg, &addr);
  476. }
  477. default:
  478. cifs_dbg(FYI, "%s: unknown notification type %d\n", __func__, type);
  479. break;
  480. }
  481. return 0;
  482. }
  483. int cifs_swn_register(struct cifs_tcon *tcon)
  484. {
  485. struct cifs_swn_reg *swnreg;
  486. int ret;
  487. swnreg = cifs_get_swn_reg(tcon);
  488. if (IS_ERR(swnreg))
  489. return PTR_ERR(swnreg);
  490. ret = cifs_swn_send_register_message(swnreg);
  491. if (ret < 0) {
  492. cifs_dbg(VFS, "%s: Failed to send swn register message: %d\n", __func__, ret);
  493. /* Do not put the swnreg or return error, the echo task will retry */
  494. }
  495. return 0;
  496. }
  497. int cifs_swn_unregister(struct cifs_tcon *tcon)
  498. {
  499. struct cifs_swn_reg *swnreg;
  500. mutex_lock(&cifs_swnreg_idr_mutex);
  501. swnreg = cifs_find_swn_reg(tcon);
  502. if (IS_ERR(swnreg)) {
  503. mutex_unlock(&cifs_swnreg_idr_mutex);
  504. return PTR_ERR(swnreg);
  505. }
  506. mutex_unlock(&cifs_swnreg_idr_mutex);
  507. cifs_put_swn_reg(swnreg);
  508. return 0;
  509. }
  510. void cifs_swn_dump(struct seq_file *m)
  511. {
  512. struct cifs_swn_reg *swnreg;
  513. struct sockaddr_in *sa;
  514. struct sockaddr_in6 *sa6;
  515. int id;
  516. seq_puts(m, "Witness registrations:");
  517. mutex_lock(&cifs_swnreg_idr_mutex);
  518. idr_for_each_entry(&cifs_swnreg_idr, swnreg, id) {
  519. seq_printf(m, "\nId: %u Refs: %u Network name: '%s'%s Share name: '%s'%s Ip address: ",
  520. id, kref_read(&swnreg->ref_count),
  521. swnreg->net_name, swnreg->net_name_notify ? "(y)" : "(n)",
  522. swnreg->share_name, swnreg->share_name_notify ? "(y)" : "(n)");
  523. switch (swnreg->tcon->ses->server->dstaddr.ss_family) {
  524. case AF_INET:
  525. sa = (struct sockaddr_in *) &swnreg->tcon->ses->server->dstaddr;
  526. seq_printf(m, "%pI4", &sa->sin_addr.s_addr);
  527. break;
  528. case AF_INET6:
  529. sa6 = (struct sockaddr_in6 *) &swnreg->tcon->ses->server->dstaddr;
  530. seq_printf(m, "%pI6", &sa6->sin6_addr.s6_addr);
  531. if (sa6->sin6_scope_id)
  532. seq_printf(m, "%%%u", sa6->sin6_scope_id);
  533. break;
  534. default:
  535. seq_puts(m, "(unknown)");
  536. }
  537. seq_printf(m, "%s", swnreg->ip_notify ? "(y)" : "(n)");
  538. }
  539. mutex_unlock(&cifs_swnreg_idr_mutex);
  540. seq_puts(m, "\n");
  541. }
  542. void cifs_swn_check(void)
  543. {
  544. struct cifs_swn_reg *swnreg;
  545. int id;
  546. int ret;
  547. mutex_lock(&cifs_swnreg_idr_mutex);
  548. idr_for_each_entry(&cifs_swnreg_idr, swnreg, id) {
  549. ret = cifs_swn_send_register_message(swnreg);
  550. if (ret < 0)
  551. cifs_dbg(FYI, "%s: Failed to send register message: %d\n", __func__, ret);
  552. }
  553. mutex_unlock(&cifs_swnreg_idr_mutex);
  554. }