@@ -80,6 +80,7 @@ static DEFINE_RWLOCK(fib6_walker_lock);
8080#endif
8181
8282static void fib6_prune_clones (struct fib6_node * fn , struct rt6_info * rt );
83+ static struct rt6_info * fib6_find_prefix (struct fib6_node * fn );
8384static struct fib6_node * fib6_repair_tree (struct fib6_node * fn );
8485static int fib6_walk (struct fib6_walker_t * w );
8586static int fib6_walk_continue (struct fib6_walker_t * w );
@@ -697,7 +698,7 @@ void fib6_force_start_gc(void)
697698
698699int 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
779782out :
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