|
@@ -933,6 +933,10 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt,
|
|
int replace_required = 0;
|
|
int replace_required = 0;
|
|
int sernum = fib6_new_sernum(info->nl_net);
|
|
int sernum = fib6_new_sernum(info->nl_net);
|
|
|
|
|
|
|
|
+ if (WARN_ON_ONCE((rt->dst.flags & DST_NOCACHE) &&
|
|
|
|
+ !atomic_read(&rt->dst.__refcnt)))
|
|
|
|
+ return -EINVAL;
|
|
|
|
+
|
|
if (info->nlh) {
|
|
if (info->nlh) {
|
|
if (!(info->nlh->nlmsg_flags & NLM_F_CREATE))
|
|
if (!(info->nlh->nlmsg_flags & NLM_F_CREATE))
|
|
allow_create = 0;
|
|
allow_create = 0;
|
|
@@ -1025,6 +1029,7 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt,
|
|
fib6_start_gc(info->nl_net, rt);
|
|
fib6_start_gc(info->nl_net, rt);
|
|
if (!(rt->rt6i_flags & RTF_CACHE))
|
|
if (!(rt->rt6i_flags & RTF_CACHE))
|
|
fib6_prune_clones(info->nl_net, pn);
|
|
fib6_prune_clones(info->nl_net, pn);
|
|
|
|
+ rt->dst.flags &= ~DST_NOCACHE;
|
|
}
|
|
}
|
|
|
|
|
|
out:
|
|
out:
|
|
@@ -1049,7 +1054,8 @@ out:
|
|
atomic_inc(&pn->leaf->rt6i_ref);
|
|
atomic_inc(&pn->leaf->rt6i_ref);
|
|
}
|
|
}
|
|
#endif
|
|
#endif
|
|
- dst_free(&rt->dst);
|
|
|
|
|
|
+ if (!(rt->dst.flags & DST_NOCACHE))
|
|
|
|
+ dst_free(&rt->dst);
|
|
}
|
|
}
|
|
return err;
|
|
return err;
|
|
|
|
|
|
@@ -1060,7 +1066,8 @@ out:
|
|
st_failure:
|
|
st_failure:
|
|
if (fn && !(fn->fn_flags & (RTN_RTINFO|RTN_ROOT)))
|
|
if (fn && !(fn->fn_flags & (RTN_RTINFO|RTN_ROOT)))
|
|
fib6_repair_tree(info->nl_net, fn);
|
|
fib6_repair_tree(info->nl_net, fn);
|
|
- dst_free(&rt->dst);
|
|
|
|
|
|
+ if (!(rt->dst.flags & DST_NOCACHE))
|
|
|
|
+ dst_free(&rt->dst);
|
|
return err;
|
|
return err;
|
|
#endif
|
|
#endif
|
|
}
|
|
}
|