Blame SOURCES/0018-exfat-truncate-atimes-to-2s-granularity.patch

Kmods SIG 9e3ffb
From 81df1ad40644b706a1cdbd28a1471f9f0c0ea3e8 Mon Sep 17 00:00:00 2001
Kmods SIG 9e3ffb
From: Eric Sandeen <sandeen@sandeen.net>
Kmods SIG 9e3ffb
Date: Tue, 21 Apr 2020 11:13:10 +0900
Kmods SIG 9e3ffb
Subject: [Backport 81df1ad40644] exfat: truncate atimes to 2s granularity
Kmods SIG 9e3ffb
Kmods SIG 9e3ffb
The timestamp for access_time has double seconds granularity(There is no
Kmods SIG 9e3ffb
10msIncrement field for access_time unlike create/modify_time).
Kmods SIG 9e3ffb
exfat's atimes are restricted to only 2s granularity so after
Kmods SIG 9e3ffb
we set an atime, round it down to the nearest 2s and set the
Kmods SIG 9e3ffb
sub-second component of the timestamp to 0.
Kmods SIG 9e3ffb
Kmods SIG 9e3ffb
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
Kmods SIG 9e3ffb
Signed-off-by: Namjae Jeon <namjae.jeon@samsung.com>
Kmods SIG 9e3ffb
---
Kmods SIG 9e3ffb
 src/exfat_fs.h |  1 +
Kmods SIG 9e3ffb
 src/file.c     |  2 ++
Kmods SIG 9e3ffb
 src/misc.c     | 14 +++++++++++++-
Kmods SIG 9e3ffb
 src/namei.c    |  7 +++++++
Kmods SIG 9e3ffb
 src/super.c    |  1 +
Kmods SIG 9e3ffb
 5 files changed, 24 insertions(+), 1 deletion(-)
Kmods SIG 9e3ffb
Kmods SIG 9e3ffb
diff --git a/src/exfat_fs.h b/src/exfat_fs.h
Kmods SIG 9e3ffb
index 67d4e46fb81003d0c367862ee986b37c80e7fa4e..d67fb8a6f770c28db8f1618c78fde493e2a4b965 100644
Kmods SIG 9e3ffb
--- a/src/exfat_fs.h
Kmods SIG 9e3ffb
+++ b/src/exfat_fs.h
Kmods SIG 9e3ffb
@@ -507,6 +507,7 @@ void exfat_msg(struct super_block *sb, const char *lv, const char *fmt, ...)
Kmods SIG 9e3ffb
 		__printf(3, 4) __cold;
Kmods SIG 9e3ffb
 void exfat_get_entry_time(struct exfat_sb_info *sbi, struct timespec64 *ts,
Kmods SIG 9e3ffb
 		u8 tz, __le16 time, __le16 date, u8 time_ms);
Kmods SIG 9e3ffb
+void exfat_truncate_atime(struct timespec64 *ts);
Kmods SIG 9e3ffb
 void exfat_set_entry_time(struct exfat_sb_info *sbi, struct timespec64 *ts,
Kmods SIG 9e3ffb
 		u8 *tz, __le16 *time, __le16 *date, u8 *time_ms);
