49 #include <linux/module.h>
83 #ifdef CONFIG_JFS_STATISTICS
87 uint txBegin_lockslow;
90 uint txBeginAnon_barrier;
91 uint txBeginAnon_lockslow;
93 uint txLockAlloc_freelock;
97 static int nTxBlock = -1;
100 "Number of transaction blocks (max:65536)");
102 static int nTxLock = -1;
105 "Number of transaction locks (max:65536)");
108 static int TxLockLWM;
109 static int TxLockHWM;
110 static int TxLockVHWM;
118 #define TXN_LOCK() spin_lock(&jfsTxnLock)
119 #define TXN_UNLOCK() spin_unlock(&jfsTxnLock)
121 #define LAZY_LOCK_INIT() spin_lock_init(&TxAnchor.LazyLock);
122 #define LAZY_LOCK(flags) spin_lock_irqsave(&TxAnchor.LazyLock, flags)
123 #define LAZY_UNLOCK(flags) spin_unlock_irqrestore(&TxAnchor.LazyLock, flags)
126 static int jfs_commit_thread_waking;
143 #define TXN_SLEEP(event)\
145 TXN_SLEEP_DROP_LOCK(event);\
149 #define TXN_WAKEUP(event) wake_up_all(event)
168 struct tlock * tlck);
170 struct tlock * tlck);
172 struct tlock * tlck);
175 static void txForce(
struct tblock * tblk);
178 static void txUpdateMap(
struct tblock * tblk);
179 static void txRelease(
struct tblock * tblk);
181 struct tlock * tlck);
182 static void LogSyncRelease(
struct metapage *
mp);
194 static lid_t txLockAlloc(
void)
199 if (!TxAnchor.freelock) {
203 while (!(lid = TxAnchor.freelock))
205 TxAnchor.freelock = TxLock[
lid].
next;
207 if ((++TxAnchor.tlocksInUse > TxLockHWM) && (
jfs_tlocks_low == 0)) {
216 static void txLockFree(
lid_t lid)
219 TxLock[
lid].
next = TxAnchor.freelock;
220 TxAnchor.freelock =
lid;
221 TxAnchor.tlocksInUse--;
223 jfs_info(
"txLockFree jfs_tlocks_low no more");
247 if (nTxBlock == -1) {
254 }
else if (nTxBlock > (8 * 1024))
257 nTxLock = nTxBlock << 3;
260 nTxBlock = nTxLock >> 3;
265 if (nTxBlock > 65536)
280 TxLockLWM = (nTxLock * 4) / 10;
281 TxLockHWM = (nTxLock * 7) / 10;
282 TxLockVHWM = (nTxLock * 8) / 10;
284 size =
sizeof(
struct tblock) * nTxBlock;
289 for (k = 1; k < nTxBlock - 1; k++) {
290 TxBlock[
k].
next = k + 1;
298 TxAnchor.freetid = 1;
309 size =
sizeof(
struct tlock) * nTxLock;
311 if (TxLock ==
NULL) {
317 for (k = 1; k < nTxLock - 1; k++)
318 TxLock[k].
next = k + 1;
323 TxAnchor.freelock = 1;
324 TxAnchor.tlocksInUse = 0;
325 INIT_LIST_HEAD(&TxAnchor.anon_list);
326 INIT_LIST_HEAD(&TxAnchor.anon_list2);
329 INIT_LIST_HEAD(&TxAnchor.unlock_queue);
368 jfs_info(
"txBegin: flag = 0x%x", flag);
369 log = JFS_SBI(sb)->log;
393 if (TxAnchor.tlocksInUse > TxLockVHWM) {
403 if ((t = TxAnchor.freetid) == 0) {
404 jfs_info(
"txBegin: waiting for free tid");
412 if ((tblk->
next == 0) && !(flag & COMMIT_FORCE)) {
414 jfs_info(
"txBegin: waiting for free tid");
420 TxAnchor.freetid = tblk->
next;
445 jfs_info(
"txBegin: returning tid = %d", t);
465 log = JFS_SBI(sb)->log;
484 if (TxAnchor.tlocksInUse > TxLockVHWM) {
515 log = JFS_SBI(tblk->
sb)->log;
526 jfs_info(
"txEnd called w/lazy tid: %d, tblk = 0x%p", tid, tblk);
529 spin_lock_irq(&log->
gclock);
531 spin_unlock_irq(&log->
gclock);
535 jfs_info(
"txEnd: tid: %d, tblk = 0x%p", tid, tblk);
542 tblk->
next = TxAnchor.freetid;
543 TxAnchor.freetid = tid;
621 jfs_info(
"txLock: tid:%d ip:0x%p mp:0x%p lid:%d", tid, ip, mp, lid);
625 if ((xtid = tlck->
tid) == tid) {
711 metapage_nohomeok(mp);
713 jfs_info(
"locking mp = 0x%p, nohomeok = %d tid = %d tlck = 0x%p",
721 if ((tid == 0) && mp->
lsn)
760 if (tlck->
next == 0) {
765 &TxAnchor.anon_list);
771 linelock = (
struct linelock *) & tlck->
lock;
785 xtlck = (
struct xtlock *) linelock;
795 p = &jfs_ip->i_xtroot;
799 xtlck->
lwm.length = 0;
800 xtlck->
twm.offset = 0;
801 xtlck->
hwm.offset = 0;
815 jfs_err(
"UFO tlock:0x%p", tlck);
838 print_hex_dump(
KERN_ERR,
"Locker's tblock: ",
840 sizeof(
struct tblock), 0);
842 tlck,
sizeof(*tlck), 0);
851 jfs_info(
"txLock: in waitLock, tid = %d, xtid = %d, lid = %d",
855 if (xtid && (tlck->
mp == mp) && (mp->
lid == lid))
859 jfs_info(
"txLock: awakened tid = %d, lid = %d", tid, lid);
877 static void txRelease(
struct tblock * tblk)
885 for (lid = tblk->
next; lid; lid = tlck->
next) {
887 if ((mp = tlck->
mp) !=
NULL &&
909 static void txUnlock(
struct tblock * tblk)
919 jfs_info(
"txUnlock: tblk = 0x%p", tblk);
920 log = JFS_SBI(tblk->
sb)->log;
925 for (lid = tblk->
next; lid; lid = next) {
929 jfs_info(
"unlocking lid = %d, tlck = 0x%p", lid, tlck);
932 if ((mp = tlck->
mp) !=
NULL &&
941 _metapage_homeok(mp);
964 llid = ((
struct linelock *) & tlck->
lock)->next;
1009 lid = txLockAlloc();
1045 if (tlck->
next == 0) {
1049 &TxAnchor.anon_list);
1056 maplock = (
struct maplock *) & tlck->
lock;
1073 struct linelock *linelock;
1078 lid = txLockAlloc();
1084 linelock = (
struct linelock *) tlck;
1088 linelock->
index = 0;
1138 struct inode **iplist,
1152 jfs_info(
"txCommit, tid = %d, flag = %d", tid, flag);
1154 if (isReadOnly(iplist[0])) {
1159 sb = cd.
sb = iplist[0]->
i_sb;
1169 log = JFS_SBI(sb)->log;
1204 for (k = 0; k < cd.
nip; k++) {
1206 for (n = k + 1; n < cd.
nip; n++) {
1208 if (ip->
i_ino > top) {
1216 jfs_ip = JFS_IP(ip);
1264 if (((rc =
diWrite(tid, ip))))
1273 if ((rc = txLog(log, tblk, &cd)))
1304 ((tblk->
u.
ip->i_nlink == 0) &&
1336 if (tblk->
xflag & COMMIT_FORCE)
1351 for (k = 0; k < cd.
nip; k++) {
1353 jfs_ip = JFS_IP(ip);
1367 jfs_info(
"txCommit: tid = %d, returning %d", tid, rc);
1393 for (lid = tblk->
next; lid; lid = tlck->
next) {
1407 xtLog(log, tblk, lrd, tlck);
1411 dtLog(log, tblk, lrd, tlck);
1415 diLog(log, tblk, lrd, tlck, cd);
1419 mapLog(log, tblk, lrd, tlck);
1423 dataLog(log, tblk, lrd, tlck);
1427 jfs_err(
"UFO tlock:0x%p", tlck);
1439 static int diLog(
struct jfs_log * log,
struct tblock * tblk,
struct lrd * lrd,
1500 *pxd = pxdlock->pxd;
1509 jfs_err(
"diLog: UFO type tlck:0x%p", tlck);
1525 nlock = pxdlock->index;
1526 for (
i = 0;
i < nlock;
i++, pxdlock++) {
1552 static int dataLog(
struct jfs_log * log,
struct tblock * tblk,
struct lrd * lrd,
1553 struct tlock * tlck)
1569 if (jfs_dirtable_inline(tlck->
ip)) {
1576 metapage_homeok(mp);
1577 discard_metapage(mp);
1598 static void dtLog(
struct jfs_log * log,
struct tblock * tblk,
struct lrd * lrd,
1599 struct tlock * tlck)
1645 pxdlock->pxd = *pxd;
1685 *pxd = pxdlock->pxd;
1701 static void xtLog(
struct jfs_log * log,
struct tblock * tblk,
struct lrd * lrd,
1702 struct tlock * tlck)
1725 p = &JFS_IP(ip)->i_xtroot;
1735 maplock = (
struct maplock *) & tlck->
lock;
1761 lwm = xtlck->
lwm.offset;
1768 jfs_err(
"xtLog: lwm > next\n");
1773 xadlock->
count = next - lwm;
1785 pxd = xadlock->xdlist = &xtlck->
pxdlock;
1786 for (i = 0; i < xadlock->
count; i++) {
1799 xadlock->xdlist = &p->
xad[lwm];
1802 jfs_info(
"xtLog: alloc ip:0x%p mp:0x%p tlck:0x%p lwm:%d "
1803 "count:%d", tlck->
ip, mp, tlck, lwm, xadlock->
count);
1862 hwm = xtlck->
hwm.offset;
1876 xadlock->
count = hwm - XTENTRYSTART + 1;
1888 pxd = xadlock->xdlist = &xtlck->
pxdlock;
1889 for (i = 0; i < xadlock->
count; i++) {
1905 jfs_info(
"xtLog: free ip:0x%p mp:0x%p count:%d lwm:2",
1906 tlck->
ip, mp, xadlock->
count);
1944 lwm = xtlck->
lwm.offset;
1947 hwm = xtlck->
hwm.offset;
1948 twm = xtlck->
twm.offset;
1970 if (twm == next - 1) {
1999 hwm = xtlck->
hwm.offset;
2004 xtlck->
header.length = hwm - next + 1;
2027 xadlock->xdlist = &p->
xad[
lwm];
2029 jfs_info(
"xtLog: alloc ip:0x%p mp:0x%p count:%d "
2031 tlck->
ip, mp, xadlock->
count, lwm, next);
2039 if (twm == next - 1) {
2046 pxdlock = (
struct pxd_lock *) xadlock;
2051 jfs_info(
"xtLog: truncate ip:0x%p mp:0x%p count:%d "
2052 "hwm:%d", ip, mp, pxdlock->
count, hwm);
2067 xadlock->
count = hwm - next + 1;
2068 xadlock->xdlist = &p->
xad[
next];
2070 jfs_info(
"xtLog: free ip:0x%p mp:0x%p count:%d "
2072 tlck->
ip, mp, xadlock->
count, next, hwm);
2087 static void mapLog(
struct jfs_log * log,
struct tblock * tblk,
struct lrd * lrd,
2088 struct tlock * tlck)
2108 *pxd = pxdlock->pxd;
2146 nlock = pxdlock->index;
2147 for (i = 0; i < nlock; i++, pxdlock++) {
2158 jfs_info(
"mapLog: xaddr:0x%lx xlen:0x%x",
2190 pxdlock = (
struct pxd_lock *) maplock;
2210 pxdlock = (
struct pxd_lock *) maplock;
2226 static void txForce(
struct tblock * tblk)
2252 for (lid = tblk->
next; lid; lid = next) {
2256 if ((mp = tlck->
mp) !=
NULL &&
2294 static void txUpdateMap(
struct tblock * tblk)
2297 struct inode *ipimap;
2300 struct maplock *maplock;
2306 ipimap = JFS_SBI(tblk->
sb)->ipimap;
2323 for (lid = tblk->
next; lid; lid = tlck->
next) {
2347 maplock = (
struct maplock *) & tlck->
lock;
2348 nlock = maplock->
index;
2350 for (k = 0; k < nlock; k++, maplock++) {
2357 txAllocPMap(ipimap, maplock, tblk);
2390 metapage_homeok(mp);
2391 discard_metapage(mp);
2410 pxdlock.pxd = tblk->
u.
ixpxd;
2412 txAllocPMap(ipimap, (
struct maplock *) & pxdlock, tblk);
2440 static void txAllocPMap(
struct inode *ip,
struct maplock * maplock,
2443 struct inode *ipbmap = JFS_SBI(ip->
i_sb)->ipbmap;
2458 xad = xadlistlock->xdlist;
2459 for (n = 0; n < xadlistlock->
count; n++, xad++) {
2466 jfs_info(
"allocPMap: xaddr:0x%lx xlen:%d",
2467 (
ulong) xaddr, xlen);
2471 pxdlock = (
struct pxd_lock *) maplock;
2475 jfs_info(
"allocPMap: xaddr:0x%lx xlen:%d", (
ulong) xaddr, xlen);
2479 pxd = pxdlistlock->xdlist;
2480 for (n = 0; n < pxdlistlock->
count; n++, pxd++) {
2485 jfs_info(
"allocPMap: xaddr:0x%lx xlen:%d",
2486 (
ulong) xaddr, xlen);
2499 struct maplock * maplock,
struct tblock * tblk,
int maptype)
2501 struct inode *ipbmap = JFS_SBI(ip->
i_sb)->ipbmap;
2511 jfs_info(
"txFreeMap: tblk:0x%p maplock:0x%p maptype:0x%x",
2512 tblk, maplock, maptype);
2520 xad = xadlistlock->xdlist;
2521 for (n = 0; n < xadlistlock->
count; n++, xad++) {
2529 (
ulong) xaddr, xlen);
2533 pxdlock = (
struct pxd_lock *) maplock;
2538 jfs_info(
"freePMap: xaddr:0x%lx xlen:%d",
2539 (
ulong) xaddr, xlen);
2543 pxd = pxdlistlock->xdlist;
2544 for (n = 0; n < pxdlistlock->
count; n++, pxd++) {
2549 jfs_info(
"freePMap: xaddr:0x%lx xlen:%d",
2550 (
ulong) xaddr, xlen);
2561 xad = xadlistlock->xdlist;
2562 for (n = 0; n < xadlistlock->
count; n++, xad++) {
2567 jfs_info(
"freeWMap: xaddr:0x%lx xlen:%d",
2568 (
ulong) xaddr, xlen);
2571 pxdlock = (
struct pxd_lock *) maplock;
2575 jfs_info(
"freeWMap: xaddr:0x%lx xlen:%d",
2576 (
ulong) xaddr, xlen);
2580 pxd = pxdlistlock->xdlist;
2581 for (n = 0; n < pxdlistlock->
count; n++, pxd++) {
2585 jfs_info(
"freeWMap: xaddr:0x%lx xlen:%d",
2586 (
ulong) xaddr, xlen);
2600 struct tlock *xtlck, *tlck;
2609 while ((lid = xtlck->
next) != 0) {
2653 for (lid = tblk->
next; lid; lid = next) {
2657 JFS_IP(tlck->
ip)->xtlid = 0;
2700 static void txLazyCommit(
struct tblock * tblk)
2708 jfs_info(
"jfs_lazycommit: tblk 0x%p not unlocked", tblk);
2712 jfs_info(
"txLazyCommit: processing tblk 0x%p", tblk);
2716 log = (
struct jfs_log *) JFS_SBI(tblk->
sb)->log;
2718 spin_lock_irq(&log->
gclock);
2731 spin_unlock_irq(&log->
gclock);
2734 txEnd(tblk - TxBlock);
2736 spin_unlock_irq(&log->
gclock);
2738 jfs_info(
"txLazyCommit: done: tblk = 0x%p", tblk);
2752 unsigned long flags;
2757 jfs_commit_thread_waking = 0;
2758 while (!list_empty(&TxAnchor.unlock_queue)) {
2763 sbi = JFS_SBI(tblk->
sb);
2799 jfs_commit_thread_waking = 0;
2816 if (!list_empty(&TxAnchor.unlock_queue))
2817 jfs_err(
"jfs_lazycommit being killed w/pending transactions!");
2819 jfs_info(
"jfs_lazycommit being killed\n");
2825 unsigned long flags;
2835 !jfs_commit_thread_waking) {
2836 jfs_commit_thread_waking = 1;
2837 wake_up(&jfs_commit_thread_wait);
2842 static void LogSyncRelease(
struct metapage * mp)
2848 metapage_homeok(mp);
2865 struct jfs_log *log = JFS_SBI(sb)->log;
2872 while (!list_empty(&TxAnchor.anon_list)) {
2900 if (!list_empty(&TxAnchor.anon_list2)) {
2901 list_splice(&TxAnchor.anon_list2, &TxAnchor.anon_list);
2902 INIT_LIST_HEAD(&TxAnchor.anon_list2);
2920 struct jfs_log *log = JFS_SBI(sb)->log;
2982 &TxAnchor.anon_list2);
2990 list_splice_init(&TxAnchor.anon_list2, &TxAnchor.anon_list);
3007 #if defined(CONFIG_PROC_FS) && defined(CONFIG_JFS_DEBUG)
3008 static int jfs_txanchor_proc_show(
struct seq_file *
m,
void *
v)
3015 waitqueue_active(&TxAnchor.freewait) ?
"active" :
"empty";
3017 waitqueue_active(&TxAnchor.freelockwait) ?
"active" :
"empty";
3019 waitqueue_active(&TxAnchor.lowlockwait) ?
"active" :
"empty";
3027 "freelockwait = %s\n"
3028 "lowlockwait = %s\n"
3029 "tlocksInUse = %d\n"
3030 "jfs_tlocks_low = %d\n"
3031 "unlock_queue is %sempty\n",
3037 TxAnchor.tlocksInUse,
3039 list_empty(&TxAnchor.unlock_queue) ?
"" :
"not ");
3050 .open = jfs_txanchor_proc_open,
3057 #if defined(CONFIG_PROC_FS) && defined(CONFIG_JFS_STATISTICS)
3058 static int jfs_txstats_proc_show(
struct seq_file *m,
void *v)
3063 "calls to txBegin = %d\n"
3064 "txBegin blocked by sync barrier = %d\n"
3065 "txBegin blocked by tlocks low = %d\n"
3066 "txBegin blocked by no free tid = %d\n"
3067 "calls to txBeginAnon = %d\n"
3068 "txBeginAnon blocked by sync barrier = %d\n"
3069 "txBeginAnon blocked by tlocks low = %d\n"
3070 "calls to txLockAlloc = %d\n"
3071 "tLockAlloc blocked by no free lock = %d\n",
3073 TxStat.txBegin_barrier,
3074 TxStat.txBegin_lockslow,
3075 TxStat.txBegin_freetid,
3077 TxStat.txBeginAnon_barrier,
3078 TxStat.txBeginAnon_lockslow,
3080 TxStat.txLockAlloc_freelock);
3091 .open = jfs_txstats_proc_open,