1use crate::raw::{
11 BTRFS_BALANCE_ARGS_CONVERT, BTRFS_BALANCE_ARGS_DEVID,
12 BTRFS_BALANCE_ARGS_DRANGE, BTRFS_BALANCE_ARGS_LIMIT,
13 BTRFS_BALANCE_ARGS_LIMIT_RANGE, BTRFS_BALANCE_ARGS_PROFILES,
14 BTRFS_BALANCE_ARGS_SOFT, BTRFS_BALANCE_ARGS_STRIPES_RANGE,
15 BTRFS_BALANCE_ARGS_USAGE, BTRFS_BALANCE_ARGS_USAGE_RANGE,
16 BTRFS_BALANCE_ARGS_VRANGE, BTRFS_BALANCE_CTL_CANCEL,
17 BTRFS_BALANCE_CTL_PAUSE, BTRFS_BALANCE_DATA, BTRFS_BALANCE_FORCE,
18 BTRFS_BALANCE_METADATA, BTRFS_BALANCE_RESUME,
19 BTRFS_BALANCE_STATE_CANCEL_REQ, BTRFS_BALANCE_STATE_PAUSE_REQ,
20 BTRFS_BALANCE_STATE_RUNNING, BTRFS_BALANCE_SYSTEM, btrfs_balance_args,
21 btrfs_ioc_balance_ctl, btrfs_ioc_balance_progress, btrfs_ioc_balance_v2,
22 btrfs_ioctl_balance_args,
23};
24use bitflags::bitflags;
25use nix::libc::c_int;
26use std::os::{fd::AsRawFd, unix::io::BorrowedFd};
27
28bitflags! {
29 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
31 pub struct BalanceFlags: u64 {
32 const DATA = BTRFS_BALANCE_DATA as u64;
34 const SYSTEM = BTRFS_BALANCE_SYSTEM as u64;
36 const METADATA = BTRFS_BALANCE_METADATA as u64;
38 const FORCE = BTRFS_BALANCE_FORCE as u64;
40 const RESUME = BTRFS_BALANCE_RESUME as u64;
42 }
43}
44
45bitflags! {
46 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
48 pub struct BalanceArgsFlags: u64 {
49 const PROFILES = BTRFS_BALANCE_ARGS_PROFILES as u64;
51 const USAGE = BTRFS_BALANCE_ARGS_USAGE as u64;
53 const USAGE_RANGE = BTRFS_BALANCE_ARGS_USAGE_RANGE as u64;
55 const DEVID = BTRFS_BALANCE_ARGS_DEVID as u64;
57 const DRANGE = BTRFS_BALANCE_ARGS_DRANGE as u64;
59 const VRANGE = BTRFS_BALANCE_ARGS_VRANGE as u64;
61 const LIMIT = BTRFS_BALANCE_ARGS_LIMIT as u64;
63 const LIMIT_RANGE = BTRFS_BALANCE_ARGS_LIMIT_RANGE as u64;
65 const STRIPES_RANGE = BTRFS_BALANCE_ARGS_STRIPES_RANGE as u64;
67 const CONVERT = BTRFS_BALANCE_ARGS_CONVERT as u64;
69 const SOFT = BTRFS_BALANCE_ARGS_SOFT as u64;
71 }
72}
73
74bitflags! {
75 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
77 pub struct BalanceState: u64 {
78 const RUNNING = BTRFS_BALANCE_STATE_RUNNING as u64;
80 const PAUSE_REQ = BTRFS_BALANCE_STATE_PAUSE_REQ as u64;
82 const CANCEL_REQ = BTRFS_BALANCE_STATE_CANCEL_REQ as u64;
84 }
85}
86
87#[derive(Clone)]
93pub struct BalanceArgs {
94 raw: btrfs_balance_args,
95}
96
97impl std::fmt::Debug for BalanceArgs {
98 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
99 let flags = self.raw.flags;
102 let profiles = self.raw.profiles;
103 let devid = self.raw.devid;
104 let pstart = self.raw.pstart;
105 let pend = self.raw.pend;
106 let vstart = self.raw.vstart;
107 let vend = self.raw.vend;
108 let target = self.raw.target;
109 let stripes_min = self.raw.stripes_min;
110 let stripes_max = self.raw.stripes_max;
111 f.debug_struct("BalanceArgs")
112 .field("flags", &flags)
113 .field("profiles", &profiles)
114 .field("devid", &devid)
115 .field("pstart", &pstart)
116 .field("pend", &pend)
117 .field("vstart", &vstart)
118 .field("vend", &vend)
119 .field("target", &target)
120 .field("stripes_min", &stripes_min)
121 .field("stripes_max", &stripes_max)
122 .finish()
123 }
124}
125
126impl Default for BalanceArgs {
127 fn default() -> Self {
128 Self {
129 raw: unsafe { std::mem::zeroed() },
130 }
131 }
132}
133
134impl BalanceArgs {
135 #[must_use]
137 pub fn new() -> Self {
138 Self::default()
139 }
140
141 #[must_use]
144 pub fn profiles(mut self, profiles: u64) -> Self {
145 self.raw.profiles = profiles;
146 self.raw.flags |= BalanceArgsFlags::PROFILES.bits();
147 self
148 }
149
150 #[must_use]
152 pub fn usage(mut self, percent: u64) -> Self {
153 self.raw.__bindgen_anon_1.usage = percent;
156 self.raw.flags |= BalanceArgsFlags::USAGE.bits();
157 self
158 }
159
160 #[must_use]
162 pub fn usage_range(mut self, min: u32, max: u32) -> Self {
163 self.raw.__bindgen_anon_1.__bindgen_anon_1.usage_min = min;
164 self.raw.__bindgen_anon_1.__bindgen_anon_1.usage_max = max;
165 self.raw.flags |= BalanceArgsFlags::USAGE_RANGE.bits();
166 self
167 }
168
169 #[must_use]
171 pub fn devid(mut self, devid: u64) -> Self {
172 self.raw.devid = devid;
173 self.raw.flags |= BalanceArgsFlags::DEVID.bits();
174 self
175 }
176
177 #[must_use]
179 pub fn drange(mut self, start: u64, end: u64) -> Self {
180 self.raw.pstart = start;
181 self.raw.pend = end;
182 self.raw.flags |= BalanceArgsFlags::DRANGE.bits();
183 self
184 }
185
186 #[must_use]
188 pub fn vrange(mut self, start: u64, end: u64) -> Self {
189 self.raw.vstart = start;
190 self.raw.vend = end;
191 self.raw.flags |= BalanceArgsFlags::VRANGE.bits();
192 self
193 }
194
195 #[must_use]
197 pub fn limit(mut self, limit: u64) -> Self {
198 self.raw.__bindgen_anon_2.limit = limit;
199 self.raw.flags |= BalanceArgsFlags::LIMIT.bits();
200 self
201 }
202
203 #[must_use]
205 pub fn limit_range(mut self, min: u32, max: u32) -> Self {
206 self.raw.__bindgen_anon_2.__bindgen_anon_1.limit_min = min;
207 self.raw.__bindgen_anon_2.__bindgen_anon_1.limit_max = max;
208 self.raw.flags |= BalanceArgsFlags::LIMIT_RANGE.bits();
209 self
210 }
211
212 #[must_use]
214 pub fn stripes_range(mut self, min: u32, max: u32) -> Self {
215 self.raw.stripes_min = min;
216 self.raw.stripes_max = max;
217 self.raw.flags |= BalanceArgsFlags::STRIPES_RANGE.bits();
218 self
219 }
220
221 #[must_use]
223 pub fn convert(mut self, profile: u64) -> Self {
224 self.raw.target = profile;
225 self.raw.flags |= BalanceArgsFlags::CONVERT.bits();
226 self
227 }
228
229 #[must_use]
231 pub fn soft(mut self) -> Self {
232 self.raw.flags |= BalanceArgsFlags::SOFT.bits();
233 self
234 }
235}
236
237#[derive(Debug, Clone, Copy, PartialEq, Eq)]
239pub struct BalanceProgress {
240 pub expected: u64,
242 pub considered: u64,
244 pub completed: u64,
246}
247
248#[derive(Debug, Clone, Copy, PartialEq, Eq)]
250pub enum BalanceCtl {
251 Pause,
253 Cancel,
255}
256
257impl BalanceCtl {
258 fn as_raw(self) -> c_int {
259 match self {
260 BalanceCtl::Pause => BTRFS_BALANCE_CTL_PAUSE as c_int,
261 BalanceCtl::Cancel => BTRFS_BALANCE_CTL_CANCEL as c_int,
262 }
263 }
264}
265
266pub fn balance(
275 fd: BorrowedFd,
276 flags: BalanceFlags,
277 data: Option<BalanceArgs>,
278 meta: Option<BalanceArgs>,
279 sys: Option<BalanceArgs>,
280) -> nix::Result<BalanceProgress> {
281 let mut args: btrfs_ioctl_balance_args = unsafe { std::mem::zeroed() };
282
283 args.flags = flags.bits();
284
285 if let Some(a) = data {
286 args.data = a.raw;
287 }
288 if let Some(a) = meta {
289 args.meta = a.raw;
290 }
291 if let Some(a) = sys {
292 args.sys = a.raw;
293 }
294
295 unsafe {
296 btrfs_ioc_balance_v2(fd.as_raw_fd(), &raw mut args)?;
297 }
298
299 Ok(BalanceProgress {
300 expected: args.stat.expected,
301 considered: args.stat.considered,
302 completed: args.stat.completed,
303 })
304}
305
306pub fn balance_ctl(fd: BorrowedFd, cmd: BalanceCtl) -> nix::Result<()> {
311 unsafe {
312 btrfs_ioc_balance_ctl(fd.as_raw_fd(), cmd.as_raw() as u64)?;
313 }
314 Ok(())
315}
316
317pub fn balance_progress(
324 fd: BorrowedFd,
325) -> nix::Result<(BalanceState, BalanceProgress)> {
326 let mut args: btrfs_ioctl_balance_args = unsafe { std::mem::zeroed() };
327
328 unsafe {
329 btrfs_ioc_balance_progress(fd.as_raw_fd(), &raw mut args)?;
330 }
331
332 let state = BalanceState::from_bits_truncate(args.state);
333 let progress = BalanceProgress {
334 expected: args.stat.expected,
335 considered: args.stat.considered,
336 completed: args.stat.completed,
337 };
338
339 Ok((state, progress))
340}