public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] USB: usbmon: Remove timeval usage for timestamp
@ 2015-05-05  6:14 Tina Ruchandani
  2015-05-05  9:24 ` Arnd Bergmann
  0 siblings, 1 reply; 6+ messages in thread
From: Tina Ruchandani @ 2015-05-05  6:14 UTC (permalink / raw)
  To: Arnd Bergmann; +Cc: Greg Kroah-Hartman, linux-usb, linux-kernel

'struct timeval' uses 32-bits for its seconds field and will overflow in
the year 2038 and beyond. This patch replaces the usage of 'struct timeval'
in mon_get_timestamp() with timespec64 which uses a 64-bit seconds field
and is y2038-safe. mon_get_timestamp() truncates the timestamp at 4096 seconds,
so the correctness of the code is not affected. This patch is part of a larger
attempt to remove instances of struct timeval and other 32-bit timekeeping
(time_t, struct timespec) from the kernel.

Signed-off-by: Tina Ruchandani <ruchandani.tina@gmail.com>
---
 drivers/usb/mon/mon_text.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/usb/mon/mon_text.c b/drivers/usb/mon/mon_text.c
index ad40825..f5ea7c2 100644
--- a/drivers/usb/mon/mon_text.c
+++ b/drivers/usb/mon/mon_text.c
@@ -8,7 +8,7 @@
 #include <linux/list.h>
 #include <linux/usb.h>
 #include <linux/slab.h>
-#include <linux/time.h>
+#include <linux/time64.h>
 #include <linux/export.h>
 #include <linux/mutex.h>
 #include <linux/debugfs.h>
@@ -176,12 +176,12 @@ static inline char mon_text_get_data(struct mon_event_text *ep, struct urb *urb,
 
 static inline unsigned int mon_get_timestamp(void)
 {
-	struct timeval tval;
+	struct timespec64 now;
 	unsigned int stamp;
 
-	do_gettimeofday(&tval);
-	stamp = tval.tv_sec & 0xFFF;	/* 2^32 = 4294967296. Limit to 4096s. */
-	stamp = stamp * 1000000 + tval.tv_usec;
+	getnstimeofday64(&now);
+	stamp = now.tv_sec & 0xFFF;  /* now.tv_sec is 64-bit. Limit to 4096s */
+	stamp = stamp * USEC_PER_SEC + now.tv_nsec / NSEC_PER_USEC;
 	return stamp;
 }
 
-- 
2.2.0.rc0.207.ga3a616c


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

* Re: [PATCH] USB: usbmon: Remove timeval usage for timestamp
  2015-05-05  6:14 [PATCH] USB: usbmon: Remove timeval usage for timestamp Tina Ruchandani
@ 2015-05-05  9:24 ` Arnd Bergmann
  2015-05-05 14:59   ` Alan Stern
  2015-05-05 15:19   ` Pete Zaitcev
  0 siblings, 2 replies; 6+ messages in thread
From: Arnd Bergmann @ 2015-05-05  9:24 UTC (permalink / raw)
  To: Tina Ruchandani; +Cc: Greg Kroah-Hartman, linux-usb, linux-kernel, Pete Zaitcev

On Tuesday 05 May 2015 11:44:33 Tina Ruchandani wrote:
> 'struct timeval' uses 32-bits for its seconds field and will overflow in
> the year 2038 and beyond. This patch replaces the usage of 'struct timeval'
> in mon_get_timestamp() with timespec64 which uses a 64-bit seconds field
> and is y2038-safe. mon_get_timestamp() truncates the timestamp at 4096 seconds,
> so the correctness of the code is not affected. This patch is part of a larger
> attempt to remove instances of struct timeval and other 32-bit timekeeping
> (time_t, struct timespec) from the kernel.
> 
> Signed-off-by: Tina Ruchandani <ruchandani.tina@gmail.com>

Good description!

