1use crate::raw::*;
11use bitflags::bitflags;
12use nix::libc::c_int;
13use std::os::{fd::AsRawFd, unix::io::BorrowedFd};
14
15bitflags! {
16 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
18 pub struct BalanceFlags: u64 {
19 const DATA = BTRFS_BALANCE_DATA as u64;
21 const SYSTEM = BTRFS_BALANCE_SYSTEM as u64;
23 const METADATA = BTRFS_BALANCE_METADATA as u64;
25 const FORCE = BTRFS_BALANCE_FORCE as u64;
27 const RESUME = BTRFS_BALANCE_RESUME as u64;
29 }
30}
31
32bitflags! {
33 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
35 pub struct BalanceArgsFlags: u64 {
36 const PROFILES = BTRFS_BALANCE_ARGS_PROFILES as u64;
38 const USAGE = BTRFS_BALANCE_ARGS_USAGE as u64;
40 const USAGE_RANGE = BTRFS_BALANCE_ARGS_USAGE_RANGE as u64;
42 const DEVID = BTRFS_BALANCE_ARGS_DEVID as u64;
44 const DRANGE = BTRFS_BALANCE_ARGS_DRANGE as u64;
46 const VRANGE = BTRFS_BALANCE_ARGS_VRANGE as u64;
48 const LIMIT = BTRFS_BALANCE_ARGS_LIMIT as u64;
50 const LIMIT_RANGE = BTRFS_BALANCE_ARGS_LIMIT_RANGE as u64;
52 const STRIPES_RANGE = BTRFS_BALANCE_ARGS_STRIPES_RANGE as u64;
54 const CONVERT = BTRFS_BALANCE_ARGS_CONVERT as u64;
56 const SOFT = BTRFS_BALANCE_ARGS_SOFT as u64;
58 }
59}
60
61bitflags! {
62 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
64 pub struct BalanceState: u64 {
65 const RUNNING = BTRFS_BALANCE_STATE_RUNNING as u64;
67 const PAUSE_REQ = BTRFS_BALANCE_STATE_PAUSE_REQ as u64;
69 const CANCEL_REQ = BTRFS_BALANCE_STATE_CANCEL_REQ as u64;
71 }
72}
73
74#[derive(Clone)]
80pub struct BalanceArgs {
81 raw: btrfs_balance_args,
82}
83
84impl std::fmt::Debug for BalanceArgs {
85 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
86 let flags = self.raw.flags;
89 let profiles = self.raw.profiles;
90 let devid = self.raw.devid;
91 let pstart = self.raw.pstart;
92 let pend = self.raw.pend;
93 let vstart = self.raw.vstart;
94 let vend = self.raw.vend;
95 let target = self.raw.target;
96 let stripes_min = self.raw.stripes_min;
97 let stripes_max = self.raw.stripes_max;
98 f.debug_struct("BalanceArgs")
99 .field("flags", &flags)
100 .field("profiles", &profiles)
101 .field("devid", &devid)
102 .field("pstart", &pstart)
103 .field("pend", &pend)
104 .field("vstart", &vstart)
105 .field("vend", &vend)
106 .field("target", &target)
107 .field("stripes_min", &stripes_min)
108 .field("stripes_max", &stripes_max)
109 .finish()
110 }
111}
112
113impl Default for BalanceArgs {
114 fn default() -> Self {
115 Self {
116 raw: unsafe { std::mem::zeroed() },
117 }
118 }
119}
120
121impl BalanceArgs {
122 pub fn new() -> Self {
124 Self::default()
125 }
126
127 pub fn profiles(mut self, profiles: u64) -> Self {
130 self.raw.profiles = profiles;
131 self.raw.flags |= BalanceArgsFlags::PROFILES.bits();
132 self
133 }
134
135 pub fn usage(mut self, percent: u64) -> Self {
137 self.raw.__bindgen_anon_1.usage = percent;
140 self.raw.flags |= BalanceArgsFlags::USAGE.bits();
141 self
142 }
143
144 pub fn usage_range(mut self, min: u32, max: u32) -> Self {
146 self.raw.__bindgen_anon_1.__bindgen_anon_1.usage_min = min;
147 self.raw.__bindgen_anon_1.__bindgen_anon_1.usage_max = max;
148 self.raw.flags |= BalanceArgsFlags::USAGE_RANGE.bits();
149 self
150 }
151
152 pub fn devid(mut self, devid: u64) -> Self {
154 self.raw.devid = devid;
155 self.raw.flags |= BalanceArgsFlags::DEVID.bits();
156 self
157 }
158
159 pub fn drange(mut self, start: u64, end: u64) -> Self {
161 self.raw.pstart = start;
162 self.raw.pend = end;
163 self.raw.flags |= BalanceArgsFlags::DRANGE.bits();
164 self
165 }
166
167 pub fn vrange(mut self, start: u64, end: u64) -> Self {
169 self.raw.vstart = start;
170 self.raw.vend = end;
171 self.raw.flags |= BalanceArgsFlags::VRANGE.bits();
172 self
173 }
174
175 pub fn limit(mut self, limit: u64) -> Self {
177 self.raw.__bindgen_anon_2.limit = limit;
178 self.raw.flags |= BalanceArgsFlags::LIMIT.bits();
179 self
180 }
181
182 pub fn limit_range(mut self, min: u32, max: u32) -> Self {
184 self.raw.__bindgen_anon_2.__bindgen_anon_1.limit_min = min;
185 self.raw.__bindgen_anon_2.__bindgen_anon_1.limit_max = max;
186 self.raw.flags |= BalanceArgsFlags::LIMIT_RANGE.bits();
187 self
188 }
189
190 pub fn stripes_range(mut self, min: u32, max: u32) -> Self {
192 self.raw.stripes_min = min;
193 self.raw.stripes_max = max;
194 self.raw.flags |= BalanceArgsFlags::STRIPES_RANGE.bits();
195 self
196 }
197
198 pub fn convert(mut self, profile: u64) -> Self {
200 self.raw.target = profile;
201 self.raw.flags |= BalanceArgsFlags::CONVERT.bits();
202 self
203 }
204
205 pub fn soft(mut self) -> Self {
207 self.raw.flags |= BalanceArgsFlags::SOFT.bits();
208 self
209 }
210}
211
212#[derive(Debug, Clone, Copy, PartialEq, Eq)]
214pub struct BalanceProgress {
215 pub expected: u64,
217 pub considered: u64,
219 pub completed: u64,
221}
222
223#[derive(Debug, Clone, Copy, PartialEq, Eq)]
225pub enum BalanceCtl {
226 Pause,
228 Cancel,
230}
231
232impl BalanceCtl {
233 fn as_raw(self) -> c_int {
234 match self {
235 BalanceCtl::Pause => BTRFS_BALANCE_CTL_PAUSE as c_int,
236 BalanceCtl::Cancel => BTRFS_BALANCE_CTL_CANCEL as c_int,
237 }
238 }
239}
240
241pub fn balance(
250 fd: BorrowedFd,
251 flags: BalanceFlags,
252 data: Option<BalanceArgs>,
253 meta: Option<BalanceArgs>,
254 sys: Option<BalanceArgs>,
255) -> nix::Result<BalanceProgress> {
256 let mut args: btrfs_ioctl_balance_args = unsafe { std::mem::zeroed() };
257
258 args.flags = flags.bits();
259
260 if let Some(a) = data {
261 args.data = a.raw;
262 }
263 if let Some(a) = meta {
264 args.meta = a.raw;
265 }
266 if let Some(a) = sys {
267 args.sys = a.raw;
268 }
269
270 unsafe {
271 btrfs_ioc_balance_v2(fd.as_raw_fd(), &mut args)?;
272 }
273
274 Ok(BalanceProgress {
275 expected: args.stat.expected,
276 considered: args.stat.considered,
277 completed: args.stat.completed,
278 })
279}
280
281pub fn balance_ctl(fd: BorrowedFd, cmd: BalanceCtl) -> nix::Result<()> {
286 unsafe {
287 btrfs_ioc_balance_ctl(fd.as_raw_fd(), cmd.as_raw() as u64)?;
288 }
289 Ok(())
290}
291
292pub fn balance_progress(fd: BorrowedFd) -> nix::Result<(BalanceState, BalanceProgress)> {
299 let mut args: btrfs_ioctl_balance_args = unsafe { std::mem::zeroed() };
300
301 unsafe {
302 btrfs_ioc_balance_progress(fd.as_raw_fd(), &mut args)?;
303 }
304
305 let state = BalanceState::from_bits_truncate(args.state);
306 let progress = BalanceProgress {
307 expected: args.stat.expected,
308 considered: args.stat.considered,
309 completed: args.stat.completed,
310 };
311
312 Ok((state, progress))
313}