linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] timer: Fix jiffies wrap behavior of round_jiffies*()
@ 2013-05-21 18:43 Bart Van Assche
  2013-05-29 23:01 ` Andrew Morton
  2013-06-28 15:12 ` [tip:timers/core] timer: Fix jiffies wrap behavior of round_jiffies_common() tip-bot for Bart Van Assche
  0 siblings, 2 replies; 9+ messages in thread
From: Bart Van Assche @ 2013-05-21 18:43 UTC (permalink / raw)
  To: Thomas Gleixner; +Cc: Arjan van de Ven, Stephen Rothwell, linux-kernel

Make sure that the round_jiffies*() functions return a time that is
in the future when the jiffies counter is about to wrap.

Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Arjan van de Ven <arjan@infradead.org>
Cc: Stephen Rothwell <sfr@canb.auug.org.au>
---
 kernel/timer.c |    4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/kernel/timer.c b/kernel/timer.c
index 15ffdb3..aa8b964 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -149,9 +149,7 @@ static unsigned long round_jiffies_common(unsigned long j, int cpu,
 	/* now that we have rounded, subtract the extra skew again */
 	j -= cpu * 3;
-	if (j <= jiffies) /* rounding ate our timeout entirely; */
-		return original;
-	return j;
+	return time_is_after_jiffies(j) ? j : original;
 }
  /**
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH] timer: Fix jiffies wrap behavior of round_jiffies*()
  2013-05-21 18:43 [PATCH] timer: Fix jiffies wrap behavior of round_jiffies*() Bart Van Assche
@ 2013-05-29 23:01 ` Andrew Morton
  2013-05-29 23:17   ` Joe Perches
  2013-05-30  6:19   ` Bart Van Assche
  2013-06-28 15:12 ` [tip:timers/core] timer: Fix jiffies wrap behavior of round_jiffies_common() tip-bot for Bart Van Assche
  1 sibling, 2 replies; 9+ messages in thread
From: Andrew Morton @ 2013-05-29 23:01 UTC (permalink / raw)
  To: Bart Van Assche
  Cc: Thomas Gleixner, Arjan van de Ven, Stephen Rothwell, linux-kernel,
	Joe Perches

On Tue, 21 May 2013 20:43:50 +0200 Bart Van Assche <bart.vanassche@gmail.com> wrote:

> Make sure that the round_jiffies*() functions return a time that is
> in the future when the jiffies counter is about to wrap.

Actually "when the jiffies counter has recently wrapped".

I assume this was found by inspection?

> @@ -149,9 +149,7 @@ static unsigned long round_jiffies_common(unsigned long j, int cpu,
>  	/* now that we have rounded, subtract the extra skew again */
>  	j -= cpu * 3;
> -	if (j <= jiffies) /* rounding ate our timeout entirely; */

This used to be a very common bug - we've weeded out many instances but
I'm sure more still remain.  We could perhaps have a checkpatch rule
which looks for comparisons against jiffes (and any other
time-measuring variables we can detect) and tells people to use
time_after() and friends, or time_is_*_jiffies().

> -		return original;
> -	return j;
> +	return time_is_after_jiffies(j) ? j : original;
>  }

Your email client mangles patches, btw.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] timer: Fix jiffies wrap behavior of round_jiffies*()
  2013-05-29 23:01 ` Andrew Morton
@ 2013-05-29 23:17   ` Joe Perches
  2013-05-29 23:38     ` Andrew Morton
  2013-05-30  6:19   ` Bart Van Assche
  1 sibling, 1 reply; 9+ messages in thread
From: Joe Perches @ 2013-05-29 23:17 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Bart Van Assche, Thomas Gleixner, Arjan van de Ven,
	Stephen Rothwell, linux-kernel

