blob: e0dd69f5de29dd0dde45e8790ac789d50fec5c2b [file] [log] [blame]
#ifndef TUX3_DLEAF_H
#define TUX3_DLEAF_H
/* version:10, count:6, block:48 */
struct diskextent { __be64 block_count_version; };
#define MAX_GROUP_ENTRIES 255
/* count:8, keyhi:24 */
struct group { __be32 count_and_keyhi; };
/* limit:8, keylo:24 */
struct entry { __be32 limit_and_keylo; };
struct dleaf { __be16 magic, groups, free, used; struct diskextent table[]; };
/* Maximum size of one extent on dleaf. */
#define DLEAF_MAX_EXTENT_SIZE \
(sizeof(struct group)+sizeof(struct entry)+sizeof(struct diskextent))
struct dwalk {
struct dleaf *leaf;
struct group *group, *gstop, *gdict;
struct entry *entry, *estop;
struct diskextent *exbase, *extent, *exstop;
struct {
struct group group;
struct entry entry;
int used, free, groups;
} mock;
};
/* group wrappers */
static inline struct group make_group(tuxkey_t keyhi, unsigned count)
{
return (struct group){ cpu_to_be32(keyhi | (count << 24)) };
}
static inline unsigned group_keyhi(struct group *group)
{
return be32_to_cpup((__be32 *)group) & 0xffffff;
}
static inline unsigned group_count(struct group *group)
{
return *(unsigned char *)group;
}
static inline void set_group_count(struct group *group, int n)
{
*(unsigned char *)group = n;
}
static inline void inc_group_count(struct group *group, int n)
{
*(unsigned char *)group += n;
}
/* entry wrappers */
static inline struct entry make_entry(tuxkey_t keylo, unsigned limit)
{
return (struct entry){ cpu_to_be32(keylo | (limit << 24)) };
}
static inline unsigned entry_keylo(struct entry *entry)
{
return be32_to_cpup((__be32 *)entry) & ~(-1 << 24);
}
static inline unsigned entry_limit(struct entry *entry)
{
return *(unsigned char *)entry;
}
static inline void inc_entry_limit(struct entry *entry, int n)
{
*(unsigned char *)entry += n;
}
/* extent wrappers */
static inline struct diskextent make_extent(block_t block, unsigned count)
{
assert(block < (1ULL << 48) && count - 1 < (1 << 6));
return (struct diskextent){ cpu_to_be64(((u64)(count - 1) << 48) | block) };
}
static inline block_t extent_block(struct diskextent extent)
{
return be64_to_cpup((__be64 *)&extent) & ~(-1LL << 48);
}
static inline unsigned extent_count(struct diskextent extent)
{
return ((be64_to_cpup((__be64 *)&extent) >> 48) & 0x3f) + 1;
}
static inline unsigned extent_version(struct diskextent extent)
{
return be64_to_cpu(*(__be64 *)&extent) >> 54;
}
/* dleaf wrappers */
static inline unsigned dleaf_groups(struct dleaf *leaf)
{
return be16_to_cpu(leaf->groups);
}
static inline void set_dleaf_groups(struct dleaf *leaf, int n)
{
leaf->groups = cpu_to_be16(n);
}
static inline void inc_dleaf_groups(struct dleaf *leaf, int n)
{
be16_add_cpu(&leaf->groups, n);
}
int dleaf_init(struct btree *btree, void *leaf);
unsigned dleaf_free(struct btree *btree, void *leaf);
void dleaf_dump(struct btree *btree, void *vleaf);
int dleaf_merge(struct btree *btree, void *vinto, void *vfrom);
extern struct btree_ops dtree1_ops;
void dwalk_redirect(struct dwalk *walk, struct dleaf *src, struct dleaf *dst);
int dwalk_end(struct dwalk *walk);
block_t dwalk_block(struct dwalk *walk);
unsigned dwalk_count(struct dwalk *walk);
tuxkey_t dwalk_index(struct dwalk *walk);
int dwalk_next(struct dwalk *walk);
int dwalk_back(struct dwalk *walk);
int dwalk_probe(struct dleaf *leaf, unsigned blocksize, struct dwalk *walk, tuxkey_t key);
int dwalk_mock(struct dwalk *walk, tuxkey_t index, struct diskextent extent);
void dwalk_copy(struct dwalk *walk, struct dleaf *dest);
void dwalk_chop(struct dwalk *walk);
int dwalk_add(struct dwalk *walk, tuxkey_t index, struct diskextent extent);
#endif /* !TUX3_DLEAF_H */