#![allow(clippy::upper_case_acronyms)]
use crate::bindings::{
BTRFS_BLOCK_GROUP_DATA, BTRFS_BLOCK_GROUP_DUP, BTRFS_BLOCK_GROUP_METADATA,
BTRFS_BLOCK_GROUP_PROFILE_MASK, BTRFS_BLOCK_GROUP_RAID0, BTRFS_BLOCK_GROUP_RAID1,
BTRFS_BLOCK_GROUP_RAID10, BTRFS_BLOCK_GROUP_RAID1C3, BTRFS_BLOCK_GROUP_RAID1C4,
BTRFS_BLOCK_GROUP_RAID5, BTRFS_BLOCK_GROUP_RAID6, BTRFS_BLOCK_GROUP_RESERVED,
BTRFS_BLOCK_GROUP_SYSTEM, BTRFS_BLOCK_GROUP_TYPE_MASK, BTRFS_ERROR_DEV_RAID10_MIN_NOT_MET,
BTRFS_ERROR_DEV_RAID1C3_MIN_NOT_MET, BTRFS_ERROR_DEV_RAID1C4_MIN_NOT_MET,
BTRFS_ERROR_DEV_RAID1_MIN_NOT_MET, BTRFS_ERROR_DEV_RAID5_MIN_NOT_MET,
BTRFS_ERROR_DEV_RAID6_MIN_NOT_MET, BTRFS_SPACE_INFO_GLOBAL_RSV,
};
#[derive(Debug)]
pub enum BlockType {
Data,
System,
Metadata,
GlobalReserve,
Unknown,
}
impl From<u64> for BlockType {
fn from(value: u64) -> Self {
match value & (BTRFS_BLOCK_GROUP_TYPE_MASK | BTRFS_SPACE_INFO_GLOBAL_RSV) {
BTRFS_BLOCK_GROUP_DATA => Self::Data,
BTRFS_BLOCK_GROUP_SYSTEM => Self::System,
BTRFS_BLOCK_GROUP_METADATA => Self::Metadata,
BTRFS_SPACE_INFO_GLOBAL_RSV => Self::GlobalReserve,
_ => Self::Unknown,
}
}
}
#[derive(Clone, Copy, Debug)]
pub struct RaidProfile {
pub sub_stripes: u32,
pub dev_stripes: u32,
pub devs_max: u32,
pub devs_min: u32,
pub tolerated_failures: u32,
pub devs_increment: u32,
pub ncopies: u32,
pub nparity: u32,
pub mindev_error: u32,
pub lower_name: &'static str,
pub upper_name: &'static str,
pub bg_flag: u64,
}
impl TryFrom<u64> for RaidProfile {
type Error = std::io::Error;
fn try_from(mut value: u64) -> Result<Self, Self::Error> {
value &= !(BTRFS_BLOCK_GROUP_TYPE_MASK | BTRFS_BLOCK_GROUP_RESERVED);
let index = if value & !BTRFS_BLOCK_GROUP_PROFILE_MASK != 0 {
error!(InvalidInput;)
} else if value & BTRFS_BLOCK_GROUP_RAID10 != 0 {
RaidIndex::RAID10
} else if value & BTRFS_BLOCK_GROUP_RAID1 != 0 {
RaidIndex::RAID1
} else if value & BTRFS_BLOCK_GROUP_RAID1C3 != 0 {
RaidIndex::RAID1C3
} else if value & BTRFS_BLOCK_GROUP_RAID1C4 != 0 {
RaidIndex::RAID1C4
} else if value & BTRFS_BLOCK_GROUP_DUP != 0 {
RaidIndex::DUP
} else if value & BTRFS_BLOCK_GROUP_RAID0 != 0 {
RaidIndex::RAID0
} else if value & BTRFS_BLOCK_GROUP_RAID5 != 0 {
RaidIndex::RAID5
} else if value & BTRFS_BLOCK_GROUP_RAID6 != 0 {
RaidIndex::RAID6
} else {
RaidIndex::Single
};
Ok(RAID_ARRAY[index as usize])
}
}
enum RaidIndex {
RAID10 = 0,
RAID1,
DUP,
RAID0,
Single,
RAID5,
RAID6,
RAID1C3,
RAID1C4,
MAX,
}
const RAID_ARRAY: [RaidProfile; RaidIndex::MAX as usize] = [
BTRFS_RAID_RAID10,
BTRFS_RAID_RAID1,
BTRFS_RAID_DUP,
BTRFS_RAID_RAID0,
BTRFS_RAID_SINGLE,
BTRFS_RAID_RAID5,
BTRFS_RAID_RAID6,
BTRFS_RAID_RAID1C3,
BTRFS_RAID_RAID1C4,
];
const BTRFS_RAID_RAID10: RaidProfile = RaidProfile {
sub_stripes: 2,
dev_stripes: 1,
devs_max: 0,
devs_min: 2,
tolerated_failures: 1,
devs_increment: 2,
ncopies: 2,
nparity: 0,
lower_name: "raid10",
upper_name: "RAID10",
bg_flag: BTRFS_BLOCK_GROUP_RAID10,
mindev_error: BTRFS_ERROR_DEV_RAID10_MIN_NOT_MET,
};
const BTRFS_RAID_RAID1: RaidProfile = RaidProfile {
sub_stripes: 1,
dev_stripes: 1,
devs_max: 2,
devs_min: 2,
tolerated_failures: 1,
devs_increment: 2,
ncopies: 2,
nparity: 0,
lower_name: "raid1",
upper_name: "RAID1",
bg_flag: BTRFS_BLOCK_GROUP_RAID1,
mindev_error: BTRFS_ERROR_DEV_RAID1_MIN_NOT_MET,
};
const BTRFS_RAID_DUP: RaidProfile = RaidProfile {
sub_stripes: 1,
dev_stripes: 2,
devs_max: 1,
devs_min: 1,
tolerated_failures: 0,
devs_increment: 1,
ncopies: 2,
nparity: 0,
lower_name: "dup",
upper_name: "DUP",
bg_flag: BTRFS_BLOCK_GROUP_DUP,
mindev_error: 0,
};
const BTRFS_RAID_RAID0: RaidProfile = RaidProfile {
sub_stripes: 1,
dev_stripes: 1,
devs_max: 0,
devs_min: 1,
tolerated_failures: 0,
devs_increment: 1,
ncopies: 1,
nparity: 0,
lower_name: "raid0",
upper_name: "RAID0",
bg_flag: BTRFS_BLOCK_GROUP_RAID0,
mindev_error: 0,
};
const BTRFS_RAID_SINGLE: RaidProfile = RaidProfile {
sub_stripes: 1,
dev_stripes: 1,
devs_max: 1,
devs_min: 1,
tolerated_failures: 0,
devs_increment: 1,
ncopies: 1,
nparity: 0,
lower_name: "single",
upper_name: "SINGLE",
bg_flag: 0,
mindev_error: 0,
};
const BTRFS_RAID_RAID5: RaidProfile = RaidProfile {
sub_stripes: 1,
dev_stripes: 1,
devs_max: 0,
devs_min: 2,
tolerated_failures: 1,
devs_increment: 1,
ncopies: 1,
nparity: 1,
lower_name: "raid5",
upper_name: "RAID5",
bg_flag: BTRFS_BLOCK_GROUP_RAID5,
mindev_error: BTRFS_ERROR_DEV_RAID5_MIN_NOT_MET,
};
const BTRFS_RAID_RAID6: RaidProfile = RaidProfile {
sub_stripes: 1,
dev_stripes: 1,
devs_max: 0,
devs_min: 3,
tolerated_failures: 2,
devs_increment: 1,
ncopies: 1,
nparity: 2,
lower_name: "raid6",
upper_name: "RAID6",
bg_flag: BTRFS_BLOCK_GROUP_RAID6,
mindev_error: BTRFS_ERROR_DEV_RAID6_MIN_NOT_MET,
};
const BTRFS_RAID_RAID1C3: RaidProfile = RaidProfile {
sub_stripes: 1,
dev_stripes: 1,
devs_max: 3,
devs_min: 3,
tolerated_failures: 2,
devs_increment: 3,
ncopies: 3,
nparity: 0,
lower_name: "raid1c3",
upper_name: "RAID1C3",
bg_flag: BTRFS_BLOCK_GROUP_RAID1C3,
mindev_error: BTRFS_ERROR_DEV_RAID1C3_MIN_NOT_MET,
};
const BTRFS_RAID_RAID1C4: RaidProfile = RaidProfile {
sub_stripes: 1,
dev_stripes: 1,
devs_max: 4,
devs_min: 4,
tolerated_failures: 3,
devs_increment: 4,
ncopies: 4,
nparity: 0,
lower_name: "raid1c4",
upper_name: "RAID1C4",
bg_flag: BTRFS_BLOCK_GROUP_RAID1C4,
mindev_error: BTRFS_ERROR_DEV_RAID1C4_MIN_NOT_MET,
};