static void process_btinode( xfs_dinode_t *dip, extmap_t **extmapp, int whichfork) { xfs_bmdr_block_t *dib; int i; xfs_bmbt_ptr_t *pp; dib = (xfs_bmdr_block_t *)XFS_DFORK_PTR(dip, whichfork); if (be16_to_cpu(dib->bb_level) == 0) { xfs_bmbt_rec_t *rp = XFS_BMDR_REC_ADDR(dib, 1); process_bmbt_reclist(rp, be16_to_cpu(dib->bb_numrecs), extmapp); return; } pp = XFS_BMDR_PTR_ADDR(dib, 1, xfs_bmdr_maxrecs(mp, XFS_DFORK_SIZE(dip, mp, whichfork), 0)); for (i = 0; i < be16_to_cpu(dib->bb_numrecs); i++) scan_lbtree(be64_to_cpu(pp[i]), be16_to_cpu(dib->bb_level), scanfunc_bmap, extmapp, whichfork == XFS_DATA_FORK ? TYP_BMAPBTD : TYP_BMAPBTA); }
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; }