diff --git a/fs/jfs/jfs_dmap.c b/fs/jfs/jfs_dmap.c index 88afd108c2dd..63d23ad06e05 100644 --- a/fs/jfs/jfs_dmap.c +++ b/fs/jfs/jfs_dmap.c @@ -61,9 +61,9 @@ /* * forward references */ -static void dbAllocBits(struct bmap * bmp, struct dmap * dp, s64 blkno, +static int dbAllocBits(struct bmap * bmp, struct dmap * dp, s64 blkno, int nblocks); -static void dbSplit(dmtree_t * tp, int leafno, int splitsz, int newval); +static int dbSplit(dmtree_t * tp, int leafno, int splitsz, int newval); static int dbBackSplit(dmtree_t * tp, int leafno); static int dbJoin(dmtree_t * tp, int leafno, int newval); static void dbAdjTree(dmtree_t * tp, int leafno, int newval); @@ -2022,7 +2022,9 @@ static int dbAllocDmap(struct bmap * bmp, struct dmap * dp, s64 blkno, oldroot = dp->tree.stree[ROOT]; /* allocate the specified (blocks) bits */ - dbAllocBits(bmp, dp, blkno, nblocks); + rc = dbAllocBits(bmp, dp, blkno, nblocks); + if (rc) + return rc; /* if the root has not changed, done. */ if (dp->tree.stree[ROOT] == oldroot) @@ -2098,7 +2100,7 @@ static int dbFreeDmap(struct bmap * bmp, struct dmap * dp, s64 blkno, if (dp->tree.stree[word] == NOFREE) dbBackSplit((dmtree_t *) & dp->tree, word); - dbAllocBits(bmp, dp, blkno, nblocks); + rc = dbAllocBits(bmp, dp, blkno, nblocks); } return (rc); @@ -2123,14 +2125,15 @@ static int dbFreeDmap(struct bmap * bmp, struct dmap * dp, s64 blkno, * blkno - starting block number of the bits to be allocated. * nblocks - number of bits to be allocated. * - * RETURN VALUES: none - * + * RETURN VALUES: + * 0 - success + * -EIO - i/o error * * serialization: IREAD_LOCK(ipbmap) or IWRITE_LOCK(ipbmap) held on entry/exit; */ -static void dbAllocBits(struct bmap * bmp, struct dmap * dp, s64 blkno, +static int dbAllocBits(struct bmap * bmp, struct dmap * dp, s64 blkno, int nblocks) { - int dbitno, word, rembits, nb, nwords, wbitno, nw, agno; + int dbitno, word, rembits, nb, nwords, wbitno, nw, agno, rc; dmtree_t *tp = (dmtree_t *) & dp->tree; int size; s8 *leaf; @@ -2181,9 +2184,10 @@ static void dbAllocBits(struct bmap * bmp, struct dmap * dp, s64 blkno, * of the updated dmap word, dbSplit() will split * the binary system of the leaves if need be. */ - dbSplit(tp, word, BUDMIN, + rc = dbSplit(tp, word, BUDMIN, dbMaxBud((u8 *) & dp->wmap[word])); - + if (rc) + return rc; word += 1; } else { /* one or more dmap words are fully contained @@ -2222,8 +2226,9 @@ static void dbAllocBits(struct bmap * bmp, struct dmap * dp, s64 blkno, * system of the leaves to reflect the current * allocation (size). */ - dbSplit(tp, word, size, NOFREE); - + rc = dbSplit(tp, word, size, NOFREE); + if (rc) + return rc; /* get the number of dmap words handled */ nw = BUDSIZE(size, BUDMIN); word += nw; @@ -2249,6 +2254,8 @@ static void dbAllocBits(struct bmap * bmp, struct dmap * dp, s64 blkno, bmp->db_nfree -= nblocks; BMAP_UNLOCK(bmp); + + return 0; } @@ -2521,7 +2528,11 @@ dbAdjCtl(struct bmap * bmp, s64 blkno, int newval, int alloc, int level) } oldval = dcp->stree[ti]; } - dbSplit((dmtree_t *) dcp, leafno, dcp->budmin, newval); + rc = dbSplit((dmtree_t *) dcp, leafno, dcp->budmin, newval); + if (rc) { + release_metapage(mp); + return rc; + } } else { rc = dbJoin((dmtree_t *) dcp, leafno, newval); if (rc) { @@ -2565,7 +2576,7 @@ dbAdjCtl(struct bmap * bmp, s64 blkno, int newval, int alloc, int level) if (dcp->stree[ti] == NOFREE) dbBackSplit((dmtree_t *) dcp, leafno); - dbSplit((dmtree_t *) dcp, leafno, + rc = dbSplit((dmtree_t *) dcp, leafno, dcp->budmin, oldval); } @@ -2610,11 +2621,13 @@ dbAdjCtl(struct bmap * bmp, s64 blkno, int newval, int alloc, int level) * must be split to, specified as the log2 number of blocks. * newval - the new value for the leaf. * - * RETURN VALUES: none + * RETURN VALUES: + * 0 - success + * -EIO - i/o error * * serialization: IREAD_LOCK(ipbmap) or IWRITE_LOCK(ipbmap) held on entry/exit; */ -static void dbSplit(dmtree_t * tp, int leafno, int splitsz, int newval) +static int dbSplit(dmtree_t * tp, int leafno, int splitsz, int newval) { int budsz; int cursz; @@ -2629,6 +2642,8 @@ static void dbSplit(dmtree_t * tp, int leafno, int splitsz, int newval) * - 1 in l2) and the corresponding buddy size. */ cursz = leaf[leafno] - 1; + if ((cursz - tp->dmt_budmin) > BUDMIN) + return -EIO; budsz = BUDSIZE(cursz, tp->dmt_budmin); /* split until we reach the specified size. @@ -2649,6 +2664,7 @@ static void dbSplit(dmtree_t * tp, int leafno, int splitsz, int newval) * value. */ dbAdjTree(tp, leafno, newval); + return 0; } @@ -2675,13 +2691,15 @@ static void dbSplit(dmtree_t * tp, int leafno, int splitsz, int newval) * tp - pointer to the tree containing the leaf. * leafno - the number of the leaf to be updated. * - * RETURN VALUES: none + * RETURN VALUES: + * 0 - success + * -EIO - i/o error * * serialization: IREAD_LOCK(ipbmap) or IWRITE_LOCK(ipbmap) held on entry/exit; */ static int dbBackSplit(dmtree_t * tp, int leafno) { - int budsz, bud, w, bsz, size; + int budsz, bud, w, bsz, size, rc; int cursz; s8 *leaf = tp->dmt_stree + le32_to_cpu(tp->dmt_leafidx); @@ -2716,7 +2734,8 @@ static int dbBackSplit(dmtree_t * tp, int leafno) w = (w < bud) ? w : bud) { if (bsz >= le32_to_cpu(tp->dmt_nleafs)) { jfs_err("JFS: block map error in dbBackSplit"); - return -EIO; + rc = -EIO; + goto out; } /* determine the buddy. @@ -2730,17 +2749,22 @@ static int dbBackSplit(dmtree_t * tp, int leafno) * system in two. */ cursz = leaf[bud] - 1; - dbSplit(tp, bud, cursz, cursz); - break; + rc = dbSplit(tp, bud, cursz, cursz); + if (rc) + goto out; } } } if (leaf[leafno] != size) { jfs_err("JFS: wrong leaf value in dbBackSplit"); - return -EIO; + rc = -EIO; + goto out; } return 0; +out: +return rc + }