aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/gfs2/file.c8
-rw-r--r--fs/gfs2/glops.c32
-rw-r--r--fs/gfs2/glops.h2
-rw-r--r--fs/gfs2/super.c2
4 files changed, 20 insertions, 24 deletions
diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c
index 3467f3662149..3b65f67bb38e 100644
--- a/fs/gfs2/file.c
+++ b/fs/gfs2/file.c
@@ -593,16 +593,12 @@ static int gfs2_fsync(struct file *file, loff_t start, loff_t end,
593 sync_state &= ~I_DIRTY_SYNC; 593 sync_state &= ~I_DIRTY_SYNC;
594 594
595 if (sync_state) { 595 if (sync_state) {
596 mutex_lock(&inode->i_mutex);
597 ret = sync_inode_metadata(inode, 1); 596 ret = sync_inode_metadata(inode, 1);
598 if (ret) { 597 if (ret)
599 mutex_unlock(&inode->i_mutex);
600 return ret; 598 return ret;
601 }
602 if (gfs2_is_jdata(ip)) 599 if (gfs2_is_jdata(ip))
603 filemap_write_and_wait(mapping); 600 filemap_write_and_wait(mapping);
604 gfs2_ail_flush(ip->i_gl); 601 gfs2_ail_flush(ip->i_gl, 1);
605 mutex_unlock(&inode->i_mutex);
606 } 602 }
607 603
608 if (mapping->nrpages) 604 if (mapping->nrpages)
diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c
index 951541b6234c..78418b4fa857 100644
--- a/fs/gfs2/glops.c
+++ b/fs/gfs2/glops.c
@@ -42,41 +42,41 @@ static void gfs2_ail_error(struct gfs2_glock *gl, const struct buffer_head *bh)
42/** 42/**
43 * __gfs2_ail_flush - remove all buffers for a given lock from the AIL 43 * __gfs2_ail_flush - remove all buffers for a given lock from the AIL
44 * @gl: the glock 44 * @gl: the glock
45 * @fsync: set when called from fsync (not all buffers will be clean)
45 * 46 *
46 * None of the buffers should be dirty, locked, or pinned. 47 * None of the buffers should be dirty, locked, or pinned.
47 */ 48 */
48 49
49static void __gfs2_ail_flush(struct gfs2_glock *gl, unsigned long b_state) 50static void __gfs2_ail_flush(struct gfs2_glock *gl, bool fsync)
50{ 51{
51 struct gfs2_sbd *sdp = gl->gl_sbd; 52 struct gfs2_sbd *sdp = gl->gl_sbd;
52 struct list_head *head = &gl->gl_ail_list; 53 struct list_head *head = &gl->gl_ail_list;
53 struct gfs2_bufdata *bd; 54 struct gfs2_bufdata *bd, *tmp;
54 struct buffer_head *bh; 55 struct buffer_head *bh;
56 const unsigned long b_state = (1UL << BH_Dirty)|(1UL << BH_Pinned)|(1UL << BH_Lock);
55 sector_t blocknr; 57 sector_t blocknr;
56 58
59 gfs2_log_lock(sdp);
57 spin_lock(&sdp->sd_ail_lock); 60 spin_lock(&sdp->sd_ail_lock);
58 while (!list_empty(head)) { 61 list_for_each_entry_safe(bd, tmp, head, bd_ail_gl_list) {
59 bd = list_entry(head->next, struct gfs2_bufdata,
60 bd_ail_gl_list);
61 bh = bd->bd_bh; 62 bh = bd->bd_bh;
62 blocknr = bh->b_blocknr; 63 if (bh->b_state & b_state) {
63 if (bh->b_state & b_state) 64 if (fsync)
65 continue;
64 gfs2_ail_error(gl, bh); 66 gfs2_ail_error(gl, bh);
67 }
68 blocknr = bh->b_blocknr;
65 bh->b_private = NULL; 69 bh->b_private = NULL;
66 gfs2_remove_from_ail(bd); /* drops ref on bh */ 70 gfs2_remove_from_ail(bd); /* drops ref on bh */
67 spin_unlock(&sdp->sd_ail_lock);
68 71
69 bd->bd_bh = NULL; 72 bd->bd_bh = NULL;
70 bd->bd_blkno = blocknr; 73 bd->bd_blkno = blocknr;
71 74
72 gfs2_log_lock(sdp);
73 gfs2_trans_add_revoke(sdp, bd); 75 gfs2_trans_add_revoke(sdp, bd);
74 gfs2_log_unlock(sdp);
75
76 spin_lock(&sdp->sd_ail_lock);
77 } 76 }
78 gfs2_assert_withdraw(sdp, !atomic_read(&gl->gl_ail_count)); 77 BUG_ON(!fsync && atomic_read(&gl->gl_ail_count));
79 spin_unlock(&sdp->sd_ail_lock); 78 spin_unlock(&sdp->sd_ail_lock);
79 gfs2_log_unlock(sdp);
80} 80}
81 81
82 82
@@ -99,13 +99,13 @@ static void gfs2_ail_empty_gl(struct gfs2_glock *gl)
99 BUG_ON(current->journal_info); 99 BUG_ON(current->journal_info);
100 current->journal_info = &tr; 100 current->journal_info = &tr;
101 101
102 __gfs2_ail_flush(gl, (1ul << BH_Dirty)|(1ul << BH_Pinned)|(1ul << BH_Lock)); 102 __gfs2_ail_flush(gl, 0);
103 103
104 gfs2_trans_end(sdp); 104 gfs2_trans_end(sdp);
105 gfs2_log_flush(sdp, NULL); 105 gfs2_log_flush(sdp, NULL);
106} 106}
107 107
108void gfs2_ail_flush(struct gfs2_glock *gl) 108void gfs2_ail_flush(struct gfs2_glock *gl, bool fsync)
109{ 109{
110 struct gfs2_sbd *sdp = gl->gl_sbd; 110 struct gfs2_sbd *sdp = gl->gl_sbd;
111 unsigned int revokes = atomic_read(&gl->gl_ail_count); 111 unsigned int revokes = atomic_read(&gl->gl_ail_count);
@@ -117,7 +117,7 @@ void gfs2_ail_flush(struct gfs2_glock *gl)
117 ret = gfs2_trans_begin(sdp, 0, revokes); 117 ret = gfs2_trans_begin(sdp, 0, revokes);
118 if (ret) 118 if (ret)
119 return; 119 return;
120 __gfs2_ail_flush(gl, (1ul << BH_Dirty)|(1ul << BH_Pinned)); 120 __gfs2_ail_flush(gl, fsync);
121 gfs2_trans_end(sdp); 121 gfs2_trans_end(sdp);
122 gfs2_log_flush(sdp, NULL); 122 gfs2_log_flush(sdp, NULL);
123} 123}
diff --git a/fs/gfs2/glops.h b/fs/gfs2/glops.h
index 6fce409b5a50..bf95a2dc1662 100644
--- a/fs/gfs2/glops.h
+++ b/fs/gfs2/glops.h
@@ -23,6 +23,6 @@ extern const struct gfs2_glock_operations gfs2_quota_glops;
23extern const struct gfs2_glock_operations gfs2_journal_glops; 23extern const struct gfs2_glock_operations gfs2_journal_glops;
24extern const struct gfs2_glock_operations *gfs2_glops_list[]; 24extern const struct gfs2_glock_operations *gfs2_glops_list[];
25 25
26extern void gfs2_ail_flush(struct gfs2_glock *gl); 26extern void gfs2_ail_flush(struct gfs2_glock *gl, bool fsync);
27 27
28#endif /* __GLOPS_DOT_H__ */ 28#endif /* __GLOPS_DOT_H__ */
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c
index 87e9141a4def..71e420989f77 100644
--- a/fs/gfs2/super.c
+++ b/fs/gfs2/super.c
@@ -1533,7 +1533,7 @@ static void gfs2_evict_inode(struct inode *inode)
1533out_truncate: 1533out_truncate:
1534 gfs2_log_flush(sdp, ip->i_gl); 1534 gfs2_log_flush(sdp, ip->i_gl);
1535 write_inode_now(inode, 1); 1535 write_inode_now(inode, 1);
1536 gfs2_ail_flush(ip->i_gl); 1536 gfs2_ail_flush(ip->i_gl, 0);
1537 1537
1538 /* Case 2 starts here */ 1538 /* Case 2 starts here */
1539 error = gfs2_trans_begin(sdp, 0, sdp->sd_jdesc->jd_blocks); 1539 error = gfs2_trans_begin(sdp, 0, sdp->sd_jdesc->jd_blocks);