The following patch replaces all instances of time_t with time64_t i.e.
change the type used for representing time from 32-bit to 64-bit. All
32-bit kernels to date use a signed 32-bit time_t type, which can only
represent time until January 2038. Since embedded systems running 32-bit
Linux are going to survive beyond that date, we have to change all
current uses, in a backwards compatible way.
The patch also changes the function get_seconds() that returns a 32-bit
integer to ktime_get_seconds() that returns seconds as 64-bit integer.
The patch changes the type of ticks from time_t to u32. We keep ticks as
32-bits as the function uses 32-bit arithmetic which would prove less
expensive than 64-bit arithmetic and the function is expected to be
called atleast once every 32 seconds.
Signed-off-by: Heena Sirwani <heenasirwani(a)gmail.com>
Reviewed-by: Arnd Bergmann <arnd(a)arndb.de>
Signed-off-by: Arnd Bergmann <arnd(a)arndb.de>
---
This is an older patch I still had in my queue. Who should pick it up?
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index 10ae73611d80..c9ea63ff70a7 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -51,6 +51,7 @@
#include <linux/stat.h>
#include <linux/string.h>
#include <linux/time.h>
+#include <linux/time64.h>
#include <linux/backing-dev.h>
#include <linux/sort.h>
@@ -68,7 +69,7 @@ struct static_key cpusets_enabled_key __read_mostly = STATIC_KEY_INIT_FALSE;
struct fmeter {
int cnt; /* unprocessed events count */
int val; /* most recent output value */
- time_t time; /* clock (secs) when val computed */
+ time64_t time; /* clock (secs) when val computed */
spinlock_t lock; /* guards read or write of above */
};
@@ -1374,7 +1375,7 @@ out:
*/
#define FM_COEF 933 /* coefficient for half-life of 10 secs */
-#define FM_MAXTICKS ((time_t)99) /* useless computing more ticks than this */
+#define FM_MAXTICKS ((u32)99) /* useless computing more ticks than this */
#define FM_MAXCNT 1000000 /* limit cnt to avoid overflow */
#define FM_SCALE 1000 /* faux fixed point scale */
@@ -1390,8 +1391,11 @@ static void fmeter_init(struct fmeter *fmp)
/* Internal meter update - process cnt events and update value */
static void fmeter_update(struct fmeter *fmp)
{
- time_t now = get_seconds();
- time_t ticks = now - fmp->time;
+ time64_t now;
+ u32 ticks;
+
+ now = ktime_get_seconds();
+ ticks = now - fmp->time;
if (ticks == 0)
return;
struct timeval on 32-bit systems will have its tv_sec
value overflow in year 2038 and beyond.
Use a 64 bit value to print time of the coredump in seconds.
ktime_get_real_seconds is chosen here for efficiency reasons.
Suggested by: Arnd Bergmann <arnd(a)arndb.de>
Signed-off-by: Tina Ruchandani <ruchandani.tina(a)gmail.com>
Signed-off-by: Arnd Bergmann <arnd(a)arndb.de>
---
I've had this patch in my queue for a while, and would like for
someone to pick it up into mainline.
Andrew Morton seems to be the one who has handled most of the
coredump.c patches. Andrew, can you take this for 4.5?
My tree is part of linux-next, so I assume I have to drop it
before you can take it into -mm?
Alternatively, Al could take it for his vfs tree, or Thomas
or John for the timekeeping branch in tip.
diff --git a/fs/coredump.c b/fs/coredump.c
index 1777331eee76..b3c153ca435d 100644
--- a/fs/coredump.c
+++ b/fs/coredump.c
@@ -32,6 +32,7 @@
#include <linux/pipe_fs_i.h>
#include <linux/oom.h>
#include <linux/compat.h>
+#include <linux/timekeeping.h>
#include <asm/uaccess.h>
#include <asm/mmu_context.h>
@@ -232,9 +233,10 @@ static int format_corename(struct core_name *cn, struct coredump_params *cprm)
break;
/* UNIX time of coredump */
case 't': {
- struct timeval tv;
- do_gettimeofday(&tv);
- err = cn_printf(cn, "%lu", tv.tv_sec);
+ time64_t time;
+
+ time = ktime_get_real_seconds();
+ err = cn_printf(cn, "%lld", time);
break;
}
/* hostname */
'struct timeval tv' and 'struct timeval now' is used to calculate the
elapsed time. 'LIRC_SFH506_DELAY' is a delay t_phl in usecs.
32-bit systems using 'struct timeval' will break in the year 2038,
so we have to replace that code with more appropriate types.
This patch changes the lirc_parallel.c file of media: lirc driver
to use ktime_t.
ktime_get() is better than using do_gettimeofday(),
because it uses the monotonic clock. ktime_sub is used
to subtract two ktime variables. ktime_to_us() is used to
convert ktime to microsecond.
New ktime_t variable timeout, is added in lirc_off(),to improve
clarity. Introduced a new ktime_t variable in lirc_lirc_irq_handler()
function, to avoid the use of signal variable for storing
seconds in the first part of this fucntion as later it uses
a time unit that is defined by the global "timer" variable.
This makes it more clear.
ktime_set() is used to set a value in seconds to a value in
nanosecond so that ktime_compare() can be used appropriately.
ktime_compare() is used to compare two ktime values.
ktime_add_ns() is used to increment a ktime value by 1 sec.
One comment is also shifted a line up, as it was creating a 80
character warning.
Build tested it. Also tested it with sparse.
Signed-off-by: Tapasweni Pathak <tapaswenipathak(a)gmail.com>
Reviewed-by: Arnd Bergmann <arnd(a)arndb.de>
Signed-off-by: Arnd Bergmann <arnd(a)arndb.de>
diff --git a/drivers/staging/media/lirc/lirc_parallel.c b/drivers/staging/media/lirc/lirc_parallel.c
index c1408342b1d0..c7987c01d9e0 100644
--- a/drivers/staging/media/lirc/lirc_parallel.c
+++ b/drivers/staging/media/lirc/lirc_parallel.c
@@ -33,7 +33,7 @@
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/ioport.h>
-#include <linux/time.h>
+#include <linux/ktime.h>
#include <linux/mm.h>
#include <linux/delay.h>
@@ -144,25 +144,22 @@ static void lirc_off(void)
static unsigned int init_lirc_timer(void)
{
- struct timeval tv, now;
+ ktime_t kt, now, timeout;
unsigned int level, newlevel, timeelapsed, newtimer;
int count = 0;
- do_gettimeofday(&tv);
- tv.tv_sec++; /* wait max. 1 sec. */
+ kt = ktime_get();
+ /* wait max. 1 sec. */
+ timeout = ktime_add_ns(kt, NSEC_PER_SEC);
level = lirc_get_timer();
do {
newlevel = lirc_get_timer();
if (level == 0 && newlevel != 0)
count++;
level = newlevel;
- do_gettimeofday(&now);
- } while (count < 1000 && (now.tv_sec < tv.tv_sec
- || (now.tv_sec == tv.tv_sec
- && now.tv_usec < tv.tv_usec)));
-
- timeelapsed = (now.tv_sec + 1 - tv.tv_sec)*1000000
- + (now.tv_usec - tv.tv_usec);
+ now = ktime_get();
+ } while (count < 1000 && (ktime_before(now, timeout)));
+ timeelapsed = ktime_us_delta(now, kt);
if (count >= 1000 && timeelapsed > 0) {
if (default_timer == 0) {
/* autodetect timer */
@@ -220,8 +217,8 @@ static void rbuf_write(int signal)
static void lirc_lirc_irq_handler(void *blah)
{
- struct timeval tv;
- static struct timeval lasttv;
+ ktime_t kt, delkt;
+ static ktime_t lastkt;
static int init;
long signal;
int data;
@@ -244,16 +241,14 @@ static void lirc_lirc_irq_handler(void *blah)
#ifdef LIRC_TIMER
if (init) {
- do_gettimeofday(&tv);
+ kt = ktime_get();
- signal = tv.tv_sec - lasttv.tv_sec;
- if (signal > 15)
+ delkt = ktime_sub(kt, lastkt);
+ if (ktime_compare(delkt, ktime_set(15, 0)) > 0)
/* really long time */
data = PULSE_MASK;
else
- data = (int) (signal*1000000 +
- tv.tv_usec - lasttv.tv_usec +
- LIRC_SFH506_DELAY);
+ data = (int) (ktime_to_us(delkt) + LIRC_SFH506_DELAY);
rbuf_write(data); /* space */
} else {
@@ -301,7 +296,7 @@ static void lirc_lirc_irq_handler(void *blah)
data = 1;
rbuf_write(PULSE_BIT|data); /* pulse */
}
- do_gettimeofday(&lasttv);
+ lastkt = ktime_get();
#else
/* add your code here */
#endif
'struct timeval presstime' and 'struct timeval tv' is used to
calculate the time since the last button press.
32-bit systems using 'struct timeval' will break in the year 2038,
so we have to replace that code with more appropriate types.
This patch changes the media: lirc driver to use ktime_t.
ktime_get() is better than using do_gettimeofday(), because it uses
the monotonic clock. ktime_sub() are used to subtract two ktime
variables. 'ms' is only used to check how much time has passed by comparing
to 250. So instead of using expensive ktime_to_ms() call, it has been
changed to hold nanoseconds by using ktime_to_ns().
Build tested it. Tested with sparse too.
Signed-off-by: Tapasweni Pathak <tapaswenipathak(a)gmail.com>
Reviewed-by: Arnd Bergmann <arnd(a)arndb.de>
Signed-off-by: Arnd Bergmann <arnd(a)arndb.de>
diff --git a/drivers/staging/media/lirc/lirc_sasem.c b/drivers/staging/media/lirc/lirc_sasem.c
index f2dca69c2bc0..2218d0042030 100644
--- a/drivers/staging/media/lirc/lirc_sasem.c
+++ b/drivers/staging/media/lirc/lirc_sasem.c
@@ -42,6 +42,7 @@
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/usb.h>
+#include <linux/ktime.h>
#include <media/lirc.h>
#include <media/lirc_dev.h>
@@ -111,7 +112,7 @@ struct sasem_context {
} tx;
/* for dealing with repeat codes (wish there was a toggle bit!) */
- struct timeval presstime;
+ ktime_t presstime;
char lastcode[8];
int codesaved;
};
@@ -566,8 +567,8 @@ static void incoming_packet(struct sasem_context *context,
{
int len = urb->actual_length;
unsigned char *buf = urb->transfer_buffer;
- long ms;
- struct timeval tv;
+ u64 ns;
+ ktime_t kt;
if (len != 8) {
dev_warn(&context->dev->dev,
@@ -584,9 +585,8 @@ static void incoming_packet(struct sasem_context *context,
*/
/* get the time since the last button press */
- do_gettimeofday(&tv);
- ms = (tv.tv_sec - context->presstime.tv_sec) * 1000 +
- (tv.tv_usec - context->presstime.tv_usec) / 1000;
+ kt = ktime_get();
+ ns = ktime_to_ns(ktime_sub(kt, context->presstime));
if (memcmp(buf, "\x08\0\0\0\0\0\0\0", 8) == 0) {
/*
@@ -600,10 +600,9 @@ static void incoming_packet(struct sasem_context *context,
* in that time and then get a false repeat of the previous
* press but it is long enough for a genuine repeat
*/
- if ((ms < 250) && (context->codesaved != 0)) {
+ if ((ns < 250 * NSEC_PER_MSEC) && (context->codesaved != 0)) {
memcpy(buf, &context->lastcode, 8);
- context->presstime.tv_sec = tv.tv_sec;
- context->presstime.tv_usec = tv.tv_usec;
+ context->presstime = kt;
}
} else {
/* save the current valid code for repeats */
@@ -613,8 +612,7 @@ static void incoming_packet(struct sasem_context *context,
* just for safety reasons
*/
context->codesaved = 1;
- context->presstime.tv_sec = tv.tv_sec;
- context->presstime.tv_usec = tv.tv_usec;
+ context->presstime = kt;
}
lirc_buffer_write(context->driver->rbuf, buf);
32 bit systems using 'struct timeval' will break in the year 2038, so
we modify the code appropriately.
This patch replaces the use of struct timeval and do_gettimeofday()
with ktime_get_real_seconds() which returns a 64 bit value which is
safer than struct timeval.
Signed-off-by: Amitoj Kaur Chawla <amitoj1606(a)gmail.com>
---
drivers/scsi/bfa/bfa_svc.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/drivers/scsi/bfa/bfa_svc.c b/drivers/scsi/bfa/bfa_svc.c
index 6521896..0240554 100644
--- a/drivers/scsi/bfa/bfa_svc.c
+++ b/drivers/scsi/bfa/bfa_svc.c
@@ -3424,13 +3424,10 @@ __bfa_cb_fcport_stats_clr(void *cbarg, bfa_boolean_t complete)
struct list_head *qe, *qen;
if (complete) {
- struct timeval tv;
-
/*
* re-initialize time stamp for stats reset
*/
- do_gettimeofday(&tv);
- fcport->stats_reset_time = tv.tv_sec;
+ fcport->stats_reset_time = ktime_get_seconds();
list_for_each_safe(qe, qen, &fcport->statsclr_pending_q) {
bfa_q_deq(&fcport->statsclr_pending_q, &qe);
cb = (struct bfa_cb_pending_q_s *)qe;
--
1.9.1
32 bit systems using 'struct timeval' will break in the year 2038, so
we replace the code appropriately.
This patch replaces struct timeval and do_gettimeofday() with
monotonic ktime_get_ns(). Since we are interested in microseconds
portion of the time, we can use NSEC_PER_USEC macro but this would
lead to expensive division for a frequently used function.
Alternatively a bit shift has been done which performs a division of
1024 instead of 1000 which slightly alters the value returned by this
function.
Signed-off-by: Amitoj Kaur Chawla <amitoj1606(a)gmail.com>
---
drivers/scsi/bfa/bfa_cs.h | 8 +-------
1 file changed, 1 insertion(+), 7 deletions(-)
diff --git a/drivers/scsi/bfa/bfa_cs.h b/drivers/scsi/bfa/bfa_cs.h
index 91a8aa3..daee860 100644
--- a/drivers/scsi/bfa/bfa_cs.h
+++ b/drivers/scsi/bfa/bfa_cs.h
@@ -32,13 +32,7 @@
#define BFA_TRC_MAX (4 * 1024)
#endif
-#define BFA_TRC_TS(_trcm) \
- ({ \
- struct timeval tv; \
- \
- do_gettimeofday(&tv); \
- (tv.tv_sec*1000000+tv.tv_usec); \
- })
+#define BFA_TRC_TS(_trcm) (ktime_get_ns() >> 10)
#ifndef BFA_TRC_TS
#define BFA_TRC_TS(_trcm) ((_trcm)->ticks++)
--
1.9.1
32 bit systems using 'time_t' will break in the year 2038, so
we modify the code appropriately.
This patch removes the cast to 'time_t' in the assignment statement
since we are eventually removing the time_t definition from the kernel
as an effort to solve the y2038 problem. This change will avoid the
build error but the code is still broken and requires a change in the ioctl
interface.
Further, since the variable io_profile_start_time will break in 2038 or 2106
depending on user space interpreting it as signed or unsigned,
comments have been added to highlight the same.
Signed-off-by: Amitoj Kaur Chawla <amitoj1606(a)gmail.com>
---
Changes in v2:
-Added comments about overflow
Only apply this patch if it's seen as acceptable that the
io_profile_start_time remains truncated to 32 bits in
IOCMD_ITNIM_GET_IOPROFILE. If this is something that needs to
be fixed by adding a replacement vendor command, leave the
cast in place as a reminder.
drivers/scsi/bfa/bfa_defs_svc.h | 4 ++++
drivers/scsi/bfa/bfa_fcpim.c | 3 ++-
2 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/drivers/scsi/bfa/bfa_defs_svc.h b/drivers/scsi/bfa/bfa_defs_svc.h
index e7acf41..599db7b 100644
--- a/drivers/scsi/bfa/bfa_defs_svc.h
+++ b/drivers/scsi/bfa/bfa_defs_svc.h
@@ -1211,6 +1211,10 @@ struct bfa_itnim_ioprofile_s {
u32 clock_res_mul;
u32 clock_res_div;
u32 index;
+ /*
+ * Overflow in 2038 or 2106 depending on user space interpreting it as
+ * signed or unsigned.
+ */
u32 io_profile_start_time; /* IO profile start time */
u32 iocomps[BFA_IOBUCKET_MAX]; /* IO completed */
struct bfa_itnim_latency_s io_latency;
diff --git a/drivers/scsi/bfa/bfa_fcpim.c b/drivers/scsi/bfa/bfa_fcpim.c
index 6730340..56df8d0 100644
--- a/drivers/scsi/bfa/bfa_fcpim.c
+++ b/drivers/scsi/bfa/bfa_fcpim.c
@@ -1478,7 +1478,8 @@ bfa_itnim_get_ioprofile(struct bfa_itnim_s *itnim,
return BFA_STATUS_IOPROFILE_OFF;
itnim->ioprofile.index = BFA_IOBUCKET_MAX;
- itnim->ioprofile.io_profile_start_time = (u32)(time_t)
+ /* io_profile_start_time will overflow in 2038 or 2106 */
+ itnim->ioprofile.io_profile_start_time = (u32)
bfa_io_profile_start_time(itnim->bfa);
itnim->ioprofile.clock_res_mul = bfa_io_lat_clock_res_mul;
itnim->ioprofile.clock_res_div = bfa_io_lat_clock_res_div;
--
1.9.1