summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorAndi Kleen <ak@suse.de>2005-01-04 05:30:08 -0800
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-01-04 05:30:08 -0800
commit8ce13b01c190a7e663ea146ba89d1153240884bb (patch)
tree5979ec0f842bf2765c77f90f9628a62b7eb32ca4 /include
parent8fa29920db547f6d0e7729533be5ccf0a005b89b (diff)
[PATCH] Sync in core time granuality with filesystems
This patch corrects a problem that was originally added with the nanosecond timestamps in stat patch. The problem is that some file systems don't have enough space in their on disk inode to save nanosecond timestamps, so they truncate the c/a/mtime to seconds when flushing an dirty node. In core the inode would have full jiffies granuality. This can be observed by programs as a timestamp that jumps backwards under specific loads when an inode is flushed and then reloaded from disk. The problem was already known when the original patch went in, but it wasn't deemed important enough at that time. So far there has been only one report of it causing problems. Now Tridge is worried that it will break running Excel over samba4 because Excel seems to do very anal timestamp checking and samba4 will supply 100ns timestamps over the network. This patch solves it by putting the time resolution into the superblock of a fs and always rounding the in core timestamps to that granuality. This also supercedes some previous ext2/3 hacks to flush the inode less often when only the subsecond timestamp changes. I tried to keep the overhead low, in particular it tries to keep divisions out of fast paths as far as possible. The patch is quite big but 99% of it is just relatively straight forward search'n'replace in a lot of fs. Unconverted filesystems will default to a 1ns granuality, but may still show the problem if they continue to use CURRENT_TIME. I converted all in tree fs. One possible future extension of this would be to have two time granualities per superblock - one that specifies the visible resolution, and the other to specify how often timestamps should be flushed to disk, which could be tuned with a mount option per fs (e.g. often m/atimes don't need to be flushed every second). Would be easy to do as an addon if someone is interested. Signed-off-by: Andi Kleen <ak@suse.de> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'include')
-rw-r--r--include/linux/fs.h8
-rw-r--r--include/linux/time.h3
2 files changed, 9 insertions, 2 deletions
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 7bed389b9dfd..526f4f883fc5 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -123,7 +123,6 @@ extern int dir_notify_enable;
#define MS_REC 16384
#define MS_VERBOSE 32768
#define MS_POSIXACL (1<<16) /* VFS does not apply the umask */
-#define MS_ONE_SECOND (1<<17) /* fs has 1 sec a/m/ctime resolution */
#define MS_ACTIVE (1<<30)
#define MS_NOUSER (1<<31)
@@ -179,7 +178,6 @@ extern int dir_notify_enable;
#define IS_NOATIME(inode) (__IS_FLG(inode, MS_NOATIME) || ((inode)->i_flags & S_NOATIME))
#define IS_NODIRATIME(inode) __IS_FLG(inode, MS_NODIRATIME)
#define IS_POSIXACL(inode) __IS_FLG(inode, MS_POSIXACL)
-#define IS_ONE_SECOND(inode) __IS_FLG(inode, MS_ONE_SECOND)
#define IS_DEADDIR(inode) ((inode)->i_flags & S_DEAD)
#define IS_NOCMTIME(inode) ((inode)->i_flags & S_NOCMTIME)
@@ -798,8 +796,14 @@ struct super_block {
* even looking at it. You had been warned.
*/
struct semaphore s_vfs_rename_sem; /* Kludge */
+
+ /* Granuality of c/m/atime in ns.
+ Cannot be worse than a second */
+ u32 s_time_gran;
};
+extern struct timespec current_fs_time(struct super_block *sb);
+
/*
* Snapshotting support.
*/
diff --git a/include/linux/time.h b/include/linux/time.h
index 0814ed4a4586..5634497ff5df 100644
--- a/include/linux/time.h
+++ b/include/linux/time.h
@@ -90,6 +90,7 @@ static inline unsigned long get_seconds(void)
struct timespec current_kernel_time(void);
#define CURRENT_TIME (current_kernel_time())
+#define CURRENT_TIME_SEC ((struct timespec) { xtime.tv_sec, 0 })
extern void do_gettimeofday(struct timeval *tv);
extern int do_settimeofday(struct timespec *tv);
@@ -103,6 +104,8 @@ extern int do_setitimer(int which, struct itimerval *value, struct itimerval *ov
extern int do_getitimer(int which, struct itimerval *value);
extern void getnstimeofday (struct timespec *tv);
+extern struct timespec timespec_trunc(struct timespec t, unsigned gran);
+
static inline void
set_normalized_timespec (struct timespec *ts, time_t sec, long nsec)
{