Commit f67406c9 authored by Dave Kleikamp's avatar Dave Kleikamp

JFS: Avoid writing partial log pages for lazy transactions

JFS currently writes a journal page as any transaction is committed, as
long as there is no current journal I/O.  This results in a lot of partial
journal pages being written, even if no threads are waiting for the commit
to complete.  This patch avoids these partial page writes if the transaction
being committed is asynchronous (lazy).  It a couple places, we need to
make sure that the group commit is performed to flush all transactions to
disk.
parent cf9e638b
......@@ -599,21 +599,21 @@ static int lmNextPage(struct jfs_log * log)
/* mark tblk for end-of-page */
tblk->flag |= tblkGC_EOP;
/* if page is not already on write queue,
* just enqueue (no lbmWRITE to prevent redrive)
* buffer to wqueue to ensure correct serial order
* of the pages since log pages will be added
* continuously (tblk bound with the page hasn't
* got around to init write of the page, either
* preempted or the page got filled by its COMMIT
* record);
* pages with COMMIT are paged out explicitly by
* tblk in lmGroupCommit();
*/
if (bp->l_wqnext == NULL) {
/* bp->l_ceor = bp->l_eor; */
/* lp->h.eor = lp->t.eor = bp->l_ceor; */
lbmWrite(log, bp, 0, 0);
if (log->cflag & logGC_PAGEOUT) {
/* if page is not already on write queue,
* just enqueue (no lbmWRITE to prevent redrive)
* buffer to wqueue to ensure correct serial order
* of the pages since log pages will be added
* continuously
*/
if (bp->l_wqnext == NULL)
lbmWrite(log, bp, 0, 0);
} else {
/*
* No current GC leader, initiate group commit
*/
log->cflag |= logGC_PAGEOUT;
lmGCwrite(log, 0);
}
}
/* page is not bound with outstanding tblk:
......@@ -680,10 +680,17 @@ int lmGroupCommit(struct jfs_log * log, struct tblock * tblk)
LOGGC_UNLOCK(log);
return rc;
}
jFYI(1,
("lmGroup Commit: tblk = 0x%p, gcrtc = %d\n", tblk,
log->gcrtc));
jFYI(1, ("lmGroup Commit: tblk = 0x%p, gcrtc = %d\n", tblk,
log->gcrtc));
if (tblk->xflag & COMMIT_LAZY) {
/*
* Lazy transactions can leave now
*/
tblk->flag |= tblkGC_LAZY;
LOGGC_UNLOCK(log);
return 0;
}
/*
* group commit pageout in progress
*/
......@@ -711,12 +718,6 @@ int lmGroupCommit(struct jfs_log * log, struct tblock * tblk)
/* upcount transaction waiting for completion
*/
log->gcrtc++;
if (tblk->xflag & COMMIT_LAZY) {
tblk->flag |= tblkGC_LAZY;
LOGGC_UNLOCK(log);
return 0;
}
tblk->flag |= tblkGC_READY;
__SLEEP_COND(tblk->gcwait, (tblk->flag & tblkGC_COMMITTED),
......@@ -885,11 +886,15 @@ void lmPostGC(struct lbuf * bp)
/* are there any transactions who have entered lnGroupCommit()
* (whose COMMITs are after that of the last log page written.
* They are waiting for new group commit (above at (SLEEP 1)):
* They are waiting for new group commit (above at (SLEEP 1))
* or lazy transactions are on a full (queued) log page,
* select the latest ready transaction as new group leader and
* wake her up to lead her group.
*/
if ((log->gcrtc > 0) && log->cqueue.head)
if ((tblk = log->cqueue.head) &&
((log->gcrtc > 0) || (tblk->bp->l_wqnext != NULL) ||
test_bit(log_SYNCBARRIER, &log->flag) ||
test_bit(log_QUIESCE, &log->flag)))
/*
* Call lmGCwrite with new group leader
*/
......@@ -1046,6 +1051,16 @@ int lmLogSync(struct jfs_log * log, int nosyncwait)
log->syncpt));
}
/*
* We may have to initiate group commit
*/
LOGGC_LOCK(log);
if (log->cqueue.head && !(log->cflag & logGC_PAGEOUT)) {
log->cflag |= logGC_PAGEOUT;
lmGCwrite(log, 0);
}
LOGGC_UNLOCK(log);
return lsn;
}
......@@ -1411,6 +1426,22 @@ void lmLogWait(struct jfs_log *log)
jFYI(1, ("lmLogWait: log:0x%p\n", log));
/*
* This ensures that we will keep writing to the journal as long
* as there are unwritten commit records
*/
set_bit(log_QUIESCE, &log->flag);
/*
* Initiate I/O on outstanding transactions
*/
LOGGC_LOCK(log);
if (log->cqueue.head && !(log->cflag & logGC_PAGEOUT)) {
log->cflag |= logGC_PAGEOUT;
lmGCwrite(log, 0);
}
LOGGC_UNLOCK(log);
if (log->cqueue.head || !list_empty(&log->synclist)) {
/*
* If there was very recent activity, we may need to wait
......@@ -1427,6 +1458,8 @@ void lmLogWait(struct jfs_log *log)
}
assert(log->cqueue.head == NULL);
assert(list_empty(&log->synclist));
clear_bit(log_QUIESCE, &log->flag); /* Probably not needed */
}
/*
......
......@@ -157,7 +157,8 @@ struct {
/*
* external references
*/
extern int lmGroupCommit(struct jfs_log * log, struct tblock * tblk);
extern int lmGroupCommit(struct jfs_log *, struct tblock *);
extern int lmGCwrite(struct jfs_log *, int);
extern void lmSync(struct jfs_log *);
extern int jfs_commit_inode(struct inode *, int);
extern int jfs_stop_threads;
......@@ -2770,7 +2771,7 @@ void txLazyCommit(struct tblock * tblk)
tblk->flag |= tblkGC_COMMITTED;
if ((tblk->flag & tblkGC_READY) || (tblk->flag & tblkGC_LAZY))
if (tblk->flag & tblkGC_READY)
log->gcrtc--;
if (tblk->flag & tblkGC_READY)
......@@ -2976,6 +2977,16 @@ void txQuiesce(struct super_block *sb)
goto restart;
}
TXN_UNLOCK();
/*
* We may need to kick off the group commit
*/
spin_lock_irq(&log->gclock); // LOGGC_LOCK
if (log->cqueue.head && !(log->cflag & logGC_PAGEOUT)) {
log->cflag |= logGC_PAGEOUT;
lmGCwrite(log, 0);
}
spin_unlock_irq(&log->gclock); // LOGGC_UNLOCK
}
/*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment