Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a399a805 authored by Eric Dumazet's avatar Eric Dumazet Committed by David S. Miller
Browse files

time: jiffies_delta_to_clock_t() helper to the rescue



Various /proc/net files sometimes report crazy timer values, expressed
in clock_t units.

This happens when an expired timer delta (expires - jiffies) is passed
to jiffies_to_clock_t().

This function has an overflow in :

return div_u64((u64)x * TICK_NSEC, NSEC_PER_SEC / USER_HZ);

commit cbbc719f (time: Change jiffies_to_clock_t() argument type
to unsigned long) only got around the problem.

As we cant output negative values in /proc/net/tcp without breaking
various tools, I suggest adding a jiffies_delta_to_clock_t() wrapper
that caps the negative delta to a 0 value.

Signed-off-by: default avatarEric Dumazet <edumazet@google.com>
Reported-by: default avatarMaciej Żenczykowski <maze@google.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Paul Gortmaker <paul.gortmaker@windriver.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: hank <pyu@redhat.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 79cda75a
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -303,7 +303,13 @@ extern void jiffies_to_timespec(const unsigned long jiffies,
extern unsigned long timeval_to_jiffies(const struct timeval *value);
extern void jiffies_to_timeval(const unsigned long jiffies,
			       struct timeval *value);

extern clock_t jiffies_to_clock_t(unsigned long x);
static inline clock_t jiffies_delta_to_clock_t(long delta)
{
	return jiffies_to_clock_t(max(0L, delta));
}

extern unsigned long clock_t_to_jiffies(unsigned long x);
extern u64 jiffies_64_to_clock_t(u64 x);
extern u64 nsec_to_clock_t(u64 x);
+1 −1
Original line number Diff line number Diff line
@@ -312,7 +312,7 @@ int br_fdb_fillbuf(struct net_bridge *br, void *buf,

			fe->is_local = f->is_local;
			if (!f->is_static)
				fe->ageing_timer_value = jiffies_to_clock_t(jiffies - f->updated);
				fe->ageing_timer_value = jiffies_delta_to_clock_t(jiffies - f->updated);
			++fe;
			++num;
		}
+1 −1
Original line number Diff line number Diff line
@@ -170,5 +170,5 @@ void br_stp_port_timer_init(struct net_bridge_port *p)
unsigned long br_timer_value(const struct timer_list *timer)
{
	return timer_pending(timer)
		? jiffies_to_clock_t(timer->expires - jiffies) : 0;
		? jiffies_delta_to_clock_t(timer->expires - jiffies) : 0;
}
+1 −1
Original line number Diff line number Diff line
@@ -618,7 +618,7 @@ int rtnl_put_cacheinfo(struct sk_buff *skb, struct dst_entry *dst, u32 id,
		       long expires, u32 error)
{
	struct rta_cacheinfo ci = {
		.rta_lastuse = jiffies_to_clock_t(jiffies - dst->lastuse),
		.rta_lastuse = jiffies_delta_to_clock_t(jiffies - dst->lastuse),
		.rta_used = dst->__use,
		.rta_clntref = atomic_read(&(dst->__refcnt)),
		.rta_error = error,
+5 −2
Original line number Diff line number Diff line
@@ -2435,6 +2435,8 @@ static int igmp_mc_seq_show(struct seq_file *seq, void *v)
		struct ip_mc_list *im = (struct ip_mc_list *)v;
		struct igmp_mc_iter_state *state = igmp_mc_seq_private(seq);
		char   *querier;
		long delta;

#ifdef CONFIG_IP_MULTICAST
		querier = IGMP_V1_SEEN(state->in_dev) ? "V1" :
			  IGMP_V2_SEEN(state->in_dev) ? "V2" :
@@ -2448,11 +2450,12 @@ static int igmp_mc_seq_show(struct seq_file *seq, void *v)
				   state->dev->ifindex, state->dev->name, state->in_dev->mc_count, querier);
		}

		delta = im->timer.expires - jiffies;
		seq_printf(seq,
			   "\t\t\t\t%08X %5d %d:%08lX\t\t%d\n",
			   im->multiaddr, im->users,
			   im->tm_running, im->tm_running ?
			   jiffies_to_clock_t(im->timer.expires-jiffies) : 0,
			   im->tm_running,
			   im->tm_running ? jiffies_delta_to_clock_t(delta) : 0,
			   im->reporter);
	}
	return 0;
Loading