ipmr, ip6mr: Unite mfc seq logic
authorYuval Mintz <yuvalm@mellanox.com>
Wed, 28 Feb 2018 21:29:36 +0000 (23:29 +0200)
committerDavid S. Miller <davem@davemloft.net>
Thu, 1 Mar 2018 18:13:23 +0000 (13:13 -0500)
With the exception of the final dump, ipmr and ip6mr have the exact same
seq logic for traversing a given mr_table. Refactor that code and make
it common.

Signed-off-by: Yuval Mintz <yuvalm@mellanox.com>
Acked-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/linux/mroute_base.h
net/ipv4/ipmr.c
net/ipv4/ipmr_base.c
net/ipv6/ip6mr.c

index 46a082e25dab1eba452e78076fa7d775d6f758e7..a007c5ad0fde56033430c52ca7827dbbfe9ca98d 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <linux/netdevice.h>
 #include <linux/rhashtable.h>
+#include <linux/spinlock.h>
 #include <net/net_namespace.h>
 #include <net/sock.h>
 
@@ -203,4 +204,72 @@ static inline void *mr_mfc_find(struct mr_table *mrt, void *hasharg)
 {
        return mr_mfc_find_parent(mrt, hasharg, -1);
 }
+
+#ifdef CONFIG_PROC_FS
+struct mr_mfc_iter {
+       struct seq_net_private p;
+       struct mr_table *mrt;
+       struct list_head *cache;
+
+       /* Lock protecting the mr_table's unresolved queue */
+       spinlock_t *lock;
+};
+
+#ifdef CONFIG_IP_MROUTE_COMMON
+/* These actually return 'struct mr_mfc *', but to avoid need for explicit
+ * castings they simply return void.
+ */
+void *mr_mfc_seq_idx(struct net *net,
+                    struct mr_mfc_iter *it, loff_t pos);
+void *mr_mfc_seq_next(struct seq_file *seq, void *v,
+                     loff_t *pos);
+
+static inline void *mr_mfc_seq_start(struct seq_file *seq, loff_t *pos,
+                                    struct mr_table *mrt, spinlock_t *lock)
+{
+       struct mr_mfc_iter *it = seq->private;
+
+       it->mrt = mrt;
+       it->cache = NULL;
+       it->lock = lock;
+
+       return *pos ? mr_mfc_seq_idx(seq_file_net(seq),
+                                    seq->private, *pos - 1)
+                   : SEQ_START_TOKEN;
+}
+
+static inline void mr_mfc_seq_stop(struct seq_file *seq, void *v)
+{
+       struct mr_mfc_iter *it = seq->private;
+       struct mr_table *mrt = it->mrt;
+
+       if (it->cache == &mrt->mfc_unres_queue)
+               spin_unlock_bh(it->lock);
+       else if (it->cache == &mrt->mfc_cache_list)
+               rcu_read_unlock();
+}
+#else
+static inline void *mr_mfc_seq_idx(struct net *net,
+                                  struct mr_mfc_iter *it, loff_t pos)
+{
+       return NULL;
+}
+
+static inline void *mr_mfc_seq_next(struct seq_file *seq, void *v,
+                                   loff_t *pos)
+{
+       return NULL;
+}
+
+static inline void *mr_mfc_seq_start(struct seq_file *seq, loff_t *pos,
+                                    struct mr_table *mrt, spinlock_t *lock)
+{
+       return NULL;
+}
+
+static inline void mr_mfc_seq_stop(struct seq_file *seq, void *v)
+{
+}
+#endif
+#endif
 #endif
index 00898c319cc5f31b2a782e5d36a853c1e7c5c1f9..1eb19d9b1be0fef93d99fb19604fea7c82b0d769 100644 (file)
@@ -3014,41 +3014,8 @@ static const struct file_operations ipmr_vif_fops = {
        .release = seq_release_net,
 };
 
