mirror of
https://github.com/torvalds/linux.git
synced 2026-05-25 07:33:19 +02:00
gfs2: add some missing log locking
Function gfs2_logd() calls the log flushing functions gfs2_ail1_start(),
gfs2_ail1_wait(), and gfs2_ail1_empty() without holding sdp->sd_log_flush_lock,
but these functions require exclusion against concurrent transactions.
To fix that, add a non-locking __gfs2_log_flush() function. Then, in
gfs2_logd(), take sdp->sd_log_flush_lock before calling the above mentioned log
flushing functions and __gfs2_log_flush().
Fixes: 5e4c7632aa ("gfs2: Issue revokes more intelligently")
Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
This commit is contained in:
parent
f4e4c4e6ac
commit
fe2c8d0511
|
|
@ -1053,14 +1053,15 @@ void gfs2_remove_from_journal(struct buffer_head *bh, int meta)
|
|||
}
|
||||
|
||||
/**
|
||||
* gfs2_log_flush - flush incore transaction(s)
|
||||
* __gfs2_log_flush - flush incore transaction(s)
|
||||
* @sdp: The filesystem
|
||||
* @gl: The glock structure to flush. If NULL, flush the whole incore log
|
||||
* @flags: The log header flags: GFS2_LOG_HEAD_FLUSH_* and debug flags
|
||||
*
|
||||
*/
|
||||
|
||||
void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl, u32 flags)
|
||||
static void __gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl,
|
||||
u32 flags)
|
||||
{
|
||||
struct gfs2_trans *tr = NULL;
|
||||
unsigned int reserved_blocks = 0, used_blocks = 0;
|
||||
|
|
@ -1068,7 +1069,6 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl, u32 flags)
|
|||
unsigned int first_log_head;
|
||||
unsigned int reserved_revokes = 0;
|
||||
|
||||
down_write(&sdp->sd_log_flush_lock);
|
||||
trace_gfs2_log_flush(sdp, 1, flags);
|
||||
|
||||
repeat:
|
||||
|
|
@ -1180,7 +1180,6 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl, u32 flags)
|
|||
gfs2_assert_withdraw(sdp, used_blocks < reserved_blocks);
|
||||
gfs2_log_release(sdp, reserved_blocks - used_blocks);
|
||||
}
|
||||
up_write(&sdp->sd_log_flush_lock);
|
||||
gfs2_trans_free(sdp, tr);
|
||||
trace_gfs2_log_flush(sdp, 0, flags);
|
||||
return;
|
||||
|
|
@ -1201,6 +1200,13 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl, u32 flags)
|
|||
goto out_end;
|
||||
}
|
||||
|
||||
void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl, u32 flags)
|
||||
{
|
||||
down_write(&sdp->sd_log_flush_lock);
|
||||
__gfs2_log_flush(sdp, gl, flags);
|
||||
up_write(&sdp->sd_log_flush_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* gfs2_merge_trans - Merge a new transaction into a cached transaction
|
||||
* @sdp: the filesystem
|
||||
|
|
@ -1332,19 +1338,25 @@ int gfs2_logd(void *data)
|
|||
break;
|
||||
|
||||
if (gfs2_jrnl_flush_reqd(sdp) || t == 0) {
|
||||
down_write(&sdp->sd_log_flush_lock);
|
||||
gfs2_ail1_empty(sdp, 0);
|
||||
gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL |
|
||||
GFS2_LFC_LOGD_JFLUSH_REQD);
|
||||
__gfs2_log_flush(sdp, NULL,
|
||||
GFS2_LOG_HEAD_FLUSH_NORMAL |
|
||||
GFS2_LFC_LOGD_JFLUSH_REQD);
|
||||
up_write(&sdp->sd_log_flush_lock);
|
||||
}
|
||||
|
||||
if (test_bit(SDF_FORCE_AIL_FLUSH, &sdp->sd_flags) ||
|
||||
gfs2_ail_flush_reqd(sdp)) {
|
||||
clear_bit(SDF_FORCE_AIL_FLUSH, &sdp->sd_flags);
|
||||
down_write(&sdp->sd_log_flush_lock);
|
||||
gfs2_ail1_start(sdp);
|
||||
gfs2_ail1_wait(sdp);
|
||||
gfs2_ail1_empty(sdp, 0);
|
||||
gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL |
|
||||
GFS2_LFC_LOGD_AIL_FLUSH_REQD);
|
||||
__gfs2_log_flush(sdp, NULL,
|
||||
GFS2_LOG_HEAD_FLUSH_NORMAL |
|
||||
GFS2_LFC_LOGD_AIL_FLUSH_REQD);
|
||||
up_write(&sdp->sd_log_flush_lock);
|
||||
}
|
||||
|
||||
t = gfs2_tune_get(sdp, gt_logd_secs) * HZ;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user