static void scanfunc_bmap( struct xfs_btree_block *block, int level, extmap_t **extmapp, typnm_t btype) { int i; xfs_bmbt_ptr_t *pp; xfs_bmbt_rec_t *rp; int nrecs; nrecs = be16_to_cpu(block->bb_numrecs); if (level == 0) { if (nrecs > mp->m_bmap_dmxr[0]) { dbprintf(_("invalid numrecs (%u) in %s block\n"), nrecs, typtab[btype].name); return; } rp = XFS_BMBT_REC_ADDR(mp, block, 1); process_bmbt_reclist(rp, nrecs, extmapp); return; } if (nrecs > mp->m_bmap_dmxr[1]) { dbprintf(_("invalid numrecs (%u) in %s block\n"), nrecs, typtab[btype].name); return; } pp = XFS_BMBT_PTR_ADDR(mp, block, 1, mp->m_bmap_dmxr[0]); for (i = 0; i < nrecs; i++) scan_lbtree(be64_to_cpu(pp[i]), level, scanfunc_bmap, extmapp, btype); }
/* * Count leaf blocks given a range of extent records originally * in btree format. */ STATIC void xfs_bmap_disk_count_leaves( struct xfs_mount *mp, struct xfs_btree_block *block, int numrecs, int *count) { int b; xfs_bmbt_rec_t *frp; for (b = 1; b <= numrecs; b++) { frp = XFS_BMBT_REC_ADDR(mp, block, b); *count += xfs_bmbt_disk_get_blockcount(frp); } }
void bmap( xfs_dfiloff_t offset, xfs_dfilblks_t len, int whichfork, int *nexp, bmap_ext_t *bep) { struct xfs_btree_block *block; xfs_fsblock_t bno; xfs_dfiloff_t curoffset; xfs_dinode_t *dip; xfs_dfiloff_t eoffset; xfs_bmbt_rec_64_t *ep; xfs_dinode_fmt_t fmt; int fsize; xfs_bmbt_key_t *kp; int n; int nex; xfs_fsblock_t nextbno; int nextents; xfs_bmbt_ptr_t *pp; xfs_bmdr_block_t *rblock; typnm_t typ; xfs_bmbt_rec_64_t *xp; push_cur(); set_cur_inode(iocur_top->ino); nex = *nexp; *nexp = 0; ASSERT(nex > 0); dip = iocur_top->data; n = 0; eoffset = offset + len - 1; curoffset = offset; fmt = (xfs_dinode_fmt_t)XFS_DFORK_FORMAT(dip, whichfork); typ = whichfork == XFS_DATA_FORK ? TYP_BMAPBTD : TYP_BMAPBTA; ASSERT(typtab[typ].typnm == typ); ASSERT(fmt == XFS_DINODE_FMT_LOCAL || fmt == XFS_DINODE_FMT_EXTENTS || fmt == XFS_DINODE_FMT_BTREE); if (fmt == XFS_DINODE_FMT_EXTENTS) { nextents = XFS_DFORK_NEXTENTS(dip, whichfork); xp = (xfs_bmbt_rec_64_t *)XFS_DFORK_PTR(dip, whichfork); for (ep = xp; ep < &xp[nextents] && n < nex; ep++) { if (!bmap_one_extent(ep, &curoffset, eoffset, &n, bep)) break; } } else if (fmt == XFS_DINODE_FMT_BTREE) { push_cur(); bno = NULLFSBLOCK; rblock = (xfs_bmdr_block_t *)XFS_DFORK_PTR(dip, whichfork); fsize = XFS_DFORK_SIZE(dip, mp, whichfork); pp = XFS_BMDR_PTR_ADDR(rblock, 1, xfs_bmdr_maxrecs(mp, fsize, 0)); kp = XFS_BMDR_KEY_ADDR(rblock, 1); bno = select_child(curoffset, kp, pp, be16_to_cpu(rblock->bb_numrecs)); for (;;) { set_cur(&typtab[typ], XFS_FSB_TO_DADDR(mp, bno), blkbb, DB_RING_IGN, NULL); block = (struct xfs_btree_block *)iocur_top->data; if (be16_to_cpu(block->bb_level) == 0) break; pp = XFS_BMDR_PTR_ADDR(block, 1, xfs_bmbt_maxrecs(mp, mp->m_sb.sb_blocksize, 0)); kp = XFS_BMDR_KEY_ADDR(block, 1); bno = select_child(curoffset, kp, pp, be16_to_cpu(block->bb_numrecs)); } for (;;) { nextbno = be64_to_cpu(block->bb_u.l.bb_rightsib); nextents = be16_to_cpu(block->bb_numrecs); xp = (xfs_bmbt_rec_64_t *) XFS_BMBT_REC_ADDR(mp, block, 1); for (ep = xp; ep < &xp[nextents] && n < nex; ep++) { if (!bmap_one_extent(ep, &curoffset, eoffset, &n, bep)) { nextbno = NULLFSBLOCK; break; } } bno = nextbno; if (bno == NULLFSBLOCK) break; set_cur(&typtab[typ], XFS_FSB_TO_DADDR(mp, bno), blkbb, DB_RING_IGN, NULL); block = (struct xfs_btree_block *)iocur_top->data; } pop_cur(); } pop_cur(); *nexp = n; }