2007-02-02 17:18:22 +03:00
# ifndef __CTREE__
# define __CTREE__
2007-03-02 02:59:40 +03:00
# include "list.h"
2007-03-12 23:22:34 +03:00
# include "kerncompat.h"
2007-03-02 02:59:40 +03:00
2007-02-26 18:40:21 +03:00
# define CTREE_BLOCKSIZE 1024
2007-02-02 17:18:22 +03:00
2007-02-26 18:40:21 +03:00
/*
* the key defines the order in the tree , and so it also defines ( optimal )
* block layout . objectid corresonds to the inode number . The flags
* tells us things about the object , and is a kind of stream selector .
* so for a given inode , keys with flags of 1 might refer to the inode
* data , flags of 2 may point to file data in the btree and flags = = 3
* may point to extents .
*
* offset is the starting byte offset for this key in the stream .
2007-03-12 23:22:34 +03:00
*
* btrfs_disk_key is in disk byte order . struct btrfs_key is always
* in cpu native order . Otherwise they are identical and their sizes
* should be the same ( ie both packed )
2007-02-26 18:40:21 +03:00
*/
2007-03-12 23:22:34 +03:00
struct btrfs_disk_key {
__le64 objectid ;
__le32 flags ;
__le64 offset ;
} __attribute__ ( ( __packed__ ) ) ;
struct btrfs_key {
2007-02-02 17:18:22 +03:00
u64 objectid ;
u32 flags ;
u64 offset ;
} __attribute__ ( ( __packed__ ) ) ;
2007-02-26 18:40:21 +03:00
/*
* every tree block ( leaf or node ) starts with this header .
*/
2007-03-12 19:29:44 +03:00
struct btrfs_header {
__le64 fsid [ 2 ] ; /* FS specific uuid */
__le64 blocknr ; /* which block this node is supposed to live in */
__le64 parentid ; /* objectid of the tree root */
__le32 csum ;
__le32 ham ;
__le16 nritems ;
__le16 flags ;
2007-02-26 18:40:21 +03:00
/* generation flags to be added */
2007-02-02 17:18:22 +03:00
} __attribute__ ( ( __packed__ ) ) ;
2007-03-12 19:01:18 +03:00
# define MAX_LEVEL 8
2007-03-12 19:29:44 +03:00
# define NODEPTRS_PER_BLOCK ((CTREE_BLOCKSIZE - sizeof(struct btrfs_header)) / \
2007-03-12 23:22:34 +03:00
( sizeof ( struct btrfs_disk_key ) + sizeof ( u64 ) ) )
2007-02-02 17:18:22 +03:00
struct tree_buffer ;
2007-02-21 00:40:44 +03:00
2007-02-26 18:40:21 +03:00
/*
* in ram representation of the tree . extent_root is used for all allocations
* and for the extent tree extent_root root . current_insert is used
* only for the extent tree .
*/
2007-02-02 17:18:22 +03:00
struct ctree_root {
struct tree_buffer * node ;
2007-03-07 04:08:01 +03:00
struct tree_buffer * commit_root ;
2007-02-21 00:40:44 +03:00
struct ctree_root * extent_root ;
2007-03-12 23:22:34 +03:00
struct btrfs_key current_insert ;
struct btrfs_key last_insert ;
2007-02-02 17:18:22 +03:00
int fp ;
struct radix_tree_root cache_radix ;
2007-03-07 04:08:01 +03:00
struct radix_tree_root pinned_radix ;
2007-03-02 02:59:40 +03:00
struct list_head trans ;
struct list_head cache ;
int cache_size ;
2007-02-02 17:18:22 +03:00
} ;
2007-02-26 18:40:21 +03:00
/*
* describes a tree on disk
*/
2007-02-21 00:40:44 +03:00
struct ctree_root_info {
u64 fsid [ 2 ] ; /* FS specific uuid */
u64 blocknr ; /* blocknr of this block */
u64 objectid ; /* inode number of this root */
2007-02-26 18:40:21 +03:00
u64 tree_root ; /* the tree root block */
2007-02-21 00:40:44 +03:00
u32 csum ;
u32 ham ;
u64 snapuuid [ 2 ] ; /* root specific uuid */
} __attribute__ ( ( __packed__ ) ) ;
2007-02-26 18:40:21 +03:00
/*
* the super block basically lists the main trees of the FS
* it currently lacks any block count etc etc
*/
2007-02-22 01:04:57 +03:00
struct ctree_super_block {
struct ctree_root_info root_info ;
struct ctree_root_info extent_info ;
} __attribute__ ( ( __packed__ ) ) ;
2007-02-26 18:40:21 +03:00
/*
* A leaf is full of items . The exact type of item is defined by
* the key flags parameter . offset and size tell us where to find
* the item in the leaf ( relative to the start of the data area )
*/
2007-03-13 03:12:07 +03:00
struct btrfs_item {
2007-03-12 23:22:34 +03:00
struct btrfs_disk_key key ;
2007-03-13 03:12:07 +03:00
__le16 offset ;
__le16 size ;
2007-02-02 17:18:22 +03:00
} __attribute__ ( ( __packed__ ) ) ;
2007-02-26 18:40:21 +03:00
/*
* leaves have an item area and a data area :
* [ item0 , item1 . . . . itemN ] [ free space ] [ dataN . . . data1 , data0 ]
*
* The data is separate from the items to get the keys closer together
* during searches .
*/
2007-03-12 19:29:44 +03:00
# define LEAF_DATA_SIZE (CTREE_BLOCKSIZE - sizeof(struct btrfs_header))
2007-02-02 17:18:22 +03:00
struct leaf {
2007-03-12 19:29:44 +03:00
struct btrfs_header header ;
2007-02-02 17:18:22 +03:00
union {
2007-03-13 03:12:07 +03:00
struct btrfs_item items [ LEAF_DATA_SIZE /
sizeof ( struct btrfs_item ) ] ;
2007-03-12 19:29:44 +03:00
u8 data [ CTREE_BLOCKSIZE - sizeof ( struct btrfs_header ) ] ;
2007-02-02 17:18:22 +03:00
} ;
} __attribute__ ( ( __packed__ ) ) ;
2007-02-26 18:40:21 +03:00
/*
* all non - leaf blocks are nodes , they hold only keys and pointers to
* other blocks
*/
2007-02-02 17:18:22 +03:00
struct node {
2007-03-12 19:29:44 +03:00
struct btrfs_header header ;
2007-03-12 23:22:34 +03:00
struct btrfs_disk_key keys [ NODEPTRS_PER_BLOCK ] ;
2007-03-13 16:28:32 +03:00
__le64 blockptrs [ NODEPTRS_PER_BLOCK ] ;
2007-02-02 17:18:22 +03:00
} __attribute__ ( ( __packed__ ) ) ;
2007-02-26 18:40:21 +03:00
/*
* items in the extent btree are used to record the objectid of the
* owner of the block and the number of references
*/
2007-02-21 00:40:44 +03:00
struct extent_item {
2007-03-13 16:49:06 +03:00
__le32 refs ;
__le64 owner ;
2007-02-21 00:40:44 +03:00
} __attribute__ ( ( __packed__ ) ) ;
2007-02-26 18:40:21 +03:00
/*
* ctree_paths remember the path taken from the root down to the leaf .
* level 0 is always the leaf , and nodes [ 1. . . MAX_LEVEL ] will point
* to any other levels that are present .
*
* The slots array records the index of the item or block pointer
* used while walking the tree .
*/
2007-02-02 17:18:22 +03:00
struct ctree_path {
struct tree_buffer * nodes [ MAX_LEVEL ] ;
int slots [ MAX_LEVEL ] ;
} ;
2007-02-24 14:24:44 +03:00
2007-03-13 16:49:06 +03:00
static inline u64 btrfs_extent_owner ( struct extent_item * ei )
{
return le64_to_cpu ( ei - > owner ) ;
}
static inline void btrfs_set_extent_owner ( struct extent_item * ei , u64 val )
{
ei - > owner = cpu_to_le64 ( val ) ;
}
static inline u32 btrfs_extent_refs ( struct extent_item * ei )
{
return le32_to_cpu ( ei - > refs ) ;
}
static inline void btrfs_set_extent_refs ( struct extent_item * ei , u32 val )
{
ei - > refs = cpu_to_le32 ( val ) ;
}
2007-03-13 16:28:32 +03:00
static inline u64 btrfs_node_blockptr ( struct node * n , int nr )
{
return le64_to_cpu ( n - > blockptrs [ nr ] ) ;
}
static inline void btrfs_set_node_blockptr ( struct node * n , int nr , u64 val )
{
n - > blockptrs [ nr ] = cpu_to_le64 ( val ) ;
}
2007-03-13 03:12:07 +03:00
static inline u16 btrfs_item_offset ( struct btrfs_item * item )
{
return le16_to_cpu ( item - > offset ) ;
}
static inline void btrfs_set_item_offset ( struct btrfs_item * item , u16 val )
{
item - > offset = cpu_to_le16 ( val ) ;
}
static inline u16 btrfs_item_end ( struct btrfs_item * item )
{
return le16_to_cpu ( item - > offset ) + le16_to_cpu ( item - > size ) ;
}
static inline u16 btrfs_item_size ( struct btrfs_item * item )
{
return le16_to_cpu ( item - > size ) ;
}
static inline void btrfs_set_item_size ( struct btrfs_item * item , u16 val )
{
item - > size = cpu_to_le16 ( val ) ;
}
2007-03-12 23:22:34 +03:00
static inline void btrfs_disk_key_to_cpu ( struct btrfs_key * cpu ,
struct btrfs_disk_key * disk )
{
cpu - > offset = le64_to_cpu ( disk - > offset ) ;
cpu - > flags = le32_to_cpu ( disk - > flags ) ;
cpu - > objectid = le64_to_cpu ( disk - > objectid ) ;
}
static inline void btrfs_cpu_key_to_disk ( struct btrfs_disk_key * disk ,
struct btrfs_key * cpu )
{
disk - > offset = cpu_to_le64 ( cpu - > offset ) ;
disk - > flags = cpu_to_le32 ( cpu - > flags ) ;
disk - > objectid = cpu_to_le64 ( cpu - > objectid ) ;
}
static inline u64 btrfs_key_objectid ( struct btrfs_disk_key * disk )
{
return le64_to_cpu ( disk - > objectid ) ;
}
static inline void btrfs_set_key_objectid ( struct btrfs_disk_key * disk ,
u64 val )
{
disk - > objectid = cpu_to_le64 ( val ) ;
}
static inline u64 btrfs_key_offset ( struct btrfs_disk_key * disk )
{
return le64_to_cpu ( disk - > offset ) ;
}
static inline void btrfs_set_key_offset ( struct btrfs_disk_key * disk ,
u64 val )
{
disk - > offset = cpu_to_le64 ( val ) ;
}
static inline u32 btrfs_key_flags ( struct btrfs_disk_key * disk )
{
return le32_to_cpu ( disk - > flags ) ;
}
static inline void btrfs_set_key_flags ( struct btrfs_disk_key * disk ,
u32 val )
{
disk - > flags = cpu_to_le32 ( val ) ;
}
2007-03-12 19:29:44 +03:00
static inline u64 btrfs_header_blocknr ( struct btrfs_header * h )
2007-03-12 19:01:18 +03:00
{
2007-03-12 19:29:44 +03:00
return le64_to_cpu ( h - > blocknr ) ;
2007-03-12 19:01:18 +03:00
}
2007-03-12 19:29:44 +03:00
static inline void btrfs_set_header_blocknr ( struct btrfs_header * h , u64 blocknr )
2007-03-12 19:01:18 +03:00
{
2007-03-12 19:29:44 +03:00
h - > blocknr = cpu_to_le64 ( blocknr ) ;
2007-03-12 19:01:18 +03:00
}
2007-03-12 19:29:44 +03:00
static inline u64 btrfs_header_parentid ( struct btrfs_header * h )
2007-03-12 19:01:18 +03:00
{
2007-03-12 19:29:44 +03:00
return le64_to_cpu ( h - > parentid ) ;
2007-03-12 19:01:18 +03:00
}
2007-03-12 19:29:44 +03:00
static inline void btrfs_set_header_parentid ( struct btrfs_header * h ,
u64 parentid )
2007-03-12 19:01:18 +03:00
{
2007-03-12 19:29:44 +03:00
h - > parentid = cpu_to_le64 ( parentid ) ;
2007-03-12 19:01:18 +03:00
}
2007-03-12 19:29:44 +03:00
static inline u16 btrfs_header_nritems ( struct btrfs_header * h )
2007-03-12 19:01:18 +03:00
{
2007-03-12 19:29:44 +03:00
return le16_to_cpu ( h - > nritems ) ;
2007-03-12 19:01:18 +03:00
}
2007-03-12 19:29:44 +03:00
static inline void btrfs_set_header_nritems ( struct btrfs_header * h , u16 val )
2007-03-12 19:01:18 +03:00
{
2007-03-12 19:29:44 +03:00
h - > nritems = cpu_to_le16 ( val ) ;
2007-03-12 19:01:18 +03:00
}
2007-03-12 19:29:44 +03:00
static inline u16 btrfs_header_flags ( struct btrfs_header * h )
2007-03-12 19:01:18 +03:00
{
2007-03-12 19:29:44 +03:00
return le16_to_cpu ( h - > flags ) ;
2007-03-12 19:01:18 +03:00
}
2007-03-12 19:29:44 +03:00
static inline void btrfs_set_header_flags ( struct btrfs_header * h , u16 val )
2007-03-12 19:01:18 +03:00
{
2007-03-12 19:29:44 +03:00
h - > flags = cpu_to_le16 ( val ) ;
2007-03-12 19:01:18 +03:00
}
2007-03-12 19:29:44 +03:00
static inline int btrfs_header_level ( struct btrfs_header * h )
2007-03-12 19:01:18 +03:00
{
return btrfs_header_flags ( h ) & ( MAX_LEVEL - 1 ) ;
}
2007-03-12 19:29:44 +03:00
static inline void btrfs_set_header_level ( struct btrfs_header * h , int level )
2007-03-12 19:01:18 +03:00
{
2007-03-12 19:29:44 +03:00
u16 flags ;
2007-03-12 19:01:18 +03:00
BUG_ON ( level > MAX_LEVEL ) ;
flags = btrfs_header_flags ( h ) & ~ ( MAX_LEVEL - 1 ) ;
btrfs_set_header_flags ( h , flags | level ) ;
}
static inline int btrfs_is_leaf ( struct node * n )
{
return ( btrfs_header_level ( & n - > header ) = = 0 ) ;
}
2007-02-24 14:24:44 +03:00
struct tree_buffer * alloc_free_block ( struct ctree_root * root ) ;
2007-03-03 00:08:05 +03:00
int btrfs_inc_ref ( struct ctree_root * root , struct tree_buffer * buf ) ;
2007-02-24 14:24:44 +03:00
int free_extent ( struct ctree_root * root , u64 blocknr , u64 num_blocks ) ;
2007-03-12 23:22:34 +03:00
int search_slot ( struct ctree_root * root , struct btrfs_key * key ,
struct ctree_path * p , int ins_len , int cow ) ;
2007-02-24 14:24:44 +03:00
void release_path ( struct ctree_root * root , struct ctree_path * p ) ;
void init_path ( struct ctree_path * p ) ;
int del_item ( struct ctree_root * root , struct ctree_path * path ) ;
2007-03-12 23:22:34 +03:00
int insert_item ( struct ctree_root * root , struct btrfs_key * key ,
void * data , int data_size ) ;
2007-02-24 14:24:44 +03:00
int next_leaf ( struct ctree_root * root , struct ctree_path * path ) ;
int leaf_free_space ( struct leaf * leaf ) ;
2007-03-07 04:08:01 +03:00
int btrfs_drop_snapshot ( struct ctree_root * root , struct tree_buffer * snap ) ;
int btrfs_finish_extent_commit ( struct ctree_root * root ) ;
2007-02-02 17:18:22 +03:00
# endif