Hi,

On Jan 12, 2016 10:09 PM, "Richard Alpe" <[email protected]> wrote:
>
> Add TIPC_NL_PEER_REMOVE netlink command. This command can remove
> an offline peer node from the internal data structures.
>
> This will be supported by the tipc user space tool in iproute2.
>
> Signed-off-by: Richard Alpe <[email protected]>
> Reviewed-by: Jon Maloy <[email protected]>
> Acked-by: Ying Xue <[email protected]>
> ---
>  include/uapi/linux/tipc_netlink.h |  1 +
>  net/tipc/net.c                    |  4 +--
>  net/tipc/net.h                    |  2 ++
>  net/tipc/netlink.c                |  5 ++++
>  net/tipc/node.c                   | 60
+++++++++++++++++++++++++++++++++++----
>  net/tipc/node.h                   |  3 +-
>  6 files changed, 66 insertions(+), 9 deletions(-)
>
> diff --git a/include/uapi/linux/tipc_netlink.h
b/include/uapi/linux/tipc_netlink.h
> index d4c8f14..25eb645 100644
> --- a/include/uapi/linux/tipc_netlink.h
> +++ b/include/uapi/linux/tipc_netlink.h
> @@ -56,6 +56,7 @@ enum {
>         TIPC_NL_NET_GET,
>         TIPC_NL_NET_SET,
>         TIPC_NL_NAME_TABLE_GET,
> +       TIPC_NL_PEER_REMOVE,
>
>         __TIPC_NL_CMD_MAX,
>         TIPC_NL_CMD_MAX = __TIPC_NL_CMD_MAX - 1
> diff --git a/net/tipc/net.c b/net/tipc/net.c
> index 77bf911..042d4ce 100644
> --- a/net/tipc/net.c
> +++ b/net/tipc/net.c
> @@ -42,7 +42,7 @@
>  #include "node.h"
>  #include "bcast.h"
>
> -static const struct nla_policy tipc_nl_net_policy[TIPC_NLA_NET_MAX + 1]
= {
> +const struct nla_policy tipc_nl_net_policy[TIPC_NLA_NET_MAX + 1] = {
>         [TIPC_NLA_NET_UNSPEC]   = { .type = NLA_UNSPEC },
>         [TIPC_NLA_NET_ID]       = { .type = NLA_U32 }
>  };
> @@ -139,7 +139,7 @@ void tipc_net_stop(struct net *net)
>                               tn->own_addr);
>         rtnl_lock();
>         tipc_bearer_stop(net);
> -       tipc_node_stop(net);
> +       tipc_node_stop_net(net);
>         rtnl_unlock();
>
>         pr_info("Left network mode\n");
> diff --git a/net/tipc/net.h b/net/tipc/net.h
> index 77a7a11..c7c2549 100644
> --- a/net/tipc/net.h
> +++ b/net/tipc/net.h
> @@ -39,6 +39,8 @@
>
>  #include <net/genetlink.h>
>
> +extern const struct nla_policy tipc_nl_net_policy[];
> +
>  int tipc_net_start(struct net *net, u32 addr);
>
>  void tipc_net_stop(struct net *net);
> diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c
> index 8975b01..9019df8 100644
> --- a/net/tipc/netlink.c
> +++ b/net/tipc/netlink.c
> @@ -145,6 +145,11 @@ static const struct genl_ops tipc_genl_v2_ops[] = {
>                 .cmd    = TIPC_NL_NAME_TABLE_GET,
>                 .dumpit = tipc_nl_name_table_dump,
>                 .policy = tipc_nl_policy,
> +       },
> +       {
> +               .cmd    = TIPC_NL_PEER_REMOVE,
> +               .doit   = tipc_nl_peer_rm,
> +               .policy = tipc_nl_policy,
>         }
>  };
>
> diff --git a/net/tipc/node.c b/net/tipc/node.c
> index fa97d96..988cdd9 100644
> --- a/net/tipc/node.c
> +++ b/net/tipc/node.c
> @@ -399,17 +399,21 @@ static void tipc_node_delete(struct tipc_node *node)
>         kfree_rcu(node, rcu);
>  }
>
> -void tipc_node_stop(struct net *net)
> +static void tipc_node_stop(struct tipc_node *node)
> +{
> +       if (del_timer(&node->timer))
> +               tipc_node_put(node);
> +       tipc_node_put(node);
> +}
> +
> +void tipc_node_stop_net(struct net *net)
>  {
>         struct tipc_net *tn = net_generic(net, tipc_net_id);
>         struct tipc_node *node, *t_node;
>
>         spin_lock_bh(&tn->node_list_lock);
> -       list_for_each_entry_safe(node, t_node, &tn->node_list, list) {
> -               if (del_timer(&node->timer))
> -                       tipc_node_put(node);
> -               tipc_node_put(node);
> -       }
> +       list_for_each_entry_safe(node, t_node, &tn->node_list, list)
> +               tipc_node_stop(node);
>         spin_unlock_bh(&tn->node_list_lock);
>  }
>
> @@ -1529,6 +1533,50 @@ discard:
>         kfree_skb(skb);
>  }
>
> +int tipc_nl_peer_rm(struct sk_buff *skb, struct genl_info *info)
> +{
> +       int err;
> +       u32 addr;
> +       struct net *net = sock_net(skb->sk);
> +       struct nlattr *attrs[TIPC_NLA_NET_MAX + 1];
> +       struct tipc_net *tn = net_generic(net, tipc_net_id);
> +       struct tipc_node *peer;
> +
> +       /* We identify the peer by its net */
> +       if (!info->attrs[TIPC_NLA_NET])
> +               return -EINVAL;
> +
> +       err = nla_parse_nested(attrs, TIPC_NLA_NET_MAX,
> +                              info->attrs[TIPC_NLA_NET],
> +                              tipc_nl_net_policy);
> +       if (err)
> +               return err;
> +
> +       if (!attrs[TIPC_NLA_NET_ADDR])
> +               return -EINVAL;
> +
> +       addr = nla_get_u32(attrs[TIPC_NLA_NET_ADDR]);
> +
> +       spin_lock_bh(&tn->node_list_lock);
> +       list_for_each_entry_rcu(peer, &tn->node_list, list) {
> +               if (peer->addr != addr)
> +                       continue;
> +
> +               if (peer->state == SELF_DOWN_PEER_DOWN ||
> +                   peer->state == SELF_DOWN_PEER_LEAVING) {
> +                       tipc_node_stop(peer);

I think here is not safe to do tipc_node_stop(). Because here we are not
sure that node's refcount  really can drop to zero,thus, not sure
tipc_node_delete() can be execute in a critical region which protected by
node_list_lock spin lock. This may result in tipc_create_node() to return a
to-be-deleted node which is not in the node list any more.
> +
> +                       spin_unlock_bh(&tn->node_list_lock);
> +                       return 0;
> +               }
> +               spin_unlock_bh(&tn->node_list_lock);
> +               return -EBUSY;
> +       }
> +       spin_unlock_bh(&tn->node_list_lock);
> +
> +       return -ENXIO;
> +}
> +
>  int tipc_nl_node_dump(struct sk_buff *skb, struct netlink_callback *cb)
>  {
>         int err;
> diff --git a/net/tipc/node.h b/net/tipc/node.h
> index f39d9d0..8dfb6ba 100644
> --- a/net/tipc/node.h
> +++ b/net/tipc/node.h
> @@ -51,7 +51,7 @@ enum {
>  #define TIPC_NODE_CAPABILITIES TIPC_BCAST_SYNCH
>  #define INVALID_BEARER_ID -1
>
> -void tipc_node_stop(struct net *net);
> +void tipc_node_stop_net(struct net *net);
>  void tipc_node_check_dest(struct net *net, u32 onode,
>                           struct tipc_bearer *bearer,
>                           u16 capabilities, u32 signature,
> @@ -75,5 +75,6 @@ int tipc_nl_node_dump_link(struct sk_buff *skb, struct
netlink_callback *cb);
>  int tipc_nl_node_reset_link_stats(struct sk_buff *skb, struct genl_info
*info);
>  int tipc_nl_node_get_link(struct sk_buff *skb, struct genl_info *info);
>  int tipc_nl_node_set_link(struct sk_buff *skb, struct genl_info *info);
> +int tipc_nl_peer_rm(struct sk_buff *skb, struct genl_info *info);
>
>  #endif
> --
> 2.1.4
>
>
>
------------------------------------------------------------------------------
> Site24x7 APM Insight: Get Deep Visibility into Application Performance
> APM + Mobile APM + RUM: Monitor 3 App instances at just $35/Month
> Monitor end-to-end web transactions and take corrective actions now
> Troubleshoot faster and improve end-user experience. Signup Now!
> http://pubads.g.doubleclick.net/gampad/clk?id=267308311&iu=/4140
> _______________________________________________
> tipc-discussion mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/tipc-discussion
------------------------------------------------------------------------------
Site24x7 APM Insight: Get Deep Visibility into Application Performance
APM + Mobile APM + RUM: Monitor 3 App instances at just $35/Month
Monitor end-to-end web transactions and take corrective actions now
Troubleshoot faster and improve end-user experience. Signup Now!
http://pubads.g.doubleclick.net/gampad/clk?id=267308311&iu=/4140
_______________________________________________
tipc-discussion mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/tipc-discussion

Reply via email to