Commit 34d08260 authored by Arnd Bergmann's avatar Arnd Bergmann Committed by Linus Torvalds

reiserfs: use monotonic time for j_trans_start_time

Using CLOCK_REALTIME time_t timestamps breaks on 32-bit systems in 2038,
and gives surprising results with a concurrent settimeofday().

This changes the reiserfs journal timestamps to use ktime_get_seconds()
instead, which makes it use a 64-bit CLOCK_MONOTONIC stamp.

In the procfs output, the monotonic timestamp needs to be converted back
to CLOCK_REALTIME to keep the existing ABI.

Link: http://lkml.kernel.org/r/20180620142522.27639-2-arnd@arndb.deSigned-off-by: default avatarArnd Bergmann <arnd@arndb.de>
Reviewed-by: default avatarJan Kara <jack@suse.cz>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Jeff Mahoney <jeffm@suse.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent f168d9fd
...@@ -2381,7 +2381,7 @@ static int journal_read(struct super_block *sb) ...@@ -2381,7 +2381,7 @@ static int journal_read(struct super_block *sb)
struct reiserfs_journal_desc *desc; struct reiserfs_journal_desc *desc;
unsigned int oldest_trans_id = 0; unsigned int oldest_trans_id = 0;
unsigned int oldest_invalid_trans_id = 0; unsigned int oldest_invalid_trans_id = 0;
time_t start; time64_t start;
unsigned long oldest_start = 0; unsigned long oldest_start = 0;
unsigned long cur_dblock = 0; unsigned long cur_dblock = 0;
unsigned long newest_mount_id = 9; unsigned long newest_mount_id = 9;
...@@ -2395,7 +2395,7 @@ static int journal_read(struct super_block *sb) ...@@ -2395,7 +2395,7 @@ static int journal_read(struct super_block *sb)
cur_dblock = SB_ONDISK_JOURNAL_1st_BLOCK(sb); cur_dblock = SB_ONDISK_JOURNAL_1st_BLOCK(sb);
reiserfs_info(sb, "checking transaction log (%pg)\n", reiserfs_info(sb, "checking transaction log (%pg)\n",
journal->j_dev_bd); journal->j_dev_bd);
start = get_seconds(); start = ktime_get_seconds();
/* /*
* step 1, read in the journal header block. Check the transaction * step 1, read in the journal header block. Check the transaction
...@@ -2556,7 +2556,7 @@ static int journal_read(struct super_block *sb) ...@@ -2556,7 +2556,7 @@ static int journal_read(struct super_block *sb)
if (replay_count > 0) { if (replay_count > 0) {
reiserfs_info(sb, reiserfs_info(sb,
"replayed %d transactions in %lu seconds\n", "replayed %d transactions in %lu seconds\n",
replay_count, get_seconds() - start); replay_count, ktime_get_seconds() - start);
} }
/* needed to satisfy the locking in _update_journal_header_block */ /* needed to satisfy the locking in _update_journal_header_block */
reiserfs_write_lock(sb); reiserfs_write_lock(sb);
...@@ -2914,7 +2914,7 @@ int journal_transaction_should_end(struct reiserfs_transaction_handle *th, ...@@ -2914,7 +2914,7 @@ int journal_transaction_should_end(struct reiserfs_transaction_handle *th,
int new_alloc) int new_alloc)
{ {
struct reiserfs_journal *journal = SB_JOURNAL(th->t_super); struct reiserfs_journal *journal = SB_JOURNAL(th->t_super);
time_t now = get_seconds(); time64_t now = ktime_get_seconds();
/* cannot restart while nested */ /* cannot restart while nested */
BUG_ON(!th->t_trans_id); BUG_ON(!th->t_trans_id);
if (th->t_refcount > 1) if (th->t_refcount > 1)
...@@ -3023,7 +3023,7 @@ static int do_journal_begin_r(struct reiserfs_transaction_handle *th, ...@@ -3023,7 +3023,7 @@ static int do_journal_begin_r(struct reiserfs_transaction_handle *th,
struct super_block *sb, unsigned long nblocks, struct super_block *sb, unsigned long nblocks,
int join) int join)
{ {
time_t now = get_seconds(); time64_t now = ktime_get_seconds();
unsigned int old_trans_id; unsigned int old_trans_id;
struct reiserfs_journal *journal = SB_JOURNAL(sb); struct reiserfs_journal *journal = SB_JOURNAL(sb);
struct reiserfs_transaction_handle myth; struct reiserfs_transaction_handle myth;
...@@ -3056,7 +3056,7 @@ static int do_journal_begin_r(struct reiserfs_transaction_handle *th, ...@@ -3056,7 +3056,7 @@ static int do_journal_begin_r(struct reiserfs_transaction_handle *th,
PROC_INFO_INC(sb, journal.journal_relock_writers); PROC_INFO_INC(sb, journal.journal_relock_writers);
goto relock; goto relock;
} }
now = get_seconds(); now = ktime_get_seconds();
/* /*
* if there is no room in the journal OR * if there is no room in the journal OR
...@@ -3119,7 +3119,7 @@ static int do_journal_begin_r(struct reiserfs_transaction_handle *th, ...@@ -3119,7 +3119,7 @@ static int do_journal_begin_r(struct reiserfs_transaction_handle *th,
} }
/* we are the first writer, set trans_id */ /* we are the first writer, set trans_id */
if (journal->j_trans_start_time == 0) { if (journal->j_trans_start_time == 0) {
journal->j_trans_start_time = get_seconds(); journal->j_trans_start_time = ktime_get_seconds();
} }
atomic_inc(&journal->j_wcount); atomic_inc(&journal->j_wcount);
journal->j_len_alloc += nblocks; journal->j_len_alloc += nblocks;
...@@ -3559,11 +3559,11 @@ static void flush_async_commits(struct work_struct *work) ...@@ -3559,11 +3559,11 @@ static void flush_async_commits(struct work_struct *work)
*/ */
void reiserfs_flush_old_commits(struct super_block *sb) void reiserfs_flush_old_commits(struct super_block *sb)
{ {
time_t now; time64_t now;
struct reiserfs_transaction_handle th; struct reiserfs_transaction_handle th;
struct reiserfs_journal *journal = SB_JOURNAL(sb); struct reiserfs_journal *journal = SB_JOURNAL(sb);
now = get_seconds(); now = ktime_get_seconds();
/* /*
* safety check so we don't flush while we are replaying the log during * safety check so we don't flush while we are replaying the log during
* mount * mount
...@@ -3613,7 +3613,7 @@ void reiserfs_flush_old_commits(struct super_block *sb) ...@@ -3613,7 +3613,7 @@ void reiserfs_flush_old_commits(struct super_block *sb)
static int check_journal_end(struct reiserfs_transaction_handle *th, int flags) static int check_journal_end(struct reiserfs_transaction_handle *th, int flags)
{ {
time_t now; time64_t now;
int flush = flags & FLUSH_ALL; int flush = flags & FLUSH_ALL;
int commit_now = flags & COMMIT_NOW; int commit_now = flags & COMMIT_NOW;
int wait_on_commit = flags & WAIT; int wait_on_commit = flags & WAIT;
...@@ -3694,7 +3694,7 @@ static int check_journal_end(struct reiserfs_transaction_handle *th, int flags) ...@@ -3694,7 +3694,7 @@ static int check_journal_end(struct reiserfs_transaction_handle *th, int flags)
} }
/* deal with old transactions where we are the last writers */ /* deal with old transactions where we are the last writers */
now = get_seconds(); now = ktime_get_seconds();
if ((now - journal->j_trans_start_time) > journal->j_max_trans_age) { if ((now - journal->j_trans_start_time) > journal->j_max_trans_age) {
commit_now = 1; commit_now = 1;
journal->j_next_async_flush = 1; journal->j_next_async_flush = 1;
......
...@@ -297,6 +297,13 @@ static int show_oidmap(struct seq_file *m, void *unused) ...@@ -297,6 +297,13 @@ static int show_oidmap(struct seq_file *m, void *unused)
return 0; return 0;
} }
static time64_t ktime_mono_to_real_seconds(time64_t mono)
{
ktime_t kt = ktime_set(mono, NSEC_PER_SEC/2);
return ktime_divns(ktime_mono_to_real(kt), NSEC_PER_SEC);
}
static int show_journal(struct seq_file *m, void *unused) static int show_journal(struct seq_file *m, void *unused)
{ {
struct super_block *sb = m->private; struct super_block *sb = m->private;
...@@ -325,7 +332,7 @@ static int show_journal(struct seq_file *m, void *unused) ...@@ -325,7 +332,7 @@ static int show_journal(struct seq_file *m, void *unused)
"j_bcount: \t%lu\n" "j_bcount: \t%lu\n"
"j_first_unflushed_offset: \t%lu\n" "j_first_unflushed_offset: \t%lu\n"
"j_last_flush_trans_id: \t%u\n" "j_last_flush_trans_id: \t%u\n"
"j_trans_start_time: \t%li\n" "j_trans_start_time: \t%lli\n"
"j_list_bitmap_index: \t%i\n" "j_list_bitmap_index: \t%i\n"
"j_must_wait: \t%i\n" "j_must_wait: \t%i\n"
"j_next_full_flush: \t%i\n" "j_next_full_flush: \t%i\n"
...@@ -366,7 +373,7 @@ static int show_journal(struct seq_file *m, void *unused) ...@@ -366,7 +373,7 @@ static int show_journal(struct seq_file *m, void *unused)
JF(j_bcount), JF(j_bcount),
JF(j_first_unflushed_offset), JF(j_first_unflushed_offset),
JF(j_last_flush_trans_id), JF(j_last_flush_trans_id),
JF(j_trans_start_time), ktime_mono_to_real_seconds(JF(j_trans_start_time)),
JF(j_list_bitmap_index), JF(j_list_bitmap_index),
JF(j_must_wait), JF(j_must_wait),
JF(j_next_full_flush), JF(j_next_full_flush),
......
...@@ -331,7 +331,7 @@ struct reiserfs_journal { ...@@ -331,7 +331,7 @@ struct reiserfs_journal {
struct buffer_head *j_header_bh; struct buffer_head *j_header_bh;
time_t j_trans_start_time; /* time this transaction started */ time64_t j_trans_start_time; /* time this transaction started */
struct mutex j_mutex; struct mutex j_mutex;
struct mutex j_flush_mutex; struct mutex j_flush_mutex;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment