]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
l2tp: use get_next APIs for management requests and procfs/debugfs
authorJames Chapman <jchapman@katalix.com>
Wed, 7 Aug 2024 06:54:49 +0000 (07:54 +0100)
committerDavid S. Miller <davem@davemloft.net>
Sun, 11 Aug 2024 03:38:49 +0000 (04:38 +0100)
l2tp netlink and procfs/debugfs iterate over tunnel and session lists
to obtain data. They currently use very inefficient get_nth functions
to do so. Replace these with get_next.

For netlink, use nl cb->ctx[] for passing state instead of the
obsolete cb->args[].

l2tp_tunnel_get_nth and l2tp_session_get_nth are no longer used so
they can be removed.

Signed-off-by: James Chapman <jchapman@katalix.com>
Signed-off-by: Tom Parkin <tparkin@katalix.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/l2tp/l2tp_core.c
net/l2tp/l2tp_core.h
net/l2tp/l2tp_debugfs.c
net/l2tp/l2tp_netlink.c
net/l2tp/l2tp_ppp.c

index 5e36f45e906b9f263b8cb32d7f3d6241bc4cb337..2e60957ee8211299d9b9e7a7fff48ec8b69fe332 100644 (file)
@@ -241,27 +241,6 @@ struct l2tp_tunnel *l2tp_tunnel_get(const struct net *net, u32 tunnel_id)
 }
 EXPORT_SYMBOL_GPL(l2tp_tunnel_get);
 
