diff options
Diffstat (limited to 'fs/jfs/jfs_txnmgr.c')
-rw-r--r-- | fs/jfs/jfs_txnmgr.c | 89 |
1 files changed, 40 insertions, 49 deletions
diff --git a/fs/jfs/jfs_txnmgr.c b/fs/jfs/jfs_txnmgr.c index 98e16d93e146..bbc9c1407b55 100644 --- a/fs/jfs/jfs_txnmgr.c +++ b/fs/jfs/jfs_txnmgr.c | |||
@@ -227,6 +227,7 @@ static lid_t txLockAlloc(void) | |||
227 | 227 | ||
228 | static void txLockFree(lid_t lid) | 228 | static void txLockFree(lid_t lid) |
229 | { | 229 | { |
230 | TxLock[lid].tid = 0; | ||
230 | TxLock[lid].next = TxAnchor.freelock; | 231 | TxLock[lid].next = TxAnchor.freelock; |
231 | TxAnchor.freelock = lid; | 232 | TxAnchor.freelock = lid; |
232 | TxAnchor.tlocksInUse--; | 233 | TxAnchor.tlocksInUse--; |
@@ -633,8 +634,10 @@ struct tlock *txLock(tid_t tid, struct inode *ip, struct metapage * mp, | |||
633 | 634 | ||
634 | /* is page locked by the requester transaction ? */ | 635 | /* is page locked by the requester transaction ? */ |
635 | tlck = lid_to_tlock(lid); | 636 | tlck = lid_to_tlock(lid); |
636 | if ((xtid = tlck->tid) == tid) | 637 | if ((xtid = tlck->tid) == tid) { |
638 | TXN_UNLOCK(); | ||
637 | goto grantLock; | 639 | goto grantLock; |
640 | } | ||
638 | 641 | ||
639 | /* | 642 | /* |
640 | * is page locked by anonymous transaction/lock ? | 643 | * is page locked by anonymous transaction/lock ? |
@@ -649,6 +652,7 @@ struct tlock *txLock(tid_t tid, struct inode *ip, struct metapage * mp, | |||
649 | */ | 652 | */ |
650 | if (xtid == 0) { | 653 | if (xtid == 0) { |
651 | tlck->tid = tid; | 654 | tlck->tid = tid; |
655 | TXN_UNLOCK(); | ||
652 | tblk = tid_to_tblock(tid); | 656 | tblk = tid_to_tblock(tid); |
653 | /* | 657 | /* |
654 | * The order of the tlocks in the transaction is important | 658 | * The order of the tlocks in the transaction is important |
@@ -706,17 +710,18 @@ struct tlock *txLock(tid_t tid, struct inode *ip, struct metapage * mp, | |||
706 | */ | 710 | */ |
707 | tlck->tid = tid; | 711 | tlck->tid = tid; |
708 | 712 | ||
713 | TXN_UNLOCK(); | ||
714 | |||
709 | /* mark tlock for meta-data page */ | 715 | /* mark tlock for meta-data page */ |
710 | if (mp->xflag & COMMIT_PAGE) { | 716 | if (mp->xflag & COMMIT_PAGE) { |
711 | 717 | ||
712 | tlck->flag = tlckPAGELOCK; | 718 | tlck->flag = tlckPAGELOCK; |
713 | 719 | ||
714 | /* mark the page dirty and nohomeok */ | 720 | /* mark the page dirty and nohomeok */ |
715 | mark_metapage_dirty(mp); | 721 | metapage_nohomeok(mp); |
716 | atomic_inc(&mp->nohomeok); | ||
717 | 722 | ||
718 | jfs_info("locking mp = 0x%p, nohomeok = %d tid = %d tlck = 0x%p", | 723 | jfs_info("locking mp = 0x%p, nohomeok = %d tid = %d tlck = 0x%p", |
719 | mp, atomic_read(&mp->nohomeok), tid, tlck); | 724 | mp, mp->nohomeok, tid, tlck); |
720 | 725 | ||
721 | /* if anonymous transaction, and buffer is on the group | 726 | /* if anonymous transaction, and buffer is on the group |
722 | * commit synclist, mark inode to show this. This will | 727 | * commit synclist, mark inode to show this. This will |
@@ -762,8 +767,10 @@ struct tlock *txLock(tid_t tid, struct inode *ip, struct metapage * mp, | |||
762 | if (tlck->next == 0) { | 767 | if (tlck->next == 0) { |
763 | /* This inode's first anonymous transaction */ | 768 | /* This inode's first anonymous transaction */ |
764 | jfs_ip->atltail = lid; | 769 | jfs_ip->atltail = lid; |
770 | TXN_LOCK(); | ||
765 | list_add_tail(&jfs_ip->anon_inode_list, | 771 | list_add_tail(&jfs_ip->anon_inode_list, |
766 | &TxAnchor.anon_list); | 772 | &TxAnchor.anon_list); |
773 | TXN_UNLOCK(); | ||
767 | } | 774 | } |
768 | } | 775 | } |
769 | 776 | ||
@@ -821,8 +828,6 @@ struct tlock *txLock(tid_t tid, struct inode *ip, struct metapage * mp, | |||
821 | grantLock: | 828 | grantLock: |
822 | tlck->type |= type; | 829 | tlck->type |= type; |
823 | 830 | ||
824 | TXN_UNLOCK(); | ||
825 | |||
826 | return tlck; | 831 | return tlck; |
827 | 832 | ||
828 | /* | 833 | /* |
@@ -841,11 +846,19 @@ struct tlock *txLock(tid_t tid, struct inode *ip, struct metapage * mp, | |||
841 | BUG(); | 846 | BUG(); |
842 | } | 847 | } |
843 | INCREMENT(stattx.waitlock); /* statistics */ | 848 | INCREMENT(stattx.waitlock); /* statistics */ |
849 | TXN_UNLOCK(); | ||
844 | release_metapage(mp); | 850 | release_metapage(mp); |
851 | TXN_LOCK(); | ||
852 | xtid = tlck->tid; /* reaquire after dropping TXN_LOCK */ | ||
845 | 853 | ||
846 | jfs_info("txLock: in waitLock, tid = %d, xtid = %d, lid = %d", | 854 | jfs_info("txLock: in waitLock, tid = %d, xtid = %d, lid = %d", |
847 | tid, xtid, lid); | 855 | tid, xtid, lid); |
848 | TXN_SLEEP_DROP_LOCK(&tid_to_tblock(xtid)->waitor); | 856 | |
857 | /* Recheck everything since dropping TXN_LOCK */ | ||
858 | if (xtid && (tlck->mp == mp) && (mp->lid == lid)) | ||
859 | TXN_SLEEP_DROP_LOCK(&tid_to_tblock(xtid)->waitor); | ||
860 | else | ||
861 | TXN_UNLOCK(); | ||
849 | jfs_info("txLock: awakened tid = %d, lid = %d", tid, lid); | 862 | jfs_info("txLock: awakened tid = %d, lid = %d", tid, lid); |
850 | 863 | ||
851 | return NULL; | 864 | return NULL; |
@@ -906,6 +919,7 @@ static void txUnlock(struct tblock * tblk) | |||
906 | struct metapage *mp; | 919 | struct metapage *mp; |
907 | struct jfs_log *log; | 920 | struct jfs_log *log; |
908 | int difft, diffp; | 921 | int difft, diffp; |
922 | unsigned long flags; | ||
909 | 923 | ||
910 | jfs_info("txUnlock: tblk = 0x%p", tblk); | 924 | jfs_info("txUnlock: tblk = 0x%p", tblk); |
911 | log = JFS_SBI(tblk->sb)->log; | 925 | log = JFS_SBI(tblk->sb)->log; |
@@ -925,19 +939,14 @@ static void txUnlock(struct tblock * tblk) | |||
925 | assert(mp->xflag & COMMIT_PAGE); | 939 | assert(mp->xflag & COMMIT_PAGE); |
926 | 940 | ||
927 | /* hold buffer | 941 | /* hold buffer |
928 | * | ||
929 | * It's possible that someone else has the metapage. | ||
930 | * The only things were changing are nohomeok, which | ||
931 | * is handled atomically, and clsn which is protected | ||
932 | * by the LOGSYNC_LOCK. | ||
933 | */ | 942 | */ |
934 | hold_metapage(mp, 1); | 943 | hold_metapage(mp); |
935 | 944 | ||
936 | assert(atomic_read(&mp->nohomeok) > 0); | 945 | assert(mp->nohomeok > 0); |
937 | atomic_dec(&mp->nohomeok); | 946 | _metapage_homeok(mp); |
938 | 947 | ||
939 | /* inherit younger/larger clsn */ | 948 | /* inherit younger/larger clsn */ |
940 | LOGSYNC_LOCK(log); | 949 | LOGSYNC_LOCK(log, flags); |
941 | if (mp->clsn) { | 950 | if (mp->clsn) { |
942 | logdiff(difft, tblk->clsn, log); | 951 | logdiff(difft, tblk->clsn, log); |
943 | logdiff(diffp, mp->clsn, log); | 952 | logdiff(diffp, mp->clsn, log); |
@@ -945,16 +954,11 @@ static void txUnlock(struct tblock * tblk) | |||
945 | mp->clsn = tblk->clsn; | 954 | mp->clsn = tblk->clsn; |
946 | } else | 955 | } else |
947 | mp->clsn = tblk->clsn; | 956 | mp->clsn = tblk->clsn; |
948 | LOGSYNC_UNLOCK(log); | 957 | LOGSYNC_UNLOCK(log, flags); |
949 | 958 | ||
950 | assert(!(tlck->flag & tlckFREEPAGE)); | 959 | assert(!(tlck->flag & tlckFREEPAGE)); |
951 | 960 | ||
952 | if (tlck->flag & tlckWRITEPAGE) { | 961 | put_metapage(mp); |
953 | write_metapage(mp); | ||
954 | } else { | ||
955 | /* release page which has been forced */ | ||
956 | release_metapage(mp); | ||
957 | } | ||
958 | } | 962 | } |
959 | 963 | ||
960 | /* insert tlock, and linelock(s) of the tlock if any, | 964 | /* insert tlock, and linelock(s) of the tlock if any, |
@@ -981,10 +985,10 @@ static void txUnlock(struct tblock * tblk) | |||
981 | * has been inserted in logsync list at txUpdateMap()) | 985 | * has been inserted in logsync list at txUpdateMap()) |
982 | */ | 986 | */ |
983 | if (tblk->lsn) { | 987 | if (tblk->lsn) { |
984 | LOGSYNC_LOCK(log); | 988 | LOGSYNC_LOCK(log, flags); |
985 | log->count--; | 989 | log->count--; |
986 | list_del(&tblk->synclist); | 990 | list_del(&tblk->synclist); |
987 | LOGSYNC_UNLOCK(log); | 991 | LOGSYNC_UNLOCK(log, flags); |
988 | } | 992 | } |
989 | } | 993 | } |
990 | 994 | ||
@@ -1573,8 +1577,8 @@ static int dataLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd, | |||
1573 | * the last entry, so don't bother logging this | 1577 | * the last entry, so don't bother logging this |
1574 | */ | 1578 | */ |
1575 | mp->lid = 0; | 1579 | mp->lid = 0; |
1576 | hold_metapage(mp, 0); | 1580 | grab_metapage(mp); |
1577 | atomic_dec(&mp->nohomeok); | 1581 | metapage_homeok(mp); |
1578 | discard_metapage(mp); | 1582 | discard_metapage(mp); |
1579 | tlck->mp = NULL; | 1583 | tlck->mp = NULL; |
1580 | return 0; | 1584 | return 0; |
@@ -2270,7 +2274,8 @@ void txForce(struct tblock * tblk) | |||
2270 | tlck->flag &= ~tlckWRITEPAGE; | 2274 | tlck->flag &= ~tlckWRITEPAGE; |
2271 | 2275 | ||
2272 | /* do not release page to freelist */ | 2276 | /* do not release page to freelist */ |
2273 | 2277 | force_metapage(mp); | |
2278 | #if 0 | ||
2274 | /* | 2279 | /* |
2275 | * The "right" thing to do here is to | 2280 | * The "right" thing to do here is to |
2276 | * synchronously write the metadata. | 2281 | * synchronously write the metadata. |
@@ -2282,9 +2287,10 @@ void txForce(struct tblock * tblk) | |||
2282 | * we can get by with synchronously writing | 2287 | * we can get by with synchronously writing |
2283 | * the pages when they are released. | 2288 | * the pages when they are released. |
2284 | */ | 2289 | */ |
2285 | assert(atomic_read(&mp->nohomeok)); | 2290 | assert(mp->nohomeok); |
2286 | set_bit(META_dirty, &mp->flag); | 2291 | set_bit(META_dirty, &mp->flag); |
2287 | set_bit(META_sync, &mp->flag); | 2292 | set_bit(META_sync, &mp->flag); |
2293 | #endif | ||
2288 | } | 2294 | } |
2289 | } | 2295 | } |
2290 | } | 2296 | } |
@@ -2344,7 +2350,7 @@ static void txUpdateMap(struct tblock * tblk) | |||
2344 | */ | 2350 | */ |
2345 | mp = tlck->mp; | 2351 | mp = tlck->mp; |
2346 | ASSERT(mp->xflag & COMMIT_PAGE); | 2352 | ASSERT(mp->xflag & COMMIT_PAGE); |
2347 | hold_metapage(mp, 0); | 2353 | grab_metapage(mp); |
2348 | } | 2354 | } |
2349 | 2355 | ||
2350 | /* | 2356 | /* |
@@ -2394,8 +2400,8 @@ static void txUpdateMap(struct tblock * tblk) | |||
2394 | ASSERT(mp->lid == lid); | 2400 | ASSERT(mp->lid == lid); |
2395 | tlck->mp->lid = 0; | 2401 | tlck->mp->lid = 0; |
2396 | } | 2402 | } |
2397 | assert(atomic_read(&mp->nohomeok) == 1); | 2403 | assert(mp->nohomeok == 1); |
2398 | atomic_dec(&mp->nohomeok); | 2404 | metapage_homeok(mp); |
2399 | discard_metapage(mp); | 2405 | discard_metapage(mp); |
2400 | tlck->mp = NULL; | 2406 | tlck->mp = NULL; |
2401 | } | 2407 | } |
@@ -2861,24 +2867,9 @@ static void LogSyncRelease(struct metapage * mp) | |||
2861 | { | 2867 | { |
2862 | struct jfs_log *log = mp->log; | 2868 | struct jfs_log *log = mp->log; |
2863 | 2869 | ||
2864 | assert(atomic_read(&mp->nohomeok)); | 2870 | assert(mp->nohomeok); |
2865 | assert(log); | 2871 | assert(log); |
2866 | atomic_dec(&mp->nohomeok); | 2872 | metapage_homeok(mp); |
2867 | |||
2868 | if (atomic_read(&mp->nohomeok)) | ||
2869 | return; | ||
2870 | |||
2871 | hold_metapage(mp, 0); | ||
2872 | |||
2873 | LOGSYNC_LOCK(log); | ||
2874 | mp->log = NULL; | ||
2875 | mp->lsn = 0; | ||
2876 | mp->clsn = 0; | ||
2877 | log->count--; | ||
2878 | list_del_init(&mp->synclist); | ||
2879 | LOGSYNC_UNLOCK(log); | ||
2880 | |||
2881 | release_metapage(mp); | ||
2882 | } | 2873 | } |
2883 | 2874 | ||
2884 | /* | 2875 | /* |