Commit 135e21a5 authored by Dave Kleikamp's avatar Dave Kleikamp

JFS: Prevent hang in __lock_metapage

Remove the hold_metapage call from txLog to prevent a hang.
While investigating this one, I audited all functions that held
metapage locks and found several error paths that did not release
them correctly.  These are fixed as well.
parent db80df6e
...@@ -1526,6 +1526,7 @@ dbAllocAG(struct bmap * bmp, int agno, s64 nblocks, int l2nb, s64 * results) ...@@ -1526,6 +1526,7 @@ dbAllocAG(struct bmap * bmp, int agno, s64 nblocks, int l2nb, s64 * results)
if (n == 4) { if (n == 4) {
jfs_error(bmp->db_ipbmap->i_sb, jfs_error(bmp->db_ipbmap->i_sb,
"dbAllocAG: failed descending stree"); "dbAllocAG: failed descending stree");
release_metapage(mp);
return -EIO; return -EIO;
} }
} }
...@@ -3310,7 +3311,7 @@ int dbExtendFS(struct inode *ipbmap, s64 blkno, s64 nblocks) ...@@ -3310,7 +3311,7 @@ int dbExtendFS(struct inode *ipbmap, s64 blkno, s64 nblocks)
int i, i0 = TRUE, j, j0 = TRUE, k, n; int i, i0 = TRUE, j, j0 = TRUE, k, n;
s64 newsize; s64 newsize;
s64 p; s64 p;
struct metapage *mp, *l2mp, *l1mp, *l0mp; struct metapage *mp, *l2mp, *l1mp = NULL, *l0mp = NULL;
struct dmapctl *l2dcp, *l1dcp, *l0dcp; struct dmapctl *l2dcp, *l1dcp, *l0dcp;
struct dmap *dp; struct dmap *dp;
s8 *l0leaf, *l1leaf, *l2leaf; s8 *l0leaf, *l1leaf, *l2leaf;
...@@ -3513,6 +3514,7 @@ int dbExtendFS(struct inode *ipbmap, s64 blkno, s64 nblocks) ...@@ -3513,6 +3514,7 @@ int dbExtendFS(struct inode *ipbmap, s64 blkno, s64 nblocks)
*/ */
*l1leaf = dbInitDmapCtl(l0dcp, 0, ++i); *l1leaf = dbInitDmapCtl(l0dcp, 0, ++i);
write_metapage(l0mp); write_metapage(l0mp);
l0mp = NULL;
if (nblocks) if (nblocks)
l1leaf++; /* continue for next L0 */ l1leaf++; /* continue for next L0 */
...@@ -3536,6 +3538,7 @@ int dbExtendFS(struct inode *ipbmap, s64 blkno, s64 nblocks) ...@@ -3536,6 +3538,7 @@ int dbExtendFS(struct inode *ipbmap, s64 blkno, s64 nblocks)
*/ */
*l2leaf = dbInitDmapCtl(l1dcp, 1, ++j); *l2leaf = dbInitDmapCtl(l1dcp, 1, ++j);
write_metapage(l1mp); write_metapage(l1mp);
l1mp = NULL;
if (nblocks) if (nblocks)
l2leaf++; /* continue for next L1 */ l2leaf++; /* continue for next L1 */
...@@ -3554,17 +3557,20 @@ int dbExtendFS(struct inode *ipbmap, s64 blkno, s64 nblocks) ...@@ -3554,17 +3557,20 @@ int dbExtendFS(struct inode *ipbmap, s64 blkno, s64 nblocks)
jfs_error(ipbmap->i_sb, jfs_error(ipbmap->i_sb,
"dbExtendFS: function has not returned as expected"); "dbExtendFS: function has not returned as expected");
errout:
if (l0mp)
release_metapage(l0mp);
if (l1mp)
release_metapage(l1mp);
release_metapage(l2mp);
return -EIO; return -EIO;
/* /*
* finalize bmap control page * finalize bmap control page
*/ */
finalize: finalize:
return 0; return 0;
errout:
return -EIO;
} }
......
...@@ -1423,8 +1423,10 @@ static int dtSplitPage(tid_t tid, struct inode *ip, struct dtsplit * split, ...@@ -1423,8 +1423,10 @@ static int dtSplitPage(tid_t tid, struct inode *ip, struct dtsplit * split,
*/ */
if (nextbn != 0) { if (nextbn != 0) {
DT_GETPAGE(ip, nextbn, mp, PSIZE, p, rc); DT_GETPAGE(ip, nextbn, mp, PSIZE, p, rc);
if (rc) if (rc) {
discard_metapage(rmp);
return rc; return rc;
}
BT_MARK_DIRTY(mp, ip); BT_MARK_DIRTY(mp, ip);
/* /*
...@@ -2235,8 +2237,10 @@ static int dtDeleteUp(tid_t tid, struct inode *ip, ...@@ -2235,8 +2237,10 @@ static int dtDeleteUp(tid_t tid, struct inode *ip,
pxdlock->index = 1; pxdlock->index = 1;
/* update sibling pointers */ /* update sibling pointers */
if ((rc = dtRelink(tid, ip, fp))) if ((rc = dtRelink(tid, ip, fp))) {
BT_PUTPAGE(fmp);
return rc; return rc;
}
xlen = lengthPXD(&fp->header.self); xlen = lengthPXD(&fp->header.self);
ip->i_blocks -= LBLK2PBLK(ip->i_sb, xlen); ip->i_blocks -= LBLK2PBLK(ip->i_sb, xlen);
...@@ -2307,8 +2311,10 @@ static int dtDeleteUp(tid_t tid, struct inode *ip, ...@@ -2307,8 +2311,10 @@ static int dtDeleteUp(tid_t tid, struct inode *ip,
pxdlock->index = 1; pxdlock->index = 1;
/* update sibling pointers */ /* update sibling pointers */
if ((rc = dtRelink(tid, ip, p))) if ((rc = dtRelink(tid, ip, p))) {
DT_PUTPAGE(mp);
return rc; return rc;
}
xlen = lengthPXD(&p->header.self); xlen = lengthPXD(&p->header.self);
ip->i_blocks -= LBLK2PBLK(ip->i_sb, xlen); ip->i_blocks -= LBLK2PBLK(ip->i_sb, xlen);
...@@ -2621,8 +2627,10 @@ static int dtSearchNode(struct inode *ip, s64 lmxaddr, pxd_t * kpxd, ...@@ -2621,8 +2627,10 @@ static int dtSearchNode(struct inode *ip, s64 lmxaddr, pxd_t * kpxd,
/* /*
* descend down to leftmost child page * descend down to leftmost child page
*/ */
if (p->header.flag & BT_LEAF) if (p->header.flag & BT_LEAF) {
DT_PUTPAGE(mp);
return -ESTALE; return -ESTALE;
}
/* get the leftmost entry */ /* get the leftmost entry */
stbl = DT_GETSTBL(p); stbl = DT_GETSTBL(p);
......
...@@ -1546,6 +1546,7 @@ int diAlloc(struct inode *pip, boolean_t dir, struct inode *ip) ...@@ -1546,6 +1546,7 @@ int diAlloc(struct inode *pip, boolean_t dir, struct inode *ip)
0); 0);
if (rem >= INOSPEREXT) { if (rem >= INOSPEREXT) {
IREAD_UNLOCK(ipimap); IREAD_UNLOCK(ipimap);
release_metapage(mp);
AG_UNLOCK(imap, agno); AG_UNLOCK(imap, agno);
jfs_error(ip->i_sb, jfs_error(ip->i_sb,
"diAlloc: can't find free bit " "diAlloc: can't find free bit "
...@@ -1840,6 +1841,7 @@ static int diAllocIno(struct inomap * imap, int agno, struct inode *ip) ...@@ -1840,6 +1841,7 @@ static int diAllocIno(struct inomap * imap, int agno, struct inode *ip)
*/ */
if (!iagp->nfreeinos) { if (!iagp->nfreeinos) {
IREAD_UNLOCK(imap->im_ipimap); IREAD_UNLOCK(imap->im_ipimap);
release_metapage(mp);
jfs_error(ip->i_sb, jfs_error(ip->i_sb,
"diAllocIno: nfreeinos = 0, but iag on freelist"); "diAllocIno: nfreeinos = 0, but iag on freelist");
return -EIO; return -EIO;
...@@ -1851,6 +1853,7 @@ static int diAllocIno(struct inomap * imap, int agno, struct inode *ip) ...@@ -1851,6 +1853,7 @@ static int diAllocIno(struct inomap * imap, int agno, struct inode *ip)
for (sword = 0;; sword++) { for (sword = 0;; sword++) {
if (sword >= SMAPSZ) { if (sword >= SMAPSZ) {
IREAD_UNLOCK(imap->im_ipimap); IREAD_UNLOCK(imap->im_ipimap);
release_metapage(mp);
jfs_error(ip->i_sb, jfs_error(ip->i_sb,
"diAllocIno: free inode not found in summary map"); "diAllocIno: free inode not found in summary map");
return -EIO; return -EIO;
...@@ -1866,6 +1869,7 @@ static int diAllocIno(struct inomap * imap, int agno, struct inode *ip) ...@@ -1866,6 +1869,7 @@ static int diAllocIno(struct inomap * imap, int agno, struct inode *ip)
rem = diFindFree(le32_to_cpu(iagp->inosmap[sword]), 0); rem = diFindFree(le32_to_cpu(iagp->inosmap[sword]), 0);
if (rem >= EXTSPERSUM) { if (rem >= EXTSPERSUM) {
IREAD_UNLOCK(imap->im_ipimap); IREAD_UNLOCK(imap->im_ipimap);
release_metapage(mp);
jfs_error(ip->i_sb, "diAllocIno: no free extent found"); jfs_error(ip->i_sb, "diAllocIno: no free extent found");
return -EIO; return -EIO;
} }
...@@ -1876,6 +1880,7 @@ static int diAllocIno(struct inomap * imap, int agno, struct inode *ip) ...@@ -1876,6 +1880,7 @@ static int diAllocIno(struct inomap * imap, int agno, struct inode *ip)
rem = diFindFree(le32_to_cpu(iagp->wmap[extno]), 0); rem = diFindFree(le32_to_cpu(iagp->wmap[extno]), 0);
if (rem >= INOSPEREXT) { if (rem >= INOSPEREXT) {
IREAD_UNLOCK(imap->im_ipimap); IREAD_UNLOCK(imap->im_ipimap);
release_metapage(mp);
jfs_error(ip->i_sb, "diAllocIno: free inode not found"); jfs_error(ip->i_sb, "diAllocIno: free inode not found");
return -EIO; return -EIO;
} }
...@@ -2839,12 +2844,14 @@ diUpdatePMap(struct inode *ipimap, ...@@ -2839,12 +2844,14 @@ diUpdatePMap(struct inode *ipimap,
* and should be free in persistent map; * and should be free in persistent map;
*/ */
if (!(le32_to_cpu(iagp->wmap[extno]) & mask)) { if (!(le32_to_cpu(iagp->wmap[extno]) & mask)) {
release_metapage(mp);
jfs_error(ipimap->i_sb, jfs_error(ipimap->i_sb,
"diUpdatePMap: the inode is not allocated in " "diUpdatePMap: the inode is not allocated in "
"the working map"); "the working map");
return -EIO; return -EIO;
} }
if ((le32_to_cpu(iagp->pmap[extno]) & mask) != 0) { if ((le32_to_cpu(iagp->pmap[extno]) & mask) != 0) {
release_metapage(mp);
jfs_error(ipimap->i_sb, jfs_error(ipimap->i_sb,
"diUpdatePMap: the inode is not free in the " "diUpdatePMap: the inode is not free in the "
"persistent map"); "persistent map");
......
...@@ -1356,9 +1356,6 @@ static int txLog(struct jfs_log * log, struct tblock * tblk, struct commit * cd) ...@@ -1356,9 +1356,6 @@ static int txLog(struct jfs_log * log, struct tblock * tblk, struct commit * cd)
lrd->log.redopage.fileset = cpu_to_le32(JFS_IP(ip)->fileset); lrd->log.redopage.fileset = cpu_to_le32(JFS_IP(ip)->fileset);
lrd->log.redopage.inode = cpu_to_le32(ip->i_ino); lrd->log.redopage.inode = cpu_to_le32(ip->i_ino);
if (tlck->mp)
hold_metapage(tlck->mp, 0);
/* write log record of page from the tlock */ /* write log record of page from the tlock */
switch (tlck->type & tlckTYPE) { switch (tlck->type & tlckTYPE) {
case tlckXTREE: case tlckXTREE:
...@@ -1384,8 +1381,6 @@ static int txLog(struct jfs_log * log, struct tblock * tblk, struct commit * cd) ...@@ -1384,8 +1381,6 @@ static int txLog(struct jfs_log * log, struct tblock * tblk, struct commit * cd)
default: default:
jfs_err("UFO tlock:0x%p", tlck); jfs_err("UFO tlock:0x%p", tlck);
} }
if (tlck->mp)
release_metapage(tlck->mp);
} }
return rc; return rc;
...@@ -1535,6 +1530,7 @@ static int dataLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd, ...@@ -1535,6 +1530,7 @@ static int dataLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
* the last entry, so don't bother logging this * the last entry, so don't bother logging this
*/ */
mp->lid = 0; mp->lid = 0;
hold_metapage(mp, 0);
atomic_dec(&mp->nohomeok); atomic_dec(&mp->nohomeok);
discard_metapage(mp); discard_metapage(mp);
tlck->mp = 0; tlck->mp = 0;
......
...@@ -1032,11 +1032,11 @@ xtSplitUp(tid_t tid, ...@@ -1032,11 +1032,11 @@ xtSplitUp(tid_t tid,
rc = (sp->header.flag & BT_ROOT) ? rc = (sp->header.flag & BT_ROOT) ?
xtSplitRoot(tid, ip, split, &rmp) : xtSplitRoot(tid, ip, split, &rmp) :
xtSplitPage(tid, ip, split, &rmp, &rbn); xtSplitPage(tid, ip, split, &rmp, &rbn);
if (rc)
return -EIO;
XT_PUTPAGE(smp); XT_PUTPAGE(smp);
if (rc)
return -EIO;
/* /*
* propagate up the router entry for the leaf page just split * propagate up the router entry for the leaf page just split
* *
...@@ -1611,14 +1611,16 @@ int xtExtend(tid_t tid, /* transaction id */ ...@@ -1611,14 +1611,16 @@ int xtExtend(tid_t tid, /* transaction id */
/* there must exist extent to be extended */ /* there must exist extent to be extended */
if ((rc = xtSearch(ip, xoff - 1, &cmp, &btstack, XT_INSERT))) if ((rc = xtSearch(ip, xoff - 1, &cmp, &btstack, XT_INSERT)))
return rc; return rc;
/* retrieve search result */
XT_GETSEARCH(ip, btstack.top, bn, mp, p, index);
if (cmp != 0) { if (cmp != 0) {
XT_PUTPAGE(mp);
jfs_error(ip->i_sb, "xtExtend: xtSearch did not find extent"); jfs_error(ip->i_sb, "xtExtend: xtSearch did not find extent");
return -EIO; return -EIO;
} }
/* retrieve search result */
XT_GETSEARCH(ip, btstack.top, bn, mp, p, index);
/* extension must be contiguous */ /* extension must be contiguous */
xad = &p->xad[index]; xad = &p->xad[index];
if ((offsetXAD(xad) + lengthXAD(xad)) != xoff) { if ((offsetXAD(xad) + lengthXAD(xad)) != xoff) {
...@@ -1677,25 +1679,27 @@ int xtExtend(tid_t tid, /* transaction id */ ...@@ -1677,25 +1679,27 @@ int xtExtend(tid_t tid, /* transaction id */
* resides on the new child page; * resides on the new child page;
*/ */
if (rootsplit) { if (rootsplit) {
if (p->header.nextindex == ASSERT(p->header.nextindex ==
cpu_to_le16(XTENTRYSTART + 1)) { cpu_to_le16(XTENTRYSTART + 1));
xad = &p->xad[XTENTRYSTART]; xad = &p->xad[XTENTRYSTART];
bn = addressXAD(xad); bn = addressXAD(xad);
/* get new child page */ /* get new child page */
XT_GETPAGE(ip, bn, mp, PSIZE, p, rc); XT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
if (rc)
return rc;
BT_MARK_DIRTY(mp, ip); BT_MARK_DIRTY(mp, ip);
if (!test_cflag(COMMIT_Nolink, ip)) { if (!test_cflag(COMMIT_Nolink, ip)) {
tlck = txLock(tid, ip, mp, tlck = txLock(tid, ip, mp, tlckXTREE|tlckGROW);
tlckXTREE |
tlckGROW);
xtlck = (struct xtlock *) & tlck->lock; xtlck = (struct xtlock *) & tlck->lock;
} }
} } else {
} else
/* get back old page */ /* get back old page */
XT_GETPAGE(ip, bn, mp, PSIZE, p, rc); XT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
if (rc)
return rc;
}
} }
/* /*
* insert the new entry into the leaf page * insert the new entry into the leaf page
...@@ -1778,14 +1782,16 @@ printf("xtTailgate: nxoff:0x%lx nxlen:0x%x nxaddr:0x%lx\n", ...@@ -1778,14 +1782,16 @@ printf("xtTailgate: nxoff:0x%lx nxlen:0x%x nxaddr:0x%lx\n",
/* there must exist extent to be tailgated */ /* there must exist extent to be tailgated */
if ((rc = xtSearch(ip, xoff, &cmp, &btstack, XT_INSERT))) if ((rc = xtSearch(ip, xoff, &cmp, &btstack, XT_INSERT)))
return rc; return rc;
/* retrieve search result */
XT_GETSEARCH(ip, btstack.top, bn, mp, p, index);
if (cmp != 0) { if (cmp != 0) {
XT_PUTPAGE(mp);
jfs_error(ip->i_sb, "xtTailgate: couldn't find extent"); jfs_error(ip->i_sb, "xtTailgate: couldn't find extent");
return -EIO; return -EIO;
} }
/* retrieve search result */
XT_GETSEARCH(ip, btstack.top, bn, mp, p, index);
/* entry found must be last entry */ /* entry found must be last entry */
nextindex = le16_to_cpu(p->header.nextindex); nextindex = le16_to_cpu(p->header.nextindex);
if (index != nextindex - 1) { if (index != nextindex - 1) {
...@@ -1843,25 +1849,27 @@ printf("xtTailgate: xoff:0x%lx xlen:0x%x xaddr:0x%lx\n", ...@@ -1843,25 +1849,27 @@ printf("xtTailgate: xoff:0x%lx xlen:0x%x xaddr:0x%lx\n",
* resides on the new child page; * resides on the new child page;
*/ */
if (rootsplit) { if (rootsplit) {
if (p->header.nextindex == ASSERT(p->header.nextindex ==
cpu_to_le16(XTENTRYSTART + 1)) { cpu_to_le16(XTENTRYSTART + 1));
xad = &p->xad[XTENTRYSTART]; xad = &p->xad[XTENTRYSTART];
bn = addressXAD(xad); bn = addressXAD(xad);
/* get new child page */ /* get new child page */
XT_GETPAGE(ip, bn, mp, PSIZE, p, rc); XT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
if (rc)
return rc;
BT_MARK_DIRTY(mp, ip); BT_MARK_DIRTY(mp, ip);
if (!test_cflag(COMMIT_Nolink, ip)) { if (!test_cflag(COMMIT_Nolink, ip)) {
tlck = txLock(tid, ip, mp, tlck = txLock(tid, ip, mp, tlckXTREE|tlckGROW);
tlckXTREE |
tlckGROW);
xtlck = (struct xtlock *) & tlck->lock; xtlck = (struct xtlock *) & tlck->lock;
} }
} } else {
} else
/* get back old page */ /* get back old page */
XT_GETPAGE(ip, bn, mp, PSIZE, p, rc); XT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
if (rc)
return rc;
}
} }
/* /*
* insert the new entry into the leaf page * insert the new entry into the leaf page
...@@ -1960,14 +1968,15 @@ int xtUpdate(tid_t tid, struct inode *ip, xad_t * nxad) ...@@ -1960,14 +1968,15 @@ int xtUpdate(tid_t tid, struct inode *ip, xad_t * nxad)
if ((rc = xtSearch(ip, nxoff, &cmp, &btstack, XT_INSERT))) if ((rc = xtSearch(ip, nxoff, &cmp, &btstack, XT_INSERT)))
return rc; return rc;
/* retrieve search result */
XT_GETSEARCH(ip, btstack.top, bn, mp, p, index0);
if (cmp != 0) { if (cmp != 0) {
XT_PUTPAGE(mp);
jfs_error(ip->i_sb, "xtUpdate: Could not find extent"); jfs_error(ip->i_sb, "xtUpdate: Could not find extent");
return -EIO; return -EIO;
} }
/* retrieve search result */
XT_GETSEARCH(ip, btstack.top, bn, mp, p, index0);
BT_MARK_DIRTY(mp, ip); BT_MARK_DIRTY(mp, ip);
/* /*
* acquire tlock of the leaf page containing original entry * acquire tlock of the leaf page containing original entry
...@@ -2175,25 +2184,26 @@ int xtUpdate(tid_t tid, struct inode *ip, xad_t * nxad) ...@@ -2175,25 +2184,26 @@ int xtUpdate(tid_t tid, struct inode *ip, xad_t * nxad)
* resides on the new child page; * resides on the new child page;
*/ */
if (rootsplit) { if (rootsplit) {
if (p->header.nextindex == ASSERT(p->header.nextindex ==
cpu_to_le16(XTENTRYSTART + 1)) { cpu_to_le16(XTENTRYSTART + 1));
xad = &p->xad[XTENTRYSTART]; xad = &p->xad[XTENTRYSTART];
bn = addressXAD(xad); bn = addressXAD(xad);
/* get new child page */ /* get new child page */
XT_GETPAGE(ip, bn, mp, PSIZE, p, rc); XT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
if (rc)
return rc;
BT_MARK_DIRTY(mp, ip); BT_MARK_DIRTY(mp, ip);
if (!test_cflag(COMMIT_Nolink, ip)) { if (!test_cflag(COMMIT_Nolink, ip)) {
tlck = txLock(tid, ip, mp, tlck = txLock(tid, ip, mp, tlckXTREE|tlckGROW);
tlckXTREE |
tlckGROW);
xtlck = (struct xtlock *) & tlck->lock; xtlck = (struct xtlock *) & tlck->lock;
} }
}
} else { } else {
/* get back old page */ /* get back old page */
XT_GETPAGE(ip, bn, mp, PSIZE, p, rc); XT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
if (rc)
return rc;
/* is nXAD on new page ? */ /* is nXAD on new page ? */
if (newindex > if (newindex >
...@@ -2247,6 +2257,8 @@ int xtUpdate(tid_t tid, struct inode *ip, xad_t * nxad) ...@@ -2247,6 +2257,8 @@ int xtUpdate(tid_t tid, struct inode *ip, xad_t * nxad)
/* get new right page */ /* get new right page */
XT_GETPAGE(ip, bn, mp, PSIZE, p, rc); XT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
if (rc)
return rc;
BT_MARK_DIRTY(mp, ip); BT_MARK_DIRTY(mp, ip);
if (!test_cflag(COMMIT_Nolink, ip)) { if (!test_cflag(COMMIT_Nolink, ip)) {
...@@ -2270,13 +2282,16 @@ int xtUpdate(tid_t tid, struct inode *ip, xad_t * nxad) ...@@ -2270,13 +2282,16 @@ int xtUpdate(tid_t tid, struct inode *ip, xad_t * nxad)
if ((rc = xtSearch(ip, nxoff, &cmp, &btstack, XT_INSERT))) if ((rc = xtSearch(ip, nxoff, &cmp, &btstack, XT_INSERT)))
return rc; return rc;
/* retrieve search result */
XT_GETSEARCH(ip, btstack.top, bn, mp, p, index0);
if (cmp != 0) { if (cmp != 0) {
XT_PUTPAGE(mp);
jfs_error(ip->i_sb, "xtUpdate: xtSearch failed"); jfs_error(ip->i_sb, "xtUpdate: xtSearch failed");
return -EIO; return -EIO;
} }
/* retrieve search result */
XT_GETSEARCH(ip, btstack.top, bn, mp, p, index0);
if (index0 != index) { if (index0 != index) {
XT_PUTPAGE(mp); XT_PUTPAGE(mp);
jfs_error(ip->i_sb, jfs_error(ip->i_sb,
...@@ -2325,25 +2340,27 @@ printf("xtUpdate.updateLeft.split p:0x%p\n", p); ...@@ -2325,25 +2340,27 @@ printf("xtUpdate.updateLeft.split p:0x%p\n", p);
* resides on the new child page; * resides on the new child page;
*/ */
if (rootsplit) { if (rootsplit) {
if (p->header.nextindex == ASSERT(p->header.nextindex ==
cpu_to_le16(XTENTRYSTART + 1)) { cpu_to_le16(XTENTRYSTART + 1));
xad = &p->xad[XTENTRYSTART]; xad = &p->xad[XTENTRYSTART];
bn = addressXAD(xad); bn = addressXAD(xad);
/* get new child page */ /* get new child page */
XT_GETPAGE(ip, bn, mp, PSIZE, p, rc); XT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
if (rc)
return rc;
BT_MARK_DIRTY(mp, ip); BT_MARK_DIRTY(mp, ip);
if (!test_cflag(COMMIT_Nolink, ip)) { if (!test_cflag(COMMIT_Nolink, ip)) {
tlck = txLock(tid, ip, mp, tlck = txLock(tid, ip, mp, tlckXTREE|tlckGROW);
tlckXTREE |
tlckGROW);
xtlck = (struct xtlock *) & tlck->lock; xtlck = (struct xtlock *) & tlck->lock;
} }
} } else {
} else
/* get back old page */ /* get back old page */
XT_GETPAGE(ip, bn, mp, PSIZE, p, rc); XT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
if (rc)
return rc;
}
} else { } else {
/* if insert into middle, shift right remaining entries */ /* if insert into middle, shift right remaining entries */
if (newindex < nextindex) if (newindex < nextindex)
...@@ -2660,8 +2677,10 @@ xtDeleteUp(tid_t tid, struct inode *ip, ...@@ -2660,8 +2677,10 @@ xtDeleteUp(tid_t tid, struct inode *ip,
/* /*
* free non-root leaf page * free non-root leaf page
*/ */
if ((rc = xtRelink(tid, ip, fp))) if ((rc = xtRelink(tid, ip, fp))) {
XT_PUTPAGE(fmp);
return rc; return rc;
}
xaddr = addressPXD(&fp->header.self); xaddr = addressPXD(&fp->header.self);
xlen = lengthPXD(&fp->header.self); xlen = lengthPXD(&fp->header.self);
...@@ -2703,7 +2722,7 @@ xtDeleteUp(tid_t tid, struct inode *ip, ...@@ -2703,7 +2722,7 @@ xtDeleteUp(tid_t tid, struct inode *ip,
p->header.nextindex = p->header.nextindex =
cpu_to_le16(XTENTRYSTART); cpu_to_le16(XTENTRYSTART);
/* XT_PUTPAGE(fmp); */ /* XT_PUTPAGE(mp); */
break; break;
} else { } else {
...@@ -2717,7 +2736,7 @@ xtDeleteUp(tid_t tid, struct inode *ip, ...@@ -2717,7 +2736,7 @@ xtDeleteUp(tid_t tid, struct inode *ip,
(s64) JFS_SBI(ip->i_sb)->nbperpage); (s64) JFS_SBI(ip->i_sb)->nbperpage);
/* unpin/free the buffer page */ /* unpin/free the buffer page */
discard_metapage(fmp); discard_metapage(mp);
/* propagate up */ /* propagate up */
continue; continue;
...@@ -2826,14 +2845,15 @@ xtRelocate(tid_t tid, struct inode * ip, xad_t * oxad, /* old XAD */ ...@@ -2826,14 +2845,15 @@ xtRelocate(tid_t tid, struct inode * ip, xad_t * oxad, /* old XAD */
rc = xtSearch(ip, xoff, &cmp, &btstack, 0); rc = xtSearch(ip, xoff, &cmp, &btstack, 0);
if (rc) if (rc)
return rc; return rc;
/* retrieve search result */
XT_GETSEARCH(ip, btstack.top, bn, pmp, pp, index);
if (cmp) { if (cmp) {
XT_PUTPAGE(pmp); XT_PUTPAGE(pmp);
return -ESTALE; return -ESTALE;
} }
/* retrieve search result */
XT_GETSEARCH(ip, btstack.top, bn, pmp, pp, index);
/* validate for exact match with a single entry */ /* validate for exact match with a single entry */
xad = &pp->xad[index]; xad = &pp->xad[index];
if (addressXAD(xad) != oxaddr || lengthXAD(xad) != xlen) { if (addressXAD(xad) != oxaddr || lengthXAD(xad) != xlen) {
...@@ -2846,14 +2866,15 @@ xtRelocate(tid_t tid, struct inode * ip, xad_t * oxad, /* old XAD */ ...@@ -2846,14 +2866,15 @@ xtRelocate(tid_t tid, struct inode * ip, xad_t * oxad, /* old XAD */
rc = xtSearchNode(ip, oxad, &cmp, &btstack, 0); rc = xtSearchNode(ip, oxad, &cmp, &btstack, 0);
if (rc) if (rc)
return rc; return rc;
/* retrieve search result */
XT_GETSEARCH(ip, btstack.top, bn, pmp, pp, index);
if (cmp) { if (cmp) {
XT_PUTPAGE(pmp); XT_PUTPAGE(pmp);
return -ESTALE; return -ESTALE;
} }
/* retrieve search result */
XT_GETSEARCH(ip, btstack.top, bn, pmp, pp, index);
/* xtSearchNode() validated for exact match with a single entry /* xtSearchNode() validated for exact match with a single entry
*/ */
xad = &pp->xad[index]; xad = &pp->xad[index];
...@@ -2927,7 +2948,9 @@ xtRelocate(tid_t tid, struct inode * ip, xad_t * oxad, /* old XAD */ ...@@ -2927,7 +2948,9 @@ xtRelocate(tid_t tid, struct inode * ip, xad_t * oxad, /* old XAD */
} }
/* get back parent page */ /* get back parent page */
rc = xtSearch(ip, xoff, &cmp, &btstack, 0); if ((rc = xtSearch(ip, xoff, &cmp, &btstack, 0)))
return rc;
XT_GETSEARCH(ip, btstack.top, bn, pmp, pp, index); XT_GETSEARCH(ip, btstack.top, bn, pmp, pp, index);
jfs_info("xtRelocate: target data extent relocated."); jfs_info("xtRelocate: target data extent relocated.");
} else { /* (xtype == XTPAGE) */ } else { /* (xtype == XTPAGE) */
...@@ -3150,8 +3173,10 @@ static int xtSearchNode(struct inode *ip, xad_t * xad, /* required XAD entry */ ...@@ -3150,8 +3173,10 @@ static int xtSearchNode(struct inode *ip, xad_t * xad, /* required XAD entry */
XT_GETPAGE(ip, bn, mp, PSIZE, p, rc); XT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
if (rc) if (rc)
return rc; return rc;
if (p->header.flag & BT_LEAF) if (p->header.flag & BT_LEAF) {
XT_PUTPAGE(mp);
return -ESTALE; return -ESTALE;
}
lim = le16_to_cpu(p->header.nextindex) - XTENTRYSTART; lim = le16_to_cpu(p->header.nextindex) - XTENTRYSTART;
...@@ -3949,12 +3974,15 @@ s64 xtTruncate_pmap(tid_t tid, struct inode *ip, s64 committed_size) ...@@ -3949,12 +3974,15 @@ s64 xtTruncate_pmap(tid_t tid, struct inode *ip, s64 committed_size)
rc = xtSearch(ip, xoff, &cmp, &btstack, 0); rc = xtSearch(ip, xoff, &cmp, &btstack, 0);
if (rc) if (rc)
return rc; return rc;
XT_GETSEARCH(ip, btstack.top, bn, mp, p, index);
if (cmp != 0) { if (cmp != 0) {
XT_PUTPAGE(mp);
jfs_error(ip->i_sb, jfs_error(ip->i_sb,
"xtTruncate_pmap: did not find extent"); "xtTruncate_pmap: did not find extent");
return -EIO; return -EIO;
} }
XT_GETSEARCH(ip, btstack.top, bn, mp, p, index);
} else { } else {
/* /*
* start with root * start with root
...@@ -4202,17 +4230,10 @@ int xtDisplayTree(struct inode *ip) ...@@ -4202,17 +4230,10 @@ int xtDisplayTree(struct inode *ip)
int xtDisplayPage(struct inode *ip, s64 bn, xtpage_t * p) int xtDisplayPage(struct inode *ip, s64 bn, xtpage_t * p)
{ {
int rc = 0; int rc = 0;
struct metapage *mp;
xad_t *xad; xad_t *xad;
s64 xaddr, xoff; s64 xaddr, xoff;
int xlen, i, j; int xlen, i, j;
if (p == NULL) {
XT_GETPAGE(ip, bn, mp, PSIZE, p, rc);
if (rc)
return rc;
}
/* display page control */ /* display page control */
printf("bn:0x%lx flag:0x%x nextindex:%d\n", printf("bn:0x%lx flag:0x%x nextindex:%d\n",
(ulong) bn, p->header.flag, (ulong) bn, p->header.flag,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment