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