diff mbox

[RFC,06/15] fs: fat: convert fat to 64 bit time

Message ID 1452144972-15802-7-git-send-email-deepa.kernel@gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Deepa Dinamani Jan. 7, 2016, 5:36 a.m. UTC
FAT filesystem supports timestamps until the year 2099
even though the theoretical max is 2107.
But, the struct timespec overflows in the year 2038 on
32 bit systems.

Use inode_timespec throughout the file system code so
that the timestamps can switch to y2038 safe
struct timespec64 when CONFIG_FS_USES_64BIT_TIME is
turned on.

Use a larger data type for seconds in fat_time_fat2unix().
This extends timestamps beyond the year 2038.

Signed-off-by: Deepa Dinamani <deepa.kernel@gmail.com>
---
 fs/fat/dir.c         |  7 +++++--
 fs/fat/fat.h         |  8 +++++---
 fs/fat/file.c        | 10 ++++++++--
 fs/fat/inode.c       | 46 ++++++++++++++++++++++++++++++++--------------
 fs/fat/misc.c        |  7 ++++---
 fs/fat/namei_msdos.c | 40 +++++++++++++++++++++++++---------------
 fs/fat/namei_vfat.c  | 41 +++++++++++++++++++++++++++--------------
 7 files changed, 106 insertions(+), 53 deletions(-)
diff mbox

Patch

diff --git a/fs/fat/dir.c b/fs/fat/dir.c
index 7def96c..fa8a922 100644
--- a/fs/fat/dir.c
+++ b/fs/fat/dir.c
@@ -1034,6 +1034,7 @@  int fat_remove_entries(struct inode *dir, struct fat_slot_info *sinfo)
 	struct super_block *sb = dir->i_sb;
 	struct msdos_dir_entry *de;
 	struct buffer_head *bh;
