Commit 0c9018097fe2966d80fe39e5c9ca94bb436ec369
Committed by
Steven Whitehouse
1 parent
1d12d175ea
Exists in
smarc-imx_3.14.28_1.0.0_ga
and in
1 other branch
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
fs/gfs2/aops.c
... | ... | @@ -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); |
fs/gfs2/file.c
... | ... | @@ -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 |