file-restore-daemon/disk: dedup BucketComponents and make size optional

To support nested BucketComponents, it is necessary to dedup them, as
otherwise two components like:
  /foo/bar
  /foo/baz
will result in /foo being shown twice at the first hierarchy.

Also make the size property based on index and optional, as for example
/foo in the example above might not have a size, and bar/baz might have
differing sizes.

Signed-off-by: Stefan Reiter <s.reiter@proxmox.com>
Reviewed-By: Fabian Grünbichler <f.gruenbichler@proxmox.com>
This commit is contained in:
Stefan Reiter 2021-06-30 17:57:56 +02:00 committed by Thomas Lamprecht
parent c2e2078b3f
commit 0dda883994
2 changed files with 14 additions and 12 deletions

View File

@ -208,7 +208,7 @@ fn list(
&c_path[..], &c_path[..],
// this marks the beginning of a filesystem, i.e. '/', so this is a Directory // this marks the beginning of a filesystem, i.e. '/', so this is a Directory
Some(&DirEntryAttribute::Directory { start: 0 }), Some(&DirEntryAttribute::Directory { start: 0 }),
Some(c.1), c.1,
)); ));
} }
} }

View File

@ -44,7 +44,7 @@ lazy_static! {
pub enum ResolveResult { pub enum ResolveResult {
Path(PathBuf), Path(PathBuf),
BucketTypes(Vec<&'static str>), BucketTypes(Vec<&'static str>),
BucketComponents(Vec<(String, u64)>), BucketComponents(Vec<(String, Option<u64>)>),
} }
#[derive(Clone)] #[derive(Clone)]
@ -59,7 +59,7 @@ struct PartitionBucketData {
struct ZFSBucketData { struct ZFSBucketData {
name: String, name: String,
mountpoint: Option<PathBuf>, mountpoint: Option<PathBuf>,
size: u64, size: Option<u64>,
} }
/// A "Bucket" represents a mapping found on a disk, e.g. a partition, a zfs dataset or an LV. A /// A "Bucket" represents a mapping found on a disk, e.g. a partition, a zfs dataset or an LV. A
@ -139,9 +139,9 @@ impl Bucket {
}) })
} }
fn size(&self) -> u64 { fn size(&self, idx: usize) -> Option<u64> {
match self { match self {
Bucket::Partition(data) | Bucket::RawFs(data) => data.size, Bucket::Partition(data) | Bucket::RawFs(data) => Some(data.size),
Bucket::ZPool(data) => data.size, Bucket::ZPool(data) => data.size,
} }
} }
@ -261,7 +261,7 @@ impl Filesystems {
cmd.args(["list", "-o", "size", "-Hp", &data.name].iter()); cmd.args(["list", "-o", "size", "-Hp", &data.name].iter());
let size = run_command(cmd, None)?; let size = run_command(cmd, None)?;
if let Ok(size) = size.trim().parse::<u64>() { if let Ok(size) = size.trim().parse::<u64>() {
data.size = size; data.size = Some(size);
} }
let mp = PathBuf::from(mntpath); let mp = PathBuf::from(mntpath);
@ -409,7 +409,7 @@ impl DiskState {
for (pool, disks) in Self::parse_zpool_import(&result) { for (pool, disks) in Self::parse_zpool_import(&result) {
let mut bucket = Bucket::ZPool(ZFSBucketData { let mut bucket = Bucket::ZPool(ZFSBucketData {
name: pool.clone(), name: pool.clone(),
size: 0, size: None,
mountpoint: None, mountpoint: None,
}); });
@ -418,11 +418,11 @@ impl DiskState {
if disks.len() <= 5 { if disks.len() <= 5 {
let mp = filesystems.ensure_mounted(&mut bucket); let mp = filesystems.ensure_mounted(&mut bucket);
info!( info!(
"zpool '{}' (on: {:?}) auto-mounted at '{:?}' (size: {}B)", "zpool '{}' (on: {:?}) auto-mounted at '{:?}' (size: {:?})",
&pool, &pool,
&disks, &disks,
mp, mp,
bucket.size() bucket.size(0)
); );
} else { } else {
info!( info!(
@ -503,18 +503,20 @@ impl DiskState {
Some(c) => bail!("invalid bucket component in path: {:?}", c), Some(c) => bail!("invalid bucket component in path: {:?}", c),
None => { None => {
// list bucket components available at this level // list bucket components available at this level
let comps = buckets let mut comps = buckets
.iter() .iter()
.filter_map(|b| { .filter_map(|b| {
if b.type_string() != bucket_type { if b.type_string() != bucket_type {
return None; return None;
} }
match b.component_string(components.len()) { match b.component_string(components.len()) {
Ok(cs) => Some((cs.to_owned(), b.size())), Ok(cs) => Some((cs.to_owned(), b.size(components.len()))),
Err(_) => None, Err(_) => None,
} }
}) })
.collect(); .collect::<Vec<(String, Option<u64>)>>();
comps.sort_by(|a, b| a.0.cmp(&b.0));
comps.dedup();
return Ok(ResolveResult::BucketComponents(comps)); return Ok(ResolveResult::BucketComponents(comps));
} }
}; };