1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22#include <linux/fs.h>
23#include <linux/module.h>
24#include <linux/quotaops.h>
25#include <linux/seq_file.h>
26#include "jfs_incore.h"
27#include "jfs_filsys.h"
28#include "jfs_metapage.h"
29#include "jfs_dmap.h"
30#include "jfs_dinode.h"
31#include "jfs_superblock.h"
32#include "jfs_debug.h"
33
34
35
36
37#define XT_INSERT 0x00000001
38
39
40
41
42
43
44
45
46
47#define XT_CMP(CMP, K, X, OFFSET64)\
48{\
49 OFFSET64 = offsetXAD(X);\
50 (CMP) = ((K) >= OFFSET64 + lengthXAD(X)) ? 1 :\
51 ((K) < OFFSET64) ? -1 : 0;\
52}
53
54
55#define XT_PUTENTRY(XAD, FLAG, OFF, LEN, ADDR)\
56{\
57 (XAD)->flag = (FLAG);\
58 XADoffset((XAD), (OFF));\
59 XADlength((XAD), (LEN));\
60 XADaddress((XAD), (ADDR));\
61}
62
63#define XT_PAGE(IP, MP) BT_PAGE(IP, MP, xtpage_t, i_xtroot)
64
65
66
67#define XT_GETPAGE(IP, BN, MP, SIZE, P, RC) \
68do { \
69 BT_GETPAGE(IP, BN, MP, xtpage_t, SIZE, P, RC, i_xtroot); \
70 if (!(RC)) { \
71 if ((le16_to_cpu((P)->header.nextindex) < XTENTRYSTART) || \
72 (le16_to_cpu((P)->header.nextindex) > \
73 le16_to_cpu((P)->header.maxentry)) || \
74 (le16_to_cpu((P)->header.maxentry) > \
75 (((BN) == 0) ? XTROOTMAXSLOT : PSIZE >> L2XTSLOTSIZE))) { \
76 jfs_error((IP)->i_sb, \
77 "XT_GETPAGE: xtree page corrupt\n"); \
78 BT_PUTPAGE(MP); \
79 MP = NULL; \
80 RC = -EIO; \
81 } \
82 } \
83} while (0)
84
85
86#define XT_PUTPAGE(MP) BT_PUTPAGE(MP)
87
88#define XT_GETSEARCH(IP, LEAF, BN, MP, P, INDEX) \
89 BT_GETSEARCH(IP, LEAF, BN, MP, xtpage_t, P, INDEX, i_xtroot)
90
91struct xtsplit {
92 struct metapage *mp;
93 s16 index;
94 u8 flag;
95 s64 off;
96 s64 addr;
97 int len;
98 struct pxdlist *pxdlist;
99};
100
101
102
103
104
105#ifdef CONFIG_JFS_STATISTICS
106static struct {
107 uint search;
108 uint fastSearch;
109 uint split;
110} xtStat;
111#endif
112
113
114
115
116
117static int xtSearch(struct inode *ip, s64 xoff, s64 *next, int *cmpp,
118 struct btstack * btstack, int flag);
119
120static int xtSplitUp(tid_t tid,
121 struct inode *ip,
122 struct xtsplit * split, struct btstack * btstack);
123
124static int xtSplitPage(tid_t tid, struct inode *ip, struct xtsplit * split,
125 struct metapage ** rmpp, s64 * rbnp);
126
127static int xtSplitRoot(tid_t tid, struct inode *ip,
128 struct xtsplit * split, struct metapage ** rmpp);
129
130#ifdef _STILL_TO_PORT
131static int xtDeleteUp(tid_t tid, struct inode *ip, struct metapage * fmp,
132 xtpage_t * fp, struct btstack * btstack);
133
134static int xtSearchNode(struct inode *ip,
135 xad_t * xad,
136 int *cmpp, struct btstack * btstack, int flag);
137
138static int xtRelink(tid_t tid, struct inode *ip, xtpage_t * fp);
139#endif
140
141
142
143
144
145
146int xtLookup(struct inode *ip, s64 lstart,
147 s64 llen, int *pflag, s64 * paddr, s32 * plen, int no_check)
148{
149 int rc = 0;
150 struct btstack btstack;
151 int cmp;
152 s64 bn;
153 struct metapage *mp;
154 xtpage_t *p;
155 int index;
156 xad_t *xad;
157 s64 next, size, xoff, xend;
158 int xlen;
159 s64 xaddr;
160
161 *paddr = 0;
162 *plen = llen;
163
164 if (!no_check) {
165
166 size = ((u64) ip->i_size + (JFS_SBI(ip->i_sb)->bsize - 1)) >>
167 JFS_SBI(ip->i_sb)->l2bsize;
168 if (lstart >= size)
169 return 0;
170 }
171
172
173
174
175
176 if ((rc = xtSearch(ip, lstart, &next, &cmp, &btstack, 0))) {
177 jfs_err("xtLookup: xtSearch returned %d", rc);
178 return rc;
179 }
180
181
182
183
184
185
186
187
188 XT_GETSEARCH(ip, btstack.top, bn, mp, p, index);
189
190
191
192
193
194 if (cmp) {
195 if (next)
196 *plen = min(next - lstart, llen);
197 goto out;
198 }
199
200
201
202
203 xad = &p->xad[index];
204 xoff = offsetXAD(xad);
205 xlen = lengthXAD(xad);
206 xend = xoff + xlen;
207 xaddr = addressXAD(xad);
208
209
210 *pflag = xad->flag;
211 *paddr = xaddr + (lstart - xoff);
212
213 *plen = min(xend - lstart, llen);
214
215 out:
216 XT_PUTPAGE(mp);
217
218 return rc;
219}
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239static int xtSearch(struct inode *ip, s64 xoff, s64 *nextp,
240 int *cmpp, struct btstack * btstack, int flag)
241{
242 struct jfs_inode_info *jfs_ip = JFS_IP(ip);
243 int rc = 0;
244 int cmp = 1;
245 s64 bn;
246 struct metapage *mp;
247 xtpage_t *p;
248 xad_t *xad;
249 int base, index, lim, btindex;
250 struct btframe *btsp;
251 int nsplit = 0;
252 s64 t64;
253 s64 next = 0;
254
255 INCREMENT(xtStat.search);
256
257 BT_CLR(btstack);
258
259 btstack->nsplit = 0;
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277 for (bn = 0;;) {
278
279 XT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
280 if (rc)
281 return rc;
282
283
284
285
286
287
288
289
290 if ((jfs_ip->btorder & BT_SEQUENTIAL) &&
291 (p->header.flag & BT_LEAF) &&
292 (index = jfs_ip->btindex) <
293 le16_to_cpu(p->header.nextindex)) {
294 xad = &p->xad[index];
295 t64 = offsetXAD(xad);
296 if (xoff < t64 + lengthXAD(xad)) {
297 if (xoff >= t64) {
298 *cmpp = 0;
299 goto out;
300 }
301
302
303 goto binarySearch;
304 } else {
305
306
307 index++;
308 if (index <
309 le16_to_cpu(p->header.nextindex)) {
310 xad++;
311 t64 = offsetXAD(xad);
312 if (xoff < t64 + lengthXAD(xad)) {
313 if (xoff >= t64) {
314 *cmpp = 0;
315 goto out;
316 }
317
318
319
320
321 *cmpp = 1;
322 next = t64;
323 goto out;
324 }
325
326
327
328
329
330
331 goto binarySearch;
332 }
333
334
335
336
337
338 *cmpp = 1;
339 goto out;
340 }
341
342
343
344
345
346
347 out:
348
349 if (flag & XT_INSERT) {
350 if (p->header.nextindex ==
351 p->header.maxentry)
352 nsplit++;
353 else
354 nsplit = 0;
355 btstack->nsplit = nsplit;
356 }
357
358
359 btsp = btstack->top;
360 btsp->bn = bn;
361 btsp->index = index;
362 btsp->mp = mp;
363
364
365 jfs_ip->btindex = index;
366
367 if (nextp)
368 *nextp = next;
369
370 INCREMENT(xtStat.fastSearch);
371 return 0;
372 }
373
374
375 binarySearch:
376 lim = le16_to_cpu(p->header.nextindex) - XTENTRYSTART;
377
378
379
380
381 for (base = XTENTRYSTART; lim; lim >>= 1) {
382 index = base + (lim >> 1);
383
384 XT_CMP(cmp, xoff, &p->xad[index], t64);
385 if (cmp == 0) {
386
387
388
389
390
391
392 if (p->header.flag & BT_LEAF) {
393 *cmpp = cmp;
394
395
396 if (flag & XT_INSERT) {
397 if (p->header.nextindex ==
398 p->header.maxentry)
399 nsplit++;
400 else
401 nsplit = 0;
402 btstack->nsplit = nsplit;
403 }
404
405
406 btsp = btstack->top;
407 btsp->bn = bn;
408 btsp->index = index;
409 btsp->mp = mp;
410
411
412 btindex = jfs_ip->btindex;
413 if (index == btindex ||
414 index == btindex + 1)
415 jfs_ip->btorder = BT_SEQUENTIAL;
416 else
417 jfs_ip->btorder = BT_RANDOM;
418 jfs_ip->btindex = index;
419
420 return 0;
421 }
422
423
424
425 if (index < le16_to_cpu(p->header.nextindex)-1)
426 next = offsetXAD(&p->xad[index + 1]);
427 goto next;
428 }
429
430 if (cmp > 0) {
431 base = index + 1;
432 --lim;
433 }
434 }
435
436
437
438
439
440
441
442 if (base < le16_to_cpu(p->header.nextindex))
443 next = offsetXAD(&p->xad[base]);
444
445
446
447
448
449
450 if (p->header.flag & BT_LEAF) {
451 *cmpp = cmp;
452
453
454 if (flag & XT_INSERT) {
455 if (p->header.nextindex ==
456 p->header.maxentry)
457 nsplit++;
458 else
459 nsplit = 0;
460 btstack->nsplit = nsplit;
461 }
462
463
464 btsp = btstack->top;
465 btsp->bn = bn;
466 btsp->index = base;
467 btsp->mp = mp;
468
469
470 btindex = jfs_ip->btindex;
471 if (base == btindex || base == btindex + 1)
472 jfs_ip->btorder = BT_SEQUENTIAL;
473 else
474 jfs_ip->btorder = BT_RANDOM;
475 jfs_ip->btindex = base;
476
477 if (nextp)
478 *nextp = next;
479
480 return 0;
481 }
482
483
484
485
486
487
488
489 index = base ? base - 1 : base;
490
491
492
493
494 next:
495
496 if (p->header.nextindex == p->header.maxentry)
497 nsplit++;
498 else
499 nsplit = 0;
500
501
502 if (BT_STACK_FULL(btstack)) {
503 jfs_error(ip->i_sb, "stack overrun!\n");
504 XT_PUTPAGE(mp);
505 return -EIO;
506 }
507 BT_PUSH(btstack, bn, index);
508
509
510 bn = addressXAD(&p->xad[index]);
511
512
513 XT_PUTPAGE(mp);
514 }
515}
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537int xtInsert(tid_t tid,
538 struct inode *ip, int xflag, s64 xoff, s32 xlen, s64 * xaddrp,
539 int flag)
540{
541 int rc = 0;
542 s64 xaddr, hint;
543 struct metapage *mp;
544 xtpage_t *p;
545 s64 bn;
546 int index, nextindex;
547 struct btstack btstack;
548 struct xtsplit split;
549 xad_t *xad;
550 int cmp;
551 s64 next;
552 struct tlock *tlck;
553 struct xtlock *xtlck;
554
555 jfs_info("xtInsert: nxoff:0x%lx nxlen:0x%x", (ulong) xoff, xlen);
556
557
558
559
560
561
562
563
564
565 if ((rc = xtSearch(ip, xoff, &next, &cmp, &btstack, XT_INSERT)))
566 return rc;
567
568
569 XT_GETSEARCH(ip, btstack.top, bn, mp, p, index);
570
571
572
573 if ((cmp == 0) || (next && (xlen > next - xoff))) {
574 rc = -EEXIST;
575 goto out;
576 }
577
578
579
580
581
582
583 if ((xaddr = *xaddrp) == 0) {
584 if (index > XTENTRYSTART) {
585 xad = &p->xad[index - 1];
586 hint = addressXAD(xad) + lengthXAD(xad) - 1;
587 } else
588 hint = 0;
589 if ((rc = dquot_alloc_block(ip, xlen)))
590 goto out;
591 if ((rc = dbAlloc(ip, hint, (s64) xlen, &xaddr))) {
592 dquot_free_block(ip, xlen);
593 goto out;
594 }
595 }
596
597
598
599
600 xflag |= XAD_NEW;
601
602
603
604
605
606
607
608 nextindex = le16_to_cpu(p->header.nextindex);
609 if (nextindex == le16_to_cpu(p->header.maxentry)) {
610 split.mp = mp;
611 split.index = index;
612 split.flag = xflag;
613 split.off = xoff;
614 split.len = xlen;
615 split.addr = xaddr;
616 split.pxdlist = NULL;
617 if ((rc = xtSplitUp(tid, ip, &split, &btstack))) {
618
619 if (*xaddrp == 0) {
620 dbFree(ip, xaddr, (s64) xlen);
621 dquot_free_block(ip, xlen);
622 }
623 return rc;
624 }
625
626 *xaddrp = xaddr;
627 return 0;
628 }
629
630
631
632
633
634
635
636
637
638 BT_MARK_DIRTY(mp, ip);
639
640
641 if (index < nextindex)
642 memmove(&p->xad[index + 1], &p->xad[index],
643 (nextindex - index) * sizeof(xad_t));
644
645
646 xad = &p->xad[index];
647 XT_PUTENTRY(xad, xflag, xoff, xlen, xaddr);
648
649
650 le16_add_cpu(&p->header.nextindex, 1);
651
652
653 if (!test_cflag(COMMIT_Nolink, ip)) {
654 tlck = txLock(tid, ip, mp, tlckXTREE | tlckGROW);
655 xtlck = (struct xtlock *) & tlck->lock;
656 xtlck->lwm.offset =
657 (xtlck->lwm.offset) ? min(index,
658 (int)xtlck->lwm.offset) : index;
659 xtlck->lwm.length =
660 le16_to_cpu(p->header.nextindex) - xtlck->lwm.offset;
661 }
662
663 *xaddrp = xaddr;
664
665 out:
666
667 XT_PUTPAGE(mp);
668
669 return rc;
670}
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687static int
688xtSplitUp(tid_t tid,
689 struct inode *ip, struct xtsplit * split, struct btstack * btstack)
690{
691 int rc = 0;
692 struct metapage *smp;
693 xtpage_t *sp;
694 struct metapage *rmp;
695 s64 rbn;
696 struct metapage *rcmp;
697 xtpage_t *rcp;
698 s64 rcbn;
699 int skip;
700 int nextindex;
701 struct btframe *parent;
702 xad_t *xad;
703 s64 xaddr;
704 int xlen;
705 int nsplit;
706 struct pxdlist pxdlist;
707 pxd_t *pxd;
708 struct tlock *tlck;
709 struct xtlock *xtlck;
710
711 smp = split->mp;
712 sp = XT_PAGE(ip, smp);
713
714
715 if ((sp->header.flag & BT_ROOT) && (!S_ISDIR(ip->i_mode)) &&
716 (le16_to_cpu(sp->header.maxentry) < XTROOTMAXSLOT) &&
717 (JFS_IP(ip)->mode2 & INLINEEA)) {
718 sp->header.maxentry = cpu_to_le16(XTROOTMAXSLOT);
719 JFS_IP(ip)->mode2 &= ~INLINEEA;
720
721 BT_MARK_DIRTY(smp, ip);
722
723
724
725
726
727
728
729 skip = split->index;
730 nextindex = le16_to_cpu(sp->header.nextindex);
731 if (skip < nextindex)
732 memmove(&sp->xad[skip + 1], &sp->xad[skip],
733 (nextindex - skip) * sizeof(xad_t));
734
735
736 xad = &sp->xad[skip];
737 XT_PUTENTRY(xad, split->flag, split->off, split->len,
738 split->addr);
739
740
741 le16_add_cpu(&sp->header.nextindex, 1);
742
743
744 if (!test_cflag(COMMIT_Nolink, ip)) {
745 tlck = txLock(tid, ip, smp, tlckXTREE | tlckGROW);
746 xtlck = (struct xtlock *) & tlck->lock;
747 xtlck->lwm.offset = (xtlck->lwm.offset) ?
748 min(skip, (int)xtlck->lwm.offset) : skip;
749 xtlck->lwm.length =
750 le16_to_cpu(sp->header.nextindex) -
751 xtlck->lwm.offset;
752 }
753
754 return 0;
755 }
756
757
758
759
760
761
762 if (split->pxdlist == NULL) {
763 nsplit = btstack->nsplit;
764 split->pxdlist = &pxdlist;
765 pxdlist.maxnpxd = pxdlist.npxd = 0;
766 pxd = &pxdlist.pxd[0];
767 xlen = JFS_SBI(ip->i_sb)->nbperpage;
768 for (; nsplit > 0; nsplit--, pxd++) {
769 if ((rc = dbAlloc(ip, (s64) 0, (s64) xlen, &xaddr))
770 == 0) {
771 PXDaddress(pxd, xaddr);
772 PXDlength(pxd, xlen);
773
774 pxdlist.maxnpxd++;
775
776 continue;
777 }
778
779
780
781 XT_PUTPAGE(smp);
782 return rc;
783 }
784 }
785
786
787
788
789
790
791
792
793 rc = (sp->header.flag & BT_ROOT) ?
794 xtSplitRoot(tid, ip, split, &rmp) :
795 xtSplitPage(tid, ip, split, &rmp, &rbn);
796
797 XT_PUTPAGE(smp);
798
799 if (rc)
800 return -EIO;
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822 while ((parent = BT_POP(btstack)) != NULL) {
823
824
825
826 rcmp = rmp;
827 rcbn = rbn;
828 rcp = XT_PAGE(ip, rcmp);
829
830
831
832
833
834 XT_GETPAGE(ip, parent->bn, smp, PSIZE, sp, rc);
835 if (rc) {
836 XT_PUTPAGE(rcmp);
837 return rc;
838 }
839
840
841
842
843
844 skip = parent->index + 1;
845
846
847
848
849 nextindex = le16_to_cpu(sp->header.nextindex);
850
851
852
853 if (nextindex == le16_to_cpu(sp->header.maxentry)) {
854
855 split->mp = smp;
856 split->index = skip;
857 split->flag = XAD_NEW;
858 split->off = offsetXAD(&rcp->xad[XTENTRYSTART]);
859 split->len = JFS_SBI(ip->i_sb)->nbperpage;
860 split->addr = rcbn;
861
862
863 XT_PUTPAGE(rcmp);
864
865
866
867
868
869 rc = (sp->header.flag & BT_ROOT) ?
870 xtSplitRoot(tid, ip, split, &rmp) :
871 xtSplitPage(tid, ip, split, &rmp, &rbn);
872 if (rc) {
873 XT_PUTPAGE(smp);
874 return rc;
875 }
876
877 XT_PUTPAGE(smp);
878
879 }
880
881
882
883 else {
884
885
886
887
888
889
890
891
892
893 BT_MARK_DIRTY(smp, ip);
894
895
896
897
898 if (skip < nextindex)
899 memmove(&sp->xad[skip + 1], &sp->xad[skip],
900 (nextindex -
901 skip) << L2XTSLOTSIZE);
902
903
904 xad = &sp->xad[skip];
905 XT_PUTENTRY(xad, XAD_NEW,
906 offsetXAD(&rcp->xad[XTENTRYSTART]),
907 JFS_SBI(ip->i_sb)->nbperpage, rcbn);
908
909
910 le16_add_cpu(&sp->header.nextindex, 1);
911
912
913 if (!test_cflag(COMMIT_Nolink, ip)) {
914 tlck = txLock(tid, ip, smp,
915 tlckXTREE | tlckGROW);
916 xtlck = (struct xtlock *) & tlck->lock;
917 xtlck->lwm.offset = (xtlck->lwm.offset) ?
918 min(skip, (int)xtlck->lwm.offset) : skip;
919 xtlck->lwm.length =
920 le16_to_cpu(sp->header.nextindex) -
921 xtlck->lwm.offset;
922 }
923
924
925 XT_PUTPAGE(smp);
926
927
928 break;
929 }
930 }
931
932
933 XT_PUTPAGE(rmp);
934
935 return 0;
936}
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957static int
958xtSplitPage(tid_t tid, struct inode *ip,
959 struct xtsplit * split, struct metapage ** rmpp, s64 * rbnp)
960{
961 int rc = 0;
962 struct metapage *smp;
963 xtpage_t *sp;
964 struct metapage *rmp;
965 xtpage_t *rp;
966 s64 rbn;
967 struct metapage *mp;
968 xtpage_t *p;
969 s64 nextbn;
970 int skip, maxentry, middle, righthalf, n;
971 xad_t *xad;
972 struct pxdlist *pxdlist;
973 pxd_t *pxd;
974 struct tlock *tlck;
975 struct xtlock *sxtlck = NULL, *rxtlck = NULL;
976 int quota_allocation = 0;
977
978 smp = split->mp;
979 sp = XT_PAGE(ip, smp);
980
981 INCREMENT(xtStat.split);
982
983 pxdlist = split->pxdlist;
984 pxd = &pxdlist->pxd[pxdlist->npxd];
985 pxdlist->npxd++;
986 rbn = addressPXD(pxd);
987
988
989 rc = dquot_alloc_block(ip, lengthPXD(pxd));
990 if (rc)
991 goto clean_up;
992
993 quota_allocation += lengthPXD(pxd);
994
995
996
997
998 rmp = get_metapage(ip, rbn, PSIZE, 1);
999 if (rmp == NULL) {
1000 rc = -EIO;
1001 goto clean_up;
1002 }
1003
1004 jfs_info("xtSplitPage: ip:0x%p smp:0x%p rmp:0x%p", ip, smp, rmp);
1005
1006 BT_MARK_DIRTY(rmp, ip);
1007
1008
1009
1010
1011 rp = (xtpage_t *) rmp->data;
1012 rp->header.self = *pxd;
1013 rp->header.flag = sp->header.flag & BT_TYPE;
1014 rp->header.maxentry = sp->header.maxentry;
1015 rp->header.nextindex = cpu_to_le16(XTENTRYSTART);
1016
1017 BT_MARK_DIRTY(smp, ip);
1018
1019 if (!test_cflag(COMMIT_Nolink, ip)) {
1020
1021
1022
1023 tlck = txLock(tid, ip, rmp, tlckXTREE | tlckNEW);
1024 rxtlck = (struct xtlock *) & tlck->lock;
1025 rxtlck->lwm.offset = XTENTRYSTART;
1026
1027
1028
1029 tlck = txLock(tid, ip, smp, tlckXTREE | tlckGROW);
1030 sxtlck = (struct xtlock *) & tlck->lock;
1031 }
1032
1033
1034
1035
1036 nextbn = le64_to_cpu(sp->header.next);
1037 rp->header.next = cpu_to_le64(nextbn);
1038 rp->header.prev = cpu_to_le64(addressPXD(&sp->header.self));
1039 sp->header.next = cpu_to_le64(rbn);
1040
1041 skip = split->index;
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056 if (nextbn == 0 && skip == le16_to_cpu(sp->header.maxentry)) {
1057
1058
1059
1060
1061
1062
1063 xad = &rp->xad[XTENTRYSTART];
1064 XT_PUTENTRY(xad, split->flag, split->off, split->len,
1065 split->addr);
1066
1067 rp->header.nextindex = cpu_to_le16(XTENTRYSTART + 1);
1068
1069 if (!test_cflag(COMMIT_Nolink, ip)) {
1070
1071 rxtlck->lwm.length = 1;
1072 }
1073
1074 *rmpp = rmp;
1075 *rbnp = rbn;
1076
1077 jfs_info("xtSplitPage: sp:0x%p rp:0x%p", sp, rp);
1078 return 0;
1079 }
1080
1081
1082
1083
1084
1085
1086
1087
1088 if (nextbn != 0) {
1089 XT_GETPAGE(ip, nextbn, mp, PSIZE, p, rc);
1090 if (rc) {
1091 XT_PUTPAGE(rmp);
1092 goto clean_up;
1093 }
1094
1095 BT_MARK_DIRTY(mp, ip);
1096
1097
1098
1099
1100
1101 if (!test_cflag(COMMIT_Nolink, ip))
1102 tlck = txLock(tid, ip, mp, tlckXTREE | tlckRELINK);
1103
1104 p->header.prev = cpu_to_le64(rbn);
1105
1106
1107
1108
1109
1110 XT_PUTPAGE(mp);
1111 }
1112
1113
1114
1115
1116 maxentry = le16_to_cpu(sp->header.maxentry);
1117 middle = maxentry >> 1;
1118 righthalf = maxentry - middle;
1119
1120
1121
1122
1123 if (skip <= middle) {
1124
1125 memmove(&rp->xad[XTENTRYSTART], &sp->xad[middle],
1126 righthalf << L2XTSLOTSIZE);
1127
1128
1129 if (skip < middle)
1130 memmove(&sp->xad[skip + 1], &sp->xad[skip],
1131 (middle - skip) << L2XTSLOTSIZE);
1132
1133
1134 xad = &sp->xad[skip];
1135 XT_PUTENTRY(xad, split->flag, split->off, split->len,
1136 split->addr);
1137
1138
1139 sp->header.nextindex = cpu_to_le16(middle + 1);
1140 if (!test_cflag(COMMIT_Nolink, ip)) {
1141 sxtlck->lwm.offset = (sxtlck->lwm.offset) ?
1142 min(skip, (int)sxtlck->lwm.offset) : skip;
1143 }
1144
1145 rp->header.nextindex =
1146 cpu_to_le16(XTENTRYSTART + righthalf);
1147 }
1148
1149
1150
1151 else {
1152
1153 n = skip - middle;
1154 memmove(&rp->xad[XTENTRYSTART], &sp->xad[middle],
1155 n << L2XTSLOTSIZE);
1156
1157
1158 n += XTENTRYSTART;
1159 xad = &rp->xad[n];
1160 XT_PUTENTRY(xad, split->flag, split->off, split->len,
1161 split->addr);
1162
1163
1164 if (skip < maxentry)
1165 memmove(&rp->xad[n + 1], &sp->xad[skip],
1166 (maxentry - skip) << L2XTSLOTSIZE);
1167
1168
1169 sp->header.nextindex = cpu_to_le16(middle);
1170 if (!test_cflag(COMMIT_Nolink, ip)) {
1171 sxtlck->lwm.offset = (sxtlck->lwm.offset) ?
1172 min(middle, (int)sxtlck->lwm.offset) : middle;
1173 }
1174
1175 rp->header.nextindex = cpu_to_le16(XTENTRYSTART +
1176 righthalf + 1);
1177 }
1178
1179 if (!test_cflag(COMMIT_Nolink, ip)) {
1180 sxtlck->lwm.length = le16_to_cpu(sp->header.nextindex) -
1181 sxtlck->lwm.offset;
1182
1183
1184 rxtlck->lwm.length = le16_to_cpu(rp->header.nextindex) -
1185 XTENTRYSTART;
1186 }
1187
1188 *rmpp = rmp;
1189 *rbnp = rbn;
1190
1191 jfs_info("xtSplitPage: sp:0x%p rp:0x%p", sp, rp);
1192 return rc;
1193
1194 clean_up:
1195
1196
1197 if (quota_allocation)
1198 dquot_free_block(ip, quota_allocation);
1199
1200 return (rc);
1201}
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224static int
1225xtSplitRoot(tid_t tid,
1226 struct inode *ip, struct xtsplit * split, struct metapage ** rmpp)
1227{
1228 xtpage_t *sp;
1229 struct metapage *rmp;
1230 xtpage_t *rp;
1231 s64 rbn;
1232 int skip, nextindex;
1233 xad_t *xad;
1234 pxd_t *pxd;
1235 struct pxdlist *pxdlist;
1236 struct tlock *tlck;
1237 struct xtlock *xtlck;
1238 int rc;
1239
1240 sp = &JFS_IP(ip)->i_xtroot;
1241
1242 INCREMENT(xtStat.split);
1243
1244
1245
1246
1247 pxdlist = split->pxdlist;
1248 pxd = &pxdlist->pxd[pxdlist->npxd];
1249 pxdlist->npxd++;
1250 rbn = addressPXD(pxd);
1251 rmp = get_metapage(ip, rbn, PSIZE, 1);
1252 if (rmp == NULL)
1253 return -EIO;
1254
1255
1256 rc = dquot_alloc_block(ip, lengthPXD(pxd));
1257 if (rc) {
1258 release_metapage(rmp);
1259 return rc;
1260 }
1261
1262 jfs_info("xtSplitRoot: ip:0x%p rmp:0x%p", ip, rmp);
1263
1264
1265
1266
1267
1268
1269 BT_MARK_DIRTY(rmp, ip);
1270
1271 rp = (xtpage_t *) rmp->data;
1272 rp->header.flag =
1273 (sp->header.flag & BT_LEAF) ? BT_LEAF : BT_INTERNAL;
1274 rp->header.self = *pxd;
1275 rp->header.nextindex = cpu_to_le16(XTENTRYSTART);
1276 rp->header.maxentry = cpu_to_le16(PSIZE >> L2XTSLOTSIZE);
1277
1278
1279 rp->header.next = 0;
1280 rp->header.prev = 0;
1281
1282
1283
1284
1285 nextindex = le16_to_cpu(sp->header.maxentry);
1286 memmove(&rp->xad[XTENTRYSTART], &sp->xad[XTENTRYSTART],
1287 (nextindex - XTENTRYSTART) << L2XTSLOTSIZE);
1288
1289
1290
1291
1292
1293 skip = split->index;
1294
1295 if (skip != nextindex)
1296 memmove(&rp->xad[skip + 1], &rp->xad[skip],
1297 (nextindex - skip) * sizeof(xad_t));
1298
1299 xad = &rp->xad[skip];
1300 XT_PUTENTRY(xad, split->flag, split->off, split->len, split->addr);
1301
1302
1303 rp->header.nextindex = cpu_to_le16(nextindex + 1);
1304
1305 if (!test_cflag(COMMIT_Nolink, ip)) {
1306 tlck = txLock(tid, ip, rmp, tlckXTREE | tlckNEW);
1307 xtlck = (struct xtlock *) & tlck->lock;
1308 xtlck->lwm.offset = XTENTRYSTART;
1309 xtlck->lwm.length = le16_to_cpu(rp->header.nextindex) -
1310 XTENTRYSTART;
1311 }
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325 BT_MARK_DIRTY(split->mp, ip);
1326
1327 xad = &sp->xad[XTENTRYSTART];
1328 XT_PUTENTRY(xad, XAD_NEW, 0, JFS_SBI(ip->i_sb)->nbperpage, rbn);
1329
1330
1331 sp->header.flag &= ~BT_LEAF;
1332 sp->header.flag |= BT_INTERNAL;
1333
1334 sp->header.nextindex = cpu_to_le16(XTENTRYSTART + 1);
1335
1336 if (!test_cflag(COMMIT_Nolink, ip)) {
1337 tlck = txLock(tid, ip, split->mp, tlckXTREE | tlckGROW);
1338 xtlck = (struct xtlock *) & tlck->lock;
1339 xtlck->lwm.offset = XTENTRYSTART;
1340 xtlck->lwm.length = 1;
1341 }
1342
1343 *rmpp = rmp;
1344
1345 jfs_info("xtSplitRoot: sp:0x%p rp:0x%p", sp, rp);
1346 return 0;
1347}
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360int xtExtend(tid_t tid,
1361 struct inode *ip, s64 xoff,
1362 s32 xlen,
1363 int flag)
1364{
1365 int rc = 0;
1366 int cmp;
1367 struct metapage *mp;
1368 xtpage_t *p;
1369 s64 bn;
1370 int index, nextindex, len;
1371 struct btstack btstack;
1372 struct xtsplit split;
1373 xad_t *xad;
1374 s64 xaddr;
1375 struct tlock *tlck;
1376 struct xtlock *xtlck = NULL;
1377
1378 jfs_info("xtExtend: nxoff:0x%lx nxlen:0x%x", (ulong) xoff, xlen);
1379
1380
1381 if ((rc = xtSearch(ip, xoff - 1, NULL, &cmp, &btstack, XT_INSERT)))
1382 return rc;
1383
1384
1385 XT_GETSEARCH(ip, btstack.top, bn, mp, p, index);
1386
1387 if (cmp != 0) {
1388 XT_PUTPAGE(mp);
1389 jfs_error(ip->i_sb, "xtSearch did not find extent\n");
1390 return -EIO;
1391 }
1392
1393
1394 xad = &p->xad[index];
1395 if ((offsetXAD(xad) + lengthXAD(xad)) != xoff) {
1396 XT_PUTPAGE(mp);
1397 jfs_error(ip->i_sb, "extension is not contiguous\n");
1398 return -EIO;
1399 }
1400
1401
1402
1403
1404
1405
1406 BT_MARK_DIRTY(mp, ip);
1407 if (!test_cflag(COMMIT_Nolink, ip)) {
1408 tlck = txLock(tid, ip, mp, tlckXTREE | tlckGROW);
1409 xtlck = (struct xtlock *) & tlck->lock;
1410 }
1411
1412
1413 xlen = lengthXAD(xad) + xlen;
1414 if ((len = xlen - MAXXLEN) <= 0)
1415 goto extendOld;
1416
1417
1418
1419
1420
1421 xoff = offsetXAD(xad) + MAXXLEN;
1422 xaddr = addressXAD(xad) + MAXXLEN;
1423 nextindex = le16_to_cpu(p->header.nextindex);
1424
1425
1426
1427
1428
1429
1430
1431 if (nextindex == le16_to_cpu(p->header.maxentry)) {
1432
1433 split.mp = mp;
1434 split.index = index + 1;
1435 split.flag = XAD_NEW;
1436 split.off = xoff;
1437 split.len = len;
1438 split.addr = xaddr;
1439 split.pxdlist = NULL;
1440 if ((rc = xtSplitUp(tid, ip, &split, &btstack)))
1441 return rc;
1442
1443
1444 XT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
1445 if (rc)
1446 return rc;
1447
1448
1449
1450
1451
1452 if (p->header.flag & BT_INTERNAL) {
1453 ASSERT(p->header.nextindex ==
1454 cpu_to_le16(XTENTRYSTART + 1));
1455 xad = &p->xad[XTENTRYSTART];
1456 bn = addressXAD(xad);
1457 XT_PUTPAGE(mp);
1458
1459
1460 XT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
1461 if (rc)
1462 return rc;
1463
1464 BT_MARK_DIRTY(mp, ip);
1465 if (!test_cflag(COMMIT_Nolink, ip)) {
1466 tlck = txLock(tid, ip, mp, tlckXTREE|tlckGROW);
1467 xtlck = (struct xtlock *) & tlck->lock;
1468 }
1469 }
1470 }
1471
1472
1473
1474 else {
1475
1476 xad = &p->xad[index + 1];
1477 XT_PUTENTRY(xad, XAD_NEW, xoff, len, xaddr);
1478
1479
1480 le16_add_cpu(&p->header.nextindex, 1);
1481 }
1482
1483
1484 xad = &p->xad[index];
1485 xlen = MAXXLEN;
1486
1487
1488
1489
1490 extendOld:
1491 XADlength(xad, xlen);
1492 if (!(xad->flag & XAD_NEW))
1493 xad->flag |= XAD_EXTENDED;
1494
1495 if (!test_cflag(COMMIT_Nolink, ip)) {
1496 xtlck->lwm.offset =
1497 (xtlck->lwm.offset) ? min(index,
1498 (int)xtlck->lwm.offset) : index;
1499 xtlck->lwm.length =
1500 le16_to_cpu(p->header.nextindex) - xtlck->lwm.offset;
1501 }
1502
1503
1504 XT_PUTPAGE(mp);
1505
1506 return rc;
1507}
1508
1509#ifdef _NOTYET
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522int xtTailgate(tid_t tid,
1523 struct inode *ip, s64 xoff,
1524 s32 xlen,
1525 s64 xaddr,
1526 int flag)
1527{
1528 int rc = 0;
1529 int cmp;
1530 struct metapage *mp;
1531 xtpage_t *p;
1532 s64 bn;
1533 int index, nextindex, llen, rlen;
1534 struct btstack btstack;
1535 struct xtsplit split;
1536 xad_t *xad;
1537 struct tlock *tlck;
1538 struct xtlock *xtlck = 0;
1539 struct tlock *mtlck;
1540 struct maplock *pxdlock;
1541
1542
1543
1544
1545
1546
1547
1548 if ((rc = xtSearch(ip, xoff, NULL, &cmp, &btstack, XT_INSERT)))
1549 return rc;
1550
1551
1552 XT_GETSEARCH(ip, btstack.top, bn, mp, p, index);
1553
1554 if (cmp != 0) {
1555 XT_PUTPAGE(mp);
1556 jfs_error(ip->i_sb, "couldn't find extent\n");
1557 return -EIO;
1558 }
1559
1560
1561 nextindex = le16_to_cpu(p->header.nextindex);
1562 if (index != nextindex - 1) {
1563 XT_PUTPAGE(mp);
1564 jfs_error(ip->i_sb, "the entry found is not the last entry\n");
1565 return -EIO;
1566 }
1567
1568 BT_MARK_DIRTY(mp, ip);
1569
1570
1571
1572 if (!test_cflag(COMMIT_Nolink, ip)) {
1573 tlck = txLock(tid, ip, mp, tlckXTREE | tlckGROW);
1574 xtlck = (struct xtlock *) & tlck->lock;
1575 }
1576
1577
1578 xad = &p->xad[index];
1579
1580
1581
1582
1583 if ((llen = xoff - offsetXAD(xad)) == 0)
1584 goto updateOld;
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596 if (nextindex == le16_to_cpu(p->header.maxentry)) {
1597
1598 split.mp = mp;
1599 split.index = index + 1;
1600 split.flag = XAD_NEW;
1601 split.off = xoff;
1602 split.len = xlen;
1603 split.addr = xaddr;
1604 split.pxdlist = NULL;
1605 if ((rc = xtSplitUp(tid, ip, &split, &btstack)))
1606 return rc;
1607
1608
1609 XT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
1610 if (rc)
1611 return rc;
1612
1613
1614
1615
1616
1617 if (p->header.flag & BT_INTERNAL) {
1618 ASSERT(p->header.nextindex ==
1619 cpu_to_le16(XTENTRYSTART + 1));
1620 xad = &p->xad[XTENTRYSTART];
1621 bn = addressXAD(xad);
1622 XT_PUTPAGE(mp);
1623
1624
1625 XT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
1626 if (rc)
1627 return rc;
1628
1629 BT_MARK_DIRTY(mp, ip);
1630 if (!test_cflag(COMMIT_Nolink, ip)) {
1631 tlck = txLock(tid, ip, mp, tlckXTREE|tlckGROW);
1632 xtlck = (struct xtlock *) & tlck->lock;
1633 }
1634 }
1635 }
1636
1637
1638
1639 else {
1640
1641 xad = &p->xad[index + 1];
1642 XT_PUTENTRY(xad, XAD_NEW, xoff, xlen, xaddr);
1643
1644
1645 le16_add_cpu(&p->header.nextindex, 1);
1646 }
1647
1648
1649 xad = &p->xad[index];
1650
1651
1652
1653
1654 updateOld:
1655
1656 rlen = lengthXAD(xad) - llen;
1657 if (!(xad->flag & XAD_NEW)) {
1658
1659 if (!test_cflag(COMMIT_Nolink, ip)) {
1660 mtlck = txMaplock(tid, ip, tlckMAP);
1661 pxdlock = (struct maplock *) & mtlck->lock;
1662 pxdlock->flag = mlckFREEPXD;
1663 PXDaddress(&pxdlock->pxd, addressXAD(xad) + llen);
1664 PXDlength(&pxdlock->pxd, rlen);
1665 pxdlock->index = 1;
1666 }
1667 } else
1668
1669 dbFree(ip, addressXAD(xad) + llen, (s64) rlen);
1670
1671 if (llen)
1672
1673 XADlength(xad, llen);
1674 else
1675
1676 XT_PUTENTRY(xad, XAD_NEW, xoff, xlen, xaddr);
1677
1678 if (!test_cflag(COMMIT_Nolink, ip)) {
1679 xtlck->lwm.offset = (xtlck->lwm.offset) ?
1680 min(index, (int)xtlck->lwm.offset) : index;
1681 xtlck->lwm.length = le16_to_cpu(p->header.nextindex) -
1682 xtlck->lwm.offset;
1683 }
1684
1685
1686 XT_PUTPAGE(mp);
1687
1688 return rc;
1689}
1690#endif
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705int xtUpdate(tid_t tid, struct inode *ip, xad_t * nxad)
1706{
1707 int rc = 0;
1708 int cmp;
1709 struct metapage *mp;
1710 xtpage_t *p;
1711 s64 bn;
1712 int index0, index, newindex, nextindex;
1713 struct btstack btstack;
1714 struct xtsplit split;
1715 xad_t *xad, *lxad, *rxad;
1716 int xflag;
1717 s64 nxoff, xoff;
1718 int nxlen, xlen, lxlen, rxlen;
1719 s64 nxaddr, xaddr;
1720 struct tlock *tlck;
1721 struct xtlock *xtlck = NULL;
1722 int newpage = 0;
1723
1724
1725 nxoff = offsetXAD(nxad);
1726 nxlen = lengthXAD(nxad);
1727 nxaddr = addressXAD(nxad);
1728
1729 if ((rc = xtSearch(ip, nxoff, NULL, &cmp, &btstack, XT_INSERT)))
1730 return rc;
1731
1732
1733 XT_GETSEARCH(ip, btstack.top, bn, mp, p, index0);
1734
1735 if (cmp != 0) {
1736 XT_PUTPAGE(mp);
1737 jfs_error(ip->i_sb, "Could not find extent\n");
1738 return -EIO;
1739 }
1740
1741 BT_MARK_DIRTY(mp, ip);
1742
1743
1744
1745 if (!test_cflag(COMMIT_Nolink, ip)) {
1746 tlck = txLock(tid, ip, mp, tlckXTREE | tlckGROW);
1747 xtlck = (struct xtlock *) & tlck->lock;
1748 }
1749
1750 xad = &p->xad[index0];
1751 xflag = xad->flag;
1752 xoff = offsetXAD(xad);
1753 xlen = lengthXAD(xad);
1754 xaddr = addressXAD(xad);
1755
1756
1757 if ((xoff > nxoff) ||
1758 (nxoff + nxlen > xoff + xlen)) {
1759 XT_PUTPAGE(mp);
1760 jfs_error(ip->i_sb,
1761 "nXAD in not completely contained within XAD\n");
1762 return -EIO;
1763 }
1764
1765 index = index0;
1766 newindex = index + 1;
1767 nextindex = le16_to_cpu(p->header.nextindex);
1768
1769#ifdef _JFS_WIP_NOCOALESCE
1770 if (xoff < nxoff)
1771 goto updateRight;
1772
1773
1774
1775
1776 replace:
1777 if (nxlen == xlen) {
1778
1779 *xad = *nxad;
1780 xad->flag = xflag & ~XAD_NOTRECORDED;
1781
1782 goto out;
1783 } else
1784 goto updateLeft;
1785#endif
1786
1787
1788 if (xoff < nxoff)
1789 goto coalesceRight;
1790
1791
1792
1793
1794
1795
1796 if (index == XTENTRYSTART)
1797 goto replace;
1798
1799
1800 lxad = &p->xad[index - 1];
1801 lxlen = lengthXAD(lxad);
1802 if (!(lxad->flag & XAD_NOTRECORDED) &&
1803 (nxoff == offsetXAD(lxad) + lxlen) &&
1804 (nxaddr == addressXAD(lxad) + lxlen) &&
1805 (lxlen + nxlen < MAXXLEN)) {
1806
1807 index0 = index - 1;
1808 XADlength(lxad, lxlen + nxlen);
1809
1810
1811
1812
1813
1814
1815 if (!(lxad->flag & XAD_NEW))
1816 lxad->flag |= XAD_EXTENDED;
1817
1818 if (xlen > nxlen) {
1819
1820 XADoffset(xad, xoff + nxlen);
1821 XADlength(xad, xlen - nxlen);
1822 XADaddress(xad, xaddr + nxlen);
1823 goto out;
1824 } else {
1825
1826
1827 if (index < nextindex - 1)
1828 memmove(&p->xad[index], &p->xad[index + 1],
1829 (nextindex - index -
1830 1) << L2XTSLOTSIZE);
1831
1832 p->header.nextindex =
1833 cpu_to_le16(le16_to_cpu(p->header.nextindex) -
1834 1);
1835
1836 index = index0;
1837 newindex = index + 1;
1838 nextindex = le16_to_cpu(p->header.nextindex);
1839 xoff = nxoff = offsetXAD(lxad);
1840 xlen = nxlen = lxlen + nxlen;
1841 xaddr = nxaddr = addressXAD(lxad);
1842 goto coalesceRight;
1843 }
1844 }
1845
1846
1847
1848
1849 replace:
1850 if (nxlen == xlen) {
1851
1852 *xad = *nxad;
1853 xad->flag = xflag & ~XAD_NOTRECORDED;
1854
1855 goto coalesceRight;
1856 } else
1857 goto updateLeft;
1858
1859
1860
1861
1862 coalesceRight:
1863
1864 if (newindex == nextindex) {
1865 if (xoff == nxoff)
1866 goto out;
1867 goto updateRight;
1868 }
1869
1870
1871 rxad = &p->xad[index + 1];
1872 rxlen = lengthXAD(rxad);
1873 if (!(rxad->flag & XAD_NOTRECORDED) &&
1874 (nxoff + nxlen == offsetXAD(rxad)) &&
1875 (nxaddr + nxlen == addressXAD(rxad)) &&
1876 (rxlen + nxlen < MAXXLEN)) {
1877
1878 XADoffset(rxad, nxoff);
1879 XADlength(rxad, rxlen + nxlen);
1880 XADaddress(rxad, nxaddr);
1881
1882
1883
1884
1885
1886
1887 if (!(rxad->flag & XAD_NEW))
1888 rxad->flag |= XAD_EXTENDED;
1889
1890 if (xlen > nxlen)
1891
1892 XADlength(xad, xlen - nxlen);
1893 else {
1894
1895
1896 memmove(&p->xad[index], &p->xad[index + 1],
1897 (nextindex - index - 1) << L2XTSLOTSIZE);
1898
1899 p->header.nextindex =
1900 cpu_to_le16(le16_to_cpu(p->header.nextindex) -
1901 1);
1902 }
1903
1904 goto out;
1905 } else if (xoff == nxoff)
1906 goto out;
1907
1908 if (xoff >= nxoff) {
1909 XT_PUTPAGE(mp);
1910 jfs_error(ip->i_sb, "xoff >= nxoff\n");
1911 return -EIO;
1912 }
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922 updateRight:
1923
1924 xad = &p->xad[index];
1925 XADlength(xad, nxoff - xoff);
1926
1927
1928 if (nextindex == le16_to_cpu(p->header.maxentry)) {
1929
1930
1931 split.mp = mp;
1932 split.index = newindex;
1933 split.flag = xflag & ~XAD_NOTRECORDED;
1934 split.off = nxoff;
1935 split.len = nxlen;
1936 split.addr = nxaddr;
1937 split.pxdlist = NULL;
1938 if ((rc = xtSplitUp(tid, ip, &split, &btstack)))
1939 return rc;
1940
1941
1942 XT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
1943 if (rc)
1944 return rc;
1945
1946
1947
1948
1949
1950 if (p->header.flag & BT_INTERNAL) {
1951 ASSERT(p->header.nextindex ==
1952 cpu_to_le16(XTENTRYSTART + 1));
1953 xad = &p->xad[XTENTRYSTART];
1954 bn = addressXAD(xad);
1955 XT_PUTPAGE(mp);
1956
1957
1958 XT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
1959 if (rc)
1960 return rc;
1961
1962 BT_MARK_DIRTY(mp, ip);
1963 if (!test_cflag(COMMIT_Nolink, ip)) {
1964 tlck = txLock(tid, ip, mp, tlckXTREE|tlckGROW);
1965 xtlck = (struct xtlock *) & tlck->lock;
1966 }
1967 } else {
1968
1969 if (newindex >
1970 (le16_to_cpu(p->header.maxentry) >> 1)) {
1971 newindex =
1972 newindex -
1973 le16_to_cpu(p->header.nextindex) +
1974 XTENTRYSTART;
1975 newpage = 1;
1976 }
1977 }
1978 } else {
1979
1980 if (newindex < nextindex)
1981 memmove(&p->xad[newindex + 1], &p->xad[newindex],
1982 (nextindex - newindex) << L2XTSLOTSIZE);
1983
1984
1985 xad = &p->xad[newindex];
1986 *xad = *nxad;
1987 xad->flag = xflag & ~XAD_NOTRECORDED;
1988
1989
1990 p->header.nextindex =
1991 cpu_to_le16(le16_to_cpu(p->header.nextindex) + 1);
1992 }
1993
1994
1995
1996
1997
1998
1999
2000
2001 if (nxoff + nxlen == xoff + xlen)
2002 goto out;
2003
2004
2005 if (newpage) {
2006
2007 if (!test_cflag(COMMIT_Nolink, ip)) {
2008 xtlck->lwm.offset = (xtlck->lwm.offset) ?
2009 min(index0, (int)xtlck->lwm.offset) : index0;
2010 xtlck->lwm.length =
2011 le16_to_cpu(p->header.nextindex) -
2012 xtlck->lwm.offset;
2013 }
2014
2015 bn = le64_to_cpu(p->header.next);
2016 XT_PUTPAGE(mp);
2017
2018
2019 XT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
2020 if (rc)
2021 return rc;
2022
2023 BT_MARK_DIRTY(mp, ip);
2024 if (!test_cflag(COMMIT_Nolink, ip)) {
2025 tlck = txLock(tid, ip, mp, tlckXTREE | tlckGROW);
2026 xtlck = (struct xtlock *) & tlck->lock;
2027 }
2028
2029 index0 = index = newindex;
2030 } else
2031 index++;
2032
2033 newindex = index + 1;
2034 nextindex = le16_to_cpu(p->header.nextindex);
2035 xlen = xlen - (nxoff - xoff);
2036 xoff = nxoff;
2037 xaddr = nxaddr;
2038
2039
2040 if (nextindex == le16_to_cpu(p->header.maxentry)) {
2041 XT_PUTPAGE(mp);
2042
2043 if ((rc = xtSearch(ip, nxoff, NULL, &cmp, &btstack, XT_INSERT)))
2044 return rc;
2045
2046
2047 XT_GETSEARCH(ip, btstack.top, bn, mp, p, index0);
2048
2049 if (cmp != 0) {
2050 XT_PUTPAGE(mp);
2051 jfs_error(ip->i_sb, "xtSearch failed\n");
2052 return -EIO;
2053 }
2054
2055 if (index0 != index) {
2056 XT_PUTPAGE(mp);
2057 jfs_error(ip->i_sb, "unexpected value of index\n");
2058 return -EIO;
2059 }
2060 }
2061
2062
2063
2064
2065
2066
2067
2068
2069 updateLeft:
2070
2071 xad = &p->xad[index];
2072 *xad = *nxad;
2073 xad->flag = xflag & ~XAD_NOTRECORDED;
2074
2075
2076 xoff = xoff + nxlen;
2077 xlen = xlen - nxlen;
2078 xaddr = xaddr + nxlen;
2079 if (nextindex == le16_to_cpu(p->header.maxentry)) {
2080
2081
2082
2083
2084 split.mp = mp;
2085 split.index = newindex;
2086 split.flag = xflag;
2087 split.off = xoff;
2088 split.len = xlen;
2089 split.addr = xaddr;
2090 split.pxdlist = NULL;
2091 if ((rc = xtSplitUp(tid, ip, &split, &btstack)))
2092 return rc;
2093
2094
2095 XT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
2096 if (rc)
2097 return rc;
2098
2099
2100
2101
2102
2103
2104 if (p->header.flag & BT_INTERNAL) {
2105 ASSERT(p->header.nextindex ==
2106 cpu_to_le16(XTENTRYSTART + 1));
2107 xad = &p->xad[XTENTRYSTART];
2108 bn = addressXAD(xad);
2109 XT_PUTPAGE(mp);
2110
2111
2112 XT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
2113 if (rc)
2114 return rc;
2115
2116 BT_MARK_DIRTY(mp, ip);
2117 if (!test_cflag(COMMIT_Nolink, ip)) {
2118 tlck = txLock(tid, ip, mp, tlckXTREE|tlckGROW);
2119 xtlck = (struct xtlock *) & tlck->lock;
2120 }
2121 }
2122 } else {
2123
2124 if (newindex < nextindex)
2125 memmove(&p->xad[newindex + 1], &p->xad[newindex],
2126 (nextindex - newindex) << L2XTSLOTSIZE);
2127
2128
2129 xad = &p->xad[newindex];
2130 XT_PUTENTRY(xad, xflag, xoff, xlen, xaddr);
2131
2132
2133 p->header.nextindex =
2134 cpu_to_le16(le16_to_cpu(p->header.nextindex) + 1);
2135 }
2136
2137 out:
2138 if (!test_cflag(COMMIT_Nolink, ip)) {
2139 xtlck->lwm.offset = (xtlck->lwm.offset) ?
2140 min(index0, (int)xtlck->lwm.offset) : index0;
2141 xtlck->lwm.length = le16_to_cpu(p->header.nextindex) -
2142 xtlck->lwm.offset;
2143 }
2144
2145
2146 XT_PUTPAGE(mp);
2147
2148 return rc;
2149}
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169int xtAppend(tid_t tid,
2170 struct inode *ip, int xflag, s64 xoff, s32 maxblocks,
2171 s32 * xlenp,
2172 s64 * xaddrp,
2173 int flag)
2174{
2175 int rc = 0;
2176 struct metapage *mp;
2177 xtpage_t *p;
2178 s64 bn, xaddr;
2179 int index, nextindex;
2180 struct btstack btstack;
2181 struct xtsplit split;
2182 xad_t *xad;
2183 int cmp;
2184 struct tlock *tlck;
2185 struct xtlock *xtlck;
2186 int nsplit, nblocks, xlen;
2187 struct pxdlist pxdlist;
2188 pxd_t *pxd;
2189 s64 next;
2190
2191 xaddr = *xaddrp;
2192 xlen = *xlenp;
2193 jfs_info("xtAppend: xoff:0x%lx maxblocks:%d xlen:%d xaddr:0x%lx",
2194 (ulong) xoff, maxblocks, xlen, (ulong) xaddr);
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204 if ((rc = xtSearch(ip, xoff, &next, &cmp, &btstack, XT_INSERT)))
2205 return rc;
2206
2207
2208 XT_GETSEARCH(ip, btstack.top, bn, mp, p, index);
2209
2210 if (cmp == 0) {
2211 rc = -EEXIST;
2212 goto out;
2213 }
2214
2215 if (next)
2216 xlen = min(xlen, (int)(next - xoff));
2217
2218
2219
2220
2221 xflag |= XAD_NEW;
2222
2223
2224
2225
2226
2227
2228
2229 nextindex = le16_to_cpu(p->header.nextindex);
2230 if (nextindex < le16_to_cpu(p->header.maxentry))
2231 goto insertLeaf;
2232
2233
2234
2235
2236 nsplit = btstack.nsplit;
2237 split.pxdlist = &pxdlist;
2238 pxdlist.maxnpxd = pxdlist.npxd = 0;
2239 pxd = &pxdlist.pxd[0];
2240 nblocks = JFS_SBI(ip->i_sb)->nbperpage;
2241 for (; nsplit > 0; nsplit--, pxd++, xaddr += nblocks, maxblocks -= nblocks) {
2242 if ((rc = dbAllocBottomUp(ip, xaddr, (s64) nblocks)) == 0) {
2243 PXDaddress(pxd, xaddr);
2244 PXDlength(pxd, nblocks);
2245
2246 pxdlist.maxnpxd++;
2247
2248 continue;
2249 }
2250
2251
2252
2253 goto out;
2254 }
2255
2256 xlen = min(xlen, maxblocks);
2257
2258
2259
2260
2261 if ((rc = dbAllocBottomUp(ip, xaddr, (s64) xlen)))
2262 goto out;
2263
2264 split.mp = mp;
2265 split.index = index;
2266 split.flag = xflag;
2267 split.off = xoff;
2268 split.len = xlen;
2269 split.addr = xaddr;
2270 if ((rc = xtSplitUp(tid, ip, &split, &btstack))) {
2271
2272 dbFree(ip, *xaddrp, (s64) * xlenp);
2273
2274 return rc;
2275 }
2276
2277 *xaddrp = xaddr;
2278 *xlenp = xlen;
2279 return 0;
2280
2281
2282
2283
2284 insertLeaf:
2285
2286
2287
2288 if ((rc = dbAllocBottomUp(ip, xaddr, (s64) xlen)))
2289 goto out;
2290
2291 BT_MARK_DIRTY(mp, ip);
2292
2293
2294
2295
2296
2297 tlck = txLock(tid, ip, mp, tlckXTREE | tlckGROW);
2298 xtlck = (struct xtlock *) & tlck->lock;
2299
2300
2301 xad = &p->xad[index];
2302 XT_PUTENTRY(xad, xflag, xoff, xlen, xaddr);
2303
2304
2305 le16_add_cpu(&p->header.nextindex, 1);
2306
2307 xtlck->lwm.offset =
2308 (xtlck->lwm.offset) ? min(index,(int) xtlck->lwm.offset) : index;
2309 xtlck->lwm.length = le16_to_cpu(p->header.nextindex) -
2310 xtlck->lwm.offset;
2311
2312 *xaddrp = xaddr;
2313 *xlenp = xlen;
2314
2315 out:
2316
2317 XT_PUTPAGE(mp);
2318
2319 return rc;
2320}
2321#ifdef _STILL_TO_PORT
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339int xtDelete(tid_t tid, struct inode *ip, s64 xoff, s32 xlen, int flag)
2340{
2341 int rc = 0;
2342 struct btstack btstack;
2343 int cmp;
2344 s64 bn;
2345 struct metapage *mp;
2346 xtpage_t *p;
2347 int index, nextindex;
2348 struct tlock *tlck;
2349 struct xtlock *xtlck;
2350
2351
2352
2353
2354 if ((rc = xtSearch(ip, xoff, NULL, &cmp, &btstack, 0)))
2355 return rc;
2356
2357 XT_GETSEARCH(ip, btstack.top, bn, mp, p, index);
2358 if (cmp) {
2359
2360 XT_PUTPAGE(mp);
2361 return -ENOENT;
2362 }
2363
2364
2365
2366
2367 nextindex = le16_to_cpu(p->header.nextindex);
2368 le16_add_cpu(&p->header.nextindex, -1);
2369
2370
2371
2372
2373 if (p->header.nextindex == cpu_to_le16(XTENTRYSTART))
2374 return (xtDeleteUp(tid, ip, mp, p, &btstack));
2375
2376 BT_MARK_DIRTY(mp, ip);
2377
2378
2379
2380
2381
2382 tlck = txLock(tid, ip, mp, tlckXTREE);
2383 xtlck = (struct xtlock *) & tlck->lock;
2384 xtlck->lwm.offset =
2385 (xtlck->lwm.offset) ? min(index, xtlck->lwm.offset) : index;
2386
2387
2388 if (index < nextindex - 1)
2389 memmove(&p->xad[index], &p->xad[index + 1],
2390 (nextindex - index - 1) * sizeof(xad_t));
2391
2392 XT_PUTPAGE(mp);
2393
2394 return 0;
2395}
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409static int
2410xtDeleteUp(tid_t tid, struct inode *ip,
2411 struct metapage * fmp, xtpage_t * fp, struct btstack * btstack)
2412{
2413 int rc = 0;
2414 struct metapage *mp;
2415 xtpage_t *p;
2416 int index, nextindex;
2417 s64 xaddr;
2418 int xlen;
2419 struct btframe *parent;
2420 struct tlock *tlck;
2421 struct xtlock *xtlck;
2422
2423
2424
2425
2426 if (fp->header.flag & BT_ROOT) {
2427
2428 fp->header.flag &= ~BT_INTERNAL;
2429 fp->header.flag |= BT_LEAF;
2430 fp->header.nextindex = cpu_to_le16(XTENTRYSTART);
2431
2432
2433
2434 return 0;
2435 }
2436
2437
2438
2439
2440 if ((rc = xtRelink(tid, ip, fp))) {
2441 XT_PUTPAGE(fmp);
2442 return rc;
2443 }
2444
2445 xaddr = addressPXD(&fp->header.self);
2446 xlen = lengthPXD(&fp->header.self);
2447
2448 dbFree(ip, xaddr, (s64) xlen);
2449
2450
2451 discard_metapage(fmp);
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461 while ((parent = BT_POP(btstack)) != NULL) {
2462
2463 XT_GETPAGE(ip, parent->bn, mp, PSIZE, p, rc);
2464 if (rc)
2465 return rc;
2466
2467 index = parent->index;
2468
2469
2470
2471 nextindex = le16_to_cpu(p->header.nextindex);
2472
2473
2474
2475
2476
2477 if (nextindex == 1) {
2478 if (p->header.flag & BT_ROOT) {
2479
2480 p->header.flag &= ~BT_INTERNAL;
2481 p->header.flag |= BT_LEAF;
2482 p->header.nextindex =
2483 cpu_to_le16(XTENTRYSTART);
2484
2485
2486
2487 break;
2488 } else {
2489
2490 if ((rc = xtRelink(tid, ip, p)))
2491 return rc;
2492
2493 xaddr = addressPXD(&p->header.self);
2494
2495 dbFree(ip, xaddr,
2496 (s64) JFS_SBI(ip->i_sb)->nbperpage);
2497
2498
2499 discard_metapage(mp);
2500
2501
2502 continue;
2503 }
2504 }
2505
2506
2507
2508
2509 else {
2510 BT_MARK_DIRTY(mp, ip);
2511
2512
2513
2514
2515
2516 tlck = txLock(tid, ip, mp, tlckXTREE);
2517 xtlck = (struct xtlock *) & tlck->lock;
2518 xtlck->lwm.offset =
2519 (xtlck->lwm.offset) ? min(index,
2520 xtlck->lwm.
2521 offset) : index;
2522
2523
2524
2525
2526 if (index < nextindex - 1)
2527 memmove(&p->xad[index], &p->xad[index + 1],
2528 (nextindex - index -
2529 1) << L2XTSLOTSIZE);
2530
2531 le16_add_cpu(&p->header.nextindex, -1);
2532 jfs_info("xtDeleteUp(entry): 0x%lx[%d]",
2533 (ulong) parent->bn, index);
2534 }
2535
2536
2537 XT_PUTPAGE(mp);
2538
2539
2540 break;
2541 }
2542
2543 return 0;
2544}
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558int
2559xtRelocate(tid_t tid, struct inode * ip, xad_t * oxad,
2560 s64 nxaddr,
2561 int xtype)
2562{
2563 int rc = 0;
2564 struct tblock *tblk;
2565 struct tlock *tlck;
2566 struct xtlock *xtlck;
2567 struct metapage *mp, *pmp, *lmp, *rmp;
2568 xtpage_t *p, *pp, *rp, *lp;
2569 xad_t *xad;
2570 pxd_t *pxd;
2571 s64 xoff, xsize;
2572 int xlen;
2573 s64 oxaddr, sxaddr, dxaddr, nextbn, prevbn;
2574 cbuf_t *cp;
2575 s64 offset, nbytes, nbrd, pno;
2576 int nb, npages, nblks;
2577 s64 bn;
2578 int cmp;
2579 int index;
2580 struct pxd_lock *pxdlock;
2581 struct btstack btstack;
2582
2583 xtype = xtype & EXTENT_TYPE;
2584
2585 xoff = offsetXAD(oxad);
2586 oxaddr = addressXAD(oxad);
2587 xlen = lengthXAD(oxad);
2588
2589
2590 offset = xoff << JFS_SBI(ip->i_sb)->l2bsize;
2591 if (offset >= ip->i_size)
2592 return -ESTALE;
2593
2594 jfs_info("xtRelocate: xtype:%d xoff:0x%lx xlen:0x%x xaddr:0x%lx:0x%lx",
2595 xtype, (ulong) xoff, xlen, (ulong) oxaddr, (ulong) nxaddr);
2596
2597
2598
2599
2600
2601 if (xtype == DATAEXT) {
2602
2603 rc = xtSearch(ip, xoff, NULL, &cmp, &btstack, 0);
2604 if (rc)
2605 return rc;
2606
2607
2608 XT_GETSEARCH(ip, btstack.top, bn, pmp, pp, index);
2609
2610 if (cmp) {
2611 XT_PUTPAGE(pmp);
2612 return -ESTALE;
2613 }
2614
2615
2616 xad = &pp->xad[index];
2617 if (addressXAD(xad) != oxaddr || lengthXAD(xad) != xlen) {
2618 XT_PUTPAGE(pmp);
2619 return -ESTALE;
2620 }
2621 } else {
2622
2623
2624 rc = xtSearchNode(ip, oxad, &cmp, &btstack, 0);
2625 if (rc)
2626 return rc;
2627
2628
2629 XT_GETSEARCH(ip, btstack.top, bn, pmp, pp, index);
2630
2631 if (cmp) {
2632 XT_PUTPAGE(pmp);
2633 return -ESTALE;
2634 }
2635
2636
2637
2638 xad = &pp->xad[index];
2639 }
2640 jfs_info("xtRelocate: parent xad entry validated.");
2641
2642
2643
2644
2645 if (xtype == DATAEXT) {
2646
2647
2648
2649 if (xad->flag & XAD_NOTRECORDED)
2650 goto out;
2651 else
2652
2653 XT_PUTPAGE(pmp);
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672 offset = xoff << JFS_SBI(ip->i_sb)->l2bsize;
2673 assert((offset & CM_OFFSET) == 0);
2674 nbytes = xlen << JFS_SBI(ip->i_sb)->l2bsize;
2675 pno = offset >> CM_L2BSIZE;
2676 npages = (nbytes + (CM_BSIZE - 1)) >> CM_L2BSIZE;
2677
2678
2679
2680
2681 sxaddr = oxaddr;
2682 dxaddr = nxaddr;
2683
2684
2685 for (nbrd = 0; nbrd < nbytes; nbrd += nb,
2686 offset += nb, pno++, npages--) {
2687
2688 nb = min(nbytes - nbrd, CM_BSIZE);
2689
2690
2691 if (rc = cmRead(ip, offset, npages, &cp))
2692 break;
2693
2694 assert(addressPXD(&cp->cm_pxd) == sxaddr);
2695 assert(!cp->cm_modified);
2696
2697
2698 nblks = nb >> JFS_IP(ip->i_sb)->l2bsize;
2699 cmSetXD(ip, cp, pno, dxaddr, nblks);
2700
2701
2702 cmPut(cp, true);
2703
2704 dxaddr += nblks;
2705 sxaddr += nblks;
2706 }
2707
2708
2709 if ((rc = xtSearch(ip, xoff, NULL, &cmp, &btstack, 0)))
2710 return rc;
2711
2712 XT_GETSEARCH(ip, btstack.top, bn, pmp, pp, index);
2713 jfs_info("xtRelocate: target data extent relocated.");
2714 } else {
2715
2716
2717
2718
2719 XT_GETPAGE(ip, oxaddr, mp, PSIZE, p, rc);
2720 if (rc) {
2721 XT_PUTPAGE(pmp);
2722 return rc;
2723 }
2724
2725
2726
2727
2728 rmp = NULL;
2729 if (p->header.next) {
2730 nextbn = le64_to_cpu(p->header.next);
2731 XT_GETPAGE(ip, nextbn, rmp, PSIZE, rp, rc);
2732 if (rc) {
2733 XT_PUTPAGE(pmp);
2734 XT_PUTPAGE(mp);
2735 return (rc);
2736 }
2737 }
2738
2739 lmp = NULL;
2740 if (p->header.prev) {
2741 prevbn = le64_to_cpu(p->header.prev);
2742 XT_GETPAGE(ip, prevbn, lmp, PSIZE, lp, rc);
2743 if (rc) {
2744 XT_PUTPAGE(pmp);
2745 XT_PUTPAGE(mp);
2746 if (rmp)
2747 XT_PUTPAGE(rmp);
2748 return (rc);
2749 }
2750 }
2751
2752
2753
2754
2755
2756
2757 if (lmp) {
2758 BT_MARK_DIRTY(lmp, ip);
2759 tlck = txLock(tid, ip, lmp, tlckXTREE | tlckRELINK);
2760 lp->header.next = cpu_to_le64(nxaddr);
2761 XT_PUTPAGE(lmp);
2762 }
2763
2764 if (rmp) {
2765 BT_MARK_DIRTY(rmp, ip);
2766 tlck = txLock(tid, ip, rmp, tlckXTREE | tlckRELINK);
2767 rp->header.prev = cpu_to_le64(nxaddr);
2768 XT_PUTPAGE(rmp);
2769 }
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792 BT_MARK_DIRTY(mp, ip);
2793
2794 tlck = txLock(tid, ip, mp, tlckXTREE | tlckNEW);
2795 xtlck = (struct xtlock *) & tlck->lock;
2796
2797
2798 pxd = &p->header.self;
2799 PXDaddress(pxd, nxaddr);
2800
2801
2802 xtlck->lwm.length =
2803 le16_to_cpu(p->header.nextindex) - xtlck->lwm.offset;
2804
2805
2806 xsize = xlen << JFS_SBI(ip->i_sb)->l2bsize;
2807 bmSetXD(mp, nxaddr, xsize);
2808
2809
2810 XT_PUTPAGE(mp);
2811 jfs_info("xtRelocate: target xtpage relocated.");
2812 }
2813
2814
2815
2816
2817
2818
2819
2820 out:
2821
2822
2823
2824
2825
2826 if (xtype == DATAEXT)
2827 tlck = txMaplock(tid, ip, tlckMAP);
2828
2829
2830
2831
2832
2833
2834
2835
2836 else
2837 tlck = txMaplock(tid, ip, tlckMAP | tlckRELOCATE);
2838
2839 pxdlock = (struct pxd_lock *) & tlck->lock;
2840 pxdlock->flag = mlckFREEPXD;
2841 PXDaddress(&pxdlock->pxd, oxaddr);
2842 PXDlength(&pxdlock->pxd, xlen);
2843 pxdlock->index = 1;
2844
2845
2846
2847
2848
2849
2850
2851
2852 jfs_info("xtRelocate: update parent xad entry.");
2853 BT_MARK_DIRTY(pmp, ip);
2854 tlck = txLock(tid, ip, pmp, tlckXTREE | tlckGROW);
2855 xtlck = (struct xtlock *) & tlck->lock;
2856
2857
2858 xad = &pp->xad[index];
2859 xad->flag |= XAD_NEW;
2860 XADaddress(xad, nxaddr);
2861
2862 xtlck->lwm.offset = min(index, xtlck->lwm.offset);
2863 xtlck->lwm.length = le16_to_cpu(pp->header.nextindex) -
2864 xtlck->lwm.offset;
2865
2866
2867 XT_PUTPAGE(pmp);
2868
2869 return rc;
2870}
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891static int xtSearchNode(struct inode *ip, xad_t * xad,
2892 int *cmpp, struct btstack * btstack, int flag)
2893{
2894 int rc = 0;
2895 s64 xoff, xaddr;
2896 int xlen;
2897 int cmp = 1;
2898 s64 bn;
2899 struct metapage *mp;
2900 xtpage_t *p;
2901 int base, index, lim;
2902 struct btframe *btsp;
2903 s64 t64;
2904
2905 BT_CLR(btstack);
2906
2907 xoff = offsetXAD(xad);
2908 xlen = lengthXAD(xad);
2909 xaddr = addressXAD(xad);
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927 for (bn = 0;;) {
2928
2929 XT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
2930 if (rc)
2931 return rc;
2932 if (p->header.flag & BT_LEAF) {
2933 XT_PUTPAGE(mp);
2934 return -ESTALE;
2935 }
2936
2937 lim = le16_to_cpu(p->header.nextindex) - XTENTRYSTART;
2938
2939
2940
2941
2942 for (base = XTENTRYSTART; lim; lim >>= 1) {
2943 index = base + (lim >> 1);
2944
2945 XT_CMP(cmp, xoff, &p->xad[index], t64);
2946 if (cmp == 0) {
2947
2948
2949
2950
2951
2952 if (xaddr == addressXAD(&p->xad[index]) &&
2953 xoff == offsetXAD(&p->xad[index])) {
2954 *cmpp = cmp;
2955
2956
2957 btsp = btstack->top;
2958 btsp->bn = bn;
2959 btsp->index = index;
2960 btsp->mp = mp;
2961
2962 return 0;
2963 }
2964
2965
2966 goto next;
2967 }
2968
2969 if (cmp > 0) {
2970 base = index + 1;
2971 --lim;
2972 }
2973 }
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983 index = base ? base - 1 : base;
2984
2985
2986
2987
2988 next:
2989
2990 bn = addressXAD(&p->xad[index]);
2991
2992
2993 XT_PUTPAGE(mp);
2994 }
2995}
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011static int xtRelink(tid_t tid, struct inode *ip, xtpage_t * p)
3012{
3013 int rc = 0;
3014 struct metapage *mp;
3015 s64 nextbn, prevbn;
3016 struct tlock *tlck;
3017
3018 nextbn = le64_to_cpu(p->header.next);
3019 prevbn = le64_to_cpu(p->header.prev);
3020
3021
3022 if (nextbn != 0) {
3023 XT_GETPAGE(ip, nextbn, mp, PSIZE, p, rc);
3024 if (rc)
3025 return rc;
3026
3027
3028
3029
3030
3031
3032 BT_MARK_DIRTY(mp, ip);
3033 tlck = txLock(tid, ip, mp, tlckXTREE | tlckRELINK);
3034
3035
3036
3037 p->header.prev = cpu_to_le64(prevbn);
3038
3039 XT_PUTPAGE(mp);
3040 }
3041
3042
3043 if (prevbn != 0) {
3044 XT_GETPAGE(ip, prevbn, mp, PSIZE, p, rc);
3045 if (rc)
3046 return rc;
3047
3048
3049
3050
3051
3052
3053 BT_MARK_DIRTY(mp, ip);
3054 tlck = txLock(tid, ip, mp, tlckXTREE | tlckRELINK);
3055
3056
3057
3058 p->header.next = le64_to_cpu(nextbn);
3059
3060 XT_PUTPAGE(mp);
3061 }
3062
3063 return 0;
3064}
3065#endif
3066
3067
3068
3069
3070
3071
3072
3073void xtInitRoot(tid_t tid, struct inode *ip)
3074{
3075 xtpage_t *p;
3076
3077
3078
3079
3080
3081
3082 txLock(tid, ip, (struct metapage *) &JFS_IP(ip)->bxflag,
3083 tlckXTREE | tlckNEW);
3084 p = &JFS_IP(ip)->i_xtroot;
3085
3086 p->header.flag = DXD_INDEX | BT_ROOT | BT_LEAF;
3087 p->header.nextindex = cpu_to_le16(XTENTRYSTART);
3088
3089 if (S_ISDIR(ip->i_mode))
3090 p->header.maxentry = cpu_to_le16(XTROOTINITSLOT_DIR);
3091 else {
3092 p->header.maxentry = cpu_to_le16(XTROOTINITSLOT);
3093 ip->i_size = 0;
3094 }
3095
3096
3097 return;
3098}
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113#define MAX_TRUNCATE_LEAVES 50
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162s64 xtTruncate(tid_t tid, struct inode *ip, s64 newsize, int flag)
3163{
3164 int rc = 0;
3165 s64 teof;
3166 struct metapage *mp;
3167 xtpage_t *p;
3168 s64 bn;
3169 int index, nextindex;
3170 xad_t *xad;
3171 s64 xoff, xaddr;
3172 int xlen, len, freexlen;
3173 struct btstack btstack;
3174 struct btframe *parent;
3175 struct tblock *tblk = NULL;
3176 struct tlock *tlck = NULL;
3177 struct xtlock *xtlck = NULL;
3178 struct xdlistlock xadlock;
3179 struct pxd_lock *pxdlock;
3180 s64 nfreed;
3181 int freed, log;
3182 int locked_leaves = 0;
3183
3184
3185 if (tid) {
3186 tblk = tid_to_tblock(tid);
3187 tblk->xflag |= flag;
3188 }
3189
3190 nfreed = 0;
3191
3192 flag &= COMMIT_MAP;
3193 assert(flag != COMMIT_PMAP);
3194
3195 if (flag == COMMIT_PWMAP)
3196 log = 1;
3197 else {
3198 log = 0;
3199 xadlock.flag = mlckFREEXADLIST;
3200 xadlock.index = 1;
3201 }
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228 teof = (newsize + (JFS_SBI(ip->i_sb)->bsize - 1)) >>
3229 JFS_SBI(ip->i_sb)->l2bsize;
3230
3231
3232 BT_CLR(&btstack);
3233
3234
3235
3236
3237
3238
3239 bn = 0;
3240
3241
3242
3243
3244 getPage:
3245 XT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
3246 if (rc)
3247 return rc;
3248
3249
3250 index = le16_to_cpu(p->header.nextindex) - 1;
3251
3252
3253
3254
3255
3256
3257 if (p->header.next) {
3258 if (log)
3259
3260
3261
3262
3263
3264 tlck = txLock(tid, ip, mp, tlckXTREE|tlckGROW);
3265 BT_MARK_DIRTY(mp, ip);
3266 p->header.next = 0;
3267 }
3268
3269 if (p->header.flag & BT_INTERNAL)
3270 goto getChild;
3271
3272
3273
3274
3275 freed = 0;
3276
3277
3278 xad = &p->xad[index];
3279 xoff = offsetXAD(xad);
3280 xlen = lengthXAD(xad);
3281 if (teof >= xoff + xlen) {
3282 XT_PUTPAGE(mp);
3283 goto getParent;
3284 }
3285
3286
3287 if (log) {
3288 if (++locked_leaves > MAX_TRUNCATE_LEAVES) {
3289
3290
3291
3292
3293 XT_PUTPAGE(mp);
3294 newsize = (xoff + xlen) << JFS_SBI(ip->i_sb)->l2bsize;
3295 goto getParent;
3296 }
3297 tlck = txLock(tid, ip, mp, tlckXTREE);
3298 tlck->type = tlckXTREE | tlckTRUNCATE;
3299 xtlck = (struct xtlock *) & tlck->lock;
3300 xtlck->hwm.offset = le16_to_cpu(p->header.nextindex) - 1;
3301 }
3302 BT_MARK_DIRTY(mp, ip);
3303
3304
3305
3306
3307 for (; index >= XTENTRYSTART; index--) {
3308 xad = &p->xad[index];
3309 xoff = offsetXAD(xad);
3310 xlen = lengthXAD(xad);
3311 xaddr = addressXAD(xad);
3312
3313
3314
3315
3316
3317
3318 if (S_ISDIR(ip->i_mode) && (teof == 0))
3319 invalidate_xad_metapages(ip, *xad);
3320
3321
3322
3323
3324
3325
3326 if (teof < xoff) {
3327 nfreed += xlen;
3328 continue;
3329 }
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343 if (teof == xoff) {
3344 nfreed += xlen;
3345
3346 if (index == XTENTRYSTART)
3347 break;
3348
3349 nextindex = index;
3350 }
3351
3352
3353
3354
3355
3356
3357 else if (teof < xoff + xlen) {
3358
3359 len = teof - xoff;
3360 freexlen = xlen - len;
3361 XADlength(xad, len);
3362
3363
3364 xaddr += len;
3365 if (log) {
3366 xtlck->lwm.offset = (xtlck->lwm.offset) ?
3367 min(index, (int)xtlck->lwm.offset) : index;
3368 xtlck->lwm.length = index + 1 -
3369 xtlck->lwm.offset;
3370 xtlck->twm.offset = index;
3371 pxdlock = (struct pxd_lock *) & xtlck->pxdlock;
3372 pxdlock->flag = mlckFREEPXD;
3373 PXDaddress(&pxdlock->pxd, xaddr);
3374 PXDlength(&pxdlock->pxd, freexlen);
3375 }
3376
3377 else {
3378
3379 pxdlock = (struct pxd_lock *) & xadlock;
3380 pxdlock->flag = mlckFREEPXD;
3381 PXDaddress(&pxdlock->pxd, xaddr);
3382 PXDlength(&pxdlock->pxd, freexlen);
3383 txFreeMap(ip, pxdlock, NULL, COMMIT_WMAP);
3384
3385
3386 xadlock.flag = mlckFREEXADLIST;
3387 }
3388
3389
3390 nextindex = index + 1;
3391
3392 nfreed += freexlen;
3393 }
3394
3395
3396
3397
3398
3399
3400 else {
3401
3402 nextindex = index + 1;
3403 }
3404
3405 if (nextindex < le16_to_cpu(p->header.nextindex)) {
3406 if (!log) {
3407 xadlock.xdlist = &p->xad[nextindex];
3408 xadlock.count =
3409 le16_to_cpu(p->header.nextindex) -
3410 nextindex;
3411 txFreeMap(ip, (struct maplock *) & xadlock,
3412 NULL, COMMIT_WMAP);
3413 }
3414 p->header.nextindex = cpu_to_le16(nextindex);
3415 }
3416
3417 XT_PUTPAGE(mp);
3418
3419
3420 goto getParent;
3421 }
3422
3423 freed = 1;
3424
3425
3426
3427
3428 if (log) {
3429
3430
3431
3432
3433
3434 tlck->type = tlckXTREE | tlckFREE;
3435 } else {
3436
3437
3438 xadlock.xdlist = &p->xad[XTENTRYSTART];
3439 xadlock.count =
3440 le16_to_cpu(p->header.nextindex) - XTENTRYSTART;
3441 txFreeMap(ip, (struct maplock *) & xadlock, NULL, COMMIT_WMAP);
3442 }
3443
3444 if (p->header.flag & BT_ROOT) {
3445 p->header.flag &= ~BT_INTERNAL;
3446 p->header.flag |= BT_LEAF;
3447 p->header.nextindex = cpu_to_le16(XTENTRYSTART);
3448
3449 XT_PUTPAGE(mp);
3450 goto out;
3451 } else {
3452 if (log) {
3453
3454
3455 XT_PUTPAGE(mp);
3456 } else {
3457
3458 if (mp->lid)
3459 lid_to_tlock(mp->lid)->flag |= tlckFREELOCK;
3460
3461
3462 discard_metapage(mp);
3463 }
3464 }
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475 getParent:
3476
3477 if ((parent = BT_POP(&btstack)) == NULL)
3478
3479 goto out;
3480
3481
3482 bn = parent->bn;
3483 XT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
3484 if (rc)
3485 return rc;
3486
3487 index = parent->index;
3488
3489
3490
3491
3492 if (freed == 0) {
3493
3494 if (index < le16_to_cpu(p->header.nextindex) - 1) {
3495
3496 if (log) {
3497
3498
3499
3500 tlck = txLock(tid, ip, mp, tlckXTREE);
3501 xtlck = (struct xtlock *) & tlck->lock;
3502 if (!(tlck->type & tlckTRUNCATE)) {
3503 xtlck->hwm.offset =
3504 le16_to_cpu(p->header.
3505 nextindex) - 1;
3506 tlck->type =
3507 tlckXTREE | tlckTRUNCATE;
3508 }
3509 } else {
3510
3511
3512 xadlock.xdlist = &p->xad[index + 1];
3513 xadlock.count =
3514 le16_to_cpu(p->header.nextindex) -
3515 index - 1;
3516 txFreeMap(ip, (struct maplock *) & xadlock,
3517 NULL, COMMIT_WMAP);
3518 }
3519 BT_MARK_DIRTY(mp, ip);
3520
3521 p->header.nextindex = cpu_to_le16(index + 1);
3522 }
3523 XT_PUTPAGE(mp);
3524 goto getParent;
3525 }
3526
3527
3528
3529
3530 nfreed += lengthXAD(&p->xad[index]);
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545 if (log && mp->lid && (tblk->last != mp->lid) &&
3546 lid_to_tlock(mp->lid)->tid) {
3547 lid_t lid = mp->lid;
3548 struct tlock *prev;
3549
3550 tlck = lid_to_tlock(lid);
3551
3552 if (tblk->next == lid)
3553 tblk->next = tlck->next;
3554 else {
3555 for (prev = lid_to_tlock(tblk->next);
3556 prev->next != lid;
3557 prev = lid_to_tlock(prev->next)) {
3558 assert(prev->next);
3559 }
3560 prev->next = tlck->next;
3561 }
3562 lid_to_tlock(tblk->last)->next = lid;
3563 tlck->next = 0;
3564 tblk->last = lid;
3565 }
3566
3567
3568
3569
3570 if (index == XTENTRYSTART) {
3571 if (log) {
3572
3573
3574
3575
3576 tlck = txLock(tid, ip, mp, tlckXTREE);
3577 xtlck = (struct xtlock *) & tlck->lock;
3578 xtlck->hwm.offset =
3579 le16_to_cpu(p->header.nextindex) - 1;
3580 tlck->type = tlckXTREE | tlckFREE;
3581 } else {
3582
3583
3584 xadlock.xdlist = &p->xad[XTENTRYSTART];
3585 xadlock.count =
3586 le16_to_cpu(p->header.nextindex) -
3587 XTENTRYSTART;
3588 txFreeMap(ip, (struct maplock *) & xadlock, NULL,
3589 COMMIT_WMAP);
3590 }
3591 BT_MARK_DIRTY(mp, ip);
3592
3593 if (p->header.flag & BT_ROOT) {
3594 p->header.flag &= ~BT_INTERNAL;
3595 p->header.flag |= BT_LEAF;
3596 p->header.nextindex = cpu_to_le16(XTENTRYSTART);
3597 if (le16_to_cpu(p->header.maxentry) == XTROOTMAXSLOT) {
3598
3599
3600
3601
3602 p->header.maxentry =
3603 cpu_to_le16(XTROOTINITSLOT);
3604 JFS_IP(ip)->mode2 |= INLINEEA;
3605 }
3606
3607 XT_PUTPAGE(mp);
3608 goto out;
3609 } else {
3610 if (log) {
3611
3612
3613 XT_PUTPAGE(mp);
3614 } else {
3615
3616 if (mp->lid)
3617 lid_to_tlock(mp->lid)->flag |=
3618 tlckFREELOCK;
3619
3620
3621 discard_metapage(mp);
3622 }
3623
3624
3625
3626
3627
3628 goto getParent;
3629 }
3630 }
3631
3632
3633
3634 else {
3635
3636
3637
3638 index--;
3639
3640
3641
3642
3643 goto getChild;
3644 }
3645
3646
3647
3648
3649 getChild:
3650
3651 if (BT_STACK_FULL(&btstack)) {
3652 jfs_error(ip->i_sb, "stack overrun!\n");
3653 XT_PUTPAGE(mp);
3654 return -EIO;
3655 }
3656 BT_PUSH(&btstack, bn, index);
3657
3658
3659 xad = &p->xad[index];
3660 bn = addressXAD(xad);
3661
3662
3663
3664
3665
3666 XT_PUTPAGE(mp);
3667
3668
3669 goto getPage;
3670
3671 out:
3672
3673
3674
3675
3676
3677 if (S_ISDIR(ip->i_mode) && !newsize)
3678 ip->i_size = 1;
3679 else
3680 ip->i_size = newsize;
3681
3682
3683 dquot_free_block(ip, nfreed);
3684
3685
3686
3687
3688 if (flag == COMMIT_WMAP)
3689 txFreelock(ip);
3690
3691 return newsize;
3692}
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718s64 xtTruncate_pmap(tid_t tid, struct inode *ip, s64 committed_size)
3719{
3720 s64 bn;
3721 struct btstack btstack;
3722 int cmp;
3723 int index;
3724 int locked_leaves = 0;
3725 struct metapage *mp;
3726 xtpage_t *p;
3727 struct btframe *parent;
3728 int rc;
3729 struct tblock *tblk;
3730 struct tlock *tlck = NULL;
3731 xad_t *xad;
3732 int xlen;
3733 s64 xoff;
3734 struct xtlock *xtlck = NULL;
3735
3736
3737 tblk = tid_to_tblock(tid);
3738 tblk->xflag |= COMMIT_PMAP;
3739
3740
3741 BT_CLR(&btstack);
3742
3743 if (committed_size) {
3744 xoff = (committed_size >> JFS_SBI(ip->i_sb)->l2bsize) - 1;
3745 rc = xtSearch(ip, xoff, NULL, &cmp, &btstack, 0);
3746 if (rc)
3747 return rc;
3748
3749 XT_GETSEARCH(ip, btstack.top, bn, mp, p, index);
3750
3751 if (cmp != 0) {
3752 XT_PUTPAGE(mp);
3753 jfs_error(ip->i_sb, "did not find extent\n");
3754 return -EIO;
3755 }
3756 } else {
3757
3758
3759
3760
3761
3762 bn = 0;
3763
3764
3765
3766
3767 getPage:
3768 XT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
3769 if (rc)
3770 return rc;
3771
3772
3773 index = le16_to_cpu(p->header.nextindex) - 1;
3774
3775 if (p->header.flag & BT_INTERNAL)
3776 goto getChild;
3777 }
3778
3779
3780
3781
3782
3783 if (++locked_leaves > MAX_TRUNCATE_LEAVES) {
3784
3785
3786
3787
3788 xad = &p->xad[index];
3789 xoff = offsetXAD(xad);
3790 xlen = lengthXAD(xad);
3791 XT_PUTPAGE(mp);
3792 return (xoff + xlen) << JFS_SBI(ip->i_sb)->l2bsize;
3793 }
3794 tlck = txLock(tid, ip, mp, tlckXTREE);
3795 tlck->type = tlckXTREE | tlckFREE;
3796 xtlck = (struct xtlock *) & tlck->lock;
3797 xtlck->hwm.offset = index;
3798
3799
3800 XT_PUTPAGE(mp);
3801
3802
3803
3804
3805 getParent:
3806
3807 if ((parent = BT_POP(&btstack)) == NULL)
3808
3809 goto out;
3810
3811
3812 bn = parent->bn;
3813 XT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
3814 if (rc)
3815 return rc;
3816
3817 index = parent->index;
3818
3819
3820
3821
3822 if (index == XTENTRYSTART) {
3823
3824
3825
3826
3827 tlck = txLock(tid, ip, mp, tlckXTREE);
3828 xtlck = (struct xtlock *) & tlck->lock;
3829 xtlck->hwm.offset = le16_to_cpu(p->header.nextindex) - 1;
3830 tlck->type = tlckXTREE | tlckFREE;
3831
3832 XT_PUTPAGE(mp);
3833
3834 if (p->header.flag & BT_ROOT) {
3835
3836 goto out;
3837 } else {
3838 goto getParent;
3839 }
3840 }
3841
3842
3843
3844 else
3845 index--;
3846
3847
3848
3849 getChild:
3850
3851 if (BT_STACK_FULL(&btstack)) {
3852 jfs_error(ip->i_sb, "stack overrun!\n");
3853 XT_PUTPAGE(mp);
3854 return -EIO;
3855 }
3856 BT_PUSH(&btstack, bn, index);
3857
3858
3859 xad = &p->xad[index];
3860 bn = addressXAD(xad);
3861
3862
3863
3864
3865
3866 XT_PUTPAGE(mp);
3867
3868
3869 goto getPage;
3870
3871 out:
3872
3873 return 0;
3874}
3875
3876#ifdef CONFIG_JFS_STATISTICS
3877int jfs_xtstat_proc_show(struct seq_file *m, void *v)
3878{
3879 seq_printf(m,
3880 "JFS Xtree statistics\n"
3881 "====================\n"
3882 "searches = %d\n"
3883 "fast searches = %d\n"
3884 "splits = %d\n",
3885 xtStat.search,
3886 xtStat.fastSearch,
3887 xtStat.split);
3888 return 0;
3889}
3890#endif
3891