Skip to content

Commit

Permalink
GFS2: dirty inode correctly in gfs2_write_end
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Benjamin Marzinski authored and Steven Whitehouse committed Sep 5, 2013
1 parent 1d12d17 commit 0c90180
Show file tree
Hide file tree
Showing 2 changed files with 10 additions and 3 deletions.
9 changes: 7 additions & 2 deletions fs/gfs2/aops.c
Original file line number Diff line number Diff line change
Expand Up @@ -815,6 +815,8 @@ static int gfs2_write_end(struct file *file, struct address_space *mapping,
unsigned int from = pos & (PAGE_CACHE_SIZE - 1);
unsigned int to = from + len;
int ret;
struct gfs2_trans *tr = current->journal_info;
BUG_ON(!tr);

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

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

gfs2_trans_add_meta(ip->i_gl, dibh);

if (gfs2_is_stuffed(ip))
return gfs2_stuffed_write_end(inode, dibh, pos, len, copied, page);

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

ret = generic_write_end(file, mapping, pos, len, copied, page, fsdata);
if (tr->tr_num_buf_new)
__mark_inode_dirty(inode, I_DIRTY_DATASYNC);
else
gfs2_trans_add_meta(ip->i_gl, dibh);


if (inode == sdp->sd_rindex) {
adjust_fs_space(inode);
Expand Down
4 changes: 3 additions & 1 deletion fs/gfs2/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -650,7 +650,7 @@ static int gfs2_fsync(struct file *file, loff_t start, loff_t end,
{
struct address_space *mapping = file->f_mapping;
struct inode *inode = mapping->host;
int sync_state = inode->i_state & (I_DIRTY_SYNC|I_DIRTY_DATASYNC);
int sync_state = inode->i_state & I_DIRTY;
struct gfs2_inode *ip = GFS2_I(inode);
int ret = 0, ret1 = 0;

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

if (!gfs2_is_jdata(ip))
sync_state &= ~I_DIRTY_PAGES;
if (datasync)
sync_state &= ~I_DIRTY_SYNC;

Expand Down

0 comments on commit 0c90180

Please sign in to comment.