Skip to content

Commit 9b00289

Browse files
ccchengnamjaejeon
authored andcommitted
exfat: introduce mount option 'sys_tz'
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://docs.microsoft.com/en-us/windows/win32/fileio/exfat-specification#74102-offsetvalid-field Signed-off-by: Chung-Chiang Cheng <[email protected]> Acked-by: Sungjong Seo <[email protected]> Signed-off-by: Namjae Jeon <[email protected]>
1 parent d8dad25 commit 9b00289

File tree

3 files changed

+17
-3
lines changed

3 files changed

+17
-3
lines changed

fs/exfat/exfat_fs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@ struct exfat_mount_options {
203203
/* on error: continue, panic, remount-ro */
204204
enum exfat_error_mode errors;
205205
unsigned utf8:1, /* Use of UTF-8 character set */
206+
sys_tz:1, /* Use local timezone */
206207
discard:1, /* Issue discard requests on deletions */
207208
keep_last_dots:1; /* Keep trailing periods in paths */
208209
int time_offset; /* Offset of timestamps from UTC (in minutes) */

fs/exfat/misc.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,13 @@ static void exfat_adjust_tz(struct timespec64 *ts, u8 tz_off)
7474
ts->tv_sec += TIMEZONE_SEC(0x80 - tz_off);
7575
}
7676

77+
static inline int exfat_tz_offset(struct exfat_sb_info *sbi)
78+
{
79+
if (sbi->options.sys_tz)
80+
return -sys_tz.tz_minuteswest;
81+
return sbi->options.time_offset;
82+
}
83+
7784
/* Convert a EXFAT time/date pair to a UNIX date (seconds since 1 1 70). */
7885
void exfat_get_entry_time(struct exfat_sb_info *sbi, struct timespec64 *ts,
7986
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,
96103
/* Adjust timezone to UTC0. */
97104
exfat_adjust_tz(ts, tz & ~EXFAT_TZ_VALID);
98105
else
99-
/* Convert from local time to UTC using time_offset. */
100-
ts->tv_sec -= sbi->options.time_offset * SECS_PER_MIN;
106+
ts->tv_sec -= exfat_tz_offset(sbi) * SECS_PER_MIN;
101107
}
102108

103109
/* Convert linear UNIX date to a EXFAT time/date pair. */

fs/exfat/super.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,9 @@ static int exfat_show_options(struct seq_file *m, struct dentry *root)
170170
seq_puts(m, ",discard");
171171
if (opts->keep_last_dots)
172172
seq_puts(m, ",keep_last_dots");
173-
if (opts->time_offset)
173+
if (opts->sys_tz)
174+
seq_puts(m, ",sys_tz");
175+
else if (opts->time_offset)
174176
seq_printf(m, ",time_offset=%d", opts->time_offset);
175177
return 0;
176178
}
@@ -214,6 +216,7 @@ enum {
214216
Opt_errors,
215217
Opt_discard,
216218
Opt_keep_last_dots,
219+
Opt_sys_tz,
217220
Opt_time_offset,
218221

219222
/* Deprecated options */
@@ -241,6 +244,7 @@ static const struct fs_parameter_spec exfat_parameters[] = {
241244
fsparam_enum("errors", Opt_errors, exfat_param_enums),
242245
fsparam_flag("discard", Opt_discard),
243246
fsparam_flag("keep_last_dots", Opt_keep_last_dots),
247+
fsparam_flag("sys_tz", Opt_sys_tz),
244248
fsparam_s32("time_offset", Opt_time_offset),
245249
__fsparam(NULL, "utf8", Opt_utf8, fs_param_deprecated,
246250
NULL),
@@ -298,6 +302,9 @@ static int exfat_parse_param(struct fs_context *fc, struct fs_parameter *param)
298302
case Opt_keep_last_dots:
299303
opts->keep_last_dots = 1;
300304
break;
305+
case Opt_sys_tz:
306+
opts->sys_tz = 1;
307+
break;
301308
case Opt_time_offset:
302309
/*
303310
* Make the limit 24 just in case someone invents something

0 commit comments

Comments
 (0)