+	struct inode_timespec now;
 	int err = 0, nr_slots;
 
 	/*
@@ -1071,7 +1072,9 @@  int fat_remove_entries(struct inode *dir, struct fat_slot_info *sinfo)
 		}
 	}
 
-	dir->i_mtime = dir->i_atime = CURRENT_TIME_SEC;
+	now = current_fs_time_sec(sb);
+	VFS_INODE_SET_XTIME(i_mtime, dir, now);
+	VFS_INODE_SET_XTIME(i_atime, dir, now);
 	if (IS_DIRSYNC(dir))
 		(void)fat_sync_inode(dir);
 	else
@@ -1130,7 +1133,7 @@  error:
 	return err;
 }
 
-int fat_alloc_new_dir(struct inode *dir, struct timespec *ts)
+int fat_alloc_new_dir(struct inode *dir, struct inode_timespec *ts)
 {
 	struct super_block *sb = dir->i_sb;
 	struct msdos_sb_info *sbi = MSDOS_SB(sb);
diff --git a/fs/fat/fat.h b/fs/fat/fat.h
index e6b764a..cabb0fd 100644
--- a/fs/fat/fat.h
+++ b/fs/fat/fat.h
@@ -303,7 +303,7 @@  extern int fat_scan_logstart(struct inode *dir, int i_logstart,
 			     struct fat_slot_info *sinfo);
 extern int fat_get_dotdot_entry(struct inode *dir, struct buffer_head **bh,
 				struct msdos_dir_entry **de);
-extern int fat_alloc_new_dir(struct inode *dir, struct timespec *ts);
+extern int fat_alloc_new_dir(struct inode *dir, struct inode_timespec *ts);
 extern int fat_add_entries(struct inode *dir, void *slots, int nr_slots,
 			   struct fat_slot_info *sinfo);
 extern int fat_remove_entries(struct inode *dir, struct fat_slot_info *sinfo);
@@ -405,9 +405,11 @@  void fat_msg(struct super_block *sb, const char *level, const char *fmt, ...);
 	 } while (0)
 extern int fat_clusters_flush(struct super_block *sb);
 extern int fat_chain_add(struct inode *inode, int new_dclus, int nr_cluster);
-extern void fat_time_fat2unix(struct msdos_sb_info *sbi, struct timespec *ts,
+extern void fat_time_fat2unix(struct msdos_sb_info *sbi,
+			      struct inode_timespec *ts,
 			      __le16 __time, __le16 __date, u8 time_cs);
-extern void fat_time_unix2fat(struct msdos_sb_info *sbi, struct timespec *ts,
+extern void fat_time_unix2fat(struct msdos_sb_info *sbi,
+			      struct inode_timespec *ts,
 			      __le16 *time, __le16 *date, u8 *time_cs);
 extern int fat_sync_bhs(struct buffer_head **bhs, int nr_bhs);
 
diff --git a/fs/fat/file.c b/fs/fat/file.c
index 43d3475..e7f060f 100644
--- a/fs/fat/file.c
+++ b/fs/fat/file.c
@@ -188,13 +188,16 @@  static int fat_cont_expand(struct inode *inode, loff_t size)
 {
 	struct address_space *mapping = inode->i_mapping;
 	loff_t start = inode->i_size, count = size - inode->i_size;
+	struct inode_timespec ts;
 	int err;
 
 	err = generic_cont_expand_simple(inode, size);
 	if (err)
 		goto out;
 
-	inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC;
+	ts = current_fs_time_sec(inode->i_sb);
+	VFS_INODE_SET_XTIME(i_ctime, inode, ts);
+	VFS_INODE_SET_XTIME(i_mtime, inode, ts);
 	mark_inode_dirty(inode);
 	if (IS_SYNC(inode)) {
 		int err2;
@@ -280,6 +283,7 @@  error:
 static int fat_free(struct inode *inode, int skip)
 {
 	struct super_block *sb = inode->i_sb;
+	struct inode_timespec ts;
 	int err, wait, free_start, i_start, i_logstart;
 
 	if (MSDOS_I(inode)->i_start == 0)
@@ -297,7 +301,9 @@  static int fat_free(struct inode *inode, int skip)
 		MSDOS_I(inode)->i_logstart = 0;
 	}
 	MSDOS_I(inode)->i_attrs |= ATTR_ARCH;
-	inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC;
+	ts = current_fs_time_sec(sb);
+	VFS_INODE_SET_XTIME(i_ctime, inode, ts);
+	VFS_INODE_SET_XTIME(i_mtime, inode, ts);
 	if (wait) {
 		err = fat_sync_inode(inode);
 		if (err) {
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index a559905..a1eba05 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -232,12 +232,15 @@  static int fat_write_end(struct file *file, struct address_space *mapping,
 			struct page *pagep, void *fsdata)
 {
 	struct inode *inode = mapping->host;
+	struct inode_timespec ts;
 	int err;
 	err = generic_write_end(file, mapping, pos, len, copied, pagep, fsdata);
 	if (err < len)
 		fat_write_failed(mapping, pos + len);
 	if (!(err < 0) && !(MSDOS_I(inode)->i_attrs & ATTR_ARCH)) {
-		inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC;
+		ts = current_fs_time_sec(inode->i_sb);
+		VFS_INODE_SET_XTIME(i_ctime, inode, ts);
+		VFS_INODE_SET_XTIME(i_mtime, inode, ts);
 		MSDOS_I(inode)->i_attrs |= ATTR_ARCH;
 		mark_inode_dirty(inode);
 	}
@@ -502,6 +505,7 @@  static int fat_validate_dir(struct inode *dir)
 int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de)
 {
 	struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);
+	struct inode_timespec mtime, ctime, atime;
 	int error;
 
 	MSDOS_I(inode)->i_pos = 0;
@@ -551,13 +555,21 @@  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;
 
-	fat_time_fat2unix(sbi, &inode->i_mtime, de->time, de->date, 0);
+	mtime = VFS_INODE_GET_XTIME(i_mtime, inode);
+	fat_time_fat2unix(sbi, &mtime, de->time, de->date, 0);
 	if (sbi->options.isvfat) {
-		fat_time_fat2unix(sbi, &inode->i_ctime, de->ctime,
-				  de->cdate, de->ctime_cs);
-		fat_time_fat2unix(sbi, &inode->i_atime, 0, de->adate, 0);
-	} else
-		inode->i_ctime = inode->i_atime = inode->i_mtime;
+		ctime = VFS_INODE_GET_XTIME(i_ctime, inode);
+		fat_time_fat2unix(sbi,
+				  &ctime,
+				  de->ctime, de->cdate, de->ctime_cs);
+		atime = VFS_INODE_GET_XTIME(i_atime, inode);
+		fat_time_fat2unix(sbi, &atime,
+				  0, de->adate, 0);
+	} else {
+	mtime = VFS_INODE_GET_XTIME(i_mtime, inode);
+	VFS_INODE_SET_XTIME(i_atime, inode, mtime);
+	VFS_INODE_SET_XTIME(i_ctime, inode, mtime);
+	}
 
 	return 0;
 }
@@ -828,6 +840,7 @@  static int __fat_write_inode(struct inode *inode, int wait)
 	struct msdos_sb_info *sbi = MSDOS_SB(sb);
 	struct buffer_head *bh;
 	struct msdos_dir_entry *raw_entry;
+	struct inode_timespec ts;
 	loff_t i_pos;
 	sector_t blocknr;
 	int err, offset;
@@ -861,14 +874,18 @@  retry:
 		raw_entry->size = cpu_to_le32(inode->i_size);
 	raw_entry->attr = fat_make_attrs(inode);
 	fat_set_start(raw_entry, MSDOS_I(inode)->i_logstart);
-	fat_time_unix2fat(sbi, &inode->i_mtime, &raw_entry->time,
-			  &raw_entry->date, NULL);
+	ts = VFS_INODE_GET_XTIME(i_mtime, inode);
+	fat_time_unix2fat(sbi, &ts,
+			  &raw_entry->time, &raw_entry->date, NULL);
 	if (sbi->options.isvfat) {
 		__le16 atime;
-		fat_time_unix2fat(sbi, &inode->i_ctime, &raw_entry->ctime,
+		ts = VFS_INODE_GET_XTIME(i_ctime, inode);
+		fat_time_unix2fat(sbi, &ts,
+				  &raw_entry->ctime,
 				  &raw_entry->cdate, &raw_entry->ctime_cs);
-		fat_time_unix2fat(sbi, &inode->i_atime, &atime,
-				  &raw_entry->adate, NULL);
+		ts = VFS_INODE_GET_XTIME(i_atime, inode);
+		fat_time_unix2fat(sbi, &ts,
+				  &atime, &raw_entry->adate, NULL);
 	}
 	spin_unlock(&sbi->inode_hash_lock);
 	mark_buffer_dirty(bh);
@@ -1385,8 +1402,9 @@  static int fat_read_root(struct inode *inode)
 	MSDOS_I(inode)->mmu_private = inode->i_size;
 
 	fat_save_attrs(inode, ATTR_DIR);
-	inode->i_mtime.tv_sec = inode->i_atime.tv_sec = inode->i_ctime.tv_sec = 0;
-	inode->i_mtime.tv_nsec = inode->i_atime.tv_nsec = inode->i_ctime.tv_nsec = 0;
+	VFS_INODE_SET_XTIME(i_atime, inode, ((struct inode_timespec) {0, 0}));
+	VFS_INODE_SET_XTIME(i_mtime, inode, ((struct inode_timespec) {0, 0}));
+	VFS_INODE_SET_XTIME(i_ctime, inode, ((struct inode_timespec) {0, 0}));
 	set_nlink(inode, fat_subdirs(inode)+2);
 
 	return 0;
diff --git a/fs/fat/misc.c b/fs/fat/misc.c
index c4589e9..1544498 100644
--- a/fs/fat/misc.c
+++ b/fs/fat/misc.c
@@ -186,11 +186,12 @@  static time_t days_in_year[] = {
 };
 
 /* Convert a FAT time/date pair to a UNIX date (seconds since 1 1 70). */
