162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. 462306a36Sopenharmony_ci * All Rights Reserved. 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci#ifndef __XFS_INODE_FORK_H__ 762306a36Sopenharmony_ci#define __XFS_INODE_FORK_H__ 862306a36Sopenharmony_ci 962306a36Sopenharmony_cistruct xfs_inode_log_item; 1062306a36Sopenharmony_cistruct xfs_dinode; 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci/* 1362306a36Sopenharmony_ci * File incore extent information, present for each of data & attr forks. 1462306a36Sopenharmony_ci */ 1562306a36Sopenharmony_cistruct xfs_ifork { 1662306a36Sopenharmony_ci int64_t if_bytes; /* bytes in if_u1 */ 1762306a36Sopenharmony_ci struct xfs_btree_block *if_broot; /* file's incore btree root */ 1862306a36Sopenharmony_ci unsigned int if_seq; /* fork mod counter */ 1962306a36Sopenharmony_ci int if_height; /* height of the extent tree */ 2062306a36Sopenharmony_ci union { 2162306a36Sopenharmony_ci void *if_root; /* extent tree root */ 2262306a36Sopenharmony_ci char *if_data; /* inline file data */ 2362306a36Sopenharmony_ci } if_u1; 2462306a36Sopenharmony_ci xfs_extnum_t if_nextents; /* # of extents in this fork */ 2562306a36Sopenharmony_ci short if_broot_bytes; /* bytes allocated for root */ 2662306a36Sopenharmony_ci int8_t if_format; /* format of this fork */ 2762306a36Sopenharmony_ci uint8_t if_needextents; /* extents have not been read */ 2862306a36Sopenharmony_ci}; 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci/* 3162306a36Sopenharmony_ci * Worst-case increase in the fork extent count when we're adding a single 3262306a36Sopenharmony_ci * extent to a fork and there's no possibility of splitting an existing mapping. 3362306a36Sopenharmony_ci */ 3462306a36Sopenharmony_ci#define XFS_IEXT_ADD_NOSPLIT_CNT (1) 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci/* 3762306a36Sopenharmony_ci * Punching out an extent from the middle of an existing extent can cause the 3862306a36Sopenharmony_ci * extent count to increase by 1. 3962306a36Sopenharmony_ci * i.e. | Old extent | Hole | Old extent | 4062306a36Sopenharmony_ci */ 4162306a36Sopenharmony_ci#define XFS_IEXT_PUNCH_HOLE_CNT (1) 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci/* 4462306a36Sopenharmony_ci * Adding/removing an xattr can cause XFS_DA_NODE_MAXDEPTH extents to 4562306a36Sopenharmony_ci * be added. One extra extent for dabtree in case a local attr is 4662306a36Sopenharmony_ci * large enough to cause a double split. It can also cause extent 4762306a36Sopenharmony_ci * count to increase proportional to the size of a remote xattr's 4862306a36Sopenharmony_ci * value. 4962306a36Sopenharmony_ci */ 5062306a36Sopenharmony_ci#define XFS_IEXT_ATTR_MANIP_CNT(rmt_blks) \ 5162306a36Sopenharmony_ci (XFS_DA_NODE_MAXDEPTH + max(1, rmt_blks)) 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci/* 5462306a36Sopenharmony_ci * A write to a sub-interval of an existing unwritten extent causes the original 5562306a36Sopenharmony_ci * extent to be split into 3 extents 5662306a36Sopenharmony_ci * i.e. | Unwritten | Real | Unwritten | 5762306a36Sopenharmony_ci * Hence extent count can increase by 2. 5862306a36Sopenharmony_ci */ 5962306a36Sopenharmony_ci#define XFS_IEXT_WRITE_UNWRITTEN_CNT (2) 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci/* 6362306a36Sopenharmony_ci * Moving an extent to data fork can cause a sub-interval of an existing extent 6462306a36Sopenharmony_ci * to be unmapped. This will increase extent count by 1. Mapping in the new 6562306a36Sopenharmony_ci * extent can increase the extent count by 1 again i.e. 6662306a36Sopenharmony_ci * | Old extent | New extent | Old extent | 6762306a36Sopenharmony_ci * Hence number of extents increases by 2. 6862306a36Sopenharmony_ci */ 6962306a36Sopenharmony_ci#define XFS_IEXT_REFLINK_END_COW_CNT (2) 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci/* 7262306a36Sopenharmony_ci * Removing an initial range of source/donor file's extent and adding a new 7362306a36Sopenharmony_ci * extent (from donor/source file) in its place will cause extent count to 7462306a36Sopenharmony_ci * increase by 1. 7562306a36Sopenharmony_ci */ 7662306a36Sopenharmony_ci#define XFS_IEXT_SWAP_RMAP_CNT (1) 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci/* 7962306a36Sopenharmony_ci * Fork handling. 8062306a36Sopenharmony_ci */ 8162306a36Sopenharmony_ci#define XFS_IFORK_MAXEXT(ip, w) \ 8262306a36Sopenharmony_ci (xfs_inode_fork_size(ip, w) / sizeof(xfs_bmbt_rec_t)) 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_cistatic inline bool xfs_ifork_has_extents(struct xfs_ifork *ifp) 8562306a36Sopenharmony_ci{ 8662306a36Sopenharmony_ci return ifp->if_format == XFS_DINODE_FMT_EXTENTS || 8762306a36Sopenharmony_ci ifp->if_format == XFS_DINODE_FMT_BTREE; 8862306a36Sopenharmony_ci} 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_cistatic inline xfs_extnum_t xfs_ifork_nextents(struct xfs_ifork *ifp) 9162306a36Sopenharmony_ci{ 9262306a36Sopenharmony_ci if (!ifp) 9362306a36Sopenharmony_ci return 0; 9462306a36Sopenharmony_ci return ifp->if_nextents; 9562306a36Sopenharmony_ci} 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_cistatic inline int8_t xfs_ifork_format(struct xfs_ifork *ifp) 9862306a36Sopenharmony_ci{ 9962306a36Sopenharmony_ci if (!ifp) 10062306a36Sopenharmony_ci return XFS_DINODE_FMT_EXTENTS; 10162306a36Sopenharmony_ci return ifp->if_format; 10262306a36Sopenharmony_ci} 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_cistatic inline xfs_extnum_t xfs_iext_max_nextents(bool has_large_extent_counts, 10562306a36Sopenharmony_ci int whichfork) 10662306a36Sopenharmony_ci{ 10762306a36Sopenharmony_ci switch (whichfork) { 10862306a36Sopenharmony_ci case XFS_DATA_FORK: 10962306a36Sopenharmony_ci case XFS_COW_FORK: 11062306a36Sopenharmony_ci if (has_large_extent_counts) 11162306a36Sopenharmony_ci return XFS_MAX_EXTCNT_DATA_FORK_LARGE; 11262306a36Sopenharmony_ci return XFS_MAX_EXTCNT_DATA_FORK_SMALL; 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci case XFS_ATTR_FORK: 11562306a36Sopenharmony_ci if (has_large_extent_counts) 11662306a36Sopenharmony_ci return XFS_MAX_EXTCNT_ATTR_FORK_LARGE; 11762306a36Sopenharmony_ci return XFS_MAX_EXTCNT_ATTR_FORK_SMALL; 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci default: 12062306a36Sopenharmony_ci ASSERT(0); 12162306a36Sopenharmony_ci return 0; 12262306a36Sopenharmony_ci } 12362306a36Sopenharmony_ci} 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_cistatic inline xfs_extnum_t 12662306a36Sopenharmony_cixfs_dfork_data_extents( 12762306a36Sopenharmony_ci struct xfs_dinode *dip) 12862306a36Sopenharmony_ci{ 12962306a36Sopenharmony_ci if (xfs_dinode_has_large_extent_counts(dip)) 13062306a36Sopenharmony_ci return be64_to_cpu(dip->di_big_nextents); 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci return be32_to_cpu(dip->di_nextents); 13362306a36Sopenharmony_ci} 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_cistatic inline xfs_extnum_t 13662306a36Sopenharmony_cixfs_dfork_attr_extents( 13762306a36Sopenharmony_ci struct xfs_dinode *dip) 13862306a36Sopenharmony_ci{ 13962306a36Sopenharmony_ci if (xfs_dinode_has_large_extent_counts(dip)) 14062306a36Sopenharmony_ci return be32_to_cpu(dip->di_big_anextents); 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci return be16_to_cpu(dip->di_anextents); 14362306a36Sopenharmony_ci} 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_cistatic inline xfs_extnum_t 14662306a36Sopenharmony_cixfs_dfork_nextents( 14762306a36Sopenharmony_ci struct xfs_dinode *dip, 14862306a36Sopenharmony_ci int whichfork) 14962306a36Sopenharmony_ci{ 15062306a36Sopenharmony_ci switch (whichfork) { 15162306a36Sopenharmony_ci case XFS_DATA_FORK: 15262306a36Sopenharmony_ci return xfs_dfork_data_extents(dip); 15362306a36Sopenharmony_ci case XFS_ATTR_FORK: 15462306a36Sopenharmony_ci return xfs_dfork_attr_extents(dip); 15562306a36Sopenharmony_ci default: 15662306a36Sopenharmony_ci ASSERT(0); 15762306a36Sopenharmony_ci break; 15862306a36Sopenharmony_ci } 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci return 0; 16162306a36Sopenharmony_ci} 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_civoid xfs_ifork_zap_attr(struct xfs_inode *ip); 16462306a36Sopenharmony_civoid xfs_ifork_init_attr(struct xfs_inode *ip, enum xfs_dinode_fmt format, 16562306a36Sopenharmony_ci xfs_extnum_t nextents); 16662306a36Sopenharmony_cistruct xfs_ifork *xfs_iext_state_to_fork(struct xfs_inode *ip, int state); 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ciint xfs_iformat_data_fork(struct xfs_inode *, struct xfs_dinode *); 16962306a36Sopenharmony_ciint xfs_iformat_attr_fork(struct xfs_inode *, struct xfs_dinode *); 17062306a36Sopenharmony_civoid xfs_iflush_fork(struct xfs_inode *, struct xfs_dinode *, 17162306a36Sopenharmony_ci struct xfs_inode_log_item *, int); 17262306a36Sopenharmony_civoid xfs_idestroy_fork(struct xfs_ifork *ifp); 17362306a36Sopenharmony_civoid xfs_idata_realloc(struct xfs_inode *ip, int64_t byte_diff, 17462306a36Sopenharmony_ci int whichfork); 17562306a36Sopenharmony_civoid xfs_iroot_realloc(struct xfs_inode *, int, int); 17662306a36Sopenharmony_ciint xfs_iread_extents(struct xfs_trans *, struct xfs_inode *, int); 17762306a36Sopenharmony_ciint xfs_iextents_copy(struct xfs_inode *, struct xfs_bmbt_rec *, 17862306a36Sopenharmony_ci int); 17962306a36Sopenharmony_civoid xfs_init_local_fork(struct xfs_inode *ip, int whichfork, 18062306a36Sopenharmony_ci const void *data, int64_t size); 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_cixfs_extnum_t xfs_iext_count(struct xfs_ifork *ifp); 18362306a36Sopenharmony_civoid xfs_iext_insert(struct xfs_inode *, struct xfs_iext_cursor *cur, 18462306a36Sopenharmony_ci struct xfs_bmbt_irec *, int); 18562306a36Sopenharmony_civoid xfs_iext_remove(struct xfs_inode *, struct xfs_iext_cursor *, 18662306a36Sopenharmony_ci int); 18762306a36Sopenharmony_civoid xfs_iext_destroy(struct xfs_ifork *); 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_cibool xfs_iext_lookup_extent(struct xfs_inode *ip, 19062306a36Sopenharmony_ci struct xfs_ifork *ifp, xfs_fileoff_t bno, 19162306a36Sopenharmony_ci struct xfs_iext_cursor *cur, 19262306a36Sopenharmony_ci struct xfs_bmbt_irec *gotp); 19362306a36Sopenharmony_cibool xfs_iext_lookup_extent_before(struct xfs_inode *ip, 19462306a36Sopenharmony_ci struct xfs_ifork *ifp, xfs_fileoff_t *end, 19562306a36Sopenharmony_ci struct xfs_iext_cursor *cur, 19662306a36Sopenharmony_ci struct xfs_bmbt_irec *gotp); 19762306a36Sopenharmony_cibool xfs_iext_get_extent(struct xfs_ifork *ifp, 19862306a36Sopenharmony_ci struct xfs_iext_cursor *cur, 19962306a36Sopenharmony_ci struct xfs_bmbt_irec *gotp); 20062306a36Sopenharmony_civoid xfs_iext_update_extent(struct xfs_inode *ip, int state, 20162306a36Sopenharmony_ci struct xfs_iext_cursor *cur, 20262306a36Sopenharmony_ci struct xfs_bmbt_irec *gotp); 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_civoid xfs_iext_first(struct xfs_ifork *, struct xfs_iext_cursor *); 20562306a36Sopenharmony_civoid xfs_iext_last(struct xfs_ifork *, struct xfs_iext_cursor *); 20662306a36Sopenharmony_civoid xfs_iext_next(struct xfs_ifork *, struct xfs_iext_cursor *); 20762306a36Sopenharmony_civoid xfs_iext_prev(struct xfs_ifork *, struct xfs_iext_cursor *); 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_cistatic inline bool xfs_iext_next_extent(struct xfs_ifork *ifp, 21062306a36Sopenharmony_ci struct xfs_iext_cursor *cur, struct xfs_bmbt_irec *gotp) 21162306a36Sopenharmony_ci{ 21262306a36Sopenharmony_ci xfs_iext_next(ifp, cur); 21362306a36Sopenharmony_ci return xfs_iext_get_extent(ifp, cur, gotp); 21462306a36Sopenharmony_ci} 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_cistatic inline bool xfs_iext_prev_extent(struct xfs_ifork *ifp, 21762306a36Sopenharmony_ci struct xfs_iext_cursor *cur, struct xfs_bmbt_irec *gotp) 21862306a36Sopenharmony_ci{ 21962306a36Sopenharmony_ci xfs_iext_prev(ifp, cur); 22062306a36Sopenharmony_ci return xfs_iext_get_extent(ifp, cur, gotp); 22162306a36Sopenharmony_ci} 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ci/* 22462306a36Sopenharmony_ci * Return the extent after cur in gotp without updating the cursor. 22562306a36Sopenharmony_ci */ 22662306a36Sopenharmony_cistatic inline bool xfs_iext_peek_next_extent(struct xfs_ifork *ifp, 22762306a36Sopenharmony_ci struct xfs_iext_cursor *cur, struct xfs_bmbt_irec *gotp) 22862306a36Sopenharmony_ci{ 22962306a36Sopenharmony_ci struct xfs_iext_cursor ncur = *cur; 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci xfs_iext_next(ifp, &ncur); 23262306a36Sopenharmony_ci return xfs_iext_get_extent(ifp, &ncur, gotp); 23362306a36Sopenharmony_ci} 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ci/* 23662306a36Sopenharmony_ci * Return the extent before cur in gotp without updating the cursor. 23762306a36Sopenharmony_ci */ 23862306a36Sopenharmony_cistatic inline bool xfs_iext_peek_prev_extent(struct xfs_ifork *ifp, 23962306a36Sopenharmony_ci struct xfs_iext_cursor *cur, struct xfs_bmbt_irec *gotp) 24062306a36Sopenharmony_ci{ 24162306a36Sopenharmony_ci struct xfs_iext_cursor ncur = *cur; 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci xfs_iext_prev(ifp, &ncur); 24462306a36Sopenharmony_ci return xfs_iext_get_extent(ifp, &ncur, gotp); 24562306a36Sopenharmony_ci} 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ci#define for_each_xfs_iext(ifp, ext, got) \ 24862306a36Sopenharmony_ci for (xfs_iext_first((ifp), (ext)); \ 24962306a36Sopenharmony_ci xfs_iext_get_extent((ifp), (ext), (got)); \ 25062306a36Sopenharmony_ci xfs_iext_next((ifp), (ext))) 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ciextern struct kmem_cache *xfs_ifork_cache; 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ciextern void xfs_ifork_init_cow(struct xfs_inode *ip); 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ciint xfs_ifork_verify_local_data(struct xfs_inode *ip); 25762306a36Sopenharmony_ciint xfs_ifork_verify_local_attr(struct xfs_inode *ip); 25862306a36Sopenharmony_ciint xfs_iext_count_may_overflow(struct xfs_inode *ip, int whichfork, 25962306a36Sopenharmony_ci int nr_to_add); 26062306a36Sopenharmony_ciint xfs_iext_count_upgrade(struct xfs_trans *tp, struct xfs_inode *ip, 26162306a36Sopenharmony_ci uint nr_to_add); 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci/* returns true if the fork has extents but they are not read in yet. */ 26462306a36Sopenharmony_cistatic inline bool xfs_need_iread_extents(const struct xfs_ifork *ifp) 26562306a36Sopenharmony_ci{ 26662306a36Sopenharmony_ci /* see xfs_iformat_{data,attr}_fork() for needextents semantics */ 26762306a36Sopenharmony_ci return smp_load_acquire(&ifp->if_needextents) != 0; 26862306a36Sopenharmony_ci} 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_ci#endif /* __XFS_INODE_FORK_H__ */ 271