On Wed, 2013-05-29 at 16:01 -0700, Andrew Morton wrote:
> On Tue, 21 May 2013 20:43:50 +0200 Bart Van Assche <bart.vanassche@gmail.com> wrote:
> 
> > Make sure that the round_jiffies*() functions return a time that is
> > in the future when the jiffies counter is about to wrap.
> 
> Actually "when the jiffies counter has recently wrapped".
> 
> I assume this was found by inspection?
> 
> > @@ -149,9 +149,7 @@ static unsigned long round_jiffies_common(unsigned long j, int cpu,
> >  	/* now that we have rounded, subtract the extra skew again */
> >  	j -= cpu * 3;
> > -	if (j <= jiffies) /* rounding ate our timeout entirely; */
> 
> This used to be a very common bug - we've weeded out many instances but
> I'm sure more still remain.

This list probably isn't comprehensive.

$ git grep -E "if\s*\((\s*jiffies\s*[\<\>]|.*[\<\>]=?\s*jiffies\b)"
drivers/acpi/acpi_pad.c:                if (last_jiffies + round_robin_time * HZ < jiffies) {
drivers/acpi/acpi_pad.c:                        if (jiffies > expire_time) {
drivers/dma/ioat/dma_v2.c:      if (jiffies > chan->timer.expires && timer_pending(&chan->timer)) {
drivers/infiniband/hw/ipath/ipath_sdma.c:               if (jiffies < dd->ipath_sdma_abort_intr_timeout)
drivers/infiniband/hw/ipath/ipath_sdma.c:       if (jiffies > dd->ipath_sdma_abort_jiffies) {
drivers/infiniband/ulp/ipoib/ipoib_cm.c:                if (p && time_after_eq(jiffies, p->jiffies + IPOIB_CM_RX_UPDATE
drivers/infiniband/ulp/ipoib/ipoib_cm.c:                if (time_before_eq(jiffies, p->jiffies + IPOIB_CM_RX_TIMEOUT))
drivers/input/misc/ati_remote2.c:               if (!time_after_eq(jiffies, ar2->jiffies))
drivers/md/dm-log-userspace-base.c:     else if (jiffies < limit)
drivers/misc/sgi-gru/grumain.c:                 if (gts->ts_steal_jiffies + GRU_STEAL_DELAY < jiffies)
drivers/net/ethernet/intel/e1000/e1000_ethtool.c:               if (jiffies >= (time + 2)) {
drivers/net/ethernet/intel/e1000e/ethtool.c:            if (jiffies >= (time + 20)) {
drivers/net/ethernet/micrel/ksz884x.c:                  if (next_jiffies < jiffies)
drivers/net/ethernet/micrel/ksz884x.c:          } else if (jiffies >= hw_priv->counter[i].time) {
drivers/net/ethernet/micrel/ksz884x.c:          if (hw_priv->pme_wait <= jiffies) {
drivers/net/ethernet/neterion/vxge/vxge-main.c: if (jiffies > fifo->jiffies + HZ / 100) {
drivers/net/ethernet/neterion/vxge/vxge-main.c: if (jiffies > ring->jiffies + HZ / 100) {
drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c:                 if (jiffies > (QLCNIC_FILTER_AGE * HZ + time)) {
drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c:                 if (jiffies > (QLCNIC_FILTER_AGE * HZ + time)) {
drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c:                         if (jiffies > (QLCNIC_READD_AGE * HZ + time))
drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c:                 if (jiffies > (QLCNIC_READD_AGE * HZ + tmp_fil->ftime))
drivers/scsi/lpfc/lpfc_scsi.c:  if ((phba->last_ramp_down_time + QUEUE_RAMP_DOWN_INTERVAL) > jiffies) {
drivers/staging/bcm/InterfaceIdleMode.c:                if (timeout < jiffies )
drivers/staging/lustre/include/linux/libcfs/linux/linux-prim.h:                 if (jiffies > expire) {           \
drivers/staging/speakup/speakup_acntpc.c:               if (jiffies >= jiff_max && ch == SPACE) {
drivers/staging/speakup/speakup_decext.c:                       if (jiffies >= jiff_max) {
drivers/staging/speakup/speakup_decpc.c:                        if (jiffies >= jiff_max) {
drivers/staging/speakup/speakup_dectlk.c:                       if (jiffies >= jiff_max) {
kernel/timer.c: if (j <= jiffies) /* rounding ate our timeout entirely; */
net/rds/ib_send.c:                      if (ic->i_ack_queued + HZ/2 < jiffies)
net/rds/ib_send.c:                      if (send->s_queued + HZ/2 < jiffies)
net/rds/iw_send.c:                      if (ic->i_ack_queued + HZ/2 < jiffies)
net/rds/iw_send.c:                      if (send->s_queued + HZ/2 < jiffies)

>   We could perhaps have a checkpatch rule
> which looks for comparisons against jiffes (and any other
> time-measuring variables we can detect)

other variables like?

>  and tells people to use
> time_after() and friends, or time_is_*_jiffies().



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] timer: Fix jiffies wrap behavior of round_jiffies*()
  2013-05-29 23:17   ` Joe Perches
@ 2013-05-29 23:38     ` Andrew Morton
  2013-05-29 23:48       ` Joe Perches
  2013-05-30  0:13       ` Joe Perches
  0 siblings, 2 replies; 9+ messages in thread
From: Andrew Morton @ 2013-05-29 23:38 UTC (permalink / raw)
  To: Joe Perches
  Cc: Bart Van Assche, Thomas Gleixner, Arjan van de Ven,
	Stephen Rothwell, linux-kernel

On Wed, 29 May 2013 16:17:47 -0700 Joe Perches <joe@perches.com> wrote:

> >   We could perhaps have a checkpatch rule
> > which looks for comparisons against jiffes (and any other
> > time-measuring variables we can detect)
> 
> other variables like?

Grepping for time_after finds a bunch.  There's no real pattern to it though.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] timer: Fix jiffies wrap behavior of round_jiffies*()
  2013-05-29 23:38     ` Andrew Morton
@ 2013-05-29 23:48       ` Joe Perches
  2013-05-30  0:13       ` Joe Perches
  1 sibling, 0 replies; 9+ messages in thread
From: Joe Perches @ 2013-05-29 23:48 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Bart Van Assche, Thomas Gleixner, Arjan van de Ven,
	Stephen Rothwell, linux-kernel

On Wed, 2013-05-29 at 16:38 -0700, Andrew Morton wrote:
> On Wed, 29 May 2013 16:17:47 -0700 Joe Perches <joe@perches.com> wrote:
> 
> > >   We could perhaps have a checkpatch rule
> > > which looks for comparisons against jiffes (and any other
> > > time-measuring variables we can detect)
> > 
> > other variables like?
> 
> Grepping for time_after finds a bunch.  There's no real pattern to it though.

Yup, that's the problem.
Thought I'd ask what I was missing though.

No variable really stands out as testable other
than jiffies.

I added this to my local queue and I'll send it later.

# check for comparisons of jiffies
		if ($line =~ /\bif\s*\((\s*jiffies\s*[\<\>]|.*[\<\>]=?\s*jiffies\b)/) {
			WARN("JIFFIES_COMPARISON",
			     "Comparing jiffies is almost always wrong; prefer time_after, time_before and friends\n" . $herecurr);
		}



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] timer: Fix jiffies wrap behavior of round_jiffies*()
  2013-05-29 23:38     ` Andrew Morton
  2013-05-29 23:48       ` Joe Perches
@ 2013-05-30  0:13       ` Joe Perches
  2013-05-30  4:50         ` Andrew Morton
  1 sibling, 1 reply; 9+ messages in thread
From: Joe Perches @ 2013-05-30  0:13 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Bart Van Assche, Thomas Gleixner, Arjan van de Ven,
	Stephen Rothwell, linux-kernel

On Wed, 2013-05-29 at 16:38 -0700, Andrew Morton wrote:
> On Wed, 29 May 2013 16:17:47 -0700 Joe Perches <joe@perches.com> wrote:
> 
> > >   We could perhaps have a checkpatch rule
> > > which looks for comparisons against jiffes (and any other
> > > time-measuring variables we can detect)
> > 
> > other variables like?
> 
> Grepping for time_after finds a bunch.  There's no real pattern to it though.

get_jiffies_64() should probably be added as
another test too.

Also, these might be wrong:

arch/arm/kernel/smp_twd.c:              while (get_jiffies_64() < waitjiffies)
arch/arm/kernel/smp_twd.c:              while (get_jiffies_64() < waitjiffies)
fs/fuse/dir.c:  else if (fuse_dentry_time(entry) < get_jiffies_64()) {
fs/fuse/dir.c:  if (fi->i_time < get_jiffies_64()) {
fs/fuse/dir.c:          if (fi->i_time < get_jiffies_64()) {



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] timer: Fix jiffies wrap behavior of round_jiffies*()
  2013-05-30  0:13       ` Joe Perches
@ 2013-05-30  4:50         ` Andrew Morton
  0 siblings, 0 replies; 9+ messages in thread
From: Andrew Morton @ 2013-05-30  4:50 UTC (permalink / raw)
  To: Joe Perches
  Cc: Bart Van Assche, Thomas Gleixner, Arjan van de Ven,
	Stephen Rothwell, linux-kernel, Miklos Szeredi

On Wed, 29 May 2013 17:13:49 -0700 Joe Perches <joe@perches.com> wrote:

> On Wed, 2013-05-29 at 16:38 -0700, Andrew Morton wrote:
> > On Wed, 29 May 2013 16:17:47 -0700 Joe Perches <joe@perches.com> wrote:
> > 
> > > >   We could perhaps have a checkpatch rule
> > > > which looks for comparisons against jiffes (and any other
> > > > time-measuring variables we can detect)
> > > 
> > > other variables like?
> > 
> > Grepping for time_after finds a bunch.  There's no real pattern to it though.
> 
> get_jiffies_64() should probably be added as
> another test too.
> 
> Also, these might be wrong:
> 
> arch/arm/kernel/smp_twd.c:              while (get_jiffies_64() < waitjiffies)
> arch/arm/kernel/smp_twd.c:              while (get_jiffies_64() < waitjiffies)
> fs/fuse/dir.c:  else if (fuse_dentry_time(entry) < get_jiffies_64()) {
> fs/fuse/dir.c:  if (fi->i_time < get_jiffies_64()) {
> fs/fuse/dir.c:          if (fi->i_time < get_jiffies_64()) {
> 

Yup.  Normally a 64-bit jiffy will wrap around shortly after the heat
death of the universe, but

a) it's derived from jiffies, which we evilly cause to wrap after 5
   minutes uptime and

b) it's derived from jiffies, which is 32-bit on 32-bit and hence
   wraps every 49 days (HZ=1000).


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] timer: Fix jiffies wrap behavior of round_jiffies*()
  2013-05-29 23:01 ` Andrew Morton
  2013-05-29 23:17   ` Joe Perches
@ 2013-05-30  6:19   ` Bart Van Assche
  1 sibling, 0 replies; 9+ messages in thread
From: Bart Van Assche @ 2013-05-30  6:19 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Thomas Gleixner, Arjan van de Ven, Stephen Rothwell, linux-kernel,
	Joe Perches

On 05/30/13 01:01, Andrew Morton wrote:
> On Tue, 21 May 2013 20:43:50 +0200 Bart Van Assche <bart.vanassche@gmail.com> wrote:
>
>> Make sure that the round_jiffies*() functions return a time that is
>> in the future when the jiffies counter is about to wrap.
>
> Actually "when the jiffies counter has recently wrapped".
>
> I assume this was found by inspection?

Hello Andrew,

You are correct, this was found via source code inspection. I started 
reviewing the round_jiffies*() implementation because I was chasing a 
bug in a kernel driver using one of these functions.

>> -		return original;
>> -	return j;
>> +	return time_is_after_jiffies(j) ? j : original;
>>   }
>
> Your email client mangles patches, btw.

Sorry. Will take more care in the future.

Bart.


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [tip:timers/core] timer: Fix jiffies wrap behavior of round_jiffies_common()
  2013-05-21 18:43 [PATCH] timer: Fix jiffies wrap behavior of round_jiffies*() Bart Van Assche
  2013-05-29 23:01 ` Andrew Morton
@ 2013-06-28 15:12 ` tip-bot for Bart Van Assche
  1 sibling, 0 replies; 9+ messages in thread
From: tip-bot for Bart Van Assche @ 2013-06-28 15:12 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: linux-kernel, hpa, mingo, arjan, bvanassche, tglx, sfr,
	bart.vanassche

Commit-ID:  9e04d3804d3ac97d8c03a41d78d0f0674b5d01e1
Gitweb:     http://git.kernel.org/tip/9e04d3804d3ac97d8c03a41d78d0f0674b5d01e1
Author:     Bart Van Assche <bart.vanassche@gmail.com>
AuthorDate: Tue, 21 May 2013 20:43:50 +0200
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Fri, 28 Jun 2013 17:10:11 +0200

timer: Fix jiffies wrap behavior of round_jiffies_common()

Direct compare of jiffies related values does not work in the wrap
around case. Replace it with time_is_after_jiffies().

Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Cc: Arjan van de Ven <arjan@infradead.org>
Cc: Stephen Rothwell <sfr@canb.auug.org.au>
Link: http://lkml.kernel.org/r/519BC066.5080600@acm.org
Cc: stable@vger.kernel.org
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 kernel/timer.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/kernel/timer.c b/kernel/timer.c
index 15ffdb3..15bc1b4 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -149,9 +149,11 @@ static unsigned long round_jiffies_common(unsigned long j, int cpu,
 	/* now that we have rounded, subtract the extra skew again */
 	j -= cpu * 3;
 
-	if (j <= jiffies) /* rounding ate our timeout entirely; */
-		return original;
-	return j;
+	/*
+	 * Make sure j is still in the future. Otherwise return the
+	 * unmodified value.
+	 */
+	return time_is_after_jiffies(j) ? j : original;
 }
 
 /**

^ permalink raw reply related	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2013-06-28 15:13 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-05-21 18:43 [PATCH] timer: Fix jiffies wrap behavior of round_jiffies*() Bart Van Assche
2013-05-29 23:01 ` Andrew Morton
2013-05-29 23:17   ` Joe Perches
2013-05-29 23:38     ` Andrew Morton
2013-05-29 23:48       ` Joe Perches
2013-05-30  0:13       ` Joe Perches
2013-05-30  4:50         ` Andrew Morton
2013-05-30  6:19   ` Bart Van Assche
2013-06-28 15:12 ` [tip:timers/core] timer: Fix jiffies wrap behavior of round_jiffies_common() tip-bot for Bart Van Assche

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).