-void fat_time_fat2unix(struct msdos_sb_info *sbi, struct timespec *ts,
+void fat_time_fat2unix(struct msdos_sb_info *sbi, struct inode_timespec *ts,
 		       __le16 __time, __le16 __date, u8 time_cs)
 {
 	u16 time = le16_to_cpu(__time), date = le16_to_cpu(__date);
-	time_t second, day, leap_day, month, year;
+	long long second;
+	time_t day, leap_day, month, year;
 
 	year  = date >> 9;
 	month = max(1, (date >> 5) & 0xf);
@@ -224,7 +225,7 @@  void fat_time_fat2unix(struct msdos_sb_info *sbi, struct timespec *ts,
 }
 
 /* Convert linear UNIX date to a FAT time/date pair. */
-void fat_time_unix2fat(struct msdos_sb_info *sbi, struct timespec *ts,
+void fat_time_unix2fat(struct msdos_sb_info *sbi, struct inode_timespec *ts,
 		       __le16 *time, __le16 *date, u8 *time_cs)
 {
 	struct tm tm;
diff --git a/fs/fat/namei_msdos.c b/fs/fat/namei_msdos.c
index b7e2b33..457dcfb 100644
--- a/fs/fat/namei_msdos.c
+++ b/fs/fat/namei_msdos.c
@@ -224,7 +224,8 @@  static struct dentry *msdos_lookup(struct inode *dir, struct dentry *dentry,
 /***** Creates a directory entry (name is already formatted). */
 static int msdos_add_entry(struct inode *dir, const unsigned char *name,
 			   int is_dir, int is_hid, int cluster,
-			   struct timespec *ts, struct fat_slot_info *sinfo)
+			   struct inode_timespec *ts,
+			   struct fat_slot_info *sinfo)
 {
 	struct msdos_sb_info *sbi = MSDOS_SB(dir->i_sb);
 	struct msdos_dir_entry de;
@@ -249,7 +250,8 @@  static int msdos_add_entry(struct inode *dir, const unsigned char *name,
 	if (err)
 		return err;
 
-	dir->i_ctime = dir->i_mtime = *ts;
+	VFS_INODE_SET_XTIME(i_ctime, dir, *ts);
+	VFS_INODE_SET_XTIME(i_mtime, dir, *ts);
 	if (IS_DIRSYNC(dir))
 		(void)fat_sync_inode(dir);
 	else
@@ -265,7 +267,7 @@  static int msdos_create(struct inode *dir, struct dentry *dentry, umode_t mode,
 	struct super_block *sb = dir->i_sb;
 	struct inode *inode = NULL;
 	struct fat_slot_info sinfo;
-	struct timespec ts;
+	struct inode_timespec ts;
 	unsigned char msdos_name[MSDOS_NAME];
 	int err, is_hid;
 
@@ -283,7 +285,7 @@  static int msdos_create(struct inode *dir, struct dentry *dentry, umode_t mode,
 		goto out;
 	}
 
-	ts = CURRENT_TIME_SEC;
+	ts = current_fs_time_sec(sb);
 	err = msdos_add_entry(dir, msdos_name, 0, is_hid, 0, &ts, &sinfo);
 	if (err)
 		goto out;
@@ -293,7 +295,9 @@  static int msdos_create(struct inode *dir, struct dentry *dentry, umode_t mode,
 		err = PTR_ERR(inode);
 		goto out;
 	}
-	inode->i_mtime = inode->i_atime = inode->i_ctime = ts;
+	VFS_INODE_SET_XTIME(i_atime, inode, ts);
+	VFS_INODE_SET_XTIME(i_mtime, inode, ts);
+	VFS_INODE_SET_XTIME(i_ctime, inode, ts);
 	/* timestamp is already written, so mark_inode_dirty() is unneeded. */
 
 	d_instantiate(dentry, inode);
@@ -330,7 +334,7 @@  static int msdos_rmdir(struct inode *dir, struct dentry *dentry)
 	drop_nlink(dir);
 
 	clear_nlink(inode);
-	inode->i_ctime = CURRENT_TIME_SEC;
+	VFS_INODE_SET_XTIME(i_ctime, inode, current_fs_time_sec(sb));
 	fat_detach(inode);
 out:
 	mutex_unlock(&MSDOS_SB(sb)->s_lock);
@@ -347,7 +351,7 @@  static int msdos_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
 	struct fat_slot_info sinfo;
 	struct inode *inode;
 	unsigned char msdos_name[MSDOS_NAME];
-	struct timespec ts;
+	struct inode_timespec ts;
 	int err, is_hid, cluster;
 
 	mutex_lock(&MSDOS_SB(sb)->s_lock);
@@ -364,7 +368,7 @@  static int msdos_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
 		goto out;
 	}
 
-	ts = CURRENT_TIME_SEC;
+	ts = current_fs_time_sec(sb);
 	cluster = fat_alloc_new_dir(dir, &ts);
 	if (cluster < 0) {
 		err = cluster;
@@ -383,7 +387,9 @@  static int msdos_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
 		goto out;
 	}
 	set_nlink(inode, 2);
-	inode->i_mtime = inode->i_atime = inode->i_ctime = ts;
+	VFS_INODE_SET_XTIME(i_atime, inode, ts);
+	VFS_INODE_SET_XTIME(i_mtime, inode, ts);
+	VFS_INODE_SET_XTIME(i_ctime, inode, ts);
 	/* timestamp is already written, so mark_inode_dirty() is unneeded. */
 
 	d_instantiate(dentry, inode);
@@ -416,7 +422,7 @@  static int msdos_unlink(struct inode *dir, struct dentry *dentry)
 	if (err)
 		goto out;
 	clear_nlink(inode);
-	inode->i_ctime = CURRENT_TIME_SEC;
+	VFS_INODE_SET_XTIME(i_ctime, inode, current_fs_time_sec(sb));
 	fat_detach(inode);
 out:
 	mutex_unlock(&MSDOS_SB(sb)->s_lock);
@@ -434,8 +440,9 @@  static int do_msdos_rename(struct inode *old_dir, unsigned char *old_name,
 	struct buffer_head *dotdot_bh;
 	struct msdos_dir_entry *dotdot_de;
 	struct inode *old_inode, *new_inode;
+	struct super_block *sb = old_dir->i_sb;
 	struct fat_slot_info old_sinfo, sinfo;
-	struct timespec ts;
+	struct inode_timespec ts;
 	loff_t new_i_pos;
 	int err, old_attrs, is_dir, update_dotdot, corrupt = 0;
 
@@ -481,7 +488,9 @@  static int do_msdos_rename(struct inode *old_dir, unsigned char *old_name,
 				mark_inode_dirty(old_inode);
 
 			old_dir->i_version++;
-			old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME_SEC;
+			ts = current_fs_time_sec(sb);
+			VFS_INODE_SET_XTIME(i_ctime, old_dir, ts);
+			VFS_INODE_SET_XTIME(i_mtime, old_dir, ts);
 			if (IS_DIRSYNC(old_dir))
 				(void)fat_sync_inode(old_dir);
 			else
@@ -490,7 +499,7 @@  static int do_msdos_rename(struct inode *old_dir, unsigned char *old_name,
 		}
 	}
 
-	ts = CURRENT_TIME_SEC;
+	ts = current_fs_time_sec(sb);
 	if (new_inode) {
 		if (err)
 			goto out;
@@ -541,7 +550,8 @@  static int do_msdos_rename(struct inode *old_dir, unsigned char *old_name,
 	if (err)
 		goto error_dotdot;
 	old_dir->i_version++;
-	old_dir->i_ctime = old_dir->i_mtime = ts;
+	VFS_INODE_SET_XTIME(i_ctime, old_dir, ts);
+	VFS_INODE_SET_XTIME(i_mtime, old_dir, ts);
 	if (IS_DIRSYNC(old_dir))
 		(void)fat_sync_inode(old_dir);
 	else
@@ -551,7 +561,7 @@  static int do_msdos_rename(struct inode *old_dir, unsigned char *old_name,
 		drop_nlink(new_inode);
 		if (is_dir)
 			drop_nlink(new_inode);
-		new_inode->i_ctime = ts;
+		VFS_INODE_SET_XTIME(i_ctime, new_dir, ts);
 	}
 out:
 	brelse(sinfo.bh);
diff --git a/fs/fat/namei_vfat.c b/fs/fat/namei_vfat.c
index 7092584..31da5b6 100644
--- a/fs/fat/namei_vfat.c
+++ b/fs/fat/namei_vfat.c
@@ -577,7 +577,7 @@  xlate_to_uni(const unsigned char *name, int len, unsigned char *outname,
 
 static int vfat_build_slots(struct inode *dir, const unsigned char *name,
 			    int len, int is_dir, int cluster,
-			    struct timespec *ts,
+			    struct inode_timespec *ts,
 			    struct msdos_dir_slot *slots, int *nr_slots)
 {
 	struct msdos_sb_info *sbi = MSDOS_SB(dir->i_sb);
@@ -653,7 +653,7 @@  out_free:
 }
 
 static int vfat_add_entry(struct inode *dir, struct qstr *qname, int is_dir,
-			  int cluster, struct timespec *ts,
+			  int cluster, struct inode_timespec *ts,
 			  struct fat_slot_info *sinfo)
 {
 	struct msdos_dir_slot *slots;
@@ -678,7 +678,9 @@  static int vfat_add_entry(struct inode *dir, struct qstr *qname, int is_dir,
 		goto cleanup;
 
 	/* update timestamp */
-	dir->i_ctime = dir->i_mtime = dir->i_atime = *ts;
+	VFS_INODE_SET_XTIME(i_ctime, dir, *ts);
+	VFS_INODE_SET_XTIME(i_mtime, dir, *ts);
+	VFS_INODE_SET_XTIME(i_atime, dir, *ts);
 	if (IS_DIRSYNC(dir))
 		(void)fat_sync_inode(dir);
 	else
@@ -772,12 +774,12 @@  static int vfat_create(struct inode *dir, struct dentry *dentry, umode_t mode,
 	struct super_block *sb = dir->i_sb;
 	struct inode *inode;
 	struct fat_slot_info sinfo;
-	struct timespec ts;
+	struct inode_timespec ts;
 	int err;
 
 	mutex_lock(&MSDOS_SB(sb)->s_lock);
 
-	ts = CURRENT_TIME_SEC;
+	ts = current_fs_time_sec(sb);
 	err = vfat_add_entry(dir, &dentry->d_name, 0, 0, &ts, &sinfo);
 	if (err)
 		goto out;
@@ -790,7 +792,9 @@  static int vfat_create(struct inode *dir, struct dentry *dentry, umode_t mode,
 		goto out;
 	}
 	inode->i_version++;
-	inode->i_mtime = inode->i_atime = inode->i_ctime = ts;
+	VFS_INODE_SET_XTIME(i_atime, inode, ts);
+	VFS_INODE_SET_XTIME(i_mtime, inode, ts);
+	VFS_INODE_SET_XTIME(i_ctime, inode, ts);
 	/* timestamp is already written, so mark_inode_dirty() is unneeded. */
 
 	d_instantiate(dentry, inode);
@@ -804,6 +808,7 @@  static int vfat_rmdir(struct inode *dir, struct dentry *dentry)
 	struct inode *inode = d_inode(dentry);
 	struct super_block *sb = dir->i_sb;
 	struct fat_slot_info sinfo;
+	struct inode_timespec now;
 	int err;
 
 	mutex_lock(&MSDOS_SB(sb)->s_lock);
@@ -821,7 +826,9 @@  static int vfat_rmdir(struct inode *dir, struct dentry *dentry)
 	drop_nlink(dir);
 
 	clear_nlink(inode);
-	inode->i_mtime = inode->i_atime = CURRENT_TIME_SEC;
+	now = current_fs_time_sec(sb);
+	VFS_INODE_SET_XTIME(i_atime, inode, now);
+	VFS_INODE_SET_XTIME(i_mtime, inode, now);
 	fat_detach(inode);
 	dentry->d_time = dir->i_version;
 out:
@@ -835,6 +842,7 @@  static int vfat_unlink(struct inode *dir, struct dentry *dentry)
 	struct inode *inode = d_inode(dentry);
 	struct super_block *sb = dir->i_sb;
 	struct fat_slot_info sinfo;
+	struct inode_timespec now;
 	int err;
 
 	mutex_lock(&MSDOS_SB(sb)->s_lock);
@@ -847,7 +855,9 @@  static int vfat_unlink(struct inode *dir, struct dentry *dentry)
 	if (err)
 		goto out;
 	clear_nlink(inode);
-	inode->i_mtime = inode->i_atime = CURRENT_TIME_SEC;
+	now = current_fs_time_sec(sb);
+	VFS_INODE_SET_XTIME(i_atime, dir, now);
+	VFS_INODE_SET_XTIME(i_mtime, dir, now);
 	fat_detach(inode);
 	dentry->d_time = dir->i_version;
 out:
@@ -861,7 +871,7 @@  static int vfat_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
 	struct super_block *sb = dir->i_sb;
 	struct inode *inode;
 	struct fat_slot_info sinfo;
-	struct timespec ts;
+	struct inode_timespec ts;
 	int err, cluster;
 
 	mutex_lock(&MSDOS_SB(sb)->s_lock);
@@ -887,7 +897,9 @@  static int vfat_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
 	}
 	inode->i_version++;
 	set_nlink(inode, 2);
-	inode->i_mtime = inode->i_atime = inode->i_ctime = ts;
+	VFS_INODE_SET_XTIME(i_atime, inode, ts);
+	VFS_INODE_SET_XTIME(i_mtime, inode, ts);
+	VFS_INODE_SET_XTIME(i_ctime, inode, ts);
 	/* timestamp is already written, so mark_inode_dirty() is unneeded. */
 
 	d_instantiate(dentry, inode);
@@ -909,7 +921,7 @@  static int vfat_rename(struct inode *old_dir, struct dentry *old_dentry,
 	struct msdos_dir_entry *dotdot_de;
 	struct inode *old_inode, *new_inode;
 	struct fat_slot_info old_sinfo, sinfo;
-	struct timespec ts;
+	struct inode_timespec ts;
 	loff_t new_i_pos;
 	int err, is_dir, update_dotdot, corrupt = 0;
 	struct super_block *sb = old_dir->i_sb;
@@ -931,7 +943,7 @@  static int vfat_rename(struct inode *old_dir, struct dentry *old_dentry,
 		}
 	}
 
-	ts = CURRENT_TIME_SEC;
+	ts = current_fs_time_sec(sb);
 	if (new_inode) {
 		if (is_dir) {
 			err = fat_dir_empty(new_inode);
@@ -976,7 +988,8 @@  static int vfat_rename(struct inode *old_dir, struct dentry *old_dentry,
 	if (err)
 		goto error_dotdot;
 	old_dir->i_version++;
-	old_dir->i_ctime = old_dir->i_mtime = ts;
+	VFS_INODE_SET_XTIME(i_ctime, old_dir, ts);
+	VFS_INODE_SET_XTIME(i_mtime, old_dir, ts);
 	if (IS_DIRSYNC(old_dir))
 		(void)fat_sync_inode(old_dir);
 	else
@@ -986,7 +999,7 @@  static int vfat_rename(struct inode *old_dir, struct dentry *old_dentry,
 		drop_nlink(new_inode);
 		if (is_dir)
 			drop_nlink(new_inode);
-		new_inode->i_ctime = ts;
+		VFS_INODE_SET_XTIME(i_ctime, new_inode, ts);
 	}
 out:
 	brelse(sinfo.bh);