aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Marzinski <bmarzins@redhat.com>2013-09-03 17:59:42 -0400
committerSteven Whitehouse <swhiteho@redhat.com>2013-09-05 04:04:24 -0400
commit0c9018097fe2966d80fe39e5c9ca94bb436ec369 (patch)
treea3a30053c83e22f30e3e7d3fc595ea68fbdc7afa
parent1d12d175ea3b56fdf2573bf6f168cce8f39b19e3 (diff)
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>
-rw-r--r--fs/gfs2/aops.c9
-rw-r--r--fs/gfs2/file.c4
2 files changed, 10 insertions, 3 deletions
diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c
index a9ea6f07774b..1f7d8057ea68 100644
--- a/fs/gfs2/aops.c
+++ b/fs/gfs2/aops.c
@@ -815,6 +815,8 @@ static int gfs2_write_end(struct file *file, struct address_space *mapping,
815 unsigned int from = pos & (PAGE_CACHE_SIZE - 1); 815 unsigned int from = pos & (PAGE_CACHE_SIZE - 1);
816 unsigned int to = from + len; 816 unsigned int to = from + len;
817 int ret; 817 int ret;
818 struct gfs2_trans *tr = current->journal_info;
819 BUG_ON(!tr);
818 820
819 BUG_ON(gfs2_glock_is_locked_by_me(ip->i_gl) == NULL); 821 BUG_ON(gfs2_glock_is_locked_by_me(ip->i_gl) == NULL);
820 822
@@ -825,8 +827,6 @@ static int gfs2_write_end(struct file *file, struct address_space *mapping,
825 goto failed; 827 goto failed;
826 } 828 }
827 829
828 gfs2_trans_add_meta(ip->i_gl, dibh);
829
830 if (gfs2_is_stuffed(ip)) 830 if (gfs2_is_stuffed(ip))
831 return gfs2_stuffed_write_end(inode, dibh, pos, len, copied, page); 831 return gfs2_stuffed_write_end(inode, dibh, pos, len, copied, page);
832 832
@@ -834,6 +834,11 @@ static int gfs2_write_end(struct file *file, struct address_space *mapping,
834 gfs2_page_add_databufs(ip, page, from, to); 834 gfs2_page_add_databufs(ip, page, from, to);
835 835
836 ret = generic_write_end(file, mapping, pos, len, copied, page, fsdata); 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 if (inode == sdp->sd_rindex) { 843 if (inode == sdp->sd_rindex) {
839 adjust_fs_space(inode); 844 adjust_fs_space(inode);
diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c
index 72c3866a7320..0621b46d474d 100644
--- a/fs/gfs2/file.c
+++ b/fs/gfs2/file.c
@@ -650,7 +650,7 @@ static int gfs2_fsync(struct file *file, loff_t start, loff_t end,
650{ 650{
651 struct address_space *mapping = file->f_mapping; 651 struct address_space *mapping = file->f_mapping;
652 struct inode *inode = mapping->host; 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 struct gfs2_inode *ip = GFS2_I(inode); 654 struct gfs2_inode *ip = GFS2_I(inode);
655 int ret = 0, ret1 = 0; 655 int ret = 0, ret1 = 0;
656 656
@@ -660,6 +660,8 @@ static int gfs2_fsync(struct file *file, loff_t start, loff_t end,
660 return ret1; 660 return ret1;
661 } 661 }
662 662
663 if (!gfs2_is_jdata(ip))
664 sync_state &= ~I_DIRTY_PAGES;
663 if (datasync) 665 if (datasync)
664 sync_state &= ~I_DIRTY_SYNC; 666 sync_state &= ~I_DIRTY_SYNC;
665 667