use crate::raw::{
BTRFS_BALANCE_ARGS_CONVERT, BTRFS_BALANCE_ARGS_DEVID,
BTRFS_BALANCE_ARGS_DRANGE, BTRFS_BALANCE_ARGS_LIMIT,
BTRFS_BALANCE_ARGS_LIMIT_RANGE, BTRFS_BALANCE_ARGS_PROFILES,
BTRFS_BALANCE_ARGS_SOFT, BTRFS_BALANCE_ARGS_STRIPES_RANGE,
BTRFS_BALANCE_ARGS_USAGE, BTRFS_BALANCE_ARGS_USAGE_RANGE,
BTRFS_BALANCE_ARGS_VRANGE, BTRFS_BALANCE_CTL_CANCEL,
BTRFS_BALANCE_CTL_PAUSE, BTRFS_BALANCE_DATA, BTRFS_BALANCE_FORCE,
BTRFS_BALANCE_METADATA, BTRFS_BALANCE_RESUME,
BTRFS_BALANCE_STATE_CANCEL_REQ, BTRFS_BALANCE_STATE_PAUSE_REQ,
BTRFS_BALANCE_STATE_RUNNING, BTRFS_BALANCE_SYSTEM, btrfs_balance_args,
btrfs_ioc_balance_ctl, btrfs_ioc_balance_progress, btrfs_ioc_balance_v2,
btrfs_ioctl_balance_args,
};
use bitflags::bitflags;
use nix::libc::c_int;
use std::os::{fd::AsRawFd, unix::io::BorrowedFd};
bitflags! {
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct BalanceFlags: u64 {
const DATA = BTRFS_BALANCE_DATA as u64;
const SYSTEM = BTRFS_BALANCE_SYSTEM as u64;
const METADATA = BTRFS_BALANCE_METADATA as u64;
const FORCE = BTRFS_BALANCE_FORCE as u64;
const RESUME = BTRFS_BALANCE_RESUME as u64;
}
}
bitflags! {
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct BalanceArgsFlags: u64 {
const PROFILES = BTRFS_BALANCE_ARGS_PROFILES as u64;
const USAGE = BTRFS_BALANCE_ARGS_USAGE as u64;
const USAGE_RANGE = BTRFS_BALANCE_ARGS_USAGE_RANGE as u64;
const DEVID = BTRFS_BALANCE_ARGS_DEVID as u64;
const DRANGE = BTRFS_BALANCE_ARGS_DRANGE as u64;
const VRANGE = BTRFS_BALANCE_ARGS_VRANGE as u64;
const LIMIT = BTRFS_BALANCE_ARGS_LIMIT as u64;
const LIMIT_RANGE = BTRFS_BALANCE_ARGS_LIMIT_RANGE as u64;
const STRIPES_RANGE = BTRFS_BALANCE_ARGS_STRIPES_RANGE as u64;
const CONVERT = BTRFS_BALANCE_ARGS_CONVERT as u64;
const SOFT = BTRFS_BALANCE_ARGS_SOFT as u64;
}
}
bitflags! {
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct BalanceState: u64 {
const RUNNING = BTRFS_BALANCE_STATE_RUNNING as u64;
const PAUSE_REQ = BTRFS_BALANCE_STATE_PAUSE_REQ as u64;
const CANCEL_REQ = BTRFS_BALANCE_STATE_CANCEL_REQ as u64;
}
}
#[derive(Clone)]
pub struct BalanceArgs {
raw: btrfs_balance_args,
}
impl std::fmt::Debug for BalanceArgs {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let flags = self.raw.flags;
let profiles = self.raw.profiles;
let devid = self.raw.devid;
let pstart = self.raw.pstart;
let pend = self.raw.pend;
let vstart = self.raw.vstart;
let vend = self.raw.vend;
let target = self.raw.target;
let stripes_min = self.raw.stripes_min;
let stripes_max = self.raw.stripes_max;
f.debug_struct("BalanceArgs")
.field("flags", &flags)
.field("profiles", &profiles)
.field("devid", &devid)
.field("pstart", &pstart)
.field("pend", &pend)
.field("vstart", &vstart)
.field("vend", &vend)
.field("target", &target)
.field("stripes_min", &stripes_min)
.field("stripes_max", &stripes_max)
.finish()
}
}
impl Default for BalanceArgs {
fn default() -> Self {
Self {
raw: unsafe { std::mem::zeroed() },
}
}
}
impl BalanceArgs {
#[must_use]
pub fn new() -> Self {
Self::default()
}
#[must_use]
pub fn profiles(mut self, profiles: u64) -> Self {
self.raw.profiles = profiles;
self.raw.flags |= BalanceArgsFlags::PROFILES.bits();
self
}
#[must_use]
pub fn usage(mut self, percent: u64) -> Self {
self.raw.__bindgen_anon_1.usage = percent;
self.raw.flags |= BalanceArgsFlags::USAGE.bits();
self
}
#[must_use]
pub fn usage_range(mut self, min: u32, max: u32) -> Self {
self.raw.__bindgen_anon_1.__bindgen_anon_1.usage_min = min;
self.raw.__bindgen_anon_1.__bindgen_anon_1.usage_max = max;
self.raw.flags |= BalanceArgsFlags::USAGE_RANGE.bits();
self
}
#[must_use]
pub fn devid(mut self, devid: u64) -> Self {
self.raw.devid = devid;
self.raw.flags |= BalanceArgsFlags::DEVID.bits();
self
}
#[must_use]
pub fn drange(mut self, start: u64, end: u64) -> Self {
self.raw.pstart = start;
self.raw.pend = end;
self.raw.flags |= BalanceArgsFlags::DRANGE.bits();
self
}
#[must_use]
pub fn vrange(mut self, start: u64, end: u64) -> Self {
self.raw.vstart = start;
self.raw.vend = end;
self.raw.flags |= BalanceArgsFlags::VRANGE.bits();
self
}
#[must_use]
pub fn limit(mut self, limit: u64) -> Self {
self.raw.__bindgen_anon_2.limit = limit;
self.raw.flags |= BalanceArgsFlags::LIMIT.bits();
self
}
#[must_use]
pub fn limit_range(mut self, min: u32, max: u32) -> Self {
self.raw.__bindgen_anon_2.__bindgen_anon_1.limit_min = min;
self.raw.__bindgen_anon_2.__bindgen_anon_1.limit_max = max;
self.raw.flags |= BalanceArgsFlags::LIMIT_RANGE.bits();
self
}
#[must_use]
pub fn stripes_range(mut self, min: u32, max: u32) -> Self {
self.raw.stripes_min = min;
self.raw.stripes_max = max;
self.raw.flags |= BalanceArgsFlags::STRIPES_RANGE.bits();
self
}
#[must_use]
pub fn convert(mut self, profile: u64) -> Self {
self.raw.target = profile;
self.raw.flags |= BalanceArgsFlags::CONVERT.bits();
self
}
#[must_use]
pub fn soft(mut self) -> Self {
self.raw.flags |= BalanceArgsFlags::SOFT.bits();
self
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct BalanceProgress {
pub expected: u64,
pub considered: u64,
pub completed: u64,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum BalanceCtl {
Pause,
Cancel,
}
impl BalanceCtl {
#[allow(clippy::cast_possible_wrap)] fn as_raw(self) -> c_int {
match self {
BalanceCtl::Pause => BTRFS_BALANCE_CTL_PAUSE as c_int,
BalanceCtl::Cancel => BTRFS_BALANCE_CTL_CANCEL as c_int,
}
}
}
pub fn balance(
fd: BorrowedFd,
flags: BalanceFlags,
data: Option<BalanceArgs>,
meta: Option<BalanceArgs>,
sys: Option<BalanceArgs>,
) -> nix::Result<BalanceProgress> {
let mut args: btrfs_ioctl_balance_args = unsafe { std::mem::zeroed() };
args.flags = flags.bits();
if let Some(a) = data {
args.data = a.raw;
}
if let Some(a) = meta {
args.meta = a.raw;
}
if let Some(a) = sys {
args.sys = a.raw;
}
unsafe {
btrfs_ioc_balance_v2(fd.as_raw_fd(), &raw mut args)?;
}
Ok(BalanceProgress {
expected: args.stat.expected,
considered: args.stat.considered,
completed: args.stat.completed,
})
}
pub fn balance_ctl(fd: BorrowedFd, cmd: BalanceCtl) -> nix::Result<()> {
#[allow(clippy::cast_sign_loss)] unsafe {
btrfs_ioc_balance_ctl(fd.as_raw_fd(), cmd.as_raw() as u64)?;
}
Ok(())
}
pub fn balance_progress(
fd: BorrowedFd,
) -> nix::Result<(BalanceState, BalanceProgress)> {
let mut args: btrfs_ioctl_balance_args = unsafe { std::mem::zeroed() };
unsafe {
btrfs_ioc_balance_progress(fd.as_raw_fd(), &raw mut args)?;
}
let state = BalanceState::from_bits_truncate(args.state);
let progress = BalanceProgress {
expected: args.stat.expected,
considered: args.stat.considered,
completed: args.stat.completed,
};
Ok((state, progress))
}