Skip to content

Commit

Permalink
ila: Fix use of rhashtable walk in ila_xlat.c
Browse files Browse the repository at this point in the history
Perform better EAGAIN handling, handle case where ila_dump_info
fails and we missed objects in the dump, and add a skip index
to skip over ila entires in a list on a rhashtable node that have
already been visited (by a previous call to ila_nl_dump).

Signed-off-by: Tom Herbert <tom@quantonium.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Tom Herbert authored and David S. Miller committed Jun 29, 2018
1 parent 6d26891 commit f7a2ba5
Showing 1 changed file with 54 additions and 16 deletions.
70 changes: 54 additions & 16 deletions net/ipv6/ila/ila_xlat.c
Original file line number Diff line number Diff line change
Expand Up @@ -475,24 +475,31 @@ static int ila_nl_cmd_get_mapping(struct sk_buff *skb, struct genl_info *info)

struct ila_dump_iter {
struct rhashtable_iter rhiter;
int skip;
};

static int ila_nl_dump_start(struct netlink_callback *cb)
{
struct net *net = sock_net(cb->skb->sk);
struct ila_net *ilan = net_generic(net, ila_net_id);
struct ila_dump_iter *iter = (struct ila_dump_iter *)cb->args[0];
struct ila_dump_iter *iter;
int ret;

if (!iter) {
iter = kmalloc(sizeof(*iter), GFP_KERNEL);
if (!iter)
return -ENOMEM;
iter = kmalloc(sizeof(*iter), GFP_KERNEL);
if (!iter)
return -ENOMEM;

cb->args[0] = (long)iter;
ret = rhashtable_walk_init(&ilan->rhash_table, &iter->rhiter,
GFP_KERNEL);
if (ret) {
kfree(iter);
return ret;
}

return rhashtable_walk_init(&ilan->rhash_table, &iter->rhiter,
GFP_KERNEL);
iter->skip = 0;
cb->args[0] = (long)iter;

return ret;
}

static int ila_nl_dump_done(struct netlink_callback *cb)
Expand All @@ -510,20 +517,45 @@ static int ila_nl_dump(struct sk_buff *skb, struct netlink_callback *cb)
{
struct ila_dump_iter *iter = (struct ila_dump_iter *)cb->args[0];
struct rhashtable_iter *rhiter = &iter->rhiter;
int skip = iter->skip;
struct ila_map *ila;
int ret;

rhashtable_walk_start(rhiter);

for (;;) {
ila = rhashtable_walk_next(rhiter);
/* Get first entry */
ila = rhashtable_walk_peek(rhiter);

if (ila && !IS_ERR(ila) && skip) {
/* Skip over visited entries */

while (ila && skip) {
/* Skip over any ila entries in this list that we
* have already dumped.
*/
ila = rcu_access_pointer(ila->next);
skip--;
}
}

skip = 0;

for (;;) {
if (IS_ERR(ila)) {
if (PTR_ERR(ila) == -EAGAIN)
continue;
ret = PTR_ERR(ila);
goto done;
if (ret == -EAGAIN) {
/* Table has changed and iter has reset. Return
* -EAGAIN to the application even if we have
* written data to the skb. The application
* needs to deal with this.
*/

goto out_ret;
} else {
break;
}
} else if (!ila) {
ret = 0;
break;
}

Expand All @@ -532,15 +564,21 @@ static int ila_nl_dump(struct sk_buff *skb, struct netlink_callback *cb)
cb->nlh->nlmsg_seq, NLM_F_MULTI,
skb, ILA_CMD_GET);
if (ret)
goto done;
goto out;

skip++;
ila = rcu_access_pointer(ila->next);
}

skip = 0;
ila = rhashtable_walk_next(rhiter);
}

ret = skb->len;
out:
iter->skip = skip;
ret = (skb->len ? : ret);

done:
out_ret:
rhashtable_walk_stop(rhiter);
return ret;
}
Expand Down

0 comments on commit f7a2ba5

Please sign in to comment.