Commit 0c9018097fe2966d80fe39e5c9ca94bb436ec369

Authored by Benjamin Marzinski
Committed by Steven Whitehouse
1 parent 1d12d175ea

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>

Showing 2 changed files with 10 additions and 3 deletions Side-by-side Diff

... ... @@ -815,6 +815,8 @@
815 815 unsigned int from = pos & (PAGE_CACHE_SIZE - 1);
816 816 unsigned int to = from + len;
817 817 int ret;
  818 + struct gfs2_trans *tr = current->journal_info;
  819 + BUG_ON(!tr);
818 820  
819 821 BUG_ON(gfs2_glock_is_locked_by_me(ip->i_gl) == NULL);
820 822  
... ... @@ -825,8 +827,6 @@
825 827 goto failed;
826 828 }
827 829  
828   - gfs2_trans_add_meta(ip->i_gl, dibh);
829   -
830 830 if (gfs2_is_stuffed(ip))
831 831 return gfs2_stuffed_write_end(inode, dibh, pos, len, copied, page);
832 832  
... ... @@ -834,6 +834,11 @@
834 834 gfs2_page_add_databufs(ip, page, from, to);
835 835  
836 836 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 +
837 842  
838 843 if (inode == sdp->sd_rindex) {
839 844 adjust_fs_space(inode);
... ... @@ -650,7 +650,7 @@
650 650 {
651 651 struct address_space *mapping = file->f_mapping;
652 652 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;
654 654 struct gfs2_inode *ip = GFS2_I(inode);
655 655 int ret = 0, ret1 = 0;
656 656  
... ... @@ -660,6 +660,8 @@
660 660 return ret1;
661 661 }
662 662  
  663 + if (!gfs2_is_jdata(ip))
  664 + sync_state &= ~I_DIRTY_PAGES;
663 665 if (datasync)
664 666 sync_state &= ~I_DIRTY_SYNC;
665 667