-struct l2tp_tunnel *l2tp_tunnel_get_nth(const struct net *net, int nth)
-{
-       struct l2tp_net *pn = l2tp_pernet(net);
-       unsigned long tunnel_id, tmp;
-       struct l2tp_tunnel *tunnel;
-       int count = 0;
-
-       rcu_read_lock_bh();
-       idr_for_each_entry_ul(&pn->l2tp_tunnel_idr, tunnel, tmp, tunnel_id) {
-               if (tunnel && ++count > nth &&
-                   refcount_inc_not_zero(&tunnel->ref_count)) {
-                       rcu_read_unlock_bh();
-                       return tunnel;
-               }
-       }
-       rcu_read_unlock_bh();
-
-       return NULL;
-}
-EXPORT_SYMBOL_GPL(l2tp_tunnel_get_nth);
-
 struct l2tp_tunnel *l2tp_tunnel_get_next(const struct net *net, unsigned long *key)
 {
        struct l2tp_net *pn = l2tp_pernet(net);
@@ -355,25 +334,6 @@ struct l2tp_session *l2tp_session_get(const struct net *net, struct sock *sk, in
 }
 EXPORT_SYMBOL_GPL(l2tp_session_get);
 
-struct l2tp_session *l2tp_session_get_nth(struct l2tp_tunnel *tunnel, int nth)
-{
-       struct l2tp_session *session;
-       int count = 0;
-
-       rcu_read_lock_bh();
-       list_for_each_entry_rcu(session, &tunnel->session_list, list) {
-               if (++count > nth) {
-                       l2tp_session_inc_refcount(session);
-                       rcu_read_unlock_bh();
-                       return session;
-               }
-       }
-       rcu_read_unlock_bh();
-
-       return NULL;
-}
-EXPORT_SYMBOL_GPL(l2tp_session_get_nth);
-
 static struct l2tp_session *l2tp_v2_session_get_next(const struct net *net,
                                                     u16 tid,
                                                     unsigned long *key)
index cc464982a7d97c35496621a6655d7355a5fb105a..0fabacffc3f38cee996be925baf0f6ee92af8dfa 100644 (file)
@@ -219,14 +219,12 @@ void l2tp_session_dec_refcount(struct l2tp_session *session);
  * the caller must ensure that the reference is dropped appropriately.
  */
 struct l2tp_tunnel *l2tp_tunnel_get(const struct net *net, u32 tunnel_id);
-struct l2tp_tunnel *l2tp_tunnel_get_nth(const struct net *net, int nth);
 struct l2tp_tunnel *l2tp_tunnel_get_next(const struct net *net, unsigned long *key);
 
 struct l2tp_session *l2tp_v3_session_get(const struct net *net, struct sock *sk, u32 session_id);
 struct l2tp_session *l2tp_v2_session_get(const struct net *net, u16 tunnel_id, u16 session_id);
 struct l2tp_session *l2tp_session_get(const struct net *net, struct sock *sk, int pver,
                                      u32 tunnel_id, u32 session_id);
-struct l2tp_session *l2tp_session_get_nth(struct l2tp_tunnel *tunnel, int nth);
 struct l2tp_session *l2tp_session_get_next(const struct net *net, struct sock *sk, int pver,
                                           u32 tunnel_id, unsigned long *key);
 struct l2tp_session *l2tp_session_get_by_ifname(const struct net *net,
index 8755ae521154d77eb5bd106fefc25e728641102e..b2134b57ed18ccdbcf6cb0cac9f906125a17a840 100644 (file)
@@ -34,8 +34,8 @@ static struct dentry *rootdir;
 struct l2tp_dfs_seq_data {
        struct net      *net;
        netns_tracker   ns_tracker;
-       int tunnel_idx;                 /* current tunnel */
-       int session_idx;                /* index of session within current tunnel */
+       unsigned long tkey;             /* lookup key of current tunnel */
+       unsigned long skey;             /* lookup key of current session */
        struct l2tp_tunnel *tunnel;
        struct l2tp_session *session;   /* NULL means get next tunnel */
 };
@@ -46,8 +46,8 @@ static void l2tp_dfs_next_tunnel(struct l2tp_dfs_seq_data *pd)
        if (pd->tunnel)
                l2tp_tunnel_dec_refcount(pd->tunnel);
 
-       pd->tunnel = l2tp_tunnel_get_nth(pd->net, pd->tunnel_idx);
-       pd->tunnel_idx++;
+       pd->tunnel = l2tp_tunnel_get_next(pd->net, &pd->tkey);
+       pd->tkey++;
 }
 
 static void l2tp_dfs_next_session(struct l2tp_dfs_seq_data *pd)
@@ -56,11 +56,13 @@ static void l2tp_dfs_next_session(struct l2tp_dfs_seq_data *pd)
        if (pd->session)
                l2tp_session_dec_refcount(pd->session);
 
-       pd->session = l2tp_session_get_nth(pd->tunnel, pd->session_idx);
-       pd->session_idx++;
+       pd->session = l2tp_session_get_next(pd->net, pd->tunnel->sock,
+                                           pd->tunnel->version,
+                                           pd->tunnel->tunnel_id, &pd->skey);
+       pd->skey++;
 
        if (!pd->session) {
-               pd->session_idx = 0;
+               pd->skey = 0;
                l2tp_dfs_next_tunnel(pd);
        }
 }
index fc43ecbd128cc5c866de4c8dc84b2c9e9e6382cf..0598b97a0bcae9d114d5cc1e94ecd70d737708ac 100644 (file)
@@ -491,14 +491,20 @@ err:
        return ret;
 }
 
+struct l2tp_nl_cb_data {
+       unsigned long tkey;
+       unsigned long skey;
+};
+
 static int l2tp_nl_cmd_tunnel_dump(struct sk_buff *skb, struct netlink_callback *cb)
 {
-       int ti = cb->args[0];
+       struct l2tp_nl_cb_data *cbd = (void *)&cb->ctx[0];
+       unsigned long key = cbd->tkey;
        struct l2tp_tunnel *tunnel;
        struct net *net = sock_net(skb->sk);
 
        for (;;) {
-               tunnel = l2tp_tunnel_get_nth(net, ti);
+               tunnel = l2tp_tunnel_get_next(net, &key);
                if (!tunnel)
                        goto out;
 
@@ -510,11 +516,11 @@ static int l2tp_nl_cmd_tunnel_dump(struct sk_buff *skb, struct netlink_callback
                }
                l2tp_tunnel_dec_refcount(tunnel);
 
-               ti++;
+               key++;
        }
 
 out:
-       cb->args[0] = ti;
+       cbd->tkey = key;
 
        return skb->len;
 }
