diff options
author | Steven Whitehouse <swhiteho@redhat.com> | 2006-11-30 18:14:32 +0300 |
---|---|---|
committer | Steven Whitehouse <swhiteho@redhat.com> | 2006-11-30 18:37:44 +0300 |
commit | 33c3de32872ef3c075e4dac04c0de8f86ac39f6f (patch) | |
tree | 32b8d14e4de17e78918ba8794c47781c1b069e2f /fs/gfs2/ops_file.c | |
parent | aac1a3c77a46c2d06f297641760dd740ac2a84af (diff) | |
download | linux-33c3de32872ef3c075e4dac04c0de8f86ac39f6f.tar.xz |
[GFS2] Don't flush everything on fdatasync
The gfs2_fsync() function was doing a journal flush on each
and every call. While this is correct, its also a lot of
overhead. This patch means that on fdatasync flushes we
rely on the VFS to flush the data for us and we don't do
a journal flush unless we really need to.
We have to do a journal flush for stuffed files though because
they have the data and the inode metadata in the same block.
Journaled files also need a journal flush too of course.
Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs/gfs2/ops_file.c')
-rw-r--r-- | fs/gfs2/ops_file.c | 30 |
1 files changed, 27 insertions, 3 deletions
diff --git a/fs/gfs2/ops_file.c b/fs/gfs2/ops_file.c index c2be216eb928..7bd971bf7cdd 100644 --- a/fs/gfs2/ops_file.c +++ b/fs/gfs2/ops_file.c @@ -22,6 +22,7 @@ #include <linux/ext2_fs.h> #include <linux/crc32.h> #include <linux/lm_interface.h> +#include <linux/writeback.h> #include <asm/uaccess.h> #include "gfs2.h" @@ -503,16 +504,39 @@ static int gfs2_close(struct inode *inode, struct file *file) * @file: the file that points to the dentry (we ignore this) * @dentry: the dentry that points to the inode to sync * + * The VFS will flush "normal" data for us. We only need to worry + * about metadata here. For journaled data, we just do a log flush + * as we can't avoid it. Otherwise we can just bale out if datasync + * is set. For stuffed inodes we must flush the log in order to + * ensure that all data is on disk. + * * Returns: errno */ static int gfs2_fsync(struct file *file, struct dentry *dentry, int datasync) { - struct gfs2_inode *ip = GFS2_I(dentry->d_inode); + struct inode *inode = dentry->d_inode; + int sync_state = inode->i_state & (I_DIRTY_SYNC|I_DIRTY_DATASYNC); + int ret = 0; + struct writeback_control wbc = { + .sync_mode = WB_SYNC_ALL, + .nr_to_write = 0, + }; + + if (gfs2_is_jdata(GFS2_I(inode))) { + gfs2_log_flush(GFS2_SB(inode), GFS2_I(inode)->i_gl); + return 0; + } - gfs2_log_flush(ip->i_gl->gl_sbd, ip->i_gl); + if (sync_state != 0) { + if (!datasync) + ret = sync_inode(inode, &wbc); - return 0; + if (gfs2_is_stuffed(GFS2_I(inode))) + gfs2_log_flush(GFS2_SB(inode), GFS2_I(inode)->i_gl); + } + + return ret; } /** |