Jan Kara <jack@xxxxxxx> writes: > So far FAT either offsets time stamps by sys_tz.minuteswest or leaves them > as they are (when tz=UTC mount option is used). However in some cases it > is useful if one can specify time stamp offset on his own (e.g. when time > zone of the camera connected is different from time zone of the computer, > or when HW clock is in UTC and thus sys_tz.minuteswest == 0). > > So provide a mount option tz= which allows user to specify offset in minutes > that should be applied to time stamps on the filesystem. What is in some cases? tz_minuteswest style timezone is known as it doesn't work. E.g. summer time. And tz= is reserved for true solution. E.g. load timezone database to kernel and use it for time conversion. So, if we really want this hack, it should be different option name. > Signed-off-by: Jan Kara <jack@xxxxxxx> > --- > fs/fat/fat.h | 3 ++- > fs/fat/inode.c | 20 +++++++++++++++----- > fs/fat/misc.c | 9 ++++++--- > 3 files changed, 23 insertions(+), 9 deletions(-) > > diff --git a/fs/fat/fat.h b/fs/fat/fat.h > index 2deeeb8..5f19eac 100644 > --- a/fs/fat/fat.h > +++ b/fs/fat/fat.h > @@ -28,6 +28,7 @@ struct fat_mount_options { > unsigned short fs_fmask; > unsigned short fs_dmask; > unsigned short codepage; /* Codepage for shortname conversions */ > + short tz_offset; /* Offset of timestamps from UTC (in minutes) */ > char *iocharset; /* Charset used for filename input/display */ > unsigned short shortname; /* flags for shortname display/create rule */ > unsigned char name_check; /* r = relaxed, n = normal, s = strict */ > @@ -44,7 +45,7 @@ struct fat_mount_options { > flush:1, /* write things quickly */ > nocase:1, /* Does this need case conversion? 0=need case conversion*/ > usefree:1, /* Use free_clusters for FAT32 */ > - tz_utc:1, /* Filesystem timestamps are in UTC */ > + tz_set:1, /* Filesystem timestamps' offset set */ > rodir:1, /* allow ATTR_RO for directory */ > discard:1; /* Issue discard requests on deletions */ > }; > diff --git a/fs/fat/inode.c b/fs/fat/inode.c > index 05e897f..23c29a2 100644 > --- a/fs/fat/inode.c > +++ b/fs/fat/inode.c > @@ -850,8 +850,8 @@ static int fat_show_options(struct seq_file *m, struct dentry *root) > } > if (opts->flush) > seq_puts(m, ",flush"); > - if (opts->tz_utc) > - seq_puts(m, ",tz=UTC"); > + if (opts->tz_set) > + seq_printf(m, ",tz=%d", opts->tz_offset); > if (opts->errors == FAT_ERRORS_CONT) > seq_puts(m, ",errors=continue"); > else if (opts->errors == FAT_ERRORS_PANIC) > @@ -872,7 +872,7 @@ enum { > Opt_charset, Opt_shortname_lower, Opt_shortname_win95, > Opt_shortname_winnt, Opt_shortname_mixed, Opt_utf8_no, Opt_utf8_yes, > Opt_uni_xl_no, Opt_uni_xl_yes, Opt_nonumtail_no, Opt_nonumtail_yes, > - Opt_obsolete, Opt_flush, Opt_tz_utc, Opt_rodir, Opt_err_cont, > + Opt_obsolete, Opt_flush, Opt_tz_utc, Opt_tz, Opt_rodir, Opt_err_cont, > Opt_err_panic, Opt_err_ro, Opt_discard, Opt_err, > }; > > @@ -898,6 +898,7 @@ static const match_table_t fat_tokens = { > {Opt_immutable, "sys_immutable"}, > {Opt_flush, "flush"}, > {Opt_tz_utc, "tz=UTC"}, > + {Opt_tz, "tz=%d"}, > {Opt_err_cont, "errors=continue"}, > {Opt_err_panic, "errors=panic"}, > {Opt_err_ro, "errors=remount-ro"}, > @@ -981,7 +982,7 @@ static int parse_options(struct super_block *sb, char *options, int is_vfat, > opts->utf8 = opts->unicode_xlate = 0; > opts->numtail = 1; > opts->usefree = opts->nocase = 0; > - opts->tz_utc = 0; > + opts->tz_set = 0; > opts->errors = FAT_ERRORS_RO; > *debug = 0; > > @@ -1072,8 +1073,17 @@ static int parse_options(struct super_block *sb, char *options, int is_vfat, > case Opt_flush: > opts->flush = 1; > break; > + case Opt_tz: > + if (match_int(&args[0], &option)) > + return 0; > + if (option < -12 * 60 || option > 12 * 60) > + return 0; > + opts->tz_set = 1; > + opts->tz_offset = option; > + break; > case Opt_tz_utc: > - opts->tz_utc = 1; > + opts->tz_set = 1; > + opts->tz_offset = 0; > break; > case Opt_err_cont: > opts->errors = FAT_ERRORS_CONT; > diff --git a/fs/fat/misc.c b/fs/fat/misc.c > index 6d93360..cc20a78 100644 > --- a/fs/fat/misc.c > +++ b/fs/fat/misc.c > @@ -212,8 +212,10 @@ void fat_time_fat2unix(struct msdos_sb_info *sbi, struct timespec *ts, > + days_in_year[month] + day > + DAYS_DELTA) * SECS_PER_DAY; > > - if (!sbi->options.tz_utc) > + if (!sbi->options.tz_set) > second += sys_tz.tz_minuteswest * SECS_PER_MIN; > + else > + second -= sbi->options.tz_offset * SECS_PER_MIN; > > if (time_cs) { > ts->tv_sec = second + (time_cs / 100); > @@ -229,8 +231,9 @@ void fat_time_unix2fat(struct msdos_sb_info *sbi, struct timespec *ts, > __le16 *time, __le16 *date, u8 *time_cs) > { > struct tm tm; > - time_to_tm(ts->tv_sec, sbi->options.tz_utc ? 0 : > - -sys_tz.tz_minuteswest * 60, &tm); > + time_to_tm(ts->tv_sec, > + (sbi->options.tz_set ? sbi->options.tz_offset : > + -sys_tz.tz_minuteswest) * SECS_PER_MIN, &tm); > > /* FAT can only support year between 1980 to 2107 */ > if (tm.tm_year < 1980 - 1900) { -- OGAWA Hirofumi <hirofumi@xxxxxxxxxxxxxxxxxx> -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html