use crate::dir::fetch::lfs_dir_fetch;
use crate::dir::LfsMdir;
pub fn lfs_fs_mkconsistent_(lfs: *mut super::lfs::Lfs) -> i32 {
use crate::dir::commit::lfs_dir_commit;
use crate::lfs_gstate::{lfs_gstate_iszero, lfs_gstate_xor};
let err = super::superblock::lfs_fs_forceconsistency(lfs);
if err != 0 {
return crate::lfs_pass_err!(err);
}
unsafe {
let mut delta = crate::lfs_gstate::LfsGstate {
tag: 0,
pair: [0, 0],
};
lfs_gstate_xor(&mut delta, &(*lfs).gdisk);
lfs_gstate_xor(&mut delta, &(*lfs).gstate);
if !lfs_gstate_iszero(&delta) {
let mut root = core::mem::zeroed::<LfsMdir>();
let err = lfs_dir_fetch(lfs, &mut root, &(*lfs).root);
if err != 0 {
return crate::lfs_pass_err!(err);
}
let err = lfs_dir_commit(lfs, &mut root, core::ptr::null(), 0);
if err != 0 {
return crate::lfs_pass_err!(err);
}
}
}
0
}
pub fn lfs_fs_gc_(lfs: *mut super::lfs::Lfs) -> i32 {
use crate::block_alloc::alloc::lfs_alloc_scan;
use crate::dir::commit::lfs_dir_commit;
use crate::util::{lfs_min, lfs_pair_isnull};
crate::lfs_trace!("lfs_fs_gc: start");
let err = super::superblock::lfs_fs_forceconsistency(lfs);
crate::lfs_trace!("lfs_fs_gc: after forceconsistency err={}", err);
if err != 0 {
return crate::lfs_pass_err!(err);
}
unsafe {
let lfs_ref = &*lfs;
let cfg = lfs_ref.cfg.as_ref().expect("cfg");
let block_size = cfg.block_size;
let prog_size = cfg.prog_size;
let compact_thresh = cfg.compact_thresh;
if compact_thresh < block_size.saturating_sub(prog_size) {
crate::lfs_trace!("lfs_fs_gc: compact loop start");
let mut mdir = LfsMdir {
pair: [0, 0],
rev: 0,
off: 0,
etag: 0,
count: 0,
erased: false,
split: false,
tail: [0, 1],
};
#[cfg(feature = "loop_limits")]
const MAX_GC_COMPACT_ITER: u32 = 2048;
#[cfg(feature = "loop_limits")]
let mut iter: u32 = 0;
while !lfs_pair_isnull(&mdir.tail) {
#[cfg(feature = "loop_limits")]
{
if iter >= MAX_GC_COMPACT_ITER {
panic!(
"loop_limits: MAX_GC_COMPACT_ITER ({}) exceeded",
MAX_GC_COMPACT_ITER
);
}
iter += 1;
}
let err = lfs_dir_fetch(lfs, &mut mdir, &mdir.tail);
if err != 0 {
return crate::lfs_pass_err!(err);
}
let should_compact = !mdir.erased
|| if compact_thresh == 0 {
mdir.off > block_size - block_size / 8
} else {
mdir.off > compact_thresh
};
if should_compact {
let mdir_ref = &mut mdir;
mdir_ref.erased = false;
let err = lfs_dir_commit(lfs, mdir_ref, core::ptr::null(), 0);
if err != 0 {
return crate::lfs_pass_err!(err);
}
}
}
}
let lfs_ref = &*lfs;
let lookahead_size = cfg.lookahead_size;
let block_count = lfs_ref.block_count;
if lfs_ref.lookahead.size < lfs_min(8 * lookahead_size, block_count) {
crate::lfs_trace!("lfs_fs_gc: alloc_scan start");
let err = lfs_alloc_scan(lfs);
crate::lfs_trace!("lfs_fs_gc: alloc_scan done err={}", err);
if err != 0 {
return crate::lfs_pass_err!(err);
}
}
}
0
}