>  static inline unsigned int mon_get_timestamp(void)
>  {
> -	struct timeval tval;
> +	struct timespec64 now;
>  	unsigned int stamp;
>  
> -	do_gettimeofday(&tval);
> -	stamp = tval.tv_sec & 0xFFF;	/* 2^32 = 4294967296. Limit to 4096s. */
> -	stamp = stamp * 1000000 + tval.tv_usec;
> +	getnstimeofday64(&now);
> +	stamp = now.tv_sec & 0xFFF;  /* now.tv_sec is 64-bit. Limit to 4096s */
> +	stamp = stamp * USEC_PER_SEC + now.tv_nsec / NSEC_PER_USEC;
>  	return stamp;
>  }

Your conversion looks entirely correct, but the original code is a bit
odd here as it does not use the entire range of the 32-bit microsecond
value, and counts from 0 to 4096000000us instead of the more intuitive
0 to 4294967296 us range before wrapping around.

If we change the code to 

static inline unsigned int mon_get_timestamp(void)
{
	return ktime_to_us(ktime_get_real());
}

it might be more obvious what is going on, but it would slightly change
the output in the debugfs file to use the full range. Do we know what
behavior is expected by normal user space here? Pete Zaitcev submitted
a patch for this behavior in 2010, he might remember something about it.

I also wonder if we should make the output use monotonic time instead
of real time (so change it to ktime_get_ts64() or ktime_get()). The effect
of that would be to keep the time ticking monotonically across a concurrent
settimeofday() call.

	Arnd

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

* Re: [PATCH] USB: usbmon: Remove timeval usage for timestamp
  2015-05-05  9:24 ` Arnd Bergmann
@ 2015-05-05 14:59   ` Alan Stern
  2015-05-05 15:33     ` Arnd Bergmann
  2015-05-05 15:19   ` Pete Zaitcev
  1 sibling, 1 reply; 6+ messages in thread
From: Alan Stern @ 2015-05-05 14:59 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Tina Ruchandani, Greg Kroah-Hartman, linux-usb, linux-kernel,
	Pete Zaitcev

On Tue, 5 May 2015, Arnd Bergmann wrote:

> Your conversion looks entirely correct, but the original code is a bit
> odd here as it does not use the entire range of the 32-bit microsecond
> value, and counts from 0 to 4096000000us instead of the more intuitive
> 0 to 4294967296 us range before wrapping around.
> 
> If we change the code to 
> 
> static inline unsigned int mon_get_timestamp(void)
> {
> 	return ktime_to_us(ktime_get_real());
> }
> 
> it might be more obvious what is going on, but it would slightly change
> the output in the debugfs file to use the full range. Do we know what
> behavior is expected by normal user space here? Pete Zaitcev submitted
> a patch for this behavior in 2010, he might remember something about it.

I don't know of any programs that use the timestamp value, but if some 
do exist then the way overflow works should not be changed.

In my experience, the timestamps are used by humans reading the usbmon
output.  Overflow is rare, but when it does occur, a human finds it
much easier to wrap from 4095.999999 seconds to 0.000000 than to wrap
from 4294.967295 to 0.000000.

(Also, in the rare cases where usbmon timestamps have to be matched up
with printk timestamps, it's easier to figure the relative offset when
overflow affects only the seconds, not the fractions of a second.)

> I also wonder if we should make the output use monotonic time instead
> of real time (so change it to ktime_get_ts64() or ktime_get()). The effect
> of that would be to keep the time ticking monotonically across a concurrent
> settimeofday() call.

That seems reasonable to me.  The absolute values of the timestamps are 
practically meaningless; only the differences are important.

Alan Stern


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

* Re: [PATCH] USB: usbmon: Remove timeval usage for timestamp
  2015-05-05  9:24 ` Arnd Bergmann
  2015-05-05 14:59   ` Alan Stern
@ 2015-05-05 15:19   ` Pete Zaitcev
  2015-05-05 15:40     ` Arnd Bergmann
  1 sibling, 1 reply; 6+ messages in thread
From: Pete Zaitcev @ 2015-05-05 15:19 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Tina Ruchandani, Greg Kroah-Hartman, linux-usb, linux-kernel,
	zaitcev

On Tue, 05 May 2015 11:24:16 +0200
Arnd Bergmann <arnd@arndb.de> wrote:

> On Tuesday 05 May 2015 11:44:33 Tina Ruchandani wrote:

