Skip to content

Commit

Permalink
rufs: finish inode_shrink()
Browse files Browse the repository at this point in the history
  • Loading branch information
realchonk committed Nov 1, 2024
1 parent 815de23 commit 51a3bdc
Showing 1 changed file with 109 additions and 8 deletions.
117 changes: 109 additions & 8 deletions rufs/src/ufs/ialloc.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::mem::replace;

use super::*;
use crate::{err, InodeNum};

Expand Down Expand Up @@ -64,6 +66,17 @@ impl<R: Backend> Ufs<R> {
self.file.read_at(bno * fs, block)
}

fn write_pblock(&mut self, bno: u64, block: &[u64]) -> IoResult<()> {
let fs = self.superblock.fsize as u64;
let block = unsafe {
std::slice::from_raw_parts(
block.as_ptr() as *const u8,
block.len() * size_of::<u64>(),
)
};
self.file.write_at(bno * fs, block)
}

fn inode_free_l1(&mut self, ino: &Inode, bno: u64, block: &mut Vec<u64>) -> IoResult<()> {
if bno == 0 {
return Ok(());
Expand Down Expand Up @@ -176,28 +189,116 @@ impl<R: Backend> Ufs<R> {
Ok(())
}

fn inode_shrink(&mut self, ino: &mut Inode, size: u64) -> IoResult<()> {
fn inode_shrink(&mut self, ino: &mut Inode) -> IoResult<()> {
let (begin_indir1, begin_indir2, begin_indir3, _) = self.inode_data_zones();
let sb = &self.superblock;
let bs = sb.bsize as u64;
let fs = sb.fsize as u64;
let (blocks, frags) = ino.size(bs, fs);
let blocks = blocks + (frags > 0) as u64;
let pbp = bs / size_of::<u64>() as u64;
let nd = UFS_NDADDR as u64;

let InodeData::Blocks(iblocks) = ino.data.clone() else {
let InodeData::Blocks(mut iblocks) = ino.data.clone() else {
return Err(err!(EINVAL));
};

if blocks > begin_indir3 {
todo!();
let mut block = vec![0u64; bs as usize / size_of::<u64>()];

if blocks >= begin_indir3 {
let used = blocks - nd - pbp - (pbp * pbp);
self.read_pblock(iblocks.indirect[2] as u64, &mut block)?;
let mut fst = block.clone();

let off1 = used / pbp / pbp;
let off2 = used / pbp % pbp;
let off3 = used % pbp;

// handle the first table separately, as it only needs to be partially freed
self.read_pblock(fst[off1 as usize], &mut block)?;
let mut snd = block.clone();
self.read_pblock(snd[off2 as usize], &mut block)?;
for i in off3..pbp {
let bno = replace(&mut block[i as usize], 0);
let size = self.inode_get_block_size(ino, bno);
self.blk_free(bno, size as u64)?;
}
self.write_pblock(snd[off2 as usize], &mut block)?;
for i in (off2 + 1)..pbp {
let bno = replace(&mut snd[i as usize], 0);
self.inode_free_l1(ino, bno, &mut block)?;
}
self.write_pblock(fst[off1 as usize], &snd)?;

// the remaining tables can be freed completely
for i in (off1 + 1)..pbp {
let bno = replace(&mut fst[i as usize], 0);
self.inode_free_l2(ino, bno, &mut block)?;
}

self.write_pblock(iblocks.indirect[2] as u64, &block)?;
ino.data = InodeData::Blocks(iblocks);
return Ok(());
}

let mut block = vec![0u64; bs as usize / size_of::<u64>()];

self.inode_free_l3(ino, iblocks.indirect[2] as u64, &mut block)?;

todo!();
if blocks >= begin_indir2 {
let used = blocks - nd - pbp;
self.read_pblock(iblocks.indirect[1] as u64, &mut block)?;
let mut fst = block.clone();

let off1 = used / pbp;
let off2 = used % pbp;

// handle the first table specially, as it only needs to be partially freed
self.read_pblock(fst[off1 as usize], &mut block)?;
for i in off2..pbp {
let bno = replace(&mut block[i as usize], 0);
let size = self.inode_get_block_size(ino, bno);
self.blk_free(bno as u64, size as u64)?;
}
self.write_pblock(fst[off1 as usize], &block)?;

// the remaining tables can be freed completely
for i in (off1 + 1)..pbp {
let bno = replace(&mut fst[i as usize], 0);
self.inode_free_l1(ino, bno, &mut block)?;
}

self.write_pblock(iblocks.indirect[1] as u64, &fst)?;
ino.data = InodeData::Blocks(iblocks);
return Ok(());
}

self.inode_free_l2(ino, iblocks.indirect[1] as u64, &mut block)?;

if blocks >= begin_indir1 {
let used = blocks - nd;
self.read_pblock(iblocks.indirect[0] as u64, &mut block)?;

for i in used..pbp {
let bno = replace(&mut block[i as usize], 0);
let size = self.inode_get_block_size(ino, bno);
self.blk_free(bno as u64, size as u64)?;
}

self.write_pblock(iblocks.indirect[0] as u64, &block)?;

ino.data = InodeData::Blocks(iblocks);
return Ok(());
}

self.inode_free_l1(ino, iblocks.indirect[0] as u64, &mut block)?;

for i in (blocks as usize)..UFS_NDADDR {
let bno = replace(&mut iblocks.direct[i], 0) as u64;
let size = self.inode_get_block_size(ino, bno);
self.blk_free(bno, size as u64)?;
}

ino.data = InodeData::Blocks(iblocks);
Ok(())
}

pub fn inode_truncate(&mut self, inr: InodeNum, new_size: u64) -> IoResult<()> {
Expand All @@ -208,7 +309,7 @@ impl<R: Backend> Ufs<R> {
ino.size = new_size;

if new_size < old_size {
self.inode_shrink(&mut ino, new_size)?;
self.inode_shrink(&mut ino)?;
}

self.write_inode(inr, &ino)?;
Expand Down

0 comments on commit 51a3bdc

Please sign in to comment.