[tipc-discussion] [PATCH 0/2] New node removal netlink command

2015-12-02 Thread Richard Alpe
Add a new netlink command that can remove a dead node from the internal
data structures.

There is still an impediment here:

When I wrote this a node was removed properly on the first call. After rebase
it now requires the netlink command and the subsequent tipc_node_stop() function
to be executed twice before the node is actually removed. To me this suggests
that something is wrong with the node ref-count. I bisected and found the change
in behaviour to be introduced in 5405ff6e15f4 tipc: convert node lock to rwlock

Looking at that commit the only change in ref-counting that I can spot is new
return at line 463 of the patch:
if (likely(!skb_queue_empty(&xmitq)))
...
return ...

Taking this return would result in one less tipc_node_put(). I'm not familiar
with how the node ref counting is suppose to work. Can someone help me here?
Why are we changing the ref count of a node in the transmit function?

Richard Alpe (2):
  tipc: move netlink policies to netlink.h
  tipc: add node removal functionality

 include/uapi/linux/tipc_netlink.h |  1 +
 net/tipc/bearer.c | 19 +
 net/tipc/link.c   |  8 
 net/tipc/name_table.c |  7 +---
 net/tipc/net.c|  8 +---
 net/tipc/netlink.c| 18 +++--
 net/tipc/netlink.h| 85 +++
 net/tipc/node.c   | 83 +-
 net/tipc/node.h   |  3 +-
 net/tipc/socket.c |  9 +
 net/tipc/udp_media.c  |  9 +
 11 files changed, 155 insertions(+), 95 deletions(-)

-- 
2.1.4


--
Go from Idea to Many App Stores Faster with Intel(R) XDK
Give your users amazing mobile app experiences with Intel(R) XDK.
Use one codebase in this all-in-one HTML5 development environment.
Design, debug & build mobile apps & 2D/3D high-impact games for multiple OSs.
http://pubads.g.doubleclick.net/gampad/clk?id=254741911&iu=/4140
___
tipc-discussion mailing list
tipc-discussion@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/tipc-discussion


[tipc-discussion] [PATCH 1/2] tipc: move netlink policies to netlink.h

2015-12-02 Thread Richard Alpe
Make the c files less cluttered and enable netlink attributes to be
shared between files. This will prove useful in future patches where a
node message contains a nested network.

Signed-off-by: Richard Alpe 
---
 net/tipc/bearer.c | 19 +---
 net/tipc/link.c   |  8 -
 net/tipc/name_table.c |  7 +
 net/tipc/net.c|  6 +---
 net/tipc/netlink.c| 13 +---
 net/tipc/netlink.h| 85 +++
 net/tipc/node.c   | 23 +-
 net/tipc/socket.c |  9 +-
 net/tipc/udp_media.c  |  9 +-
 9 files changed, 92 insertions(+), 87 deletions(-)

diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c
index 802ffad..d654cfe 100644
--- a/net/tipc/bearer.c
+++ b/net/tipc/bearer.c
@@ -40,6 +40,7 @@
 #include "link.h"
 #include "discover.h"
 #include "bcast.h"
+#include "netlink.h"
 
 #define MAX_ADDR_STR 60
 
@@ -53,24 +54,6 @@ static struct tipc_media * const media_info_array[] = {
 #endif
NULL
 };
