Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Witness Service client for CIFS
0004  *
0005  * Copyright (c) 2020 Samuel Cabrero <scabrero@suse.de>
0006  */
0007 
0008 #include <linux/kref.h>
0009 #include <net/genetlink.h>
0010 #include <uapi/linux/cifs/cifs_netlink.h>
0011 
0012 #include "cifs_swn.h"
0013 #include "cifsglob.h"
0014 #include "cifsproto.h"
0015 #include "fscache.h"
0016 #include "cifs_debug.h"
0017 #include "netlink.h"
0018 
0019 static DEFINE_IDR(cifs_swnreg_idr);
0020 static DEFINE_MUTEX(cifs_swnreg_idr_mutex);
0021 
0022 struct cifs_swn_reg {
0023     int id;
0024     struct kref ref_count;
0025 
0026     const char *net_name;
0027     const char *share_name;
0028     bool net_name_notify;
0029     bool share_name_notify;
0030     bool ip_notify;
0031 
0032     struct cifs_tcon *tcon;
0033 };
0034 
0035 static int cifs_swn_auth_info_krb(struct cifs_tcon *tcon, struct sk_buff *skb)
0036 {
0037     int ret;
0038 
0039     ret = nla_put_flag(skb, CIFS_GENL_ATTR_SWN_KRB_AUTH);
0040     if (ret < 0)
0041         return ret;
0042 
0043     return 0;
0044 }
0045 
0046 static int cifs_swn_auth_info_ntlm(struct cifs_tcon *tcon, struct sk_buff *skb)
0047 {
0048     int ret;
0049 
0050     if (tcon->ses->user_name != NULL) {
0051         ret = nla_put_string(skb, CIFS_GENL_ATTR_SWN_USER_NAME, tcon->ses->user_name);
0052         if (ret < 0)
0053             return ret;
0054     }
0055 
0056     if (tcon->ses->password != NULL) {
0057         ret = nla_put_string(skb, CIFS_GENL_ATTR_SWN_PASSWORD, tcon->ses->password);
0058         if (ret < 0)
0059             return ret;
0060     }
0061 
0062     if (tcon->ses->domainName != NULL) {
0063         ret = nla_put_string(skb, CIFS_GENL_ATTR_SWN_DOMAIN_NAME, tcon->ses->domainName);
0064         if (ret < 0)
0065             return ret;
0066     }
0067 
0068     return 0;
0069 }
0070 
0071 /*
0072  * Sends a register message to the userspace daemon based on the registration.
0073  * The authentication information to connect to the witness service is bundled
0074  * into the message.
0075  */
0076 static int cifs_swn_send_register_message(struct cifs_swn_reg *swnreg)
0077 {
0078     struct sk_buff *skb;
0079     struct genlmsghdr *hdr;
0080     enum securityEnum authtype;
0081     struct sockaddr_storage *addr;
0082     int ret;
0083 
0084     skb = genlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
0085     if (skb == NULL) {
0086         ret = -ENOMEM;
0087         goto fail;
0088     }
0089 
0090     hdr = genlmsg_put(skb, 0, 0, &cifs_genl_family, 0, CIFS_GENL_CMD_SWN_REGISTER);
0091     if (hdr == NULL) {
0092         ret = -ENOMEM;
0093         goto nlmsg_fail;
0094     }
0095 
0096     ret = nla_put_u32(skb, CIFS_GENL_ATTR_SWN_REGISTRATION_ID, swnreg->id);
0097     if (ret < 0)
0098         goto nlmsg_fail;
0099 
0100     ret = nla_put_string(skb, CIFS_GENL_ATTR_SWN_NET_NAME, swnreg->net_name);
0101     if (ret < 0)
0102         goto nlmsg_fail;
0103 
0104     ret = nla_put_string(skb, CIFS_GENL_ATTR_SWN_SHARE_NAME, swnreg->share_name);
0105     if (ret < 0)
0106         goto nlmsg_fail;
0107 
0108     /*
0109      * If there is an address stored use it instead of the server address, because we are
0110      * in the process of reconnecting to it after a share has been moved or we have been
0111      * told to switch to it (client move message). In these cases we unregister from the
0112      * server address and register to the new address when we receive the notification.
0113      */
0114     if (swnreg->tcon->ses->server->use_swn_dstaddr)
0115         addr = &swnreg->tcon->ses->server->swn_dstaddr;
0116     else
0117         addr = &swnreg->tcon->ses->server->dstaddr;
0118 
0119     ret = nla_put(skb, CIFS_GENL_ATTR_SWN_IP, sizeof(struct sockaddr_storage), addr);
0120     if (ret < 0)
0121         goto nlmsg_fail;
0122 
0123     if (swnreg->net_name_notify) {
0124         ret = nla_put_flag(skb, CIFS_GENL_ATTR_SWN_NET_NAME_NOTIFY);
0125         if (ret < 0)
0126             goto nlmsg_fail;
0127     }
0128 
0129     if (swnreg->share_name_notify) {
0130         ret = nla_put_flag(skb, CIFS_GENL_ATTR_SWN_SHARE_NAME_NOTIFY);
0131         if (ret < 0)
0132             goto nlmsg_fail;
0133     }
0134 
0135     if (swnreg->ip_notify) {
0136         ret = nla_put_flag(skb, CIFS_GENL_ATTR_SWN_IP_NOTIFY);
0137         if (ret < 0)
0138             goto nlmsg_fail;
0139     }
0140 
0141     authtype = cifs_select_sectype(swnreg->tcon->ses->server, swnreg->tcon->ses->sectype);
0142     switch (authtype) {
0143     case Kerberos:
0144         ret = cifs_swn_auth_info_krb(swnreg->tcon, skb);
0145         if (ret < 0) {
0146             cifs_dbg(VFS, "%s: Failed to get kerberos auth info: %d\n", __func__, ret);
0147             goto nlmsg_fail;
0148         }
0149         break;
0150     case NTLMv2:
0151     case RawNTLMSSP:
0152         ret = cifs_swn_auth_info_ntlm(swnreg->tcon, skb);
0153         if (ret < 0) {
0154             cifs_dbg(VFS, "%s: Failed to get NTLM auth info: %d\n", __func__, ret);
0155             goto nlmsg_fail;
0156         }
0157         break;
0158     default:
0159         cifs_dbg(VFS, "%s: secType %d not supported!\n", __func__, authtype);
0160         ret = -EINVAL;
0161         goto nlmsg_fail;
0162     }
0163 
0164     genlmsg_end(skb, hdr);
0165     genlmsg_multicast(&cifs_genl_family, skb, 0, CIFS_GENL_MCGRP_SWN, GFP_ATOMIC);
0166 
0167     cifs_dbg(FYI, "%s: Message to register for network name %s with id %d sent\n", __func__,
0168             swnreg->net_name, swnreg->id);
0169 
0170     return 0;
0171 
0172 nlmsg_fail:
0173     genlmsg_cancel(skb, hdr);
0174     nlmsg_free(skb);
0175 fail:
0176     return ret;
0177 }
0178 
0179 /*
0180  * Sends an uregister message to the userspace daemon based on the registration
0181  */
0182 static int cifs_swn_send_unregister_message(struct cifs_swn_reg *swnreg)
0183 {
0184     struct sk_buff *skb;
0185     struct genlmsghdr *hdr;
0186     int ret;
0187 
0188     skb = genlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
0189     if (skb == NULL)
0190         return -ENOMEM;
0191 
0192     hdr = genlmsg_put(skb, 0, 0, &cifs_genl_family, 0, CIFS_GENL_CMD_SWN_UNREGISTER);
0193     if (hdr == NULL) {
0194         ret = -ENOMEM;
0195         goto nlmsg_fail;
0196     }
0197 
0198     ret = nla_put_u32(skb, CIFS_GENL_ATTR_SWN_REGISTRATION_ID, swnreg->id);
0199     if (ret < 0)
0200         goto nlmsg_fail;
0201 
0202     ret = nla_put_string(skb, CIFS_GENL_ATTR_SWN_NET_NAME, swnreg->net_name);
0203     if (ret < 0)
0204         goto nlmsg_fail;
0205 
0206     ret = nla_put_string(skb, CIFS_GENL_ATTR_SWN_SHARE_NAME, swnreg->share_name);
0207     if (ret < 0)
0208         goto nlmsg_fail;
0209 
0210     ret = nla_put(skb, CIFS_GENL_ATTR_SWN_IP, sizeof(struct sockaddr_storage),
0211             &swnreg->tcon->ses->server->dstaddr);
0212     if (ret < 0)
0213         goto nlmsg_fail;
0214 
0215     if (swnreg->net_name_notify) {
0216         ret = nla_put_flag(skb, CIFS_GENL_ATTR_SWN_NET_NAME_NOTIFY);
0217         if (ret < 0)
0218             goto nlmsg_fail;
0219     }
0220 
0221     if (swnreg->share_name_notify) {
0222         ret = nla_put_flag(skb, CIFS_GENL_ATTR_SWN_SHARE_NAME_NOTIFY);
0223         if (ret < 0)
0224             goto nlmsg_fail;
0225     }
0226 
0227     if (swnreg->ip_notify) {
0228         ret = nla_put_flag(skb, CIFS_GENL_ATTR_SWN_IP_NOTIFY);
0229         if (ret < 0)
0230             goto nlmsg_fail;
0231     }
0232 
0233     genlmsg_end(skb, hdr);
0234     genlmsg_multicast(&cifs_genl_family, skb, 0, CIFS_GENL_MCGRP_SWN, GFP_ATOMIC);
0235 
0236     cifs_dbg(FYI, "%s: Message to unregister for network name %s with id %d sent\n", __func__,
0237             swnreg->net_name, swnreg->id);
0238 
0239     return 0;
0240 
0241 nlmsg_fail:
0242     genlmsg_cancel(skb, hdr);
0243     nlmsg_free(skb);
0244     return ret;
0245 }
0246 
0247 /*
0248  * Try to find a matching registration for the tcon's server name and share name.
0249  * Calls to this function must be protected by cifs_swnreg_idr_mutex.
0250  * TODO Try to avoid memory allocations
0251  */
0252 static struct cifs_swn_reg *cifs_find_swn_reg(struct cifs_tcon *tcon)
0253 {
0254     struct cifs_swn_reg *swnreg;
0255     int id;
0256     const char *share_name;
0257     const char *net_name;
0258 
0259     net_name = extract_hostname(tcon->treeName);
0260     if (IS_ERR(net_name)) {
0261         int ret;
0262 
0263         ret = PTR_ERR(net_name);
0264         cifs_dbg(VFS, "%s: failed to extract host name from target '%s': %d\n",
0265                 __func__, tcon->treeName, ret);
0266         return ERR_PTR(-EINVAL);
0267     }
0268 
0269     share_name = extract_sharename(tcon->treeName);
0270     if (IS_ERR(share_name)) {
0271         int ret;
0272 
0273         ret = PTR_ERR(share_name);
0274         cifs_dbg(VFS, "%s: failed to extract share name from target '%s': %d\n",
0275                 __func__, tcon->treeName, ret);
0276         kfree(net_name);
0277         return ERR_PTR(-EINVAL);
0278     }
0279 
0280     idr_for_each_entry(&cifs_swnreg_idr, swnreg, id) {
0281         if (strcasecmp(swnreg->net_name, net_name) != 0
0282             || strcasecmp(swnreg->share_name, share_name) != 0) {
0283             continue;
0284         }
0285 
0286         cifs_dbg(FYI, "Existing swn registration for %s:%s found\n", swnreg->net_name,
0287                 swnreg->share_name);
0288 
0289         kfree(net_name);
0290         kfree(share_name);
0291 
0292         return swnreg;
0293     }
0294 
0295     kfree(net_name);
0296     kfree(share_name);
0297 
0298     return ERR_PTR(-EEXIST);
0299 }
0300 
0301 /*
0302  * Get a registration for the tcon's server and share name, allocating a new one if it does not
0303  * exists
0304  */
0305 static struct cifs_swn_reg *cifs_get_swn_reg(struct cifs_tcon *tcon)
0306 {
0307     struct cifs_swn_reg *reg = NULL;
0308     int ret;
0309 
0310     mutex_lock(&cifs_swnreg_idr_mutex);
0311 
0312     /* Check if we are already registered for this network and share names */
0313     reg = cifs_find_swn_reg(tcon);
0314     if (!IS_ERR(reg)) {
0315         kref_get(&reg->ref_count);
0316         mutex_unlock(&cifs_swnreg_idr_mutex);
0317         return reg;
0318     } else if (PTR_ERR(reg) != -EEXIST) {
0319         mutex_unlock(&cifs_swnreg_idr_mutex);
0320         return reg;
0321     }
0322 
0323     reg = kmalloc(sizeof(struct cifs_swn_reg), GFP_ATOMIC);
0324     if (reg == NULL) {
0325         mutex_unlock(&cifs_swnreg_idr_mutex);
0326         return ERR_PTR(-ENOMEM);
0327     }
0328 
0329     kref_init(&reg->ref_count);
0330 
0331     reg->id = idr_alloc(&cifs_swnreg_idr, reg, 1, 0, GFP_ATOMIC);
0332     if (reg->id < 0) {
0333         cifs_dbg(FYI, "%s: failed to allocate registration id\n", __func__);
0334         ret = reg->id;
0335         goto fail;
0336     }
0337 
0338     reg->net_name = extract_hostname(tcon->treeName);
0339     if (IS_ERR(reg->net_name)) {
0340         ret = PTR_ERR(reg->net_name);
0341         cifs_dbg(VFS, "%s: failed to extract host name from target: %d\n", __func__, ret);
0342         goto fail_idr;
0343     }
0344 
0345     reg->share_name = extract_sharename(tcon->treeName);
0346     if (IS_ERR(reg->share_name)) {
0347         ret = PTR_ERR(reg->share_name);
0348         cifs_dbg(VFS, "%s: failed to extract share name from target: %d\n", __func__, ret);
0349         goto fail_net_name;
0350     }
0351 
0352     reg->net_name_notify = true;
0353     reg->share_name_notify = true;
0354     reg->ip_notify = (tcon->capabilities & SMB2_SHARE_CAP_SCALEOUT);
0355 
0356     reg->tcon = tcon;
0357 
0358     mutex_unlock(&cifs_swnreg_idr_mutex);
0359 
0360     return reg;
0361 
0362 fail_net_name:
0363     kfree(reg->net_name);
0364 fail_idr:
0365     idr_remove(&cifs_swnreg_idr, reg->id);
0366 fail:
0367     kfree(reg);
0368     mutex_unlock(&cifs_swnreg_idr_mutex);
0369     return ERR_PTR(ret);
0370 }
0371 
0372 static void cifs_swn_reg_release(struct kref *ref)
0373 {
0374     struct cifs_swn_reg *swnreg = container_of(ref, struct cifs_swn_reg, ref_count);
0375     int ret;
0376 
0377     ret = cifs_swn_send_unregister_message(swnreg);
0378     if (ret < 0)
0379         cifs_dbg(VFS, "%s: Failed to send unregister message: %d\n", __func__, ret);
0380 
0381     idr_remove(&cifs_swnreg_idr, swnreg->id);
0382     kfree(swnreg->net_name);
0383     kfree(swnreg->share_name);
0384     kfree(swnreg);
0385 }
0386 
0387 static void cifs_put_swn_reg(struct cifs_swn_reg *swnreg)
0388 {
0389     mutex_lock(&cifs_swnreg_idr_mutex);
0390     kref_put(&swnreg->ref_count, cifs_swn_reg_release);
0391     mutex_unlock(&cifs_swnreg_idr_mutex);
0392 }
0393 
0394 static int cifs_swn_resource_state_changed(struct cifs_swn_reg *swnreg, const char *name, int state)
0395 {
0396     switch (state) {
0397     case CIFS_SWN_RESOURCE_STATE_UNAVAILABLE:
0398         cifs_dbg(FYI, "%s: resource name '%s' become unavailable\n", __func__, name);
0399         cifs_signal_cifsd_for_reconnect(swnreg->tcon->ses->server, true);
0400         break;
0401     case CIFS_SWN_RESOURCE_STATE_AVAILABLE:
0402         cifs_dbg(FYI, "%s: resource name '%s' become available\n", __func__, name);
0403         cifs_signal_cifsd_for_reconnect(swnreg->tcon->ses->server, true);
0404         break;
0405     case CIFS_SWN_RESOURCE_STATE_UNKNOWN:
0406         cifs_dbg(FYI, "%s: resource name '%s' changed to unknown state\n", __func__, name);
0407         break;
0408     }
0409     return 0;
0410 }
0411 
0412 static bool cifs_sockaddr_equal(struct sockaddr_storage *addr1, struct sockaddr_storage *addr2)
0413 {
0414     if (addr1->ss_family != addr2->ss_family)
0415         return false;
0416 
0417     if (addr1->ss_family == AF_INET) {
0418         return (memcmp(&((const struct sockaddr_in *)addr1)->sin_addr,
0419                 &((const struct sockaddr_in *)addr2)->sin_addr,
0420                 sizeof(struct in_addr)) == 0);
0421     }
0422 
0423     if (addr1->ss_family == AF_INET6) {
0424         return (memcmp(&((const struct sockaddr_in6 *)addr1)->sin6_addr,
0425                 &((const struct sockaddr_in6 *)addr2)->sin6_addr,
0426                 sizeof(struct in6_addr)) == 0);
0427     }
0428 
0429     return false;
0430 }
0431 
0432 static int cifs_swn_store_swn_addr(const struct sockaddr_storage *new,
0433                    const struct sockaddr_storage *old,
0434                    struct sockaddr_storage *dst)
0435 {
0436     __be16 port = cpu_to_be16(CIFS_PORT);
0437 
0438     if (old->ss_family == AF_INET) {
0439         struct sockaddr_in *ipv4 = (struct sockaddr_in *)old;
0440 
0441         port = ipv4->sin_port;
0442     } else if (old->ss_family == AF_INET6) {
0443         struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)old;
0444 
0445         port = ipv6->sin6_port;
0446     }
0447 
0448     if (new->ss_family == AF_INET) {
0449         struct sockaddr_in *ipv4 = (struct sockaddr_in *)new;
0450 
0451         ipv4->sin_port = port;
0452     } else if (new->ss_family == AF_INET6) {
0453         struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)new;
0454 
0455         ipv6->sin6_port = port;
0456     }
0457 
0458     *dst = *new;
0459 
0460     return 0;
0461 }
0462 
0463 static int cifs_swn_reconnect(struct cifs_tcon *tcon, struct sockaddr_storage *addr)
0464 {
0465     int ret = 0;
0466 
0467     /* Store the reconnect address */
0468     cifs_server_lock(tcon->ses->server);
0469     if (cifs_sockaddr_equal(&tcon->ses->server->dstaddr, addr))
0470         goto unlock;
0471 
0472     ret = cifs_swn_store_swn_addr(addr, &tcon->ses->server->dstaddr,
0473                       &tcon->ses->server->swn_dstaddr);
0474     if (ret < 0) {
0475         cifs_dbg(VFS, "%s: failed to store address: %d\n", __func__, ret);
0476         goto unlock;
0477     }
0478     tcon->ses->server->use_swn_dstaddr = true;
0479 
0480     /*
0481      * Unregister to stop receiving notifications for the old IP address.
0482      */
0483     ret = cifs_swn_unregister(tcon);
0484     if (ret < 0) {
0485         cifs_dbg(VFS, "%s: Failed to unregister for witness notifications: %d\n",
0486              __func__, ret);
0487         goto unlock;
0488     }
0489 
0490     /*
0491      * And register to receive notifications for the new IP address now that we have
0492      * stored the new address.
0493      */
0494     ret = cifs_swn_register(tcon);
0495     if (ret < 0) {
0496         cifs_dbg(VFS, "%s: Failed to register for witness notifications: %d\n",
0497              __func__, ret);
0498         goto unlock;
0499     }
0500 
0501     cifs_signal_cifsd_for_reconnect(tcon->ses->server, false);
0502 
0503 unlock:
0504     cifs_server_unlock(tcon->ses->server);
0505 
0506     return ret;
0507 }
0508 
0509 static int cifs_swn_client_move(struct cifs_swn_reg *swnreg, struct sockaddr_storage *addr)
0510 {
0511     struct sockaddr_in *ipv4 = (struct sockaddr_in *)addr;
0512     struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)addr;
0513 
0514     if (addr->ss_family == AF_INET)
0515         cifs_dbg(FYI, "%s: move to %pI4\n", __func__, &ipv4->sin_addr);
0516     else if (addr->ss_family == AF_INET6)
0517         cifs_dbg(FYI, "%s: move to %pI6\n", __func__, &ipv6->sin6_addr);
0518 
0519     return cifs_swn_reconnect(swnreg->tcon, addr);
0520 }
0521 
0522 int cifs_swn_notify(struct sk_buff *skb, struct genl_info *info)
0523 {
0524     struct cifs_swn_reg *swnreg;
0525     char name[256];
0526     int type;
0527 
0528     if (info->attrs[CIFS_GENL_ATTR_SWN_REGISTRATION_ID]) {
0529         int swnreg_id;
0530 
0531         swnreg_id = nla_get_u32(info->attrs[CIFS_GENL_ATTR_SWN_REGISTRATION_ID]);
0532         mutex_lock(&cifs_swnreg_idr_mutex);
0533         swnreg = idr_find(&cifs_swnreg_idr, swnreg_id);
0534         mutex_unlock(&cifs_swnreg_idr_mutex);
0535         if (swnreg == NULL) {
0536             cifs_dbg(FYI, "%s: registration id %d not found\n", __func__, swnreg_id);
0537             return -EINVAL;
0538         }
0539     } else {
0540         cifs_dbg(FYI, "%s: missing registration id attribute\n", __func__);
0541         return -EINVAL;
0542     }
0543 
0544     if (info->attrs[CIFS_GENL_ATTR_SWN_NOTIFICATION_TYPE]) {
0545         type = nla_get_u32(info->attrs[CIFS_GENL_ATTR_SWN_NOTIFICATION_TYPE]);
0546     } else {
0547         cifs_dbg(FYI, "%s: missing notification type attribute\n", __func__);
0548         return -EINVAL;
0549     }
0550 
0551     switch (type) {
0552     case CIFS_SWN_NOTIFICATION_RESOURCE_CHANGE: {
0553         int state;
0554 
0555         if (info->attrs[CIFS_GENL_ATTR_SWN_RESOURCE_NAME]) {
0556             nla_strscpy(name, info->attrs[CIFS_GENL_ATTR_SWN_RESOURCE_NAME],
0557                     sizeof(name));
0558         } else {
0559             cifs_dbg(FYI, "%s: missing resource name attribute\n", __func__);
0560             return -EINVAL;
0561         }
0562         if (info->attrs[CIFS_GENL_ATTR_SWN_RESOURCE_STATE]) {
0563             state = nla_get_u32(info->attrs[CIFS_GENL_ATTR_SWN_RESOURCE_STATE]);
0564         } else {
0565             cifs_dbg(FYI, "%s: missing resource state attribute\n", __func__);
0566             return -EINVAL;
0567         }
0568         return cifs_swn_resource_state_changed(swnreg, name, state);
0569     }
0570     case CIFS_SWN_NOTIFICATION_CLIENT_MOVE: {
0571         struct sockaddr_storage addr;
0572 
0573         if (info->attrs[CIFS_GENL_ATTR_SWN_IP]) {
0574             nla_memcpy(&addr, info->attrs[CIFS_GENL_ATTR_SWN_IP], sizeof(addr));
0575         } else {
0576             cifs_dbg(FYI, "%s: missing IP address attribute\n", __func__);
0577             return -EINVAL;
0578         }
0579         return cifs_swn_client_move(swnreg, &addr);
0580     }
0581     default:
0582         cifs_dbg(FYI, "%s: unknown notification type %d\n", __func__, type);
0583         break;
0584     }
0585 
0586     return 0;
0587 }
0588 
0589 int cifs_swn_register(struct cifs_tcon *tcon)
0590 {
0591     struct cifs_swn_reg *swnreg;
0592     int ret;
0593 
0594     swnreg = cifs_get_swn_reg(tcon);
0595     if (IS_ERR(swnreg))
0596         return PTR_ERR(swnreg);
0597 
0598     ret = cifs_swn_send_register_message(swnreg);
0599     if (ret < 0) {
0600         cifs_dbg(VFS, "%s: Failed to send swn register message: %d\n", __func__, ret);
0601         /* Do not put the swnreg or return error, the echo task will retry */
0602     }
0603 
0604     return 0;
0605 }
0606 
0607 int cifs_swn_unregister(struct cifs_tcon *tcon)
0608 {
0609     struct cifs_swn_reg *swnreg;
0610 
0611     mutex_lock(&cifs_swnreg_idr_mutex);
0612 
0613     swnreg = cifs_find_swn_reg(tcon);
0614     if (IS_ERR(swnreg)) {
0615         mutex_unlock(&cifs_swnreg_idr_mutex);
0616         return PTR_ERR(swnreg);
0617     }
0618 
0619     mutex_unlock(&cifs_swnreg_idr_mutex);
0620 
0621     cifs_put_swn_reg(swnreg);
0622 
0623     return 0;
0624 }
0625 
0626 void cifs_swn_dump(struct seq_file *m)
0627 {
0628     struct cifs_swn_reg *swnreg;
0629     struct sockaddr_in *sa;
0630     struct sockaddr_in6 *sa6;
0631     int id;
0632 
0633     seq_puts(m, "Witness registrations:");
0634 
0635     mutex_lock(&cifs_swnreg_idr_mutex);
0636     idr_for_each_entry(&cifs_swnreg_idr, swnreg, id) {
0637         seq_printf(m, "\nId: %u Refs: %u Network name: '%s'%s Share name: '%s'%s Ip address: ",
0638                 id, kref_read(&swnreg->ref_count),
0639                 swnreg->net_name, swnreg->net_name_notify ? "(y)" : "(n)",
0640                 swnreg->share_name, swnreg->share_name_notify ? "(y)" : "(n)");
0641         switch (swnreg->tcon->ses->server->dstaddr.ss_family) {
0642         case AF_INET:
0643             sa = (struct sockaddr_in *) &swnreg->tcon->ses->server->dstaddr;
0644             seq_printf(m, "%pI4", &sa->sin_addr.s_addr);
0645             break;
0646         case AF_INET6:
0647             sa6 = (struct sockaddr_in6 *) &swnreg->tcon->ses->server->dstaddr;
0648             seq_printf(m, "%pI6", &sa6->sin6_addr.s6_addr);
0649             if (sa6->sin6_scope_id)
0650                 seq_printf(m, "%%%u", sa6->sin6_scope_id);
0651             break;
0652         default:
0653             seq_puts(m, "(unknown)");
0654         }
0655         seq_printf(m, "%s", swnreg->ip_notify ? "(y)" : "(n)");
0656     }
0657     mutex_unlock(&cifs_swnreg_idr_mutex);
0658     seq_puts(m, "\n");
0659 }
0660 
0661 void cifs_swn_check(void)
0662 {
0663     struct cifs_swn_reg *swnreg;
0664     int id;
0665     int ret;
0666 
0667     mutex_lock(&cifs_swnreg_idr_mutex);
0668     idr_for_each_entry(&cifs_swnreg_idr, swnreg, id) {
0669         ret = cifs_swn_send_register_message(swnreg);
0670         if (ret < 0)
0671             cifs_dbg(FYI, "%s: Failed to send register message: %d\n", __func__, ret);
0672     }
0673     mutex_unlock(&cifs_swnreg_idr_mutex);
0674 }