]> Pileus Git - ~andy/linux/commitdiff
[GFS2] Add nanosecond timestamp feature
authorSteven Whitehouse <swhiteho@redhat.com>
Tue, 5 Jun 2007 08:39:18 +0000 (09:39 +0100)
committerSteven Whitehouse <swhiteho@redhat.com>
Mon, 9 Jul 2007 07:23:12 +0000 (08:23 +0100)
This adds a nanosecond timestamp feature to the GFS2 filesystem. Due
to the way that the on-disk format works, older filesystems will just
appear to have this field set to zero. When mounted by an older version
of GFS2, the filesystem will simply ignore the extra fields so that
it will again appear to have whole second resolution, so that its
trivially backward compatible.

Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
fs/gfs2/bmap.c
fs/gfs2/dir.c
fs/gfs2/eattr.c
fs/gfs2/inode.c
fs/gfs2/ops_fstype.c
fs/gfs2/ops_inode.c
include/linux/gfs2_ondisk.h

index b784cf3c6482e46bd54ee09144e2af87f2215657..d16044cb023adfa8480852ec61df7d89b5310fd0 100644 (file)
@@ -772,7 +772,7 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh,
                        gfs2_free_data(ip, bstart, blen);
        }
 
-       ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC;
+       ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
 
        gfs2_dinode_out(ip, dibh->b_data);
 
@@ -847,7 +847,7 @@ static int do_grow(struct gfs2_inode *ip, u64 size)
        }
 
        ip->i_di.di_size = size;
-       ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC;
+       ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
 
        error = gfs2_meta_inode_buffer(ip, &dibh);
        if (error)
@@ -958,7 +958,7 @@ static int trunc_start(struct gfs2_inode *ip, u64 size)
 
        if (gfs2_is_stuffed(ip)) {
                ip->i_di.di_size = size;
-               ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC;
+               ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
                gfs2_trans_add_bh(ip->i_gl, dibh, 1);
                gfs2_dinode_out(ip, dibh->b_data);
                gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode) + size);
@@ -970,7 +970,7 @@ static int trunc_start(struct gfs2_inode *ip, u64 size)
 
                if (!error) {
                        ip->i_di.di_size = size;
-                       ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC;
+                       ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
                        ip->i_di.di_flags |= GFS2_DIF_TRUNC_IN_PROG;
                        gfs2_trans_add_bh(ip->i_gl, dibh, 1);
                        gfs2_dinode_out(ip, dibh->b_data);
@@ -1043,7 +1043,7 @@ static int trunc_end(struct gfs2_inode *ip)
                        ip->i_no_addr;
                gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode));
        }
-       ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC;
+       ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
        ip->i_di.di_flags &= ~GFS2_DIF_TRUNC_IN_PROG;
 
        gfs2_trans_add_bh(ip->i_gl, dibh, 1);
