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