[PATCH v3 4/5] vfs: Add timestamp_truncate() api

From: Deepa Dinamani
Date: Sat Feb 18 2017 - 18:31:55 EST


timespec_trunc() function is used to truncate a
filesystem timestamp to the right granularity.
But, the function does not clamp tv_sec part of the
timestamps according to the filesystem timestamp limits.

Also, timespec_trunc() is exclusively used for filesystem
timestamps. Move the api to be part of vfs.

The replacement api: timestamp_truncate() also alters the
signature of the function to accommodate filesystem
timestamp clamping according to flesystem limits.

Note that the clamp_t macro is used for clamping here as vfs
is not yet using struct timespec64 internally. This is
required for compilation purposes.
Also note that clamp won't do the right thing for timestamps
beyond 2038 on 32-bit machines until the vfs uses timespec64.
After the vfs is transitioned to use timespec64 for timestamps,
clamp_t() can be replaced by clamp().

Signed-off-by: Deepa Dinamani <deepa.kernel@xxxxxxxxx>
---
fs/inode.c | 32 +++++++++++++++++++++++++++++++-
1 file changed, 31 insertions(+), 1 deletion(-)

diff --git a/fs/inode.c b/fs/inode.c
index 0573a3e..6a1bc12 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -2114,6 +2114,36 @@ void inode_nohighmem(struct inode *inode)
EXPORT_SYMBOL(inode_nohighmem);

/**
+ * fs_timespec_trunc - Truncate timespec to a granularity
+ * @t: Timespec
+ * @gran: Granularity in ns.
+ *
+ * Truncate a timespec to a granularity. Always rounds down. gran must
+ * not be 0 nor greater than a second (NSEC_PER_SEC, or 10^9 ns).
+ */
+struct timespec timestamp_truncate(struct timespec t, struct inode *inode)
+{
+ struct super_block *sb = inode->i_sb;
+ unsigned int gran = sb->s_time_gran;
+
+ t.tv_sec = clamp_t(time64_t, t.tv_sec, sb->s_time_min, sb->s_time_max);
+
+ /* Avoid division in the common cases 1 ns and 1 s. */
+ if (gran == 1) {
+ /* nothing */
+ } else if (gran == NSEC_PER_SEC) {
+ t.tv_nsec = 0;
+ } else if (gran > 1 && gran < NSEC_PER_SEC) {
+ t.tv_nsec -= t.tv_nsec % gran;
+ } else {
+ WARN(1, "illegal file time granularity: %u", gran);
+ }
+ return t;
+}
+EXPORT_SYMBOL(timestamp_truncate);
+
+
+/**
* current_time - Return FS time
* @inode: inode.
*
@@ -2132,6 +2162,6 @@ struct timespec current_time(struct inode *inode)
return now;
}

- return timespec_trunc(now, inode->i_sb->s_time_gran);
+ return timestamp_truncate(now, inode);
}
EXPORT_SYMBOL(current_time);
--
2.7.4