index 2f154049b59deabf2998c95af6cad83f42a4af5a..f793e31a050ec3936bd493b613a34d94f66b0f11 100644 (file)
@@ -130,7 +130,7 @@ static int gfs2_dir_write_stuffed(struct gfs2_inode *ip, const char *buf,
        memcpy(dibh->b_data + offset + sizeof(struct gfs2_dinode), buf, size);
        if (ip->i_di.di_size < offset + size)
                ip->i_di.di_size = offset + size;
-       ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC;
+       ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
        gfs2_dinode_out(ip, dibh->b_data);
 
        brelse(dibh);
@@ -228,7 +228,7 @@ out:
 
        if (ip->i_di.di_size < offset + copied)
                ip->i_di.di_size = offset + copied;
-       ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC;
+       ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
 
        gfs2_trans_add_bh(ip->i_gl, dibh, 1);
        gfs2_dinode_out(ip, dibh->b_data);
@@ -1622,7 +1622,7 @@ int gfs2_dir_add(struct inode *inode, const struct qstr *name,
                                break;
                        gfs2_trans_add_bh(ip->i_gl, bh, 1);
                        ip->i_di.di_entries++;
-                       ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME_SEC;
+                       ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
                        gfs2_dinode_out(ip, bh->b_data);
                        brelse(bh);
                        error = 0;
@@ -1708,7 +1708,7 @@ int gfs2_dir_del(struct gfs2_inode *dip, const struct qstr *name)
                gfs2_consist_inode(dip);
        gfs2_trans_add_bh(dip->i_gl, bh, 1);
        dip->i_di.di_entries--;
-       dip->i_inode.i_mtime = dip->i_inode.i_ctime = CURRENT_TIME_SEC;
+       dip->i_inode.i_mtime = dip->i_inode.i_ctime = CURRENT_TIME;
        gfs2_dinode_out(dip, bh->b_data);
        brelse(bh);
        mark_inode_dirty(&dip->i_inode);
@@ -1756,7 +1756,7 @@ int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename,
                gfs2_trans_add_bh(dip->i_gl, bh, 1);
        }
 
-       dip->i_inode.i_mtime = dip->i_inode.i_ctime = CURRENT_TIME_SEC;
+       dip->i_inode.i_mtime = dip->i_inode.i_ctime = CURRENT_TIME;
        gfs2_dinode_out(dip, bh->b_data);
        brelse(bh);
        return 0;
index 40e1d37112e6c8c5d5da4638e3929a6ee09ec7c0..2a7435b5c4dc54442fd464d2053742bea923a56d 100644 (file)
@@ -300,7 +300,7 @@ static int ea_dealloc_unstuffed(struct gfs2_inode *ip, struct buffer_head *bh,
 
        error = gfs2_meta_inode_buffer(ip, &dibh);
        if (!error) {
-               ip->i_inode.i_ctime = CURRENT_TIME_SEC;
+               ip->i_inode.i_ctime = CURRENT_TIME;
                gfs2_trans_add_bh(ip->i_gl, dibh, 1);
                gfs2_dinode_out(ip, dibh->b_data);
                brelse(dibh);
@@ -717,7 +717,7 @@ static int ea_alloc_skeleton(struct gfs2_inode *ip, struct gfs2_ea_request *er,
                                            (er->er_mode & S_IFMT));
                        ip->i_inode.i_mode = er->er_mode;
                }
-               ip->i_inode.i_ctime = CURRENT_TIME_SEC;
+               ip->i_inode.i_ctime = CURRENT_TIME;
                gfs2_trans_add_bh(ip->i_gl, dibh, 1);
                gfs2_dinode_out(ip, dibh->b_data);
                brelse(dibh);
@@ -852,7 +852,7 @@ static int ea_set_simple_noalloc(struct gfs2_inode *ip, struct buffer_head *bh,
                        (ip->i_inode.i_mode & S_IFMT) == (er->er_mode & S_IFMT));
                ip->i_inode.i_mode = er->er_mode;
        }
-       ip->i_inode.i_ctime = CURRENT_TIME_SEC;
+       ip->i_inode.i_ctime = CURRENT_TIME;
        gfs2_trans_add_bh(ip->i_gl, dibh, 1);
        gfs2_dinode_out(ip, dibh->b_data);
        brelse(dibh);
@@ -1133,7 +1133,7 @@ static int ea_remove_stuffed(struct gfs2_inode *ip, struct gfs2_ea_location *el)
 
        error = gfs2_meta_inode_buffer(ip, &dibh);
        if (!error) {
-               ip->i_inode.i_ctime = CURRENT_TIME_SEC;
+               ip->i_inode.i_ctime = CURRENT_TIME;
                gfs2_trans_add_bh(ip->i_gl, dibh, 1);
                gfs2_dinode_out(ip, dibh->b_data);
                brelse(dibh);
index a31a4b80ba3c004ac696eba4f86fd7154c628fdf..3ef0f051d076ba491c27d90a36bc22cf6c2f3b74 100644 (file)
@@ -178,11 +178,11 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf)
        di->di_blocks = be64_to_cpu(str->di_blocks);
        gfs2_set_inode_blocks(&ip->i_inode);
        ip->i_inode.i_atime.tv_sec = be64_to_cpu(str->di_atime);
-       ip->i_inode.i_atime.tv_nsec = 0;
+       ip->i_inode.i_atime.tv_nsec = be32_to_cpu(str->di_atime_nsec);
        ip->i_inode.i_mtime.tv_sec = be64_to_cpu(str->di_mtime);
-       ip->i_inode.i_mtime.tv_nsec = 0;
+       ip->i_inode.i_mtime.tv_nsec = be32_to_cpu(str->di_mtime_nsec);
        ip->i_inode.i_ctime.tv_sec = be64_to_cpu(str->di_ctime);
-       ip->i_inode.i_ctime.tv_nsec = 0;
+       ip->i_inode.i_ctime.tv_nsec = be32_to_cpu(str->di_ctime_nsec);
 
        di->di_goal_meta = be64_to_cpu(str->di_goal_meta);
        di->di_goal_data = be64_to_cpu(str->di_goal_data);
@@ -317,7 +317,7 @@ int gfs2_change_nlink(struct gfs2_inode *ip, int diff)
        else
                drop_nlink(&ip->i_inode);
 
-       ip->i_inode.i_ctime = CURRENT_TIME_SEC;
+       ip->i_inode.i_ctime = CURRENT_TIME;
 
        gfs2_trans_add_bh(ip->i_gl, dibh, 1);
        gfs2_dinode_out(ip, dibh->b_data);
@@ -648,6 +648,7 @@ static void init_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl,
        struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
        struct gfs2_dinode *di;
        struct buffer_head *dibh;
+       struct timespec tv = CURRENT_TIME;
 
        dibh = gfs2_meta_new(gl, inum->no_addr);
        gfs2_trans_add_bh(gl, dibh, 1);
@@ -663,7 +664,7 @@ static void init_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl,
        di->di_nlink = 0;
        di->di_size = 0;
        di->di_blocks = cpu_to_be64(1);
-       di->di_atime = di->di_mtime = di->di_ctime = cpu_to_be64(get_seconds());
+       di->di_atime = di->di_mtime = di->di_ctime = cpu_to_be64(tv.tv_sec);
        di->di_major = cpu_to_be32(MAJOR(dev));
        di->di_minor = cpu_to_be32(MINOR(dev));
        di->di_goal_meta = di->di_goal_data = cpu_to_be64(inum->no_addr);
@@ -693,6 +694,9 @@ static void init_dinode(struct gfs2_inode *dip, struct gfs2_glock *gl,
        di->di_entries = 0;
        memset(&di->__pad4, 0, sizeof(di->__pad4));
        di->di_eattr = 0;
+       di->di_atime_nsec = cpu_to_be32(tv.tv_nsec);
+       di->di_mtime_nsec = cpu_to_be32(tv.tv_nsec);
+       di->di_ctime_nsec = cpu_to_be32(tv.tv_nsec);
        memset(&di->di_reserved, 0, sizeof(di->di_reserved));
 
        brelse(dibh);
@@ -1135,10 +1139,11 @@ int gfs2_glock_nq_atime(struct gfs2_holder *gh)
        struct gfs2_glock *gl = gh->gh_gl;
        struct gfs2_sbd *sdp = gl->gl_sbd;
        struct gfs2_inode *ip = gl->gl_object;
-       s64 curtime, quantum = gfs2_tune_get(sdp, gt_atime_quantum);
+       s64 quantum = gfs2_tune_get(sdp, gt_atime_quantum);
        unsigned int state;
        int flags;
        int error;
+       struct timespec tv = CURRENT_TIME;
 
        if (gfs2_assert_warn(sdp, gh->gh_flags & GL_ATIME) ||
            gfs2_assert_warn(sdp, !(gh->gh_flags & GL_ASYNC)) ||
@@ -1156,8 +1161,7 @@ int gfs2_glock_nq_atime(struct gfs2_holder *gh)
            (sdp->sd_vfs->s_flags & MS_RDONLY))
                return 0;
 
-       curtime = get_seconds();
-       if (curtime - ip->i_inode.i_atime.tv_sec >= quantum) {
+       if (tv.tv_sec - ip->i_inode.i_atime.tv_sec >= quantum) {
                gfs2_glock_dq(gh);
                gfs2_holder_reinit(LM_ST_EXCLUSIVE, gh->gh_flags & ~LM_FLAG_ANY,
                                   gh);
@@ -1168,8 +1172,8 @@ int gfs2_glock_nq_atime(struct gfs2_holder *gh)
                /* Verify that atime hasn't been updated while we were
                   trying to get exclusive lock. */
 
-               curtime = get_seconds();
-               if (curtime - ip->i_inode.i_atime.tv_sec >= quantum) {
+               tv = CURRENT_TIME;
+               if (tv.tv_sec - ip->i_inode.i_atime.tv_sec >= quantum) {
                        struct buffer_head *dibh;
                        struct gfs2_dinode *di;
 
@@ -1183,11 +1187,12 @@ int gfs2_glock_nq_atime(struct gfs2_holder *gh)
                        if (error)
                                goto fail_end_trans;
 
-                       ip->i_inode.i_atime.tv_sec = curtime;
+                       ip->i_inode.i_atime = tv;
 
                        gfs2_trans_add_bh(ip->i_gl, dibh, 1);
                        di = (struct gfs2_dinode *)dibh->b_data;
                        di->di_atime = cpu_to_be64(ip->i_inode.i_atime.tv_sec);
+                       di->di_atime_nsec = cpu_to_be32(ip->i_inode.i_atime.tv_nsec);
                        brelse(dibh);
 
                        gfs2_trans_end(sdp);
@@ -1290,6 +1295,9 @@ void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf)
        str->di_entries = cpu_to_be32(di->di_entries);
 
        str->di_eattr = cpu_to_be64(di->di_eattr);
+       str->di_atime_nsec = cpu_to_be32(ip->i_inode.i_atime.tv_nsec);
+       str->di_mtime_nsec = cpu_to_be32(ip->i_inode.i_mtime.tv_nsec);
+       str->di_ctime_nsec = cpu_to_be32(ip->i_inode.i_ctime.tv_nsec);
 }
 
 void gfs2_dinode_print(const struct gfs2_inode *ip)
index 0443e255173dd2fa1de9d170eb1b6608cc4e5d1e..b46727275e585f50ee291b47b9880258bfcabe59 100644 (file)
@@ -104,6 +104,7 @@ static void init_vfs(struct super_block *sb, unsigned noatime)
        sb->s_magic = GFS2_MAGIC;
        sb->s_op = &gfs2_super_ops;
        sb->s_export_op = &gfs2_export_ops;
+       sb->s_time_gran = 1;
        sb->s_maxbytes = MAX_LFS_FILESIZE;
 
        if (sb->s_flags & (MS_NOATIME | MS_NODIRATIME))
index 919a661e4f79f5190696cbff4a8e1e9e5edc62af..9cc07f442ef56ee69babae78cb843d94b1e96d15 100644 (file)
@@ -757,7 +757,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry,
                error = gfs2_meta_inode_buffer(ip, &dibh);
                if (error)
                        goto out_end_trans;
-               ip->i_inode.i_ctime = CURRENT_TIME_SEC;
+               ip->i_inode.i_ctime = CURRENT_TIME;
                gfs2_trans_add_bh(ip->i_gl, dibh, 1);
                gfs2_dinode_out(ip, dibh->b_data);
                brelse(dibh);
index 2c4e24fb076505d08d0b763f3f3f3c023da588b7..a44a6a078f0a68b487ff6d049c71b6ceea154a05 100644 (file)
@@ -259,8 +259,11 @@ struct gfs2_dinode {
        struct gfs2_inum __pad4; /* Unused even in current gfs1 */
 
        __be64 di_eattr;        /* extended attribute block number */
+       __be32 di_atime_nsec;   /* nsec portion of atime */
+       __be32 di_mtime_nsec;   /* nsec portion of mtime */
+       __be32 di_ctime_nsec;   /* nsec portion of ctime */
 
-       __u8 di_reserved[56];
+       __u8 di_reserved[44];
 };
 
 /*