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