> >  static inline unsigned int mon_get_timestamp(void)
> >  {
> > -	struct timeval tval;
> > +	struct timespec64 now;
> >  	unsigned int stamp;
> >  
> > -	do_gettimeofday(&tval);
> > -	stamp = tval.tv_sec & 0xFFF;	/* 2^32 = 4294967296. Limit to 4096s. */
> > -	stamp = stamp * 1000000 + tval.tv_usec;
> > +	getnstimeofday64(&now);
> > +	stamp = now.tv_sec & 0xFFF;  /* now.tv_sec is 64-bit. Limit to 4096s */
> > +	stamp = stamp * USEC_PER_SEC + now.tv_nsec / NSEC_PER_USEC;
> >  	return stamp;
> >  }
> 
> Your conversion looks entirely correct, but the original code is a bit
> odd here as it does not use the entire range of the 32-bit microsecond
> value, and counts from 0 to 4096000000us instead of the more intuitive
> 0 to 4294967296 us range before wrapping around.

The intent was to create a rolling timestamp that is not too large.
Remember that the text format is intended to be eyeballed. The wrap point
could be anything. No consideration was given to what's intuitive.

> it might be more obvious what is going on, but it would slightly change
> the output in the debugfs file to use the full range. Do we know what
> behavior is expected by normal user space here?
> [...]
> I also wonder if we should make the output use monotonic time instead

The only guarantee we give is that the time corresponds to microseconds.
This is sometimes necessary to debug things in microntrollers in USB
devices.

A monotonic time is fine.

One thing though, I object to Tina's new comment. It does not matter what
now.tv_sec is. The comment is about the destination, that is the stamp.
So, please don't change it, unless you change the type of the ep->tstamp.

> static inline unsigned int mon_get_timestamp(void)
> {
> 	return ktime_to_us(ktime_get_real());
> }
> 
> it might be more obvious what is going on, but it would slightly change

Now you made the truncation explicit, so if anyhing it's less obvious.
The code is fine, but at least add a comment to that effect, if you don't
want to tack %4096000000 or %4000000000.

-- Pete

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

* Re: [PATCH] USB: usbmon: Remove timeval usage for timestamp
  2015-05-05 14:59   ` Alan Stern
@ 2015-05-05 15:33     ` Arnd Bergmann
  0 siblings, 0 replies; 6+ messages in thread
From: Arnd Bergmann @ 2015-05-05 15:33 UTC (permalink / raw)
  To: Alan Stern
  Cc: Tina Ruchandani, Greg Kroah-Hartman, linux-usb, linux-kernel,
	Pete Zaitcev

On Tuesday 05 May 2015 10:59:32 Alan Stern wrote:
> On Tue, 5 May 2015, Arnd Bergmann wrote:
> 
> > Your conversion looks entirely correct, but the original code is a bit
> > odd here as it does not use the entire range of the 32-bit microsecond
> > value, and counts from 0 to 4096000000us instead of the more intuitive
> > 0 to 4294967296 us range before wrapping around.
> > 
> > If we change the code to 
> > 
> > static inline unsigned int mon_get_timestamp(void)
> > {
> > 	return ktime_to_us(ktime_get_real());
> > }
> > 
> > it might be more obvious what is going on, but it would slightly change
> > the output in the debugfs file to use the full range. Do we know what
> > behavior is expected by normal user space here? Pete Zaitcev submitted
> > a patch for this behavior in 2010, he might remember something about it.
> 
> I don't know of any programs that use the timestamp value, but if some 
> do exist then the way overflow works should not be changed.
> 
> In my experience, the timestamps are used by humans reading the usbmon
> output.  Overflow is rare, but when it does occur, a human finds it
> much easier to wrap from 4095.999999 seconds to 0.000000 than to wrap
> from 4294.967295 to 0.000000.
> 
> (Also, in the rare cases where usbmon timestamps have to be matched up
> with printk timestamps, it's easier to figure the relative offset when
> overflow affects only the seconds, not the fractions of a second.)

Ok, got it.

> > I also wonder if we should make the output use monotonic time instead
> > of real time (so change it to ktime_get_ts64() or ktime_get()). The effect
> > of that would be to keep the time ticking monotonically across a concurrent
> > settimeofday() call.
> 
> That seems reasonable to me.  The absolute values of the timestamps are 
> practically meaningless; only the differences are important.

