Skip to content

Commit 0c90180

Browse files
bmarzinsswhiteho
authored andcommitted
GFS2: dirty inode correctly in gfs2_write_end
GFS2 was only setting I_DIRTY_DATASYNC on files that it wrote to, when it actually increased the file size. If gfs2_fsync was called without I_DIRTY_DATASYNC set, it didn't flush the incore data to the log before returning, so any metadata or journaled data changes were not getting fsynced. This meant that writes to the middle of files were not always getting fsynced properly. This patch makes gfs2 set I_DIRTY_DATASYNC whenever metadata has been updated during a write. It also make gfs2_sync flush the incore log if I_DIRTY_PAGES is set, and the file is using data journalling. This will make sure that all incore logged data gets written to disk before returning from a fsync. Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com> Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
1 parent 1d12d17 commit 0c90180

File tree

2 files changed

+10
-3
lines changed

2 files changed

+10
-3
lines changed

fs/gfs2/aops.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -815,6 +815,8 @@ static int gfs2_write_end(struct file *file, struct address_space *mapping,
815815
unsigned int from = pos & (PAGE_CACHE_SIZE - 1);
816816
unsigned int to = from + len;
817817
int ret;
818+
struct gfs2_trans *tr = current->journal_info;
819+
BUG_ON(!tr);
818820

819821
BUG_ON(gfs2_glock_is_locked_by_me(ip->i_gl) == NULL);
820822

@@ -825,15 +827,18 @@ static int gfs2_write_end(struct file *file, struct address_space *mapping,
825827
goto failed;
826828
}
827829

828-
gfs2_trans_add_meta(ip->i_gl, dibh);
829-
830830
if (gfs2_is_stuffed(ip))
831831
return gfs2_stuffed_write_end(inode, dibh, pos, len, copied, page);
832832

833833
if (!gfs2_is_writeback(ip))
834834
gfs2_page_add_databufs(ip, page, from, to);
835835

836836
ret = generic_write_end(file, mapping, pos, len, copied, page, fsdata);
837+
if (tr->tr_num_buf_new)
838+
__mark_inode_dirty(inode, I_DIRTY_DATASYNC);
839+
else
840+
gfs2_trans_add_meta(ip->i_gl, dibh);
841+
837842

838843
if (inode == sdp->sd_rindex) {
839844
adjust_fs_space(inode);

fs/gfs2/file.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -650,7 +650,7 @@ static int gfs2_fsync(struct file *file, loff_t start, loff_t end,
650650
{
651651
struct address_space *mapping = file->f_mapping;
652652
struct inode *inode = mapping->host;
653-
int sync_state = inode->i_state & (I_DIRTY_SYNC|I_DIRTY_DATASYNC);
653+
int sync_state = inode->i_state & I_DIRTY;
654654
struct gfs2_inode *ip = GFS2_I(inode);
655655
int ret = 0, ret1 = 0;
656656

@@ -660,6 +660,8 @@ static int gfs2_fsync(struct file *file, loff_t start, loff_t end,
660660
return ret1;
661661
}
662662

663+
if (!gfs2_is_jdata(ip))
664+
sync_state &= ~I_DIRTY_PAGES;
663665
if (datasync)
664666
sync_state &= ~I_DIRTY_SYNC;
665667

0 commit comments

Comments
 (0)