Skip to content

Commit 66729e1

Browse files
yoshfujiDavid S. Miller
authored andcommitted
[IPV6] ROUTE: Make sure we have fn->leaf when adding a node on subtree.
Based on MIPL2 kernel patch. Signed-off-by: YOSHIFUJI Hideaki <[email protected]> Signed-off-by: Ville Nuorvala <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 8e1ef0a commit 66729e1

File tree

1 file changed

+26
-6
lines changed

1 file changed

+26
-6
lines changed

net/ipv6/ip6_fib.c

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ static DEFINE_RWLOCK(fib6_walker_lock);
8080
#endif
8181

8282
static void fib6_prune_clones(struct fib6_node *fn, struct rt6_info *rt);
83+
static struct rt6_info * fib6_find_prefix(struct fib6_node *fn);
8384
static struct fib6_node * fib6_repair_tree(struct fib6_node *fn);
8485
static int fib6_walk(struct fib6_walker_t *w);
8586
static int fib6_walk_continue(struct fib6_walker_t *w);
@@ -697,7 +698,7 @@ void fib6_force_start_gc(void)
697698

698699
int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nl_info *info)
699700
{
700-
struct fib6_node *fn;
701+
struct fib6_node *fn, *pn = NULL;
701702
int err = -ENOMEM;
702703

703704
fn = fib6_add_1(root, &rt->rt6i_dst.addr, sizeof(struct in6_addr),
@@ -706,6 +707,8 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nl_info *info)
706707
if (fn == NULL)
707708
goto out;
708709

710+
pn = fn;
711+
709712
#ifdef CONFIG_IPV6_SUBTREES
710713
if (rt->rt6i_src.plen) {
711714
struct fib6_node *sn;
@@ -751,10 +754,6 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nl_info *info)
751754
/* Now link new subtree to main tree */
752755
sfn->parent = fn;
753756
fn->subtree = sfn;
754-
if (fn->leaf == NULL) {
755-
fn->leaf = rt;
756-
atomic_inc(&rt->rt6i_ref);
757-
}
758757
} else {
759758
sn = fib6_add_1(fn->subtree, &rt->rt6i_src.addr,
760759
sizeof(struct in6_addr), rt->rt6i_src.plen,
@@ -764,6 +763,10 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nl_info *info)
764763
goto st_failure;
765764
}
766765

766+
if (fn->leaf == NULL) {
767+
fn->leaf = rt;
768+
atomic_inc(&rt->rt6i_ref);
769+
}
767770
fn = sn;
768771
}
769772
#endif
@@ -777,8 +780,25 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nl_info *info)
777780
}
778781

779782
out:
780-
if (err)
783+
if (err) {
784+
#ifdef CONFIG_IPV6_SUBTREES
785+
/*
786+
* If fib6_add_1 has cleared the old leaf pointer in the
787+
* super-tree leaf node we have to find a new one for it.
788+
*/
789+
if (pn != fn && !pn->leaf && !(pn->fn_flags & RTN_RTINFO)) {
790+
pn->leaf = fib6_find_prefix(pn);
791+
#if RT6_DEBUG >= 2
792+
if (!pn->leaf) {
793+
BUG_TRAP(pn->leaf != NULL);
794+
pn->leaf = &ip6_null_entry;
795+
}
796+
#endif
797+
atomic_inc(&pn->leaf->rt6i_ref);
798+
}
799+
#endif
781800
dst_free(&rt->u.dst);
801+
}
782802
return err;
783803

784804
#ifdef CONFIG_IPV6_SUBTREES

0 commit comments

Comments
 (0)