-struct ipmr_mfc_iter {
-       struct seq_net_private p;
-       struct mr_table *mrt;
-       struct list_head *cache;
-};
-
-static struct mfc_cache *ipmr_mfc_seq_idx(struct net *net,
-                                         struct ipmr_mfc_iter *it, loff_t pos)
-{
-       struct mr_table *mrt = it->mrt;
-       struct mr_mfc *mfc;
-
-       rcu_read_lock();
-       it->cache = &mrt->mfc_cache_list;
-       list_for_each_entry_rcu(mfc, &mrt->mfc_cache_list, list)
-               if (pos-- == 0)
-                       return (struct mfc_cache *)mfc;
-       rcu_read_unlock();
-
-       spin_lock_bh(&mfc_unres_lock);
-       it->cache = &mrt->mfc_unres_queue;
-       list_for_each_entry(mfc, it->cache, list)
-               if (pos-- == 0)
-                       return (struct mfc_cache *)mfc;
-
-       spin_unlock_bh(&mfc_unres_lock);
-
-       it->cache = NULL;
-       return NULL;
-}
-
-
 static void *ipmr_mfc_seq_start(struct seq_file *seq, loff_t *pos)
 {
-       struct ipmr_mfc_iter *it = seq->private;
        struct net *net = seq_file_net(seq);
        struct mr_table *mrt;
 
@@ -3056,57 +3023,7 @@ static void *ipmr_mfc_seq_start(struct seq_file *seq, loff_t *pos)
        if (!mrt)
                return ERR_PTR(-ENOENT);
 
-       it->mrt = mrt;
-       it->cache = NULL;
-       return *pos ? ipmr_mfc_seq_idx(net, seq->private, *pos - 1)
-               : SEQ_START_TOKEN;
-}
-
-static void *ipmr_mfc_seq_next(struct seq_file *seq, void *v, loff_t *pos)
-{
-       struct ipmr_mfc_iter *it = seq->private;
-       struct net *net = seq_file_net(seq);
-       struct mr_table *mrt = it->mrt;
-       struct mfc_cache *mfc = v;
-
-       ++*pos;
-
-       if (v == SEQ_START_TOKEN)
-               return ipmr_mfc_seq_idx(net, seq->private, 0);
-
-       if (mfc->_c.list.next != it->cache)
-               return (struct mfc_cache *)(list_entry(mfc->_c.list.next,
-                                                      struct mr_mfc, list));
-
-       if (it->cache == &mrt->mfc_unres_queue)
-               goto end_of_list;
-
-       /* exhausted cache_array, show unresolved */
-       rcu_read_unlock();
-       it->cache = &mrt->mfc_unres_queue;
-
-       spin_lock_bh(&mfc_unres_lock);
-       if (!list_empty(it->cache))
-               return (struct mfc_cache *)(list_first_entry(it->cache,
-                                                            struct mr_mfc,
-                                                            list));
-
-end_of_list:
-       spin_unlock_bh(&mfc_unres_lock);
-       it->cache = NULL;
-
-       return NULL;
-}
-
-static void ipmr_mfc_seq_stop(struct seq_file *seq, void *v)
-{
-       struct ipmr_mfc_iter *it = seq->private;
-       struct mr_table *mrt = it->mrt;
-
-       if (it->cache == &mrt->mfc_unres_queue)
-               spin_unlock_bh(&mfc_unres_lock);
-       else if (it->cache == &mrt->mfc_cache_list)
-               rcu_read_unlock();
+       return mr_mfc_seq_start(seq, pos, mrt, &mfc_unres_lock);
 }
 
 static int ipmr_mfc_seq_show(struct seq_file *seq, void *v)
