Skip to content

Commit 9ff7828

Browse files
committed
gfs2: Do log_flush in gfs2_ail_empty_gl even if ail list is empty
Before this patch, if gfs2_ail_empty_gl saw there was nothing on the ail list, it would return and not flush the log. The problem is that there could still be a revoke for the rgrp sitting on the sd_log_le_revoke list that's been recently taken off the ail list. But that revoke still needs to be written, and the rgrp_go_inval still needs to call log_flush_wait to ensure the revokes are all properly written to the journal before we relinquish control of the glock to another node. If we give the glock to another node before we have this knowledge, the node might crash and its journal replayed, in which case the missing revoke would allow the journal replay to replay the rgrp over top of the rgrp we already gave to another node, thus overwriting its changes and corrupting the file system. This patch makes gfs2_ail_empty_gl still call gfs2_log_flush rather than returning. Signed-off-by: Bob Peterson <[email protected]> Reviewed-by: Andreas Gruenbacher <[email protected]>
1 parent d93ae38 commit 9ff7828

File tree

3 files changed

+28
-2
lines changed

3 files changed

+28
-2
lines changed

fs/gfs2/glops.c

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,32 @@ static void gfs2_ail_empty_gl(struct gfs2_glock *gl)
9292
INIT_LIST_HEAD(&tr.tr_databuf);
9393
tr.tr_revokes = atomic_read(&gl->gl_ail_count);
9494

95-
if (!tr.tr_revokes)
95+
if (!tr.tr_revokes) {
96+
bool have_revokes;
97+
bool log_in_flight;
98+
99+
/*
100+
* We have nothing on the ail, but there could be revokes on
101+
* the sdp revoke queue, in which case, we still want to flush
102+
* the log and wait for it to finish.
103+
*
104+
* If the sdp revoke list is empty too, we might still have an
105+
* io outstanding for writing revokes, so we should wait for
106+
* it before returning.
107+
*
108+
* If none of these conditions are true, our revokes are all
109+
* flushed and we can return.
110+
*/
111+
gfs2_log_lock(sdp);
112+
have_revokes = !list_empty(&sdp->sd_log_revokes);
113+
log_in_flight = atomic_read(&sdp->sd_log_in_flight);
114+
gfs2_log_unlock(sdp);
115+
if (have_revokes)
116+
goto flush;
117+
if (log_in_flight)
118+
log_flush_wait(sdp);
96119
return;
120+
}
97121

98122
/* A shortened, inline version of gfs2_trans_begin()
99123
* tr->alloced is not set since the transaction structure is
@@ -108,6 +132,7 @@ static void gfs2_ail_empty_gl(struct gfs2_glock *gl)
108132
__gfs2_ail_flush(gl, 0, tr.tr_revokes);
109133

110134
gfs2_trans_end(sdp);
135+
flush:
111136
gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL |
112137
GFS2_LFC_AIL_EMPTY_GL);
113138
}

fs/gfs2/log.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -537,7 +537,7 @@ static void log_pull_tail(struct gfs2_sbd *sdp, unsigned int new_tail)
537537
}
538538

539539

540-
static void log_flush_wait(struct gfs2_sbd *sdp)
540+
void log_flush_wait(struct gfs2_sbd *sdp)
541541
{
542542
DEFINE_WAIT(wait);
543543

fs/gfs2/log.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ extern void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl,
7373
u32 type);
7474
extern void gfs2_log_commit(struct gfs2_sbd *sdp, struct gfs2_trans *trans);
7575
extern void gfs2_ail1_flush(struct gfs2_sbd *sdp, struct writeback_control *wbc);
76+
extern void log_flush_wait(struct gfs2_sbd *sdp);
7677

7778
extern int gfs2_logd(void *data);
7879
extern void gfs2_add_revoke(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd);

0 commit comments

Comments
 (0)