> EXFAT_TZ_VALID bit in {create,modify,access}_tz is corresponding to > OffsetValid field in exfat specification [1]. When this bit isn't set, > timestamps should be treated as having the same UTC offset as the current > local time. > > Currently, there is an option 'time_offset' for users to specify the UTC > offset for this issue. This patch introduces a new mount option 'sys_tz' > to use system timezone as time offset. > > Link: [1] https://protect2.fireeye.com/v1/url?k=6c606ee0-0d1d8463- > 6c61e5af-74fe48600158-7870d6304b957d98&q=1&e=3704e121-39fa-4c75-a3c8- > a4e968c00dbf&u=https%3A%2F%2Fdocs.microsoft.com%2Fen- > us%2Fwindows%2Fwin32%2Ffileio%2Fexfat-specification%2374102-offsetvalid- > field > > Signed-off-by: Chung-Chiang Cheng <cccheng@xxxxxxxxxxxx> Looks good! Acked-by: Sungjong Seo <sj1557.seo@xxxxxxxxxxx> > --- > fs/exfat/exfat_fs.h | 1 + > fs/exfat/misc.c | 10 ++++++++-- > fs/exfat/super.c | 9 ++++++++- > 3 files changed, 17 insertions(+), 3 deletions(-) > > diff --git a/fs/exfat/exfat_fs.h b/fs/exfat/exfat_fs.h index > c6800b880920..82e507413291 100644 > --- a/fs/exfat/exfat_fs.h > +++ b/fs/exfat/exfat_fs.h > @@ -203,6 +203,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/fs/exfat/misc.c b/fs/exfat/misc.c index > d5bd8e6d9741..9380e0188b55 100644 > --- a/fs/exfat/misc.c > +++ b/fs/exfat/misc.c > @@ -74,6 +74,13 @@ static void exfat_adjust_tz(struct timespec64 *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). > */ void exfat_get_entry_time(struct exfat_sb_info *sbi, struct timespec64 > *ts, > u8 tz, __le16 time, __le16 date, u8 time_cs) @@ -96,8 +103,7 > @@ void exfat_get_entry_time(struct exfat_sb_info *sbi, struct timespec64 > *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/fs/exfat/super.c b/fs/exfat/super.c index 8ca21e7917d1..3e0f67b2103e > 100644 > --- a/fs/exfat/super.c > +++ b/fs/exfat/super.c > @@ -170,7 +170,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; > } > @@ -214,6 +216,7 @@ enum { > Opt_errors, > Opt_discard, > Opt_keep_last_dots, > + Opt_sys_tz, > Opt_time_offset, > > /* Deprecated options */ > @@ -241,6 +244,7 @@ static const struct fs_parameter_spec > exfat_parameters[] = { > fsparam_enum("errors", Opt_errors, > exfat_param_enums), > 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), > @@ -298,6 +302,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 > -- > 2.34.1