GFS: write vfs inode attributes to disk
PATCH 1/1 GFS: write vfs inode attributes to disk
GFS wasn't ever updating mtime during mmaps to a file. This patch makes gfs_write_inode write the vfs inode attributes out to disk if it can, so that they get updated when the mmap data is written back to disk. Unfortunately, gfs_write_inode can only do this if it was called with the inode already exclusively locked, and not already in a transaction. The patch also makes sure that the updated vfs timestamps don't get overwritten by older gfs ones before they can be written out.
This patch is similar to my previous version, except that in now doesn't do it's own locking. This means it can only work when it happens to get called with the glock already held. This is necessary to preserve the correct locking order. The down side is that it does not write out the mtime in many of the cases where it should.
--- gfs-kernel/src/gfs/inode.c | 15 +++++++++------ gfs-kernel/src/gfs/ops_super.c | 31 +++++++++++++++++++++++++++++-- 2 files changed, 38 insertions(+), 8 deletions(-)
gfs-kernel/src/gfs/inode.c +9 -6
@@ -46,7 +46,7 @@*/ static void -inode_attr_in (struct gfs_inode *ip,struct inode *inode) +inode_attr_in (struct gfs_inode *ip,struct inode *inode,int force) {unsigned int mode;
@@ -93,9 +93,12 @@ inode_attr_in(struct gfs_inode *ip, struct inode *inode) inode->i_uid = ip->i_di.di_uid; inode->i_gid = ip->i_di.di_gid;i_size_write (inode, ip->i_di.di_size); - inode->i_atime.tv_sec = ip->i_di.di_atime; - inode->i_mtime.tv_sec = ip->i_di.di_mtime; - inode->i_ctime.tv_sec = ip->i_di.di_ctime; +if (force || ip->i_di.di_atime > inode->i_atime.tv_sec) + inode->i_atime.tv_sec = ip->i_di.di_atime; +if (force || ip->i_di.di_mtime > inode->i_mtime.tv_sec) + inode->i_mtime.tv_sec = ip->i_di.di_mtime; +if (force || ip->i_di.di_ctime > inode->i_ctime.tv_sec) + inode->i_ctime.tv_sec = ip->i_di.di_ctime; inode->i_atime.tv_nsec = inode->i_mtime.tv_nsec = inode->i_ctime.tv_nsec =0 ; inode->i_blocks = ip->i_di.di_blocks << (ip->i_sbd->sd_sb.sb_bsize_shift -GFS_BASIC_BLOCK_SHIFT );
@@ -125,7 +128,7 @@ gfs_inode_attr_in(struct gfs_inode *ip) inode =gfs_iget (ip,NO_CREATE );if (inode) { -inode_attr_in (ip, inode); +inode_attr_in (ip, inode,0 );iput (inode); }
@@ -185,7 +188,7 @@ gfs_iget(struct gfs_inode *ip, int create)if (!tmp)return NULL ; -inode_attr_in (ip, tmp); +inode_attr_in (ip, tmp,1 );/* Attach GFS-specific ops vectors */ if (ip->i_di.di_type ==GFS_FILE_REG ) {
gfs-kernel/src/gfs/ops_super.c +29 -2
@@ -39,6 +39,7 @@#include "super.h" #include "sys.h" #include "mount.h" +#include "trans.h" /** * gfs_write_inode - Make sure the inode is stable on the disk
@@ -51,14 +52,40 @@static int gfs_write_inode (struct inode *inode,int sync) { +int ret =0 ;struct gfs_inode *ip =get_v2ip (inode); +struct buffer_head *dibh; +struct gfs_holder i_gh; + +if (!ip) +return 0 ;atomic_inc (&ip->i_sbd->sd_ops_super); -if (ip && sync) +if (current->flags &PF_MEMALLOC || get_transaction || + !gfs_glock_is_locked_by_me (ip->i_gl) || !gfs_glock_is_held_excl (ip->i_gl)) + goto do_flush; +/* Trans may require: +one dinode block. */ + ret =gfs_trans_begin (ip->i_sbd,1 ,0 ); +if (ret) + goto do_flush; + + ret =gfs_get_inode_buffer (ip, &dibh); +if (ret ==0 ) { +gfs_inode_attr_out (ip); +gfs_trans_add_bh (ip->i_gl, dibh); +gfs_dinode_out (&ip->i_di, dibh->b_data); +brelse (dibh); + } + +gfs_trans_end (ip->i_sbd); + +do_flush: +if (sync)gfs_log_flush_glock (ip->i_gl,0 ); -return 0 ; +return ret; }/**
Signature · 1 line
1.8.3.1
PATCH 1/1 GFS: write vfs inode attributes to disk
Hi,
Yes, its not ideal, but it is a worthwhile step forward I think. ACK,
Steve.
Quoted 122 lines · Benjamin Marzinski
GFS wasn't ever updating mtime during mmaps to a file. This patch makes
gfs_write_inodewrite the vfs inode attributes out to disk if it can, so that they get updated when the mmap data is written back to disk. Unfortunately,gfs_write_inodecan only do this if it was called with the inode already exclusively locked, and not already in a transaction. The patch also makes sure that the updated vfs timestamps don't get overwritten by older gfs ones before they can be written out.This patch is similar to my previous version, except that in now doesn't do it's own locking. This means it can only work when it happens to get called with the glock already held. This is necessary to preserve the correct locking order. The down side is that it does not write out the mtime in many of the cases where it should.
Signed-off-by Benjamin Marzinski <[email protected]>--- gfs-kernel/src/gfs/inode.c | 15 +++++++++------ gfs-kernel/src/gfs/ops_super.c | 31 +++++++++++++++++++++++++++++-- 2 files changed, 38 insertions(+), 8 deletions(-)gfs-kernel/src/gfs/inode.c +9
-6@@ -46,7 +46,7 @@*/ static void -inode_attr_in (struct gfs_inode *ip,struct inode *inode) +inode_attr_in (struct gfs_inode *ip,struct inode *inode,int force) {unsigned int mode;@@ -93,9 +93,12 @@ inode_attr_in(struct gfs_inode *ip, struct inode *inode) inode->i_uid = ip->i_di.di_uid; inode->i_gid = ip->i_di.di_gid;i_size_write (inode, ip->i_di.di_size); - inode->i_atime.tv_sec = ip->i_di.di_atime; - inode->i_mtime.tv_sec = ip->i_di.di_mtime; - inode->i_ctime.tv_sec = ip->i_di.di_ctime; +if (force || ip->i_di.di_atime > inode->i_atime.tv_sec) + inode->i_atime.tv_sec = ip->i_di.di_atime; +if (force || ip->i_di.di_mtime > inode->i_mtime.tv_sec) + inode->i_mtime.tv_sec = ip->i_di.di_mtime; +if (force || ip->i_di.di_ctime > inode->i_ctime.tv_sec) + inode->i_ctime.tv_sec = ip->i_di.di_ctime; inode->i_atime.tv_nsec = inode->i_mtime.tv_nsec = inode->i_ctime.tv_nsec =0 ; inode->i_blocks = ip->i_di.di_blocks << (ip->i_sbd->sd_sb.sb_bsize_shift -GFS_BASIC_BLOCK_SHIFT );@@ -125,7 +128,7 @@ gfs_inode_attr_in(struct gfs_inode *ip) inode =gfs_iget (ip,NO_CREATE );if (inode) { -inode_attr_in (ip, inode); +inode_attr_in (ip, inode,0 );iput (inode); }@@ -185,7 +188,7 @@ gfs_iget(struct gfs_inode *ip, int create)if (!tmp)return NULL ; -inode_attr_in (ip, tmp); +inode_attr_in (ip, tmp,1 );/* Attach GFS-specific ops vectors */ if (ip->i_di.di_type ==GFS_FILE_REG ) {gfs-kernel/src/gfs/ops_super.c +29
-2@@ -39,6 +39,7 @@#include "super.h" #include "sys.h" #include "mount.h" +#include "trans.h" /** * gfs_write_inode - Make sure the inode is stable on the disk @@ -51,14 +52,40 @@static int gfs_write_inode (struct inode *inode,int sync) { +int ret =0 ;struct gfs_inode *ip =get_v2ip (inode); +struct buffer_head *dibh; +struct gfs_holder i_gh; + +if (!ip) +return 0 ;atomic_inc (&ip->i_sbd->sd_ops_super); -if (ip && sync) +if (current->flags &PF_MEMALLOC || get_transaction || + !gfs_glock_is_locked_by_me (ip->i_gl) || !gfs_glock_is_held_excl (ip->i_gl)) + goto do_flush; +/* Trans may require: +one dinode block. */ + ret =gfs_trans_begin (ip->i_sbd,1 ,0 ); +if (ret) + goto do_flush; + + ret =gfs_get_inode_buffer (ip, &dibh); +if (ret ==0 ) { +gfs_inode_attr_out (ip); +gfs_trans_add_bh (ip->i_gl, dibh); +gfs_dinode_out (&ip->i_di, dibh->b_data); +brelse (dibh); + } + +gfs_trans_end (ip->i_sbd); + +do_flush: +if (sync)gfs_log_flush_glock (ip->i_gl,0 ); -return 0 ; +return ret; }/**