diff options
Diffstat (limited to 'fs/jfs/jfs_dmap.c')
-rw-r--r-- | fs/jfs/jfs_dmap.c | 344 |
1 files changed, 38 insertions, 306 deletions
diff --git a/fs/jfs/jfs_dmap.c b/fs/jfs/jfs_dmap.c index cced2fed9d0..c739626f5bf 100644 --- a/fs/jfs/jfs_dmap.c +++ b/fs/jfs/jfs_dmap.c @@ -26,36 +26,6 @@ #include "jfs_debug.h" /* - * Debug code for double-checking block map - */ -/* #define _JFS_DEBUG_DMAP 1 */ - -#ifdef _JFS_DEBUG_DMAP -#define DBINITMAP(size,ipbmap,results) \ - DBinitmap(size,ipbmap,results) -#define DBALLOC(dbmap,mapsize,blkno,nblocks) \ - DBAlloc(dbmap,mapsize,blkno,nblocks) -#define DBFREE(dbmap,mapsize,blkno,nblocks) \ - DBFree(dbmap,mapsize,blkno,nblocks) -#define DBALLOCCK(dbmap,mapsize,blkno,nblocks) \ - DBAllocCK(dbmap,mapsize,blkno,nblocks) -#define DBFREECK(dbmap,mapsize,blkno,nblocks) \ - DBFreeCK(dbmap,mapsize,blkno,nblocks) - -static void DBinitmap(s64, struct inode *, u32 **); -static void DBAlloc(uint *, s64, s64, s64); -static void DBFree(uint *, s64, s64, s64); -static void DBAllocCK(uint *, s64, s64, s64); -static void DBFreeCK(uint *, s64, s64, s64); -#else -#define DBINITMAP(size,ipbmap,results) -#define DBALLOC(dbmap, mapsize, blkno, nblocks) -#define DBFREE(dbmap, mapsize, blkno, nblocks) -#define DBALLOCCK(dbmap, mapsize, blkno, nblocks) -#define DBFREECK(dbmap, mapsize, blkno, nblocks) -#endif /* _JFS_DEBUG_DMAP */ - -/* * SERIALIZATION of the Block Allocation Map. * * the working state of the block allocation map is accessed in @@ -105,7 +75,7 @@ static void dbAllocBits(struct bmap * bmp, struct dmap * dp, s64 blkno, int nblocks); static void dbSplit(dmtree_t * tp, int leafno, int splitsz, int newval); static void dbBackSplit(dmtree_t * tp, int leafno); -static void dbJoin(dmtree_t * tp, int leafno, int newval); +static int dbJoin(dmtree_t * tp, int leafno, int newval); static void dbAdjTree(dmtree_t * tp, int leafno, int newval); static int dbAdjCtl(struct bmap * bmp, s64 blkno, int newval, int alloc, int level); @@ -128,8 +98,8 @@ static int dbExtend(struct inode *ip, s64 blkno, s64 nblocks, s64 addnblocks); static int dbFindBits(u32 word, int l2nb); static int dbFindCtl(struct bmap * bmp, int l2nb, int level, s64 * blkno); static int dbFindLeaf(dmtree_t * tp, int l2nb, int *leafidx); -static void dbFreeBits(struct bmap * bmp, struct dmap * dp, s64 blkno, - int nblocks); +static int dbFreeBits(struct bmap * bmp, struct dmap * dp, s64 blkno, + int nblocks); static int dbFreeDmap(struct bmap * bmp, struct dmap * dp, s64 blkno, int nblocks); static int dbMaxBud(u8 * cp); @@ -242,7 +212,6 @@ int dbMount(struct inode *ipbmap) JFS_SBI(ipbmap->i_sb)->bmap = bmp; memset(bmp->db_active, 0, sizeof(bmp->db_active)); - DBINITMAP(bmp->db_mapsize, ipbmap, &bmp->db_DBmap); /* * allocate/initialize the bmap lock @@ -407,16 +376,13 @@ int dbFree(struct inode *ip, s64 blkno, s64 nblocks) */ nb = min(rem, BPERDMAP - (blkno & (BPERDMAP - 1))); - DBALLOCCK(bmp->db_DBmap, bmp->db_mapsize, blkno, nb); - /* free the blocks. */ if ((rc = dbFreeDmap(bmp, dp, blkno, nb))) { + jfs_error(ip->i_sb, "dbFree: error in block map\n"); release_metapage(mp); IREAD_UNLOCK(ipbmap); return (rc); } - - DBFREE(bmp->db_DBmap, bmp->db_mapsize, blkno, nb); } /* write the last buffer. */ @@ -775,10 +741,6 @@ int dbAlloc(struct inode *ip, s64 hint, s64 nblocks, s64 * results) IWRITE_LOCK(ipbmap); rc = dbAllocAny(bmp, nblocks, l2nb, results); - if (rc == 0) { - DBALLOC(bmp->db_DBmap, bmp->db_mapsize, *results, - nblocks); - } goto write_unlock; } @@ -836,8 +798,6 @@ int dbAlloc(struct inode *ip, s64 hint, s64 nblocks, s64 * results) != -ENOSPC) { if (rc == 0) { *results = blkno; - DBALLOC(bmp->db_DBmap, bmp->db_mapsize, - *results, nblocks); mark_metapage_dirty(mp); } @@ -863,11 +823,8 @@ int dbAlloc(struct inode *ip, s64 hint, s64 nblocks, s64 * results) if ((rc = dbAllocNear(bmp, dp, blkno, (int) nblocks, l2nb, results)) != -ENOSPC) { - if (rc == 0) { - DBALLOC(bmp->db_DBmap, bmp->db_mapsize, - *results, nblocks); + if (rc == 0) mark_metapage_dirty(mp); - } release_metapage(mp); goto read_unlock; @@ -878,11 +835,8 @@ int dbAlloc(struct inode *ip, s64 hint, s64 nblocks, s64 * results) */ if ((rc = dbAllocDmapLev(bmp, dp, (int) nblocks, l2nb, results)) != -ENOSPC) { - if (rc == 0) { - DBALLOC(bmp->db_DBmap, bmp->db_mapsize, - *results, nblocks); + if (rc == 0) mark_metapage_dirty(mp); - } release_metapage(mp); goto read_unlock; @@ -896,13 +850,9 @@ int dbAlloc(struct inode *ip, s64 hint, s64 nblocks, s64 * results) * the same allocation group as the hint. */ IWRITE_LOCK(ipbmap); - if ((rc = dbAllocAG(bmp, agno, nblocks, l2nb, results)) - != -ENOSPC) { - if (rc == 0) - DBALLOC(bmp->db_DBmap, bmp->db_mapsize, - *results, nblocks); + if ((rc = dbAllocAG(bmp, agno, nblocks, l2nb, results)) != -ENOSPC) goto write_unlock; - } + IWRITE_UNLOCK(ipbmap); @@ -918,9 +868,6 @@ int dbAlloc(struct inode *ip, s64 hint, s64 nblocks, s64 * results) */ if ((rc = dbAllocAG(bmp, agno, nblocks, l2nb, results)) == -ENOSPC) rc = dbAllocAny(bmp, nblocks, l2nb, results); - if (rc == 0) { - DBALLOC(bmp->db_DBmap, bmp->db_mapsize, *results, nblocks); - } write_unlock: IWRITE_UNLOCK(ipbmap); @@ -992,10 +939,9 @@ int dbAllocExact(struct inode *ip, s64 blkno, int nblocks) IREAD_UNLOCK(ipbmap); - if (rc == 0) { - DBALLOC(bmp->db_DBmap, bmp->db_mapsize, blkno, nblocks); + if (rc == 0) mark_metapage_dirty(mp); - } + release_metapage(mp); return (rc); @@ -1144,7 +1090,6 @@ static int dbExtend(struct inode *ip, s64 blkno, s64 nblocks, s64 addnblocks) return -EIO; } - DBALLOCCK(bmp->db_DBmap, bmp->db_mapsize, blkno, nblocks); dp = (struct dmap *) mp->data; /* try to allocate the blocks immediately following the @@ -1155,11 +1100,9 @@ static int dbExtend(struct inode *ip, s64 blkno, s64 nblocks, s64 addnblocks) IREAD_UNLOCK(ipbmap); /* were we successful ? */ - if (rc == 0) { - DBALLOC(bmp->db_DBmap, bmp->db_mapsize, extblkno, - addnblocks); + if (rc == 0) write_metapage(mp); - } else + else /* we were not successful */ release_metapage(mp); @@ -2078,7 +2021,7 @@ static int dbFreeDmap(struct bmap * bmp, struct dmap * dp, s64 blkno, int nblocks) { s8 oldroot; - int rc, word; + int rc = 0, word; /* save the current value of the root (i.e. maximum free string) * of the dmap tree. @@ -2086,11 +2029,11 @@ static int dbFreeDmap(struct bmap * bmp, struct dmap * dp, s64 blkno, oldroot = dp->tree.stree[ROOT]; /* free the specified (blocks) bits */ - dbFreeBits(bmp, dp, blkno, nblocks); + rc = dbFreeBits(bmp, dp, blkno, nblocks); - /* if the root has not changed, done. */ - if (dp->tree.stree[ROOT] == oldroot) - return (0); + /* if error or the root has not changed, done. */ + if (rc || (dp->tree.stree[ROOT] == oldroot)) + return (rc); /* root changed. bubble the change up to the dmap control pages. * if the adjustment of the upper level control pages fails, @@ -2279,15 +2222,16 @@ static void dbAllocBits(struct bmap * bmp, struct dmap * dp, s64 blkno, * blkno - starting block number of the bits to be freed. * nblocks - number of bits to be freed. * - * RETURN VALUES: none + * RETURN VALUES: 0 for success * * serialization: IREAD_LOCK(ipbmap) or IWRITE_LOCK(ipbmap) held on entry/exit; */ -static void dbFreeBits(struct bmap * bmp, struct dmap * dp, s64 blkno, +static int dbFreeBits(struct bmap * bmp, struct dmap * dp, s64 blkno, int nblocks) { int dbitno, word, rembits, nb, nwords, wbitno, nw, agno; dmtree_t *tp = (dmtree_t *) & dp->tree; + int rc = 0; int size; /* determine the bit number and word within the dmap of the @@ -2336,8 +2280,10 @@ static void dbFreeBits(struct bmap * bmp, struct dmap * dp, s64 blkno, /* update the leaf for this dmap word. */ - dbJoin(tp, word, - dbMaxBud((u8 *) & dp->wmap[word])); + rc = dbJoin(tp, word, + dbMaxBud((u8 *) & dp->wmap[word])); + if (rc) + return rc; word += 1; } else { @@ -2368,7 +2314,9 @@ static void dbFreeBits(struct bmap * bmp, struct dmap * dp, s64 blkno, /* update the leaf. */ - dbJoin(tp, word, size); + rc = dbJoin(tp, word, size); + if (rc) + return rc; /* get the number of dmap words handled. */ @@ -2415,6 +2363,8 @@ static void dbFreeBits(struct bmap * bmp, struct dmap * dp, s64 blkno, } BMAP_UNLOCK(bmp); + + return 0; } @@ -2522,7 +2472,9 @@ dbAdjCtl(struct bmap * bmp, s64 blkno, int newval, int alloc, int level) } dbSplit((dmtree_t *) dcp, leafno, dcp->budmin, newval); } else { - dbJoin((dmtree_t *) dcp, leafno, newval); + rc = dbJoin((dmtree_t *) dcp, leafno, newval); + if (rc) + return rc; } /* check if the root of the current dmap control page changed due @@ -2747,7 +2699,7 @@ static void dbBackSplit(dmtree_t * tp, int leafno) * * RETURN VALUES: none */ -static void dbJoin(dmtree_t * tp, int leafno, int newval) +static int dbJoin(dmtree_t * tp, int leafno, int newval) { int budsz, buddy; s8 *leaf; @@ -2787,7 +2739,9 @@ static void dbJoin(dmtree_t * tp, int leafno, int newval) if (newval > leaf[buddy]) break; - assert(newval == leaf[buddy]); + /* It shouldn't be less */ + if (newval < leaf[buddy]) + return -EIO; /* check which (leafno or buddy) is the left buddy. * the left buddy gets to claim the blocks resulting @@ -2819,6 +2773,8 @@ static void dbJoin(dmtree_t * tp, int leafno, int newval) /* update the leaf value. */ dbAdjTree(tp, leafno, newval); + + return 0; } @@ -3185,16 +3141,12 @@ int dbAllocBottomUp(struct inode *ip, s64 blkno, s64 nblocks) */ nb = min(rem, BPERDMAP - (blkno & (BPERDMAP - 1))); - DBFREECK(bmp->db_DBmap, bmp->db_mapsize, blkno, nb); - /* allocate the blocks. */ if ((rc = dbAllocDmapBU(bmp, dp, blkno, nb))) { release_metapage(mp); IREAD_UNLOCK(ipbmap); return (rc); } - - DBALLOC(bmp->db_DBmap, bmp->db_mapsize, blkno, nb); } /* write the last buffer. */ @@ -4041,223 +3993,3 @@ s64 dbMapFileSizeToMapSize(struct inode * ipbmap) return (nblocks); } - - -#ifdef _JFS_DEBUG_DMAP -/* - * DBinitmap() - */ -static void DBinitmap(s64 size, struct inode *ipbmap, u32 ** results) -{ - int npages; - u32 *dbmap, *d; - int n; - s64 lblkno, cur_block; - struct dmap *dp; - struct metapage *mp; - - npages = size / 32768; - npages += (size % 32768) ? 1 : 0; - - dbmap = (u32 *) xmalloc(npages * 4096, L2PSIZE, kernel_heap); - if (dbmap == NULL) - BUG(); /* Not robust since this is only unused debug code */ - - for (n = 0, d = dbmap; n < npages; n++, d += 1024) - bzero(d, 4096); - - /* Need to initialize from disk map pages - */ - for (d = dbmap, cur_block = 0; cur_block < size; - cur_block += BPERDMAP, d += LPERDMAP) { - lblkno = BLKTODMAP(cur_block, - JFS_SBI(ipbmap->i_sb)->bmap-> - db_l2nbperpage); - mp = read_metapage(ipbmap, lblkno, PSIZE, 0); - if (mp == NULL) { - jfs_error(ipbmap->i_sb, - "DBinitmap: could not read disk map page"); - continue; - } - dp = (struct dmap *) mp->data; - - for (n = 0; n < LPERDMAP; n++) - d[n] = le32_to_cpu(dp->wmap[n]); - - release_metapage(mp); - } - - *results = dbmap; -} - - -/* - * DBAlloc() - */ -void DBAlloc(uint * dbmap, s64 mapsize, s64 blkno, s64 nblocks) -{ - int word, nb, bitno; - u32 mask; - - assert(blkno > 0 && blkno < mapsize); - assert(nblocks > 0 && nblocks <= mapsize); - - assert(blkno + nblocks <= mapsize); - - dbmap += (blkno / 32); - while (nblocks > 0) { - bitno = blkno & (32 - 1); - nb = min(nblocks, 32 - bitno); - - mask = (0xffffffff << (32 - nb) >> bitno); - assert((mask & *dbmap) == 0); - *dbmap |= mask; - - dbmap++; - blkno += nb; - nblocks -= nb; - } -} - - -/* - * DBFree() - */ -static void DBFree(uint * dbmap, s64 mapsize, s64 blkno, s64 nblocks) -{ - int word, nb, bitno; - u32 mask; - - assert(blkno > 0 && blkno < mapsize); - assert(nblocks > 0 && nblocks <= mapsize); - - assert(blkno + nblocks <= mapsize); - - dbmap += (blkno / 32); - while (nblocks > 0) { - bitno = blkno & (32 - 1); - nb = min(nblocks, 32 - bitno); - - mask = (0xffffffff << (32 - nb) >> bitno); - assert((mask & *dbmap) == mask); - *dbmap &= ~mask; - - dbmap++; - blkno += nb; - nblocks -= nb; - } -} - - -/* - * DBAllocCK() - */ -static void DBAllocCK(uint * dbmap, s64 mapsize, s64 blkno, s64 nblocks) -{ - int word, nb, bitno; - u32 mask; - - assert(blkno > 0 && blkno < mapsize); - assert(nblocks > 0 && nblocks <= mapsize); - - assert(blkno + nblocks <= mapsize); - - dbmap += (blkno / 32); - while (nblocks > 0) { - bitno = blkno & (32 - 1); - nb = min(nblocks, 32 - bitno); - - mask = (0xffffffff << (32 - nb) >> bitno); - assert((mask & *dbmap) == mask); - - dbmap++; - blkno += nb; - nblocks -= nb; - } -} - - -/* - * DBFreeCK() - */ -static void DBFreeCK(uint * dbmap, s64 mapsize, s64 blkno, s64 nblocks) -{ - int word, nb, bitno; - u32 mask; - - assert(blkno > 0 && blkno < mapsize); - assert(nblocks > 0 && nblocks <= mapsize); - - assert(blkno + nblocks <= mapsize); - - dbmap += (blkno / 32); - while (nblocks > 0) { - bitno = blkno & (32 - 1); - nb = min(nblocks, 32 - bitno); - - mask = (0xffffffff << (32 - nb) >> bitno); - assert((mask & *dbmap) == 0); - - dbmap++; - blkno += nb; - nblocks -= nb; - } -} - - -/* - * dbPrtMap() - */ -static void dbPrtMap(struct bmap * bmp) -{ - printk(" mapsize: %d%d\n", bmp->db_mapsize); - printk(" nfree: %d%d\n", bmp->db_nfree); - printk(" numag: %d\n", bmp->db_numag); - printk(" agsize: %d%d\n", bmp->db_agsize); - printk(" agl2size: %d\n", bmp->db_agl2size); - printk(" agwidth: %d\n", bmp->db_agwidth); - printk(" agstart: %d\n", bmp->db_agstart); - printk(" agheigth: %d\n", bmp->db_agheigth); - printk(" aglevel: %d\n", bmp->db_aglevel); - printk(" maxlevel: %d\n", bmp->db_maxlevel); - printk(" maxag: %d\n", bmp->db_maxag); - printk(" agpref: %d\n", bmp->db_agpref); - printk(" l2nbppg: %d\n", bmp->db_l2nbperpage); -} - - -/* - * dbPrtCtl() - */ -static void dbPrtCtl(struct dmapctl * dcp) -{ - int i, j, n; - - printk(" height: %08x\n", le32_to_cpu(dcp->height)); - printk(" leafidx: %08x\n", le32_to_cpu(dcp->leafidx)); - printk(" budmin: %08x\n", dcp->budmin); - printk(" nleafs: %08x\n", le32_to_cpu(dcp->nleafs)); - printk(" l2nleafs: %08x\n", le32_to_cpu(dcp->l2nleafs)); - - printk("\n Tree:\n"); - for (i = 0; i < CTLLEAFIND; i += 8) { - n = min(8, CTLLEAFIND - i); - - for (j = 0; j < n; j++) - printf(" [%03x]: %02x", i + j, - (char) dcp->stree[i + j]); - printf("\n"); - } - - printk("\n Tree Leaves:\n"); - for (i = 0; i < LPERCTL; i += 8) { - n = min(8, LPERCTL - i); - - for (j = 0; j < n; j++) - printf(" [%03x]: %02x", - i + j, - (char) dcp->stree[i + j + CTLLEAFIND]); - printf("\n"); - } -} -#endif /* _JFS_DEBUG_DMAP */ |