23 #include <linux/module.h>
37 #define XT_INSERT 0x00000001
47 #define XT_CMP(CMP, K, X, OFFSET64)\
49 OFFSET64 = offsetXAD(X);\
50 (CMP) = ((K) >= OFFSET64 + lengthXAD(X)) ? 1 :\
51 ((K) < OFFSET64) ? -1 : 0;\
55 #define XT_PUTENTRY(XAD, FLAG, OFF, LEN, ADDR)\
57 (XAD)->flag = (FLAG);\
58 XADoffset((XAD), (OFF));\
59 XADlength((XAD), (LEN));\
60 XADaddress((XAD), (ADDR));\
63 #define XT_PAGE(IP, MP) BT_PAGE(IP, MP, xtpage_t, i_xtroot)
67 #define XT_GETPAGE(IP, BN, MP, SIZE, P, RC)\
69 BT_GETPAGE(IP, BN, MP, xtpage_t, SIZE, P, RC, i_xtroot)\
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)))\
76 jfs_error((IP)->i_sb, "XT_GETPAGE: xtree page corrupt");\
85 #define XT_PUTPAGE(MP) BT_PUTPAGE(MP)
87 #define XT_GETSEARCH(IP, LEAF, BN, MP, P, INDEX) \
88 BT_GETSEARCH(IP, LEAF, BN, MP, xtpage_t, P, INDEX, i_xtroot)
104 #ifdef CONFIG_JFS_STATISTICS
119 static int xtSplitUp(
tid_t tid,
129 #ifdef _STILL_TO_PORT
133 static int xtSearchNode(
struct inode *
ip,
165 size = ((
u64) ip->
i_size + (JFS_SBI(ip->
i_sb)->bsize - 1)) >>
166 JFS_SBI(ip->
i_sb)->l2bsize;
175 if ((rc = xtSearch(ip, lstart, &next, &cmp, &btstack, 0))) {
176 jfs_err(
"xtLookup: xtSearch returned %d", rc);
195 *plen =
min(next - lstart, llen);
210 *paddr = xaddr + (lstart -
xoff);
212 *plen =
min(xend - lstart, llen);
349 if (p->
header.nextindex ==
381 index = base + (lim >> 1);
395 if (flag & XT_INSERT) {
396 if (p->
header.nextindex ==
412 if (index == btindex ||
413 index == btindex + 1)
453 if (flag & XT_INSERT) {
454 if (p->
header.nextindex ==
470 if (base == btindex || base == btindex + 1)
488 index = base ? base - 1 : base;
545 int index, nextindex;
546 struct btstack btstack;
554 jfs_info(
"xtInsert: nxoff:0x%lx nxlen:0x%x", (
ulong) xoff, xlen);
564 if ((rc = xtSearch(ip, xoff, &next, &cmp, &btstack, XT_INSERT)))
572 if ((cmp == 0) || (next && (xlen > next - xoff))) {
582 if ((xaddr = *xaddrp) == 0) {
584 xad = &p->
xad[index - 1];
588 if ((rc = dquot_alloc_block(ip, xlen)))
590 if ((rc =
dbAlloc(ip, hint, (
s64) xlen, &xaddr))) {
591 dquot_free_block(ip, xlen);
616 if ((rc = xtSplitUp(tid, ip, &split, &btstack))) {
620 dquot_free_block(ip, xlen);
640 if (index < nextindex)
642 (nextindex - index) *
sizeof(
xad_t));
649 le16_add_cpu(&p->
header.nextindex, 1);
656 (xtlck->
lwm.offset) ?
min(index,
718 JFS_IP(ip)->mode2 &= ~INLINEEA;
730 if (skip < nextindex)
732 (nextindex - skip) *
sizeof(
xad_t));
740 le16_add_cpu(&sp->
header.nextindex, 1);
746 xtlck->
lwm.offset = (xtlck->
lwm.offset) ?
747 min(skip, (
int)xtlck->
lwm.offset) : skip;
766 xlen = JFS_SBI(ip->
i_sb)->nbperpage;
767 for (; nsplit > 0; nsplit--, pxd++) {
793 xtSplitRoot(tid, ip, split, &rmp) :
794 xtSplitPage(tid, ip, split, &rmp, &rbn);
843 skip = parent->
index + 1;
858 split->
len = JFS_SBI(ip->
i_sb)->nbperpage;
869 xtSplitRoot(tid, ip, split, &rmp) :
870 xtSplitPage(tid, ip, split, &rmp, &rbn);
897 if (skip < nextindex)
906 JFS_SBI(ip->
i_sb)->nbperpage, rcbn);
909 le16_add_cpu(&sp->
header.nextindex, 1);
913 tlck =
txLock(tid, ip, smp,
916 xtlck->
lwm.offset = (xtlck->
lwm.offset) ?
917 min(skip, (
int)xtlck->
lwm.offset) : skip;
969 int skip, maxentry, middle, righthalf,
n;
975 int quota_allocation = 0;
983 pxd = &pxdlist->
pxd[pxdlist->
npxd];
988 rc = dquot_alloc_block(ip,
lengthPXD(pxd));
1003 jfs_info(
"xtSplitPage: ip:0x%p smp:0x%p rmp:0x%p", ip, smp, rmp);
1040 skip = split->
index;
1070 rxtlck->lwm.length = 1;
1076 jfs_info(
"xtSplitPage: sp:0x%p rp:0x%p", sp, rp);
1116 middle = maxentry >> 1;
1117 righthalf = maxentry - middle;
1122 if (skip <= middle) {
1140 sxtlck->
lwm.offset = (sxtlck->
lwm.offset) ?
1141 min(skip, (
int)sxtlck->
lwm.offset) : skip;
1163 if (skip < maxentry)
1170 sxtlck->
lwm.offset = (sxtlck->
lwm.offset) ?
1171 min(middle, (
int)sxtlck->
lwm.offset) : middle;
1190 jfs_info(
"xtSplitPage: sp:0x%p rp:0x%p", sp, rp);
1196 if (quota_allocation)
1197 dquot_free_block(ip, quota_allocation);
1224 xtSplitRoot(
tid_t tid,
1231 int skip, nextindex;
1234 struct pxdlist *pxdlist;
1239 sp = &JFS_IP(ip)->i_xtroot;
1247 pxd = &pxdlist->
pxd[pxdlist->
npxd];
1255 rc = dquot_alloc_block(ip,
lengthPXD(pxd));
1261 jfs_info(
"xtSplitRoot: ip:0x%p rmp:0x%p", ip, rmp);
1292 skip = split->
index;
1294 if (skip != nextindex)
1296 (nextindex - skip) *
sizeof(
xad_t));
1339 xtlck->
lwm.length = 1;
1344 jfs_info(
"xtSplitRoot: sp:0x%p rp:0x%p", sp, rp);
1370 struct btstack btstack;
1377 jfs_info(
"xtExtend: nxoff:0x%lx nxlen:0x%x", (
ulong) xoff, xlen);
1380 if ((rc = xtSearch(ip, xoff - 1,
NULL, &cmp, &btstack, XT_INSERT)))
1388 jfs_error(ip->
i_sb,
"xtExtend: xtSearch did not find extent");
1396 jfs_error(ip->
i_sb,
"xtExtend: extension is not contiguous");
1413 if ((len = xlen -
MAXXLEN) <= 0)
1433 split.
index = index + 1;
1439 if ((rc = xtSplitUp(tid, ip, &split, &btstack)))
1475 xad = &p->
xad[index + 1];
1479 le16_add_cpu(&p->
header.nextindex, 1);
1496 (xtlck->
lwm.offset) ?
min(index,
1497 (
int)xtlck->
lwm.offset) : index;
1521 int xtTailgate(
tid_t tid,
1532 int index, nextindex, llen, rlen;
1533 struct btstack btstack;
1537 struct xtlock *xtlck = 0;
1538 struct tlock *mtlck;
1547 if ((rc = xtSearch(ip, xoff,
NULL, &cmp, &btstack, XT_INSERT)))
1561 if (index != nextindex - 1) {
1564 "xtTailgate: the entry found is not the last entry");
1583 if ((llen = xoff -
offsetXAD(xad)) == 0)
1599 split.
index = index + 1;
1605 if ((rc = xtSplitUp(tid, ip, &split, &btstack)))
1641 xad = &p->
xad[index + 1];
1645 le16_add_cpu(&p->
header.nextindex, 1);
1679 xtlck->
lwm.offset = (xtlck->
lwm.offset) ?
1680 min(index, (
int)xtlck->
lwm.offset) : index;
1712 int index0,
index, newindex, nextindex;
1713 struct btstack btstack;
1715 xad_t *xad, *lxad, *rxad;
1718 int nxlen, xlen, lxlen,
rxlen;
1729 if ((rc = xtSearch(ip, nxoff,
NULL, &cmp, &btstack, XT_INSERT)))
1750 xad = &p->
xad[index0];
1757 if ((xoff > nxoff) ||
1758 (nxoff + nxlen > xoff + xlen)) {
1761 "xtUpdate: nXAD in not completely contained within XAD");
1766 newindex = index + 1;
1769 #ifdef _JFS_WIP_NOCOALESCE
1777 if (nxlen == xlen) {
1800 lxad = &p->
xad[index - 1];
1827 if (index < nextindex - 1)
1829 (nextindex - index -
1837 newindex = index + 1;
1840 xlen = nxlen = lxlen + nxlen;
1850 if (nxlen == xlen) {
1864 if (newindex == nextindex) {
1871 rxad = &p->
xad[index + 1];
1905 }
else if (xoff == nxoff)
1908 if (xoff >= nxoff) {
1932 split.
index = newindex;
1936 split.
addr = nxaddr;
1938 if ((rc = xtSplitUp(tid, ip, &split, &btstack)))
1980 if (newindex < nextindex)
1985 xad = &p->
xad[newindex];
2001 if (nxoff + nxlen == xoff + xlen)
2008 xtlck->
lwm.offset = (xtlck->
lwm.offset) ?
2009 min(index0, (
int)xtlck->
lwm.offset) : index0;
2029 index0 = index = newindex;
2033 newindex = index + 1;
2035 xlen = xlen - (nxoff -
xoff);
2043 if ((rc = xtSearch(ip, nxoff,
NULL, &cmp, &btstack, XT_INSERT)))
2055 if (index0 != index) {
2058 "xtUpdate: unexpected value of index");
2077 xoff = xoff + nxlen;
2078 xlen = xlen - nxlen;
2079 xaddr = xaddr + nxlen;
2086 split.
index = newindex;
2092 if ((rc = xtSplitUp(tid, ip, &split, &btstack)))
2125 if (newindex < nextindex)
2130 xad = &p->
xad[newindex];
2140 xtlck->
lwm.offset = (xtlck->
lwm.offset) ?
2141 min(index0, (
int)xtlck->
lwm.offset) : index0;
2171 struct inode *ip,
int xflag,
s64 xoff,
s32 maxblocks,
2180 int index, nextindex;
2181 struct btstack btstack;
2187 int nsplit, nblocks, xlen;
2188 struct pxdlist pxdlist;
2194 jfs_info(
"xtAppend: xoff:0x%lx maxblocks:%d xlen:%d xaddr:0x%lx",
2195 (
ulong) xoff, maxblocks, xlen, (
ulong) xaddr);
2205 if ((rc = xtSearch(ip, xoff, &next, &cmp, &btstack, XT_INSERT)))
2217 xlen =
min(xlen, (
int)(next - xoff));
2240 pxd = &pxdlist.
pxd[0];
2241 nblocks = JFS_SBI(ip->
i_sb)->nbperpage;
2242 for (; nsplit > 0; nsplit--, pxd++, xaddr += nblocks, maxblocks -= nblocks) {
2257 xlen =
min(xlen, maxblocks);
2271 if ((rc = xtSplitUp(tid, ip, &split, &btstack))) {
2302 xad = &p->
xad[index];
2306 le16_add_cpu(&p->
header.nextindex, 1);
2309 (xtlck->
lwm.offset) ?
min(index,(
int) xtlck->
lwm.offset) : index;
2322 #ifdef _STILL_TO_PORT
2343 struct btstack btstack;
2348 int index, nextindex;
2355 if ((rc = xtSearch(ip, xoff,
NULL, &cmp, &btstack, 0)))
2369 le16_add_cpu(&p->
header.nextindex, -1);
2375 return (xtDeleteUp(tid, ip, mp, p, &btstack));
2386 (xtlck->
lwm.offset) ?
min(index, xtlck->
lwm.offset) : index;
2389 if (index < nextindex - 1)
2391 (nextindex - index - 1) *
sizeof(
xad_t));
2417 int index, nextindex;
2441 if ((rc = xtRelink(tid, ip, fp))) {
2452 discard_metapage(fmp);
2468 index = parent->
index;
2478 if (nextindex == 1) {
2491 if ((rc = xtRelink(tid, ip, p)))
2497 (
s64) JFS_SBI(ip->
i_sb)->nbperpage);
2500 discard_metapage(mp);
2520 (xtlck->
lwm.offset) ?
min(index,
2527 if (index < nextindex - 1)
2529 (nextindex - index -
2532 le16_add_cpu(&p->
header.nextindex, -1);
2533 jfs_info(
"xtDeleteUp(entry): 0x%lx[%d]",
2574 s64 oxaddr, sxaddr, dxaddr, nextbn, prevbn;
2577 int nb, npages, nblks;
2582 struct btstack btstack;
2584 xtype = xtype & EXTENT_TYPE;
2591 offset = xoff << JFS_SBI(ip->
i_sb)->l2bsize;
2592 if (offset >= ip->
i_size)
2595 jfs_info(
"xtRelocate: xtype:%d xoff:0x%lx xlen:0x%x xaddr:0x%lx:0x%lx",
2602 if (xtype == DATAEXT) {
2604 rc = xtSearch(ip, xoff,
NULL, &cmp, &btstack, 0);
2625 rc = xtSearchNode(ip, oxad, &cmp, &btstack, 0);
2641 jfs_info(
"xtRelocate: parent xad entry validated.");
2646 if (xtype == DATAEXT) {
2673 offset = xoff << JFS_SBI(ip->
i_sb)->l2bsize;
2674 assert((offset & CM_OFFSET) == 0);
2675 nbytes = xlen << JFS_SBI(ip->
i_sb)->l2bsize;
2676 pno = offset >> CM_L2BSIZE;
2677 npages = (nbytes + (CM_BSIZE - 1)) >> CM_L2BSIZE;
2686 for (nbrd = 0; nbrd <
nbytes; nbrd += nb,
2687 offset += nb, pno++, npages--) {
2689 nb =
min(nbytes - nbrd, CM_BSIZE);
2692 if (rc = cmRead(ip, offset, npages, &cp))
2696 assert(!cp->cm_modified);
2699 nblks = nb >> JFS_IP(ip->
i_sb)->l2bsize;
2700 cmSetXD(ip, cp, pno, dxaddr, nblks);
2710 if ((rc = xtSearch(ip, xoff,
NULL, &cmp, &btstack, 0)))
2714 jfs_info(
"xtRelocate: target data extent relocated.");
2807 xsize = xlen << JFS_SBI(ip->
i_sb)->l2bsize;
2808 bmSetXD(mp, nxaddr, xsize);
2812 jfs_info(
"xtRelocate: target xtpage relocated.");
2827 if (xtype == DATAEXT)
2853 jfs_info(
"xtRelocate: update parent xad entry.");
2859 xad = &pp->
xad[index];
2863 xtlck->
lwm.offset =
min(index, xtlck->
lwm.offset);
2892 static int xtSearchNode(
struct inode *ip,
xad_t * xad,
2893 int *cmpp,
struct btstack * btstack,
int flag)
2902 int base,
index, lim;
2944 index = base + (lim >> 1);
2958 btsp = btstack->
top;
2984 index = base ? base - 1 : base;
3085 p = &JFS_IP(ip)->i_xtroot;
3114 #define MAX_TRUNCATE_LEAVES 50
3170 int index, nextindex;
3173 int xlen,
len, freexlen;
3174 struct btstack btstack;
3183 int locked_leaves = 0;
3229 teof = (newsize + (JFS_SBI(ip->
i_sb)->bsize - 1)) >>
3230 JFS_SBI(ip->
i_sb)->l2bsize;
3282 if (teof >= xoff + xlen) {
3295 newsize = (xoff + xlen) << JFS_SBI(ip->
i_sb)->l2bsize;
3358 else if (teof < xoff + xlen) {
3361 freexlen = xlen - len;
3367 xtlck->
lwm.offset = (xtlck->
lwm.offset) ?
3368 min(index, (
int)xtlck->
lwm.offset) : index;
3369 xtlck->
lwm.length = index + 1 -
3380 pxdlock = (
struct pxd_lock *) & xadlock;
3391 nextindex = index + 1;
3403 nextindex = index + 1;
3408 xadlock.xdlist = &p->
xad[nextindex];
3463 discard_metapage(mp);
3488 index = parent->
index;
3513 xadlock.xdlist = &p->
xad[index + 1];
3546 if (log && mp->
lid && (tblk->
last != mp->
lid) &&
3553 if (tblk->
next == lid)
3622 discard_metapage(mp);
3684 dquot_free_block(ip, nfreed);
3722 struct btstack btstack;
3725 int locked_leaves = 0;
3744 if (committed_size) {
3745 xoff = (committed_size >> JFS_SBI(ip->
i_sb)->l2bsize) - 1;
3746 rc = xtSearch(ip, xoff,
NULL, &cmp, &btstack, 0);
3755 "xtTruncate_pmap: did not find extent");
3794 return (xoff + xlen) << JFS_SBI(ip->
i_sb)->l2bsize;
3799 xtlck->
hwm.offset = index;
3819 index = parent->
index;
3878 #ifdef CONFIG_JFS_STATISTICS
3879 static int jfs_xtstat_proc_show(
struct seq_file *
m,
void *
v)
3882 "JFS Xtree statistics\n"
3883 "====================\n"
3885 "fast searches = %d\n"
3900 .open = jfs_xtstat_proc_open,