162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * linux/fs/hfs/btree.h 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2001 662306a36Sopenharmony_ci * Brad Boyer (flar@allandria.com) 762306a36Sopenharmony_ci * (C) 2003 Ardis Technologies <roman@ardistech.com> 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include "hfs_fs.h" 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_citypedef int (*btree_keycmp)(const btree_key *, const btree_key *); 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci#define NODE_HASH_SIZE 256 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci/* B-tree mutex nested subclasses */ 1762306a36Sopenharmony_cienum hfs_btree_mutex_classes { 1862306a36Sopenharmony_ci CATALOG_BTREE_MUTEX, 1962306a36Sopenharmony_ci EXTENTS_BTREE_MUTEX, 2062306a36Sopenharmony_ci ATTR_BTREE_MUTEX, 2162306a36Sopenharmony_ci}; 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci/* A HFS BTree held in memory */ 2462306a36Sopenharmony_cistruct hfs_btree { 2562306a36Sopenharmony_ci struct super_block *sb; 2662306a36Sopenharmony_ci struct inode *inode; 2762306a36Sopenharmony_ci btree_keycmp keycmp; 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci u32 cnid; 3062306a36Sopenharmony_ci u32 root; 3162306a36Sopenharmony_ci u32 leaf_count; 3262306a36Sopenharmony_ci u32 leaf_head; 3362306a36Sopenharmony_ci u32 leaf_tail; 3462306a36Sopenharmony_ci u32 node_count; 3562306a36Sopenharmony_ci u32 free_nodes; 3662306a36Sopenharmony_ci u32 attributes; 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci unsigned int node_size; 3962306a36Sopenharmony_ci unsigned int node_size_shift; 4062306a36Sopenharmony_ci unsigned int max_key_len; 4162306a36Sopenharmony_ci unsigned int depth; 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci //unsigned int map1_size, map_size; 4462306a36Sopenharmony_ci struct mutex tree_lock; 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci unsigned int pages_per_bnode; 4762306a36Sopenharmony_ci spinlock_t hash_lock; 4862306a36Sopenharmony_ci struct hfs_bnode *node_hash[NODE_HASH_SIZE]; 4962306a36Sopenharmony_ci int node_hash_cnt; 5062306a36Sopenharmony_ci}; 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci/* A HFS BTree node in memory */ 5362306a36Sopenharmony_cistruct hfs_bnode { 5462306a36Sopenharmony_ci struct hfs_btree *tree; 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci u32 prev; 5762306a36Sopenharmony_ci u32 this; 5862306a36Sopenharmony_ci u32 next; 5962306a36Sopenharmony_ci u32 parent; 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci u16 num_recs; 6262306a36Sopenharmony_ci u8 type; 6362306a36Sopenharmony_ci u8 height; 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci struct hfs_bnode *next_hash; 6662306a36Sopenharmony_ci unsigned long flags; 6762306a36Sopenharmony_ci wait_queue_head_t lock_wq; 6862306a36Sopenharmony_ci atomic_t refcnt; 6962306a36Sopenharmony_ci unsigned int page_offset; 7062306a36Sopenharmony_ci struct page *page[]; 7162306a36Sopenharmony_ci}; 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci#define HFS_BNODE_ERROR 0 7462306a36Sopenharmony_ci#define HFS_BNODE_NEW 1 7562306a36Sopenharmony_ci#define HFS_BNODE_DELETED 2 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_cistruct hfs_find_data { 7862306a36Sopenharmony_ci btree_key *key; 7962306a36Sopenharmony_ci btree_key *search_key; 8062306a36Sopenharmony_ci struct hfs_btree *tree; 8162306a36Sopenharmony_ci struct hfs_bnode *bnode; 8262306a36Sopenharmony_ci int record; 8362306a36Sopenharmony_ci int keyoffset, keylength; 8462306a36Sopenharmony_ci int entryoffset, entrylength; 8562306a36Sopenharmony_ci}; 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci/* btree.c */ 8962306a36Sopenharmony_ciextern struct hfs_btree *hfs_btree_open(struct super_block *, u32, btree_keycmp); 9062306a36Sopenharmony_ciextern void hfs_btree_close(struct hfs_btree *); 9162306a36Sopenharmony_ciextern void hfs_btree_write(struct hfs_btree *); 9262306a36Sopenharmony_ciextern int hfs_bmap_reserve(struct hfs_btree *, int); 9362306a36Sopenharmony_ciextern struct hfs_bnode * hfs_bmap_alloc(struct hfs_btree *); 9462306a36Sopenharmony_ciextern void hfs_bmap_free(struct hfs_bnode *node); 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci/* bnode.c */ 9762306a36Sopenharmony_ciextern void hfs_bnode_read(struct hfs_bnode *, void *, int, int); 9862306a36Sopenharmony_ciextern u16 hfs_bnode_read_u16(struct hfs_bnode *, int); 9962306a36Sopenharmony_ciextern u8 hfs_bnode_read_u8(struct hfs_bnode *, int); 10062306a36Sopenharmony_ciextern void hfs_bnode_read_key(struct hfs_bnode *, void *, int); 10162306a36Sopenharmony_ciextern void hfs_bnode_write(struct hfs_bnode *, void *, int, int); 10262306a36Sopenharmony_ciextern void hfs_bnode_write_u16(struct hfs_bnode *, int, u16); 10362306a36Sopenharmony_ciextern void hfs_bnode_write_u8(struct hfs_bnode *, int, u8); 10462306a36Sopenharmony_ciextern void hfs_bnode_clear(struct hfs_bnode *, int, int); 10562306a36Sopenharmony_ciextern void hfs_bnode_copy(struct hfs_bnode *, int, 10662306a36Sopenharmony_ci struct hfs_bnode *, int, int); 10762306a36Sopenharmony_ciextern void hfs_bnode_move(struct hfs_bnode *, int, int, int); 10862306a36Sopenharmony_ciextern void hfs_bnode_dump(struct hfs_bnode *); 10962306a36Sopenharmony_ciextern void hfs_bnode_unlink(struct hfs_bnode *); 11062306a36Sopenharmony_ciextern struct hfs_bnode *hfs_bnode_findhash(struct hfs_btree *, u32); 11162306a36Sopenharmony_ciextern struct hfs_bnode *hfs_bnode_find(struct hfs_btree *, u32); 11262306a36Sopenharmony_ciextern void hfs_bnode_unhash(struct hfs_bnode *); 11362306a36Sopenharmony_ciextern void hfs_bnode_free(struct hfs_bnode *); 11462306a36Sopenharmony_ciextern struct hfs_bnode *hfs_bnode_create(struct hfs_btree *, u32); 11562306a36Sopenharmony_ciextern void hfs_bnode_get(struct hfs_bnode *); 11662306a36Sopenharmony_ciextern void hfs_bnode_put(struct hfs_bnode *); 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci/* brec.c */ 11962306a36Sopenharmony_ciextern u16 hfs_brec_lenoff(struct hfs_bnode *, u16, u16 *); 12062306a36Sopenharmony_ciextern u16 hfs_brec_keylen(struct hfs_bnode *, u16); 12162306a36Sopenharmony_ciextern int hfs_brec_insert(struct hfs_find_data *, void *, int); 12262306a36Sopenharmony_ciextern int hfs_brec_remove(struct hfs_find_data *); 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci/* bfind.c */ 12562306a36Sopenharmony_ciextern int hfs_find_init(struct hfs_btree *, struct hfs_find_data *); 12662306a36Sopenharmony_ciextern void hfs_find_exit(struct hfs_find_data *); 12762306a36Sopenharmony_ciextern int __hfs_brec_find(struct hfs_bnode *, struct hfs_find_data *); 12862306a36Sopenharmony_ciextern int hfs_brec_find(struct hfs_find_data *); 12962306a36Sopenharmony_ciextern int hfs_brec_read(struct hfs_find_data *, void *, int); 13062306a36Sopenharmony_ciextern int hfs_brec_goto(struct hfs_find_data *, int); 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_cistruct hfs_bnode_desc { 13462306a36Sopenharmony_ci __be32 next; /* (V) Number of the next node at this level */ 13562306a36Sopenharmony_ci __be32 prev; /* (V) Number of the prev node at this level */ 13662306a36Sopenharmony_ci u8 type; /* (F) The type of node */ 13762306a36Sopenharmony_ci u8 height; /* (F) The level of this node (leaves=1) */ 13862306a36Sopenharmony_ci __be16 num_recs; /* (V) The number of records in this node */ 13962306a36Sopenharmony_ci u16 reserved; 14062306a36Sopenharmony_ci} __packed; 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci#define HFS_NODE_INDEX 0x00 /* An internal (index) node */ 14362306a36Sopenharmony_ci#define HFS_NODE_HEADER 0x01 /* The tree header node (node 0) */ 14462306a36Sopenharmony_ci#define HFS_NODE_MAP 0x02 /* Holds part of the bitmap of used nodes */ 14562306a36Sopenharmony_ci#define HFS_NODE_LEAF 0xFF /* A leaf (ndNHeight==1) node */ 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_cistruct hfs_btree_header_rec { 14862306a36Sopenharmony_ci __be16 depth; /* (V) The number of levels in this B-tree */ 14962306a36Sopenharmony_ci __be32 root; /* (V) The node number of the root node */ 15062306a36Sopenharmony_ci __be32 leaf_count; /* (V) The number of leaf records */ 15162306a36Sopenharmony_ci __be32 leaf_head; /* (V) The number of the first leaf node */ 15262306a36Sopenharmony_ci __be32 leaf_tail; /* (V) The number of the last leaf node */ 15362306a36Sopenharmony_ci __be16 node_size; /* (F) The number of bytes in a node (=512) */ 15462306a36Sopenharmony_ci __be16 max_key_len; /* (F) The length of a key in an index node */ 15562306a36Sopenharmony_ci __be32 node_count; /* (V) The total number of nodes */ 15662306a36Sopenharmony_ci __be32 free_nodes; /* (V) The number of unused nodes */ 15762306a36Sopenharmony_ci u16 reserved1; 15862306a36Sopenharmony_ci __be32 clump_size; /* (F) clump size. not usually used. */ 15962306a36Sopenharmony_ci u8 btree_type; /* (F) BTree type */ 16062306a36Sopenharmony_ci u8 reserved2; 16162306a36Sopenharmony_ci __be32 attributes; /* (F) attributes */ 16262306a36Sopenharmony_ci u32 reserved3[16]; 16362306a36Sopenharmony_ci} __packed; 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci#define BTREE_ATTR_BADCLOSE 0x00000001 /* b-tree not closed properly. not 16662306a36Sopenharmony_ci used by hfsplus. */ 16762306a36Sopenharmony_ci#define HFS_TREE_BIGKEYS 0x00000002 /* key length is u16 instead of u8. 16862306a36Sopenharmony_ci used by hfsplus. */ 16962306a36Sopenharmony_ci#define HFS_TREE_VARIDXKEYS 0x00000004 /* variable key length instead of 17062306a36Sopenharmony_ci max key length. use din catalog 17162306a36Sopenharmony_ci b-tree but not in extents 17262306a36Sopenharmony_ci b-tree (hfsplus). */ 173