Resize file, without test.

master
WangRunji 7 years ago
parent 37839f316f
commit 9b187374b5

@ -62,7 +62,7 @@ impl Debug for INode {
impl INode { impl INode {
/// Map file block id to disk block id /// Map file block id to disk block id
fn disk_block_id(&self, file_block_id: BlockId) -> Option<BlockId> { fn get_disk_block_id(&self, file_block_id: BlockId) -> Option<BlockId> {
match file_block_id { match file_block_id {
id if id >= self.disk_inode.blocks as BlockId => id if id >= self.disk_inode.blocks as BlockId =>
None, None,
@ -81,6 +81,27 @@ impl INode {
id => unimplemented!("double indirect blocks is not supported"), id => unimplemented!("double indirect blocks is not supported"),
} }
} }
fn set_disk_block_id(&mut self, file_block_id: BlockId, disk_block_id: BlockId) -> Result<(),()> {
match file_block_id {
id if id >= self.disk_inode.blocks as BlockId =>
Err(()),
id if id < NDIRECT => {
self.disk_inode.direct[id] = disk_block_id as u32;
Ok(())
},
id if id < NDIRECT + BLK_NENTRY => {
let disk_block_id = disk_block_id as u32;
let fs = self.fs.upgrade().unwrap();
fs.borrow_mut().device.write_block(
self.disk_inode.indirect as usize,
ENTRY_SIZE * (id - NDIRECT),
disk_block_id.as_buf(),
).unwrap();
Ok(())
}
id => unimplemented!("double indirect blocks is not supported"),
}
}
} }
impl vfs::INode for INode { impl vfs::INode for INode {
@ -102,7 +123,7 @@ impl vfs::INode for INode {
// Read for each block // Read for each block
let mut buf_offset = 0usize; let mut buf_offset = 0usize;
for BlockRange { block, begin, end } in iter { for BlockRange { block, begin, end } in iter {
if let Some(disk_block_id) = self.disk_block_id(block) { if let Some(disk_block_id) = self.get_disk_block_id(block) {
let len = end - begin; let len = end - begin;
fs.borrow_mut().device.read_block(disk_block_id, begin, &mut buf[buf_offset..buf_offset + len]).unwrap(); fs.borrow_mut().device.read_block(disk_block_id, begin, &mut buf[buf_offset..buf_offset + len]).unwrap();
buf_offset += len; buf_offset += len;
@ -124,7 +145,7 @@ impl vfs::INode for INode {
// Read for each block // Read for each block
let mut buf_offset = 0usize; let mut buf_offset = 0usize;
for BlockRange { block, begin, end } in iter { for BlockRange { block, begin, end } in iter {
if let Some(disk_block_id) = self.disk_block_id(block) { if let Some(disk_block_id) = self.get_disk_block_id(block) {
let len = end - begin; let len = end - begin;
fs.borrow_mut().device.write_block(disk_block_id, begin, &buf[buf_offset..buf_offset + len]).unwrap(); fs.borrow_mut().device.write_block(disk_block_id, begin, &buf[buf_offset..buf_offset + len]).unwrap();
buf_offset += len; buf_offset += len;
@ -156,6 +177,37 @@ impl vfs::INode for INode {
fn type_(&self) -> Result<u32, ()> { fn type_(&self) -> Result<u32, ()> {
Ok(self.disk_inode.type_.clone() as u32) Ok(self.disk_inode.type_.clone() as u32)
} }
fn resize(&mut self, len: usize) -> Result<(), ()> {
if self.disk_inode.type_ != FileType::File || len > MAX_FILE_SIZE {
return Err(());
}
let blocks = ((len + BLKSIZE - 1) / BLKSIZE) as u32;
use core::cmp::{Ord, Ordering};
match blocks.cmp(&self.disk_inode.blocks) {
Ordering::Equal => {}, // Do nothing
Ordering::Greater => {
let fs = self.fs.upgrade().unwrap();
let old_blocks = self.disk_inode.blocks;
self.disk_inode.blocks = blocks;
// allocate extra blocks
for i in old_blocks .. blocks {
let disk_block_id = fs.borrow_mut().alloc_block().expect("no more space");
self.set_disk_block_id(i as usize, disk_block_id).unwrap();
}
},
Ordering::Less => {
let fs = self.fs.upgrade().unwrap();
// free extra blocks
for i in blocks .. self.disk_inode.blocks {
let disk_block_id = self.get_disk_block_id(i as usize).unwrap();
fs.borrow_mut().free_block(disk_block_id);
}
self.disk_inode.blocks = blocks;
},
}
self.disk_inode.size = len as u32;
Ok(())
}
} }
/// Given a range and iterate sub-range for each block /// Given a range and iterate sub-range for each block

@ -13,7 +13,7 @@ pub trait INode {
// fn reclaim(&mut self) -> Result<(), ()>; // fn reclaim(&mut self) -> Result<(), ()>;
fn type_(&self) -> Result<u32, ()>; fn type_(&self) -> Result<u32, ()>;
// fn try_seek(&mut self, offset: u64) -> Result<(), ()>; // fn try_seek(&mut self, offset: u64) -> Result<(), ()>;
// fn truncate(&mut self, len: u64) -> Result<(), ()>; fn resize(&mut self, len: usize) -> Result<(), ()>;
// fn create(&mut self, name: &'static str, excl: bool) -> Result<(), ()>; // fn create(&mut self, name: &'static str, excl: bool) -> Result<(), ()>;
// fn loopup(&mut self, path: &'static str) -> Result<(), ()>; // fn loopup(&mut self, path: &'static str) -> Result<(), ()>;
// fn io_ctrl(&mut self, op: u32, data: &[u8]) -> Result<(), ()>; // fn io_ctrl(&mut self, op: u32, data: &[u8]) -> Result<(), ()>;

Loading…
Cancel
Save