struct  dst_ops         *ops;
        unsigned long           _metrics;
        unsigned long           expires;
-       struct dst_entry        *path;
 #ifdef CONFIG_XFRM
        struct xfrm_state       *xfrm;
 #else
         * Align __refcnt to a 64 bytes alignment
         * (L1_CACHE_SIZE would be too much)
         */
-       long                    __pad_to_align_refcnt[4];
+       long                    __pad_to_align_refcnt[5];
 #endif
        /*
         * __refcnt wants to be on a different cache line from
 
        } u;
        struct dst_entry *route;
        struct dst_entry *child;
+       struct dst_entry *path;
        struct xfrm_policy *pols[XFRM_POLICY_TYPE_MAX];
        int num_pols, num_xfrms;
        u32 xfrm_genid;
        u32 path_cookie;
 };
 
+static inline struct dst_entry *xfrm_dst_path(const struct dst_entry *dst)
+{
+#ifdef CONFIG_XFRM
+       if (dst->xfrm) {
+               const struct xfrm_dst *xdst = (const struct xfrm_dst *) dst;
+
+               return xdst->path;
+       }
+#endif
+       return (struct dst_entry *) dst;
+}
+
 static inline struct dst_entry *xfrm_dst_child(const struct dst_entry *dst)
 {
 #ifdef CONFIG_XFRM
                return false;
 
        xdst = (struct xfrm_dst *) dst;
-       if (x->xso.offload_handle && (x->xso.dev == dst->path->dev) &&
+       if (x->xso.offload_handle && (x->xso.dev == xfrm_dst_path(dst)->dev) &&
            !xdst->child->xfrm)
                return true;
 
 
 
        atomic_set(&rt->dst.__refcnt, 1);
        rt->dst.dev = br->dev;
-       rt->dst.path = &rt->dst;
        dst_init_metrics(&rt->dst, br_dst_default_metrics, true);
        rt->dst.flags   = DST_NOXFRM | DST_FAKE_RTABLE;
        rt->dst.ops = &fake_dst_ops;
 
        dst->ops = ops;
        dst_init_metrics(dst, dst_default_metrics.metrics, true);
        dst->expires = 0UL;
-       dst->path = dst;
 #ifdef CONFIG_XFRM
        dst->xfrm = NULL;
 #endif
 
                new = true;
        }
 
-       __ip_rt_update_pmtu((struct rtable *) rt->dst.path, &fl4, mtu);
+       __ip_rt_update_pmtu((struct rtable *) xfrm_dst_path(&rt->dst), &fl4, mtu);
 
        if (!dst_check(&rt->dst, 0)) {
                if (new)
 
                      rt->dst.dev->mtu : dst_mtu(&rt->dst);
        else
                mtu = np->pmtudisc >= IPV6_PMTUDISC_PROBE ?
-                     rt->dst.dev->mtu : dst_mtu(rt->dst.path);
+                     rt->dst.dev->mtu : dst_mtu(xfrm_dst_path(&rt->dst));
        if (np->frag_size < mtu) {
                if (np->frag_size)
                        mtu = np->frag_size;
        }
        cork->base.fragsize = mtu;
-       if (dst_allfrag(rt->dst.path))
+       if (dst_allfrag(xfrm_dst_path(&rt->dst)))
                cork->base.flags |= IPCORK_ALLFRAG;
        cork->base.length = 0;
 
 
                                           GFP_KERNEL);
        if (!net->ipv6.ip6_null_entry)
                goto out_ip6_dst_entries;
-       net->ipv6.ip6_null_entry->dst.path =
-               (struct dst_entry *)net->ipv6.ip6_null_entry;
        net->ipv6.ip6_null_entry->dst.ops = &net->ipv6.ip6_dst_ops;
        dst_init_metrics(&net->ipv6.ip6_null_entry->dst,
                         ip6_template_metrics, true);
                                               GFP_KERNEL);
        if (!net->ipv6.ip6_prohibit_entry)
                goto out_ip6_null_entry;
-       net->ipv6.ip6_prohibit_entry->dst.path =
-               (struct dst_entry *)net->ipv6.ip6_prohibit_entry;
        net->ipv6.ip6_prohibit_entry->dst.ops = &net->ipv6.ip6_dst_ops;
        dst_init_metrics(&net->ipv6.ip6_prohibit_entry->dst,
                         ip6_template_metrics, true);
                                               GFP_KERNEL);
        if (!net->ipv6.ip6_blk_hole_entry)
                goto out_ip6_prohibit_entry;
-       net->ipv6.ip6_blk_hole_entry->dst.path =
-               (struct dst_entry *)net->ipv6.ip6_blk_hole_entry;
        net->ipv6.ip6_blk_hole_entry->dst.ops = &net->ipv6.ip6_dst_ops;
        dst_init_metrics(&net->ipv6.ip6_blk_hole_entry->dst,
                         ip6_template_metrics, true);
 
        if (!x->type_offload || x->encap)
                return false;
 
-       if ((x->xso.offload_handle && (dev == dst->path->dev)) &&
+       if ((x->xso.offload_handle && (dev == xfrm_dst_path(dst)->dev)) &&
             !xdst->child->xfrm && x->type->get_mtu) {
                mtu = x->type->get_mtu(x, xdst->child_mtu_cached);
 
 
        }
 
        xfrm_dst_set_child(xdst_prev, dst);
-       xdst0->u.dst.path = dst;
+       xdst0->path = dst;
 
        err = -ENODEV;
        dev = dst->dev;
        xfrm_decode_session(skb, &fl, dst->ops->family);
        spin_unlock(&pq->hold_queue.lock);
 
-       dst_hold(dst->path);
-       dst = xfrm_lookup(net, dst->path, &fl, sk, 0);
+       dst_hold(xfrm_dst_path(dst));
+       dst = xfrm_lookup(net, xfrm_dst_path(dst), &fl, sk, 0);
        if (IS_ERR(dst))
                goto purge_queue;
 
                skb = __skb_dequeue(&list);
 
                xfrm_decode_session(skb, &fl, skb_dst(skb)->ops->family);
-               dst_hold(skb_dst(skb)->path);
-               dst = xfrm_lookup(net, skb_dst(skb)->path, &fl, skb->sk, 0);
+               dst_hold(xfrm_dst_path(skb_dst(skb)));
+               dst = xfrm_lookup(net, xfrm_dst_path(skb_dst(skb)), &fl, skb->sk, 0);
                if (IS_ERR(dst)) {
                        kfree_skb(skb);
                        continue;
 
        dst_hold(dst);
        xfrm_dst_set_child(xdst, dst);
-       dst1->path = dst;
+       xdst->path = dst;
 
        xfrm_init_path((struct xfrm_dst *)dst1, dst, 0);
 
        struct xfrm_dst *last;
        u32 mtu;
 
-       if (!dst_check(dst->path, ((struct xfrm_dst *)dst)->path_cookie) ||
+       if (!dst_check(xfrm_dst_path(dst), ((struct xfrm_dst *)dst)->path_cookie) ||
            (dst->dev && !netif_running(dst->dev)))
                return 0;
 
 
 static unsigned int xfrm_default_advmss(const struct dst_entry *dst)
 {
-       return dst_metric_advmss(dst->path);
+       return dst_metric_advmss(xfrm_dst_path(dst));
 }
 
 static unsigned int xfrm_mtu(const struct dst_entry *dst)
 {
        unsigned int mtu = dst_metric_raw(dst, RTAX_MTU);
 
-       return mtu ? : dst_mtu(dst->path);
+       return mtu ? : dst_mtu(xfrm_dst_path(dst));
 }
 
 static const void *xfrm_get_dst_nexthop(const struct dst_entry *dst,
                                        const void *daddr)
 {
-       const struct dst_entry *path = dst->path;
-
-       for (; dst != path; dst = xfrm_dst_child(dst)) {
+       while (dst->xfrm) {
                const struct xfrm_state *xfrm = dst->xfrm;
 
                if (xfrm->props.mode == XFRM_MODE_TRANSPORT)
                        daddr = xfrm->coaddr;
                else if (!(xfrm->type->flags & XFRM_TYPE_LOCAL_COADDR))
                        daddr = &xfrm->id.daddr;
+
+               dst = xfrm_dst_child(dst);
        }
        return daddr;
 }
                                           struct sk_buff *skb,
                                           const void *daddr)
 {
-       const struct dst_entry *path = dst->path;
+       const struct dst_entry *path = xfrm_dst_path(dst);
 
        if (!skb)
                daddr = xfrm_get_dst_nexthop(dst, daddr);
 
 static void xfrm_confirm_neigh(const struct dst_entry *dst, const void *daddr)
 {
-       const struct dst_entry *path = dst->path;
+       const struct dst_entry *path = xfrm_dst_path(dst);
 
        daddr = xfrm_get_dst_nexthop(dst, daddr);
        path->ops->confirm_neigh(path, daddr);