tipc: modify struct tipc_plist to be more versatile
authorJon Paul Maloy <jon.maloy@ericsson.com>
Tue, 3 Jan 2017 15:55:10 +0000 (10:55 -0500)
committerDavid S. Miller <davem@davemloft.net>
Tue, 3 Jan 2017 16:13:05 +0000 (11:13 -0500)
During multicast reception we currently use a simple linked list with
push/pop semantics to store port numbers.

We now see a need for a more generic list for storing values of type
u32. We therefore make some modifications to this list, while replacing
the prefix 'tipc_plist_' with 'u32_'. We also add a couple of new
functions which will come to use in the next commits.

Acked-by: Parthasarathy Bhuvaragan <parthasarathy.bhuvaragan@ericsson.com>
Acked-by: Ying Xue <ying.xue@windriver.com>
Signed-off-by: Jon Maloy <jon.maloy@ericsson.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/tipc/name_table.c
net/tipc/name_table.h
net/tipc/socket.c

index e190460fe0d396e795da064c9c3fe4523177879c..5a86df1e5fc20167ce2b48bd7b4e4309492fea6d 100644 (file)
@@ -608,7 +608,7 @@ not_found:
  * Returns non-zero if any off-node ports overlap
  */
 int tipc_nametbl_mc_translate(struct net *net, u32 type, u32 lower, u32 upper,
-                             u32 limit, struct tipc_plist *dports)
+                             u32 limit, struct list_head *dports)
 {
        struct name_seq *seq;
        struct sub_seq *sseq;
@@ -633,7 +633,7 @@ int tipc_nametbl_mc_translate(struct net *net, u32 type, u32 lower, u32 upper,
                info = sseq->info;
                list_for_each_entry(publ, &info->node_list, node_list) {
                        if (publ->scope <= limit)
-                               tipc_plist_push(dports, publ->ref);
+                               u32_push(dports, publ->ref);
                }
 
                if (info->cluster_list_size != info->node_list_size)
@@ -1022,40 +1022,84 @@ int tipc_nl_name_table_dump(struct sk_buff *skb, struct netlink_callback *cb)
        return skb->len;
 }
 
-void tipc_plist_push(struct tipc_plist *pl, u32 port)
+struct u32_item {
+       struct list_head list;
+       u32 value;
+};
+
+bool u32_find(struct list_head *l, u32 value)
 {
-       struct tipc_plist *nl;
+       struct u32_item *item;
 
-       if (likely(!pl->port)) {
-               pl->port = port;
-               return;
+       list_for_each_entry(item, l, list) {
+               if (item->value == value)
+                       return true;
        }
-       if (pl->port == port)
-               return;
-       list_for_each_entry(nl, &pl->list, list) {
-               if (nl->port == port)
-                       return;
+       return false;
+}
+
+bool u32_push(struct list_head *l, u32 value)
+{
+       struct u32_item *item;
+
+       list_for_each_entry(item, l, list) {
+               if (item->value == value)
+                       return false;
+       }
+       item = kmalloc(sizeof(*item), GFP_ATOMIC);
+       if (unlikely(!item))
+               return false;
+
+       item->value = value;
+       list_add(&item->list, l);
+       return true;
+}
+
+u32 u32_pop(struct list_head *l)
+{
+       struct u32_item *item;
+       u32 value = 0;
+
+       if (list_empty(l))
+               return 0;
+       item = list_first_entry(l, typeof(*item), list);
+       value = item->value;
+       list_del(&item->list);
+       kfree(item);
+       return value;
+}
+
+bool u32_del(struct list_head *l, u32 value)
+{
+       struct u32_item *item, *tmp;
+
+       list_for_each_entry_safe(item, tmp, l, list) {
+               if (item->value != value)
+                       continue;
+               list_del(&item->list);
+               kfree(item);
+               return true;
        }
-       nl = kmalloc(sizeof(*nl), GFP_ATOMIC);
-       if (nl) {
-               nl->port = port;
-               list_add(&nl->list, &pl->list);
+       return false;
+}
+
+void u32_list_purge(struct list_head *l)
+{
+       struct u32_item *item, *tmp;
+
+       list_for_each_entry_safe(item, tmp, l, list) {
+               list_del(&item->list);
+               kfree(item);
        }
 }
 
-u32 tipc_plist_pop(struct tipc_plist *pl)
+int u32_list_len(struct list_head *l)
 {
-       struct tipc_plist *nl;
-       u32 port = 0;
+       struct u32_item *item;
+       int i = 0;
 
-       if (likely(list_empty(&pl->list))) {
-               port = pl->port;
-               pl->port = 0;
-               return port;
+       list_for_each_entry(item, l, list) {
+               i++;
        }
-       nl = list_first_entry(&pl->list, typeof(*nl), list);
-       port = nl->port;
-       list_del(&nl->list);
-       kfree(nl);
-       return port;
+       return i;
 }
index 1524a73830f7e89b078cd374d81e725daea39a3c..c89bb3f5c364c7a342a0006d42d48b64d2f86db3 100644 (file)
@@ -99,7 +99,7 @@ int tipc_nl_name_table_dump(struct sk_buff *skb, struct netlink_callback *cb);
 
 u32 tipc_nametbl_translate(struct net *net, u32 type, u32 instance, u32 *node);
 int tipc_nametbl_mc_translate(struct net *net, u32 type, u32 lower, u32 upper,
-                             u32 limit, struct tipc_plist *dports);
+                             u32 limit, struct list_head *dports);
 struct publication *tipc_nametbl_publish(struct net *net, u32 type, u32 lower,
                                         u32 upper, u32 scope, u32 port_ref,
                                         u32 key);
@@ -116,18 +116,11 @@ void tipc_nametbl_unsubscribe(struct tipc_subscription *s);
 int tipc_nametbl_init(struct net *net);
 void tipc_nametbl_stop(struct net *net);
 
-struct tipc_plist {
-       struct list_head list;
-       u32 port;
-};
-
-static inline void tipc_plist_init(struct tipc_plist *pl)
-{
-       INIT_LIST_HEAD(&pl->list);
-       pl->port = 0;
-}
-
-void tipc_plist_push(struct tipc_plist *pl, u32 port);
-u32 tipc_plist_pop(struct tipc_plist *pl);
+bool u32_push(struct list_head *l, u32 value);
+u32 u32_pop(struct list_head *l);
+bool u32_find(struct list_head *l, u32 value);
+bool u32_del(struct list_head *l, u32 value);
+void u32_list_purge(struct list_head *l);
+int u32_list_len(struct list_head *l);
 
 #endif
index f27462eeccbe6f8b6403cde79390df6cf2003928..fae6a55ef1b08efd78bb220f827fbdd09afad0ac 100644 (file)
@@ -788,7 +788,7 @@ void tipc_sk_mcast_rcv(struct net *net, struct sk_buff_head *arrvq,
                       struct sk_buff_head *inputq)
 {
        struct tipc_msg *msg;
-       struct tipc_plist dports;
+       struct list_head dports;
        u32 portid;
        u32 scope = TIPC_CLUSTER_SCOPE;
        struct sk_buff_head tmpq;
@@ -796,7 +796,7 @@ void tipc_sk_mcast_rcv(struct net *net, struct sk_buff_head *arrvq,
        struct sk_buff *skb, *_skb;
 
        __skb_queue_head_init(&tmpq);
-       tipc_plist_init(&dports);
+       INIT_LIST_HEAD(&dports);
 
        skb = tipc_skb_peek(arrvq, &inputq->lock);
        for (; skb; skb = tipc_skb_peek(arrvq, &inputq->lock)) {
@@ -810,8 +810,8 @@ void tipc_sk_mcast_rcv(struct net *net, struct sk_buff_head *arrvq,
                tipc_nametbl_mc_translate(net,
                                          msg_nametype(msg), msg_namelower(msg),
                                          msg_nameupper(msg), scope, &dports);
-               portid = tipc_plist_pop(&dports);
-               for (; portid; portid = tipc_plist_pop(&dports)) {
+               portid = u32_pop(&dports);
+               for (; portid; portid = u32_pop(&dports)) {
                        _skb = __pskb_copy(skb, hsz, GFP_ATOMIC);
                        if (_skb) {
                                msg_set_destport(buf_msg(_skb), portid);