From 110590348741a0aedac3285e7e8f19dd1f065960 Mon Sep 17 00:00:00 2001 From: Dave Kleikamp Date: Mon, 10 Mar 2003 00:32:02 -0600 Subject: [PATCH] JFS: Fix hang while flushing outstanding transactions under heavy load During syncbarrier recovery, when JFS is waiting for all outstanding transactions to complete before allowing new ones to start, there was a window where a new transaction starts, but is not committed when JFS thought it could stop flushing the journal to disk. This caused the log_SYNCBARRIER flag to not be reset, and no new transactions are allowed to start. This is fixed by using the log->active field to determine when to reset the log_FLUSH flag. --- fs/jfs/jfs_logmgr.c | 34 ++++++++++++++++------------------ fs/jfs/jfs_txnmgr.c | 26 ++++++++++++++------------ 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/fs/jfs/jfs_logmgr.c b/fs/jfs/jfs_logmgr.c index fc218ce7c5970..2d18d1d648751 100644 --- a/fs/jfs/jfs_logmgr.c +++ b/fs/jfs/jfs_logmgr.c @@ -674,28 +674,29 @@ int lmGroupCommit(struct jfs_log * log, struct tblock * tblk) } jfs_info("lmGroup Commit: tblk = 0x%p, gcrtc = %d", tblk, log->gcrtc); - if (tblk->xflag & COMMIT_LAZY) { - /* - * Lazy transactions can leave now - */ + if (tblk->xflag & COMMIT_LAZY) tblk->flag |= tblkGC_LAZY; - LOGGC_UNLOCK(log); - return 0; - } - /* - * group commit pageout in progress - */ - if ((!(log->cflag & logGC_PAGEOUT)) && log->cqueue.head) { + + if ((!(log->cflag & logGC_PAGEOUT)) && log->cqueue.head && + (!(tblk->xflag & COMMIT_LAZY) || test_bit(log_FLUSH, &log->flag))) { /* - * only transaction in the commit queue: + * No pageout in progress * - * start one-transaction group commit as - * its group leader. + * start group commit as its group leader. */ log->cflag |= logGC_PAGEOUT; lmGCwrite(log, 0); } + + if (tblk->xflag & COMMIT_LAZY) { + /* + * Lazy transactions can leave now + */ + LOGGC_UNLOCK(log); + return 0; + } + /* lmGCwrite gives up LOGGC_LOCK, check again */ if (tblk->flag & tblkGC_COMMITTED) { @@ -894,11 +895,8 @@ void lmPostGC(struct lbuf * bp) * the first transaction entering group commit * will elect herself as new group leader. */ - else { + else log->cflag &= ~logGC_PAGEOUT; - clear_bit(log_FLUSH, &log->flag); - WARN_ON(log->flush_tblk); - } //LOGGC_UNLOCK(log); spin_unlock_irqrestore(&log->gclock, flags); diff --git a/fs/jfs/jfs_txnmgr.c b/fs/jfs/jfs_txnmgr.c index 13226284c648d..e07b272769983 100644 --- a/fs/jfs/jfs_txnmgr.c +++ b/fs/jfs/jfs_txnmgr.c @@ -518,22 +518,24 @@ void txEnd(tid_t tid) /* * mark the tblock not active */ - --log->active; + if (--log->active == 0) { + clear_bit(log_FLUSH, &log->flag); - /* - * synchronize with logsync barrier - */ - if (test_bit(log_SYNCBARRIER, &log->flag) && log->active == 0) { - /* forward log syncpt */ - /* lmSync(log); */ + /* + * synchronize with logsync barrier + */ + if (test_bit(log_SYNCBARRIER, &log->flag)) { + /* forward log syncpt */ + /* lmSync(log); */ - jfs_info(" log barrier off: 0x%x", log->lsn); + jfs_info("log barrier off: 0x%x", log->lsn); - /* enable new transactions start */ - clear_bit(log_SYNCBARRIER, &log->flag); + /* enable new transactions start */ + clear_bit(log_SYNCBARRIER, &log->flag); - /* wakeup all waitors for logsync barrier */ - TXN_WAKEUP(&log->syncwait); + /* wakeup all waitors for logsync barrier */ + TXN_WAKEUP(&log->syncwait); + } } /* -- 2.53.0