net/mlx5: Add new list to store deleted flow counters
authorVlad Buslov <vladbu@mellanox.com>
Mon, 23 Jul 2018 08:32:05 +0000 (11:32 +0300)
committerSaeed Mahameed <saeedm@mellanox.com>
Thu, 6 Sep 2018 04:14:57 +0000 (21:14 -0700)
In order to prevent flow counters stats work function from traversing whole
flow counters tree while searching for deleted flow counters, new list to
store deleted flow counters is added to struct mlx5_fc_stats. Lockless
NULL-terminated single linked list data type is used due to following
reasons:
 - This use case only needs to add single element to list and
 remove/iterate whole list. Lockless list doesn't require any additional
 synchronization for these operations.
 - First cache line of flow counter data structure only has space to store
 single additional pointer, which precludes usage of double linked list.

Remove flow counter 'deleted' flag that is no longer needed.

Signed-off-by: Vlad Buslov <vladbu@mellanox.com>
Acked-by: Amir Vadai <amir@vadai.me>
Reviewed-by: Paul Blakey <paulb@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
drivers/net/ethernet/mellanox/mlx5/core/fs_core.h
drivers/net/ethernet/mellanox/mlx5/core/fs_counters.c
include/linux/mlx5/driver.h

index f68590291e0cd48ed160c02195f0589bd1cb9e74..617d6239c5f343d4499704401669879b163d30ce 100644 (file)
@@ -141,6 +141,7 @@ struct mlx5_fc_cache {
 struct mlx5_fc {
        struct rb_node node;
        struct llist_node addlist;
 struct mlx5_fc {
        struct rb_node node;
        struct llist_node addlist;
+       struct llist_node dellist;
 
        /* last{packets,bytes} members are used when calculating the delta since
         * last reading
 
        /* last{packets,bytes} members are used when calculating the delta since
         * last reading
@@ -149,7 +150,6 @@ struct mlx5_fc {
        u64 lastbytes;
 
        u32 id;
        u64 lastbytes;
 
        u32 id;
-       bool deleted;
        bool aging;
 
        struct mlx5_fc_cache cache ____cacheline_aligned_in_smp;
        bool aging;
 
        struct mlx5_fc_cache cache ____cacheline_aligned_in_smp;
index d996d6cf9e198a59e49c4e2f7b40f118a51af8ac..f1266f215a31319425d8111ecc804434817964c4 100644 (file)
@@ -58,7 +58,7 @@
  *   - spawn thread to do the actual destroy
  *
  * - destroy (user context)
  *   - spawn thread to do the actual destroy
  *
  * - destroy (user context)
- *   - mark a counter as deleted
+ *   - add a counter to lockless dellist
  *   - spawn thread to do the actual del
  *
  * - dump (user context)
  *   - spawn thread to do the actual del
  *
  * - dump (user context)
@@ -171,9 +171,8 @@ static void mlx5_fc_stats_work(struct work_struct *work)
                                                 priv.fc_stats.work.work);
        struct mlx5_fc_stats *fc_stats = &dev->priv.fc_stats;
        struct llist_node *tmplist = llist_del_all(&fc_stats->addlist);
                                                 priv.fc_stats.work.work);
        struct mlx5_fc_stats *fc_stats = &dev->priv.fc_stats;
        struct llist_node *tmplist = llist_del_all(&fc_stats->addlist);
+       struct mlx5_fc *counter = NULL, *last = NULL, *tmp;
        unsigned long now = jiffies;
        unsigned long now = jiffies;
-       struct mlx5_fc *counter = NULL;
-       struct mlx5_fc *last = NULL;
        struct rb_node *node;
 
        if (tmplist || !RB_EMPTY_ROOT(&fc_stats->counters))
        struct rb_node *node;
 
        if (tmplist || !RB_EMPTY_ROOT(&fc_stats->counters))
@@ -183,26 +182,17 @@ static void mlx5_fc_stats_work(struct work_struct *work)
        llist_for_each_entry(counter, tmplist, addlist)
                mlx5_fc_stats_insert(&fc_stats->counters, counter);
 
        llist_for_each_entry(counter, tmplist, addlist)
                mlx5_fc_stats_insert(&fc_stats->counters, counter);
 
-       node = rb_first(&fc_stats->counters);
-       while (node) {
-               counter = rb_entry(node, struct mlx5_fc, node);
-
-               node = rb_next(node);
-
-               if (counter->deleted) {
-                       rb_erase(&counter->node, &fc_stats->counters);
-
-                       mlx5_cmd_fc_free(dev, counter->id);
-
-                       kfree(counter);
-                       continue;
-               }
+       tmplist = llist_del_all(&fc_stats->dellist);
+       llist_for_each_entry_safe(counter, tmp, tmplist, dellist) {
+               rb_erase(&counter->node, &fc_stats->counters);
 
 
-               last = counter;
+               mlx5_free_fc(dev, counter);
        }
 
        }
 
-       if (time_before(now, fc_stats->next_query) || !last)
+       node = rb_last(&fc_stats->counters);
+       if (time_before(now, fc_stats->next_query) || !node)
                return;
                return;
+       last = rb_entry(node, struct mlx5_fc, node);
 
        node = rb_first(&fc_stats->counters);
        while (node) {
 
        node = rb_first(&fc_stats->counters);
        while (node) {
@@ -254,13 +244,12 @@ void mlx5_fc_destroy(struct mlx5_core_dev *dev, struct mlx5_fc *counter)
                return;
 
        if (counter->aging) {
                return;
 
        if (counter->aging) {
-               counter->deleted = true;
+               llist_add(&counter->dellist, &fc_stats->dellist);
                mod_delayed_work(fc_stats->wq, &fc_stats->work, 0);
                return;
        }
 
                mod_delayed_work(fc_stats->wq, &fc_stats->work, 0);
                return;
        }
 
-       mlx5_cmd_fc_free(dev, counter->id);
-       kfree(counter);
+       mlx5_free_fc(dev, counter);
 }
 EXPORT_SYMBOL(mlx5_fc_destroy);
 
 }
 EXPORT_SYMBOL(mlx5_fc_destroy);
 
@@ -270,6 +259,7 @@ int mlx5_init_fc_stats(struct mlx5_core_dev *dev)
 
        fc_stats->counters = RB_ROOT;
        init_llist_head(&fc_stats->addlist);
 
        fc_stats->counters = RB_ROOT;
        init_llist_head(&fc_stats->addlist);
+       init_llist_head(&fc_stats->dellist);
 
        fc_stats->wq = create_singlethread_workqueue("mlx5_fc");
        if (!fc_stats->wq)
 
        fc_stats->wq = create_singlethread_workqueue("mlx5_fc");
        if (!fc_stats->wq)
index c00549293982ebf305d8e4ac05829d05f6b6c0b2..4b53ac64004b9b5d2afef0f0e0f3f4cd304ae2c4 100644 (file)
@@ -585,6 +585,7 @@ struct mlx5_irq_info {
 struct mlx5_fc_stats {
        struct rb_root counters;
        struct llist_head addlist;
 struct mlx5_fc_stats {
        struct rb_root counters;
        struct llist_head addlist;
+       struct llist_head dellist;
 
        struct workqueue_struct *wq;
        struct delayed_work work;
 
        struct workqueue_struct *wq;
        struct delayed_work work;