/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2022 Oracle. All Rights Reserved. * Author: Darrick J. Wong */ #ifndef __XFS_RTRMAP_BTREE_H__ #define __XFS_RTRMAP_BTREE_H__ struct xfs_buf; struct xfs_btree_cur; struct xfs_mount; struct xbtree_ifakeroot; struct xfs_rtgroup; struct xfs_imeta_path; /* rmaps only exist on crc enabled filesystems */ #define XFS_RTRMAP_BLOCK_LEN XFS_BTREE_LBLOCK_CRC_LEN struct xfs_btree_cur *xfs_rtrmapbt_init_cursor(struct xfs_mount *mp, struct xfs_trans *tp, struct xfs_rtgroup *rtg, struct xfs_inode *ip); struct xfs_btree_cur *xfs_rtrmapbt_stage_cursor(struct xfs_mount *mp, struct xfs_rtgroup *rtg, struct xfs_inode *ip, struct xbtree_ifakeroot *ifake); void xfs_rtrmapbt_commit_staged_btree(struct xfs_btree_cur *cur, struct xfs_trans *tp); unsigned int xfs_rtrmapbt_maxrecs(struct xfs_mount *mp, unsigned int blocklen, bool leaf); void xfs_rtrmapbt_compute_maxlevels(struct xfs_mount *mp); unsigned int xfs_rtrmapbt_droot_maxrecs(unsigned int blocklen, bool leaf); /* * Addresses of records, keys, and pointers within an incore rtrmapbt block. * * (note that some of these may appear unused, but they are used in userspace) */ static inline struct xfs_rtrmap_rec * xfs_rtrmap_rec_addr( struct xfs_btree_block *block, unsigned int index) { return (struct xfs_rtrmap_rec *) ((char *)block + XFS_RTRMAP_BLOCK_LEN + (index - 1) * sizeof(struct xfs_rtrmap_rec)); } static inline struct xfs_rtrmap_key * xfs_rtrmap_key_addr( struct xfs_btree_block *block, unsigned int index) { return (struct xfs_rtrmap_key *) ((char *)block + XFS_RTRMAP_BLOCK_LEN + (index - 1) * 2 * sizeof(struct xfs_rtrmap_key)); } static inline struct xfs_rtrmap_key * xfs_rtrmap_high_key_addr( struct xfs_btree_block *block, unsigned int index) { return (struct xfs_rtrmap_key *) ((char *)block + XFS_RTRMAP_BLOCK_LEN + sizeof(struct xfs_rtrmap_key) + (index - 1) * 2 * sizeof(struct xfs_rtrmap_key)); } static inline xfs_rtrmap_ptr_t * xfs_rtrmap_ptr_addr( struct xfs_btree_block *block, unsigned int index, unsigned int maxrecs) { return (xfs_rtrmap_ptr_t *) ((char *)block + XFS_RTRMAP_BLOCK_LEN + maxrecs * 2 * sizeof(struct xfs_rtrmap_key) + (index - 1) * sizeof(xfs_rtrmap_ptr_t)); } unsigned int xfs_rtrmapbt_maxlevels_ondisk(void); int __init xfs_rtrmapbt_init_cur_cache(void); void xfs_rtrmapbt_destroy_cur_cache(void); int xfs_rtrmapbt_create_path(struct xfs_mount *mp, xfs_rgnumber_t rgno, struct xfs_imeta_path **pathp); xfs_filblks_t xfs_rtrmapbt_calc_reserves(struct xfs_mount *mp); /* Addresses of key, pointers, and records within an ondisk rtrmapbt block. */ static inline struct xfs_rtrmap_rec * xfs_rtrmap_droot_rec_addr( struct xfs_rtrmap_root *block, unsigned int index) { return (struct xfs_rtrmap_rec *) ((char *)(block + 1) + (index - 1) * sizeof(struct xfs_rtrmap_rec)); } static inline struct xfs_rtrmap_key * xfs_rtrmap_droot_key_addr( struct xfs_rtrmap_root *block, unsigned int index) { return (struct xfs_rtrmap_key *) ((char *)(block + 1) + (index - 1) * 2 * sizeof(struct xfs_rtrmap_key)); } static inline xfs_rtrmap_ptr_t * xfs_rtrmap_droot_ptr_addr( struct xfs_rtrmap_root *block, unsigned int index, unsigned int maxrecs) { return (xfs_rtrmap_ptr_t *) ((char *)(block + 1) + maxrecs * 2 * sizeof(struct xfs_rtrmap_key) + (index - 1) * sizeof(xfs_rtrmap_ptr_t)); } /* * Address of pointers within the incore btree root. * * These are to be used when we know the size of the block and * we don't have a cursor. */ static inline xfs_rtrmap_ptr_t * xfs_rtrmap_broot_ptr_addr( struct xfs_mount *mp, struct xfs_btree_block *bb, unsigned int index, unsigned int block_size) { return xfs_rtrmap_ptr_addr(bb, index, xfs_rtrmapbt_maxrecs(mp, block_size, false)); } /* * Compute the space required for the incore btree root containing the given * number of records. */ static inline size_t xfs_rtrmap_broot_space_calc( struct xfs_mount *mp, unsigned int level, unsigned int nrecs) { size_t sz = XFS_RTRMAP_BLOCK_LEN; if (level > 0) return sz + nrecs * (2 * sizeof(struct xfs_rtrmap_key) + sizeof(xfs_rtrmap_ptr_t)); return sz + nrecs * sizeof(struct xfs_rtrmap_rec); } /* * Compute the space required for the incore btree root given the ondisk * btree root block. */ static inline size_t xfs_rtrmap_broot_space(struct xfs_mount *mp, struct xfs_rtrmap_root *bb) { return xfs_rtrmap_broot_space_calc(mp, be16_to_cpu(bb->bb_level), be16_to_cpu(bb->bb_numrecs)); } /* Compute the space required for the ondisk root block. */ static inline size_t xfs_rtrmap_droot_space_calc( unsigned int level, unsigned int nrecs) { size_t sz = sizeof(struct xfs_rtrmap_root); if (level > 0) return sz + nrecs * (2 * sizeof(struct xfs_rtrmap_key) + sizeof(xfs_rtrmap_ptr_t)); return sz + nrecs * sizeof(struct xfs_rtrmap_rec); } /* * Compute the space required for the ondisk root block given an incore root * block. */ static inline size_t xfs_rtrmap_droot_space(struct xfs_btree_block *bb) { return xfs_rtrmap_droot_space_calc(be16_to_cpu(bb->bb_level), be16_to_cpu(bb->bb_numrecs)); } int xfs_iformat_rtrmap(struct xfs_inode *ip, struct xfs_dinode *dip); void xfs_rtrmapbt_to_disk(struct xfs_mount *mp, struct xfs_btree_block *rblock, unsigned int rblocklen, struct xfs_rtrmap_root *dblock, unsigned int dblocklen); void xfs_iflush_rtrmap(struct xfs_inode *ip, struct xfs_dinode *dip); struct xfs_imeta_update; int xfs_rtrmapbt_create(struct xfs_trans **tpp, struct xfs_imeta_path *path, struct xfs_imeta_update *ic, struct xfs_inode **ipp); unsigned long long xfs_rtrmapbt_calc_size(struct xfs_mount *mp, unsigned long long len); #ifdef CONFIG_XFS_IN_MEMORY_BTREE struct xfbtree; struct xfs_btree_cur *xfs_rtrmapbt_mem_cursor(struct xfs_mount *mp, struct xfs_trans *tp, struct xfs_buf *mhead_bp, struct xfbtree *xfbtree); int xfs_rtrmapbt_mem_create(struct xfs_mount *mp, xfs_rgnumber_t rgno, struct xfs_buftarg *target, struct xfbtree **xfbtreep); bool xfs_rtrmapbt_mem_verify_rec(struct xfs_btree_cur *cur, const struct xfs_rmap_irec *irec); #else # define xfs_rtrmapbt_mem_verify_rec(cur, irec) (false) #endif /* CONFIG_XFS_IN_MEMORY_BTREE */ #endif /* __XFS_RTRMAP_BTREE_H__ */