nilfs2: support nanosecond timestamp
authorRyusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>
Tue, 7 Apr 2009 02:02:00 +0000 (19:02 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 7 Apr 2009 15:31:20 +0000 (08:31 -0700)
After a review of user's feedback for finding out other compatibility
issues, I found nilfs improperly initializes timestamps in inode;
CURRENT_TIME was used there instead of CURRENT_TIME_SEC even though nilfs
didn't have nanosecond timestamps on disk.  A few users gave us the report
that the tar program sometimes failed to expand symbolic links on nilfs,
and it turned out to be the cause.

Instead of applying the above displacement, I've decided to support
nanosecond timestamps on this occation.  Fortunetaly, a needless 64-bit
field was in the nilfs_inode struct, and I found it's available for this
purpose without impact for the users.

So, this will do the enhancement and resolve the tar problem.

Signed-off-by: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
fs/nilfs2/gcinode.c
fs/nilfs2/inode.c
fs/nilfs2/nilfs.h
fs/nilfs2/super.c
include/linux/nilfs2_fs.h

index 77615aabc7e20722a2c1cc43814da387a2bd650a..19d2102b6a69ee09fa0d7b7a819b96e31c51e903 100644 (file)
@@ -226,7 +226,6 @@ static struct inode *alloc_gcinode(struct the_nilfs *nilfs, ino_t ino,
        ii->i_flags = 0;
        ii->i_state = 1 << NILFS_I_GCINODE;
        ii->i_bh = NULL;
-       ii->i_dtime = 0;
        nilfs_bmap_init_gc(ii->i_bmap);
 
        return inode;
index a1922b17662c5ae52eb1b865e3a9f73c8946b2e4..49ab4a49bb4faa121e2a7e03f6869ae79841b201 100644 (file)
@@ -306,7 +306,6 @@ struct inode *nilfs_new_inode(struct inode *dir, int mode)
 
        /* ii->i_file_acl = 0; */
        /* ii->i_dir_acl = 0; */
-       ii->i_dtime = 0;
        ii->i_dir_start_lookup = 0;
 #ifdef CONFIG_NILFS_FS_POSIX_ACL
        ii->i_acl = NULL;
@@ -390,11 +389,10 @@ int nilfs_read_inode_common(struct inode *inode,
        inode->i_atime.tv_sec = le64_to_cpu(raw_inode->i_mtime);
        inode->i_ctime.tv_sec = le64_to_cpu(raw_inode->i_ctime);
        inode->i_mtime.tv_sec = le64_to_cpu(raw_inode->i_mtime);
-       inode->i_atime.tv_nsec = 0;
-       inode->i_ctime.tv_nsec = 0;
-       inode->i_mtime.tv_nsec = 0;
-       ii->i_dtime = le64_to_cpu(raw_inode->i_dtime);
-       if (inode->i_nlink == 0 && (inode->i_mode == 0 || ii->i_dtime))
+       inode->i_atime.tv_nsec = le32_to_cpu(raw_inode->i_mtime_nsec);
+       inode->i_ctime.tv_nsec = le32_to_cpu(raw_inode->i_ctime_nsec);
+       inode->i_mtime.tv_nsec = le32_to_cpu(raw_inode->i_mtime_nsec);
+       if (inode->i_nlink == 0 && inode->i_mode == 0)
                return -EINVAL; /* this inode is deleted */
 
        inode->i_blocks = le64_to_cpu(raw_inode->i_blocks);
@@ -505,9 +503,10 @@ void nilfs_write_inode_common(struct inode *inode,
        raw_inode->i_size = cpu_to_le64(inode->i_size);
        raw_inode->i_ctime = cpu_to_le64(inode->i_ctime.tv_sec);
        raw_inode->i_mtime = cpu_to_le64(inode->i_mtime.tv_sec);
+       raw_inode->i_ctime_nsec = cpu_to_le32(inode->i_ctime.tv_nsec);
+       raw_inode->i_mtime_nsec = cpu_to_le32(inode->i_mtime.tv_nsec);
        raw_inode->i_blocks = cpu_to_le64(inode->i_blocks);
 
-       raw_inode->i_dtime = cpu_to_le64(ii->i_dtime);
        raw_inode->i_flags = cpu_to_le32(ii->i_flags);
        raw_inode->i_generation = cpu_to_le32(inode->i_generation);
 
index 19af5ab862751a7ff7860416427f1355adba49b2..7558c977db02655a6158ddd64e4094d9abbbeead 100644 (file)
@@ -48,7 +48,6 @@ struct nilfs_inode_info {
        struct nilfs_bmap *i_bmap;
        union nilfs_bmap_union i_bmap_union;
        __u64 i_xattr;  /* sector_t ??? */
-       __u32 i_dtime;
        __u32 i_dir_start_lookup;
        __u64 i_cno;            /* check point number for GC inode */
        struct address_space i_btnode_cache;
index e2ced824c6243492737a37764b5b22d64fac67e0..e117e1ea9bffc641fe53ad4d09d570e1d8f0b4a9 100644 (file)
@@ -792,6 +792,7 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent,
        sb->s_op = &nilfs_sops;
        sb->s_export_op = &nilfs_export_ops;
        sb->s_root = NULL;
+       sb->s_time_gran = 1;
 
        if (!nilfs_loaded(nilfs)) {
                err = load_nilfs(nilfs, sbi);
index 1275b3099535896c1ee3cba6e92726fe440a7a8e..79fec6af3f9f805800d7bfdce69bc15301215dc2 100644 (file)
  * struct nilfs_inode - structure of an inode on disk
  * @i_blocks: blocks count
  * @i_size: size in bytes
- * @i_ctime: creation time
- * @i_mtime: modification time
- * @i_dtime: deletion time
+ * @i_ctime: creation time (seconds)
+ * @i_mtime: modification time (seconds)
+ * @i_ctime_nsec: creation time (nano seconds)
+ * @i_mtime_nsec: modification time (nano seconds)
  * @i_uid: user id
  * @i_gid: group id
  * @i_mode: file mode
@@ -85,7 +86,8 @@ struct nilfs_inode {
        __le64  i_size;
        __le64  i_ctime;
        __le64  i_mtime;
-       __le64  i_dtime;
+       __le32  i_ctime_nsec;
+       __le32  i_mtime_nsec;
        __le32  i_uid;
        __le32  i_gid;
        __le16  i_mode;