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

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