static inline void rt6_clean_expires(struct rt6_info *rt)
 {
-       if (!(rt->rt6i_flags & RTF_EXPIRES) && rt->dst.from)
-               dst_release(rt->dst.from);
-
        rt->rt6i_flags &= ~RTF_EXPIRES;
-       rt->dst.from = NULL;
 }
 
 static inline void rt6_set_expires(struct rt6_info *rt, unsigned long expires)
 {
-       if (!(rt->rt6i_flags & RTF_EXPIRES) && rt->dst.from)
-               dst_release(rt->dst.from);
-
-       rt->rt6i_flags |= RTF_EXPIRES;
        rt->dst.expires = expires;
+       rt->rt6i_flags |= RTF_EXPIRES;
 }
 
-static inline void rt6_update_expires(struct rt6_info *rt, int timeout)
+static inline void rt6_update_expires(struct rt6_info *rt0, int timeout)
 {
-       if (!(rt->rt6i_flags & RTF_EXPIRES)) {
-               if (rt->dst.from)
-                       dst_release(rt->dst.from);
-               /* dst_set_expires relies on expires == 0 
-                * if it has not been set previously.
-                */
-               rt->dst.expires = 0;
-       }
-
-       dst_set_expires(&rt->dst, timeout);
-       rt->rt6i_flags |= RTF_EXPIRES;
+       struct rt6_info *rt;
+
+       for (rt = rt0; rt && !(rt->rt6i_flags & RTF_EXPIRES);
+            rt = (struct rt6_info *)rt->dst.from);
+       if (rt && rt != rt0)
+               rt0->dst.expires = rt->dst.expires;
+
+       dst_set_expires(&rt0->dst, timeout);
+       rt0->rt6i_flags |= RTF_EXPIRES;
 }
 
 static inline void rt6_set_from(struct rt6_info *rt, struct rt6_info *from)
 {
        struct dst_entry *new = (struct dst_entry *) from;
 
-       if (!(rt->rt6i_flags & RTF_EXPIRES) && rt->dst.from) {
-               if (new == rt->dst.from)
-                       return;
-               dst_release(rt->dst.from);
-       }
-
        rt->rt6i_flags &= ~RTF_EXPIRES;
-       rt->dst.from = new;
        dst_hold(new);
+       rt->dst.from = new;
 }
 
 static inline void ip6_rt_put(struct rt6_info *rt)
 
 {
        struct rt6_info *rt = (struct rt6_info *)dst;
        struct inet6_dev *idev = rt->rt6i_idev;
+       struct dst_entry *from = dst->from;
 
        if (!(rt->dst.flags & DST_HOST))
                dst_destroy_metrics_generic(dst);
                in6_dev_put(idev);
        }
 
-       if (!(rt->rt6i_flags & RTF_EXPIRES) && dst->from)
-               dst_release(dst->from);
+       dst->from = NULL;
+       dst_release(from);
 
        if (rt6_has_peer(rt)) {
                struct inet_peer *peer = rt6_peer_ptr(rt);
 
                rt->rt6i_gateway = ort->rt6i_gateway;
                rt->rt6i_flags = ort->rt6i_flags;
-               rt6_clean_expires(rt);
                rt->rt6i_metric = 0;
 
                memcpy(&rt->rt6i_dst, &ort->rt6i_dst, sizeof(struct rt6key));
                if ((ort->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF)) ==
                    (RTF_DEFAULT | RTF_ADDRCONF))
                        rt6_set_from(rt, ort);
-               else
-                       rt6_clean_expires(rt);
                rt->rt6i_metric = 0;
 
 #ifdef CONFIG_IPV6_SUBTREES