--- /dev/null
+Index: linux-2.6.10/drivers/char/qtronix.c
+===================================================================
+--- linux-2.6.10.orig/drivers/char/qtronix.c 2004-12-24 14:35:50.000000000 -0700
++++ linux-2.6.10/drivers/char/qtronix.c 2006-01-03 16:16:52.000000000 -0700
+@@ -537,7 +537,7 @@
+ i--;
+ }
+ if (count-i) {
+- file->f_dentry->d_inode->i_atime = CURRENT_TIME;
++ file->f_dentry->d_inode->i_atime = current_fs_time(inode->i_sb);
+ return count-i;
+ }
+ if (signal_pending(current))
+Index: linux-2.6.10/drivers/char/random.c
+===================================================================
+--- linux-2.6.10.orig/drivers/char/random.c 2005-04-06 09:38:33.000000000 -0600
++++ linux-2.6.10/drivers/char/random.c 2006-01-03 16:16:52.000000000 -0700
+@@ -1743,8 +1743,9 @@
+ if (p == buffer) {
+ return (ssize_t)ret;
+ } else {
+- file->f_dentry->d_inode->i_mtime = CURRENT_TIME;
+- mark_inode_dirty(file->f_dentry->d_inode);
++ struct inode *inode = file->f_dentry->d_inode;
++ inode->i_mtime = current_fs_time(inode->i_sb);
++ mark_inode_dirty(inode);
+ return (ssize_t)(p - buffer);
+ }
+ }
+Index: linux-2.6.10/drivers/char/sonypi.c
+===================================================================
+--- linux-2.6.10.orig/drivers/char/sonypi.c 2004-12-24 14:35:23.000000000 -0700
++++ linux-2.6.10/drivers/char/sonypi.c 2006-01-03 16:18:31.000000000 -0700
+@@ -537,7 +537,8 @@
+ }
+
+ if (ret > 0)
+- file->f_dentry->d_inode->i_atime = CURRENT_TIME;
++ struct inode *inode = file->f_dentry->d_inode;
++ inode->i_atime = current_fs_time(inode->i_sb);
+
+ return ret;
+ }
+Index: linux-2.6.10/drivers/char/tty_io.c
+===================================================================
+--- linux-2.6.10.orig/drivers/char/tty_io.c 2005-04-06 09:38:33.000000000 -0600
++++ linux-2.6.10/drivers/char/tty_io.c 2006-01-03 16:16:52.000000000 -0700
+@@ -1018,7 +1018,7 @@
+ tty_ldisc_deref(ld);
+ unlock_kernel();
+ if (i > 0)
+- inode->i_atime = CURRENT_TIME;
++ inode->i_atime = current_fs_time(inode->i_sb);
+ return i;
+ }
+
+@@ -1095,7 +1095,8 @@
+ cond_resched();
+ }
+ if (written) {
+- file->f_dentry->d_inode->i_mtime = CURRENT_TIME;
++ struct inode *inode = file->f_dentry->d_inode;
++ inode->i_mtime = current_fs_time(inode->i_sb);
+ ret = written;
+ }
+ up(&tty->atomic_write);
+Index: linux-2.6.10/fs/attr.c
+===================================================================
+--- linux-2.6.10.orig/fs/attr.c 2004-12-24 14:34:00.000000000 -0700
++++ linux-2.6.10/fs/attr.c 2006-01-03 16:16:52.000000000 -0700
+@@ -14,6 +14,7 @@
+ #include <linux/fcntl.h>
+ #include <linux/quotaops.h>
+ #include <linux/security.h>
++#include <linux/time.h>
+
+ /* Taken over from the old code... */
+
+@@ -87,11 +88,14 @@
+ if (ia_valid & ATTR_GID)
+ inode->i_gid = attr->ia_gid;
+ if (ia_valid & ATTR_ATIME)
+- inode->i_atime = attr->ia_atime;
++ inode->i_atime = timespec_trunc(attr->ia_atime,
++ get_sb_time_gran(inode->i_sb));
+ if (ia_valid & ATTR_MTIME)
+- inode->i_mtime = attr->ia_mtime;
++ inode->i_mtime = timespec_trunc(attr->ia_mtime,
++ get_sb_time_gran(inode->i_sb));
+ if (ia_valid & ATTR_CTIME)
+- inode->i_ctime = attr->ia_ctime;
++ inode->i_ctime = timespec_trunc(attr->ia_ctime,
++ get_sb_time_gran(inode->i_sb));
+ if (ia_valid & ATTR_MODE) {
+ umode_t mode = attr->ia_mode;
+
+@@ -131,14 +135,17 @@
+ int notify_change(struct dentry * dentry, struct iattr * attr)
+ {
+ struct inode *inode = dentry->d_inode;
+- mode_t mode = inode->i_mode;
++ mode_t mode;
+ int error;
+- struct timespec now = CURRENT_TIME;
++ struct timespec now;
+ unsigned int ia_valid = attr->ia_valid;
+
+ if (!inode)
+ BUG();
+
++ mode = inode->i_mode;
++ now = current_fs_time(inode->i_sb);
++
+ attr->ia_ctime = now;
+ if (!(ia_valid & ATTR_ATIME_SET))
+ attr->ia_atime = now;
+Index: linux-2.6.10/fs/bad_inode.c
+===================================================================
+--- linux-2.6.10.orig/fs/bad_inode.c 2004-12-24 14:35:50.000000000 -0700
++++ linux-2.6.10/fs/bad_inode.c 2006-01-03 16:16:52.000000000 -0700
+@@ -105,7 +105,8 @@
+ remove_inode_hash(inode);
+
+ inode->i_mode = S_IFREG;
+- inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
++ inode->i_atime = inode->i_mtime = inode->i_ctime =
++ current_fs_time(inode->i_sb);
+ inode->i_op = &bad_inode_ops;
+ inode->i_fop = &bad_file_ops;
+ }
+Index: linux-2.6.10/fs/binfmt_misc.c
+===================================================================
+--- linux-2.6.10.orig/fs/binfmt_misc.c 2004-12-24 14:34:31.000000000 -0700
++++ linux-2.6.10/fs/binfmt_misc.c 2006-01-03 16:16:52.000000000 -0700
+@@ -509,7 +509,8 @@
+ inode->i_gid = 0;
+ inode->i_blksize = PAGE_CACHE_SIZE;
+ inode->i_blocks = 0;
+- inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
++ inode->i_atime = inode->i_mtime = inode->i_ctime =
++ current_fs_time(inode->i_sb);
+ }
+ return inode;
+ }
+Index: linux-2.6.10/fs/ext2/dir.c
+===================================================================
+--- linux-2.6.10.orig/fs/ext2/dir.c 2004-12-24 14:34:58.000000000 -0700
++++ linux-2.6.10/fs/ext2/dir.c 2006-01-03 16:16:52.000000000 -0700
+@@ -426,7 +426,7 @@
+ ext2_set_de_type (de, inode);
+ err = ext2_commit_chunk(page, from, to);
+ ext2_put_page(page);
+- dir->i_mtime = dir->i_ctime = CURRENT_TIME;
++ dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC;
+ EXT2_I(dir)->i_flags &= ~EXT2_BTREE_FL;
+ mark_inode_dirty(dir);
+ }
+@@ -516,7 +516,7 @@
+ de->inode = cpu_to_le32(inode->i_ino);
+ ext2_set_de_type (de, inode);
+ err = ext2_commit_chunk(page, from, to);
+- dir->i_mtime = dir->i_ctime = CURRENT_TIME;
++ dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC;
+ EXT2_I(dir)->i_flags &= ~EXT2_BTREE_FL;
+ mark_inode_dirty(dir);
+ /* OFFSET_CACHE */
+@@ -564,7 +564,7 @@
+ pde->rec_len = cpu_to_le16(to-from);
+ dir->inode = 0;
+ err = ext2_commit_chunk(page, from, to);
+- inode->i_ctime = inode->i_mtime = CURRENT_TIME;
++ inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC;
+ EXT2_I(inode)->i_flags &= ~EXT2_BTREE_FL;
+ mark_inode_dirty(inode);
+ out:
+Index: linux-2.6.10/fs/ext2/ialloc.c
+===================================================================
+--- linux-2.6.10.orig/fs/ext2/ialloc.c 2004-12-24 14:34:47.000000000 -0700
++++ linux-2.6.10/fs/ext2/ialloc.c 2006-01-03 16:16:52.000000000 -0700
+@@ -577,7 +577,7 @@
+ inode->i_ino = ino;
+ inode->i_blksize = PAGE_SIZE; /* This is the optimal IO size (for stat), not the fs block size */
+ inode->i_blocks = 0;
+- inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
++ inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
+ memset(ei->i_data, 0, sizeof(ei->i_data));
+ ei->i_flags = EXT2_I(dir)->i_flags & ~EXT2_BTREE_FL;
+ if (S_ISLNK(mode))
+Index: linux-2.6.10/fs/ext2/inode.c
+===================================================================
+--- linux-2.6.10.orig/fs/ext2/inode.c 2004-12-24 14:33:51.000000000 -0700
++++ linux-2.6.10/fs/ext2/inode.c 2006-01-03 16:16:52.000000000 -0700
+@@ -493,7 +493,7 @@
+
+ /* We are done with atomic stuff, now do the rest of housekeeping */
+
+- inode->i_ctime = CURRENT_TIME;
++ inode->i_ctime = CURRENT_TIME_SEC;
+
+ /* had we spliced it onto indirect block? */
+ if (where->bh)
+@@ -953,7 +953,7 @@
+ case EXT2_TIND_BLOCK:
+ ;
+ }
+- inode->i_mtime = inode->i_ctime = CURRENT_TIME;
++ inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC;
+ if (inode_needs_sync(inode)) {
+ sync_mapping_buffers(inode->i_mapping);
+ ext2_sync_inode (inode);
+Index: linux-2.6.10/fs/ext2/ioctl.c
+===================================================================
+--- linux-2.6.10.orig/fs/ext2/ioctl.c 2004-12-24 14:35:49.000000000 -0700
++++ linux-2.6.10/fs/ext2/ioctl.c 2006-01-03 16:16:52.000000000 -0700
+@@ -59,7 +59,7 @@
+ ei->i_flags = flags;
+
+ ext2_set_inode_flags(inode);
+- inode->i_ctime = CURRENT_TIME;
++ inode->i_ctime = CURRENT_TIME_SEC;
+ mark_inode_dirty(inode);
+ return 0;
+ }
+@@ -72,7 +72,7 @@
+ return -EROFS;
+ if (get_user(inode->i_generation, (int __user *) arg))
+ return -EFAULT;
+- inode->i_ctime = CURRENT_TIME;
++ inode->i_ctime = CURRENT_TIME_SEC;
+ mark_inode_dirty(inode);
+ return 0;
+ default:
+Index: linux-2.6.10/fs/ext2/namei.c
+===================================================================
+--- linux-2.6.10.orig/fs/ext2/namei.c 2004-12-24 14:35:25.000000000 -0700
++++ linux-2.6.10/fs/ext2/namei.c 2006-01-03 16:16:52.000000000 -0700
+@@ -211,7 +211,7 @@
+ if (inode->i_nlink >= EXT2_LINK_MAX)
+ return -EMLINK;
+
+- inode->i_ctime = CURRENT_TIME;
++ inode->i_ctime = CURRENT_TIME_SEC;
+ ext2_inc_count(inode);
+ atomic_inc(&inode->i_count);
+
+@@ -337,7 +337,7 @@
+ goto out_dir;
+ ext2_inc_count(old_inode);
+ ext2_set_link(new_dir, new_de, new_page, old_inode);
+- new_inode->i_ctime = CURRENT_TIME;
++ new_inode->i_ctime = CURRENT_TIME_SEC;
+ if (dir_de)
+ new_inode->i_nlink--;
+ ext2_dec_count(new_inode);
+@@ -362,7 +362,7 @@
+ * rename.
+ * ext2_dec_count() will mark the inode dirty.
+ */
+- old_inode->i_ctime = CURRENT_TIME;
++ old_inode->i_ctime = CURRENT_TIME_SEC;
+
+ ext2_delete_entry (old_de, old_page);
+ ext2_dec_count(old_inode);
+Index: linux-2.6.10/fs/ext2/super.c
+===================================================================
+--- linux-2.6.10.orig/fs/ext2/super.c 2004-12-24 14:35:01.000000000 -0700
++++ linux-2.6.10/fs/ext2/super.c 2006-01-03 16:19:06.000000000 -0700
+@@ -595,7 +595,7 @@
+ es = (struct ext2_super_block *) (((char *)bh->b_data) + offset);
+ sbi->s_es = es;
+ sb->s_magic = le16_to_cpu(es->s_magic);
+- sb->s_flags |= MS_ONE_SECOND;
++ set_sb_time_gran(sb, 1000000000U);
+
+ if (sb->s_magic != EXT2_SUPER_MAGIC)
+ goto cantfind_ext2;
+Index: linux-2.6.10/fs/ext2/xattr.c
+===================================================================
+--- linux-2.6.10.orig/fs/ext2/xattr.c 2005-04-06 09:38:35.000000000 -0600
++++ linux-2.6.10/fs/ext2/xattr.c 2006-01-03 16:16:52.000000000 -0700
+@@ -702,7 +702,7 @@
+
+ /* Update the inode. */
+ EXT2_I(inode)->i_file_acl = new_bh ? new_bh->b_blocknr : 0;
+- inode->i_ctime = CURRENT_TIME;
++ inode->i_ctime = CURRENT_TIME_SEC;
+ if (IS_SYNC(inode)) {
+ error = ext2_sync_inode (inode);
+ if (error)
+Index: linux-2.6.10/fs/ext3/ialloc.c
+===================================================================
+--- linux-2.6.10.orig/fs/ext3/ialloc.c 2004-12-24 14:34:45.000000000 -0700
++++ linux-2.6.10/fs/ext3/ialloc.c 2006-01-03 16:16:52.000000000 -0700
+@@ -558,7 +558,7 @@
+ /* This is the optimal IO size (for stat), not the fs block size */
+ inode->i_blksize = PAGE_SIZE;
+ inode->i_blocks = 0;
+- inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
++ inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
+
+ memset(ei->i_data, 0, sizeof(ei->i_data));
+ ei->i_next_alloc_block = 0;
+Index: linux-2.6.10/fs/ext3/inode.c
+===================================================================
+--- linux-2.6.10.orig/fs/ext3/inode.c 2005-04-06 09:38:35.000000000 -0600
++++ linux-2.6.10/fs/ext3/inode.c 2006-01-03 16:16:52.000000000 -0700
+@@ -626,7 +626,7 @@
+
+ /* We are done with atomic stuff, now do the rest of housekeeping */
+
+- inode->i_ctime = CURRENT_TIME;
++ inode->i_ctime = CURRENT_TIME_SEC;
+ ext3_mark_inode_dirty(handle, inode);
+
+ /* had we spliced it onto indirect block? */
+@@ -2199,7 +2199,7 @@
+ ;
+ }
+ up(&ei->truncate_sem);
+- inode->i_mtime = inode->i_ctime = CURRENT_TIME;
++ inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC;
+ ext3_mark_inode_dirty(handle, inode);
+
+ /* In a multi-transaction truncate, we only make the final
+Index: linux-2.6.10/fs/ext3/ioctl.c
+===================================================================
+--- linux-2.6.10.orig/fs/ext3/ioctl.c 2004-12-24 14:34:31.000000000 -0700
++++ linux-2.6.10/fs/ext3/ioctl.c 2006-01-03 16:16:52.000000000 -0700
+@@ -87,7 +87,7 @@
+ ei->i_flags = flags;
+
+ ext3_set_inode_flags(inode);
+- inode->i_ctime = CURRENT_TIME;
++ inode->i_ctime = CURRENT_TIME_SEC;
+
+ err = ext3_mark_iloc_dirty(handle, inode, &iloc);
+ flags_err:
+@@ -121,7 +121,7 @@
+ return PTR_ERR(handle);
+ err = ext3_reserve_inode_write(handle, inode, &iloc);
+ if (err == 0) {
+- inode->i_ctime = CURRENT_TIME;
++ inode->i_ctime = CURRENT_TIME_SEC;
+ inode->i_generation = generation;
+ err = ext3_mark_iloc_dirty(handle, inode, &iloc);
+ }
+Index: linux-2.6.10/fs/ext3/namei.c
+===================================================================
+--- linux-2.6.10.orig/fs/ext3/namei.c 2004-12-24 14:34:58.000000000 -0700
++++ linux-2.6.10/fs/ext3/namei.c 2006-01-03 16:16:52.000000000 -0700
+@@ -1251,7 +1251,7 @@
+ * happen is that the times are slightly out of date
+ * and/or different from the directory change time.
+ */
+- dir->i_mtime = dir->i_ctime = CURRENT_TIME;
++ dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC;
+ ext3_update_dx_flag(dir);
+ dir->i_version++;
+ ext3_mark_inode_dirty(handle, dir);
+@@ -2029,7 +2029,7 @@
+ * recovery. */
+ inode->i_size = 0;
+ ext3_orphan_add(handle, inode);
+- inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
++ inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC;
+ ext3_mark_inode_dirty(handle, inode);
+ dir->i_nlink--;
+ ext3_update_dx_flag(dir);
+@@ -2079,7 +2079,7 @@
+ retval = ext3_delete_entry(handle, dir, de, bh);
+ if (retval)
+ goto end_unlink;
+- dir->i_ctime = dir->i_mtime = CURRENT_TIME;
++ dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC;
+ ext3_update_dx_flag(dir);
+ ext3_mark_inode_dirty(handle, dir);
+ inode->i_nlink--;
+@@ -2169,7 +2169,7 @@
+ if (IS_DIRSYNC(dir))
+ handle->h_sync = 1;
+
+- inode->i_ctime = CURRENT_TIME;
++ inode->i_ctime = CURRENT_TIME_SEC;
+ ext3_inc_count(handle, inode);
+ atomic_inc(&inode->i_count);
+
+@@ -2270,7 +2270,7 @@
+ * Like most other Unix systems, set the ctime for inodes on a
+ * rename.
+ */
+- old_inode->i_ctime = CURRENT_TIME;
++ old_inode->i_ctime = CURRENT_TIME_SEC;
+ ext3_mark_inode_dirty(handle, old_inode);
+
+ /*
+@@ -2303,9 +2303,9 @@
+
+ if (new_inode) {
+ new_inode->i_nlink--;
+- new_inode->i_ctime = CURRENT_TIME;
++ new_inode->i_ctime = CURRENT_TIME_SEC;
+ }
+- old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
++ old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME_SEC;
+ ext3_update_dx_flag(old_dir);
+ if (dir_bh) {
+ BUFFER_TRACE(dir_bh, "get_write_access");
+Index: linux-2.6.10/fs/ext3/super.c
+===================================================================
+--- linux-2.6.10.orig/fs/ext3/super.c 2005-04-06 09:38:35.000000000 -0600
++++ linux-2.6.10/fs/ext3/super.c 2006-01-03 16:16:52.000000000 -0700
+@@ -1318,7 +1318,7 @@
+ if (!parse_options ((char *) data, sb, &journal_inum, NULL, 0))
+ goto failed_mount;
+
+- sb->s_flags |= MS_ONE_SECOND;
++ set_sb_time_gran(sb, 1000000000U);
+ sb->s_flags = (sb->s_flags & ~MS_POSIXACL) |
+ ((sbi->s_mount_opt & EXT3_MOUNT_POSIX_ACL) ? MS_POSIXACL : 0);
+
+Index: linux-2.6.10/fs/ext3/xattr.c
+===================================================================
+--- linux-2.6.10.orig/fs/ext3/xattr.c 2005-04-06 09:38:35.000000000 -0600
++++ linux-2.6.10/fs/ext3/xattr.c 2006-01-03 16:16:52.000000000 -0700
+@@ -723,7 +723,7 @@
+
+ /* Update the inode. */
+ EXT3_I(inode)->i_file_acl = new_bh ? new_bh->b_blocknr : 0;
+- inode->i_ctime = CURRENT_TIME;
++ inode->i_ctime = CURRENT_TIME_SEC;
+ ext3_mark_inode_dirty(handle, inode);
+ if (IS_SYNC(inode))
+ handle->h_sync = 1;
+Index: linux-2.6.10/fs/inode.c
+===================================================================
+--- linux-2.6.10.orig/fs/inode.c 2006-01-03 15:33:21.000000000 -0700
++++ linux-2.6.10/fs/inode.c 2006-01-03 16:16:52.000000000 -0700
+@@ -1131,19 +1131,6 @@
+
+ EXPORT_SYMBOL(bmap);
+
+-/*
+- * Return true if the filesystem which backs this inode considers the two
+- * passed timespecs to be sufficiently different to warrant flushing the
+- * altered time out to disk.
+- */
+-static int inode_times_differ(struct inode *inode,
+- struct timespec *old, struct timespec *new)
+-{
+- if (IS_ONE_SECOND(inode))
+- return old->tv_sec != new->tv_sec;
+- return !timespec_equal(old, new);
+-}
+-
+ /**
+ * update_atime - update the access time
+ * @inode: inode accessed
+@@ -1163,8 +1150,8 @@
+ if (IS_RDONLY(inode))
+ return;
+
+- now = current_kernel_time();
+- if (inode_times_differ(inode, &inode->i_atime, &now)) {
++ now = current_fs_time(inode->i_sb);
++ if (!timespec_equal(&inode->i_atime, &now)) {
+ inode->i_atime = now;
+ mark_inode_dirty_sync(inode);
+ } else {
+@@ -1194,14 +1181,13 @@
+ if (IS_RDONLY(inode))
+ return;
+
+- now = current_kernel_time();
+-
+- if (inode_times_differ(inode, &inode->i_mtime, &now))
++ now = current_fs_time(inode->i_sb);
++ if (!timespec_equal(&inode->i_mtime, &now))
+ sync_it = 1;
+ inode->i_mtime = now;
+
+ if (ctime_too) {
+- if (inode_times_differ(inode, &inode->i_ctime, &now))
++ if (!timespec_equal(&inode->i_ctime, &now))
+ sync_it = 1;
+ inode->i_ctime = now;
+ }
+Index: linux-2.6.10/fs/locks.c
+===================================================================
+--- linux-2.6.10.orig/fs/locks.c 2004-12-24 14:35:28.000000000 -0700
++++ linux-2.6.10/fs/locks.c 2006-01-03 16:16:52.000000000 -0700
+@@ -1228,7 +1228,7 @@
+ {
+ struct file_lock *flock = inode->i_flock;
+ if (flock && IS_LEASE(flock) && (flock->fl_type & F_WRLCK))
+- *time = CURRENT_TIME;
++ *time = current_fs_time(inode->i_sb);
+ else
+ *time = inode->i_mtime;
+ }
+Index: linux-2.6.10/include/linux/fs.h
+===================================================================
+--- linux-2.6.10.orig/include/linux/fs.h 2006-01-03 16:04:26.000000000 -0700
++++ linux-2.6.10/include/linux/fs.h 2006-01-03 16:16:52.000000000 -0700
+@@ -124,7 +124,8 @@
+ #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_ONE_SECOND (1<<17) /* fs has 1 sec time resolution (obsolete) */
++#define MS_TIME_GRAN (1<<18) /* fs has s_time_gran field */
+ #define MS_ACTIVE (1<<30)
+ #define MS_NOUSER (1<<31)
+
+@@ -803,8 +804,33 @@
+ * 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 */
++#ifndef __GENKSYMS__
++ u32 s_time_gran;
++#endif
+ };
+
++extern struct timespec current_fs_time(struct super_block *sb);
++
++static inline u32 get_sb_time_gran(struct super_block *sb)
++{
++ if (sb->s_flags & MS_TIME_GRAN)
++ return sb->s_time_gran;
++ if (sb->s_flags & MS_ONE_SECOND)
++ return 1000000000U;
++ return 1;
++}
++
++static inline void set_sb_time_gran(struct super_block *sb, u32 time_gran)
++{
++ sb->s_time_gran = time_gran;
++ sb->s_flags |= MS_TIME_GRAN;
++ if (time_gran == 1000000000U)
++ sb->s_flags |= MS_ONE_SECOND;
++}
++
+ /*
+ * Snapshotting support.
+ */
+Index: linux-2.6.10/include/linux/time.h
+===================================================================
+--- linux-2.6.10.orig/include/linux/time.h 2004-12-24 14:35:00.000000000 -0700
++++ linux-2.6.10/include/linux/time.h 2006-01-03 16:16:52.000000000 -0700
+@@ -90,6 +90,7 @@
+ 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_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)
+ {
+Index: linux-2.6.10/kernel/time.c
+===================================================================
+--- linux-2.6.10.orig/kernel/time.c 2004-12-24 14:34:26.000000000 -0700
++++ linux-2.6.10/kernel/time.c 2006-01-03 16:16:52.000000000 -0700
+@@ -36,6 +36,7 @@
+
+ #include <asm/uaccess.h>
+ #include <asm/unistd.h>
++#include <linux/fs.h>
+
+ /*
+ * The timezone where the local system is located. Used as a default by some
+@@ -433,6 +434,50 @@
+
+ EXPORT_SYMBOL(current_kernel_time);
+
++/**
++ * current_fs_time - Return FS time
++ * @sb: Superblock.
++ *
++ * Return the current time truncated to the time granuality supported by
++ * the fs.
++ */
++struct timespec current_fs_time(struct super_block *sb)
++{
++ struct timespec now = current_kernel_time();
++ return timespec_trunc(now, get_sb_time_gran(sb));
++}
++EXPORT_SYMBOL(current_fs_time);
++
++/**
++ * timespec_trunc - Truncate timespec to a granuality
++ * @t: Timespec
++ * @gran: Granuality in ns.
++ *
++ * Truncate a timespec to a granuality. gran must be smaller than a second.
++ * Always rounds down.
++ *
++ * This function should be only used for timestamps returned by
++ * current_kernel_time() or CURRENT_TIME, not with do_gettimeofday() because
++ * it doesn't handle the better resolution of the later.
++ */
++struct timespec timespec_trunc(struct timespec t, unsigned gran)
++{
++ /*
++ * Division is pretty slow so avoid it for common cases.
++ * Currently current_kernel_time() never returns better than
++ * jiffies resolution. Exploit that.
++ */
++ if (gran <= jiffies_to_usecs(1) * 1000) {
++ /* nothing */
++ } else if (gran == 1000000000) {
++ t.tv_nsec = 0;
++ } else {
++ t.tv_nsec -= t.tv_nsec % gran;
++ }
++ return t;
++}
++EXPORT_SYMBOL(timespec_trunc);
++
+ #ifdef CONFIG_TIME_INTERPOLATION
+ void getnstimeofday (struct timespec *tv)
+ {