Kmods SIG 9e3ffb
 unsigned short exfat_calc_chksum_2byte(void *data, int len,
Kmods SIG 9e3ffb
diff --git a/src/file.c b/src/file.c
Kmods SIG 9e3ffb
index 483f683757aa87420ba347afd3c9db9e94b8a14d..4f76764165cf6f63a99c5e192ab33685e8e987b7 100644
Kmods SIG 9e3ffb
--- a/src/file.c
Kmods SIG 9e3ffb
+++ b/src/file.c
Kmods SIG 9e3ffb
@@ -273,6 +273,7 @@ int exfat_getattr(const struct path *path, struct kstat *stat,
Kmods SIG 9e3ffb
 	struct exfat_inode_info *ei = EXFAT_I(inode);
Kmods SIG 9e3ffb
 
Kmods SIG 9e3ffb
 	generic_fillattr(inode, stat);
Kmods SIG 9e3ffb
+	exfat_truncate_atime(&stat->atime);
Kmods SIG 9e3ffb
 	stat->result_mask |= STATX_BTIME;
Kmods SIG 9e3ffb
 	stat->btime.tv_sec = ei->i_crtime.tv_sec;
Kmods SIG 9e3ffb
 	stat->btime.tv_nsec = ei->i_crtime.tv_nsec;
Kmods SIG 9e3ffb
@@ -339,6 +340,7 @@ int exfat_setattr(struct dentry *dentry, struct iattr *attr)
Kmods SIG 9e3ffb
 	}
Kmods SIG 9e3ffb
 
Kmods SIG 9e3ffb
 	setattr_copy(inode, attr);
Kmods SIG 9e3ffb
+	exfat_truncate_atime(&inode->i_atime);
Kmods SIG 9e3ffb
 	mark_inode_dirty(inode);
Kmods SIG 9e3ffb
 
Kmods SIG 9e3ffb
 out:
Kmods SIG 9e3ffb
diff --git a/src/misc.c b/src/misc.c
Kmods SIG 9e3ffb
index 14a3300848f6a0fb754b9d34bdacbc31b90f5d07..ebd2cbe3cbc11c2aede3819c414020b9344ec1f9 100644
Kmods SIG 9e3ffb
--- a/src/misc.c
Kmods SIG 9e3ffb
+++ b/src/misc.c
Kmods SIG 9e3ffb
@@ -88,7 +88,8 @@ void exfat_get_entry_time(struct exfat_sb_info *sbi, struct timespec64 *ts,
Kmods SIG 9e3ffb
 	if (time_ms) {
Kmods SIG 9e3ffb
 		ts->tv_sec += time_ms / 100;
Kmods SIG 9e3ffb
 		ts->tv_nsec = (time_ms % 100) * 10 * NSEC_PER_MSEC;
Kmods SIG 9e3ffb
-	}
Kmods SIG 9e3ffb
+	} else
Kmods SIG 9e3ffb
+		ts->tv_nsec = 0;
Kmods SIG 9e3ffb
 
Kmods SIG 9e3ffb
 	if (tz & EXFAT_TZ_VALID)
Kmods SIG 9e3ffb
 		/* Adjust timezone to UTC0. */
Kmods SIG 9e3ffb
@@ -124,6 +125,17 @@ void exfat_set_entry_time(struct exfat_sb_info *sbi, struct timespec64 *ts,
Kmods SIG 9e3ffb
 	*tz = EXFAT_TZ_VALID;
Kmods SIG 9e3ffb
 }
Kmods SIG 9e3ffb
 
Kmods SIG 9e3ffb
+/*
Kmods SIG 9e3ffb
+ * The timestamp for access_time has double seconds granularity.
Kmods SIG 9e3ffb
+ * (There is no 10msIncrement field for access_time unlike create/modify_time)
Kmods SIG 9e3ffb
+ * atime also has only a 2-second resolution.
Kmods SIG 9e3ffb
+ */
Kmods SIG 9e3ffb
+void exfat_truncate_atime(struct timespec64 *ts)
Kmods SIG 9e3ffb
+{
Kmods SIG 9e3ffb
+	ts->tv_sec = round_down(ts->tv_sec, 2);
Kmods SIG 9e3ffb
+	ts->tv_nsec = 0;
Kmods SIG 9e3ffb
+}
Kmods SIG 9e3ffb
+
Kmods SIG 9e3ffb
 unsigned short exfat_calc_chksum_2byte(void *data, int len,
Kmods SIG 9e3ffb
 		unsigned short chksum, int type)
Kmods SIG 9e3ffb
 {
Kmods SIG 9e3ffb
diff --git a/src/namei.c b/src/namei.c
Kmods SIG 9e3ffb
index a8681d91f56900107ea3df90e2b6dd986045a7bc..b72d782568b811ece222db0dd3575fd8bf2c958a 100644
Kmods SIG 9e3ffb
--- a/src/namei.c
Kmods SIG 9e3ffb
+++ b/src/namei.c
Kmods SIG 9e3ffb
@@ -595,6 +595,7 @@ static int exfat_create(struct inode *dir, struct dentry *dentry, umode_t mode,
Kmods SIG 9e3ffb
 	inode_inc_iversion(inode);
Kmods SIG 9e3ffb
 	inode->i_mtime = inode->i_atime = inode->i_ctime =
Kmods SIG 9e3ffb
 		EXFAT_I(inode)->i_crtime = current_time(inode);
Kmods SIG 9e3ffb
+	exfat_truncate_atime(&inode->i_atime);
Kmods SIG 9e3ffb
 	/* timestamp is already written, so mark_inode_dirty() is unneeded. */
Kmods SIG 9e3ffb
 
Kmods SIG 9e3ffb
 	d_instantiate(dentry, inode);
Kmods SIG 9e3ffb
@@ -854,6 +855,7 @@ static int exfat_unlink(struct inode *dir, struct dentry *dentry)
Kmods SIG 9e3ffb
 
Kmods SIG 9e3ffb
 	inode_inc_iversion(dir);
Kmods SIG 9e3ffb
 	dir->i_mtime = dir->i_atime = current_time(dir);
Kmods SIG 9e3ffb
+	exfat_truncate_atime(&dir->i_atime);
Kmods SIG 9e3ffb
 	if (IS_DIRSYNC(dir))
Kmods SIG 9e3ffb
 		exfat_sync_inode(dir);
Kmods SIG 9e3ffb
 	else
Kmods SIG 9e3ffb
@@ -861,6 +863,7 @@ static int exfat_unlink(struct inode *dir, struct dentry *dentry)
Kmods SIG 9e3ffb
 
Kmods SIG 9e3ffb
 	clear_nlink(inode);
Kmods SIG 9e3ffb
 	inode->i_mtime = inode->i_atime = current_time(inode);
Kmods SIG 9e3ffb
+	exfat_truncate_atime(&inode->i_atime);
Kmods SIG 9e3ffb
 	exfat_unhash_inode(inode);
Kmods SIG 9e3ffb
 	exfat_d_version_set(dentry, inode_query_iversion(dir));
Kmods SIG 9e3ffb
 unlock:
Kmods SIG 9e3ffb
@@ -903,6 +906,7 @@ static int exfat_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
Kmods SIG 9e3ffb
 	inode_inc_iversion(inode);
Kmods SIG 9e3ffb
 	inode->i_mtime = inode->i_atime = inode->i_ctime =
Kmods SIG 9e3ffb
 		EXFAT_I(inode)->i_crtime = current_time(inode);
Kmods SIG 9e3ffb
+	exfat_truncate_atime(&inode->i_atime);
Kmods SIG 9e3ffb
 	/* timestamp is already written, so mark_inode_dirty() is unneeded. */
Kmods SIG 9e3ffb
 
Kmods SIG 9e3ffb
 	d_instantiate(dentry, inode);
Kmods SIG 9e3ffb
@@ -1019,6 +1023,7 @@ static int exfat_rmdir(struct inode *dir, struct dentry *dentry)
Kmods SIG 9e3ffb
 
Kmods SIG 9e3ffb
 	inode_inc_iversion(dir);
Kmods SIG 9e3ffb
 	dir->i_mtime = dir->i_atime = current_time(dir);
Kmods SIG 9e3ffb
+	exfat_truncate_atime(&dir->i_atime);
Kmods SIG 9e3ffb
 	if (IS_DIRSYNC(dir))
Kmods SIG 9e3ffb
 		exfat_sync_inode(dir);
Kmods SIG 9e3ffb
 	else
Kmods SIG 9e3ffb
@@ -1027,6 +1032,7 @@ static int exfat_rmdir(struct inode *dir, struct dentry *dentry)
Kmods SIG 9e3ffb
 
Kmods SIG 9e3ffb
 	clear_nlink(inode);
Kmods SIG 9e3ffb
 	inode->i_mtime = inode->i_atime = current_time(inode);
Kmods SIG 9e3ffb
+	exfat_truncate_atime(&inode->i_atime);
Kmods SIG 9e3ffb
 	exfat_unhash_inode(inode);
Kmods SIG 9e3ffb
 	exfat_d_version_set(dentry, inode_query_iversion(dir));
Kmods SIG 9e3ffb
 unlock:
Kmods SIG 9e3ffb
@@ -1387,6 +1393,7 @@ static int exfat_rename(struct inode *old_dir, struct dentry *old_dentry,
Kmods SIG 9e3ffb
 	inode_inc_iversion(new_dir);
Kmods SIG 9e3ffb
 	new_dir->i_ctime = new_dir->i_mtime = new_dir->i_atime =
Kmods SIG 9e3ffb
 		EXFAT_I(new_dir)->i_crtime = current_time(new_dir);
Kmods SIG 9e3ffb
+	exfat_truncate_atime(&new_dir->i_atime);
Kmods SIG 9e3ffb
 	if (IS_DIRSYNC(new_dir))
Kmods SIG 9e3ffb
 		exfat_sync_inode(new_dir);
Kmods SIG 9e3ffb
 	else
Kmods SIG 9e3ffb
diff --git a/src/super.c b/src/super.c
Kmods SIG 9e3ffb
index ee42ecf59059a6c9bf61f5b6ec19efde21a4d897..0565d5539d57c6678c81997228dc3b8116eb864c 100644
Kmods SIG 9e3ffb
--- a/src/super.c
Kmods SIG 9e3ffb
+++ b/src/super.c
Kmods SIG 9e3ffb
@@ -342,6 +342,7 @@ static int exfat_read_root(struct inode *inode)
Kmods SIG 9e3ffb
 	exfat_save_attr(inode, ATTR_SUBDIR);
Kmods SIG 9e3ffb
 	inode->i_mtime = inode->i_atime = inode->i_ctime = ei->i_crtime =
Kmods SIG 9e3ffb
 		current_time(inode);
Kmods SIG 9e3ffb
+	exfat_truncate_atime(&inode->i_atime);
Kmods SIG 9e3ffb
 	exfat_cache_init_inode(inode);
Kmods SIG 9e3ffb
 	return 0;
Kmods SIG 9e3ffb
 }
Kmods SIG 9e3ffb
-- 
Kmods SIG 9e3ffb
2.31.1
Kmods SIG 9e3ffb