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:
parent
c2e2078b3f
commit
0dda883994
|
@ -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,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue