aboutsummaryrefslogtreecommitdiffstats
path: root/fs/gfs2/glops.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/gfs2/glops.c')
-rw-r--r--fs/gfs2/glops.c89
1 files changed, 42 insertions, 47 deletions
diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c
index da21ecaafcc2..78418b4fa857 100644
--- a/fs/gfs2/glops.c
+++ b/fs/gfs2/glops.c
@@ -28,40 +28,55 @@
28#include "trans.h" 28#include "trans.h"
29#include "dir.h" 29#include "dir.h"
30 30
31static void gfs2_ail_error(struct gfs2_glock *gl, const struct buffer_head *bh)
32{
33 fs_err(gl->gl_sbd, "AIL buffer %p: blocknr %llu state 0x%08lx mapping %p page state 0x%lx\n",
34 bh, (unsigned long long)bh->b_blocknr, bh->b_state,
35 bh->b_page->mapping, bh->b_page->flags);
36 fs_err(gl->gl_sbd, "AIL glock %u:%llu mapping %p\n",
37 gl->gl_name.ln_type, gl->gl_name.ln_number,
38 gfs2_glock2aspace(gl));
39 gfs2_lm_withdraw(gl->gl_sbd, "AIL error\n");
40}
41
31/** 42/**
32 * __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
33 * @gl: the glock 44 * @gl: the glock
45 * @fsync: set when called from fsync (not all buffers will be clean)
34 * 46 *
35 * None of the buffers should be dirty, locked, or pinned. 47 * None of the buffers should be dirty, locked, or pinned.
36 */ 48 */
37 49
38static void __gfs2_ail_flush(struct gfs2_glock *gl) 50static void __gfs2_ail_flush(struct gfs2_glock *gl, bool fsync)
39{ 51{
40 struct gfs2_sbd *sdp = gl->gl_sbd; 52 struct gfs2_sbd *sdp = gl->gl_sbd;
41 struct list_head *head = &gl->gl_ail_list; 53 struct list_head *head = &gl->gl_ail_list;
42 struct gfs2_bufdata *bd; 54 struct gfs2_bufdata *bd, *tmp;
43 struct buffer_head *bh; 55 struct buffer_head *bh;
56 const unsigned long b_state = (1UL << BH_Dirty)|(1UL << BH_Pinned)|(1UL << BH_Lock);
57 sector_t blocknr;
44 58
59 gfs2_log_lock(sdp);
45 spin_lock(&sdp->sd_ail_lock); 60 spin_lock(&sdp->sd_ail_lock);
46 while (!list_empty(head)) { 61 list_for_each_entry_safe(bd, tmp, head, bd_ail_gl_list) {
47 bd = list_entry(head->next, struct gfs2_bufdata,
48 bd_ail_gl_list);
49 bh = bd->bd_bh; 62 bh = bd->bd_bh;
50 gfs2_remove_from_ail(bd); 63 if (bh->b_state & b_state) {
51 bd->bd_bh = NULL; 64 if (fsync)
65 continue;
66 gfs2_ail_error(gl, bh);
67 }
68 blocknr = bh->b_blocknr;
52 bh->b_private = NULL; 69 bh->b_private = NULL;
53 spin_unlock(&sdp->sd_ail_lock); 70 gfs2_remove_from_ail(bd); /* drops ref on bh */
54 71
55 bd->bd_blkno = bh->b_blocknr; 72 bd->bd_bh = NULL;
56 gfs2_log_lock(sdp); 73 bd->bd_blkno = blocknr;
57 gfs2_assert_withdraw(sdp, !buffer_busy(bh));
58 gfs2_trans_add_revoke(sdp, bd);
59 gfs2_log_unlock(sdp);
60 74
61 spin_lock(&sdp->sd_ail_lock); 75 gfs2_trans_add_revoke(sdp, bd);
62 } 76 }
63 gfs2_assert_withdraw(sdp, !atomic_read(&gl->gl_ail_count)); 77 BUG_ON(!fsync && atomic_read(&gl->gl_ail_count));
64 spin_unlock(&sdp->sd_ail_lock); 78 spin_unlock(&sdp->sd_ail_lock);
79 gfs2_log_unlock(sdp);
65} 80}
66 81
67 82
@@ -84,13 +99,13 @@ static void gfs2_ail_empty_gl(struct gfs2_glock *gl)
84 BUG_ON(current->journal_info); 99 BUG_ON(current->journal_info);
85 current->journal_info = &tr; 100 current->journal_info = &tr;
86 101
87 __gfs2_ail_flush(gl); 102 __gfs2_ail_flush(gl, 0);
88 103
89 gfs2_trans_end(sdp); 104 gfs2_trans_end(sdp);
90 gfs2_log_flush(sdp, NULL); 105 gfs2_log_flush(sdp, NULL);
91} 106}
92 107
93void gfs2_ail_flush(struct gfs2_glock *gl) 108void gfs2_ail_flush(struct gfs2_glock *gl, bool fsync)
94{ 109{
95 struct gfs2_sbd *sdp = gl->gl_sbd; 110 struct gfs2_sbd *sdp = gl->gl_sbd;
96 unsigned int revokes = atomic_read(&gl->gl_ail_count); 111 unsigned int revokes = atomic_read(&gl->gl_ail_count);
@@ -102,7 +117,7 @@ void gfs2_ail_flush(struct gfs2_glock *gl)
102 ret = gfs2_trans_begin(sdp, 0, revokes); 117 ret = gfs2_trans_begin(sdp, 0, revokes);
103 if (ret) 118 if (ret)
104 return; 119 return;
105 __gfs2_ail_flush(gl); 120 __gfs2_ail_flush(gl, fsync);
106 gfs2_trans_end(sdp); 121 gfs2_trans_end(sdp);
107 gfs2_log_flush(sdp, NULL); 122 gfs2_log_flush(sdp, NULL);
108} 123}
@@ -119,6 +134,7 @@ void gfs2_ail_flush(struct gfs2_glock *gl)
119static void rgrp_go_sync(struct gfs2_glock *gl) 134static void rgrp_go_sync(struct gfs2_glock *gl)
120{ 135{
121 struct address_space *metamapping = gfs2_glock2aspace(gl); 136 struct address_space *metamapping = gfs2_glock2aspace(gl);
137 struct gfs2_rgrpd *rgd;
122 int error; 138 int error;
123 139
124 if (!test_and_clear_bit(GLF_DIRTY, &gl->gl_flags)) 140 if (!test_and_clear_bit(GLF_DIRTY, &gl->gl_flags))
@@ -130,6 +146,12 @@ static void rgrp_go_sync(struct gfs2_glock *gl)
130 error = filemap_fdatawait(metamapping); 146 error = filemap_fdatawait(metamapping);
131 mapping_set_error(metamapping, error); 147 mapping_set_error(metamapping, error);
132 gfs2_ail_empty_gl(gl); 148 gfs2_ail_empty_gl(gl);
149
150 spin_lock(&gl->gl_spin);
151 rgd = gl->gl_object;
152 if (rgd)
153 gfs2_free_clones(rgd);
154 spin_unlock(&gl->gl_spin);
133} 155}
134 156
135/** 157/**
@@ -430,33 +452,6 @@ static int inode_go_dump(struct seq_file *seq, const struct gfs2_glock *gl)
430} 452}
431 453
432/** 454/**
433 * rgrp_go_lock - operation done after an rgrp lock is locked by
434 * a first holder on this node.
435 * @gl: the glock
436 * @flags:
437 *
438 * Returns: errno
439 */
440
441static int rgrp_go_lock(struct gfs2_holder *gh)
442{
443 return gfs2_rgrp_bh_get(gh->gh_gl->gl_object);
444}
445
446/**
447 * rgrp_go_unlock - operation done before an rgrp lock is unlocked by
448 * a last holder on this node.
449 * @gl: the glock
450 * @flags:
451 *
452 */
453
454static void rgrp_go_unlock(struct gfs2_holder *gh)
455{
456 gfs2_rgrp_bh_put(gh->gh_gl->gl_object);
457}
458
459/**
460 * trans_go_sync - promote/demote the transaction glock 455 * trans_go_sync - promote/demote the transaction glock
461 * @gl: the glock 456 * @gl: the glock
462 * @state: the requested state 457 * @state: the requested state
@@ -558,8 +553,8 @@ const struct gfs2_glock_operations gfs2_inode_glops = {
558const struct gfs2_glock_operations gfs2_rgrp_glops = { 553const struct gfs2_glock_operations gfs2_rgrp_glops = {
559 .go_xmote_th = rgrp_go_sync, 554 .go_xmote_th = rgrp_go_sync,
560 .go_inval = rgrp_go_inval, 555 .go_inval = rgrp_go_inval,
561 .go_lock = rgrp_go_lock, 556 .go_lock = gfs2_rgrp_go_lock,
562 .go_unlock = rgrp_go_unlock, 557 .go_unlock = gfs2_rgrp_go_unlock,
563 .go_dump = gfs2_rgrp_dump, 558 .go_dump = gfs2_rgrp_dump,
564 .go_type = LM_TYPE_RGRP, 559 .go_type = LM_TYPE_RGRP,
565 .go_flags = GLOF_ASPACE, 560 .go_flags = GLOF_ASPACE,