use btrfs_disk::raw;
pub const SYSTEM_GROUP_OFFSET: u64 = 1024 * 1024;
pub const SYSTEM_GROUP_SIZE: u64 = 4 * 1024 * 1024;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum TreeId {
Root,
Extent,
Chunk,
Dev,
Fs,
Csum,
FreeSpace,
DataReloc,
}
impl TreeId {
pub fn objectid(self) -> u64 {
match self {
TreeId::Root => raw::BTRFS_ROOT_TREE_OBJECTID as u64,
TreeId::Extent => raw::BTRFS_EXTENT_TREE_OBJECTID as u64,
TreeId::Chunk => raw::BTRFS_CHUNK_TREE_OBJECTID as u64,
TreeId::Dev => raw::BTRFS_DEV_TREE_OBJECTID as u64,
TreeId::Fs => raw::BTRFS_FS_TREE_OBJECTID as u64,
TreeId::Csum => raw::BTRFS_CSUM_TREE_OBJECTID as u64,
TreeId::FreeSpace => raw::BTRFS_FREE_SPACE_TREE_OBJECTID as u64,
TreeId::DataReloc => raw::BTRFS_DATA_RELOC_TREE_OBJECTID as u64,
}
}
pub const ALL: [TreeId; 8] = [
TreeId::Root,
TreeId::Extent,
TreeId::Chunk,
TreeId::Dev,
TreeId::Fs,
TreeId::Csum,
TreeId::FreeSpace,
TreeId::DataReloc,
];
pub const ROOT_ITEM_TREES: [TreeId; 6] = [
TreeId::Extent,
TreeId::Dev,
TreeId::Fs,
TreeId::Csum,
TreeId::FreeSpace,
TreeId::DataReloc,
];
}
pub struct BlockLayout {
nodesize: u32,
}
impl BlockLayout {
pub fn new(nodesize: u32) -> Self {
Self { nodesize }
}
pub fn block_addr(&self, tree: TreeId) -> u64 {
let index = TreeId::ALL.iter().position(|&t| t == tree).unwrap();
SYSTEM_GROUP_OFFSET + (index as u64) * u64::from(self.nodesize)
}
pub fn total_used(&self) -> u64 {
TreeId::ALL.len() as u64 * u64::from(self.nodesize)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn block_addresses_sequential() {
let layout = BlockLayout::new(16384);
assert_eq!(layout.block_addr(TreeId::Root), 0x100000);
assert_eq!(layout.block_addr(TreeId::Extent), 0x100000 + 16384);
assert_eq!(layout.block_addr(TreeId::Chunk), 0x100000 + 2 * 16384);
assert_eq!(layout.block_addr(TreeId::Dev), 0x100000 + 3 * 16384);
assert_eq!(layout.block_addr(TreeId::Fs), 0x100000 + 4 * 16384);
assert_eq!(layout.block_addr(TreeId::Csum), 0x100000 + 5 * 16384);
assert_eq!(layout.block_addr(TreeId::FreeSpace), 0x100000 + 6 * 16384);
assert_eq!(layout.block_addr(TreeId::DataReloc), 0x100000 + 7 * 16384);
}
#[test]
fn total_used() {
let layout = BlockLayout::new(16384);
assert_eq!(layout.total_used(), 8 * 16384);
}
}