/* * Realtime Reference Count btree. * * This is a btree used to track the owner(s) of a given extent in the realtime * device. See the comments in xfs_refcount_btree.c for more information. * * This tree is basically the same as the regular refcount btree except that * it's rooted in an inode.
*/
/* * Calculate number of records in a realtime refcount btree inode root.
*/ unsignedint
xfs_rtrefcountbt_droot_maxrecs( unsignedint blocklen, bool leaf)
{
blocklen -= sizeof(struct xfs_rtrefcount_root);
/* * Get the maximum records we could store in the on-disk format. * * For non-root nodes this is equivalent to xfs_rtrefcountbt_get_maxrecs, but * for the root node this checks the available space in the dinode fork so that * we can resize the in-memory buffer to match it. After a resize to the * maximum size this function returns the same value as * xfs_rtrefcountbt_get_maxrecs for the root node, too.
*/ STATICint
xfs_rtrefcountbt_get_dmaxrecs( struct xfs_btree_cur *cur, int level)
{ if (level != cur->bc_nlevels - 1) return cur->bc_mp->m_rtrefc_mxr[level != 0]; return xfs_rtrefcountbt_droot_maxrecs(cur->bc_ino.forksize, level == 0);
}
/* Handle the nop case quietly. */ if (new_size == old_size) return ifp->if_broot;
if (new_size > old_size) { unsignedint old_numrecs;
/* * If there wasn't any memory allocated before, just allocate * it now and get out.
*/ if (old_size == 0) return xfs_broot_realloc(ifp, new_size);
/* * If there is already an existing if_broot, then we need to * realloc it and possibly move the node block pointers because * those are not butted up against the btree block header.
*/
old_numrecs = xfs_rtrefcountbt_maxrecs(mp, old_size, level);
broot = xfs_broot_realloc(ifp, new_size); if (level > 0)
xfs_rtrefcountbt_move_ptrs(mp, broot, old_size,
new_size, old_numrecs); goto out_broot;
}
/* * We're reducing numrecs. If we're going all the way to zero, just * free the block.
*/
ASSERT(ifp->if_broot != NULL && old_size > 0); if (new_size == 0) return xfs_broot_realloc(ifp, 0);
/* * Shrink the btree root by possibly moving the rtrmapbt pointers, * since they are not butted up against the btree block header. Then * reallocate broot.
*/ if (level > 0)
xfs_rtrefcountbt_move_ptrs(mp, ifp->if_broot, old_size,
new_size, new_numrecs);
broot = xfs_broot_realloc(ifp, new_size);
/* * Free any resources hanging off the real fork, then shallow-copy the * staging fork's contents into the real fork to transfer everything * we just built.
*/
ifp = xfs_ifork_ptr(cur->bc_ino.ip, XFS_DATA_FORK);
xfs_idestroy_fork(ifp);
memcpy(ifp, ifake->if_fork, sizeof(struct xfs_ifork));
/* Calculate number of records in a realtime refcount btree block. */ staticinlineunsignedint
xfs_rtrefcountbt_block_maxrecs( unsignedint blocklen, bool leaf)
{
/* * Calculate number of records in an refcount btree block.
*/ unsignedint
xfs_rtrefcountbt_maxrecs( struct xfs_mount *mp, unsignedint blocklen, bool leaf)
{
blocklen -= XFS_RTREFCOUNT_BLOCK_LEN; return xfs_rtrefcountbt_block_maxrecs(blocklen, leaf);
}
/* Compute the max possible height for realtime refcount btrees. */ unsignedint
xfs_rtrefcountbt_maxlevels_ondisk(void)
{ unsignedint minrecs[2]; unsignedint blocklen;
/* Compute the maximum height of a realtime refcount btree. */ void
xfs_rtrefcountbt_compute_maxlevels( struct xfs_mount *mp)
{ unsignedint d_maxlevels, r_maxlevels;
if (!xfs_has_rtreflink(mp)) {
mp->m_rtrefc_maxlevels = 0; return;
}
/* * The realtime refcountbt lives on the data device, which means that * its maximum height is constrained by the size of the data device and * the height required to store one refcount record for each rtextent * in an rt group.
*/
d_maxlevels = xfs_btree_space_to_height(mp->m_rtrefc_mnr,
mp->m_sb.sb_dblocks);
r_maxlevels = xfs_btree_compute_maxlevels(mp->m_rtrefc_mnr,
mp->m_sb.sb_rgextents);
/* Add one level to handle the inode root level. */
mp->m_rtrefc_maxlevels = min(d_maxlevels, r_maxlevels) + 1;
}
/* Calculate the rtrefcount btree size for some records. */ unsignedlonglong
xfs_rtrefcountbt_calc_size( struct xfs_mount *mp, unsignedlonglong len)
{ return xfs_btree_calc_size(mp->m_rtrefc_mnr, len);
}
/* * Calculate the maximum refcount btree size.
*/ staticunsignedlonglong
xfs_rtrefcountbt_max_size( struct xfs_mount *mp,
xfs_rtblock_t rtblocks)
{ /* Bail out if we're uninitialized, which can happen in mkfs. */ if (mp->m_rtrefc_mxr[0] == 0) return 0;
/* * Figure out how many blocks to reserve and how many are used by this btree. * We need enough space to hold one record for every rt extent in the rtgroup.
*/
xfs_filblks_t
xfs_rtrefcountbt_calc_reserves( struct xfs_mount *mp)
{ if (!xfs_has_rtreflink(mp)) return 0;
/* Load a realtime reference count btree root in from disk. */ int
xfs_iformat_rtrefcount( struct xfs_inode *ip, struct xfs_dinode *dip)
{ struct xfs_mount *mp = ip->i_mount; struct xfs_rtrefcount_root *dfp = XFS_DFORK_PTR(dip, XFS_DATA_FORK); struct xfs_btree_block *broot; unsignedint numrecs; unsignedint level; int dsize;
/* * growfs must create the rtrefcount inodes before adding a realtime * volume to the filesystem, so we cannot use the rtrefcount predicate * here.
*/ if (!xfs_has_reflink(ip->i_mount)) {
xfs_inode_mark_sick(ip, XFS_SICK_INO_CORE); return -EFSCORRUPTED;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.