/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _SYS_ZAP_LEAF_H #define _SYS_ZAP_LEAF_H #pragma ident "%Z%%M% %I% %E% SMI" #ifdef __cplusplus extern "C" { #endif struct zap; #define ZAP_LEAF_MAGIC 0x2AB1EAF /* chunk size = 24 bytes */ #define ZAP_LEAF_NUMCHUNKS 5118 #define ZAP_LEAF_ARRAY_BYTES 21 #define ZAP_LEAF_HASH_SHIFT 12 #define ZAP_LEAF_HASH_NUMENTRIES (1 << ZAP_LEAF_HASH_SHIFT) #define ZAP_LLA_DATA_BYTES ((1 << ZAP_BLOCK_SHIFT) - 16) typedef enum zap_entry_type { ZAP_LEAF_FREE = 253, ZAP_LEAF_ENTRY = 252, ZAP_LEAF_ARRAY = 251, ZAP_LEAF_TYPE_MAX = 250 } zap_entry_type_t; /* * TAKE NOTE: * If zap_leaf_phys_t is modified, zap_leaf_byteswap() must be modified. */ typedef struct zap_leaf_phys { struct zap_leaf_header { uint64_t lhr_block_type; /* ZBT_LEAF */ uint64_t lhr_next; /* next block in leaf chain */ uint64_t lhr_prefix; uint32_t lhr_magic; /* ZAP_LEAF_MAGIC */ uint16_t lhr_nfree; /* number free chunks */ uint16_t lhr_nentries; /* number of entries */ uint16_t lhr_prefix_len; #define lh_block_type l_phys->l_hdr.lhr_block_type #define lh_magic l_phys->l_hdr.lhr_magic #define lh_next l_phys->l_hdr.lhr_next #define lh_prefix l_phys->l_hdr.lhr_prefix #define lh_nfree l_phys->l_hdr.lhr_nfree #define lh_prefix_len l_phys->l_hdr.lhr_prefix_len #define lh_nentries l_phys->l_hdr.lhr_nentries /* above is accessable to zap, below is zap_leaf private */ uint16_t lh_freelist; /* chunk head of free list */ uint8_t lh_pad2[12]; } l_hdr; /* 2 24-byte chunks */ uint16_t l_hash[ZAP_LEAF_HASH_NUMENTRIES]; /* 170 24-byte chunks plus 16 bytes leftover space */ union zap_leaf_chunk { struct zap_leaf_entry { uint8_t le_type; /* always ZAP_LEAF_ENTRY */ uint8_t le_int_size; /* size of ints */ uint16_t le_next; /* next entry in hash chain */ uint16_t le_name_chunk; /* first chunk of the name */ uint16_t le_name_length; /* bytes in name, incl null */ uint16_t le_value_chunk; /* first chunk of the value */ uint16_t le_value_length; /* value length in ints */ uint32_t le_cd; /* collision differentiator */ uint64_t le_hash; /* hash value of the name */ } l_entry; struct zap_leaf_array { uint8_t la_type; uint8_t la_array[ZAP_LEAF_ARRAY_BYTES]; uint16_t la_next; /* next blk or CHAIN_END */ } l_array; struct zap_leaf_free { uint8_t lf_type; /* always ZAP_LEAF_FREE */ uint8_t lf_pad[ZAP_LEAF_ARRAY_BYTES]; uint16_t lf_next; /* next in free list, or CHAIN_END */ } l_free; } l_chunk[ZAP_LEAF_NUMCHUNKS]; } zap_leaf_phys_t; typedef struct zap_leaf { krwlock_t l_rwlock; /* only used on head of chain */ uint64_t l_blkid; /* 1<<ZAP_BLOCK_SHIFT byte block off */ struct zap_leaf *l_next; /* next in chain */ dmu_buf_t *l_dbuf; zap_leaf_phys_t *l_phys; } zap_leaf_t; typedef struct zap_entry_handle { /* below is set by zap_leaf.c and is public to zap.c */ uint64_t zeh_num_integers; uint64_t zeh_hash; uint32_t zeh_cd; uint8_t zeh_integer_size; /* below is private to zap_leaf.c */ uint16_t zeh_fakechunk; uint16_t *zeh_chunkp; zap_leaf_t *zeh_head_leaf; zap_leaf_t *zeh_found_leaf; } zap_entry_handle_t; /* * Return a handle to the named entry, or ENOENT if not found. The hash * value must equal zap_hash(name). */ extern int zap_leaf_lookup(zap_leaf_t *l, const char *name, uint64_t h, zap_entry_handle_t *zeh); /* * Return a handle to the entry with this hash+cd, or the entry with the * next closest hash+cd. */ extern int zap_leaf_lookup_closest(zap_leaf_t *l, uint64_t hash, uint32_t cd, zap_entry_handle_t *zeh); /* * Read the first num_integers in the attribute. Integer size * conversion will be done without sign extension. Return EINVAL if * integer_size is too small. Return EOVERFLOW if there are more than * num_integers in the attribute. */ extern int zap_entry_read(const zap_entry_handle_t *zeh, uint8_t integer_size, uint64_t num_integers, void *buf); extern int zap_entry_read_name(const zap_entry_handle_t *zeh, uint16_t buflen, char *buf); /* * Replace the value of an existing entry. * * zap_entry_update may fail if it runs out of space (ENOSPC). */ extern int zap_entry_update(zap_entry_handle_t *zeh, uint8_t integer_size, uint64_t num_integers, const void *buf); /* * Remove an entry. */ extern void zap_entry_remove(zap_entry_handle_t *zeh); /* * Create an entry. An equal entry must not exist, and this entry must * belong in this leaf (according to its hash value). Fills in the * entry handle on success. Returns 0 on success or ENOSPC on failure. */ extern int zap_entry_create(zap_leaf_t *l, const char *name, uint64_t h, uint32_t cd, uint8_t integer_size, uint64_t num_integers, const void *buf, zap_entry_handle_t *zeh); /* * Other stuff. */ extern void zap_leaf_init(zap_leaf_t *l); extern void zap_leaf_byteswap(zap_leaf_phys_t *buf); extern zap_leaf_t *zap_leaf_split(struct zap *zap, zap_leaf_t *l, dmu_tx_t *tx); extern int zap_leaf_merge(zap_leaf_t *l, zap_leaf_t *sibling); extern zap_leaf_t *zap_leaf_chainmore(zap_leaf_t *l, zap_leaf_t *nl); extern int zap_leaf_advance(zap_leaf_t *l, zap_cursor_t *zc); extern void zap_stats_leaf(zap_t *zap, zap_leaf_t *l, zap_stats_t *zs); #ifdef __cplusplus } #endif #endif /* _SYS_ZAP_LEAF_H */