-
-static const struct nla_policy
-tipc_nl_bearer_policy[TIPC_NLA_BEARER_MAX + 1] = {
-   [TIPC_NLA_BEARER_UNSPEC]= { .type = NLA_UNSPEC },
-   [TIPC_NLA_BEARER_NAME] = {
-   .type = NLA_STRING,
-   .len = TIPC_MAX_BEARER_NAME
-   },
-   [TIPC_NLA_BEARER_PROP]  = { .type = NLA_NESTED },
-   [TIPC_NLA_BEARER_DOMAIN]= { .type = NLA_U32 }
-};
-
-static const struct nla_policy tipc_nl_media_policy[TIPC_NLA_MEDIA_MAX + 1] = {
-   [TIPC_NLA_MEDIA_UNSPEC] = { .type = NLA_UNSPEC },
-   [TIPC_NLA_MEDIA_NAME]   = { .type = NLA_STRING },
-   [TIPC_NLA_MEDIA_PROP]   = { .type = NLA_NESTED }
-};
-
 static void bearer_disable(struct net *net, struct tipc_bearer *b);
 
 /**
diff --git a/net/tipc/link.c b/net/tipc/link.c
index b11afe7..5f7fa42 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -196,14 +196,6 @@ struct tipc_link {
 static const char *link_co_err = "Link tunneling error, ";
 static const char *link_rst_msg = "Resetting link ";
 
-/* Properties valid for media, bearar and link */
-static const struct nla_policy tipc_nl_prop_policy[TIPC_NLA_PROP_MAX + 1] = {
-   [TIPC_NLA_PROP_UNSPEC]  = { .type = NLA_UNSPEC },
-   [TIPC_NLA_PROP_PRIO]= { .type = NLA_U32 },
-   [TIPC_NLA_PROP_TOL] = { .type = NLA_U32 },
-   [TIPC_NLA_PROP_WIN] = { .type = NLA_U32 }
-};
-
 /* Send states for broadcast NACKs
  */
 enum {
diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c
index 91fce70..75992b5 100644
--- a/net/tipc/name_table.c
+++ b/net/tipc/name_table.c
@@ -44,15 +44,10 @@
 #include "addr.h"
 #include "node.h"
 #include 
+#include "netlink.h"
 
 #define TIPC_NAMETBL_SIZE 1024 /* must be a power of 2 */
 
-static const struct nla_policy
-tipc_nl_name_table_policy[TIPC_NLA_NAME_TABLE_MAX + 1] = {
-   [TIPC_NLA_NAME_TABLE_UNSPEC]= { .type = NLA_UNSPEC },
-   [TIPC_NLA_NAME_TABLE_PUBL]  = { .type = NLA_NESTED }
-};
-
 /**
  * struct name_info - name sequence publication info
  * @node_list: circular list of publications made by own node
diff --git a/net/tipc/net.c b/net/tipc/net.c
index 77bf911..d7a5c11 100644
--- a/net/tipc/net.c
+++ b/net/tipc/net.c
@@ -41,11 +41,7 @@
 #include "socket.h"
 #include "node.h"
 #include "bcast.h"
-
-static 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 }
-};
+#include "netlink.h"
 
 /*
  * The TIPC locking policy is designed to ensure a very fine locking
diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c
index 8975b01..234cb93 100644
--- a/net/tipc/netlink.c
+++ b/net/tipc/netlink.c
@@ -42,18 +42,7 @@
 #include "node.h"
 #include "net.h"
 #include 
-
-static const struct nla_policy tipc_nl_policy[TIPC_NLA_MAX + 1] = {
-   [TIPC_NLA_UNSPEC]   = { .type = NLA_UNSPEC, },
-   [TIPC_NLA_BEARER]   = { .type = NLA_NESTED, },
-   [TIPC_NLA_SOCK] = { .type = NLA_NESTED, },
-   [TIPC_NLA_PUBL] = { .type = NLA_NESTED, },
-   [TIPC_NLA_LINK] = { .type = NLA_NESTED, },
-   [TIPC_NLA_MEDIA]= { .type = NLA_NESTED, },
-   [TIPC_NLA_NODE] = { .type = NLA_NESTED, },
-   [TIPC_NLA_NET]  = { .type = NLA_NESTED, },
-   [TIPC_NLA_NAME_TABLE]   = { .type = NLA_NESTED, }
-};
+#include "netlink.h"
 
 /* Users of the legacy API (tipc-config) can't handle that we add operations,
  * so we have a separate genl handling for the new API.
diff --git a/net/tipc/netlink.h b/net/tipc/netlink.h
index 08a1db6..ff7a39da 100644
--- a/net/tipc/netlink.h
+++ b/net/tipc/netlink.h
@@ -36,7 +36,92 @@
 #ifndef _TIPC_NETLINK_H
 #define _TIPC_NETLINK_H
 
+#include 
+
 extern struct genl_family tipc_genl_family;
+
+static const struct nla_policy tipc_nl_policy[TIPC_NLA_MAX + 1] = {
+   [TIPC_NLA_UNSPEC]   = {

[tipc-discussion] [PATCH 2/2] tipc: add node removal functionality

2015-12-02 Thread Richard Alpe
Add a new netlink command, TIPC_NL_NODE_REMOVE. 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 
---
 include/uapi/linux/tipc_netlink.h |  1 +
 net/tipc/net.c|  2 +-
 net/tipc/netlink.c|  5 
 net/tipc/node.c   | 60 +++
 net/tipc/node.h   |  3 +-
 5 files changed, 63 insertions(+), 8 deletions(-)

diff --git a/include/uapi/linux/tipc_netlink.h 
b/include/uapi/linux/tipc_netlink.h
index d4c8f14..3f8a2b8 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_NODE_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 d7a5c11..bc6b4a6 100644
--- a/net/tipc/net.c
+++ b/net/tipc/net.c
@@ -135,7 +135,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/netlink.c b/net/tipc/netlink.c
index 234cb93..3566832 100644
--- a/net/tipc/netlink.c
+++ b/net/tipc/netlink.c
@@ -134,6 +134,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_NODE_REMOVE,
+   .doit   = tipc_nl_node_rm,
+   .policy = tipc_nl_policy,
}
 };
 
diff --git a/net/tipc/node.c b/net/tipc/node.c
index 6182d9d..31f40cc 100644
--- a/net/tipc/node.c
+++ b/net/tipc/node.c
@@ -378,17 +378,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);
 }
 
@@ -1509,6 +1513,50 @@ discard:
kfree_skb(skb);
 }
 
+int tipc_nl_node_rm(struct sk_buff *skb, struct genl_info *info)
+{
+   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 *node;
+   int err;
+
+   /* We identify the node 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(node, &tn->node_list, list) {
+   if (node->addr != addr)
+   continue;
+
+   if (node->state == SELF_DOWN_PEER_DOWN ||
+   node->state == SELF_DOWN_PEER_LEAVING) {
+   tipc_node_stop(node);
+
+   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..d6250ec 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(struc

Re: [tipc-discussion] [PATCH 0/2] New node removal netlink command

2015-12-02 Thread Jon Maloy


> -Original Message-
> From: Richard Alpe
> Sent: Wednesday, 02 December, 2015 07:52
> To: tipc-discussion@lists.sourceforge.net
> Cc: Jon Maloy; Ying Xue; Richard Alpe
> Subject: [PATCH 0/2] New node removal netlink command
> 
> Add a new netlink command that can remove a dead node from the internal
> data structures.
> 
> There is still an impediment here:
> 
> When I wrote this a node was removed properly on the first call. After
> rebase it now requires the netlink command and the subsequent
> tipc_node_stop() function to be executed twice before the node is actually
> removed. To me this suggests that something is wrong with the node ref-
> count. I bisected and found the change in behaviour to be introduced in
> 5405ff6e15f4 tipc: convert node lock to rwlock
> 
> Looking at that commit the only change in ref-counting that I can spot is new
> return at line 463 of the patch:
> if (likely(!skb_queue_empty(&xmitq)))
>   ...
>   return ...
> 

Yes, this is clearly a bug. I will post a patch. Thank you for spotting this.

///jon

> Taking this return would result in one less tipc_node_put(). I'm not familiar
> with how the node ref counting is suppose to work. Can someone help me
> here?
> Why are we changing the ref count of a node in the transmit function?
> 
> Richard Alpe (2):
>   tipc: move netlink policies to netlink.h
>   tipc: add node removal functionality
> 
>  include/uapi/linux/tipc_netlink.h |  1 +
>  net/tipc/bearer.c | 19 +
>  net/tipc/link.c   |  8 
>  net/tipc/name_table.c |  7 +---
>  net/tipc/net.c|  8 +---
>  net/tipc/netlink.c| 18 +++--
>  net/tipc/netlink.h| 85
> +++
>  net/tipc/node.c   | 83 +-
>  net/tipc/node.h   |  3 +-
>  net/tipc/socket.c |  9 +
>  net/tipc/udp_media.c  |  9 +
>  11 files changed, 155 insertions(+), 95 deletions(-)
> 
> --
> 2.1.4


--
Go from Idea to Many App Stores Faster with Intel(R) XDK
Give your users amazing mobile app experiences with Intel(R) XDK.
Use one codebase in this all-in-one HTML5 development environment.
Design, debug & build mobile apps & 2D/3D high-impact games for multiple OSs.
http://pubads.g.doubleclick.net/gampad/clk?id=254741911&iu=/4140
___
tipc-discussion mailing list
tipc-discussion@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/tipc-discussion


Re: [tipc-discussion] [PATCH 1/2] tipc: move netlink policies to netlink.h

2015-12-02 Thread Jon Maloy
Very appreciated change.
Maybe you should add the standard phrase "There are no functional changes in 
this commit"

Acked-by: me

///jon



> -Original Message-
> From: Richard Alpe
> Sent: Wednesday, 02 December, 2015 07:52
> To: tipc-discussion@lists.sourceforge.net
> Cc: Jon Maloy; Ying Xue; Richard Alpe
> Subject: [PATCH 1/2] tipc: move netlink policies to netlink.h
> 
> Make the c files less cluttered and enable netlink attributes to be shared
> between files. This will prove useful in future patches where a node message
> contains a nested network.
> 
> Signed-off-by: Richard Alpe 
> ---
>  net/tipc/bearer.c | 19 +---
>  net/tipc/link.c   |  8 -
>  net/tipc/name_table.c |  7 +
>  net/tipc/net.c|  6 +---
>  net/tipc/netlink.c| 13 +---
>  net/tipc/netlink.h| 85
> +++
>  net/tipc/node.c   | 23 +-
>  net/tipc/socket.c |  9 +-
>  net/tipc/udp_media.c  |  9 +-
>  9 files changed, 92 insertions(+), 87 deletions(-)
> 
> diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index 802ffad..d654cfe
> 100644
> --- a/net/tipc/bearer.c
> +++ b/net/tipc/bearer.c
> @@ -40,6 +40,7 @@
>  #include "link.h"
>  #include "discover.h"
>  #include "bcast.h"
> +#include "netlink.h"
> 
>  #define MAX_ADDR_STR 60
> 
> @@ -53,24 +54,6 @@ static struct tipc_media * const media_info_array[] = {
> #endif
>   NULL
>  };
> -
> -static const struct nla_policy
> -tipc_nl_bearer_policy[TIPC_NLA_BEARER_MAX + 1]   = {
> - [TIPC_NLA_BEARER_UNSPEC]= { .type = NLA_UNSPEC },
> - [TIPC_NLA_BEARER_NAME] = {
> - .type = NLA_STRING,
> - .len = TIPC_MAX_BEARER_NAME
> - },
> - [TIPC_NLA_BEARER_PROP]  = { .type =
> NLA_NESTED },
> - [TIPC_NLA_BEARER_DOMAIN]= { .type = NLA_U32 }
> -};
> -
> -static const struct nla_policy tipc_nl_media_policy[TIPC_NLA_MEDIA_MAX
> + 1] = {
> - [TIPC_NLA_MEDIA_UNSPEC] = { .type = NLA_UNSPEC },
> - [TIPC_NLA_MEDIA_NAME]   = { .type = NLA_STRING },
> - [TIPC_NLA_MEDIA_PROP]   = { .type = NLA_NESTED }
> -};
> -
>  static void bearer_disable(struct net *net, struct tipc_bearer *b);
> 
>  /**
> diff --git a/net/tipc/link.c b/net/tipc/link.c index b11afe7..5f7fa42 100644
> --- a/net/tipc/link.c
> +++ b/net/tipc/link.c
> @@ -196,14 +196,6 @@ struct tipc_link {
>  static const char *link_co_err = "Link tunneling error, ";  static const char
> *link_rst_msg = "Resetting link ";
> 
> -/* Properties valid for media, bearar and link */ -static const struct
> nla_policy tipc_nl_prop_policy[TIPC_NLA_PROP_MAX + 1] = {
> - [TIPC_NLA_PROP_UNSPEC]  = { .type = NLA_UNSPEC },
> - [TIPC_NLA_PROP_PRIO]= { .type = NLA_U32 },
> - [TIPC_NLA_PROP_TOL] = { .type = NLA_U32 },
> - [TIPC_NLA_PROP_WIN] = { .type = NLA_U32 }
> -};
> -
>  /* Send states for broadcast NACKs
>   */
>  enum {
> diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c index
> 91fce70..75992b5 100644
> --- a/net/tipc/name_table.c
> +++ b/net/tipc/name_table.c
> @@ -44,15 +44,10 @@
>  #include "addr.h"
>  #include "node.h"
>  #include 
> +#include "netlink.h"
> 
>  #define TIPC_NAMETBL_SIZE 1024   /* must be a power of 2 */
> 
> -static const struct nla_policy
> -tipc_nl_name_table_policy[TIPC_NLA_NAME_TABLE_MAX + 1] = {
> - [TIPC_NLA_NAME_TABLE_UNSPEC]= { .type = NLA_UNSPEC },
> - [TIPC_NLA_NAME_TABLE_PUBL]  = { .type = NLA_NESTED }
> -};
> -
>  /**
>   * struct name_info - name sequence publication info
>   * @node_list: circular list of publications made by own node diff --git
> a/net/tipc/net.c b/net/tipc/net.c index 77bf911..d7a5c11 100644
> --- a/net/tipc/net.c
> +++ b/net/tipc/net.c
> @@ -41,11 +41,7 @@
>  #include "socket.h"
>  #include "node.h"
>  #include "bcast.h"
> -
> -static 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 }
> -};
> +#include "netlink.h"
> 
>  /*
>   * The TIPC locking policy is designed to ensure a very fine locking diff 
> --git
> a/net/tipc/netlink.c b/net/tipc/netlink.c index 8975b01..234cb93 100644
> --- a/net/tipc/netlink.c
> +++ b/net/tipc/netlink.c
> @@ -42,18 +42,7 @@
>  #include "node.h"
>  #include "net.h"
>  #include 
> -
> -static const struct nla_policy tipc_nl_policy[TIPC_NLA_MAX + 1] = {
> - [TIPC_NLA_UNSPEC]   = { .type = NLA_UNSPEC, },
> - [TIPC_NLA_BEARER]   = { .type = NLA_NESTED, },
> - [TIPC_NLA_SOCK] = { .type = NLA_NESTED, },
> - [TIPC_NLA_PUBL] = { .type = NLA_NESTED, },
> - [TIPC_NLA_LINK] = { .type = NLA_NESTED, },
> - [TIPC_NLA_MEDIA]= { .type = NLA_NESTED, },
> - [TIPC_NLA_NODE] = { .type = NLA_NESTED, },
> - [TIPC_NLA_NET]  = { .type = NLA_NESTED, },
>

Re: [tipc-discussion] [PATCH 2/2] tipc: add node removal functionality

2015-12-02 Thread Jon Maloy
Looks good.
Reviewed-by: me

///jon


> -Original Message-
> From: Richard Alpe
> Sent: Wednesday, 02 December, 2015 07:52
> To: tipc-discussion@lists.sourceforge.net
> Cc: Jon Maloy; Ying Xue; Richard Alpe
> Subject: [PATCH 2/2] tipc: add node removal functionality
> 
> Add a new netlink command, TIPC_NL_NODE_REMOVE. 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 
> ---
>  include/uapi/linux/tipc_netlink.h |  1 +
>  net/tipc/net.c|  2 +-
>  net/tipc/netlink.c|  5 
>  net/tipc/node.c   | 60 +++-
> ---
>  net/tipc/node.h   |  3 +-
>  5 files changed, 63 insertions(+), 8 deletions(-)
> 
> diff --git a/include/uapi/linux/tipc_netlink.h
> b/include/uapi/linux/tipc_netlink.h
> index d4c8f14..3f8a2b8 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_NODE_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 d7a5c11..bc6b4a6 100644
> --- a/net/tipc/net.c
> +++ b/net/tipc/net.c
> @@ -135,7 +135,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/netlink.c b/net/tipc/netlink.c index 234cb93..3566832
> 100644
> --- a/net/tipc/netlink.c
> +++ b/net/tipc/netlink.c
> @@ -134,6 +134,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_NODE_REMOVE,
> + .doit   = tipc_nl_node_rm,
> + .policy = tipc_nl_policy,
>   }
>  };
> 
> diff --git a/net/tipc/node.c b/net/tipc/node.c index 6182d9d..31f40cc 100644
> --- a/net/tipc/node.c
> +++ b/net/tipc/node.c
> @@ -378,17 +378,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);
>  }
> 
> @@ -1509,6 +1513,50 @@ discard:
>   kfree_skb(skb);
>  }
> 
> +int tipc_nl_node_rm(struct sk_buff *skb, struct genl_info *info) {
> + 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 *node;
> + int err;
> +
> + /* We identify the node 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(node, &tn->node_list, list) {
> + if (node->addr != addr)
> + continue;
> +
> + if (node->state == SELF_DOWN_PEER_DOWN ||
> + node->state == SELF_DOWN_PEER_LEAVING) {
> + tipc_node_stop(node);
> +
> + 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..d6250ec
> 100644
> --- a/net/tipc/node.h
> +++ b/net/tipc/node.h
> @@ -51,7 +51,7 @@ enum {
>  #define TIPC_NODE_CAPABILITIES TIPC_BCAST_SYNCH  #define

[tipc-discussion] [PATCH net-next 1/1] tipc: fix node reference count bug

2015-12-02 Thread Jon Maloy
Commit 5405ff6e15f40f2f ("tipc: convert node lock to rwlock")
introduced a bug to the node reference counter handling. When a
message is successfully sent in the function tipc_node_xmit(),
we return directly after releasing the node lock, instead of
continuing and decrementing the node reference counter as we
should do.

This commit fixes this bug.

Signed-off-by: Jon Maloy 
---
 net/tipc/node.c | 15 +++
 1 file changed, 7 insertions(+), 8 deletions(-)

diff --git a/net/tipc/node.c b/net/tipc/node.c
index 3f7a4ed..fa97d96 100644
--- a/net/tipc/node.c
+++ b/net/tipc/node.c
@@ -1189,20 +1189,19 @@ int tipc_node_xmit(struct net *net, struct sk_buff_head 
*list,
spin_unlock_bh(&le->lock);
}
tipc_node_read_unlock(n);
-   if (likely(!skb_queue_empty(&xmitq))) {
+   if (likely(!rc))
tipc_bearer_xmit(net, bearer_id, &xmitq, &le->maddr);
-   return 0;
-   }
-   if (unlikely(rc == -ENOBUFS))
+   else if (rc == -ENOBUFS)
tipc_node_link_down(n, bearer_id, false);
tipc_node_put(n);
return rc;
}
 
-   if (unlikely(!in_own_node(net, dnode)))
-   return rc;
-   tipc_sk_rcv(net, list);
-   return 0;
+   if (likely(in_own_node(net, dnode))) {
+   tipc_sk_rcv(net, list);
+   return 0;
+   }
+   return rc;
 }
 
 /* tipc_node_xmit_skb(): send single buffer to destination
-- 
1.9.1


--
Go from Idea to Many App Stores Faster with Intel(R) XDK
Give your users amazing mobile app experiences with Intel(R) XDK.
Use one codebase in this all-in-one HTML5 development environment.
Design, debug & build mobile apps & 2D/3D high-impact games for multiple OSs.
http://pubads.g.doubleclick.net/gampad/clk?id=254741911&iu=/4140
___
tipc-discussion mailing list
tipc-discussion@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/tipc-discussion