LKML Archive on lore.kernel.org
help / color / mirror / Atom feed
From: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
To: Paul Collins <paul@briny.ondioline.org>
Cc: linux-kernel@vger.kernel.org, Hiroyuki_Machida@hq.scei.sony.co.jp
Subject: Re: [PATCH] fat/vfat: optionally ignore system timezone offset when reading/writing timestamps
Date: Mon, 19 Mar 2007 23:31:06 +0900	[thread overview]
Message-ID: <87r6rltidx.fsf@duaron.myhome.or.jp> (raw)
In-Reply-To: <87k5xdfotp.fsf@briny.internal.ondioline.org> (Paul Collins's message of "Mon\, 19 Mar 2007 23\:35\:46 +1200")

Paul Collins <paul@briny.ondioline.org> writes:

> Hello,

Hello,

> Here is a patch that adds a mount option named "posixtime" that, when
> enabled, causes the fat/vfat code to not adjust timestamps as they are
> read/written to/from disk.  The intent of the adjustment as performed
> by the existing code appears to be to present correct timestamps to
> Windows and friends, which treat the timestamp values as local time.
>
> However, the systems that I use to update my FAT32 filesystems are all
> running Linux, and as such will process POSIX timestamps correctly.
> (The filesystems are on disks in digital audio players, which do not
> process timestamps except to check if they have changed.)  Due to the
> aforementioned adjustment on read/write, after a Daylight Savings
> transition I must update the file timestamps on the filesystems so
> that rsync does not needlessly re-copy files.
>
> Please review and consider applying this patch.

Thanks. Looks good to me as start. IIRC, Machida-san did this few
years ago. Machida-san, do you have any comment?

> diff --git a/fs/fat/dir.c b/fs/fat/dir.c
> index c16af24..d6c0a7f 100644
> --- a/fs/fat/dir.c
> +++ b/fs/fat/dir.c
> @@ -1064,7 +1064,7 @@ int fat_alloc_new_dir(struct inode *dir, struct timespec *ts)
>  		goto error_free;
>  	}
>  
> -	fat_date_unix2dos(ts->tv_sec, &time, &date);
> +	fat_date_unix2dos(ts->tv_sec, &time, &date, sbi->options.adjust);
>  
>  	de = (struct msdos_dir_entry *)bhs[0]->b_data;
>  	/* filling the new directory slots ("." and ".." entries) */
> diff --git a/fs/fat/inode.c b/fs/fat/inode.c
> index a9e4688..02d9225 100644
> --- a/fs/fat/inode.c
> +++ b/fs/fat/inode.c
> @@ -374,17 +374,20 @@ static int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de)
>  	inode->i_blocks = ((inode->i_size + (sbi->cluster_size - 1))
>  			   & ~((loff_t)sbi->cluster_size - 1)) >> 9;
>  	inode->i_mtime.tv_sec =
> -		date_dos2unix(le16_to_cpu(de->time), le16_to_cpu(de->date));
> +		date_dos2unix(le16_to_cpu(de->time), le16_to_cpu(de->date),
> +			      sbi->options.adjust);
>  	inode->i_mtime.tv_nsec = 0;
>  	if (sbi->options.isvfat) {
>  		int secs = de->ctime_cs / 100;
>  		int csecs = de->ctime_cs % 100;
>  		inode->i_ctime.tv_sec  =
>  			date_dos2unix(le16_to_cpu(de->ctime),
> -				      le16_to_cpu(de->cdate)) + secs;
> +				      le16_to_cpu(de->cdate),
> +				      sbi->options.adjust) + secs;
>  		inode->i_ctime.tv_nsec = csecs * 10000000;
>  		inode->i_atime.tv_sec =
> -			date_dos2unix(0, le16_to_cpu(de->adate));
> +			date_dos2unix(0, le16_to_cpu(de->adate),
> +				      sbi->options.adjust);
>  		inode->i_atime.tv_nsec = 0;
>  	} else
>  		inode->i_ctime = inode->i_atime = inode->i_mtime;
> @@ -592,11 +595,14 @@ retry:
>  	raw_entry->attr = fat_attr(inode);
>  	raw_entry->start = cpu_to_le16(MSDOS_I(inode)->i_logstart);
>  	raw_entry->starthi = cpu_to_le16(MSDOS_I(inode)->i_logstart >> 16);
> -	fat_date_unix2dos(inode->i_mtime.tv_sec, &raw_entry->time, &raw_entry->date);
> +	fat_date_unix2dos(inode->i_mtime.tv_sec, &raw_entry->time, &raw_entry->date,
> +			  sbi->options.adjust);
>  	if (sbi->options.isvfat) {
>  		__le16 atime;
> -		fat_date_unix2dos(inode->i_ctime.tv_sec,&raw_entry->ctime,&raw_entry->cdate);
> -		fat_date_unix2dos(inode->i_atime.tv_sec,&atime,&raw_entry->adate);
> +		fat_date_unix2dos(inode->i_ctime.tv_sec,&raw_entry->ctime,&raw_entry->cdate,
> +				  sbi->options.adjust);
> +		fat_date_unix2dos(inode->i_atime.tv_sec,&atime,&raw_entry->adate,
> +				  sbi->options.adjust);
>  		raw_entry->ctime_cs = (inode->i_ctime.tv_sec & 1) * 100 +
>  			inode->i_ctime.tv_nsec / 10000000;
>  	}
> @@ -854,7 +860,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_obsolate, Opt_flush, Opt_err,
> +	Opt_obsolate, Opt_flush, Opt_posixtime, Opt_err,
>  };
>  
>  static match_table_t fat_tokens = {
> @@ -887,6 +893,7 @@ static match_table_t fat_tokens = {
>  	{Opt_obsolate, "cvf_options=%100s"},
>  	{Opt_obsolate, "posix"},
>  	{Opt_flush, "flush"},
> +	{Opt_posixtime, "posixtime"},
>  	{Opt_err, NULL},
>  };
>  static match_table_t msdos_tokens = {
> @@ -950,6 +957,7 @@ static int parse_options(char *options, int is_vfat, int silent, int *debug,
>  	opts->utf8 = opts->unicode_xlate = 0;
>  	opts->numtail = 1;
>  	opts->nocase = 0;
> +	opts->adjust = 1;
>  	*debug = 0;
>  
>  	if (!options)
> @@ -1032,6 +1040,10 @@ static int parse_options(char *options, int is_vfat, int silent, int *debug,
>  			opts->flush = 1;
>  			break;
>  
> +		case Opt_posixtime:
> +			opts->adjust = 0;
> +			break;
> +
>  		/* msdos specific */
>  		case Opt_dots:
>  			opts->dotsOK = 1;
> diff --git a/fs/fat/misc.c b/fs/fat/misc.c
> index 308f2b6..72a1a29 100644
> --- a/fs/fat/misc.c
> +++ b/fs/fat/misc.c
> @@ -143,7 +143,7 @@ static int day_n[] = {
>  };
>  
>  /* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */
> -int date_dos2unix(unsigned short time, unsigned short date)
> +int date_dos2unix(unsigned short time, unsigned short date, int adjust)
>  {
>  	int month, year, secs;
>  
> @@ -157,16 +157,18 @@ int date_dos2unix(unsigned short time, unsigned short date)
>  	    ((date & 31)-1+day_n[month]+(year/4)+year*365-((year & 3) == 0 &&
>  	    month < 2 ? 1 : 0)+3653);
>  			/* days since 1.1.70 plus 80's leap day */
> -	secs += sys_tz.tz_minuteswest*60;
> +	if (adjust)
> +		secs += sys_tz.tz_minuteswest*60;
>  	return secs;
>  }
>  
>  /* Convert linear UNIX date to a MS-DOS time/date pair. */
> -void fat_date_unix2dos(int unix_date, __le16 *time, __le16 *date)
> +void fat_date_unix2dos(int unix_date, __le16 *time, __le16 *date, int adjust)
>  {
>  	int day, year, nl_day, month;
>  
> -	unix_date -= sys_tz.tz_minuteswest*60;
> +	if (adjust)
> +		unix_date -= sys_tz.tz_minuteswest*60;
>  
>  	/* Jan 1 GMT 00:00:00 1980. But what about another time zone? */
>  	if (unix_date < 315532800)
> diff --git a/fs/vfat/namei.c b/fs/vfat/namei.c
> index 0afd745..7e5487b 100644
> --- a/fs/vfat/namei.c
> +++ b/fs/vfat/namei.c
> @@ -626,7 +626,7 @@ shortname:
>  	memcpy(de->name, msdos_name, MSDOS_NAME);
>  	de->attr = is_dir ? ATTR_DIR : ATTR_ARCH;
>  	de->lcase = lcase;
> -	fat_date_unix2dos(ts->tv_sec, &time, &date);
> +	fat_date_unix2dos(ts->tv_sec, &time, &date, sbi->options.adjust);
>  	de->time = de->ctime = time;
>  	de->date = de->cdate = de->adate = date;
>  	de->ctime_cs = 0;
> diff --git a/include/linux/msdos_fs.h b/include/linux/msdos_fs.h
> index 24a9ef1..b3eeec8 100644
> --- a/include/linux/msdos_fs.h
> +++ b/include/linux/msdos_fs.h
> @@ -205,7 +205,8 @@ struct fat_mount_options {
>  		 numtail:1,       /* Does first alias have a numeric '~1' type tail? */
>  		 atari:1,         /* Use Atari GEMDOS variation of MS-DOS fs */
>  		 flush:1,	  /* write things quickly */
> -		 nocase:1;	  /* Does this need case conversion? 0=need case conversion*/
> +		 nocase:1,	  /* Does this need case conversion? 0=need case conversion*/
> +		 adjust:1;	  /* Adjust time and date based on sys_tz?*/
>  };
>  
>  #define FAT_HASH_BITS	8
> @@ -421,8 +422,8 @@ extern int fat_flush_inodes(struct super_block *sb, struct inode *i1,
>  extern void fat_fs_panic(struct super_block *s, const char *fmt, ...);
>  extern void fat_clusters_flush(struct super_block *sb);
>  extern int fat_chain_add(struct inode *inode, int new_dclus, int nr_cluster);
> -extern int date_dos2unix(unsigned short time, unsigned short date);
> -extern void fat_date_unix2dos(int unix_date, __le16 *time, __le16 *date);
> +extern int date_dos2unix(unsigned short time, unsigned short date, int adjust);
> +extern void fat_date_unix2dos(int unix_date, __le16 *time, __le16 *date, int adjust);
>  extern int fat_sync_bhs(struct buffer_head **bhs, int nr_bhs);
>  
>  int fat_cache_init(void);
-- 
OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>

  reply	other threads:[~2007-03-19 14:31 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-03-19 11:35 Paul Collins
2007-03-19 14:31 ` OGAWA Hirofumi [this message]
2007-03-26  4:05 Hiroyuki Machida
2007-03-26 15:31 ` OGAWA Hirofumi
2007-03-27  9:52   ` Paul Collins
2007-03-27 15:40     ` OGAWA Hirofumi

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87r6rltidx.fsf@duaron.myhome.or.jp \
    --to=hirofumi@mail.parknet.co.jp \
    --cc=Hiroyuki_Machida@hq.scei.sony.co.jp \
    --cc=linux-kernel@vger.kernel.org \
    --cc=paul@briny.ondioline.org \
    --subject='Re: [PATCH] fat/vfat: optionally ignore system timezone offset when reading/writing timestamps' \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

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).