162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (c) 2000,2002,2005 Silicon Graphics, Inc. 462306a36Sopenharmony_ci * Copyright (c) 2013 Red Hat, Inc. 562306a36Sopenharmony_ci * All Rights Reserved. 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci#ifndef __XFS_DA_BTREE_H__ 862306a36Sopenharmony_ci#define __XFS_DA_BTREE_H__ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_cistruct xfs_inode; 1162306a36Sopenharmony_cistruct xfs_trans; 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci/* 1462306a36Sopenharmony_ci * Directory/attribute geometry information. There will be one of these for each 1562306a36Sopenharmony_ci * data fork type, and it will be passed around via the xfs_da_args. Global 1662306a36Sopenharmony_ci * structures will be attached to the xfs_mount. 1762306a36Sopenharmony_ci */ 1862306a36Sopenharmony_cistruct xfs_da_geometry { 1962306a36Sopenharmony_ci unsigned int blksize; /* da block size in bytes */ 2062306a36Sopenharmony_ci unsigned int fsbcount; /* da block size in filesystem blocks */ 2162306a36Sopenharmony_ci uint8_t fsblog; /* log2 of _filesystem_ block size */ 2262306a36Sopenharmony_ci uint8_t blklog; /* log2 of da block size */ 2362306a36Sopenharmony_ci unsigned int node_hdr_size; /* danode header size in bytes */ 2462306a36Sopenharmony_ci unsigned int node_ents; /* # of entries in a danode */ 2562306a36Sopenharmony_ci unsigned int magicpct; /* 37% of block size in bytes */ 2662306a36Sopenharmony_ci xfs_dablk_t datablk; /* blockno of dir data v2 */ 2762306a36Sopenharmony_ci unsigned int leaf_hdr_size; /* dir2 leaf header size */ 2862306a36Sopenharmony_ci unsigned int leaf_max_ents; /* # of entries in dir2 leaf */ 2962306a36Sopenharmony_ci xfs_dablk_t leafblk; /* blockno of leaf data v2 */ 3062306a36Sopenharmony_ci unsigned int free_hdr_size; /* dir2 free header size */ 3162306a36Sopenharmony_ci unsigned int free_max_bests; /* # of bests entries in dir2 free */ 3262306a36Sopenharmony_ci xfs_dablk_t freeblk; /* blockno of free data v2 */ 3362306a36Sopenharmony_ci xfs_extnum_t max_extents; /* Max. extents in corresponding fork */ 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci xfs_dir2_data_aoff_t data_first_offset; 3662306a36Sopenharmony_ci size_t data_entry_offset; 3762306a36Sopenharmony_ci}; 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci/*======================================================================== 4062306a36Sopenharmony_ci * Btree searching and modification structure definitions. 4162306a36Sopenharmony_ci *========================================================================*/ 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci/* 4462306a36Sopenharmony_ci * Search comparison results 4562306a36Sopenharmony_ci */ 4662306a36Sopenharmony_cienum xfs_dacmp { 4762306a36Sopenharmony_ci XFS_CMP_DIFFERENT, /* names are completely different */ 4862306a36Sopenharmony_ci XFS_CMP_EXACT, /* names are exactly the same */ 4962306a36Sopenharmony_ci XFS_CMP_CASE /* names are same but differ in case */ 5062306a36Sopenharmony_ci}; 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci/* 5362306a36Sopenharmony_ci * Structure to ease passing around component names. 5462306a36Sopenharmony_ci */ 5562306a36Sopenharmony_citypedef struct xfs_da_args { 5662306a36Sopenharmony_ci struct xfs_da_geometry *geo; /* da block geometry */ 5762306a36Sopenharmony_ci const uint8_t *name; /* string (maybe not NULL terminated) */ 5862306a36Sopenharmony_ci int namelen; /* length of string (maybe no NULL) */ 5962306a36Sopenharmony_ci uint8_t filetype; /* filetype of inode for directories */ 6062306a36Sopenharmony_ci void *value; /* set of bytes (maybe contain NULLs) */ 6162306a36Sopenharmony_ci int valuelen; /* length of value */ 6262306a36Sopenharmony_ci unsigned int attr_filter; /* XFS_ATTR_{ROOT,SECURE,INCOMPLETE} */ 6362306a36Sopenharmony_ci unsigned int attr_flags; /* XATTR_{CREATE,REPLACE} */ 6462306a36Sopenharmony_ci xfs_dahash_t hashval; /* hash value of name */ 6562306a36Sopenharmony_ci xfs_ino_t inumber; /* input/output inode number */ 6662306a36Sopenharmony_ci struct xfs_inode *dp; /* directory inode to manipulate */ 6762306a36Sopenharmony_ci struct xfs_trans *trans; /* current trans (changes over time) */ 6862306a36Sopenharmony_ci xfs_extlen_t total; /* total blocks needed, for 1st bmap */ 6962306a36Sopenharmony_ci int whichfork; /* data or attribute fork */ 7062306a36Sopenharmony_ci xfs_dablk_t blkno; /* blkno of attr leaf of interest */ 7162306a36Sopenharmony_ci int index; /* index of attr of interest in blk */ 7262306a36Sopenharmony_ci xfs_dablk_t rmtblkno; /* remote attr value starting blkno */ 7362306a36Sopenharmony_ci int rmtblkcnt; /* remote attr value block count */ 7462306a36Sopenharmony_ci int rmtvaluelen; /* remote attr value length in bytes */ 7562306a36Sopenharmony_ci xfs_dablk_t blkno2; /* blkno of 2nd attr leaf of interest */ 7662306a36Sopenharmony_ci int index2; /* index of 2nd attr in blk */ 7762306a36Sopenharmony_ci xfs_dablk_t rmtblkno2; /* remote attr value starting blkno */ 7862306a36Sopenharmony_ci int rmtblkcnt2; /* remote attr value block count */ 7962306a36Sopenharmony_ci int rmtvaluelen2; /* remote attr value length in bytes */ 8062306a36Sopenharmony_ci uint32_t op_flags; /* operation flags */ 8162306a36Sopenharmony_ci enum xfs_dacmp cmpresult; /* name compare result for lookups */ 8262306a36Sopenharmony_ci} xfs_da_args_t; 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci/* 8562306a36Sopenharmony_ci * Operation flags: 8662306a36Sopenharmony_ci */ 8762306a36Sopenharmony_ci#define XFS_DA_OP_JUSTCHECK (1u << 0) /* check for ok with no space */ 8862306a36Sopenharmony_ci#define XFS_DA_OP_REPLACE (1u << 1) /* this is an atomic replace op */ 8962306a36Sopenharmony_ci#define XFS_DA_OP_ADDNAME (1u << 2) /* this is an add operation */ 9062306a36Sopenharmony_ci#define XFS_DA_OP_OKNOENT (1u << 3) /* lookup op, ENOENT ok, else die */ 9162306a36Sopenharmony_ci#define XFS_DA_OP_CILOOKUP (1u << 4) /* lookup returns CI name if found */ 9262306a36Sopenharmony_ci#define XFS_DA_OP_NOTIME (1u << 5) /* don't update inode timestamps */ 9362306a36Sopenharmony_ci#define XFS_DA_OP_REMOVE (1u << 6) /* this is a remove operation */ 9462306a36Sopenharmony_ci#define XFS_DA_OP_RECOVERY (1u << 7) /* Log recovery operation */ 9562306a36Sopenharmony_ci#define XFS_DA_OP_LOGGED (1u << 8) /* Use intent items to track op */ 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci#define XFS_DA_OP_FLAGS \ 9862306a36Sopenharmony_ci { XFS_DA_OP_JUSTCHECK, "JUSTCHECK" }, \ 9962306a36Sopenharmony_ci { XFS_DA_OP_REPLACE, "REPLACE" }, \ 10062306a36Sopenharmony_ci { XFS_DA_OP_ADDNAME, "ADDNAME" }, \ 10162306a36Sopenharmony_ci { XFS_DA_OP_OKNOENT, "OKNOENT" }, \ 10262306a36Sopenharmony_ci { XFS_DA_OP_CILOOKUP, "CILOOKUP" }, \ 10362306a36Sopenharmony_ci { XFS_DA_OP_NOTIME, "NOTIME" }, \ 10462306a36Sopenharmony_ci { XFS_DA_OP_REMOVE, "REMOVE" }, \ 10562306a36Sopenharmony_ci { XFS_DA_OP_RECOVERY, "RECOVERY" }, \ 10662306a36Sopenharmony_ci { XFS_DA_OP_LOGGED, "LOGGED" } 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci/* 10962306a36Sopenharmony_ci * Storage for holding state during Btree searches and split/join ops. 11062306a36Sopenharmony_ci * 11162306a36Sopenharmony_ci * Only need space for 5 intermediate nodes. With a minimum of 62-way 11262306a36Sopenharmony_ci * fanout to the Btree, we can support over 900 million directory blocks, 11362306a36Sopenharmony_ci * which is slightly more than enough. 11462306a36Sopenharmony_ci */ 11562306a36Sopenharmony_citypedef struct xfs_da_state_blk { 11662306a36Sopenharmony_ci struct xfs_buf *bp; /* buffer containing block */ 11762306a36Sopenharmony_ci xfs_dablk_t blkno; /* filesystem blkno of buffer */ 11862306a36Sopenharmony_ci xfs_daddr_t disk_blkno; /* on-disk blkno (in BBs) of buffer */ 11962306a36Sopenharmony_ci int index; /* relevant index into block */ 12062306a36Sopenharmony_ci xfs_dahash_t hashval; /* last hash value in block */ 12162306a36Sopenharmony_ci int magic; /* blk's magic number, ie: blk type */ 12262306a36Sopenharmony_ci} xfs_da_state_blk_t; 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_citypedef struct xfs_da_state_path { 12562306a36Sopenharmony_ci int active; /* number of active levels */ 12662306a36Sopenharmony_ci xfs_da_state_blk_t blk[XFS_DA_NODE_MAXDEPTH]; 12762306a36Sopenharmony_ci} xfs_da_state_path_t; 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_citypedef struct xfs_da_state { 13062306a36Sopenharmony_ci xfs_da_args_t *args; /* filename arguments */ 13162306a36Sopenharmony_ci struct xfs_mount *mp; /* filesystem mount point */ 13262306a36Sopenharmony_ci xfs_da_state_path_t path; /* search/split paths */ 13362306a36Sopenharmony_ci xfs_da_state_path_t altpath; /* alternate path for join */ 13462306a36Sopenharmony_ci unsigned char inleaf; /* insert into 1->lf, 0->splf */ 13562306a36Sopenharmony_ci unsigned char extravalid; /* T/F: extrablk is in use */ 13662306a36Sopenharmony_ci unsigned char extraafter; /* T/F: extrablk is after new */ 13762306a36Sopenharmony_ci xfs_da_state_blk_t extrablk; /* for double-splits on leaves */ 13862306a36Sopenharmony_ci /* for dirv2 extrablk is data */ 13962306a36Sopenharmony_ci} xfs_da_state_t; 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci/* 14262306a36Sopenharmony_ci * In-core version of the node header to abstract the differences in the v2 and 14362306a36Sopenharmony_ci * v3 disk format of the headers. Callers need to convert to/from disk format as 14462306a36Sopenharmony_ci * appropriate. 14562306a36Sopenharmony_ci */ 14662306a36Sopenharmony_cistruct xfs_da3_icnode_hdr { 14762306a36Sopenharmony_ci uint32_t forw; 14862306a36Sopenharmony_ci uint32_t back; 14962306a36Sopenharmony_ci uint16_t magic; 15062306a36Sopenharmony_ci uint16_t count; 15162306a36Sopenharmony_ci uint16_t level; 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci /* 15462306a36Sopenharmony_ci * Pointer to the on-disk format entries, which are behind the 15562306a36Sopenharmony_ci * variable size (v4 vs v5) header in the on-disk block. 15662306a36Sopenharmony_ci */ 15762306a36Sopenharmony_ci struct xfs_da_node_entry *btree; 15862306a36Sopenharmony_ci}; 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci/* 16162306a36Sopenharmony_ci * Utility macros to aid in logging changed structure fields. 16262306a36Sopenharmony_ci */ 16362306a36Sopenharmony_ci#define XFS_DA_LOGOFF(BASE, ADDR) ((char *)(ADDR) - (char *)(BASE)) 16462306a36Sopenharmony_ci#define XFS_DA_LOGRANGE(BASE, ADDR, SIZE) \ 16562306a36Sopenharmony_ci (uint)(XFS_DA_LOGOFF(BASE, ADDR)), \ 16662306a36Sopenharmony_ci (uint)(XFS_DA_LOGOFF(BASE, ADDR)+(SIZE)-1) 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci/*======================================================================== 16962306a36Sopenharmony_ci * Function prototypes. 17062306a36Sopenharmony_ci *========================================================================*/ 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci/* 17362306a36Sopenharmony_ci * Routines used for growing the Btree. 17462306a36Sopenharmony_ci */ 17562306a36Sopenharmony_ciint xfs_da3_node_create(struct xfs_da_args *args, xfs_dablk_t blkno, 17662306a36Sopenharmony_ci int level, struct xfs_buf **bpp, int whichfork); 17762306a36Sopenharmony_ciint xfs_da3_split(xfs_da_state_t *state); 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci/* 18062306a36Sopenharmony_ci * Routines used for shrinking the Btree. 18162306a36Sopenharmony_ci */ 18262306a36Sopenharmony_ciint xfs_da3_join(xfs_da_state_t *state); 18362306a36Sopenharmony_civoid xfs_da3_fixhashpath(struct xfs_da_state *state, 18462306a36Sopenharmony_ci struct xfs_da_state_path *path_to_to_fix); 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci/* 18762306a36Sopenharmony_ci * Routines used for finding things in the Btree. 18862306a36Sopenharmony_ci */ 18962306a36Sopenharmony_ciint xfs_da3_node_lookup_int(xfs_da_state_t *state, int *result); 19062306a36Sopenharmony_ciint xfs_da3_path_shift(xfs_da_state_t *state, xfs_da_state_path_t *path, 19162306a36Sopenharmony_ci int forward, int release, int *result); 19262306a36Sopenharmony_ci/* 19362306a36Sopenharmony_ci * Utility routines. 19462306a36Sopenharmony_ci */ 19562306a36Sopenharmony_ciint xfs_da3_blk_link(xfs_da_state_t *state, xfs_da_state_blk_t *old_blk, 19662306a36Sopenharmony_ci xfs_da_state_blk_t *new_blk); 19762306a36Sopenharmony_ciint xfs_da3_node_read(struct xfs_trans *tp, struct xfs_inode *dp, 19862306a36Sopenharmony_ci xfs_dablk_t bno, struct xfs_buf **bpp, int whichfork); 19962306a36Sopenharmony_ciint xfs_da3_node_read_mapped(struct xfs_trans *tp, struct xfs_inode *dp, 20062306a36Sopenharmony_ci xfs_daddr_t mappedbno, struct xfs_buf **bpp, 20162306a36Sopenharmony_ci int whichfork); 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci/* 20462306a36Sopenharmony_ci * Utility routines. 20562306a36Sopenharmony_ci */ 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci#define XFS_DABUF_MAP_HOLE_OK (1u << 0) 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ciint xfs_da_grow_inode(xfs_da_args_t *args, xfs_dablk_t *new_blkno); 21062306a36Sopenharmony_ciint xfs_da_grow_inode_int(struct xfs_da_args *args, xfs_fileoff_t *bno, 21162306a36Sopenharmony_ci int count); 21262306a36Sopenharmony_ciint xfs_da_get_buf(struct xfs_trans *trans, struct xfs_inode *dp, 21362306a36Sopenharmony_ci xfs_dablk_t bno, struct xfs_buf **bp, int whichfork); 21462306a36Sopenharmony_ciint xfs_da_read_buf(struct xfs_trans *trans, struct xfs_inode *dp, 21562306a36Sopenharmony_ci xfs_dablk_t bno, unsigned int flags, struct xfs_buf **bpp, 21662306a36Sopenharmony_ci int whichfork, const struct xfs_buf_ops *ops); 21762306a36Sopenharmony_ciint xfs_da_reada_buf(struct xfs_inode *dp, xfs_dablk_t bno, 21862306a36Sopenharmony_ci unsigned int flags, int whichfork, 21962306a36Sopenharmony_ci const struct xfs_buf_ops *ops); 22062306a36Sopenharmony_ciint xfs_da_shrink_inode(xfs_da_args_t *args, xfs_dablk_t dead_blkno, 22162306a36Sopenharmony_ci struct xfs_buf *dead_buf); 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ciuint xfs_da_hashname(const uint8_t *name_string, int name_length); 22462306a36Sopenharmony_cienum xfs_dacmp xfs_da_compname(struct xfs_da_args *args, 22562306a36Sopenharmony_ci const unsigned char *name, int len); 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_cistruct xfs_da_state *xfs_da_state_alloc(struct xfs_da_args *args); 22962306a36Sopenharmony_civoid xfs_da_state_free(xfs_da_state_t *state); 23062306a36Sopenharmony_civoid xfs_da_state_reset(struct xfs_da_state *state, struct xfs_da_args *args); 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_civoid xfs_da3_node_hdr_from_disk(struct xfs_mount *mp, 23362306a36Sopenharmony_ci struct xfs_da3_icnode_hdr *to, struct xfs_da_intnode *from); 23462306a36Sopenharmony_civoid xfs_da3_node_hdr_to_disk(struct xfs_mount *mp, 23562306a36Sopenharmony_ci struct xfs_da_intnode *to, struct xfs_da3_icnode_hdr *from); 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ciextern struct kmem_cache *xfs_da_state_cache; 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci#endif /* __XFS_DA_BTREE_H__ */ 240