* [PATCH] fat: Provide option for setting timezone offset
@ 2012-11-08 21:57 Jan Kara
2012-11-11 16:06 ` OGAWA Hirofumi
0 siblings, 1 reply; 5+ messages in thread
From: Jan Kara @ 2012-11-08 21:57 UTC (permalink / raw)
To: OGAWA Hirofumi; +Cc: linux-fsdevel, Jan Kara
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.
Signed-off-by: Jan Kara <jack@suse.cz>
---
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) {
--
1.7.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH] fat: Provide option for setting timezone offset
2012-11-08 21:57 [PATCH] fat: Provide option for setting timezone offset Jan Kara
@ 2012-11-11 16:06 ` OGAWA Hirofumi
2012-11-12 11:05 ` Jan Kara
0 siblings, 1 reply; 5+ messages in thread
From: OGAWA Hirofumi @ 2012-11-11 16:06 UTC (permalink / raw)
To: Jan Kara; +Cc: linux-fsdevel
Jan Kara <jack@suse.cz> 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@suse.cz>
> ---
> 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@mail.parknet.co.jp>
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] fat: Provide option for setting timezone offset
2012-11-11 16:06 ` OGAWA Hirofumi
@ 2012-11-12 11:05 ` Jan Kara
2012-11-12 16:50 ` OGAWA Hirofumi
0 siblings, 1 reply; 5+ messages in thread
From: Jan Kara @ 2012-11-12 11:05 UTC (permalink / raw)
To: OGAWA Hirofumi; +Cc: Jan Kara, linux-fsdevel
On Mon 12-11-12 01:06:41, OGAWA Hirofumi wrote:
> Jan Kara <jack@suse.cz> 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.
Yes, DST is one problem. Another problem (which is more annoying to the
user reporting this) is that he has HW clock set to UTC but system time is
in CET. Somewhat surprisingly (at least to me before I read the code) this
means sys_tz.minuteswest == 0. So when he connects say his camera, which
has time in CET, to the computer he sees timestamps off by one hour. With
tz= mount option he could mount the filesystem with tz=60 and be mostly
happy (modulo DST).
> 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.
Yes, knowing about time zones in kernel is the only way to properly
handle fat timestamps in the presence of DST. But time zones are such a
mess (DST being determined by a law separately each year) I don't see this
happening - the annoyance by bad timestamps simply isn't big enough.
If you feel strongly about reserving 'tz' mount option, I can rename the
mount option to something else... Would 'time_offset' be OK with you?
Honza
--
Jan Kara <jack@suse.cz>
SUSE Labs, CR
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] fat: Provide option for setting timezone offset
2012-11-12 11:05 ` Jan Kara
@ 2012-11-12 16:50 ` OGAWA Hirofumi
2012-11-12 22:26 ` Jan Kara
0 siblings, 1 reply; 5+ messages in thread
From: OGAWA Hirofumi @ 2012-11-12 16:50 UTC (permalink / raw)
To: Jan Kara; +Cc: linux-fsdevel
Jan Kara <jack@suse.cz> writes:
> On Mon 12-11-12 01:06:41, OGAWA Hirofumi wrote:
>> Jan Kara <jack@suse.cz> 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.
> Yes, DST is one problem. Another problem (which is more annoying to the
> user reporting this) is that he has HW clock set to UTC but system time is
> in CET. Somewhat surprisingly (at least to me before I read the code) this
> means sys_tz.minuteswest == 0. So when he connects say his camera, which
> has time in CET, to the computer he sees timestamps off by one hour. With
> tz= mount option he could mount the filesystem with tz=60 and be mostly
> happy (modulo DST).
>
>> 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.
> Yes, knowing about time zones in kernel is the only way to properly
> handle fat timestamps in the presence of DST. But time zones are such a
> mess (DST being determined by a law separately each year) I don't see this
> happening - the annoyance by bad timestamps simply isn't big enough.
>
> If you feel strongly about reserving 'tz' mount option, I can rename the
> mount option to something else... Would 'time_offset' be OK with you?
OK. It should be exclusive with "tz", and the option should be
documented to
Documentation/filesystems/vfat.txt
as it doesn't work sometimes.
--
OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] fat: Provide option for setting timezone offset
2012-11-12 16:50 ` OGAWA Hirofumi
@ 2012-11-12 22:26 ` Jan Kara
0 siblings, 0 replies; 5+ messages in thread
From: Jan Kara @ 2012-11-12 22:26 UTC (permalink / raw)
To: OGAWA Hirofumi; +Cc: Jan Kara, linux-fsdevel
On Tue 13-11-12 01:50:48, OGAWA Hirofumi wrote:
> Jan Kara <jack@suse.cz> writes:
>
> > On Mon 12-11-12 01:06:41, OGAWA Hirofumi wrote:
> >> Jan Kara <jack@suse.cz> 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.
> > Yes, DST is one problem. Another problem (which is more annoying to the
> > user reporting this) is that he has HW clock set to UTC but system time is
> > in CET. Somewhat surprisingly (at least to me before I read the code) this
> > means sys_tz.minuteswest == 0. So when he connects say his camera, which
> > has time in CET, to the computer he sees timestamps off by one hour. With
> > tz= mount option he could mount the filesystem with tz=60 and be mostly
> > happy (modulo DST).
> >
> >> 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.
> > Yes, knowing about time zones in kernel is the only way to properly
> > handle fat timestamps in the presence of DST. But time zones are such a
> > mess (DST being determined by a law separately each year) I don't see this
> > happening - the annoyance by bad timestamps simply isn't big enough.
> >
> > If you feel strongly about reserving 'tz' mount option, I can rename the
> > mount option to something else... Would 'time_offset' be OK with you?
>
> OK. It should be exclusive with "tz", and the option should be
> documented to
>
> Documentation/filesystems/vfat.txt
>
> as it doesn't work sometimes.
That's a good idea. Thanks for reminding me. I'll send you an updated
patch in a moment.
Honza
--
Jan Kara <jack@suse.cz>
SUSE Labs, CR
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2012-11-12 22:26 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-11-08 21:57 [PATCH] fat: Provide option for setting timezone offset Jan Kara
2012-11-11 16:06 ` OGAWA Hirofumi
2012-11-12 11:05 ` Jan Kara
2012-11-12 16:50 ` OGAWA Hirofumi
2012-11-12 22:26 ` Jan Kara
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).