|
@@ -312,6 +312,24 @@ void ext4_itable_unused_set(struct super_block *sb,
|
|
bg->bg_itable_unused_hi = cpu_to_le16(count >> 16);
|
|
bg->bg_itable_unused_hi = cpu_to_le16(count >> 16);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static void __ext4_update_tstamp(__le32 *lo, __u8 *hi)
|
|
|
|
+{
|
|
|
|
+ time64_t now = ktime_get_real_seconds();
|
|
|
|
+
|
|
|
|
+ now = clamp_val(now, 0, (1ull << 40) - 1);
|
|
|
|
+
|
|
|
|
+ *lo = cpu_to_le32(lower_32_bits(now));
|
|
|
|
+ *hi = upper_32_bits(now);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static time64_t __ext4_get_tstamp(__le32 *lo, __u8 *hi)
|
|
|
|
+{
|
|
|
|
+ return ((time64_t)(*hi) << 32) + le32_to_cpu(*lo);
|
|
|
|
+}
|
|
|
|
+#define ext4_update_tstamp(es, tstamp) \
|
|
|
|
+ __ext4_update_tstamp(&(es)->tstamp, &(es)->tstamp ## _hi)
|
|
|
|
+#define ext4_get_tstamp(es, tstamp) \
|
|
|
|
+ __ext4_get_tstamp(&(es)->tstamp, &(es)->tstamp ## _hi)
|
|
|
|
|
|
static void __save_error_info(struct super_block *sb, const char *func,
|
|
static void __save_error_info(struct super_block *sb, const char *func,
|
|
unsigned int line)
|
|
unsigned int line)
|
|
@@ -322,11 +340,12 @@ static void __save_error_info(struct super_block *sb, const char *func,
|
|
if (bdev_read_only(sb->s_bdev))
|
|
if (bdev_read_only(sb->s_bdev))
|
|
return;
|
|
return;
|
|
es->s_state |= cpu_to_le16(EXT4_ERROR_FS);
|
|
es->s_state |= cpu_to_le16(EXT4_ERROR_FS);
|
|
- es->s_last_error_time = cpu_to_le32(get_seconds());
|
|
|
|
|
|
+ ext4_update_tstamp(es, s_last_error_time);
|
|
strncpy(es->s_last_error_func, func, sizeof(es->s_last_error_func));
|
|
strncpy(es->s_last_error_func, func, sizeof(es->s_last_error_func));
|
|
es->s_last_error_line = cpu_to_le32(line);
|
|
es->s_last_error_line = cpu_to_le32(line);
|
|
if (!es->s_first_error_time) {
|
|
if (!es->s_first_error_time) {
|
|
es->s_first_error_time = es->s_last_error_time;
|
|
es->s_first_error_time = es->s_last_error_time;
|
|
|
|
+ es->s_first_error_time_hi = es->s_last_error_time_hi;
|
|
strncpy(es->s_first_error_func, func,
|
|
strncpy(es->s_first_error_func, func,
|
|
sizeof(es->s_first_error_func));
|
|
sizeof(es->s_first_error_func));
|
|
es->s_first_error_line = cpu_to_le32(line);
|
|
es->s_first_error_line = cpu_to_le32(line);
|
|
@@ -2174,8 +2193,8 @@ static int ext4_setup_super(struct super_block *sb, struct ext4_super_block *es,
|
|
"warning: maximal mount count reached, "
|
|
"warning: maximal mount count reached, "
|
|
"running e2fsck is recommended");
|
|
"running e2fsck is recommended");
|
|
else if (le32_to_cpu(es->s_checkinterval) &&
|
|
else if (le32_to_cpu(es->s_checkinterval) &&
|
|
- (le32_to_cpu(es->s_lastcheck) +
|
|
|
|
- le32_to_cpu(es->s_checkinterval) <= get_seconds()))
|
|
|
|
|
|
+ (ext4_get_tstamp(es, s_lastcheck) +
|
|
|
|
+ le32_to_cpu(es->s_checkinterval) <= ktime_get_real_seconds()))
|
|
ext4_msg(sb, KERN_WARNING,
|
|
ext4_msg(sb, KERN_WARNING,
|
|
"warning: checktime reached, "
|
|
"warning: checktime reached, "
|
|
"running e2fsck is recommended");
|
|
"running e2fsck is recommended");
|
|
@@ -2184,7 +2203,7 @@ static int ext4_setup_super(struct super_block *sb, struct ext4_super_block *es,
|
|
if (!(__s16) le16_to_cpu(es->s_max_mnt_count))
|
|
if (!(__s16) le16_to_cpu(es->s_max_mnt_count))
|
|
es->s_max_mnt_count = cpu_to_le16(EXT4_DFL_MAX_MNT_COUNT);
|
|
es->s_max_mnt_count = cpu_to_le16(EXT4_DFL_MAX_MNT_COUNT);
|
|
le16_add_cpu(&es->s_mnt_count, 1);
|
|
le16_add_cpu(&es->s_mnt_count, 1);
|
|
- es->s_mtime = cpu_to_le32(get_seconds());
|
|
|
|
|
|
+ ext4_update_tstamp(es, s_mtime);
|
|
ext4_update_dynamic_rev(sb);
|
|
ext4_update_dynamic_rev(sb);
|
|
if (sbi->s_journal)
|
|
if (sbi->s_journal)
|
|
ext4_set_feature_journal_needs_recovery(sb);
|
|
ext4_set_feature_journal_needs_recovery(sb);
|
|
@@ -2875,8 +2894,9 @@ static void print_daily_error_info(struct timer_list *t)
|
|
ext4_msg(sb, KERN_NOTICE, "error count since last fsck: %u",
|
|
ext4_msg(sb, KERN_NOTICE, "error count since last fsck: %u",
|
|
le32_to_cpu(es->s_error_count));
|
|
le32_to_cpu(es->s_error_count));
|
|
if (es->s_first_error_time) {
|
|
if (es->s_first_error_time) {
|
|
- printk(KERN_NOTICE "EXT4-fs (%s): initial error at time %u: %.*s:%d",
|
|
|
|
- sb->s_id, le32_to_cpu(es->s_first_error_time),
|
|
|
|
|
|
+ printk(KERN_NOTICE "EXT4-fs (%s): initial error at time %llu: %.*s:%d",
|
|
|
|
+ sb->s_id,
|
|
|
|
+ ext4_get_tstamp(es, s_first_error_time),
|
|
(int) sizeof(es->s_first_error_func),
|
|
(int) sizeof(es->s_first_error_func),
|
|
es->s_first_error_func,
|
|
es->s_first_error_func,
|
|
le32_to_cpu(es->s_first_error_line));
|
|
le32_to_cpu(es->s_first_error_line));
|
|
@@ -2889,8 +2909,9 @@ static void print_daily_error_info(struct timer_list *t)
|
|
printk(KERN_CONT "\n");
|
|
printk(KERN_CONT "\n");
|
|
}
|
|
}
|
|
if (es->s_last_error_time) {
|
|
if (es->s_last_error_time) {
|
|
- printk(KERN_NOTICE "EXT4-fs (%s): last error at time %u: %.*s:%d",
|
|
|
|
- sb->s_id, le32_to_cpu(es->s_last_error_time),
|
|
|
|
|
|
+ printk(KERN_NOTICE "EXT4-fs (%s): last error at time %llu: %.*s:%d",
|
|
|
|
+ sb->s_id,
|
|
|
|
+ ext4_get_tstamp(es, s_last_error_time),
|
|
(int) sizeof(es->s_last_error_func),
|
|
(int) sizeof(es->s_last_error_func),
|
|
es->s_last_error_func,
|
|
es->s_last_error_func,
|
|
le32_to_cpu(es->s_last_error_line));
|
|
le32_to_cpu(es->s_last_error_line));
|
|
@@ -4813,7 +4834,7 @@ static int ext4_commit_super(struct super_block *sb, int sync)
|
|
* to complain and force a full file system check.
|
|
* to complain and force a full file system check.
|
|
*/
|
|
*/
|
|
if (!(sb->s_flags & SB_RDONLY))
|
|
if (!(sb->s_flags & SB_RDONLY))
|
|
- es->s_wtime = cpu_to_le32(get_seconds());
|
|
|
|
|
|
+ ext4_update_tstamp(es, s_wtime);
|
|
if (sb->s_bdev->bd_part)
|
|
if (sb->s_bdev->bd_part)
|
|
es->s_kbytes_written =
|
|
es->s_kbytes_written =
|
|
cpu_to_le64(EXT4_SB(sb)->s_kbytes_written +
|
|
cpu_to_le64(EXT4_SB(sb)->s_kbytes_written +
|