@@ -3118,7 +3035,7 @@ static int ipmr_mfc_seq_show(struct seq_file *seq, void *v)
                 "Group    Origin   Iif     Pkts    Bytes    Wrong Oifs\n");
        } else {
                const struct mfc_cache *mfc = v;
-               const struct ipmr_mfc_iter *it = seq->private;
+               const struct mr_mfc_iter *it = seq->private;
                const struct mr_table *mrt = it->mrt;
 
                seq_printf(seq, "%08X %08X %-3hd",
@@ -3152,15 +3069,15 @@ static int ipmr_mfc_seq_show(struct seq_file *seq, void *v)
 
 static const struct seq_operations ipmr_mfc_seq_ops = {
        .start = ipmr_mfc_seq_start,
-       .next  = ipmr_mfc_seq_next,
-       .stop  = ipmr_mfc_seq_stop,
+       .next  = mr_mfc_seq_next,
+       .stop  = mr_mfc_seq_stop,
        .show  = ipmr_mfc_seq_show,
 };
 
 static int ipmr_mfc_open(struct inode *inode, struct file *file)
 {
        return seq_open_net(inode, file, &ipmr_mfc_seq_ops,
-                           sizeof(struct ipmr_mfc_iter));
+                           sizeof(struct mr_mfc_iter));
 }
 
 static const struct file_operations ipmr_mfc_fops = {
index 172f92acffef8f5cdb1ffa07781513f85894843f..37ad0a79303577610e65ecb71cfe7d5679d7dbd3 100644 (file)
@@ -103,3 +103,65 @@ void *mr_mfc_find_any(struct mr_table *mrt, int vifi, void *hasharg)
        return mr_mfc_find_any_parent(mrt, vifi);
 }
 EXPORT_SYMBOL(mr_mfc_find_any);
+
+#ifdef CONFIG_PROC_FS
+void *mr_mfc_seq_idx(struct net *net,
+                    struct mr_mfc_iter *it, loff_t pos)
+{
+       struct mr_table *mrt = it->mrt;
+       struct mr_mfc *mfc;
+
+       rcu_read_lock();
+       it->cache = &mrt->mfc_cache_list;
+       list_for_each_entry_rcu(mfc, &mrt->mfc_cache_list, list)
+               if (pos-- == 0)
+                       return mfc;
+       rcu_read_unlock();
+
+       spin_lock_bh(it->lock);
+       it->cache = &mrt->mfc_unres_queue;
+       list_for_each_entry(mfc, it->cache, list)
+               if (pos-- == 0)
+                       return mfc;
+       spin_unlock_bh(it->lock);
+
+       it->cache = NULL;
+       return NULL;
+}
+EXPORT_SYMBOL(mr_mfc_seq_idx);
+
+void *mr_mfc_seq_next(struct seq_file *seq, void *v,
+                     loff_t *pos)
+{
+       struct mr_mfc_iter *it = seq->private;
+       struct net *net = seq_file_net(seq);
+       struct mr_table *mrt = it->mrt;
+       struct mr_mfc *c = v;
+
+       ++*pos;
+
+       if (v == SEQ_START_TOKEN)
+               return mr_mfc_seq_idx(net, seq->private, 0);
+
+       if (c->list.next != it->cache)
+               return list_entry(c->list.next, struct mr_mfc, list);
+
+       if (it->cache == &mrt->mfc_unres_queue)
+               goto end_of_list;
+
+       /* exhausted cache_array, show unresolved */
+       rcu_read_unlock();
+       it->cache = &mrt->mfc_unres_queue;
+
+       spin_lock_bh(it->lock);
+       if (!list_empty(it->cache))
+               return list_first_entry(it->cache, struct mr_mfc, list);
+
+end_of_list:
+       spin_unlock_bh(it->lock);
+       it->cache = NULL;
+
+       return NULL;
+}
+EXPORT_SYMBOL(mr_mfc_seq_next);
+#endif
index ea902a952fb6ec79c9cc92389a8e9814f2249642..26315065e7df53f5ca160244f54fb7a8f8a1a579 100644 (file)
@@ -333,40 +333,8 @@ static void ip6mr_free_table(struct mr_table *mrt)
 }
 
 #ifdef CONFIG_PROC_FS
-
-struct ipmr_mfc_iter {
-       struct seq_net_private p;
-       struct mr_table *mrt;
-       struct list_head *cache;
-};
-
-
-static struct mfc6_cache *ipmr_mfc_seq_idx(struct net *net,
-                                          struct ipmr_mfc_iter *it, loff_t pos)
-{
-       struct mr_table *mrt = it->mrt;
-       struct mr_mfc *mfc;
-
-       rcu_read_lock();
-       it->cache = &mrt->mfc_cache_list;
-       list_for_each_entry_rcu(mfc, &mrt->mfc_cache_list, list)
-               if (pos-- == 0)
-                       return (struct mfc6_cache *)mfc;
-       rcu_read_unlock();
-
-       spin_lock_bh(&mfc_unres_lock);
-       it->cache = &mrt->mfc_unres_queue;
-       list_for_each_entry(mfc, it->cache, list)
-               if (pos-- == 0)
-                       return (struct mfc6_cache *)mfc;
-       spin_unlock_bh(&mfc_unres_lock);
-
-       it->cache = NULL;
-       return NULL;
-}
-
-/*
- *     The /proc interfaces to multicast routing /proc/ip6_mr_cache /proc/ip6_mr_vif
+/* The /proc interfaces to multicast routing
+ * /proc/ip6_mr_cache /proc/ip6_mr_vif
  */
 
 struct ipmr_vif_iter {
@@ -476,7 +444,6 @@ static const struct file_operations ip6mr_vif_fops = {
 
 static void *ipmr_mfc_seq_start(struct seq_file *seq, loff_t *pos)
 {
-       struct ipmr_mfc_iter *it = seq->private;
        struct net *net = seq_file_net(seq);
        struct mr_table *mrt;
 
@@ -484,57 +451,7 @@ static void *ipmr_mfc_seq_start(struct seq_file *seq, loff_t *pos)
        if (!mrt)
                return ERR_PTR(-ENOENT);
 
-       it->mrt = mrt;
-       it->cache = NULL;
-       return *pos ? ipmr_mfc_seq_idx(net, seq->private, *pos - 1)
-               : SEQ_START_TOKEN;
-}
-
-static void *ipmr_mfc_seq_next(struct seq_file *seq, void *v, loff_t *pos)
-{
-       struct mfc6_cache *mfc = v;
-       struct ipmr_mfc_iter *it = seq->private;
-       struct net *net = seq_file_net(seq);
-       struct mr_table *mrt = it->mrt;
-
-       ++*pos;
-
-       if (v == SEQ_START_TOKEN)
-               return ipmr_mfc_seq_idx(net, seq->private, 0);
-
-       if (mfc->_c.list.next != it->cache)
-               return (struct mfc6_cache *)(list_entry(mfc->_c.list.next,
-                                                       struct mr_mfc, list));
-
-       if (it->cache == &mrt->mfc_unres_queue)
-               goto end_of_list;
-
-       /* exhausted cache_array, show unresolved */
-       rcu_read_unlock();
-       it->cache = &mrt->mfc_unres_queue;
-
-       spin_lock_bh(&mfc_unres_lock);
-       if (!list_empty(it->cache))
-               return (struct mfc6_cache *)(list_first_entry(it->cache,
-                                                             struct mr_mfc,
-                                                             list));
-
- end_of_list:
-       spin_unlock_bh(&mfc_unres_lock);
-       it->cache = NULL;
-
-       return NULL;
-}
-
-static void ipmr_mfc_seq_stop(struct seq_file *seq, void *v)
-{
-       struct ipmr_mfc_iter *it = seq->private;
-       struct mr_table *mrt = it->mrt;
-
-       if (it->cache == &mrt->mfc_unres_queue)
-               spin_unlock_bh(&mfc_unres_lock);
-       else if (it->cache == &mrt->mfc_cache_list)
-               rcu_read_unlock();
+       return mr_mfc_seq_start(seq, pos, mrt, &mfc_unres_lock);
 }
 
 static int ipmr_mfc_seq_show(struct seq_file *seq, void *v)
@@ -548,7 +465,7 @@ static int ipmr_mfc_seq_show(struct seq_file *seq, void *v)
                         "Iif      Pkts  Bytes     Wrong  Oifs\n");
        } else {
                const struct mfc6_cache *mfc = v;
-               const struct ipmr_mfc_iter *it = seq->private;
+               const struct mr_mfc_iter *it = seq->private;
                struct mr_table *mrt = it->mrt;
 
                seq_printf(seq, "%pI6 %pI6 %-3hd",
@@ -581,15 +498,15 @@ static int ipmr_mfc_seq_show(struct seq_file *seq, void *v)
 
 static const struct seq_operations ipmr_mfc_seq_ops = {
        .start = ipmr_mfc_seq_start,
-       .next  = ipmr_mfc_seq_next,
-       .stop  = ipmr_mfc_seq_stop,
+       .next  = mr_mfc_seq_next,
+       .stop  = mr_mfc_seq_stop,
        .show  = ipmr_mfc_seq_show,
 };
 
 static int ipmr_mfc_open(struct inode *inode, struct file *file)
 {
        return seq_open_net(inode, file, &ipmr_mfc_seq_ops,
-                           sizeof(struct ipmr_mfc_iter));
+                           sizeof(struct mr_mfc_iter));
 }
 
 static const struct file_operations ip6mr_mfc_fops = {