mirror of
https://git.proxmox.com/git/proxmox-offline-mirror
synced 2025-08-15 20:13:58 +00:00
pool: gc: remove empty directories under link_dir
garbage collection currently is quite aggressive in removing all files under the link_dir, which are not a hard-link to a checksum file. removing directories that remain empty below the link_dir should thus not too dangerous. without this patch, removing a snapshot on a mirror, running gc there, and syncing everything to a medium, leaves the medium with an hierarchy of empty directories below the removed snapshot (the files get cleaned up the directories remain). using WalkDir::content_first() seems better than to check for emptiness after each file-removal [0] [0] https://docs.rs/walkdir/latest/walkdir/struct.WalkDir.html#method.contents_first Signed-off-by: Stoiko Ivanov <s.ivanov@proxmox.com>
This commit is contained in:
parent
2089e5d4b0
commit
24c697e8cd
13
src/pool.rs
13
src/pool.rs
@ -451,6 +451,7 @@ impl PoolLockGuard<'_> {
|
|||||||
/// Run a garbage collection, removing
|
/// Run a garbage collection, removing
|
||||||
/// - any checksum files that have no links outside of `pool_dir`
|
/// - any checksum files that have no links outside of `pool_dir`
|
||||||
/// - any files in `link_dir` that have no corresponding checksum files
|
/// - any files in `link_dir` that have no corresponding checksum files
|
||||||
|
/// - any empty directories below `link_dir` remaining after the file removal
|
||||||
pub(crate) fn gc(&self) -> Result<(usize, u64), Error> {
|
pub(crate) fn gc(&self) -> Result<(usize, u64), Error> {
|
||||||
let (inode_map, _link_count) = self.get_inode_csum_map()?;
|
let (inode_map, _link_count) = self.get_inode_csum_map()?;
|
||||||
|
|
||||||
@ -459,7 +460,8 @@ impl PoolLockGuard<'_> {
|
|||||||
|
|
||||||
let handle_entry = |entry: Result<walkdir::DirEntry, walkdir::Error>,
|
let handle_entry = |entry: Result<walkdir::DirEntry, walkdir::Error>,
|
||||||
count: &mut usize,
|
count: &mut usize,
|
||||||
size: &mut u64|
|
size: &mut u64,
|
||||||
|
remove_empty_dir: bool|
|
||||||
-> Result<(), Error> {
|
-> Result<(), Error> {
|
||||||
let path = entry?.into_path();
|
let path = entry?.into_path();
|
||||||
if path == self.lock_path() {
|
if path == self.lock_path() {
|
||||||
@ -467,6 +469,10 @@ impl PoolLockGuard<'_> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let meta = path.metadata()?;
|
let meta = path.metadata()?;
|
||||||
|
if remove_empty_dir && meta.is_dir() && path.read_dir()?.next().is_none() {
|
||||||
|
std::fs::remove_dir(path)?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
if !meta.is_file() {
|
if !meta.is_file() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
};
|
};
|
||||||
@ -507,11 +513,12 @@ impl PoolLockGuard<'_> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
WalkDir::new(&self.pool.link_dir)
|
WalkDir::new(&self.pool.link_dir)
|
||||||
|
.contents_first(true)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.try_for_each(|entry| handle_entry(entry, &mut count, &mut size))?;
|
.try_for_each(|entry| handle_entry(entry, &mut count, &mut size, true))?;
|
||||||
WalkDir::new(&self.pool.pool_dir)
|
WalkDir::new(&self.pool.pool_dir)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.try_for_each(|entry| handle_entry(entry, &mut count, &mut size))?;
|
.try_for_each(|entry| handle_entry(entry, &mut count, &mut size, false))?;
|
||||||
|
|
||||||
Ok((count, size))
|
Ok((count, size))
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user