Commit 22e36ea9 authored by Eric Dumazet's avatar Eric Dumazet Committed by David S. Miller
Browse files

inet: allow ip_valid_fib_dump_req() to be called with RTNL or RCU



Add a new field into struct fib_dump_filter, to let callers
tell if they use RTNL locking or RCU.

This is used in the following patch, when inet_dump_fib()
no longer holds RTNL.

Signed-off-by: default avatarEric Dumazet <edumazet@google.com>
Reviewed-by: default avatarDonald Hunter <donald.hunter@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 69fdb7e4
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -264,6 +264,7 @@ struct fib_dump_filter {
	bool			filter_set;
	bool			dump_routes;
	bool			dump_exceptions;
	bool			rtnl_held;
	unsigned char		protocol;
	unsigned char		rt_type;
	unsigned int		flags;
+11 −4
Original line number Diff line number Diff line
@@ -916,6 +916,7 @@ int ip_valid_fib_dump_req(struct net *net, const struct nlmsghdr *nlh,
	struct rtmsg *rtm;
	int err, i;

	if (filter->rtnl_held)
		ASSERT_RTNL();

	if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*rtm))) {
@@ -961,7 +962,10 @@ int ip_valid_fib_dump_req(struct net *net, const struct nlmsghdr *nlh,
			break;
		case RTA_OIF:
			ifindex = nla_get_u32(tb[i]);
			if (filter->rtnl_held)
				filter->dev = __dev_get_by_index(net, ifindex);
			else
				filter->dev = dev_get_by_index_rcu(net, ifindex);
			if (!filter->dev)
				return -ENODEV;
			break;
@@ -983,8 +987,11 @@ EXPORT_SYMBOL_GPL(ip_valid_fib_dump_req);

static int inet_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
{
	struct fib_dump_filter filter = { .dump_routes = true,
					  .dump_exceptions = true };
	struct fib_dump_filter filter = {
		.dump_routes = true,
		.dump_exceptions = true,
		.rtnl_held = true,
	};
	const struct nlmsghdr *nlh = cb->nlh;
	struct net *net = sock_net(skb->sk);
	unsigned int h, s_h;
+3 −1
Original line number Diff line number Diff line
@@ -2587,7 +2587,9 @@ static int ipmr_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh,

static int ipmr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb)
{
	struct fib_dump_filter filter = {};
	struct fib_dump_filter filter = {
		.rtnl_held = true,
	};
	int err;

	if (cb->strict_check) {
+5 −2
Original line number Diff line number Diff line
@@ -620,8 +620,11 @@ static int fib6_dump_table(struct fib6_table *table, struct sk_buff *skb,

static int inet6_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
{
	struct rt6_rtnl_dump_arg arg = { .filter.dump_exceptions = true,
					 .filter.dump_routes = true };
	struct rt6_rtnl_dump_arg arg = {
		.filter.dump_exceptions = true,
		.filter.dump_routes = true,
		.filter.rtnl_held = true,
	};
	const struct nlmsghdr *nlh = cb->nlh;
	struct net *net = sock_net(skb->sk);
	unsigned int h, s_h;
+3 −1
Original line number Diff line number Diff line
@@ -2592,7 +2592,9 @@ static int ip6mr_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh,
static int ip6mr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb)
{
	const struct nlmsghdr *nlh = cb->nlh;
	struct fib_dump_filter filter = {};
	struct fib_dump_filter filter = {
		.rtnl_held = true,
	};
	int err;

	if (cb->strict_check) {
Loading