GFS2: Log the reason for log flushes in every log header
This patch just adds the capability for GFS2 to track which function called gfs2_log_flush. This should make it easier to diagnose problems based on the sequence of events found in the journals. Signed-off-by: Bob Peterson <rpeterso@redhat.com> Reviewed-by: Andreas Gruenbacher <agruenba@redhat.com>
This commit is contained in:
parent
c1696fb85d
commit
805c090750
|
@ -448,7 +448,8 @@ static int gfs2_jdata_writepages(struct address_space *mapping,
|
|||
|
||||
ret = gfs2_write_cache_jdata(mapping, wbc);
|
||||
if (ret == 0 && wbc->sync_mode == WB_SYNC_ALL) {
|
||||
gfs2_log_flush(sdp, ip->i_gl, GFS2_LOG_HEAD_FLUSH_NORMAL);
|
||||
gfs2_log_flush(sdp, ip->i_gl, GFS2_LOG_HEAD_FLUSH_NORMAL |
|
||||
GFS2_LFC_JDATA_WPAGES);
|
||||
ret = gfs2_write_cache_jdata(mapping, wbc);
|
||||
}
|
||||
return ret;
|
||||
|
|
|
@ -247,7 +247,8 @@ static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask)
|
|||
if ((flags ^ new_flags) & GFS2_DIF_JDATA) {
|
||||
if (new_flags & GFS2_DIF_JDATA)
|
||||
gfs2_log_flush(sdp, ip->i_gl,
|
||||
GFS2_LOG_HEAD_FLUSH_NORMAL);
|
||||
GFS2_LOG_HEAD_FLUSH_NORMAL |
|
||||
GFS2_LFC_SET_FLAGS);
|
||||
error = filemap_fdatawrite(inode->i_mapping);
|
||||
if (error)
|
||||
goto out;
|
||||
|
|
|
@ -107,7 +107,8 @@ static void gfs2_ail_empty_gl(struct gfs2_glock *gl)
|
|||
__gfs2_ail_flush(gl, 0, tr.tr_revokes);
|
||||
|
||||
gfs2_trans_end(sdp);
|
||||
gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL);
|
||||
gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL |
|
||||
GFS2_LFC_AIL_EMPTY_GL);
|
||||
}
|
||||
|
||||
void gfs2_ail_flush(struct gfs2_glock *gl, bool fsync)
|
||||
|
@ -128,7 +129,8 @@ void gfs2_ail_flush(struct gfs2_glock *gl, bool fsync)
|
|||
return;
|
||||
__gfs2_ail_flush(gl, fsync, max_revokes);
|
||||
gfs2_trans_end(sdp);
|
||||
gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL);
|
||||
gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL |
|
||||
GFS2_LFC_AIL_FLUSH);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -157,7 +159,8 @@ static void rgrp_go_sync(struct gfs2_glock *gl)
|
|||
return;
|
||||
GLOCK_BUG_ON(gl, gl->gl_state != LM_ST_EXCLUSIVE);
|
||||
|
||||
gfs2_log_flush(sdp, gl, GFS2_LOG_HEAD_FLUSH_NORMAL);
|
||||
gfs2_log_flush(sdp, gl, GFS2_LOG_HEAD_FLUSH_NORMAL |
|
||||
GFS2_LFC_RGRP_GO_SYNC);
|
||||
filemap_fdatawrite_range(mapping, gl->gl_vm.start, gl->gl_vm.end);
|
||||
error = filemap_fdatawait_range(mapping, gl->gl_vm.start, gl->gl_vm.end);
|
||||
mapping_set_error(mapping, error);
|
||||
|
@ -252,7 +255,8 @@ static void inode_go_sync(struct gfs2_glock *gl)
|
|||
|
||||
GLOCK_BUG_ON(gl, gl->gl_state != LM_ST_EXCLUSIVE);
|
||||
|
||||
gfs2_log_flush(gl->gl_name.ln_sbd, gl, GFS2_LOG_HEAD_FLUSH_NORMAL);
|
||||
gfs2_log_flush(gl->gl_name.ln_sbd, gl, GFS2_LOG_HEAD_FLUSH_NORMAL |
|
||||
GFS2_LFC_INODE_GO_SYNC);
|
||||
filemap_fdatawrite(metamapping);
|
||||
if (isreg) {
|
||||
struct address_space *mapping = ip->i_inode.i_mapping;
|
||||
|
@ -304,7 +308,8 @@ static void inode_go_inval(struct gfs2_glock *gl, int flags)
|
|||
|
||||
if (ip == GFS2_I(gl->gl_name.ln_sbd->sd_rindex)) {
|
||||
gfs2_log_flush(gl->gl_name.ln_sbd, NULL,
|
||||
GFS2_LOG_HEAD_FLUSH_NORMAL);
|
||||
GFS2_LOG_HEAD_FLUSH_NORMAL |
|
||||
GFS2_LFC_INODE_GO_INVAL);
|
||||
gl->gl_name.ln_sbd->sd_rindex_uptodate = 0;
|
||||
}
|
||||
if (ip && S_ISREG(ip->i_inode.i_mode))
|
||||
|
@ -496,7 +501,8 @@ static void freeze_go_sync(struct gfs2_glock *gl)
|
|||
gfs2_assert_withdraw(sdp, 0);
|
||||
}
|
||||
queue_work(gfs2_freeze_wq, &sdp->sd_freeze_work);
|
||||
gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_FREEZE);
|
||||
gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_FREEZE |
|
||||
GFS2_LFC_FREEZE_GO_SYNC);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -757,7 +757,7 @@ static void log_write_header(struct gfs2_sbd *sdp, u32 flags)
|
|||
* 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_*
|
||||
* @flags: The log header flags: GFS2_LOG_HEAD_FLUSH_* and debug flags
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -773,7 +773,7 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl, u32 flags)
|
|||
up_write(&sdp->sd_log_flush_lock);
|
||||
return;
|
||||
}
|
||||
trace_gfs2_log_flush(sdp, 1);
|
||||
trace_gfs2_log_flush(sdp, 1, flags);
|
||||
|
||||
if (flags & GFS2_LOG_HEAD_FLUSH_SHUTDOWN)
|
||||
clear_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags);
|
||||
|
@ -841,7 +841,7 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl, u32 flags)
|
|||
atomic_set(&sdp->sd_freeze_state, SFS_FROZEN);
|
||||
}
|
||||
|
||||
trace_gfs2_log_flush(sdp, 0);
|
||||
trace_gfs2_log_flush(sdp, 0, flags);
|
||||
up_write(&sdp->sd_log_flush_lock);
|
||||
|
||||
kfree(tr);
|
||||
|
@ -937,7 +937,7 @@ void gfs2_log_shutdown(struct gfs2_sbd *sdp)
|
|||
|
||||
sdp->sd_log_flush_head = sdp->sd_log_head;
|
||||
|
||||
log_write_header(sdp, GFS2_LOG_HEAD_UNMOUNT);
|
||||
log_write_header(sdp, GFS2_LOG_HEAD_UNMOUNT | GFS2_LFC_SHUTDOWN);
|
||||
|
||||
gfs2_assert_warn(sdp, sdp->sd_log_head == sdp->sd_log_tail);
|
||||
gfs2_assert_warn(sdp, list_empty(&sdp->sd_ail2_list));
|
||||
|
@ -993,7 +993,8 @@ int gfs2_logd(void *data)
|
|||
did_flush = false;
|
||||
if (gfs2_jrnl_flush_reqd(sdp) || t == 0) {
|
||||
gfs2_ail1_empty(sdp);
|
||||
gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL);
|
||||
gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL |
|
||||
GFS2_LFC_LOGD_JFLUSH_REQD);
|
||||
did_flush = true;
|
||||
}
|
||||
|
||||
|
@ -1001,7 +1002,8 @@ int gfs2_logd(void *data)
|
|||
gfs2_ail1_start(sdp);
|
||||
gfs2_ail1_wait(sdp);
|
||||
gfs2_ail1_empty(sdp);
|
||||
gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL);
|
||||
gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL |
|
||||
GFS2_LFC_LOGD_AIL_FLUSH_REQD);
|
||||
did_flush = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -1382,7 +1382,7 @@ static void gfs2_kill_sb(struct super_block *sb)
|
|||
return;
|
||||
}
|
||||
|
||||
gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_SYNC);
|
||||
gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_SYNC | GFS2_LFC_KILL_SB);
|
||||
dput(sdp->sd_root_dir);
|
||||
dput(sdp->sd_master_dir);
|
||||
sdp->sd_root_dir = NULL;
|
||||
|
|
|
@ -956,7 +956,7 @@ static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda)
|
|||
inode_unlock(&ip->i_inode);
|
||||
kfree(ghs);
|
||||
gfs2_log_flush(ip->i_gl->gl_name.ln_sbd, ip->i_gl,
|
||||
GFS2_LOG_HEAD_FLUSH_NORMAL);
|
||||
GFS2_LOG_HEAD_FLUSH_NORMAL | GFS2_LFC_DO_SYNC);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
|
|
@ -2093,7 +2093,8 @@ int gfs2_inplace_reserve(struct gfs2_inode *ip, struct gfs2_alloc_parms *ap)
|
|||
}
|
||||
/* Flushing the log may release space */
|
||||
if (loops == 2)
|
||||
gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL);
|
||||
gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL |
|
||||
GFS2_LFC_INPLACE_RESERVE);
|
||||
}
|
||||
|
||||
return -ENOSPC;
|
||||
|
|
|
@ -758,7 +758,8 @@ static int gfs2_write_inode(struct inode *inode, struct writeback_control *wbc)
|
|||
|
||||
if (flush_all)
|
||||
gfs2_log_flush(GFS2_SB(inode), ip->i_gl,
|
||||
GFS2_LOG_HEAD_FLUSH_NORMAL);
|
||||
GFS2_LOG_HEAD_FLUSH_NORMAL |
|
||||
GFS2_LFC_WRITE_INODE);
|
||||
if (bdi->wb.dirty_exceeded)
|
||||
gfs2_ail1_flush(sdp, wbc);
|
||||
else
|
||||
|
@ -854,7 +855,8 @@ static int gfs2_make_fs_ro(struct gfs2_sbd *sdp)
|
|||
gfs2_quota_sync(sdp->sd_vfs, 0);
|
||||
gfs2_statfs_sync(sdp->sd_vfs, 0);
|
||||
|
||||
gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_SHUTDOWN);
|
||||
gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_SHUTDOWN |
|
||||
GFS2_LFC_MAKE_FS_RO);
|
||||
wait_event(sdp->sd_reserving_log_wait, atomic_read(&sdp->sd_reserving_log) == 0);
|
||||
gfs2_assert_warn(sdp, atomic_read(&sdp->sd_log_blks_free) == sdp->sd_jdesc->jd_blocks);
|
||||
|
||||
|
@ -947,7 +949,8 @@ static int gfs2_sync_fs(struct super_block *sb, int wait)
|
|||
|
||||
gfs2_quota_sync(sb, -1);
|
||||
if (wait)
|
||||
gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL);
|
||||
gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL |
|
||||
GFS2_LFC_SYNC_FS);
|
||||
return sdp->sd_log_error;
|
||||
}
|
||||
|
||||
|
@ -1651,7 +1654,8 @@ static void gfs2_evict_inode(struct inode *inode)
|
|||
goto out_unlock;
|
||||
|
||||
out_truncate:
|
||||
gfs2_log_flush(sdp, ip->i_gl, GFS2_LOG_HEAD_FLUSH_NORMAL);
|
||||
gfs2_log_flush(sdp, ip->i_gl, GFS2_LOG_HEAD_FLUSH_NORMAL |
|
||||
GFS2_LFC_EVICT_INODE);
|
||||
metamapping = gfs2_glock2aspace(ip->i_gl);
|
||||
if (test_bit(GLF_DIRTY, &ip->i_gl->gl_flags)) {
|
||||
filemap_fdatawrite(metamapping);
|
||||
|
|
|
@ -353,26 +353,29 @@ TRACE_EVENT(gfs2_pin,
|
|||
/* Flushing the log */
|
||||
TRACE_EVENT(gfs2_log_flush,
|
||||
|
||||
TP_PROTO(const struct gfs2_sbd *sdp, int start),
|
||||
TP_PROTO(const struct gfs2_sbd *sdp, int start, u32 flags),
|
||||
|
||||
TP_ARGS(sdp, start),
|
||||
TP_ARGS(sdp, start, flags),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field( dev_t, dev )
|
||||
__field( int, start )
|
||||
__field( u64, log_seq )
|
||||
__field( u32, flags )
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->dev = sdp->sd_vfs->s_dev;
|
||||
__entry->start = start;
|
||||
__entry->log_seq = sdp->sd_log_sequence;
|
||||
__entry->flags = flags;
|
||||
),
|
||||
|
||||
TP_printk("%u,%u log flush %s %llu",
|
||||
TP_printk("%u,%u log flush %s %llu %llx",
|
||||
MAJOR(__entry->dev), MINOR(__entry->dev),
|
||||
__entry->start ? "start" : "end",
|
||||
(unsigned long long)__entry->log_seq)
|
||||
(unsigned long long)__entry->log_seq,
|
||||
(unsigned long long)__entry->flags)
|
||||
);
|
||||
|
||||
/* Reserving/releasing blocks in the log */
|
||||
|
|
|
@ -117,7 +117,8 @@ void gfs2_trans_end(struct gfs2_sbd *sdp)
|
|||
up_read(&sdp->sd_log_flush_lock);
|
||||
|
||||
if (sdp->sd_vfs->s_flags & SB_SYNCHRONOUS)
|
||||
gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL);
|
||||
gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL |
|
||||
GFS2_LFC_TRANS_END);
|
||||
if (alloced)
|
||||
sb_end_intwrite(sdp->sd_vfs);
|
||||
}
|
||||
|
|
|
@ -411,6 +411,27 @@ struct gfs2_ea_header {
|
|||
#define GFS2_LOG_HEAD_RECOVERY 0x00000020 /* Journal recovery */
|
||||
#define GFS2_LOG_HEAD_USERSPACE 0x80000000 /* Written by gfs2-utils */
|
||||
|
||||
/* Log flush callers */
|
||||
#define GFS2_LFC_SHUTDOWN 0x00000100
|
||||
#define GFS2_LFC_JDATA_WPAGES 0x00000200
|
||||
#define GFS2_LFC_SET_FLAGS 0x00000400
|
||||
#define GFS2_LFC_AIL_EMPTY_GL 0x00000800
|
||||
#define GFS2_LFC_AIL_FLUSH 0x00001000
|
||||
#define GFS2_LFC_RGRP_GO_SYNC 0x00002000
|
||||
#define GFS2_LFC_INODE_GO_SYNC 0x00004000
|
||||
#define GFS2_LFC_INODE_GO_INVAL 0x00008000
|
||||
#define GFS2_LFC_FREEZE_GO_SYNC 0x00010000
|
||||
#define GFS2_LFC_KILL_SB 0x00020000
|
||||
#define GFS2_LFC_DO_SYNC 0x00040000
|
||||
#define GFS2_LFC_INPLACE_RESERVE 0x00080000
|
||||
#define GFS2_LFC_WRITE_INODE 0x00100000
|
||||
#define GFS2_LFC_MAKE_FS_RO 0x00200000
|
||||
#define GFS2_LFC_SYNC_FS 0x00400000
|
||||
#define GFS2_LFC_EVICT_INODE 0x00800000
|
||||
#define GFS2_LFC_TRANS_END 0x01000000
|
||||
#define GFS2_LFC_LOGD_JFLUSH_REQD 0x02000000
|
||||
#define GFS2_LFC_LOGD_AIL_FLUSH_REQD 0x04000000
|
||||
|
||||
#define LH_V1_SIZE (offsetofend(struct gfs2_log_header, lh_hash))
|
||||
|
||||
struct gfs2_log_header {
|
||||
|
|
Loading…
Reference in New Issue