diff --git a/exfat_fs.h b/exfat_fs.h index deb7755655c6..e5afb4ca5bab 100644 --- a/exfat_fs.h +++ b/exfat_fs.h @@ -213,6 +213,7 @@ struct exfat_mount_options { /* on error: continue, panic, remount-ro */ enum exfat_error_mode errors; unsigned utf8:1, /* Use of UTF-8 character set */ + sys_tz:1, /* Use local timezone */ discard:1, /* Issue discard requests on deletions */ keep_last_dots:1; /* Keep trailing periods in paths */ int time_offset; /* Offset of timestamps from UTC (in minutes) */ diff --git a/misc.c b/misc.c index 47c3682b17f6..c03a58677574 100644 --- a/misc.c +++ b/misc.c @@ -84,6 +84,13 @@ static void exfat_adjust_tz(struct timespec *ts, u8 tz_off) ts->tv_sec += TIMEZONE_SEC(0x80 - tz_off); } +static inline int exfat_tz_offset(struct exfat_sb_info *sbi) +{ + if (sbi->options.sys_tz) + return -sys_tz.tz_minuteswest; + return sbi->options.time_offset; +} + /* Convert a EXFAT time/date pair to a UNIX date (seconds since 1 1 70). */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) void exfat_get_entry_time(struct exfat_sb_info *sbi, struct timespec64 *ts, @@ -111,8 +118,7 @@ void exfat_get_entry_time(struct exfat_sb_info *sbi, struct timespec *ts, /* Adjust timezone to UTC0. */ exfat_adjust_tz(ts, tz & ~EXFAT_TZ_VALID); else - /* Convert from local time to UTC using time_offset. */ - ts->tv_sec -= sbi->options.time_offset * SECS_PER_MIN; + ts->tv_sec -= exfat_tz_offset(sbi) * SECS_PER_MIN; } /* Convert linear UNIX date to a EXFAT time/date pair. */ diff --git a/super.c b/super.c index 615e52d7bb75..ec9de282cb9a 100644 --- a/super.c +++ b/super.c @@ -191,7 +191,9 @@ static int exfat_show_options(struct seq_file *m, struct dentry *root) seq_puts(m, ",discard"); if (opts->keep_last_dots) seq_puts(m, ",keep_last_dots"); - if (opts->time_offset) + if (opts->sys_tz) + seq_puts(m, ",sys_tz"); + else if (opts->time_offset) seq_printf(m, ",time_offset=%d", opts->time_offset); return 0; } @@ -270,6 +272,7 @@ enum { Opt_errors, Opt_discard, Opt_keep_last_dots, + Opt_sys_tz, Opt_time_offset, /* Deprecated options */ @@ -314,6 +317,7 @@ static const struct fs_parameter_spec exfat_param_specs[] = { #endif fsparam_flag("discard", Opt_discard), fsparam_flag("keep_last_dots", Opt_keep_last_dots), + fsparam_flag("sys_tz", Opt_sys_tz), fsparam_s32("time_offset", Opt_time_offset), __fsparam(NULL, "utf8", Opt_utf8, fs_param_deprecated, NULL), @@ -383,6 +387,9 @@ static int exfat_parse_param(struct fs_context *fc, struct fs_parameter *param) case Opt_keep_last_dots: opts->keep_last_dots = 1; break; + case Opt_sys_tz: + opts->sys_tz = 1; + break; case Opt_time_offset: /* * Make the limit 24 just in case someone invents something