Right, although it would also mean you could no longer match up the
microseconds with the printk timestamps.

	Arnd

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

* Re: [PATCH] USB: usbmon: Remove timeval usage for timestamp
  2015-05-05 15:19   ` Pete Zaitcev
@ 2015-05-05 15:40     ` Arnd Bergmann
  0 siblings, 0 replies; 6+ messages in thread
From: Arnd Bergmann @ 2015-05-05 15:40 UTC (permalink / raw)
  To: Pete Zaitcev; +Cc: Tina Ruchandani, Greg Kroah-Hartman, linux-usb, linux-kernel

On Tuesday 05 May 2015 09:19:37 Pete Zaitcev wrote:
> On Tue, 05 May 2015 11:24:16 +0200
> Arnd Bergmann <arnd@arndb.de> wrote:
> 
> > On Tuesday 05 May 2015 11:44:33 Tina Ruchandani wrote:
> 
> > >  static inline unsigned int mon_get_timestamp(void)
> > >  {
> > > -	struct timeval tval;
> > > +	struct timespec64 now;
> > >  	unsigned int stamp;
> > >  
> > > -	do_gettimeofday(&tval);
> > > -	stamp = tval.tv_sec & 0xFFF;	/* 2^32 = 4294967296. Limit to 4096s. */
> > > -	stamp = stamp * 1000000 + tval.tv_usec;
> > > +	getnstimeofday64(&now);
> > > +	stamp = now.tv_sec & 0xFFF;  /* now.tv_sec is 64-bit. Limit to 4096s */
> > > +	stamp = stamp * USEC_PER_SEC + now.tv_nsec / NSEC_PER_USEC;
> > >  	return stamp;
> > >  }
> > 
> > Your conversion looks entirely correct, but the original code is a bit
> > odd here as it does not use the entire range of the 32-bit microsecond
> > value, and counts from 0 to 4096000000us instead of the more intuitive
> > 0 to 4294967296 us range before wrapping around.
> 
> The intent was to create a rolling timestamp that is not too large.
> Remember that the text format is intended to be eyeballed. The wrap point
> could be anything. No consideration was given to what's intuitive.

Ok

> > it might be more obvious what is going on, but it would slightly change
> > the output in the debugfs file to use the full range. Do we know what
> > behavior is expected by normal user space here?
> > [...]
> > I also wonder if we should make the output use monotonic time instead
> 
> The only guarantee we give is that the time corresponds to microseconds.
> This is sometimes necessary to debug things in microntrollers in USB
> devices.
> 
> A monotonic time is fine.
> 
> One thing though, I object to Tina's new comment. It does not matter what
> now.tv_sec is. The comment is about the destination, that is the stamp.
> So, please don't change it, unless you change the type of the ep->tstamp.

The point of the patch that I thought she had made clear enough is to
eliminate the use of 'struct timeval' from one of the 236 files that
currently use it, to make it clearer what the remaining problems
are. 

> > static inline unsigned int mon_get_timestamp(void)
> > {
> > 	return ktime_to_us(ktime_get_real());
> > }
> > 
> > it might be more obvious what is going on, but it would slightly change
> 
> Now you made the truncation explicit, so if anyhing it's less obvious.
> The code is fine, but at least add a comment to that effect, if you don't
> want to tack %4096000000 or %4000000000.

As Alan Stern commented, we should probably leave the wrap point alone,
and adding "% 4096000000" (actually do_div() or ktime_divns()) on a 64-bit
value is more expensive than the current code, so it's probably best if
Tina leaves the existing logic and just changes it to using ktime_get_ts64()
for the monotonic time, as well as trying to be more explicit in the
changelog about the intention.

	Arnd

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

end of thread, other threads:[~2015-05-05 16:10 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-05-05  6:14 [PATCH] USB: usbmon: Remove timeval usage for timestamp Tina Ruchandani
2015-05-05  9:24 ` Arnd Bergmann
2015-05-05 14:59   ` Alan Stern
2015-05-05 15:33     ` Arnd Bergmann
2015-05-05 15:19   ` Pete Zaitcev
2015-05-05 15:40     ` Arnd Bergmann

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox