l2tp: use get_next APIs for management requests and procfs/debugfs
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>
This commit is contained in:
parent
aa92c1cec9
commit
1f4c3dce91
@ -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)
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user