/* * Calculate number of records in an alloc btree block. */ int xfs_allocbt_maxrecs( struct xfs_mount *mp, int blocklen, int leaf) { blocklen -= XFS_ALLOC_BLOCK_LEN(mp); if (leaf) return blocklen / sizeof(xfs_alloc_rec_t); return blocklen / (sizeof(xfs_alloc_key_t) + sizeof(xfs_alloc_ptr_t)); }
/* * rebuilds a freespace tree given a cursor and magic number of type * of tree to build (bno or bcnt). returns the number of free blocks * represented by the tree. */ static xfs_extlen_t build_freespace_tree(xfs_mount_t *mp, xfs_agnumber_t agno, bt_status_t *btree_curs, __uint32_t magic) { xfs_agnumber_t i; xfs_agblock_t j; struct xfs_btree_block *bt_hdr; xfs_alloc_rec_t *bt_rec; int level; xfs_agblock_t agbno; extent_tree_node_t *ext_ptr; bt_stat_level_t *lptr; xfs_extlen_t freeblks; __uint32_t crc_magic; #ifdef XR_BLD_FREE_TRACE fprintf(stderr, "in build_freespace_tree, agno = %d\n", agno); #endif level = btree_curs->num_levels; freeblks = 0; ASSERT(level > 0); if (magic == XFS_ABTB_MAGIC) crc_magic = XFS_ABTB_CRC_MAGIC; else crc_magic = XFS_ABTC_CRC_MAGIC; /* * initialize the first block on each btree level */ for (i = 0; i < level; i++) { lptr = &btree_curs->level[i]; agbno = get_next_blockaddr(agno, i, btree_curs); lptr->buf_p = libxfs_getbuf(mp->m_dev, XFS_AGB_TO_DADDR(mp, agno, agbno), XFS_FSB_TO_BB(mp, 1)); if (i == btree_curs->num_levels - 1) btree_curs->root = agbno; lptr->agbno = agbno; lptr->prev_agbno = NULLAGBLOCK; lptr->prev_buf_p = NULL; /* * initialize block header */ lptr->buf_p->b_ops = &xfs_allocbt_buf_ops; bt_hdr = XFS_BUF_TO_BLOCK(lptr->buf_p); memset(bt_hdr, 0, mp->m_sb.sb_blocksize); if (xfs_sb_version_hascrc(&mp->m_sb)) xfs_btree_init_block(mp, lptr->buf_p, crc_magic, i, 0, agno, XFS_BTREE_CRC_BLOCKS); else xfs_btree_init_block(mp, lptr->buf_p, magic, i, 0, agno, 0); } /* * run along leaf, setting up records. as we have to switch * blocks, call the prop_freespace_cursor routine to set up the new * pointers for the parent. that can recurse up to the root * if required. set the sibling pointers for leaf level here. */ if (magic == XFS_ABTB_MAGIC) ext_ptr = findfirst_bno_extent(agno); else ext_ptr = findfirst_bcnt_extent(agno); #ifdef XR_BLD_FREE_TRACE fprintf(stderr, "bft, agno = %d, start = %u, count = %u\n", agno, ext_ptr->ex_startblock, ext_ptr->ex_blockcount); #endif lptr = &btree_curs->level[0]; for (i = 0; i < btree_curs->level[0].num_blocks; i++) { /* * block initialization, lay in block header */ lptr->buf_p->b_ops = &xfs_allocbt_buf_ops; bt_hdr = XFS_BUF_TO_BLOCK(lptr->buf_p); memset(bt_hdr, 0, mp->m_sb.sb_blocksize); if (xfs_sb_version_hascrc(&mp->m_sb)) xfs_btree_init_block(mp, lptr->buf_p, crc_magic, 0, 0, agno, XFS_BTREE_CRC_BLOCKS); else xfs_btree_init_block(mp, lptr->buf_p, magic, 0, 0, agno, 0); bt_hdr->bb_u.s.bb_leftsib = cpu_to_be32(lptr->prev_agbno); bt_hdr->bb_numrecs = cpu_to_be16(lptr->num_recs_pb + (lptr->modulo > 0)); #ifdef XR_BLD_FREE_TRACE fprintf(stderr, "bft, bb_numrecs = %d\n", be16_to_cpu(bt_hdr->bb_numrecs)); #endif if (lptr->modulo > 0) lptr->modulo--; /* * initialize values in the path up to the root if * this is a multi-level btree */ if (btree_curs->num_levels > 1) prop_freespace_cursor(mp, agno, btree_curs, ext_ptr->ex_startblock, ext_ptr->ex_blockcount, 0, magic); bt_rec = (xfs_alloc_rec_t *) ((char *)bt_hdr + XFS_ALLOC_BLOCK_LEN(mp)); for (j = 0; j < be16_to_cpu(bt_hdr->bb_numrecs); j++) { ASSERT(ext_ptr != NULL); bt_rec[j].ar_startblock = cpu_to_be32( ext_ptr->ex_startblock); bt_rec[j].ar_blockcount = cpu_to_be32( ext_ptr->ex_blockcount); freeblks += ext_ptr->ex_blockcount; if (magic == XFS_ABTB_MAGIC) ext_ptr = findnext_bno_extent(ext_ptr); else ext_ptr = findnext_bcnt_extent(agno, ext_ptr); #if 0 #ifdef XR_BLD_FREE_TRACE if (ext_ptr == NULL) fprintf(stderr, "null extent pointer, j = %d\n", j); else fprintf(stderr, "bft, agno = %d, start = %u, count = %u\n", agno, ext_ptr->ex_startblock, ext_ptr->ex_blockcount); #endif #endif } if (ext_ptr != NULL) { /* * get next leaf level block */ if (lptr->prev_buf_p != NULL) { #ifdef XR_BLD_FREE_TRACE fprintf(stderr, " writing fst agbno %u\n", lptr->prev_agbno); #endif ASSERT(lptr->prev_agbno != NULLAGBLOCK); libxfs_writebuf(lptr->prev_buf_p, 0); } lptr->prev_buf_p = lptr->buf_p; lptr->prev_agbno = lptr->agbno; lptr->agbno = get_next_blockaddr(agno, 0, btree_curs); bt_hdr->bb_u.s.bb_rightsib = cpu_to_be32(lptr->agbno); lptr->buf_p = libxfs_getbuf(mp->m_dev, XFS_AGB_TO_DADDR(mp, agno, lptr->agbno), XFS_FSB_TO_BB(mp, 1)); } } return(freeblks); }