X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=fs%2Fjfs%2Fjfs_xtree.c;h=82bb1381d313ed4368b12cb8844e5f7da32b8068;hb=97bf2856c6014879bd04983a3e9dfcdac1e7fe85;hp=19913fcd4c332a48d8b4f49594d4eb66e1a6a26c;hpb=9bf4aaab3e101692164d49b7ca357651eb691cb6;p=linux-2.6.git diff --git a/fs/jfs/jfs_xtree.c b/fs/jfs/jfs_xtree.c index 19913fcd4..82bb1381d 100644 --- a/fs/jfs/jfs_xtree.c +++ b/fs/jfs/jfs_xtree.c @@ -1,18 +1,18 @@ /* - * Copyright (C) International Business Machines Corp., 2000-2003 + * Copyright (C) International Business Machines Corp., 2000-2005 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or + * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See * the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software + * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* @@ -20,6 +20,8 @@ */ #include +#include +#include #include "jfs_incore.h" #include "jfs_filsys.h" #include "jfs_metapage.h" @@ -110,8 +112,8 @@ static struct { /* * forward references */ -static int xtSearch(struct inode *ip, - s64 xoff, int *cmpp, struct btstack * btstack, int flag); +static int xtSearch(struct inode *ip, s64 xoff, s64 *next, int *cmpp, + struct btstack * btstack, int flag); static int xtSplitUp(tid_t tid, struct inode *ip, @@ -134,14 +136,6 @@ static int xtSearchNode(struct inode *ip, static int xtRelink(tid_t tid, struct inode *ip, xtpage_t * fp); #endif /* _STILL_TO_PORT */ -/* External references */ - -/* - * debug control - */ -/* #define _JFS_DEBUG_XTREE 1 */ - - /* * xtLookup() * @@ -158,11 +152,12 @@ int xtLookup(struct inode *ip, s64 lstart, xtpage_t *p; int index; xad_t *xad; - s64 size, xoff, xend; + s64 next, size, xoff, xend; int xlen; s64 xaddr; - *plen = 0; + *paddr = 0; + *plen = llen; if (!no_check) { /* is lookup offset beyond eof ? */ @@ -179,7 +174,7 @@ int xtLookup(struct inode *ip, s64 lstart, * search for the xad entry covering the logical extent */ //search: - if ((rc = xtSearch(ip, lstart, &cmp, &btstack, 0))) { + if ((rc = xtSearch(ip, lstart, &next, &cmp, &btstack, 0))) { jfs_err("xtLookup: xtSearch returned %d", rc); return rc; } @@ -197,8 +192,11 @@ int xtLookup(struct inode *ip, s64 lstart, * lstart is a page start address, * i.e., lstart cannot start in a hole; */ - if (cmp) + if (cmp) { + if (next) + *plen = min(next - lstart, llen); goto out; + } /* * lxd covered by xad @@ -283,7 +281,7 @@ int xtLookupList(struct inode *ip, struct lxdlist * lxdlist, if (lstart >= size) return 0; - if ((rc = xtSearch(ip, lstart, &cmp, &btstack, 0))) + if ((rc = xtSearch(ip, lstart, NULL, &cmp, &btstack, 0))) return rc; /* @@ -487,6 +485,7 @@ int xtLookupList(struct inode *ip, struct lxdlist * lxdlist, * parameters: * ip - file object; * xoff - extent offset; + * nextp - address of next extent (if any) for search miss * cmpp - comparison result: * btstack - traverse stack; * flag - search process flag (XT_INSERT); @@ -496,7 +495,7 @@ int xtLookupList(struct inode *ip, struct lxdlist * lxdlist, * *cmpp is set to result of comparison with the entry returned. * the page containing the entry is pinned at exit. */ -static int xtSearch(struct inode *ip, s64 xoff, /* offset of extent */ +static int xtSearch(struct inode *ip, s64 xoff, s64 *nextp, int *cmpp, struct btstack * btstack, int flag) { struct jfs_inode_info *jfs_ip = JFS_IP(ip); @@ -510,6 +509,7 @@ static int xtSearch(struct inode *ip, s64 xoff, /* offset of extent */ struct btframe *btsp; int nsplit = 0; /* number of pages to split */ s64 t64; + s64 next = 0; INCREMENT(xtStat.search); @@ -578,6 +578,7 @@ static int xtSearch(struct inode *ip, s64 xoff, /* offset of extent */ * previous and this entry */ *cmpp = 1; + next = t64; goto out; } @@ -622,6 +623,9 @@ static int xtSearch(struct inode *ip, s64 xoff, /* offset of extent */ /* update sequential access heuristics */ jfs_ip->btindex = index; + if (nextp) + *nextp = next; + INCREMENT(xtStat.fastSearch); return 0; } @@ -674,10 +678,11 @@ static int xtSearch(struct inode *ip, s64 xoff, /* offset of extent */ return 0; } - /* search hit - internal page: * descend/search its child page */ + if (index < le16_to_cpu(p->header.nextindex)-1) + next = offsetXAD(&p->xad[index + 1]); goto next; } @@ -693,6 +698,8 @@ static int xtSearch(struct inode *ip, s64 xoff, /* offset of extent */ * base is the smallest index with key (Kj) greater than * search key (K) and may be zero or maxentry index. */ + if (base < le16_to_cpu(p->header.nextindex)) + next = offsetXAD(&p->xad[base]); /* * search miss - leaf page: * @@ -726,6 +733,9 @@ static int xtSearch(struct inode *ip, s64 xoff, /* offset of extent */ jfs_ip->btorder = BT_RANDOM; jfs_ip->btindex = base; + if (nextp) + *nextp = next; + return 0; } @@ -792,6 +802,7 @@ int xtInsert(tid_t tid, /* transaction id */ struct xtsplit split; /* split information */ xad_t *xad; int cmp; + s64 next; struct tlock *tlck; struct xtlock *xtlck; @@ -805,7 +816,7 @@ int xtInsert(tid_t tid, /* transaction id */ * n.b. xtSearch() may return index of maxentry of * the full page. */ - if ((rc = xtSearch(ip, xoff, &cmp, &btstack, XT_INSERT))) + if ((rc = xtSearch(ip, xoff, &next, &cmp, &btstack, XT_INSERT))) return rc; /* retrieve search result */ @@ -813,7 +824,7 @@ int xtInsert(tid_t tid, /* transaction id */ /* This test must follow XT_GETSEARCH since mp must be valid if * we branch to out: */ - if (cmp == 0) { + if ((cmp == 0) || (next && (xlen > next - xoff))) { rc = -EEXIST; goto out; } @@ -829,8 +840,17 @@ int xtInsert(tid_t tid, /* transaction id */ hint = addressXAD(xad) + lengthXAD(xad) - 1; } else hint = 0; - if ((rc = dbAlloc(ip, hint, (s64) xlen, &xaddr))) + if ((rc = DQUOT_ALLOC_BLOCK(ip, xlen))) + goto out; + if ((rc = DLIMIT_ALLOC_BLOCK(ip, xlen))) { + DQUOT_FREE_BLOCK(ip, xlen); + goto out; + } + if ((rc = dbAlloc(ip, hint, (s64) xlen, &xaddr))) { + DLIMIT_FREE_BLOCK(ip, xlen); + DQUOT_FREE_BLOCK(ip, xlen); goto out; + } } /* @@ -855,8 +875,11 @@ int xtInsert(tid_t tid, /* transaction id */ split.pxdlist = NULL; if ((rc = xtSplitUp(tid, ip, &split, &btstack))) { /* undo data extent allocation */ - if (*xaddrp == 0) + if (*xaddrp == 0) { dbFree(ip, xaddr, (s64) xlen); + DLIMIT_FREE_BLOCK(ip, xlen); + DQUOT_FREE_BLOCK(ip, xlen); + } return rc; } @@ -951,7 +974,7 @@ xtSplitUp(tid_t tid, /* is inode xtree root extension/inline EA area free ? */ if ((sp->header.flag & BT_ROOT) && (!S_ISDIR(ip->i_mode)) && - (sp->header.maxentry < cpu_to_le16(XTROOTMAXSLOT)) && + (le16_to_cpu(sp->header.maxentry) < XTROOTMAXSLOT) && (JFS_IP(ip)->mode2 & INLINEEA)) { sp->header.maxentry = cpu_to_le16(XTROOTMAXSLOT); JFS_IP(ip)->mode2 &= ~INLINEEA; @@ -1214,22 +1237,42 @@ xtSplitPage(tid_t tid, struct inode *ip, pxd_t *pxd; struct tlock *tlck; struct xtlock *sxtlck = NULL, *rxtlck = NULL; + int quota_allocation = 0; + int dlimit_allocation = 0; smp = split->mp; sp = XT_PAGE(ip, smp); INCREMENT(xtStat.split); - /* - * allocate the new right page for the split - */ pxdlist = split->pxdlist; pxd = &pxdlist->pxd[pxdlist->npxd]; pxdlist->npxd++; rbn = addressPXD(pxd); + + /* Allocate blocks to quota. */ + if (DQUOT_ALLOC_BLOCK(ip, lengthPXD(pxd))) { + rc = -EDQUOT; + goto clean_up; + } + + quota_allocation += lengthPXD(pxd); + + /* Allocate blocks to dlimit. */ + if (DLIMIT_ALLOC_BLOCK(ip, lengthPXD(pxd))) { + rc = -ENOSPC; + goto clean_up; + } + dlimit_allocation += lengthPXD(pxd); + + /* + * allocate the new right page for the split + */ rmp = get_metapage(ip, rbn, PSIZE, 1); - if (rmp == NULL) - return -EIO; + if (rmp == NULL) { + rc = -EIO; + goto clean_up; + } jfs_info("xtSplitPage: ip:0x%p smp:0x%p rmp:0x%p", ip, smp, rmp); @@ -1304,8 +1347,6 @@ xtSplitPage(tid_t tid, struct inode *ip, *rmpp = rmp; *rbnp = rbn; - ip->i_blocks += LBLK2PBLK(ip->i_sb, lengthPXD(pxd)); - jfs_info("xtSplitPage: sp:0x%p rp:0x%p", sp, rp); return 0; } @@ -1321,7 +1362,7 @@ xtSplitPage(tid_t tid, struct inode *ip, XT_GETPAGE(ip, nextbn, mp, PSIZE, p, rc); if (rc) { XT_PUTPAGE(rmp); - return rc; + goto clean_up; } BT_MARK_DIRTY(mp, ip); @@ -1420,10 +1461,19 @@ xtSplitPage(tid_t tid, struct inode *ip, *rmpp = rmp; *rbnp = rbn; - ip->i_blocks += LBLK2PBLK(ip->i_sb, lengthPXD(pxd)); - jfs_info("xtSplitPage: sp:0x%p rp:0x%p", sp, rp); return rc; + + clean_up: + + /* Rollback dlimit allocation. */ + if (dlimit_allocation) + DLIMIT_FREE_BLOCK(ip, dlimit_allocation); + /* Rollback quota allocation. */ + if (quota_allocation) + DQUOT_FREE_BLOCK(ip, quota_allocation); + + return (rc); } @@ -1478,6 +1528,18 @@ xtSplitRoot(tid_t tid, if (rmp == NULL) return -EIO; + /* Allocate blocks to quota. */ + if (DQUOT_ALLOC_BLOCK(ip, lengthPXD(pxd))) { + release_metapage(rmp); + return -EDQUOT; + } + /* Allocate blocks to dlimit. */ + if (DLIMIT_ALLOC_BLOCK(ip, lengthPXD(pxd))) { + DQUOT_FREE_BLOCK(ip, lengthPXD(pxd)); + release_metapage(rmp); + return -ENOSPC; + } + jfs_info("xtSplitRoot: ip:0x%p rmp:0x%p", ip, rmp); /* @@ -1561,8 +1623,6 @@ xtSplitRoot(tid_t tid, *rmpp = rmp; - ip->i_blocks += LBLK2PBLK(ip->i_sb, lengthPXD(pxd)); - jfs_info("xtSplitRoot: sp:0x%p rp:0x%p", sp, rp); return 0; } @@ -1595,12 +1655,11 @@ int xtExtend(tid_t tid, /* transaction id */ s64 xaddr; struct tlock *tlck; struct xtlock *xtlck = NULL; - int rootsplit = 0; jfs_info("xtExtend: nxoff:0x%lx nxlen:0x%x", (ulong) xoff, xlen); /* there must exist extent to be extended */ - if ((rc = xtSearch(ip, xoff - 1, &cmp, &btstack, XT_INSERT))) + if ((rc = xtSearch(ip, xoff - 1, NULL, &cmp, &btstack, XT_INSERT))) return rc; /* retrieve search result */ @@ -1651,8 +1710,6 @@ int xtExtend(tid_t tid, /* transaction id */ * The xtSplitUp() will insert the entry and unpin the leaf page. */ if (nextindex == le16_to_cpu(p->header.maxentry)) { - rootsplit = p->header.flag & BT_ROOT; - /* xtSpliUp() unpins leaf pages */ split.mp = mp; split.index = index + 1; @@ -1664,16 +1721,21 @@ int xtExtend(tid_t tid, /* transaction id */ if ((rc = xtSplitUp(tid, ip, &split, &btstack))) return rc; + /* get back old page */ + XT_GETPAGE(ip, bn, mp, PSIZE, p, rc); + if (rc) + return rc; /* * if leaf root has been split, original root has been * copied to new child page, i.e., original entry now * resides on the new child page; */ - if (rootsplit) { + if (p->header.flag & BT_INTERNAL) { ASSERT(p->header.nextindex == cpu_to_le16(XTENTRYSTART + 1)); xad = &p->xad[XTENTRYSTART]; bn = addressXAD(xad); + XT_PUTPAGE(mp); /* get new child page */ XT_GETPAGE(ip, bn, mp, PSIZE, p, rc); @@ -1685,11 +1747,6 @@ int xtExtend(tid_t tid, /* transaction id */ tlck = txLock(tid, ip, mp, tlckXTREE|tlckGROW); xtlck = (struct xtlock *) & tlck->lock; } - } else { - /* get back old page */ - XT_GETPAGE(ip, bn, mp, PSIZE, p, rc); - if (rc) - return rc; } } /* @@ -1763,7 +1820,6 @@ int xtTailgate(tid_t tid, /* transaction id */ struct xtlock *xtlck = 0; struct tlock *mtlck; struct maplock *pxdlock; - int rootsplit = 0; /* printf("xtTailgate: nxoff:0x%lx nxlen:0x%x nxaddr:0x%lx\n", @@ -1771,7 +1827,7 @@ printf("xtTailgate: nxoff:0x%lx nxlen:0x%x nxaddr:0x%lx\n", */ /* there must exist extent to be tailgated */ - if ((rc = xtSearch(ip, xoff, &cmp, &btstack, XT_INSERT))) + if ((rc = xtSearch(ip, xoff, NULL, &cmp, &btstack, XT_INSERT))) return rc; /* retrieve search result */ @@ -1821,8 +1877,6 @@ printf("xtTailgate: xoff:0x%lx xlen:0x%x xaddr:0x%lx\n", * The xtSplitUp() will insert the entry and unpin the leaf page. */ if (nextindex == le16_to_cpu(p->header.maxentry)) { - rootsplit = p->header.flag & BT_ROOT; - /* xtSpliUp() unpins leaf pages */ split.mp = mp; split.index = index + 1; @@ -1834,16 +1888,21 @@ printf("xtTailgate: xoff:0x%lx xlen:0x%x xaddr:0x%lx\n", if ((rc = xtSplitUp(tid, ip, &split, &btstack))) return rc; + /* get back old page */ + XT_GETPAGE(ip, bn, mp, PSIZE, p, rc); + if (rc) + return rc; /* * if leaf root has been split, original root has been * copied to new child page, i.e., original entry now * resides on the new child page; */ - if (rootsplit) { + if (p->header.flag & BT_INTERNAL) { ASSERT(p->header.nextindex == cpu_to_le16(XTENTRYSTART + 1)); xad = &p->xad[XTENTRYSTART]; bn = addressXAD(xad); + XT_PUTPAGE(mp); /* get new child page */ XT_GETPAGE(ip, bn, mp, PSIZE, p, rc); @@ -1855,11 +1914,6 @@ printf("xtTailgate: xoff:0x%lx xlen:0x%x xaddr:0x%lx\n", tlck = txLock(tid, ip, mp, tlckXTREE|tlckGROW); xtlck = (struct xtlock *) & tlck->lock; } - } else { - /* get back old page */ - XT_GETPAGE(ip, bn, mp, PSIZE, p, rc); - if (rc) - return rc; } } /* @@ -1949,14 +2003,14 @@ int xtUpdate(tid_t tid, struct inode *ip, xad_t * nxad) s64 nxaddr, xaddr; struct tlock *tlck; struct xtlock *xtlck = NULL; - int rootsplit = 0, newpage = 0; + int newpage = 0; /* there must exist extent to be tailgated */ nxoff = offsetXAD(nxad); nxlen = lengthXAD(nxad); nxaddr = addressXAD(nxad); - if ((rc = xtSearch(ip, nxoff, &cmp, &btstack, XT_INSERT))) + if ((rc = xtSearch(ip, nxoff, NULL, &cmp, &btstack, XT_INSERT))) return rc; /* retrieve search result */ @@ -2156,7 +2210,6 @@ int xtUpdate(tid_t tid, struct inode *ip, xad_t * nxad) /* insert nXAD:recorded */ if (nextindex == le16_to_cpu(p->header.maxentry)) { - rootsplit = p->header.flag & BT_ROOT; /* xtSpliUp() unpins leaf pages */ split.mp = mp; @@ -2169,16 +2222,21 @@ int xtUpdate(tid_t tid, struct inode *ip, xad_t * nxad) if ((rc = xtSplitUp(tid, ip, &split, &btstack))) return rc; + /* get back old page */ + XT_GETPAGE(ip, bn, mp, PSIZE, p, rc); + if (rc) + return rc; /* * if leaf root has been split, original root has been * copied to new child page, i.e., original entry now * resides on the new child page; */ - if (rootsplit) { + if (p->header.flag & BT_INTERNAL) { ASSERT(p->header.nextindex == cpu_to_le16(XTENTRYSTART + 1)); xad = &p->xad[XTENTRYSTART]; bn = addressXAD(xad); + XT_PUTPAGE(mp); /* get new child page */ XT_GETPAGE(ip, bn, mp, PSIZE, p, rc); @@ -2191,11 +2249,6 @@ int xtUpdate(tid_t tid, struct inode *ip, xad_t * nxad) xtlck = (struct xtlock *) & tlck->lock; } } else { - /* get back old page */ - XT_GETPAGE(ip, bn, mp, PSIZE, p, rc); - if (rc) - return rc; - /* is nXAD on new page ? */ if (newindex > (le16_to_cpu(p->header.maxentry) >> 1)) { @@ -2271,7 +2324,7 @@ int xtUpdate(tid_t tid, struct inode *ip, xad_t * nxad) if (nextindex == le16_to_cpu(p->header.maxentry)) { XT_PUTPAGE(mp); - if ((rc = xtSearch(ip, nxoff, &cmp, &btstack, XT_INSERT))) + if ((rc = xtSearch(ip, nxoff, NULL, &cmp, &btstack, XT_INSERT))) return rc; /* retrieve search result */ @@ -2309,8 +2362,6 @@ int xtUpdate(tid_t tid, struct inode *ip, xad_t * nxad) xlen = xlen - nxlen; xaddr = xaddr + nxlen; if (nextindex == le16_to_cpu(p->header.maxentry)) { - rootsplit = p->header.flag & BT_ROOT; - /* printf("xtUpdate.updateLeft.split p:0x%p\n", p); */ @@ -2325,16 +2376,22 @@ printf("xtUpdate.updateLeft.split p:0x%p\n", p); if ((rc = xtSplitUp(tid, ip, &split, &btstack))) return rc; + /* get back old page */ + XT_GETPAGE(ip, bn, mp, PSIZE, p, rc); + if (rc) + return rc; + /* * if leaf root has been split, original root has been * copied to new child page, i.e., original entry now * resides on the new child page; */ - if (rootsplit) { + if (p->header.flag & BT_INTERNAL) { ASSERT(p->header.nextindex == cpu_to_le16(XTENTRYSTART + 1)); xad = &p->xad[XTENTRYSTART]; bn = addressXAD(xad); + XT_PUTPAGE(mp); /* get new child page */ XT_GETPAGE(ip, bn, mp, PSIZE, p, rc); @@ -2346,11 +2403,6 @@ printf("xtUpdate.updateLeft.split p:0x%p\n", p); tlck = txLock(tid, ip, mp, tlckXTREE|tlckGROW); xtlck = (struct xtlock *) & tlck->lock; } - } else { - /* get back old page */ - XT_GETPAGE(ip, bn, mp, PSIZE, p, rc); - if (rc) - return rc; } } else { /* if insert into middle, shift right remaining entries */ @@ -2400,7 +2452,7 @@ printf("xtUpdate.updateLeft.split p:0x%p\n", p); * return: */ int xtAppend(tid_t tid, /* transaction id */ - struct inode *ip, int xflag, s64 xoff, s32 maxblocks, + struct inode *ip, int xflag, s64 xoff, s32 maxblocks, s32 * xlenp, /* (in/out) */ s64 * xaddrp, /* (in/out) */ int flag) @@ -2419,6 +2471,7 @@ int xtAppend(tid_t tid, /* transaction id */ int nsplit, nblocks, xlen; struct pxdlist pxdlist; pxd_t *pxd; + s64 next; xaddr = *xaddrp; xlen = *xlenp; @@ -2433,7 +2486,7 @@ int xtAppend(tid_t tid, /* transaction id */ * n.b. xtSearch() may return index of maxentry of * the full page. */ - if ((rc = xtSearch(ip, xoff, &cmp, &btstack, XT_INSERT))) + if ((rc = xtSearch(ip, xoff, &next, &cmp, &btstack, XT_INSERT))) return rc; /* retrieve search result */ @@ -2443,6 +2496,9 @@ int xtAppend(tid_t tid, /* transaction id */ rc = -EEXIST; goto out; } + + if (next) + xlen = min(xlen, (int)(next - xoff)); //insert: /* * insert entry for new extent @@ -2467,7 +2523,7 @@ int xtAppend(tid_t tid, /* transaction id */ pxdlist.maxnpxd = pxdlist.npxd = 0; pxd = &pxdlist.pxd[0]; nblocks = JFS_SBI(ip->i_sb)->nbperpage; - for (; nsplit > 0; nsplit--, pxd++, xaddr += nblocks, maxblocks -= nblocks) { + for (; nsplit > 0; nsplit--, pxd++, xaddr += nblocks, maxblocks -= nblocks) { if ((rc = dbAllocBottomUp(ip, xaddr, (s64) nblocks)) == 0) { PXDaddress(pxd, xaddr); PXDlength(pxd, nblocks); @@ -2482,7 +2538,7 @@ int xtAppend(tid_t tid, /* transaction id */ goto out; } - xlen = min(xlen, maxblocks); + xlen = min(xlen, maxblocks); /* * allocate data extent requested @@ -2581,7 +2637,7 @@ int xtDelete(tid_t tid, struct inode *ip, s64 xoff, s32 xlen, int flag) /* * find the matching entry; xtSearch() pins the page */ - if ((rc = xtSearch(ip, xoff, &cmp, &btstack, 0))) + if ((rc = xtSearch(ip, xoff, NULL, &cmp, &btstack, 0))) return rc; XT_GETSEARCH(ip, btstack.top, bn, mp, p, index); @@ -2833,7 +2889,7 @@ xtRelocate(tid_t tid, struct inode * ip, xad_t * oxad, /* old XAD */ */ if (xtype == DATAEXT) { /* search in leaf entry */ - rc = xtSearch(ip, xoff, &cmp, &btstack, 0); + rc = xtSearch(ip, xoff, NULL, &cmp, &btstack, 0); if (rc) return rc; @@ -2932,14 +2988,14 @@ xtRelocate(tid_t tid, struct inode * ip, xad_t * oxad, /* old XAD */ cmSetXD(ip, cp, pno, dxaddr, nblks); /* release the cbuf, mark it as modified */ - cmPut(cp, TRUE); + cmPut(cp, true); dxaddr += nblks; sxaddr += nblks; } /* get back parent page */ - if ((rc = xtSearch(ip, xoff, &cmp, &btstack, 0))) + if ((rc = xtSearch(ip, xoff, NULL, &cmp, &btstack, 0))) return rc; XT_GETSEARCH(ip, btstack.top, bn, pmp, pp, index); @@ -3484,16 +3540,10 @@ s64 xtTruncate(tid_t tid, struct inode *ip, s64 newsize, int flag) /* process entries backward from last index */ index = le16_to_cpu(p->header.nextindex) - 1; - if (p->header.flag & BT_INTERNAL) - goto getChild; - - /* - * leaf page - */ - /* Since this is the rightmost leaf, and we may have already freed - * a page that was formerly to the right, let's make sure that the - * next pointer is zero. + /* Since this is the rightmost page at this level, and we may have + * already freed a page that was formerly to the right, let's make + * sure that the next pointer is zero. */ if (p->header.next) { if (log) @@ -3507,6 +3557,12 @@ s64 xtTruncate(tid_t tid, struct inode *ip, s64 newsize, int flag) p->header.next = 0; } + if (p->header.flag & BT_INTERNAL) + goto getChild; + + /* + * leaf page + */ freed = 0; /* does region covered by leaf page precede Teof ? */ @@ -3909,8 +3965,10 @@ s64 xtTruncate(tid_t tid, struct inode *ip, s64 newsize, int flag) else ip->i_size = newsize; - /* update nblocks to reflect freed blocks */ - ip->i_blocks -= LBLK2PBLK(ip->i_sb, nfreed); + /* update dlimit allocation to reflect freed blocks */ + DLIMIT_FREE_BLOCK(ip, nfreed); + /* update quota allocation to reflect freed blocks */ + DQUOT_FREE_BLOCK(ip, nfreed); /* * free tlock of invalidated pages @@ -3972,7 +4030,7 @@ s64 xtTruncate_pmap(tid_t tid, struct inode *ip, s64 committed_size) if (committed_size) { xoff = (committed_size >> JFS_SBI(ip->i_sb)->l2bsize) - 1; - rc = xtSearch(ip, xoff, &cmp, &btstack, 0); + rc = xtSearch(ip, xoff, NULL, &cmp, &btstack, 0); if (rc) return rc; @@ -4100,338 +4158,6 @@ s64 xtTruncate_pmap(tid_t tid, struct inode *ip, s64 committed_size) return 0; } - -#ifdef _JFS_DEBUG_XTREE -/* - * xtDisplayTree() - * - * function: traverse forward - */ -int xtDisplayTree(struct inode *ip) -{ - int rc = 0; - struct metapage *mp; - xtpage_t *p; - s64 bn, pbn; - int index, lastindex, v, h; - xad_t *xad; - struct btstack btstack; - struct btframe *btsp; - struct btframe *parent; - - printk("display B+-tree.\n"); - - /* clear stack */ - btsp = btstack.stack; - - /* - * start with root - * - * root resides in the inode - */ - bn = 0; - v = h = 0; - - /* - * first access of each page: - */ - getPage: - XT_GETPAGE(ip, bn, mp, PSIZE, p, rc); - if (rc) - return rc; - - /* process entries forward from first index */ - index = XTENTRYSTART; - lastindex = le16_to_cpu(p->header.nextindex) - 1; - - if (p->header.flag & BT_INTERNAL) { - /* - * first access of each internal page - */ - goto getChild; - } else { /* (p->header.flag & BT_LEAF) */ - - /* - * first access of each leaf page - */ - printf("leaf page "); - xtDisplayPage(ip, bn, p); - - /* unpin the leaf page */ - XT_PUTPAGE(mp); - } - - /* - * go back up to the parent page - */ - getParent: - /* pop/restore parent entry for the current child page */ - if ((parent = (btsp == btstack.stack ? NULL : --btsp)) == NULL) - /* current page must have been root */ - return; - - /* - * parent page scan completed - */ - if ((index = parent->index) == (lastindex = parent->lastindex)) { - /* go back up to the parent page */ - goto getParent; - } - - /* - * parent page has entries remaining - */ - /* get back the parent page */ - bn = parent->bn; - /* v = parent->level; */ - XT_GETPAGE(ip, bn, mp, PSIZE, p, rc); - if (rc) - return rc; - - /* get next parent entry */ - index++; - - /* - * internal page: go down to child page of current entry - */ - getChild: - /* push/save current parent entry for the child page */ - btsp->bn = pbn = bn; - btsp->index = index; - btsp->lastindex = lastindex; - /* btsp->level = v; */ - /* btsp->node = h; */ - ++btsp; - - /* get child page */ - xad = &p->xad[index]; - bn = addressXAD(xad); - - /* - * first access of each internal entry: - */ - /* release parent page */ - XT_PUTPAGE(mp); - - printk("traverse down 0x%lx[%d]->0x%lx\n", (ulong) pbn, index, - (ulong) bn); - v++; - h = index; - - /* process the child page */ - goto getPage; -} - - -/* - * xtDisplayPage() - * - * function: display page - */ -int xtDisplayPage(struct inode *ip, s64 bn, xtpage_t * p) -{ - int rc = 0; - xad_t *xad; - s64 xaddr, xoff; - int xlen, i, j; - - /* display page control */ - printf("bn:0x%lx flag:0x%x nextindex:%d\n", - (ulong) bn, p->header.flag, - le16_to_cpu(p->header.nextindex)); - - /* display entries */ - xad = &p->xad[XTENTRYSTART]; - for (i = XTENTRYSTART, j = 1; i < le16_to_cpu(p->header.nextindex); - i++, xad++, j++) { - xoff = offsetXAD(xad); - xaddr = addressXAD(xad); - xlen = lengthXAD(xad); - printf("\t[%d] 0x%lx:0x%lx(0x%x)", i, (ulong) xoff, - (ulong) xaddr, xlen); - - if (j == 4) { - printf("\n"); - j = 0; - } - } - - printf("\n"); -} -#endif /* _JFS_DEBUG_XTREE */ - - -#ifdef _JFS_WIP -/* - * xtGather() - * - * function: - * traverse for allocation acquiring tlock at commit time - * (vs at the time of update) logging backward top down - * - * note: - * problem - establishing that all new allocation have been - * processed both for append and random write in sparse file - * at the current entry at the current subtree root page - * - */ -int xtGather(btree_t *t) -{ - int rc = 0; - xtpage_t *p; - u64 bn; - int index; - btentry_t *e; - struct btstack btstack; - struct btsf *parent; - - /* clear stack */ - BT_CLR(&btstack); - - /* - * start with root - * - * root resides in the inode - */ - bn = 0; - XT_GETPAGE(ip, bn, mp, PSIZE, p, rc); - if (rc) - return rc; - - /* new root is NOT pointed by a new entry - if (p->header.flag & NEW) - allocate new page lock; - write a NEWPAGE log; - */ - - dopage: - /* - * first access of each page: - */ - /* process entries backward from last index */ - index = le16_to_cpu(p->header.nextindex) - 1; - - if (p->header.flag & BT_LEAF) { - /* - * first access of each leaf page - */ - /* process leaf page entries backward */ - for (; index >= XTENTRYSTART; index--) { - e = &p->xad[index]; - /* - * if newpage, log NEWPAGE. - * - if (e->flag & XAD_NEW) { - nfound =+ entry->length; - update current page lock for the entry; - newpage(entry); - * - * if moved, log move. - * - } else if (e->flag & XAD_MOVED) { - reset flag; - update current page lock for the entry; - } - */ - } - - /* unpin the leaf page */ - XT_PUTPAGE(mp); - - /* - * go back up to the parent page - */ - getParent: - /* restore parent entry for the current child page */ - if ((parent = BT_POP(&btstack)) == NULL) - /* current page must have been root */ - return 0; - - if ((index = parent->index) == XTENTRYSTART) { - /* - * parent page scan completed - */ - /* go back up to the parent page */ - goto getParent; - } else { - /* - * parent page has entries remaining - */ - /* get back the parent page */ - bn = parent->bn; - XT_GETPAGE(ip, bn, mp, PSIZE, p, rc); - if (rc) - return -EIO; - - /* first subroot page which - * covers all new allocated blocks - * itself not new/modified. - * (if modified from split of descendent, - * go down path of split page) - - if (nfound == nnew && - !(p->header.flag & (NEW | MOD))) - exit scan; - */ - - /* process parent page entries backward */ - index--; - } - } else { - /* - * first access of each internal page - */ - } - - /* - * internal page: go down to child page of current entry - */ - - /* save current parent entry for the child page */ - BT_PUSH(&btstack, bn, index); - - /* get current entry for the child page */ - e = &p->xad[index]; - - /* - * first access of each internal entry: - */ - /* - * if new entry, log btree_tnewentry. - * - if (e->flag & XAD_NEW) - update parent page lock for the entry; - */ - - /* release parent page */ - XT_PUTPAGE(mp); - - /* get child page */ - bn = e->bn; - XT_GETPAGE(ip, bn, mp, PSIZE, p, rc); - if (rc) - return rc; - - /* - * first access of each non-root page: - */ - /* - * if new, log btree_newpage. - * - if (p->header.flag & NEW) - allocate new page lock; - write a NEWPAGE log (next, prev); - */ - - /* process the child page */ - goto dopage; - - out: - return 0; -} -#endif /* _JFS_WIP */ - - #ifdef CONFIG_JFS_STATISTICS int jfs_xtstat_read(char *buffer, char **start, off_t offset, int length, int *eof, void *data)