diff --git a/include/linux/jiffies.h b/include/linux/jiffies.h index c080f61..fb23951 100644 --- a/include/linux/jiffies.h +++ b/include/linux/jiffies.h @@ -89,7 +89,16 @@ static inline u64 get_jiffies_64(void) return (u64)jiffies; } #endif - +/* + * On 64bit archs, storing timestamps in 'unsigned long' vars + * may consume unecessary memory. Using u32 is ok when deltas + * between current jiffie and past timestamps are known to + * fit in 32-1 bits. Even with HZ=1000, thats 24 days. + */ +static inline u32 get_jiffies_32(void) +{ + return (u32)jiffies; +} /* * These inlines deal with timer wrapping correctly. You are * strongly encouraged to use them diff --git a/include/net/dst.h b/include/net/dst.h index e12a8ce..70366b7 100644 --- a/include/net/dst.h +++ b/include/net/dst.h @@ -67,13 +67,13 @@ #define DST_BALANCED 0x10 int (*input)(struct sk_buff*); int (*output)(struct sk_buff*); + + struct dst_ops *ops; #ifdef CONFIG_NET_CLS_ROUTE __u32 tclassid; #endif - - struct dst_ops *ops; - unsigned long lastuse; + u32 __lastuse; atomic_t __refcnt; /* client references */ int __use; union { @@ -103,11 +103,23 @@ struct dst_ops int entry_size; atomic_t entries; - struct kmem_cache *kmem_cachep; + struct kmem_cache *kmem_cachep; }; #ifdef __KERNEL__ +static inline void +dst_lastuse_set(struct dst_entry *dst) +{ + dst->__lastuse = get_jiffies_32(); +} + +static inline unsigned long +dst_lastuse_delta(const struct dst_entry *dst) +{ + return get_jiffies_32() - dst->__lastuse; +} + static inline u32 dst_metric(const struct dst_entry *dst, int metric) { diff --git a/net/core/dst.c b/net/core/dst.c index 764bccb..6c0a023 100644 --- a/net/core/dst.c +++ b/net/core/dst.c @@ -136,7 +136,7 @@ void * dst_alloc(struct dst_ops * ops) return NULL; atomic_set(&dst->__refcnt, 0); dst->ops = ops; - dst->lastuse = jiffies; + dst_lastuse_set(dst); dst->path = dst; dst->input = dst_discard_in; dst->output = dst_discard_out; diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 6055074..c3f5264 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -215,7 +215,7 @@ int rtnl_put_cacheinfo(struct sk_buff *s u32 ts, u32 tsage, long expires, u32 error) { struct rta_cacheinfo ci = { - .rta_lastuse = jiffies_to_clock_t(jiffies - dst->lastuse), + .rta_lastuse = jiffies_to_clock_t(dst_lastuse_delta(dst)), .rta_used = dst->__use, .rta_clntref = atomic_read(&(dst->__refcnt)), .rta_error = error, diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c index 32a7db3..3d5c46c 100644 --- a/net/decnet/dn_route.c +++ b/net/decnet/dn_route.c @@ -166,7 +166,7 @@ static void dn_dst_check_expire(unsigned spin_lock(&dn_rt_hash_table[i].lock); while((rt=*rtp) != NULL) { if (atomic_read(&rt->u.dst.__refcnt) || - (now - rt->u.dst.lastuse) < expire) { + dst_lastuse_delta(&rt->u.dst) < expire) { rtp = &rt->u.dst.dn_next; continue; } @@ -187,7 +187,6 @@ static int dn_dst_gc(void) { struct dn_route *rt, **rtp; int i; - unsigned long now = jiffies; unsigned long expire = 10 * HZ; for(i = 0; i <= dn_rt_hash_mask; i++) { @@ -197,7 +196,7 @@ static int dn_dst_gc(void) while((rt=*rtp) != NULL) { if (atomic_read(&rt->u.dst.__refcnt) || - (now - rt->u.dst.lastuse) < expire) { + dst_lastuse_delta(&rt->u.dst) < expire) { rtp = &rt->u.dst.dn_next; continue; } @@ -278,7 +277,6 @@ static inline int compare_keys(struct fl static int dn_insert_route(struct dn_route *rt, unsigned hash, struct dn_route **rp) { struct dn_route *rth, **rthp; - unsigned long now = jiffies; rthp = &dn_rt_hash_table[hash].chain; @@ -293,7 +291,7 @@ static int dn_insert_route(struct dn_rou rth->u.dst.__use++; dst_hold(&rth->u.dst); - rth->u.dst.lastuse = now; + dst_lastuse_set(&rth->u.dst); spin_unlock_bh(&dn_rt_hash_table[hash].lock); dnrt_drop(rt); @@ -308,7 +306,7 @@ static int dn_insert_route(struct dn_rou dst_hold(&rt->u.dst); rt->u.dst.__use++; - rt->u.dst.lastuse = now; + dst_lastuse_set(&rt->u.dst); spin_unlock_bh(&dn_rt_hash_table[hash].lock); *rp = rt; return 0; @@ -1119,7 +1117,7 @@ make_route: rt->u.dst.neighbour = neigh; neigh = NULL; - rt->u.dst.lastuse = jiffies; + dst_lastuse_set(&rt->u.dst); rt->u.dst.output = dn_output; rt->u.dst.input = dn_rt_bug; rt->rt_flags = flags; @@ -1175,7 +1173,7 @@ static int __dn_route_output_key(struct (flp->mark == rt->fl.mark) && (rt->fl.iif == 0) && (rt->fl.oif == flp->oif)) { - rt->u.dst.lastuse = jiffies; + dst_lastuse_set(&rt->u.dst); dst_hold(&rt->u.dst); rt->u.dst.__use++; rcu_read_unlock_bh(); @@ -1380,7 +1378,7 @@ make_route: rt->u.dst.flags = DST_HOST; rt->u.dst.neighbour = neigh; rt->u.dst.dev = out_dev; - rt->u.dst.lastuse = jiffies; + dst_lastuse_set(&rt->u.dst); rt->u.dst.output = dn_rt_bug; switch(res.type) { case RTN_UNICAST: @@ -1449,7 +1447,7 @@ int dn_route_input(struct sk_buff *skb) (rt->fl.oif == 0) && (rt->fl.mark == skb->mark) && (rt->fl.iif == cb->iif)) { - rt->u.dst.lastuse = jiffies; + dst_lastuse_set(&rt->u.dst); dst_hold(&rt->u.dst); rt->u.dst.__use++; rcu_read_unlock(); diff --git a/net/ipv4/inetpeer.c b/net/ipv4/inetpeer.c index 2f44e61..6831897 100644 --- a/net/ipv4/inetpeer.c +++ b/net/ipv4/inetpeer.c @@ -343,7 +343,7 @@ static int cleanup_once(unsigned long tt spin_lock_bh(&inet_peer_unused_lock); p = inet_peer_unused_head; if (p != NULL) { - __u32 delta = (__u32)jiffies - p->dtime; + __u32 delta = get_jiffies_32() - p->dtime; if (delta < ttl) { /* Do not prune fresh entries. */ spin_unlock_bh(&inet_peer_unused_lock); @@ -471,7 +471,7 @@ void inet_putpeer(struct inet_peer *p) p->unused_next = NULL; *inet_peer_unused_tailp = p; inet_peer_unused_tailp = &p->unused_next; - p->dtime = (__u32)jiffies; + p->dtime = get_jiffies_32(); } spin_unlock_bh(&inet_peer_unused_lock); } diff --git a/net/ipv4/multipath_drr.c b/net/ipv4/multipath_drr.c index 574c735..e318dbd 100644 --- a/net/ipv4/multipath_drr.c +++ b/net/ipv4/multipath_drr.c @@ -147,7 +147,7 @@ static void drr_select_route(const struc multipath_comparekeys(&nh->fl, flp)) { int nh_ifidx = nh->u.dst.dev->ifindex; - nh->u.dst.lastuse = jiffies; + dst_lastuse_set(&nh->u.dst); nh->u.dst.__use++; if (result != NULL) continue; diff --git a/net/ipv4/multipath_random.c b/net/ipv4/multipath_random.c index c312785..5355593 100644 --- a/net/ipv4/multipath_random.c +++ b/net/ipv4/multipath_random.c @@ -78,7 +78,7 @@ static void random_select_route(const st for (rt = first; rt; rt = rt->u.dst.rt_next) { if ((rt->u.dst.flags & DST_BALANCED) != 0 && multipath_comparekeys(&rt->fl, flp)) { - rt->u.dst.lastuse = jiffies; + dst_lastuse_set(&rt->u.dst); if (i == candidate_no) decision = rt; diff --git a/net/ipv4/multipath_rr.c b/net/ipv4/multipath_rr.c index 0ad2252..26a55bf 100644 --- a/net/ipv4/multipath_rr.c +++ b/net/ipv4/multipath_rr.c @@ -60,7 +60,7 @@ static void rr_select_route(const struct nh = rcu_dereference(nh->u.dst.rt_next)) { if ((nh->u.dst.flags & DST_BALANCED) != 0 && multipath_comparekeys(&nh->fl, flp)) { - nh->u.dst.lastuse = jiffies; + dst_lastuse_set(&nh->u.dst); if (min_use == -1 || nh->u.dst.__use < min_use) { min_use = nh->u.dst.__use; diff --git a/net/ipv4/multipath_wrandom.c b/net/ipv4/multipath_wrandom.c index 57c5036..30467d3 100644 --- a/net/ipv4/multipath_wrandom.c +++ b/net/ipv4/multipath_wrandom.c @@ -189,7 +189,7 @@ static void wrandom_select_route(const s decision = first; last_mpc = NULL; for (mpc = first_mpc; mpc; mpc = mpc->next) { - mpc->rt->u.dst.lastuse = jiffies; + dst_lastuse_set(&mpc->rt->u.dst); if (last_power <= selector && selector < mpc->power) decision = mpc->rt; diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 5841739..cbd6337 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -533,7 +533,7 @@ static int rt_may_expire(struct rtable * time_after_eq(jiffies, rth->u.dst.expires)) goto out; - age = jiffies - rth->u.dst.lastuse; + age = dst_lastuse_delta(&rth->u.dst); ret = 0; if ((age <= tmo1 && !rt_fast_clean(rth)) || (age <= tmo2 && rt_valuable(rth))) @@ -549,7 +549,7 @@ out: return ret; */ static inline u32 rt_score(struct rtable *rt) { - u32 score = jiffies - rt->u.dst.lastuse; + u32 score = dst_lastuse_delta(&rt->u.dst); score = ~score & ~(3<<30); @@ -922,7 +922,6 @@ out: return 0; static int rt_intern_hash(unsigned hash, struct rtable *rt, struct rtable **rp) { struct rtable *rth, **rthp; - unsigned long now; struct rtable *cand, **candp; u32 min_score; int chain_length; @@ -933,7 +932,6 @@ restart: min_score = ~(u32)0; cand = NULL; candp = NULL; - now = jiffies; rthp = &rt_hash_table[hash].chain; @@ -962,7 +960,7 @@ #endif rth->u.dst.__use++; dst_hold(&rth->u.dst); - rth->u.dst.lastuse = now; + dst_lastuse_set(&rth->u.dst); spin_unlock_bh(rt_hash_lock_addr(hash)); rt_drop(rt); @@ -1198,7 +1196,7 @@ void ip_rt_redirect(__be32 old_gw, __be3 if (rt->idev) in_dev_hold(rt->idev); rt->u.dst.obsolete = 0; - rt->u.dst.lastuse = jiffies; + dst_lastuse_set(&rt->u.dst); rt->u.dst.path = &rt->u.dst; rt->u.dst.neighbour = NULL; rt->u.dst.hh = NULL; @@ -2105,7 +2103,7 @@ int ip_route_input(struct sk_buff *skb, rth->fl.oif == 0 && rth->fl.mark == skb->mark && rth->fl.fl4_tos == tos) { - rth->u.dst.lastuse = jiffies; + dst_lastuse_set(&rth->u.dst); dst_hold(&rth->u.dst); rth->u.dst.__use++; RT_CACHE_STAT_INC(in_hit); @@ -2581,7 +2579,7 @@ int __ip_route_output_key(struct rtable return 0; } - rth->u.dst.lastuse = jiffies; + dst_lastuse_set(&rth->u.dst); dst_hold(&rth->u.dst); rth->u.dst.__use++; RT_CACHE_STAT_INC(out_hit); diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c index f1c32ff..ecc8aa9 100644 --- a/net/ipv4/xfrm4_policy.c +++ b/net/ipv4/xfrm4_policy.c @@ -160,7 +160,7 @@ #endif dev_hold(rt->u.dst.dev); dst_prev->obsolete = -1; dst_prev->flags |= DST_HOST; - dst_prev->lastuse = jiffies; + dst_lastuse_set(dst_prev); dst_prev->header_len = header_len; dst_prev->nfheader_len = 0; dst_prev->trailer_len = trailer_len; diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index f4d7be7..906cfed 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c @@ -1425,7 +1425,7 @@ static int fib6_age(struct rt6_info *rt, gc_args.more++; } else if (rt->rt6i_flags & RTF_CACHE) { if (atomic_read(&rt->u.dst.__refcnt) == 0 && - time_after_eq(now, rt->u.dst.lastuse + gc_args.timeout)) { + dst_lastuse_delta(&rt->u.dst) >= gc_args.timeout) { RT6_TRACE("aging clone %p\n", rt); return -1; } else if ((rt->rt6i_flags & RTF_GATEWAY) && diff --git a/net/ipv6/route.c b/net/ipv6/route.c index bb2b508..bb7f203 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -528,7 +528,7 @@ out: dst_hold(&rt->u.dst); read_unlock_bh(&table->tb6_lock); - rt->u.dst.lastuse = jiffies; + dst_lastuse_set(&rt->u.dst); rt->u.dst.__use++; return rt; @@ -706,7 +706,7 @@ out: dst_hold(&rt->u.dst); read_unlock_bh(&table->tb6_lock); out2: - rt->u.dst.lastuse = jiffies; + dst_lastuse_set(&rt->u.dst); rt->u.dst.__use++; return rt; @@ -801,7 +801,7 @@ out: dst_hold(&rt->u.dst); read_unlock_bh(&table->tb6_lock); out2: - rt->u.dst.lastuse = jiffies; + dst_lastuse_set(&rt->u.dst); rt->u.dst.__use++; return rt; } @@ -1560,7 +1560,7 @@ static struct rt6_info * ip6_rt_copy(str rt->rt6i_idev = ort->rt6i_idev; if (rt->rt6i_idev) in6_dev_hold(rt->rt6i_idev); - rt->u.dst.lastuse = jiffies; + dst_lastuse_set(&rt->u.dst); rt->rt6i_expires = 0; ipv6_addr_copy(&rt->rt6i_gateway, &ort->rt6i_gateway); diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c index b93bfb8..f059cbe 100644 --- a/net/ipv6/xfrm6_policy.c +++ b/net/ipv6/xfrm6_policy.c @@ -223,7 +223,7 @@ __xfrm6_bundle_create(struct xfrm_policy dev_hold(rt->u.dst.dev); dst_prev->obsolete = -1; dst_prev->flags |= DST_HOST; - dst_prev->lastuse = jiffies; + dst_lastuse_set(dst_prev); dst_prev->header_len = header_len; dst_prev->nfheader_len = nfheader_len; dst_prev->trailer_len = trailer_len;