xfs: Reduce log force overhead for delayed logging
PATCH 1/1 xfs: Reduce log force overhead for delayed logging
From: Dave Chinner <[email protected]>
Delayed logging adds some serialisation to the log force process to ensure that it does not deference a bad commit context structure when determining if a CIl push is necessary or not. It does this by grabing the CIl contrext lock exclusively, then dropping it before pushing the CIL if necessary. This causes serialisation of all log forces and pushes regardless of whether a force is necessary or not. As a result fsync heavy workloads (like dbench) can be significantly slower with delayed logging than without.
To avoid this penalty, copy the current sequence from the context to the CIL structure when they are swapped. This allows us to do unlocked checks on the current sequence without having to worry about dereferencing context structures that may have already been freed. Hence we can remove the CIL context locking in the forcing code and only call into the push code if the current context matches the sequence we need to force.
By passing the sequence into the push code, we can check the sequence again once we have the CIL lock held exclusive and abort if the sequence has already been pushed. This avoids a lock round-trip and unnecessary CIL pushes when we have racing push calls.
The result is that the regression in dbench performance goes away - this change improves dbench performance on a ramdisk from ~2100MB/s to ~2500MB/s. This compares favourably to not using delayed logging which retuns ~2500MB/s for the same workload.
--- fs/xfs/xfs_log.c | 6 +- fs/xfs/xfs_log_cil.c | 243 ++++++++++++++++++++++++++----------------------- fs/xfs/xfs_log_priv.h | 15 +++- 3 files changed, 147 insertions(+), 117 deletions(-)
fs/xfs/xfs_log.c +3 -3
@@ -3015,7 +3015,7 @@ _xfs_log_force(XFS_STATS_INC (xs_log_force); -xlog_cil_push (log,1 ); +xlog_cil_force (log);spin_lock (&log->l_icloglock);
@@ -3167,7 +3167,7 @@ _xfs_log_force_lsn(XFS_STATS_INC (xs_log_force);if (log->l_cilp) { - lsn =xlog_cil_push_lsn (log, lsn); + lsn =xlog_cil_force_lsn (log, lsn);if (lsn ==NULLCOMMITLSN )return 0 ; }
@@ -3724,7 +3724,7 @@ xfs_log_force_umount(* call below. */ if (!logerror && (mp->m_flags &XFS_MOUNT_DELAYLOG )) -xlog_cil_push (log,1 ); +xlog_cil_force (log);/* * We must hold both the GRANT lock and the LOG lock,
fs/xfs/xfs_log_cil.c +131 -112
321 lines not on this page · raw message
fs/xfs/xfs_log_priv.h +13 -2
@@ -422,6 +422,7 @@ struct xfs_cil {struct rw_semaphore xc_ctx_lock;struct list_head xc_committing;sv_t xc_commit_wait; +xfs_lsn_t xc_current_sequence; };/*
@@ -562,8 +563,18 @@ int xlog_cil_init(struct log *log);void xlog_cil_init_post_recovery (struct log *log);void xlog_cil_destroy (struct log *log); -int xlog_cil_push (struct log *log,int push_now); -xfs_lsn_t xlog_cil_push_lsn (struct log *log,xfs_lsn_t push_sequence); +/* +* CIL force routines +*/ +xfs_lsn_t xlog_cil_force_lsn (struct log *log,xfs_lsn_t sequence); + +static inline void +xlog_cil_force (struct log *log) +{ +if (log->l_cilp) +xlog_cil_force_lsn (log, log->l_cilp->xc_current_sequence); +} +/* * Unmount record type is used as a pseudo transaction type for the ticket.
Signature · 6 lines
1.7.1 _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
Looks good to me,
minor nitpicks below:
Quoted 2 lines
int
xlog_cil_push(
This can be marked STATIC now.
fs/xfs/xfs_log_priv.h int xlog_cil_init(struct log *log); · line 576
Quoted 11 lines
fs/xfs/xfs_log_priv.h +11
-0+/* +* CIL force routines +*/ +xfs_lsn_t xlog_cil_force_lsn (struct log *log,xfs_lsn_t sequence); + +static inline void +xlog_cil_force (struct log *log) +{ +if (log->l_cilp) +xlog_cil_force_lsn (log, log->l_cilp->xc_current_sequence); +}
I'd move the if (log->l_cilp) check to the caller. One of the two already does so, as does the caller of xlog_cil_force_lsn.
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs