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