1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45#include <linux/fs.h>
46#include <linux/vmalloc.h>
47#include <linux/completion.h>
48#include <linux/freezer.h>
49#include <linux/module.h>
50#include <linux/moduleparam.h>
51#include <linux/kthread.h>
52#include <linux/seq_file.h>
53#include "jfs_incore.h"
54#include "jfs_inode.h"
55#include "jfs_filsys.h"
56#include "jfs_metapage.h"
57#include "jfs_dinode.h"
58#include "jfs_imap.h"
59#include "jfs_dmap.h"
60#include "jfs_superblock.h"
61#include "jfs_debug.h"
62
63
64
65
66static struct {
67 int freetid;
68 int freelock;
69 wait_queue_head_t freewait;
70 wait_queue_head_t freelockwait;
71 wait_queue_head_t lowlockwait;
72 int tlocksInUse;
73 spinlock_t LazyLock;
74
75 struct list_head unlock_queue;
76 struct list_head anon_list;
77 struct list_head anon_list2;
78
79} TxAnchor;
80
81int jfs_tlocks_low;
82
83#ifdef CONFIG_JFS_STATISTICS
84static struct {
85 uint txBegin;
86 uint txBegin_barrier;
87 uint txBegin_lockslow;
88 uint txBegin_freetid;
89 uint txBeginAnon;
90 uint txBeginAnon_barrier;
91 uint txBeginAnon_lockslow;
92 uint txLockAlloc;
93 uint txLockAlloc_freelock;
94} TxStat;
95#endif
96
97static int nTxBlock = -1;
98module_param(nTxBlock, int, 0);
99MODULE_PARM_DESC(nTxBlock,
100 "Number of transaction blocks (max:65536)");
101
102static int nTxLock = -1;
103module_param(nTxLock, int, 0);
104MODULE_PARM_DESC(nTxLock,
105 "Number of transaction locks (max:65536)");
106
107struct tblock *TxBlock;
108static int TxLockLWM;
109static int TxLockHWM;
110static int TxLockVHWM;
111struct tlock *TxLock;
112
113
114
115
116static DEFINE_SPINLOCK(jfsTxnLock);
117
118#define TXN_LOCK() spin_lock(&jfsTxnLock)
119#define TXN_UNLOCK() spin_unlock(&jfsTxnLock)
120
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)
124
125static DECLARE_WAIT_QUEUE_HEAD(jfs_commit_thread_wait);
126static int jfs_commit_thread_waking;
127
128
129
130
131static inline void TXN_SLEEP_DROP_LOCK(wait_queue_head_t * event)
132{
133 DECLARE_WAITQUEUE(wait, current);
134
135 add_wait_queue(event, &wait);
136 set_current_state(TASK_UNINTERRUPTIBLE);
137 TXN_UNLOCK();
138 io_schedule();
139 __set_current_state(TASK_RUNNING);
140 remove_wait_queue(event, &wait);
141}
142
143#define TXN_SLEEP(event)\
144{\
145 TXN_SLEEP_DROP_LOCK(event);\
146 TXN_LOCK();\
147}
148
149#define TXN_WAKEUP(event) wake_up_all(event)
150
151
152
153
154static struct {
155 tid_t maxtid;
156 lid_t maxlid;
157 int ntid;
158 int nlid;
159 int waitlock;
160} stattx;
161
162
163
164
165static int diLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
166 struct tlock * tlck, struct commit * cd);
167static int dataLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
168 struct tlock * tlck);
169static void dtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
170 struct tlock * tlck);
171static void mapLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
172 struct tlock * tlck);
173static void txAllocPMap(struct inode *ip, struct maplock * maplock,
174 struct tblock * tblk);
175static void txForce(struct tblock * tblk);
176static int txLog(struct jfs_log * log, struct tblock * tblk,
177 struct commit * cd);
178static void txUpdateMap(struct tblock * tblk);
179static void txRelease(struct tblock * tblk);
180static void xtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
181 struct tlock * tlck);
182static void LogSyncRelease(struct metapage * mp);
183
184
185
186
187
188
189
190
191
192
193
194static lid_t txLockAlloc(void)
195{
196 lid_t lid;
197
198 INCREMENT(TxStat.txLockAlloc);
199 if (!TxAnchor.freelock) {
200 INCREMENT(TxStat.txLockAlloc_freelock);
201 }
202
203 while (!(lid = TxAnchor.freelock))
204 TXN_SLEEP(&TxAnchor.freelockwait);
205 TxAnchor.freelock = TxLock[lid].next;
206 HIGHWATERMARK(stattx.maxlid, lid);
207 if ((++TxAnchor.tlocksInUse > TxLockHWM) && (jfs_tlocks_low == 0)) {
208 jfs_info("txLockAlloc tlocks low");
209 jfs_tlocks_low = 1;
210 wake_up_process(jfsSyncThread);
211 }
212
213 return lid;
214}
215
216static void txLockFree(lid_t lid)
217{
218 TxLock[lid].tid = 0;
219 TxLock[lid].next = TxAnchor.freelock;
220 TxAnchor.freelock = lid;
221 TxAnchor.tlocksInUse--;
222 if (jfs_tlocks_low && (TxAnchor.tlocksInUse < TxLockLWM)) {
223 jfs_info("txLockFree jfs_tlocks_low no more");
224 jfs_tlocks_low = 0;
225 TXN_WAKEUP(&TxAnchor.lowlockwait);
226 }
227 TXN_WAKEUP(&TxAnchor.freelockwait);
228}
229
230
231
232
233
234
235
236
237
238
239int txInit(void)
240{
241 int k, size;
242 struct sysinfo si;
243
244
245
246 if (nTxLock == -1) {
247 if (nTxBlock == -1) {
248
249 si_meminfo(&si);
250 if (si.totalram > (256 * 1024))
251 nTxLock = 64 * 1024;
252 else
253 nTxLock = si.totalram >> 2;
254 } else if (nTxBlock > (8 * 1024))
255 nTxLock = 64 * 1024;
256 else
257 nTxLock = nTxBlock << 3;
258 }
259 if (nTxBlock == -1)
260 nTxBlock = nTxLock >> 3;
261
262
263 if (nTxBlock < 16)
264 nTxBlock = 16;
265 if (nTxBlock > 65536)
266 nTxBlock = 65536;
267 if (nTxLock < 256)
268 nTxLock = 256;
269 if (nTxLock > 65536)
270 nTxLock = 65536;
271
272 printk(KERN_INFO "JFS: nTxBlock = %d, nTxLock = %d\n",
273 nTxBlock, nTxLock);
274
275
276
277
278
279
280 TxLockLWM = (nTxLock * 4) / 10;
281 TxLockHWM = (nTxLock * 7) / 10;
282 TxLockVHWM = (nTxLock * 8) / 10;
283
284 size = sizeof(struct tblock) * nTxBlock;
285 TxBlock = vmalloc(size);
286 if (TxBlock == NULL)
287 return -ENOMEM;
288
289 for (k = 1; k < nTxBlock - 1; k++) {
290 TxBlock[k].next = k + 1;
291 init_waitqueue_head(&TxBlock[k].gcwait);
292 init_waitqueue_head(&TxBlock[k].waitor);
293 }
294 TxBlock[k].next = 0;
295 init_waitqueue_head(&TxBlock[k].gcwait);
296 init_waitqueue_head(&TxBlock[k].waitor);
297
298 TxAnchor.freetid = 1;
299 init_waitqueue_head(&TxAnchor.freewait);
300
301 stattx.maxtid = 1;
302
303
304
305
306
307
308
309 size = sizeof(struct tlock) * nTxLock;
310 TxLock = vmalloc(size);
311 if (TxLock == NULL) {
312 vfree(TxBlock);
313 return -ENOMEM;
314 }
315
316
317 for (k = 1; k < nTxLock - 1; k++)
318 TxLock[k].next = k + 1;
319 TxLock[k].next = 0;
320 init_waitqueue_head(&TxAnchor.freelockwait);
321 init_waitqueue_head(&TxAnchor.lowlockwait);
322
323 TxAnchor.freelock = 1;
324 TxAnchor.tlocksInUse = 0;
325 INIT_LIST_HEAD(&TxAnchor.anon_list);
326 INIT_LIST_HEAD(&TxAnchor.anon_list2);
327
328 LAZY_LOCK_INIT();
329 INIT_LIST_HEAD(&TxAnchor.unlock_queue);
330
331 stattx.maxlid = 1;
332
333 return 0;
334}
335
336
337
338
339
340
341void txExit(void)
342{
343 vfree(TxLock);
344 TxLock = NULL;
345 vfree(TxBlock);
346 TxBlock = NULL;
347}
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362tid_t txBegin(struct super_block *sb, int flag)
363{
364 tid_t t;
365 struct tblock *tblk;
366 struct jfs_log *log;
367
368 jfs_info("txBegin: flag = 0x%x", flag);
369 log = JFS_SBI(sb)->log;
370
371 TXN_LOCK();
372
373 INCREMENT(TxStat.txBegin);
374
375 retry:
376 if (!(flag & COMMIT_FORCE)) {
377
378
379
380 if (test_bit(log_SYNCBARRIER, &log->flag) ||
381 test_bit(log_QUIESCE, &log->flag)) {
382 INCREMENT(TxStat.txBegin_barrier);
383 TXN_SLEEP(&log->syncwait);
384 goto retry;
385 }
386 }
387 if (flag == 0) {
388
389
390
391
392
393 if (TxAnchor.tlocksInUse > TxLockVHWM) {
394 INCREMENT(TxStat.txBegin_lockslow);
395 TXN_SLEEP(&TxAnchor.lowlockwait);
396 goto retry;
397 }
398 }
399
400
401
402
403 if ((t = TxAnchor.freetid) == 0) {
404 jfs_info("txBegin: waiting for free tid");
405 INCREMENT(TxStat.txBegin_freetid);
406 TXN_SLEEP(&TxAnchor.freewait);
407 goto retry;
408 }
409
410 tblk = tid_to_tblock(t);
411
412 if ((tblk->next == 0) && !(flag & COMMIT_FORCE)) {
413
414 jfs_info("txBegin: waiting for free tid");
415 INCREMENT(TxStat.txBegin_freetid);
416 TXN_SLEEP(&TxAnchor.freewait);
417 goto retry;
418 }
419
420 TxAnchor.freetid = tblk->next;
421
422
423
424
425
426
427
428
429
430
431
432 tblk->next = tblk->last = tblk->xflag = tblk->flag = tblk->lsn = 0;
433
434 tblk->sb = sb;
435 ++log->logtid;
436 tblk->logtid = log->logtid;
437
438 ++log->active;
439
440 HIGHWATERMARK(stattx.maxtid, t);
441 INCREMENT(stattx.ntid);
442
443 TXN_UNLOCK();
444
445 jfs_info("txBegin: returning tid = %d", t);
446
447 return t;
448}
449
450
451
452
453
454
455
456
457
458
459
460
461void txBeginAnon(struct super_block *sb)
462{
463 struct jfs_log *log;
464
465 log = JFS_SBI(sb)->log;
466
467 TXN_LOCK();
468 INCREMENT(TxStat.txBeginAnon);
469
470 retry:
471
472
473
474 if (test_bit(log_SYNCBARRIER, &log->flag) ||
475 test_bit(log_QUIESCE, &log->flag)) {
476 INCREMENT(TxStat.txBeginAnon_barrier);
477 TXN_SLEEP(&log->syncwait);
478 goto retry;
479 }
480
481
482
483
484 if (TxAnchor.tlocksInUse > TxLockVHWM) {
485 INCREMENT(TxStat.txBeginAnon_lockslow);
486 TXN_SLEEP(&TxAnchor.lowlockwait);
487 goto retry;
488 }
489 TXN_UNLOCK();
490}
491
492
493
494
495
496
497
498
499
500
501void txEnd(tid_t tid)
502{
503 struct tblock *tblk = tid_to_tblock(tid);
504 struct jfs_log *log;
505
506 jfs_info("txEnd: tid = %d", tid);
507 TXN_LOCK();
508
509
510
511
512
513 TXN_WAKEUP(&tblk->waitor);
514
515 log = JFS_SBI(tblk->sb)->log;
516
517
518
519
520
521
522
523
524
525 if (tblk->flag & tblkGC_LAZY) {
526 jfs_info("txEnd called w/lazy tid: %d, tblk = 0x%p", tid, tblk);
527 TXN_UNLOCK();
528
529 spin_lock_irq(&log->gclock);
530 tblk->flag |= tblkGC_UNLOCKED;
531 spin_unlock_irq(&log->gclock);
532 return;
533 }
534
535 jfs_info("txEnd: tid: %d, tblk = 0x%p", tid, tblk);
536
537 assert(tblk->next == 0);
538
539
540
541
542 tblk->next = TxAnchor.freetid;
543 TxAnchor.freetid = tid;
544
545
546
547
548 if (--log->active == 0) {
549 clear_bit(log_FLUSH, &log->flag);
550
551
552
553
554 if (test_bit(log_SYNCBARRIER, &log->flag)) {
555 TXN_UNLOCK();
556
557
558 jfs_syncpt(log, 1);
559
560 jfs_info("log barrier off: 0x%x", log->lsn);
561
562
563 clear_bit(log_SYNCBARRIER, &log->flag);
564
565
566 TXN_WAKEUP(&log->syncwait);
567
568 goto wakeup;
569 }
570 }
571
572 TXN_UNLOCK();
573wakeup:
574
575
576
577 TXN_WAKEUP(&TxAnchor.freewait);
578}
579
580
581
582
583
584
585
586
587
588
589
590
591struct tlock *txLock(tid_t tid, struct inode *ip, struct metapage * mp,
592 int type)
593{
594 struct jfs_inode_info *jfs_ip = JFS_IP(ip);
595 int dir_xtree = 0;
596 lid_t lid;
597 tid_t xtid;
598 struct tlock *tlck;
599 struct xtlock *xtlck;
600 struct linelock *linelock;
601 xtpage_t *p;
602 struct tblock *tblk;
603
604 TXN_LOCK();
605
606 if (S_ISDIR(ip->i_mode) && (type & tlckXTREE) &&
607 !(mp->xflag & COMMIT_PAGE)) {
608
609
610
611
612 dir_xtree = 1;
613 lid = jfs_ip->xtlid;
614 } else
615 lid = mp->lid;
616
617
618 if (lid == 0)
619 goto allocateLock;
620
621 jfs_info("txLock: tid:%d ip:0x%p mp:0x%p lid:%d", tid, ip, mp, lid);
622
623
624 tlck = lid_to_tlock(lid);
625 if ((xtid = tlck->tid) == tid) {
626 TXN_UNLOCK();
627 goto grantLock;
628 }
629
630
631
632
633
634
635
636
637
638
639
640
641 if (xtid == 0) {
642 tlck->tid = tid;
643 TXN_UNLOCK();
644 tblk = tid_to_tblock(tid);
645
646
647
648
649
650
651
652
653
654
655 if (jfs_ip->atlhead == lid) {
656 if (jfs_ip->atltail == lid) {
657
658
659
660 TXN_LOCK();
661 list_del_init(&jfs_ip->anon_inode_list);
662 TXN_UNLOCK();
663 }
664 jfs_ip->atlhead = tlck->next;
665 } else {
666 lid_t last;
667 for (last = jfs_ip->atlhead;
668 lid_to_tlock(last)->next != lid;
669 last = lid_to_tlock(last)->next) {
670 assert(last);
671 }
672 lid_to_tlock(last)->next = tlck->next;
673 if (jfs_ip->atltail == lid)
674 jfs_ip->atltail = last;
675 }
676
677
678
679 if (tblk->next)
680 lid_to_tlock(tblk->last)->next = lid;
681 else
682 tblk->next = lid;
683 tlck->next = 0;
684 tblk->last = lid;
685
686 goto grantLock;
687 }
688
689 goto waitLock;
690
691
692
693
694 allocateLock:
695 lid = txLockAlloc();
696 tlck = lid_to_tlock(lid);
697
698
699
700
701 tlck->tid = tid;
702
703 TXN_UNLOCK();
704
705
706 if (mp->xflag & COMMIT_PAGE) {
707
708 tlck->flag = tlckPAGELOCK;
709
710
711 metapage_nohomeok(mp);
712
713 jfs_info("locking mp = 0x%p, nohomeok = %d tid = %d tlck = 0x%p",
714 mp, mp->nohomeok, tid, tlck);
715
716
717
718
719
720
721 if ((tid == 0) && mp->lsn)
722 set_cflag(COMMIT_Synclist, ip);
723 }
724
725 else
726 tlck->flag = tlckINODELOCK;
727
728 if (S_ISDIR(ip->i_mode))
729 tlck->flag |= tlckDIRECTORY;
730
731 tlck->type = 0;
732
733
734 tlck->ip = ip;
735 tlck->mp = mp;
736 if (dir_xtree)
737 jfs_ip->xtlid = lid;
738 else
739 mp->lid = lid;
740
741
742
743
744
745 if (tid) {
746 tblk = tid_to_tblock(tid);
747 if (tblk->next)
748 lid_to_tlock(tblk->last)->next = lid;
749 else
750 tblk->next = lid;
751 tlck->next = 0;
752 tblk->last = lid;
753 }
754
755
756
757 else {
758 tlck->next = jfs_ip->atlhead;
759 jfs_ip->atlhead = lid;
760 if (tlck->next == 0) {
761
762 jfs_ip->atltail = lid;
763 TXN_LOCK();
764 list_add_tail(&jfs_ip->anon_inode_list,
765 &TxAnchor.anon_list);
766 TXN_UNLOCK();
767 }
768 }
769
770
771 linelock = (struct linelock *) & tlck->lock;
772 linelock->next = 0;
773 linelock->flag = tlckLINELOCK;
774 linelock->maxcnt = TLOCKSHORT;
775 linelock->index = 0;
776
777 switch (type & tlckTYPE) {
778 case tlckDTREE:
779 linelock->l2linesize = L2DTSLOTSIZE;
780 break;
781
782 case tlckXTREE:
783 linelock->l2linesize = L2XTSLOTSIZE;
784
785 xtlck = (struct xtlock *) linelock;
786 xtlck->header.offset = 0;
787 xtlck->header.length = 2;
788
789 if (type & tlckNEW) {
790 xtlck->lwm.offset = XTENTRYSTART;
791 } else {
792 if (mp->xflag & COMMIT_PAGE)
793 p = (xtpage_t *) mp->data;
794 else
795 p = &jfs_ip->i_xtroot;
796 xtlck->lwm.offset =
797 le16_to_cpu(p->header.nextindex);
798 }
799 xtlck->lwm.length = 0;
800 xtlck->twm.offset = 0;
801 xtlck->hwm.offset = 0;
802
803 xtlck->index = 2;
804 break;
805
806 case tlckINODE:
807 linelock->l2linesize = L2INODESLOTSIZE;
808 break;
809
810 case tlckDATA:
811 linelock->l2linesize = L2DATASLOTSIZE;
812 break;
813
814 default:
815 jfs_err("UFO tlock:0x%p", tlck);
816 }
817
818
819
820
821 grantLock:
822 tlck->type |= type;
823
824 return tlck;
825
826
827
828
829 waitLock:
830
831
832 if (jfs_ip->fileset != AGGREGATE_I) {
833 printk(KERN_ERR "txLock: trying to lock locked page!");
834 print_hex_dump(KERN_ERR, "ip: ", DUMP_PREFIX_ADDRESS, 16, 4,
835 ip, sizeof(*ip), 0);
836 print_hex_dump(KERN_ERR, "mp: ", DUMP_PREFIX_ADDRESS, 16, 4,
837 mp, sizeof(*mp), 0);
838 print_hex_dump(KERN_ERR, "Locker's tblock: ",
839 DUMP_PREFIX_ADDRESS, 16, 4, tid_to_tblock(tid),
840 sizeof(struct tblock), 0);
841 print_hex_dump(KERN_ERR, "Tlock: ", DUMP_PREFIX_ADDRESS, 16, 4,
842 tlck, sizeof(*tlck), 0);
843 BUG();
844 }
845 INCREMENT(stattx.waitlock);
846 TXN_UNLOCK();
847 release_metapage(mp);
848 TXN_LOCK();
849 xtid = tlck->tid;
850
851 jfs_info("txLock: in waitLock, tid = %d, xtid = %d, lid = %d",
852 tid, xtid, lid);
853
854
855 if (xtid && (tlck->mp == mp) && (mp->lid == lid))
856 TXN_SLEEP_DROP_LOCK(&tid_to_tblock(xtid)->waitor);
857 else
858 TXN_UNLOCK();
859 jfs_info("txLock: awakened tid = %d, lid = %d", tid, lid);
860
861 return NULL;
862}
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877static void txRelease(struct tblock * tblk)
878{
879 struct metapage *mp;
880 lid_t lid;
881 struct tlock *tlck;
882
883 TXN_LOCK();
884
885 for (lid = tblk->next; lid; lid = tlck->next) {
886 tlck = lid_to_tlock(lid);
887 if ((mp = tlck->mp) != NULL &&
888 (tlck->type & tlckBTROOT) == 0) {
889 assert(mp->xflag & COMMIT_PAGE);
890 mp->lid = 0;
891 }
892 }
893
894
895
896
897
898 TXN_WAKEUP(&tblk->waitor);
899
900 TXN_UNLOCK();
901}
902
903
904
905
906
907
908
909static void txUnlock(struct tblock * tblk)
910{
911 struct tlock *tlck;
912 struct linelock *linelock;
913 lid_t lid, next, llid, k;
914 struct metapage *mp;
915 struct jfs_log *log;
916 int difft, diffp;
917 unsigned long flags;
918
919 jfs_info("txUnlock: tblk = 0x%p", tblk);
920 log = JFS_SBI(tblk->sb)->log;
921
922
923
924
925 for (lid = tblk->next; lid; lid = next) {
926 tlck = lid_to_tlock(lid);
927 next = tlck->next;
928
929 jfs_info("unlocking lid = %d, tlck = 0x%p", lid, tlck);
930
931
932 if ((mp = tlck->mp) != NULL &&
933 (tlck->type & tlckBTROOT) == 0) {
934 assert(mp->xflag & COMMIT_PAGE);
935
936
937
938 hold_metapage(mp);
939
940 assert(mp->nohomeok > 0);
941 _metapage_homeok(mp);
942
943
944 LOGSYNC_LOCK(log, flags);
945 if (mp->clsn) {
946 logdiff(difft, tblk->clsn, log);
947 logdiff(diffp, mp->clsn, log);
948 if (difft > diffp)
949 mp->clsn = tblk->clsn;
950 } else
951 mp->clsn = tblk->clsn;
952 LOGSYNC_UNLOCK(log, flags);
953
954 assert(!(tlck->flag & tlckFREEPAGE));
955
956 put_metapage(mp);
957 }
958
959
960
961
962 TXN_LOCK();
963
964 llid = ((struct linelock *) & tlck->lock)->next;
965 while (llid) {
966 linelock = (struct linelock *) lid_to_tlock(llid);
967 k = linelock->next;
968 txLockFree(llid);
969 llid = k;
970 }
971 txLockFree(lid);
972
973 TXN_UNLOCK();
974 }
975 tblk->next = tblk->last = 0;
976
977
978
979
980
981
982 if (tblk->lsn) {
983 LOGSYNC_LOCK(log, flags);
984 log->count--;
985 list_del(&tblk->synclist);
986 LOGSYNC_UNLOCK(log, flags);
987 }
988}
989
990
991
992
993
994
995
996struct tlock *txMaplock(tid_t tid, struct inode *ip, int type)
997{
998 struct jfs_inode_info *jfs_ip = JFS_IP(ip);
999 lid_t lid;
1000 struct tblock *tblk;
1001 struct tlock *tlck;
1002 struct maplock *maplock;
1003
1004 TXN_LOCK();
1005
1006
1007
1008
1009 lid = txLockAlloc();
1010 tlck = lid_to_tlock(lid);
1011
1012
1013
1014
1015 tlck->tid = tid;
1016
1017
1018 tlck->flag = tlckINODELOCK;
1019 if (S_ISDIR(ip->i_mode))
1020 tlck->flag |= tlckDIRECTORY;
1021 tlck->ip = ip;
1022 tlck->mp = NULL;
1023
1024 tlck->type = type;
1025
1026
1027
1028
1029
1030 if (tid) {
1031 tblk = tid_to_tblock(tid);
1032 if (tblk->next)
1033 lid_to_tlock(tblk->last)->next = lid;
1034 else
1035 tblk->next = lid;
1036 tlck->next = 0;
1037 tblk->last = lid;
1038 }
1039
1040
1041
1042 else {
1043 tlck->next = jfs_ip->atlhead;
1044 jfs_ip->atlhead = lid;
1045 if (tlck->next == 0) {
1046
1047 jfs_ip->atltail = lid;
1048 list_add_tail(&jfs_ip->anon_inode_list,
1049 &TxAnchor.anon_list);
1050 }
1051 }
1052
1053 TXN_UNLOCK();
1054
1055
1056 maplock = (struct maplock *) & tlck->lock;
1057 maplock->next = 0;
1058 maplock->maxcnt = 0;
1059 maplock->index = 0;
1060
1061 return tlck;
1062}
1063
1064
1065
1066
1067
1068
1069struct linelock *txLinelock(struct linelock * tlock)
1070{
1071 lid_t lid;
1072 struct tlock *tlck;
1073 struct linelock *linelock;
1074
1075 TXN_LOCK();
1076
1077
1078 lid = txLockAlloc();
1079 tlck = lid_to_tlock(lid);
1080
1081 TXN_UNLOCK();
1082
1083
1084 linelock = (struct linelock *) tlck;
1085 linelock->next = 0;
1086 linelock->flag = tlckLINELOCK;
1087 linelock->maxcnt = TLOCKLONG;
1088 linelock->index = 0;
1089 if (tlck->flag & tlckDIRECTORY)
1090 linelock->flag |= tlckDIRECTORY;
1091
1092
1093 linelock->next = tlock->next;
1094 tlock->next = lid;
1095
1096 return linelock;
1097}
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136int txCommit(tid_t tid,
1137 int nip,
1138 struct inode **iplist,
1139 int flag)
1140{
1141 int rc = 0;
1142 struct commit cd;
1143 struct jfs_log *log;
1144 struct tblock *tblk;
1145 struct lrd *lrd;
1146 struct inode *ip;
1147 struct jfs_inode_info *jfs_ip;
1148 int k, n;
1149 ino_t top;
1150 struct super_block *sb;
1151
1152 jfs_info("txCommit, tid = %d, flag = %d", tid, flag);
1153
1154 if (isReadOnly(iplist[0])) {
1155 rc = -EROFS;
1156 goto TheEnd;
1157 }
1158
1159 sb = cd.sb = iplist[0]->i_sb;
1160 cd.tid = tid;
1161
1162 if (tid == 0)
1163 tid = txBegin(sb, 0);
1164 tblk = tid_to_tblock(tid);
1165
1166
1167
1168
1169 log = JFS_SBI(sb)->log;
1170 cd.log = log;
1171
1172
1173 lrd = &cd.lrd;
1174 lrd->logtid = cpu_to_le32(tblk->logtid);
1175 lrd->backchain = 0;
1176
1177 tblk->xflag |= flag;
1178
1179 if ((flag & (COMMIT_FORCE | COMMIT_SYNC)) == 0)
1180 tblk->xflag |= COMMIT_LAZY;
1181
1182
1183
1184
1185
1186
1187
1188
1189 cd.iplist = iplist;
1190 cd.nip = nip;
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204 for (k = 0; k < cd.nip; k++) {
1205 top = (cd.iplist[k])->i_ino;
1206 for (n = k + 1; n < cd.nip; n++) {
1207 ip = cd.iplist[n];
1208 if (ip->i_ino > top) {
1209 top = ip->i_ino;
1210 cd.iplist[n] = cd.iplist[k];
1211 cd.iplist[k] = ip;
1212 }
1213 }
1214
1215 ip = cd.iplist[k];
1216 jfs_ip = JFS_IP(ip);
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246 clear_cflag(COMMIT_Dirty, ip);
1247
1248
1249 if (jfs_ip->atlhead) {
1250 lid_to_tlock(jfs_ip->atltail)->next = tblk->next;
1251 tblk->next = jfs_ip->atlhead;
1252 if (!tblk->last)
1253 tblk->last = jfs_ip->atltail;
1254 jfs_ip->atlhead = jfs_ip->atltail = 0;
1255 TXN_LOCK();
1256 list_del_init(&jfs_ip->anon_inode_list);
1257 TXN_UNLOCK();
1258 }
1259
1260
1261
1262
1263
1264 if (((rc = diWrite(tid, ip))))
1265 goto out;
1266 }
1267
1268
1269
1270
1271
1272
1273 if ((rc = txLog(log, tblk, &cd)))
1274 goto TheEnd;
1275
1276
1277
1278
1279
1280 if (tblk->xflag & COMMIT_DELETE) {
1281 ihold(tblk->u.ip);
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299 if (tblk->u.ip->i_state & I_SYNC)
1300 tblk->xflag &= ~COMMIT_LAZY;
1301 }
1302
1303 ASSERT((!(tblk->xflag & COMMIT_DELETE)) ||
1304 ((tblk->u.ip->i_nlink == 0) &&
1305 !test_cflag(COMMIT_Nolink, tblk->u.ip)));
1306
1307
1308
1309
1310 lrd->type = cpu_to_le16(LOG_COMMIT);
1311 lrd->length = 0;
1312 lmLog(log, tblk, lrd, NULL);
1313
1314 lmGroupCommit(log, tblk);
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324 if (flag & COMMIT_FORCE)
1325 txForce(tblk);
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336 if (tblk->xflag & COMMIT_FORCE)
1337 txUpdateMap(tblk);
1338
1339
1340
1341
1342 txRelease(tblk);
1343
1344 if ((tblk->flag & tblkGC_LAZY) == 0)
1345 txUnlock(tblk);
1346
1347
1348
1349
1350
1351 for (k = 0; k < cd.nip; k++) {
1352 ip = cd.iplist[k];
1353 jfs_ip = JFS_IP(ip);
1354
1355
1356
1357
1358 jfs_ip->bxflag = 0;
1359 jfs_ip->blid = 0;
1360 }
1361
1362 out:
1363 if (rc != 0)
1364 txAbort(tid, 1);
1365
1366 TheEnd:
1367 jfs_info("txCommit: tid = %d, returning %d", tid, rc);
1368 return rc;
1369}
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382static int txLog(struct jfs_log * log, struct tblock * tblk, struct commit * cd)
1383{
1384 int rc = 0;
1385 struct inode *ip;
1386 lid_t lid;
1387 struct tlock *tlck;
1388 struct lrd *lrd = &cd->lrd;
1389
1390
1391
1392
1393 for (lid = tblk->next; lid; lid = tlck->next) {
1394 tlck = lid_to_tlock(lid);
1395
1396 tlck->flag |= tlckLOG;
1397
1398
1399 ip = tlck->ip;
1400 lrd->aggregate = cpu_to_le32(JFS_SBI(ip->i_sb)->aggregate);
1401 lrd->log.redopage.fileset = cpu_to_le32(JFS_IP(ip)->fileset);
1402 lrd->log.redopage.inode = cpu_to_le32(ip->i_ino);
1403
1404
1405 switch (tlck->type & tlckTYPE) {
1406 case tlckXTREE:
1407 xtLog(log, tblk, lrd, tlck);
1408 break;
1409
1410 case tlckDTREE:
1411 dtLog(log, tblk, lrd, tlck);
1412 break;
1413
1414 case tlckINODE:
1415 diLog(log, tblk, lrd, tlck, cd);
1416 break;
1417
1418 case tlckMAP:
1419 mapLog(log, tblk, lrd, tlck);
1420 break;
1421
1422 case tlckDATA:
1423 dataLog(log, tblk, lrd, tlck);
1424 break;
1425
1426 default:
1427 jfs_err("UFO tlock:0x%p", tlck);
1428 }
1429 }
1430
1431 return rc;
1432}
1433
1434
1435
1436
1437
1438
1439static int diLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
1440 struct tlock * tlck, struct commit * cd)
1441{
1442 int rc = 0;
1443 struct metapage *mp;
1444 pxd_t *pxd;
1445 struct pxd_lock *pxdlock;
1446
1447 mp = tlck->mp;
1448
1449
1450 lrd->log.redopage.type = cpu_to_le16(LOG_INODE);
1451 lrd->log.redopage.l2linesize = cpu_to_le16(L2INODESLOTSIZE);
1452
1453 pxd = &lrd->log.redopage.pxd;
1454
1455
1456
1457
1458 if (tlck->type & tlckENTRY) {
1459
1460 lrd->type = cpu_to_le16(LOG_REDOPAGE);
1461 PXDaddress(pxd, mp->index);
1462 PXDlength(pxd,
1463 mp->logical_size >> tblk->sb->s_blocksize_bits);
1464 lrd->backchain = cpu_to_le32(lmLog(log, tblk, lrd, tlck));
1465
1466
1467 tlck->flag |= tlckWRITEPAGE;
1468 } else if (tlck->type & tlckFREE) {
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486 lrd->type = cpu_to_le16(LOG_NOREDOINOEXT);
1487
1488
1489
1490
1491
1492
1493
1494 lrd->log.noredoinoext.iagnum =
1495 cpu_to_le32((u32) (size_t) cd->iplist[1]);
1496 lrd->log.noredoinoext.inoext_idx =
1497 cpu_to_le32((u32) (size_t) cd->iplist[2]);
1498
1499 pxdlock = (struct pxd_lock *) & tlck->lock;
1500 *pxd = pxdlock->pxd;
1501 lrd->backchain = cpu_to_le32(lmLog(log, tblk, lrd, NULL));
1502
1503
1504 tlck->flag |= tlckUPDATEMAP;
1505
1506
1507 tlck->flag |= tlckWRITEPAGE;
1508 } else
1509 jfs_err("diLog: UFO type tlck:0x%p", tlck);
1510#ifdef _JFS_WIP
1511
1512
1513
1514
1515
1516
1517 else {
1518 assert(tlck->type & tlckEA);
1519
1520
1521
1522
1523 lrd->type = cpu_to_le16(LOG_UPDATEMAP);
1524 pxdlock = (struct pxd_lock *) & tlck->lock;
1525 nlock = pxdlock->index;
1526 for (i = 0; i < nlock; i++, pxdlock++) {
1527 if (pxdlock->flag & mlckALLOCPXD)
1528 lrd->log.updatemap.type =
1529 cpu_to_le16(LOG_ALLOCPXD);
1530 else
1531 lrd->log.updatemap.type =
1532 cpu_to_le16(LOG_FREEPXD);
1533 lrd->log.updatemap.nxd = cpu_to_le16(1);
1534 lrd->log.updatemap.pxd = pxdlock->pxd;
1535 lrd->backchain =
1536 cpu_to_le32(lmLog(log, tblk, lrd, NULL));
1537 }
1538
1539
1540 tlck->flag |= tlckUPDATEMAP;
1541 }
1542#endif
1543
1544 return rc;
1545}
1546
1547
1548
1549
1550
1551
1552static int dataLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
1553 struct tlock * tlck)
1554{
1555 struct metapage *mp;
1556 pxd_t *pxd;
1557
1558 mp = tlck->mp;
1559
1560
1561 lrd->log.redopage.type = cpu_to_le16(LOG_DATA);
1562 lrd->log.redopage.l2linesize = cpu_to_le16(L2DATASLOTSIZE);
1563
1564 pxd = &lrd->log.redopage.pxd;
1565
1566
1567 lrd->type = cpu_to_le16(LOG_REDOPAGE);
1568
1569 if (jfs_dirtable_inline(tlck->ip)) {
1570
1571
1572
1573
1574 mp->lid = 0;
1575 grab_metapage(mp);
1576 metapage_homeok(mp);
1577 discard_metapage(mp);
1578 tlck->mp = NULL;
1579 return 0;
1580 }
1581
1582 PXDaddress(pxd, mp->index);
1583 PXDlength(pxd, mp->logical_size >> tblk->sb->s_blocksize_bits);
1584
1585 lrd->backchain = cpu_to_le32(lmLog(log, tblk, lrd, tlck));
1586
1587
1588 tlck->flag |= tlckWRITEPAGE;
1589
1590 return 0;
1591}
1592
1593
1594
1595
1596
1597
1598static void dtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
1599 struct tlock * tlck)
1600{
1601 struct metapage *mp;
1602 struct pxd_lock *pxdlock;
1603 pxd_t *pxd;
1604
1605 mp = tlck->mp;
1606
1607
1608 lrd->log.redopage.type = cpu_to_le16(LOG_DTREE);
1609 lrd->log.redopage.l2linesize = cpu_to_le16(L2DTSLOTSIZE);
1610
1611 pxd = &lrd->log.redopage.pxd;
1612
1613 if (tlck->type & tlckBTROOT)
1614 lrd->log.redopage.type |= cpu_to_le16(LOG_BTROOT);
1615
1616
1617
1618
1619
1620
1621
1622 if (tlck->type & (tlckNEW | tlckEXTEND)) {
1623
1624
1625
1626
1627 lrd->type = cpu_to_le16(LOG_REDOPAGE);
1628 if (tlck->type & tlckEXTEND)
1629 lrd->log.redopage.type |= cpu_to_le16(LOG_EXTEND);
1630 else
1631 lrd->log.redopage.type |= cpu_to_le16(LOG_NEW);
1632 PXDaddress(pxd, mp->index);
1633 PXDlength(pxd,
1634 mp->logical_size >> tblk->sb->s_blocksize_bits);
1635 lrd->backchain = cpu_to_le32(lmLog(log, tblk, lrd, tlck));
1636
1637
1638
1639
1640 if (tlck->type & tlckBTROOT)
1641 return;
1642 tlck->flag |= tlckUPDATEMAP;
1643 pxdlock = (struct pxd_lock *) & tlck->lock;
1644 pxdlock->flag = mlckALLOCPXD;
1645 pxdlock->pxd = *pxd;
1646
1647 pxdlock->index = 1;
1648
1649
1650 tlck->flag |= tlckWRITEPAGE;
1651 return;
1652 }
1653
1654
1655
1656
1657
1658 if (tlck->type & (tlckENTRY | tlckRELINK)) {
1659
1660 lrd->type = cpu_to_le16(LOG_REDOPAGE);
1661 PXDaddress(pxd, mp->index);
1662 PXDlength(pxd,
1663 mp->logical_size >> tblk->sb->s_blocksize_bits);
1664 lrd->backchain = cpu_to_le32(lmLog(log, tblk, lrd, tlck));
1665
1666
1667 tlck->flag |= tlckWRITEPAGE;
1668 return;
1669 }
1670
1671
1672
1673
1674
1675
1676
1677
1678 if (tlck->type & (tlckFREE | tlckRELOCATE)) {
1679
1680
1681
1682
1683 lrd->type = cpu_to_le16(LOG_NOREDOPAGE);
1684 pxdlock = (struct pxd_lock *) & tlck->lock;
1685 *pxd = pxdlock->pxd;
1686 lrd->backchain = cpu_to_le32(lmLog(log, tblk, lrd, NULL));
1687
1688
1689
1690
1691 tlck->flag |= tlckUPDATEMAP;
1692 }
1693 return;
1694}
1695
1696
1697
1698
1699
1700
1701static void xtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
1702 struct tlock * tlck)
1703{
1704 struct inode *ip;
1705 struct metapage *mp;
1706 xtpage_t *p;
1707 struct xtlock *xtlck;
1708 struct maplock *maplock;
1709 struct xdlistlock *xadlock;
1710 struct pxd_lock *pxdlock;
1711 pxd_t *page_pxd;
1712 int next, lwm, hwm;
1713
1714 ip = tlck->ip;
1715 mp = tlck->mp;
1716
1717
1718 lrd->log.redopage.type = cpu_to_le16(LOG_XTREE);
1719 lrd->log.redopage.l2linesize = cpu_to_le16(L2XTSLOTSIZE);
1720
1721 page_pxd = &lrd->log.redopage.pxd;
1722
1723 if (tlck->type & tlckBTROOT) {
1724 lrd->log.redopage.type |= cpu_to_le16(LOG_BTROOT);
1725 p = &JFS_IP(ip)->i_xtroot;
1726 if (S_ISDIR(ip->i_mode))
1727 lrd->log.redopage.type |=
1728 cpu_to_le16(LOG_DIR_XTREE);
1729 } else
1730 p = (xtpage_t *) mp->data;
1731 next = le16_to_cpu(p->header.nextindex);
1732
1733 xtlck = (struct xtlock *) & tlck->lock;
1734
1735 maplock = (struct maplock *) & tlck->lock;
1736 xadlock = (struct xdlistlock *) maplock;
1737
1738
1739
1740
1741
1742 if (tlck->type & (tlckNEW | tlckGROW | tlckRELINK)) {
1743
1744
1745
1746
1747
1748
1749
1750 lrd->type = cpu_to_le16(LOG_REDOPAGE);
1751 PXDaddress(page_pxd, mp->index);
1752 PXDlength(page_pxd,
1753 mp->logical_size >> tblk->sb->s_blocksize_bits);
1754 lrd->backchain = cpu_to_le32(lmLog(log, tblk, lrd, tlck));
1755
1756
1757
1758
1759
1760
1761 lwm = xtlck->lwm.offset;
1762 if (lwm == 0)
1763 lwm = XTPAGEMAXSLOT;
1764
1765 if (lwm == next)
1766 goto out;
1767 if (lwm > next) {
1768 jfs_err("xtLog: lwm > next\n");
1769 goto out;
1770 }
1771 tlck->flag |= tlckUPDATEMAP;
1772 xadlock->flag = mlckALLOCXADLIST;
1773 xadlock->count = next - lwm;
1774 if ((xadlock->count <= 4) && (tblk->xflag & COMMIT_LAZY)) {
1775 int i;
1776 pxd_t *pxd;
1777
1778
1779
1780
1781
1782
1783
1784 xadlock->flag = mlckALLOCPXDLIST;
1785 pxd = xadlock->xdlist = &xtlck->pxdlock;
1786 for (i = 0; i < xadlock->count; i++) {
1787 PXDaddress(pxd, addressXAD(&p->xad[lwm + i]));
1788 PXDlength(pxd, lengthXAD(&p->xad[lwm + i]));
1789 p->xad[lwm + i].flag &=
1790 ~(XAD_NEW | XAD_EXTENDED);
1791 pxd++;
1792 }
1793 } else {
1794
1795
1796
1797
1798 xadlock->flag = mlckALLOCXADLIST;
1799 xadlock->xdlist = &p->xad[lwm];
1800 tblk->xflag &= ~COMMIT_LAZY;
1801 }
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);
1804
1805 maplock->index = 1;
1806
1807 out:
1808
1809 tlck->flag |= tlckWRITEPAGE;
1810
1811 return;
1812 }
1813
1814
1815
1816
1817
1818
1819
1820 if (tlck->type & tlckFREE) {
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837 if (tblk->xflag & COMMIT_TRUNCATE) {
1838
1839 lrd->type = cpu_to_le16(LOG_NOREDOPAGE);
1840 PXDaddress(page_pxd, mp->index);
1841 PXDlength(page_pxd,
1842 mp->logical_size >> tblk->sb->
1843 s_blocksize_bits);
1844 lrd->backchain =
1845 cpu_to_le32(lmLog(log, tblk, lrd, NULL));
1846
1847 if (tlck->type & tlckBTROOT) {
1848
1849 lrd->type = cpu_to_le16(LOG_REDOPAGE);
1850 lrd->backchain =
1851 cpu_to_le32(lmLog(log, tblk, lrd, tlck));
1852 }
1853 }
1854
1855
1856
1857
1858
1859 lrd->type = cpu_to_le16(LOG_UPDATEMAP);
1860 lrd->log.updatemap.type = cpu_to_le16(LOG_FREEXADLIST);
1861 xtlck = (struct xtlock *) & tlck->lock;
1862 hwm = xtlck->hwm.offset;
1863 lrd->log.updatemap.nxd =
1864 cpu_to_le16(hwm - XTENTRYSTART + 1);
1865
1866 xtlck->header.offset = XTENTRYSTART;
1867 xtlck->header.length = hwm - XTENTRYSTART + 1;
1868 xtlck->index = 1;
1869 lrd->backchain = cpu_to_le32(lmLog(log, tblk, lrd, tlck));
1870
1871
1872
1873
1874
1875 tlck->flag |= tlckUPDATEMAP;
1876 xadlock->count = hwm - XTENTRYSTART + 1;
1877 if ((xadlock->count <= 4) && (tblk->xflag & COMMIT_LAZY)) {
1878 int i;
1879 pxd_t *pxd;
1880
1881
1882
1883
1884
1885
1886
1887 xadlock->flag = mlckFREEPXDLIST;
1888 pxd = xadlock->xdlist = &xtlck->pxdlock;
1889 for (i = 0; i < xadlock->count; i++) {
1890 PXDaddress(pxd,
1891 addressXAD(&p->xad[XTENTRYSTART + i]));
1892 PXDlength(pxd,
1893 lengthXAD(&p->xad[XTENTRYSTART + i]));
1894 pxd++;
1895 }
1896 } else {
1897
1898
1899
1900
1901 xadlock->flag = mlckFREEXADLIST;
1902 xadlock->xdlist = &p->xad[XTENTRYSTART];
1903 tblk->xflag &= ~COMMIT_LAZY;
1904 }
1905 jfs_info("xtLog: free ip:0x%p mp:0x%p count:%d lwm:2",
1906 tlck->ip, mp, xadlock->count);
1907
1908 maplock->index = 1;
1909
1910
1911 if (((tblk->xflag & COMMIT_PWMAP) || S_ISDIR(ip->i_mode))
1912 && !(tlck->type & tlckBTROOT))
1913 tlck->flag |= tlckFREEPAGE;
1914
1915
1916
1917
1918 return;
1919 }
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931 if (tlck->type & tlckTRUNCATE) {
1932
1933 pxd_t pxd = pxd;
1934 int twm;
1935
1936
1937
1938
1939
1940
1941
1942
1943 tblk->xflag &= ~COMMIT_LAZY;
1944 lwm = xtlck->lwm.offset;
1945 if (lwm == 0)
1946 lwm = XTPAGEMAXSLOT;
1947 hwm = xtlck->hwm.offset;
1948 twm = xtlck->twm.offset;
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961 lrd->type = cpu_to_le16(LOG_REDOPAGE);
1962 PXDaddress(page_pxd, mp->index);
1963 PXDlength(page_pxd,
1964 mp->logical_size >> tblk->sb->s_blocksize_bits);
1965 lrd->backchain = cpu_to_le32(lmLog(log, tblk, lrd, tlck));
1966
1967
1968
1969
1970 if (twm == next - 1) {
1971
1972
1973
1974
1975
1976 pxdlock = (struct pxd_lock *) & xtlck->pxdlock;
1977
1978 lrd->type = cpu_to_le16(LOG_UPDATEMAP);
1979 lrd->log.updatemap.type = cpu_to_le16(LOG_FREEPXD);
1980 lrd->log.updatemap.nxd = cpu_to_le16(1);
1981 lrd->log.updatemap.pxd = pxdlock->pxd;
1982 pxd = pxdlock->pxd;
1983 lrd->backchain =
1984 cpu_to_le32(lmLog(log, tblk, lrd, NULL));
1985 }
1986
1987
1988
1989
1990 if (hwm >= next) {
1991
1992
1993
1994
1995 lrd->type = cpu_to_le16(LOG_UPDATEMAP);
1996 lrd->log.updatemap.type =
1997 cpu_to_le16(LOG_FREEXADLIST);
1998 xtlck = (struct xtlock *) & tlck->lock;
1999 hwm = xtlck->hwm.offset;
2000 lrd->log.updatemap.nxd =
2001 cpu_to_le16(hwm - next + 1);
2002
2003 xtlck->header.offset = next;
2004 xtlck->header.length = hwm - next + 1;
2005 xtlck->index = 1;
2006 lrd->backchain =
2007 cpu_to_le32(lmLog(log, tblk, lrd, tlck));
2008 }
2009
2010
2011
2012
2013 maplock->index = 0;
2014
2015
2016
2017
2018 if (lwm < next) {
2019
2020
2021
2022
2023
2024 tlck->flag |= tlckUPDATEMAP;
2025 xadlock->flag = mlckALLOCXADLIST;
2026 xadlock->count = next - lwm;
2027 xadlock->xdlist = &p->xad[lwm];
2028
2029 jfs_info("xtLog: alloc ip:0x%p mp:0x%p count:%d "
2030 "lwm:%d next:%d",
2031 tlck->ip, mp, xadlock->count, lwm, next);
2032 maplock->index++;
2033 xadlock++;
2034 }
2035
2036
2037
2038
2039 if (twm == next - 1) {
2040
2041
2042
2043
2044
2045 tlck->flag |= tlckUPDATEMAP;
2046 pxdlock = (struct pxd_lock *) xadlock;
2047 pxdlock->flag = mlckFREEPXD;
2048 pxdlock->count = 1;
2049 pxdlock->pxd = pxd;
2050
2051 jfs_info("xtLog: truncate ip:0x%p mp:0x%p count:%d "
2052 "hwm:%d", ip, mp, pxdlock->count, hwm);
2053 maplock->index++;
2054 xadlock++;
2055 }
2056
2057
2058
2059
2060 if (hwm >= next) {
2061
2062
2063
2064
2065 tlck->flag |= tlckUPDATEMAP;
2066 xadlock->flag = mlckFREEXADLIST;
2067 xadlock->count = hwm - next + 1;
2068 xadlock->xdlist = &p->xad[next];
2069
2070 jfs_info("xtLog: free ip:0x%p mp:0x%p count:%d "
2071 "next:%d hwm:%d",
2072 tlck->ip, mp, xadlock->count, next, hwm);
2073 maplock->index++;
2074 }
2075
2076
2077 tlck->flag |= tlckWRITEPAGE;
2078 }
2079 return;
2080}
2081
2082
2083
2084
2085
2086
2087static void mapLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
2088 struct tlock * tlck)
2089{
2090 struct pxd_lock *pxdlock;
2091 int i, nlock;
2092 pxd_t *pxd;
2093
2094
2095
2096
2097
2098
2099
2100
2101 if (tlck->type & tlckRELOCATE) {
2102
2103
2104
2105 lrd->type = cpu_to_le16(LOG_NOREDOPAGE);
2106 pxdlock = (struct pxd_lock *) & tlck->lock;
2107 pxd = &lrd->log.redopage.pxd;
2108 *pxd = pxdlock->pxd;
2109 lrd->backchain = cpu_to_le32(lmLog(log, tblk, lrd, NULL));
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121 lrd->type = cpu_to_le16(LOG_UPDATEMAP);
2122 lrd->log.updatemap.type = cpu_to_le16(LOG_FREEPXD);
2123 lrd->log.updatemap.nxd = cpu_to_le16(1);
2124 lrd->log.updatemap.pxd = pxdlock->pxd;
2125 lrd->backchain = cpu_to_le32(lmLog(log, tblk, lrd, NULL));
2126
2127
2128
2129
2130 tlck->flag |= tlckUPDATEMAP;
2131 return;
2132 }
2133
2134
2135
2136
2137
2138 else {
2139
2140
2141
2142
2143
2144 lrd->type = cpu_to_le16(LOG_UPDATEMAP);
2145 pxdlock = (struct pxd_lock *) & tlck->lock;
2146 nlock = pxdlock->index;
2147 for (i = 0; i < nlock; i++, pxdlock++) {
2148 if (pxdlock->flag & mlckALLOCPXD)
2149 lrd->log.updatemap.type =
2150 cpu_to_le16(LOG_ALLOCPXD);
2151 else
2152 lrd->log.updatemap.type =
2153 cpu_to_le16(LOG_FREEPXD);
2154 lrd->log.updatemap.nxd = cpu_to_le16(1);
2155 lrd->log.updatemap.pxd = pxdlock->pxd;
2156 lrd->backchain =
2157 cpu_to_le32(lmLog(log, tblk, lrd, NULL));
2158 jfs_info("mapLog: xaddr:0x%lx xlen:0x%x",
2159 (ulong) addressPXD(&pxdlock->pxd),
2160 lengthPXD(&pxdlock->pxd));
2161 }
2162
2163
2164 tlck->flag |= tlckUPDATEMAP;
2165 }
2166}
2167
2168
2169
2170
2171
2172
2173
2174void txEA(tid_t tid, struct inode *ip, dxd_t * oldea, dxd_t * newea)
2175{
2176 struct tlock *tlck = NULL;
2177 struct pxd_lock *maplock = NULL, *pxdlock = NULL;
2178
2179
2180
2181
2182 if (newea) {
2183
2184
2185
2186
2187 if (newea->flag & DXD_EXTENT) {
2188 tlck = txMaplock(tid, ip, tlckMAP);
2189 maplock = (struct pxd_lock *) & tlck->lock;
2190 pxdlock = (struct pxd_lock *) maplock;
2191 pxdlock->flag = mlckALLOCPXD;
2192 PXDaddress(&pxdlock->pxd, addressDXD(newea));
2193 PXDlength(&pxdlock->pxd, lengthDXD(newea));
2194 pxdlock++;
2195 maplock->index = 1;
2196 } else if (newea->flag & DXD_INLINE) {
2197 tlck = NULL;
2198
2199 set_cflag(COMMIT_Inlineea, ip);
2200 }
2201 }
2202
2203
2204
2205
2206 if (!test_cflag(COMMIT_Nolink, ip) && oldea->flag & DXD_EXTENT) {
2207 if (tlck == NULL) {
2208 tlck = txMaplock(tid, ip, tlckMAP);
2209 maplock = (struct pxd_lock *) & tlck->lock;
2210 pxdlock = (struct pxd_lock *) maplock;
2211 maplock->index = 0;
2212 }
2213 pxdlock->flag = mlckFREEPXD;
2214 PXDaddress(&pxdlock->pxd, addressDXD(oldea));
2215 PXDlength(&pxdlock->pxd, lengthDXD(oldea));
2216 maplock->index++;
2217 }
2218}
2219
2220
2221
2222
2223
2224
2225
2226static void txForce(struct tblock * tblk)
2227{
2228 struct tlock *tlck;
2229 lid_t lid, next;
2230 struct metapage *mp;
2231
2232
2233
2234
2235
2236
2237 tlck = lid_to_tlock(tblk->next);
2238 lid = tlck->next;
2239 tlck->next = 0;
2240 while (lid) {
2241 tlck = lid_to_tlock(lid);
2242 next = tlck->next;
2243 tlck->next = tblk->next;
2244 tblk->next = lid;
2245 lid = next;
2246 }
2247
2248
2249
2250
2251
2252 for (lid = tblk->next; lid; lid = next) {
2253 tlck = lid_to_tlock(lid);
2254 next = tlck->next;
2255
2256 if ((mp = tlck->mp) != NULL &&
2257 (tlck->type & tlckBTROOT) == 0) {
2258 assert(mp->xflag & COMMIT_PAGE);
2259
2260 if (tlck->flag & tlckWRITEPAGE) {
2261 tlck->flag &= ~tlckWRITEPAGE;
2262
2263
2264 force_metapage(mp);
2265#if 0
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277 assert(mp->nohomeok);
2278 set_bit(META_dirty, &mp->flag);
2279 set_bit(META_sync, &mp->flag);
2280#endif
2281 }
2282 }
2283 }
2284}
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294static void txUpdateMap(struct tblock * tblk)
2295{
2296 struct inode *ip;
2297 struct inode *ipimap;
2298 lid_t lid;
2299 struct tlock *tlck;
2300 struct maplock *maplock;
2301 struct pxd_lock pxdlock;
2302 int maptype;
2303 int k, nlock;
2304 struct metapage *mp = NULL;
2305
2306 ipimap = JFS_SBI(tblk->sb)->ipimap;
2307
2308 maptype = (tblk->xflag & COMMIT_PMAP) ? COMMIT_PMAP : COMMIT_PWMAP;
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323 for (lid = tblk->next; lid; lid = tlck->next) {
2324 tlck = lid_to_tlock(lid);
2325
2326 if ((tlck->flag & tlckUPDATEMAP) == 0)
2327 continue;
2328
2329 if (tlck->flag & tlckFREEPAGE) {
2330
2331
2332
2333
2334
2335
2336
2337 mp = tlck->mp;
2338 ASSERT(mp->xflag & COMMIT_PAGE);
2339 grab_metapage(mp);
2340 }
2341
2342
2343
2344
2345
2346
2347 maplock = (struct maplock *) & tlck->lock;
2348 nlock = maplock->index;
2349
2350 for (k = 0; k < nlock; k++, maplock++) {
2351
2352
2353
2354
2355
2356 if (maplock->flag & mlckALLOC) {
2357 txAllocPMap(ipimap, maplock, tblk);
2358 }
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373 else {
2374
2375 if (tlck->flag & tlckDIRECTORY)
2376 txFreeMap(ipimap, maplock,
2377 tblk, COMMIT_PWMAP);
2378 else
2379 txFreeMap(ipimap, maplock,
2380 tblk, maptype);
2381 }
2382 }
2383 if (tlck->flag & tlckFREEPAGE) {
2384 if (!(tblk->flag & tblkGC_LAZY)) {
2385
2386 ASSERT(mp->lid == lid);
2387 tlck->mp->lid = 0;
2388 }
2389 assert(mp->nohomeok == 1);
2390 metapage_homeok(mp);
2391 discard_metapage(mp);
2392 tlck->mp = NULL;
2393 }
2394 }
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404 if (tblk->xflag & COMMIT_CREATE) {
2405 diUpdatePMap(ipimap, tblk->ino, false, tblk);
2406
2407
2408
2409 pxdlock.flag = mlckALLOCPXD;
2410 pxdlock.pxd = tblk->u.ixpxd;
2411 pxdlock.index = 1;
2412 txAllocPMap(ipimap, (struct maplock *) & pxdlock, tblk);
2413 } else if (tblk->xflag & COMMIT_DELETE) {
2414 ip = tblk->u.ip;
2415 diUpdatePMap(ipimap, ip->i_ino, true, tblk);
2416 iput(ip);
2417 }
2418}
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440static void txAllocPMap(struct inode *ip, struct maplock * maplock,
2441 struct tblock * tblk)
2442{
2443 struct inode *ipbmap = JFS_SBI(ip->i_sb)->ipbmap;
2444 struct xdlistlock *xadlistlock;
2445 xad_t *xad;
2446 s64 xaddr;
2447 int xlen;
2448 struct pxd_lock *pxdlock;
2449 struct xdlistlock *pxdlistlock;
2450 pxd_t *pxd;
2451 int n;
2452
2453
2454
2455
2456 if (maplock->flag & mlckALLOCXADLIST) {
2457 xadlistlock = (struct xdlistlock *) maplock;
2458 xad = xadlistlock->xdlist;
2459 for (n = 0; n < xadlistlock->count; n++, xad++) {
2460 if (xad->flag & (XAD_NEW | XAD_EXTENDED)) {
2461 xaddr = addressXAD(xad);
2462 xlen = lengthXAD(xad);
2463 dbUpdatePMap(ipbmap, false, xaddr,
2464 (s64) xlen, tblk);
2465 xad->flag &= ~(XAD_NEW | XAD_EXTENDED);
2466 jfs_info("allocPMap: xaddr:0x%lx xlen:%d",
2467 (ulong) xaddr, xlen);
2468 }
2469 }
2470 } else if (maplock->flag & mlckALLOCPXD) {
2471 pxdlock = (struct pxd_lock *) maplock;
2472 xaddr = addressPXD(&pxdlock->pxd);
2473 xlen = lengthPXD(&pxdlock->pxd);
2474 dbUpdatePMap(ipbmap, false, xaddr, (s64) xlen, tblk);
2475 jfs_info("allocPMap: xaddr:0x%lx xlen:%d", (ulong) xaddr, xlen);
2476 } else {
2477
2478 pxdlistlock = (struct xdlistlock *) maplock;
2479 pxd = pxdlistlock->xdlist;
2480 for (n = 0; n < pxdlistlock->count; n++, pxd++) {
2481 xaddr = addressPXD(pxd);
2482 xlen = lengthPXD(pxd);
2483 dbUpdatePMap(ipbmap, false, xaddr, (s64) xlen,
2484 tblk);
2485 jfs_info("allocPMap: xaddr:0x%lx xlen:%d",
2486 (ulong) xaddr, xlen);
2487 }
2488 }
2489}
2490
2491
2492
2493
2494
2495
2496
2497
2498void txFreeMap(struct inode *ip,
2499 struct maplock * maplock, struct tblock * tblk, int maptype)
2500{
2501 struct inode *ipbmap = JFS_SBI(ip->i_sb)->ipbmap;
2502 struct xdlistlock *xadlistlock;
2503 xad_t *xad;
2504 s64 xaddr;
2505 int xlen;
2506 struct pxd_lock *pxdlock;
2507 struct xdlistlock *pxdlistlock;
2508 pxd_t *pxd;
2509 int n;
2510
2511 jfs_info("txFreeMap: tblk:0x%p maplock:0x%p maptype:0x%x",
2512 tblk, maplock, maptype);
2513
2514
2515
2516
2517 if (maptype == COMMIT_PMAP || maptype == COMMIT_PWMAP) {
2518 if (maplock->flag & mlckFREEXADLIST) {
2519 xadlistlock = (struct xdlistlock *) maplock;
2520 xad = xadlistlock->xdlist;
2521 for (n = 0; n < xadlistlock->count; n++, xad++) {
2522 if (!(xad->flag & XAD_NEW)) {
2523 xaddr = addressXAD(xad);
2524 xlen = lengthXAD(xad);
2525 dbUpdatePMap(ipbmap, true, xaddr,
2526 (s64) xlen, tblk);
2527 jfs_info("freePMap: xaddr:0x%lx "
2528 "xlen:%d",
2529 (ulong) xaddr, xlen);
2530 }
2531 }
2532 } else if (maplock->flag & mlckFREEPXD) {
2533 pxdlock = (struct pxd_lock *) maplock;
2534 xaddr = addressPXD(&pxdlock->pxd);
2535 xlen = lengthPXD(&pxdlock->pxd);
2536 dbUpdatePMap(ipbmap, true, xaddr, (s64) xlen,
2537 tblk);
2538 jfs_info("freePMap: xaddr:0x%lx xlen:%d",
2539 (ulong) xaddr, xlen);
2540 } else {
2541
2542 pxdlistlock = (struct xdlistlock *) maplock;
2543 pxd = pxdlistlock->xdlist;
2544 for (n = 0; n < pxdlistlock->count; n++, pxd++) {
2545 xaddr = addressPXD(pxd);
2546 xlen = lengthPXD(pxd);
2547 dbUpdatePMap(ipbmap, true, xaddr,
2548 (s64) xlen, tblk);
2549 jfs_info("freePMap: xaddr:0x%lx xlen:%d",
2550 (ulong) xaddr, xlen);
2551 }
2552 }
2553 }
2554
2555
2556
2557
2558 if (maptype == COMMIT_PWMAP || maptype == COMMIT_WMAP) {
2559 if (maplock->flag & mlckFREEXADLIST) {
2560 xadlistlock = (struct xdlistlock *) maplock;
2561 xad = xadlistlock->xdlist;
2562 for (n = 0; n < xadlistlock->count; n++, xad++) {
2563 xaddr = addressXAD(xad);
2564 xlen = lengthXAD(xad);
2565 dbFree(ip, xaddr, (s64) xlen);
2566 xad->flag = 0;
2567 jfs_info("freeWMap: xaddr:0x%lx xlen:%d",
2568 (ulong) xaddr, xlen);
2569 }
2570 } else if (maplock->flag & mlckFREEPXD) {
2571 pxdlock = (struct pxd_lock *) maplock;
2572 xaddr = addressPXD(&pxdlock->pxd);
2573 xlen = lengthPXD(&pxdlock->pxd);
2574 dbFree(ip, xaddr, (s64) xlen);
2575 jfs_info("freeWMap: xaddr:0x%lx xlen:%d",
2576 (ulong) xaddr, xlen);
2577 } else {
2578
2579 pxdlistlock = (struct xdlistlock *) maplock;
2580 pxd = pxdlistlock->xdlist;
2581 for (n = 0; n < pxdlistlock->count; n++, pxd++) {
2582 xaddr = addressPXD(pxd);
2583 xlen = lengthPXD(pxd);
2584 dbFree(ip, xaddr, (s64) xlen);
2585 jfs_info("freeWMap: xaddr:0x%lx xlen:%d",
2586 (ulong) xaddr, xlen);
2587 }
2588 }
2589 }
2590}
2591
2592
2593
2594
2595
2596
2597void txFreelock(struct inode *ip)
2598{
2599 struct jfs_inode_info *jfs_ip = JFS_IP(ip);
2600 struct tlock *xtlck, *tlck;
2601 lid_t xlid = 0, lid;
2602
2603 if (!jfs_ip->atlhead)
2604 return;
2605
2606 TXN_LOCK();
2607 xtlck = (struct tlock *) &jfs_ip->atlhead;
2608
2609 while ((lid = xtlck->next) != 0) {
2610 tlck = lid_to_tlock(lid);
2611 if (tlck->flag & tlckFREELOCK) {
2612 xtlck->next = tlck->next;
2613 txLockFree(lid);
2614 } else {
2615 xtlck = tlck;
2616 xlid = lid;
2617 }
2618 }
2619
2620 if (jfs_ip->atlhead)
2621 jfs_ip->atltail = xlid;
2622 else {
2623 jfs_ip->atltail = 0;
2624
2625
2626
2627 list_del_init(&jfs_ip->anon_inode_list);
2628 }
2629 TXN_UNLOCK();
2630}
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643void txAbort(tid_t tid, int dirty)
2644{
2645 lid_t lid, next;
2646 struct metapage *mp;
2647 struct tblock *tblk = tid_to_tblock(tid);
2648 struct tlock *tlck;
2649
2650
2651
2652
2653 for (lid = tblk->next; lid; lid = next) {
2654 tlck = lid_to_tlock(lid);
2655 next = tlck->next;
2656 mp = tlck->mp;
2657 JFS_IP(tlck->ip)->xtlid = 0;
2658
2659 if (mp) {
2660 mp->lid = 0;
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670 if (mp->xflag & COMMIT_PAGE && mp->lsn)
2671 LogSyncRelease(mp);
2672 }
2673
2674 TXN_LOCK();
2675 txLockFree(lid);
2676 TXN_UNLOCK();
2677 }
2678
2679
2680
2681 tblk->next = tblk->last = 0;
2682
2683
2684
2685
2686 if (dirty)
2687 jfs_error(tblk->sb, "\n");
2688
2689 return;
2690}
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700static void txLazyCommit(struct tblock * tblk)
2701{
2702 struct jfs_log *log;
2703
2704 while (((tblk->flag & tblkGC_READY) == 0) &&
2705 ((tblk->flag & tblkGC_UNLOCKED) == 0)) {
2706
2707
2708 jfs_info("jfs_lazycommit: tblk 0x%p not unlocked", tblk);
2709 yield();
2710 }
2711
2712 jfs_info("txLazyCommit: processing tblk 0x%p", tblk);
2713
2714 txUpdateMap(tblk);
2715
2716 log = (struct jfs_log *) JFS_SBI(tblk->sb)->log;
2717
2718 spin_lock_irq(&log->gclock);
2719
2720 tblk->flag |= tblkGC_COMMITTED;
2721
2722 if (tblk->flag & tblkGC_READY)
2723 log->gcrtc--;
2724
2725 wake_up_all(&tblk->gcwait);
2726
2727
2728
2729
2730 if (tblk->flag & tblkGC_LAZY) {
2731 spin_unlock_irq(&log->gclock);
2732 txUnlock(tblk);
2733 tblk->flag &= ~tblkGC_LAZY;
2734 txEnd(tblk - TxBlock);
2735 } else
2736 spin_unlock_irq(&log->gclock);
2737
2738 jfs_info("txLazyCommit: done: tblk = 0x%p", tblk);
2739}
2740
2741
2742
2743
2744
2745
2746
2747
2748int jfs_lazycommit(void *arg)
2749{
2750 int WorkDone;
2751 struct tblock *tblk;
2752 unsigned long flags;
2753 struct jfs_sb_info *sbi;
2754
2755 do {
2756 LAZY_LOCK(flags);
2757 jfs_commit_thread_waking = 0;
2758 while (!list_empty(&TxAnchor.unlock_queue)) {
2759 WorkDone = 0;
2760 list_for_each_entry(tblk, &TxAnchor.unlock_queue,
2761 cqueue) {
2762
2763 sbi = JFS_SBI(tblk->sb);
2764
2765
2766
2767
2768
2769
2770 if (sbi->commit_state & IN_LAZYCOMMIT)
2771 continue;
2772
2773 sbi->commit_state |= IN_LAZYCOMMIT;
2774 WorkDone = 1;
2775
2776
2777
2778
2779 list_del(&tblk->cqueue);
2780
2781 LAZY_UNLOCK(flags);
2782 txLazyCommit(tblk);
2783 LAZY_LOCK(flags);
2784
2785 sbi->commit_state &= ~IN_LAZYCOMMIT;
2786
2787
2788
2789
2790
2791 break;
2792 }
2793
2794
2795 if (!WorkDone)
2796 break;
2797 }
2798
2799 jfs_commit_thread_waking = 0;
2800
2801 if (freezing(current)) {
2802 LAZY_UNLOCK(flags);
2803 try_to_freeze();
2804 } else {
2805 DECLARE_WAITQUEUE(wq, current);
2806
2807 add_wait_queue(&jfs_commit_thread_wait, &wq);
2808 set_current_state(TASK_INTERRUPTIBLE);
2809 LAZY_UNLOCK(flags);
2810 schedule();
2811 __set_current_state(TASK_RUNNING);
2812 remove_wait_queue(&jfs_commit_thread_wait, &wq);
2813 }
2814 } while (!kthread_should_stop());
2815
2816 if (!list_empty(&TxAnchor.unlock_queue))
2817 jfs_err("jfs_lazycommit being killed w/pending transactions!");
2818 else
2819 jfs_info("jfs_lazycommit being killed\n");
2820 return 0;
2821}
2822
2823void txLazyUnlock(struct tblock * tblk)
2824{
2825 unsigned long flags;
2826
2827 LAZY_LOCK(flags);
2828
2829 list_add_tail(&tblk->cqueue, &TxAnchor.unlock_queue);
2830
2831
2832
2833
2834 if (!(JFS_SBI(tblk->sb)->commit_state & IN_LAZYCOMMIT) &&
2835 !jfs_commit_thread_waking) {
2836 jfs_commit_thread_waking = 1;
2837 wake_up(&jfs_commit_thread_wait);
2838 }
2839 LAZY_UNLOCK(flags);
2840}
2841
2842static void LogSyncRelease(struct metapage * mp)
2843{
2844 struct jfs_log *log = mp->log;
2845
2846 assert(mp->nohomeok);
2847 assert(log);
2848 metapage_homeok(mp);
2849}
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861void txQuiesce(struct super_block *sb)
2862{
2863 struct inode *ip;
2864 struct jfs_inode_info *jfs_ip;
2865 struct jfs_log *log = JFS_SBI(sb)->log;
2866 tid_t tid;
2867
2868 set_bit(log_QUIESCE, &log->flag);
2869
2870 TXN_LOCK();
2871restart:
2872 while (!list_empty(&TxAnchor.anon_list)) {
2873 jfs_ip = list_entry(TxAnchor.anon_list.next,
2874 struct jfs_inode_info,
2875 anon_inode_list);
2876 ip = &jfs_ip->vfs_inode;
2877
2878
2879
2880
2881
2882 TXN_UNLOCK();
2883 tid = txBegin(ip->i_sb, COMMIT_INODE | COMMIT_FORCE);
2884 mutex_lock(&jfs_ip->commit_mutex);
2885 txCommit(tid, 1, &ip, 0);
2886 txEnd(tid);
2887 mutex_unlock(&jfs_ip->commit_mutex);
2888
2889
2890
2891
2892 cond_resched();
2893 TXN_LOCK();
2894 }
2895
2896
2897
2898
2899
2900 if (!list_empty(&TxAnchor.anon_list2)) {
2901 list_splice(&TxAnchor.anon_list2, &TxAnchor.anon_list);
2902 INIT_LIST_HEAD(&TxAnchor.anon_list2);
2903 goto restart;
2904 }
2905 TXN_UNLOCK();
2906
2907
2908
2909
2910 jfs_flush_journal(log, 0);
2911}
2912
2913
2914
2915
2916
2917
2918void txResume(struct super_block *sb)
2919{
2920 struct jfs_log *log = JFS_SBI(sb)->log;
2921
2922 clear_bit(log_QUIESCE, &log->flag);
2923 TXN_WAKEUP(&log->syncwait);
2924}
2925
2926
2927
2928
2929
2930
2931
2932
2933int jfs_sync(void *arg)
2934{
2935 struct inode *ip;
2936 struct jfs_inode_info *jfs_ip;
2937 tid_t tid;
2938
2939 do {
2940
2941
2942
2943 TXN_LOCK();
2944 while (jfs_tlocks_low && !list_empty(&TxAnchor.anon_list)) {
2945 jfs_ip = list_entry(TxAnchor.anon_list.next,
2946 struct jfs_inode_info,
2947 anon_inode_list);
2948 ip = &jfs_ip->vfs_inode;
2949
2950 if (! igrab(ip)) {
2951
2952
2953
2954 list_del_init(&jfs_ip->anon_inode_list);
2955 } else if (mutex_trylock(&jfs_ip->commit_mutex)) {
2956
2957
2958
2959
2960 TXN_UNLOCK();
2961 tid = txBegin(ip->i_sb, COMMIT_INODE);
2962 txCommit(tid, 1, &ip, 0);
2963 txEnd(tid);
2964 mutex_unlock(&jfs_ip->commit_mutex);
2965
2966 iput(ip);
2967
2968
2969
2970
2971 cond_resched();
2972 TXN_LOCK();
2973 } else {
2974
2975
2976
2977
2978
2979
2980
2981 list_move(&jfs_ip->anon_inode_list,
2982 &TxAnchor.anon_list2);
2983
2984 TXN_UNLOCK();
2985 iput(ip);
2986 TXN_LOCK();
2987 }
2988 }
2989
2990 list_splice_init(&TxAnchor.anon_list2, &TxAnchor.anon_list);
2991
2992 if (freezing(current)) {
2993 TXN_UNLOCK();
2994 try_to_freeze();
2995 } else {
2996 set_current_state(TASK_INTERRUPTIBLE);
2997 TXN_UNLOCK();
2998 schedule();
2999 __set_current_state(TASK_RUNNING);
3000 }
3001 } while (!kthread_should_stop());
3002
3003 jfs_info("jfs_sync being killed");
3004 return 0;
3005}
3006
3007#if defined(CONFIG_PROC_FS) && defined(CONFIG_JFS_DEBUG)
3008static int jfs_txanchor_proc_show(struct seq_file *m, void *v)
3009{
3010 char *freewait;
3011 char *freelockwait;
3012 char *lowlockwait;
3013
3014 freewait =
3015 waitqueue_active(&TxAnchor.freewait) ? "active" : "empty";
3016 freelockwait =
3017 waitqueue_active(&TxAnchor.freelockwait) ? "active" : "empty";
3018 lowlockwait =
3019 waitqueue_active(&TxAnchor.lowlockwait) ? "active" : "empty";
3020
3021 seq_printf(m,
3022 "JFS TxAnchor\n"
3023 "============\n"
3024 "freetid = %d\n"
3025 "freewait = %s\n"
3026 "freelock = %d\n"
3027 "freelockwait = %s\n"
3028 "lowlockwait = %s\n"
3029 "tlocksInUse = %d\n"
3030 "jfs_tlocks_low = %d\n"
3031 "unlock_queue is %sempty\n",
3032 TxAnchor.freetid,
3033 freewait,
3034 TxAnchor.freelock,
3035 freelockwait,
3036 lowlockwait,
3037 TxAnchor.tlocksInUse,
3038 jfs_tlocks_low,
3039 list_empty(&TxAnchor.unlock_queue) ? "" : "not ");
3040 return 0;
3041}
3042
3043static int jfs_txanchor_proc_open(struct inode *inode, struct file *file)
3044{
3045 return single_open(file, jfs_txanchor_proc_show, NULL);
3046}
3047
3048const struct file_operations jfs_txanchor_proc_fops = {
3049 .owner = THIS_MODULE,
3050 .open = jfs_txanchor_proc_open,
3051 .read = seq_read,
3052 .llseek = seq_lseek,
3053 .release = single_release,
3054};
3055#endif
3056
3057#if defined(CONFIG_PROC_FS) && defined(CONFIG_JFS_STATISTICS)
3058static int jfs_txstats_proc_show(struct seq_file *m, void *v)
3059{
3060 seq_printf(m,
3061 "JFS TxStats\n"
3062 "===========\n"
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",
3072 TxStat.txBegin,
3073 TxStat.txBegin_barrier,
3074 TxStat.txBegin_lockslow,
3075 TxStat.txBegin_freetid,
3076 TxStat.txBeginAnon,
3077 TxStat.txBeginAnon_barrier,
3078 TxStat.txBeginAnon_lockslow,
3079 TxStat.txLockAlloc,
3080 TxStat.txLockAlloc_freelock);
3081 return 0;
3082}
3083
3084static int jfs_txstats_proc_open(struct inode *inode, struct file *file)
3085{
3086 return single_open(file, jfs_txstats_proc_show, NULL);
3087}
3088
3089const struct file_operations jfs_txstats_proc_fops = {
3090 .owner = THIS_MODULE,
3091 .open = jfs_txstats_proc_open,
3092 .read = seq_read,
3093 .llseek = seq_lseek,
3094 .release = single_release,
3095};
3096#endif
3097