#ifndef BTRFS_H
#define BTRFS_H
#include "system_dependencies.h"
typedef uint64 fileblock_t;
typedef uint64 fsblock_t;
#define BTRFS_LABEL_SIZE 256
#define BTRFS_SUPER_BLOCK_OFFSET 0x10000
#define BTRFS_RESERVED_SPACE_OFFSET 0x100000
#define BTRFS_NUM_ROOT_BACKUPS 4
#define BTRFS_CSUM_SIZE 32
struct btrfs_backup_roots {
uint64 root;
uint64 root_generation;
uint64 chunk_root;
uint64 chunk_root_generation;
uint64 extent_root;
uint64 extent_root_generation;
uint64 fs_root;
uint64 fs_root_generation;
uint64 device_root;
uint64 device_root_generation;
uint64 csum_root;
uint64 csum_root_generation;
uint64 total_size;
uint64 used_size;
uint64 num_devices;
uint8 unused_1[32];
uint8 root_level;
uint8 chunk_root_level;
uint8 extent_root_level;
uint8 fs_root_level;
uint8 device_root_level;
uint8 csum_root_level;
uint8 unused_2[10];
uint64 Root() const { return B_LENDIAN_TO_HOST_INT64(root); }
uint64 RootGen() const
{ return B_LENDIAN_TO_HOST_INT64(root_generation); }
uint64 ChunkRoot() const { return B_LENDIAN_TO_HOST_INT64(chunk_root); }
uint64 ChunkRootGen() const
{ return B_LENDIAN_TO_HOST_INT64(chunk_root_generation); }
uint64 ExtentRoot() const { return B_LENDIAN_TO_HOST_INT64(extent_root); }
uint64 ExtentRootGen() const
{ return B_LENDIAN_TO_HOST_INT64(extent_root_generation); }
uint64 FSRoot() const { return B_LENDIAN_TO_HOST_INT64(fs_root); }
uint64 FSRootGen() const
{ return B_LENDIAN_TO_HOST_INT64(fs_root_generation); }
uint64 DeviceRoot() const { return B_LENDIAN_TO_HOST_INT64(device_root); }
uint64 DeviceRootGen() const
{ return B_LENDIAN_TO_HOST_INT64(device_root_generation); }
uint64 CSumRoot() const { return B_LENDIAN_TO_HOST_INT64(csum_root); }
uint64 CSumRootGen() const
{ return B_LENDIAN_TO_HOST_INT64(csum_root_generation); }
uint8 RootLevel() const { return root_level; }
uint8 ChunkRootLevel() const { return chunk_root_level; }
uint8 ExtentRootLevel() const { return extent_root_level; }
uint8 FSRootLevel() const { return fs_root_level; }
uint8 DeviceRootLevel() const { return device_root_level; }
uint8 CSumRootLevel() const { return csum_root_level; }
} _PACKED;
struct btrfs_key {
uint64 object_id;
uint8 type;
uint64 offset;
uint64 ObjectID() const { return B_LENDIAN_TO_HOST_INT64(object_id); }
uint8 Type() const { return type; }
uint64 Offset() const { return B_LENDIAN_TO_HOST_INT64(offset); }
void SetObjectID(uint64 id) { object_id = B_HOST_TO_LENDIAN_INT64(id); }
void SetType(uint8 key_type) { type = key_type; }
void SetOffset(uint64 off) { offset = B_HOST_TO_LENDIAN_INT64(off); }
int32 Compare(const btrfs_key& key) const;
} _PACKED;
struct btrfs_timespec {
uint64 seconds;
uint32 nanoseconds;
} _PACKED;
struct btrfs_header {
uint8 checksum[32];
uuid_t fsid;
uint64 logical_address;
uint64 flags;
uuid_t chunk_tree_uuid;
uint64 generation;
uint64 owner;
uint32 item_count;
uint8 level;
uint64 LogicalAddress() const
{ return B_LENDIAN_TO_HOST_INT64(logical_address); }
uint64 Flags() const { return B_LENDIAN_TO_HOST_INT64(flags); }
uint64 Generation() const
{ return B_LENDIAN_TO_HOST_INT64(generation); }
uint64 Owner() const
{ return B_LENDIAN_TO_HOST_INT64(owner); }
uint32 ItemCount() const
{ return B_LENDIAN_TO_HOST_INT32(item_count); }
uint8 Level() const { return level; }
void SetLogicalAddress(uint64 logical)
{ logical_address = B_HOST_TO_LENDIAN_INT64(logical); }
void SetGeneration(uint64 gen)
{ generation = B_HOST_TO_LENDIAN_INT64(gen); }
void SetItemCount(uint32 itemCount)
{ item_count = B_HOST_TO_LENDIAN_INT32(itemCount); }
} _PACKED;
struct btrfs_index {
btrfs_key key;
uint64 logical_address;
uint64 generation;
uint64 LogicalAddress() const
{ return B_LENDIAN_TO_HOST_INT64(logical_address); }
uint64 Generation() const
{ return B_LENDIAN_TO_HOST_INT64(generation); }
void SetLogicalAddress(uint64 address)
{ logical_address = B_HOST_TO_LENDIAN_INT64(address); }
void SetGeneration(uint64 gen)
{ generation = B_HOST_TO_LENDIAN_INT64(gen); }
} _PACKED;
struct btrfs_entry {
btrfs_key key;
uint32 offset;
uint32 size;
uint32 Offset() const
{ return B_LENDIAN_TO_HOST_INT32(offset); }
uint32 Size() const
{ return B_LENDIAN_TO_HOST_INT32(size); }
void SetOffset(uint32 off) { offset = B_HOST_TO_LENDIAN_INT32(off); }
void SetSize(uint32 itemSize) { size = B_HOST_TO_LENDIAN_INT32(itemSize); }
} _PACKED;
struct btrfs_stream {
btrfs_header header;
union {
btrfs_entry entries[0];
btrfs_index index[0];
};
} _PACKED;
struct btrfs_stripe {
uint64 device_id;
uint64 offset;
uuid_t device_uuid;
uint64 DeviceID() const { return B_LENDIAN_TO_HOST_INT64(device_id); }
uint64 Offset() const { return B_LENDIAN_TO_HOST_INT64(offset); }
} _PACKED;
struct btrfs_chunk {
uint64 length;
uint64 owner;
uint64 stripe_length;
uint64 type;
uint32 io_align;
uint32 io_width;
uint32 sector_size;
uint16 stripe_count;
uint16 sub_stripes;
btrfs_stripe stripes[0];
uint64 Length() const { return B_LENDIAN_TO_HOST_INT64(length); }
uint64 Owner() const { return B_LENDIAN_TO_HOST_INT64(owner); }
uint64 StripeLength() const
{ return B_LENDIAN_TO_HOST_INT64(stripe_length); }
uint64 Type() const { return B_LENDIAN_TO_HOST_INT64(type); }
uint32 IOAlign() const { return B_LENDIAN_TO_HOST_INT32(io_align); }
uint32 IOWidth() const { return B_LENDIAN_TO_HOST_INT32(io_width); }
uint32 SectorSize() const
{ return B_LENDIAN_TO_HOST_INT32(sector_size); }
uint16 StripeCount() const
{ return B_LENDIAN_TO_HOST_INT16(stripe_count); }
uint16 SubStripes() const
{ return B_LENDIAN_TO_HOST_INT16(sub_stripes); }
} _PACKED;
struct btrfs_device {
uint64 id;
uint64 total_size;
uint64 used_size;
uint32 io_align;
uint32 io_width;
uint32 sector_size;
uint64 type;
uint64 generation;
uint64 start_offset;
uint32 group;
uint8 seek_speed;
uint8 bandwidth;
uuid_t uuid;
uuid_t fsid;
} _PACKED;
struct btrfs_super_block {
uint8 checksum[BTRFS_CSUM_SIZE];
uuid_t fsid;
uint64 blocknum;
uint64 flags;
char magic[8];
uint64 generation;
uint64 root;
uint64 chunk_root;
uint64 log_root;
uint64 log_root_transaction_id;
uint64 total_size;
uint64 used_size;
uint64 root_dir_object_id;
uint64 num_devices;
uint32 sector_size;
uint32 node_size;
uint32 leaf_size;
uint32 stripe_size;
uint32 system_chunk_array_size;
uint64 chunk_root_generation;
uint64 compat_flags;
uint64 readonly_flags;
uint64 incompat_flags;
uint16 checksum_type;
uint8 root_level;
uint8 chunk_root_level;
uint8 log_root_level;
btrfs_device device;
char label[BTRFS_LABEL_SIZE];
uint64 reserved[32];
uint8 system_chunk_array[2048];
btrfs_backup_roots backup_roots[BTRFS_NUM_ROOT_BACKUPS];
bool IsMagicValid() const;
bool IsValid() const;
void Initialize(const char* name, off_t numBlocks,
uint32 blockSize, uint32 sectorSize);
uint64 TotalSize() const { return B_LENDIAN_TO_HOST_INT64(total_size); }
uint32 BlockSize() const { return B_LENDIAN_TO_HOST_INT32(node_size); }
uint32 SectorSize() const { return B_LENDIAN_TO_HOST_INT32(sector_size); }
uint64 RootDirObjectID() const
{ return B_LENDIAN_TO_HOST_INT64(root_dir_object_id); }
uint64 Generation() const
{ return B_LENDIAN_TO_HOST_INT64(generation); }
uint64 Root() const
{ return B_LENDIAN_TO_HOST_INT64(root); }
uint64 ChunkRoot() const
{ return B_LENDIAN_TO_HOST_INT64(chunk_root); }
uint64 LogRoot() const
{ return B_LENDIAN_TO_HOST_INT64(log_root); }
uint8 ChunkRootLevel() const { return chunk_root_level; }
} _PACKED;
struct btrfs_inode {
uint64 generation;
uint64 transaction_id;
uint64 size;
uint64 nbytes;
uint64 blockgroup;
uint32 num_links;
uint32 uid;
uint32 gid;
uint32 mode;
uint64 rdev;
uint64 flags;
uint64 sequence;
uint64 reserved[4];
btrfs_timespec access_time;
btrfs_timespec change_time;
btrfs_timespec modification_time;
btrfs_timespec creation_time;
uint64 Generation() const { return B_LENDIAN_TO_HOST_INT64(generation); }
uint64 Size() const { return B_LENDIAN_TO_HOST_INT64(size); }
uint32 UserID() const { return B_LENDIAN_TO_HOST_INT32(uid); }
uint32 GroupID() const { return B_LENDIAN_TO_HOST_INT32(gid); }
uint32 Mode() const { return B_LENDIAN_TO_HOST_INT32(mode); }
uint64 Flags() const { return B_LENDIAN_TO_HOST_INT64(flags); }
uint64 Sequence() const { return B_LENDIAN_TO_HOST_INT64(sequence); }
static void _DecodeTime(struct timespec& timespec,
const btrfs_timespec& time)
{
timespec.tv_sec = B_LENDIAN_TO_HOST_INT64(time.seconds);
timespec.tv_nsec = B_LENDIAN_TO_HOST_INT32(time.nanoseconds);
}
void GetAccessTime(struct timespec& timespec) const
{ _DecodeTime(timespec, access_time); }
void GetChangeTime(struct timespec& timespec) const
{ _DecodeTime(timespec, change_time); }
void GetModificationTime(struct timespec& timespec) const
{ _DecodeTime(timespec, modification_time); }
void GetCreationTime(struct timespec& timespec) const
{ _DecodeTime(timespec, creation_time); }
static void SetTime(btrfs_timespec& time, const struct timespec& timespec)
{
time.seconds = B_HOST_TO_LENDIAN_INT64(timespec.tv_sec);
time.nanoseconds = B_HOST_TO_LENDIAN_INT64(timespec.tv_nsec);
}
} _PACKED;
struct btrfs_inode_ref {
uint64 index;
uint16 name_length;
uint8 name[];
uint64 Index() const { return index; }
uint16 NameLength() const { return B_LENDIAN_TO_HOST_INT16(name_length); }
uint16 Length() const
{ return sizeof(btrfs_inode_ref) + NameLength(); }
void SetName(const char* name, uint16 nameLength)
{
name_length = B_HOST_TO_LENDIAN_INT16(nameLength);
memcpy(this->name, name, nameLength);
}
} _PACKED;
struct btrfs_root {
btrfs_inode inode;
uint64 generation;
uint64 root_dirid;
uint64 logical_address;
uint64 limit_bytes;
uint64 used_bytes;
uint64 last_snapshot;
uint64 flags;
uint32 refs;
btrfs_key drop_progress;
uint8 drop_level;
uint8 level;
uint64 Generation() const
{ return B_LENDIAN_TO_HOST_INT64(generation); }
uint64 LogicalAddress() const
{ return B_LENDIAN_TO_HOST_INT64(logical_address); }
} _PACKED;
struct btrfs_dir_entry {
btrfs_key location;
uint64 transaction_id;
uint16 data_length;
uint16 name_length;
uint8 type;
uint8 name[];
uint16 DataLength() const { return B_LENDIAN_TO_HOST_INT16(data_length); }
uint16 NameLength() const { return B_LENDIAN_TO_HOST_INT16(name_length); }
ino_t InodeID() const { return location.ObjectID(); }
uint16 Length() const
{ return sizeof(*this) + NameLength() + DataLength(); }
void SetTransactionID(uint64 id)
{ transaction_id = B_HOST_TO_LENDIAN_INT64(id); }
void SetAttributeData(void* data, uint16 dataLength)
{
data_length = B_HOST_TO_LENDIAN_INT16(dataLength);
if (data != NULL)
memcpy(&name[name_length], data, dataLength);
}
void SetName(const char* name, uint16 nameLength)
{
name_length = B_HOST_TO_LENDIAN_INT16(nameLength);
memcpy(this->name, name, nameLength);
}
} _PACKED;
struct btrfs_extent_data {
uint64 generation;
uint64 memory_size;
uint8 compression;
uint8 encryption;
uint16 reserved;
uint8 type;
union {
struct {
uint64 disk_offset;
uint64 disk_size;
uint64 extent_offset;
uint64 size;
};
uint8 inline_data[0];
};
uint64 Generation() const
{ return B_LENDIAN_TO_HOST_INT64(generation); }
uint64 MemoryBytes() const
{ return B_LENDIAN_TO_HOST_INT64(memory_size); }
uint8 Compression() const { return compression; }
uint8 Type() const { return type; }
uint64 DiskOffset() const
{ return B_LENDIAN_TO_HOST_INT64(disk_offset); }
uint64 DiskSize() const
{ return B_LENDIAN_TO_HOST_INT64(disk_size); }
uint64 ExtentOffset() const
{ return B_LENDIAN_TO_HOST_INT64(extent_offset); }
uint64 Size() const
{ return B_LENDIAN_TO_HOST_INT64(size); }
} _PACKED;
struct btrfs_block_group {
uint64 used_space;
uint64 chunk_object_id;
uint64 flags;
uint64 UsedSpace() const { return B_LENDIAN_TO_HOST_INT64(used_space); }
uint64 ChunkObjectID() const
{ return B_LENDIAN_TO_HOST_INT64(chunk_object_id); }
uint64 Flags() const { return B_LENDIAN_TO_HOST_INT64(flags); }
} _PACKED;
struct btrfs_extent {
uint64 refs;
uint64 generation;
uint64 flags;
uint64 RefCount() const { return B_LENDIAN_TO_HOST_INT64(refs); }
uint64 Generation() const { return B_LENDIAN_TO_HOST_INT64(generation); }
uint64 Flags() const { return B_LENDIAN_TO_HOST_INT64(flags); }
} _PACKED;
struct btrfs_extent_inline_ref {
uint8 type;
uint64 offset;
uint8 Type() const { return type; }
uint64 Offset() const { return B_LENDIAN_TO_HOST_INT64(offset); }
} _PACKED;
struct btrfs_extent_data_ref {
uint64 root_id;
uint64 inode_id;
uint64 offset;
uint32 ref_count;
uint64 RootID() const { return B_LENDIAN_TO_HOST_INT64(root_id); }
uint64 InodeID() const { return B_LENDIAN_TO_HOST_INT64(inode_id); }
uint64 Offset() const { return B_LENDIAN_TO_HOST_INT64(offset);}
uint32 RefCount() const { return B_LENDIAN_TO_HOST_INT32(ref_count); }
} _PACKED;
#define BTRFS_SUPER_BLOCK_MAGIC "_BHRfS_M"
#define BTRFS_SUPER_BLOCK_MAGIC_TEMPORARY "!BHRfS_M"
#define BTRFS_FIRST_SUBVOLUME 256
#define BTRFS_CSUM_TYPE_CRC32 0
#define BTRFS_OBJECT_ID_ROOT_TREE 1
#define BTRFS_OBJECT_ID_EXTENT_TREE 2
#define BTRFS_OBJECT_ID_CHUNK_TREE 3
#define BTRFS_OBJECT_ID_DEV_TREE 4
#define BTRFS_OBJECT_ID_FS_TREE 5
#define BTRFS_OBJECT_ID_ROOT_TREE_DIR 6
#define BTRFS_OBJECT_ID_CHECKSUM_TREE 7
#define BTRFS_OBJECT_ID_FIRST_CHUNK_TREE 256
#define BTRFS_KEY_TYPE_ANY 0
#define BTRFS_KEY_TYPE_INODE_ITEM 1
#define BTRFS_KEY_TYPE_INODE_REF 12
#define BTRFS_KEY_TYPE_XATTR_ITEM 24
#define BTRFS_KEY_TYPE_DIR_ITEM 84
#define BTRFS_KEY_TYPE_DIR_INDEX 96
#define BTRFS_KEY_TYPE_EXTENT_DATA 108
#define BTRFS_KEY_TYPE_ROOT_ITEM 132
#define BTRFS_KEY_TYPE_EXTENT_ITEM 168
#define BTRFS_KEY_TYPE_METADATA_ITEM 169
#define BTRFS_KEY_TYPE_EXTENT_DATA_REF 178
#define BTRFS_KEY_TYPE_BLOCKGROUP_ITEM 192
#define BTRFS_KEY_TYPE_CHUNK_ITEM 228
#define BTRFS_EXTENT_COMPRESS_NONE 0
#define BTRFS_EXTENT_COMPRESS_ZLIB 1
#define BTRFS_EXTENT_COMPRESS_LZO 2
#define BTRFS_EXTENT_COMPRESS_ZSTD 3
#define BTRFS_EXTENT_DATA_INLINE 0
#define BTRFS_EXTENT_DATA_REGULAR 1
#define BTRFS_EXTENT_DATA_PRE 2
#define BTRFS_EXTENT_FLAG_DATA 1
#define BTRFS_EXTENT_FLAG_TREE_BLOCK 2
#define BTRFS_EXTENT_FLAG_ALLOCATED 4
#define BTRFS_BLOCKGROUP_FLAG_DATA 1
#define BTRFS_BLOCKGROUP_FLAG_SYSTEM 2
#define BTRFS_BLOCKGROUP_FLAG_METADATA 4
#define BTRFS_BLOCKGROUP_FLAG_RAID0 8
#define BTRFS_BLOCKGROUP_FLAG_RAID1 16
#define BTRFS_BLOCKGROUP_FLAG_DUP 32
#define BTRFS_BLOCKGROUP_FLAG_RAID10 64
#define BTRFS_BLOCKGROUP_FLAG_RAID5 128
#define BTRFS_BLOCKGROUP_FLAG_RAID6 256
#define BTRFS_BLOCKGROUP_FLAG_MASK 511
#define BTRFS_FILETYPE_UNKNOWN 0
#define BTRFS_FILETYPE_REGULAR 1
#define BTRFS_FILETYPE_DIRECTORY 2
#define BTRFS_FILETYPE_CHRDEV 3
#define BTRFS_FILETYPE_BLKDEV 4
#define BTRFS_FILETYPE_FIFO 5
#define BTRFS_FILETYPE_SOCKET 6
#define BTRFS_FILETYPE_SYMLINK 7
#define BTRFS_FILETYPE_XATTR 8
struct file_cookie {
bigtime_t last_notification;
off_t last_size;
int open_mode;
};
#define BTRFS_OPEN_MODE_USER_MASK 0x7fffffff
extern fs_volume_ops gBtrfsVolumeOps;
extern fs_vnode_ops gBtrfsVnodeOps;
#endif