@@ -832,25 +838,27 @@ err:
 
 static int l2tp_nl_cmd_session_dump(struct sk_buff *skb, struct netlink_callback *cb)
 {
+       struct l2tp_nl_cb_data *cbd = (void *)&cb->ctx[0];
        struct net *net = sock_net(skb->sk);
        struct l2tp_session *session;
        struct l2tp_tunnel *tunnel = NULL;
-       int ti = cb->args[0];
-       int si = cb->args[1];
+       unsigned long tkey = cbd->tkey;
+       unsigned long skey = cbd->skey;
 
        for (;;) {
                if (!tunnel) {
-                       tunnel = l2tp_tunnel_get_nth(net, ti);
+                       tunnel = l2tp_tunnel_get_next(net, &tkey);
                        if (!tunnel)
                                goto out;
                }
 
-               session = l2tp_session_get_nth(tunnel, si);
+               session = l2tp_session_get_next(net, tunnel->sock, tunnel->version,
+                                               tunnel->tunnel_id, &skey);
                if (!session) {
-                       ti++;
+                       tkey++;
                        l2tp_tunnel_dec_refcount(tunnel);
                        tunnel = NULL;
-                       si = 0;
+                       skey = 0;
                        continue;
                }
 
@@ -863,12 +871,12 @@ static int l2tp_nl_cmd_session_dump(struct sk_buff *skb, struct netlink_callback
                }
                l2tp_session_dec_refcount(session);
 
-               si++;
+               skey++;
        }
 
 out:
-       cb->args[0] = ti;
-       cb->args[1] = si;
+       cbd->tkey = tkey;
+       cbd->skey = skey;
 
        return skb->len;
 }
index c25dd8e3607400a11adf8a5aaf3941a91206a7f9..8459e5159430af547744b3905cc046ce51067410 100644 (file)
@@ -1397,8 +1397,8 @@ end:
 
 struct pppol2tp_seq_data {
        struct seq_net_private p;
-       int tunnel_idx;                 /* current tunnel */
-       int session_idx;                /* index of session within current tunnel */
+       unsigned long tkey;             /* lookup key of current tunnel */
+       unsigned long skey;             /* lookup key of current session */
        struct l2tp_tunnel *tunnel;
        struct l2tp_session *session;   /* NULL means get next tunnel */
 };
@@ -1410,8 +1410,8 @@ static void pppol2tp_next_tunnel(struct net *net, struct pppol2tp_seq_data *pd)
                l2tp_tunnel_dec_refcount(pd->tunnel);
 
        for (;;) {
-               pd->tunnel = l2tp_tunnel_get_nth(net, pd->tunnel_idx);
-               pd->tunnel_idx++;
+               pd->tunnel = l2tp_tunnel_get_next(net, &pd->tkey);
+               pd->tkey++;
 
                /* Only accept L2TPv2 tunnels */
                if (!pd->tunnel || pd->tunnel->version == 2)
@@ -1427,11 +1427,13 @@ static void pppol2tp_next_session(struct net *net, struct pppol2tp_seq_data *pd)
        if (pd->session)
                l2tp_session_dec_refcount(pd->session);
 
-       pd->session = l2tp_session_get_nth(pd->tunnel, pd->session_idx);
-       pd->session_idx++;
+       pd->session = l2tp_session_get_next(net, pd->tunnel->sock,
+                                           pd->tunnel->version,
+                                           pd->tunnel->tunnel_id, &pd->skey);
+       pd->skey++;
 
        if (!pd->session) {
-               pd->session_idx = 0;
+               pd->skey = 0;
                pppol2tp_next_tunnel(net, pd);
        }
 }