aboutsummaryrefslogtreecommitdiffstats
path: root/fs/jfs/jfs_txnmgr.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/jfs/jfs_txnmgr.c')
-rw-r--r--fs/jfs/jfs_txnmgr.c166
1 files changed, 89 insertions, 77 deletions
diff --git a/fs/jfs/jfs_txnmgr.c b/fs/jfs/jfs_txnmgr.c
index f40301d93f74..e93d01aa12c4 100644
--- a/fs/jfs/jfs_txnmgr.c
+++ b/fs/jfs/jfs_txnmgr.c
@@ -227,6 +227,7 @@ static lid_t txLockAlloc(void)
static void txLockFree(lid_t lid)
{
+ TxLock[lid].tid = 0;
TxLock[lid].next = TxAnchor.freelock;
TxAnchor.freelock = lid;
TxAnchor.tlocksInUse--;
@@ -566,9 +567,6 @@ void txEnd(tid_t tid)
* 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);
/* enable new transactions start */
@@ -576,15 +574,22 @@ void txEnd(tid_t tid)
/* wakeup all waitors for logsync barrier */
TXN_WAKEUP(&log->syncwait);
+
+ TXN_UNLOCK();
+
+ /* forward log syncpt */
+ jfs_syncpt(log);
+
+ goto wakeup;
}
}
+ TXN_UNLOCK();
+wakeup:
/*
* wakeup all waitors for a free tblock
*/
TXN_WAKEUP(&TxAnchor.freewait);
-
- TXN_UNLOCK();
}
@@ -633,8 +638,10 @@ struct tlock *txLock(tid_t tid, struct inode *ip, struct metapage * mp,
/* is page locked by the requester transaction ? */
tlck = lid_to_tlock(lid);
- if ((xtid = tlck->tid) == tid)
+ if ((xtid = tlck->tid) == tid) {
+ TXN_UNLOCK();
goto grantLock;
+ }
/*
* is page locked by anonymous transaction/lock ?
@@ -649,6 +656,7 @@ struct tlock *txLock(tid_t tid, struct inode *ip, struct metapage * mp,
*/
if (xtid == 0) {
tlck->tid = tid;
+ TXN_UNLOCK();
tblk = tid_to_tblock(tid);
/*
* The order of the tlocks in the transaction is important
@@ -706,17 +714,18 @@ struct tlock *txLock(tid_t tid, struct inode *ip, struct metapage * mp,
*/
tlck->tid = tid;
+ TXN_UNLOCK();
+
/* mark tlock for meta-data page */
if (mp->xflag & COMMIT_PAGE) {
tlck->flag = tlckPAGELOCK;
/* mark the page dirty and nohomeok */
- mark_metapage_dirty(mp);
- atomic_inc(&mp->nohomeok);
+ metapage_nohomeok(mp);
jfs_info("locking mp = 0x%p, nohomeok = %d tid = %d tlck = 0x%p",
- mp, atomic_read(&mp->nohomeok), tid, tlck);
+ mp, mp->nohomeok, tid, tlck);
/* if anonymous transaction, and buffer is on the group
* commit synclist, mark inode to show this. This will
@@ -762,8 +771,10 @@ struct tlock *txLock(tid_t tid, struct inode *ip, struct metapage * mp,
if (tlck->next == 0) {
/* This inode's first anonymous transaction */
jfs_ip->atltail = lid;
+ TXN_LOCK();
list_add_tail(&jfs_ip->anon_inode_list,
&TxAnchor.anon_list);
+ TXN_UNLOCK();
}
}
@@ -821,8 +832,6 @@ struct tlock *txLock(tid_t tid, struct inode *ip, struct metapage * mp,
grantLock:
tlck->type |= type;
- TXN_UNLOCK();
-
return tlck;
/*
@@ -841,11 +850,19 @@ struct tlock *txLock(tid_t tid, struct inode *ip, struct metapage * mp,
BUG();
}
INCREMENT(stattx.waitlock); /* statistics */
+ TXN_UNLOCK();
release_metapage(mp);
+ TXN_LOCK();
+ xtid = tlck->tid; /* reaquire after dropping TXN_LOCK */
jfs_info("txLock: in waitLock, tid = %d, xtid = %d, lid = %d",
tid, xtid, lid);
- TXN_SLEEP_DROP_LOCK(&tid_to_tblock(xtid)->waitor);
+
+ /* Recheck everything since dropping TXN_LOCK */
+ if (xtid && (tlck->mp == mp) && (mp->lid == lid))
+ TXN_SLEEP_DROP_LOCK(&tid_to_tblock(xtid)->waitor);
+ else
+ TXN_UNLOCK();
jfs_info("txLock: awakened tid = %d, lid = %d", tid, lid);
return NULL;
@@ -906,6 +923,7 @@ static void txUnlock(struct tblock * tblk)
struct metapage *mp;
struct jfs_log *log;
int difft, diffp;
+ unsigned long flags;
jfs_info("txUnlock: tblk = 0x%p", tblk);
log = JFS_SBI(tblk->sb)->log;
@@ -925,19 +943,14 @@ static void txUnlock(struct tblock * tblk)
assert(mp->xflag & COMMIT_PAGE);
/* hold buffer
- *
- * It's possible that someone else has the metapage.
- * The only things were changing are nohomeok, which
- * is handled atomically, and clsn which is protected
- * by the LOGSYNC_LOCK.
*/
- hold_metapage(mp, 1);
+ hold_metapage(mp);
- assert(atomic_read(&mp->nohomeok) > 0);
- atomic_dec(&mp->nohomeok);
+ assert(mp->nohomeok > 0);
+ _metapage_homeok(mp);
/* inherit younger/larger clsn */
- LOGSYNC_LOCK(log);
+ LOGSYNC_LOCK(log, flags);
if (mp->clsn) {
logdiff(difft, tblk->clsn, log);
logdiff(diffp, mp->clsn, log);
@@ -945,16 +958,11 @@ static void txUnlock(struct tblock * tblk)
mp->clsn = tblk->clsn;
} else
mp->clsn = tblk->clsn;
- LOGSYNC_UNLOCK(log);
+ LOGSYNC_UNLOCK(log, flags);
assert(!(tlck->flag & tlckFREEPAGE));
- if (tlck->flag & tlckWRITEPAGE) {
- write_metapage(mp);
- } else {
- /* release page which has been forced */
- release_metapage(mp);
- }
+ put_metapage(mp);
}
/* insert tlock, and linelock(s) of the tlock if any,
@@ -981,10 +989,10 @@ static void txUnlock(struct tblock * tblk)
* has been inserted in logsync list at txUpdateMap())
*/
if (tblk->lsn) {
- LOGSYNC_LOCK(log);
+ LOGSYNC_LOCK(log, flags);
log->count--;
list_del(&tblk->synclist);
- LOGSYNC_UNLOCK(log);
+ LOGSYNC_UNLOCK(log, flags);
}
}
@@ -1573,8 +1581,8 @@ static int dataLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
* the last entry, so don't bother logging this
*/
mp->lid = 0;
- hold_metapage(mp, 0);
- atomic_dec(&mp->nohomeok);
+ grab_metapage(mp);
+ metapage_homeok(mp);
discard_metapage(mp);
tlck->mp = NULL;
return 0;
@@ -1712,7 +1720,7 @@ static void xtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
struct maplock *maplock;
struct xdlistlock *xadlock;
struct pxd_lock *pxdlock;
- pxd_t *pxd;
+ pxd_t *page_pxd;
int next, lwm, hwm;
ip = tlck->ip;
@@ -1722,7 +1730,7 @@ static void xtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
lrd->log.redopage.type = cpu_to_le16(LOG_XTREE);
lrd->log.redopage.l2linesize = cpu_to_le16(L2XTSLOTSIZE);
- pxd = &lrd->log.redopage.pxd;
+ page_pxd = &lrd->log.redopage.pxd;
if (tlck->type & tlckBTROOT) {
lrd->log.redopage.type |= cpu_to_le16(LOG_BTROOT);
@@ -1752,9 +1760,9 @@ static void xtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
* applying the after-image to the meta-data page.
*/
lrd->type = cpu_to_le16(LOG_REDOPAGE);
-// *pxd = mp->cm_pxd;
- PXDaddress(pxd, mp->index);
- PXDlength(pxd,
+// *page_pxd = mp->cm_pxd;
+ PXDaddress(page_pxd, mp->index);
+ PXDlength(page_pxd,
mp->logical_size >> tblk->sb->s_blocksize_bits);
lrd->backchain = cpu_to_le32(lmLog(log, tblk, lrd, tlck));
@@ -1776,25 +1784,31 @@ static void xtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
tlck->flag |= tlckUPDATEMAP;
xadlock->flag = mlckALLOCXADLIST;
xadlock->count = next - lwm;
- if ((xadlock->count <= 2) && (tblk->xflag & COMMIT_LAZY)) {
+ if ((xadlock->count <= 4) && (tblk->xflag & COMMIT_LAZY)) {
int i;
+ pxd_t *pxd;
/*
* Lazy commit may allow xtree to be modified before
* txUpdateMap runs. Copy xad into linelock to
* preserve correct data.
+ *
+ * We can fit twice as may pxd's as xads in the lock
*/
- xadlock->xdlist = &xtlck->pxdlock;
- memcpy(xadlock->xdlist, &p->xad[lwm],
- sizeof(xad_t) * xadlock->count);
-
- for (i = 0; i < xadlock->count; i++)
+ xadlock->flag = mlckALLOCPXDLIST;
+ pxd = xadlock->xdlist = &xtlck->pxdlock;
+ for (i = 0; i < xadlock->count; i++) {
+ PXDaddress(pxd, addressXAD(&p->xad[lwm + i]));
+ PXDlength(pxd, lengthXAD(&p->xad[lwm + i]));
p->xad[lwm + i].flag &=
~(XAD_NEW | XAD_EXTENDED);
+ pxd++;
+ }
} else {
/*
* xdlist will point to into inode's xtree, ensure
* that transaction is not committed lazily.
*/
+ xadlock->flag = mlckALLOCXADLIST;
xadlock->xdlist = &p->xad[lwm];
tblk->xflag &= ~COMMIT_LAZY;
}
@@ -1836,8 +1850,8 @@ static void xtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
if (tblk->xflag & COMMIT_TRUNCATE) {
/* write NOREDOPAGE for the page */
lrd->type = cpu_to_le16(LOG_NOREDOPAGE);
- PXDaddress(pxd, mp->index);
- PXDlength(pxd,
+ PXDaddress(page_pxd, mp->index);
+ PXDlength(page_pxd,
mp->logical_size >> tblk->sb->
s_blocksize_bits);
lrd->backchain =
@@ -1872,22 +1886,32 @@ static void xtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
* deleted page itself;
*/
tlck->flag |= tlckUPDATEMAP;
- xadlock->flag = mlckFREEXADLIST;
xadlock->count = hwm - XTENTRYSTART + 1;
- if ((xadlock->count <= 2) && (tblk->xflag & COMMIT_LAZY)) {
+ if ((xadlock->count <= 4) && (tblk->xflag & COMMIT_LAZY)) {
+ int i;
+ pxd_t *pxd;
/*
* Lazy commit may allow xtree to be modified before
* txUpdateMap runs. Copy xad into linelock to
* preserve correct data.
+ *
+ * We can fit twice as may pxd's as xads in the lock
*/
- xadlock->xdlist = &xtlck->pxdlock;
- memcpy(xadlock->xdlist, &p->xad[XTENTRYSTART],
- sizeof(xad_t) * xadlock->count);
+ xadlock->flag = mlckFREEPXDLIST;
+ pxd = xadlock->xdlist = &xtlck->pxdlock;
+ for (i = 0; i < xadlock->count; i++) {
+ PXDaddress(pxd,
+ addressXAD(&p->xad[XTENTRYSTART + i]));
+ PXDlength(pxd,
+ lengthXAD(&p->xad[XTENTRYSTART + i]));
+ pxd++;
+ }
} else {
/*
* xdlist will point to into inode's xtree, ensure
* that transaction is not committed lazily.
*/
+ xadlock->flag = mlckFREEXADLIST;
xadlock->xdlist = &p->xad[XTENTRYSTART];
tblk->xflag &= ~COMMIT_LAZY;
}
@@ -1918,7 +1942,7 @@ static void xtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
* header ?
*/
if (tlck->type & tlckTRUNCATE) {
- pxd_t tpxd; /* truncated extent of xad */
+ pxd_t pxd; /* truncated extent of xad */
int twm;
/*
@@ -1947,8 +1971,9 @@ static void xtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
* applying the after-image to the meta-data page.
*/
lrd->type = cpu_to_le16(LOG_REDOPAGE);
- PXDaddress(pxd, mp->index);
- PXDlength(pxd, mp->logical_size >> tblk->sb->s_blocksize_bits);
+ PXDaddress(page_pxd, mp->index);
+ PXDlength(page_pxd,
+ mp->logical_size >> tblk->sb->s_blocksize_bits);
lrd->backchain = cpu_to_le32(lmLog(log, tblk, lrd, tlck));
/*
@@ -1966,7 +1991,7 @@ static void xtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
lrd->log.updatemap.type = cpu_to_le16(LOG_FREEPXD);
lrd->log.updatemap.nxd = cpu_to_le16(1);
lrd->log.updatemap.pxd = pxdlock->pxd;
- tpxd = pxdlock->pxd; /* save to format maplock */
+ pxd = pxdlock->pxd; /* save to format maplock */
lrd->backchain =
cpu_to_le32(lmLog(log, tblk, lrd, NULL));
}
@@ -2035,7 +2060,7 @@ static void xtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
pxdlock = (struct pxd_lock *) xadlock;
pxdlock->flag = mlckFREEPXD;
pxdlock->count = 1;
- pxdlock->pxd = tpxd;
+ pxdlock->pxd = pxd;
jfs_info("xtLog: truncate ip:0x%p mp:0x%p count:%d "
"hwm:%d", ip, mp, pxdlock->count, hwm);
@@ -2253,7 +2278,8 @@ void txForce(struct tblock * tblk)
tlck->flag &= ~tlckWRITEPAGE;
/* do not release page to freelist */
-
+ force_metapage(mp);
+#if 0
/*
* The "right" thing to do here is to
* synchronously write the metadata.
@@ -2265,9 +2291,10 @@ void txForce(struct tblock * tblk)
* we can get by with synchronously writing
* the pages when they are released.
*/
- assert(atomic_read(&mp->nohomeok));
+ assert(mp->nohomeok);
set_bit(META_dirty, &mp->flag);
set_bit(META_sync, &mp->flag);
+#endif
}
}
}
@@ -2327,7 +2354,7 @@ static void txUpdateMap(struct tblock * tblk)
*/
mp = tlck->mp;
ASSERT(mp->xflag & COMMIT_PAGE);
- hold_metapage(mp, 0);
+ grab_metapage(mp);
}
/*
@@ -2377,8 +2404,8 @@ static void txUpdateMap(struct tblock * tblk)
ASSERT(mp->lid == lid);
tlck->mp->lid = 0;
}
- assert(atomic_read(&mp->nohomeok) == 1);
- atomic_dec(&mp->nohomeok);
+ assert(mp->nohomeok == 1);
+ metapage_homeok(mp);
discard_metapage(mp);
tlck->mp = NULL;
}
@@ -2844,24 +2871,9 @@ static void LogSyncRelease(struct metapage * mp)
{
struct jfs_log *log = mp->log;
- assert(atomic_read(&mp->nohomeok));
+ assert(mp->nohomeok);
assert(log);
- atomic_dec(&mp->nohomeok);
-
- if (atomic_read(&mp->nohomeok))
- return;
-
- hold_metapage(mp, 0);
-
- LOGSYNC_LOCK(log);
- mp->log = NULL;
- mp->lsn = 0;
- mp->clsn = 0;
- log->count--;
- list_del_init(&mp->synclist);
- LOGSYNC_UNLOCK(log);
-
- release_metapage(mp);
+ metapage_homeok(mp);
}
/*