begin switching to limited data size per file
This commit is contained in:
parent
e7d5daa623
commit
bdd7ba3f36
3 changed files with 502 additions and 247 deletions
|
@ -6,4 +6,5 @@ edition = "2021"
|
|||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
vapfs = { path = "../vapfs" }
|
||||
vapfs = { path = "../vapfs" }
|
||||
ondisk_btree = { path = "../../ondisk_btree" }
|
636
src/lib.rs
636
src/lib.rs
|
@ -296,80 +296,157 @@ pub fn next_journal_position(sb: &Superblock, bd: &mut dyn BlockDevice) -> Optio
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns the index of an indirectly indexed datablock, or 0 if it does not exist.
|
||||
pub fn get_indirect_datablock(sb: &Superblock, bd: &mut dyn BlockDevice, dbas: [Index; 12], address: Index) -> Index {
|
||||
if address < 12 {
|
||||
dbas[address as usize]
|
||||
/// Returns the index of the containing indirect block for the given dba address and the index in that indirect block, or None if the address is invalid.
|
||||
pub fn get_indirect_datablock(sb: &Superblock, bd: &mut dyn BlockDevice, list: ListBlock, address: Index) -> Option<(Index, Index)> {
|
||||
if address < 32 {
|
||||
None
|
||||
} else {
|
||||
let n = address - 12;
|
||||
let mut blocks_left = n / (sb.block_size as u64 - 8);
|
||||
let mut indexes_left = n % (sb.block_size as u64 - 8);
|
||||
let mut current_block = dbas[9]; // first indirect block
|
||||
let mut visited = vec![];
|
||||
loop {
|
||||
if visited.contains(¤t_block) {
|
||||
return 0;
|
||||
// copy pasted from structs.rs
|
||||
// if greater than 32, see the following:
|
||||
// let N = (maximum number of pointers in an indirect block) * 32
|
||||
// (beginning...count)
|
||||
// 32..N: single indirect block
|
||||
// 32+N..N^2: double indirect block
|
||||
// 32+N^2..N^3: triple indirect block
|
||||
// 32+N^3..N^4: quadruple indirect block
|
||||
// 32+N^4..N^5: quintuple indirect block
|
||||
// 32+N^5..N^6: sextuple indirect block
|
||||
|
||||
// block index is address / (max_per_block ^ (1 if single, 2 if double, etc))
|
||||
// after getting your layer's address, repeat the previous layer's process
|
||||
|
||||
let max_per_block = sb.block_size as u64 / 8;
|
||||
let N = max_per_block * 32;
|
||||
let N2 = N * N;
|
||||
let N3 = N2 * N;
|
||||
let N4 = N3 * N;
|
||||
let N5 = N4 * N;
|
||||
let N6 = N5 * N;
|
||||
|
||||
let mut address = address - 32;
|
||||
|
||||
// todo: you could probably rewrite this using like recursion or smth
|
||||
|
||||
match address {
|
||||
_ if address < N => {
|
||||
let block_index = address / max_per_block;
|
||||
let address = address % max_per_block;
|
||||
Some((list.single_indirect_block_address[block_index as usize], address))
|
||||
}
|
||||
visited.push(current_block);
|
||||
let mut head = 0;
|
||||
let buf = read_datablock(current_block, sb, bd);
|
||||
let count = u64::from_be_bytes(buf[0..8].try_into().unwrap());
|
||||
head += 8;
|
||||
// if blocks_left == 0, we're in the right block (either that or we're in the right block to recurse downwards into)
|
||||
if blocks_left == 0 {
|
||||
for _ in 0..count.min(indexes_left) {
|
||||
let isdata_depth = &buf[head..head + 8];
|
||||
head += 8;
|
||||
let ptr_data = &buf[head..head + 8];
|
||||
let ptr = u64::from_be_bytes(ptr_data.try_into().unwrap());
|
||||
let is_data = isdata_depth[1] != 0;
|
||||
// if not data, we need to recurse
|
||||
if !is_data {
|
||||
current_block = ptr;
|
||||
break; // skip the rest of the loop
|
||||
} else {
|
||||
// if indexes_left == 0, we found the correct index
|
||||
if indexes_left == 0 {
|
||||
return ptr;
|
||||
} else {
|
||||
indexes_left -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for _ in 0..count {
|
||||
let isdata_depth = &buf[head..head + 8];
|
||||
head += 8;
|
||||
let ptr_data = &buf[head..head + 8];
|
||||
let ptr = u64::from_be_bytes(ptr_data.try_into().unwrap());
|
||||
let is_data = isdata_depth[1] != 0;
|
||||
let mut depth = isdata_depth.to_vec();
|
||||
depth[0] = 0;
|
||||
let depth = u64::from_be_bytes(depth.try_into().unwrap());
|
||||
// if blocks_left is less than the depth, we are at the correct block
|
||||
if !is_data {
|
||||
if blocks_left < depth {
|
||||
// if not data, we need to recurse
|
||||
blocks_left = 0;
|
||||
current_block = ptr;
|
||||
break; // skip the rest of the loop
|
||||
} else {
|
||||
blocks_left -= depth;
|
||||
}
|
||||
} else {
|
||||
// if indexes_left == 0, we found the correct index
|
||||
if indexes_left == 0 {
|
||||
return ptr;
|
||||
} else {
|
||||
indexes_left -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
_ if address < N2 => {
|
||||
let address = address - N;
|
||||
let block_index = (address) / (max_per_block ^ 2);
|
||||
let layer2_block = read_datablock(list.double_indirect_block_address[block_index as usize], sb, bd);
|
||||
let layer2_address = address / max_per_block;
|
||||
let mut buf: [u8; 8] = [0; 8];
|
||||
buf.copy_from_slice(&layer2_block[(layer2_address * 8) as usize..(layer2_address * 8 + 8) as usize]);
|
||||
let layer1_block = u64::from_be_bytes(buf);
|
||||
let layer1_address = address % max_per_block;
|
||||
Some((layer1_block, layer1_address))
|
||||
}
|
||||
_ if address < N3 => {
|
||||
let address = address - N2;
|
||||
let block_index = (address) / (max_per_block ^ 3);
|
||||
let layer3_block = read_datablock(list.triple_indirect_block_address[block_index as usize], sb, bd);
|
||||
let layer3_address = address / (max_per_block ^ 2);
|
||||
let mut buf: [u8; 8] = [0; 8];
|
||||
buf.copy_from_slice(&layer3_block[(layer3_address * 8) as usize..(layer3_address * 8 + 8) as usize]);
|
||||
let layer2_block = u64::from_be_bytes(buf);
|
||||
let layer2_address = (address % (max_per_block ^ 2)) / max_per_block;
|
||||
let layer2_block = read_datablock(layer2_block, sb, bd);
|
||||
let mut buf: [u8; 8] = [0; 8];
|
||||
buf.copy_from_slice(&layer2_block[(layer2_address * 8) as usize..(layer2_address * 8 + 8) as usize]);
|
||||
let layer1_block = u64::from_be_bytes(buf);
|
||||
let layer1_address = address % max_per_block;
|
||||
Some((layer1_block, layer1_address))
|
||||
}
|
||||
_ if address < N4 => {
|
||||
let address = address - N3;
|
||||
let block_index = (address) / (max_per_block ^ 4);
|
||||
let layer4_block = read_datablock(list.quadruple_indirect_block_address[block_index as usize], sb, bd);
|
||||
let layer4_address = address / (max_per_block ^ 3);
|
||||
let mut buf: [u8; 8] = [0; 8];
|
||||
buf.copy_from_slice(&layer4_block[(layer4_address * 8) as usize..(layer4_address * 8 + 8) as usize]);
|
||||
let layer3_block = u64::from_be_bytes(buf);
|
||||
let layer3_address = (address % (max_per_block ^ 3)) / (max_per_block ^ 2);
|
||||
let layer3_block = read_datablock(layer3_block, sb, bd);
|
||||
let mut buf: [u8; 8] = [0; 8];
|
||||
buf.copy_from_slice(&layer3_block[(layer3_address * 8) as usize..(layer3_address * 8 + 8) as usize]);
|
||||
let layer2_block = u64::from_be_bytes(buf);
|
||||
let layer2_address = (address % (max_per_block ^ 2)) / max_per_block;
|
||||
let layer2_block = read_datablock(layer2_block, sb, bd);
|
||||
let mut buf: [u8; 8] = [0; 8];
|
||||
buf.copy_from_slice(&layer2_block[(layer2_address * 8) as usize..(layer2_address * 8 + 8) as usize]);
|
||||
let layer1_block = u64::from_be_bytes(buf);
|
||||
let layer1_address = address % max_per_block;
|
||||
Some((layer1_block, layer1_address))
|
||||
}
|
||||
_ if address < N5 => {
|
||||
let address = address - N4;
|
||||
let block_index = (address) / (max_per_block ^ 5);
|
||||
let layer5_block = read_datablock(list.quintuple_indirect_block_address[block_index as usize], sb, bd);
|
||||
let layer5_address = address / (max_per_block ^ 4);
|
||||
let mut buf: [u8; 8] = [0; 8];
|
||||
buf.copy_from_slice(&layer5_block[(layer5_address * 8) as usize..(layer5_address * 8 + 8) as usize]);
|
||||
let layer4_block = u64::from_be_bytes(buf);
|
||||
let layer4_address = (address % (max_per_block ^ 4)) / (max_per_block ^ 3);
|
||||
let layer4_block = read_datablock(layer4_block, sb, bd);
|
||||
let mut buf: [u8; 8] = [0; 8];
|
||||
buf.copy_from_slice(&layer4_block[(layer4_address * 8) as usize..(layer4_address * 8 + 8) as usize]);
|
||||
let layer3_block = u64::from_be_bytes(buf);
|
||||
let layer3_address = (address % (max_per_block ^ 3)) / (max_per_block ^ 2);
|
||||
let layer3_block = read_datablock(layer3_block, sb, bd);
|
||||
let mut buf: [u8; 8] = [0; 8];
|
||||
buf.copy_from_slice(&layer3_block[(layer3_address * 8) as usize..(layer3_address * 8 + 8) as usize]);
|
||||
let layer2_block = u64::from_be_bytes(buf);
|
||||
let layer2_address = (address % (max_per_block ^ 2)) / max_per_block;
|
||||
let layer2_block = read_datablock(layer2_block, sb, bd);
|
||||
let mut buf: [u8; 8] = [0; 8];
|
||||
buf.copy_from_slice(&layer2_block[(layer2_address * 8) as usize..(layer2_address * 8 + 8) as usize]);
|
||||
let layer1_block = u64::from_be_bytes(buf);
|
||||
let layer1_address = address % max_per_block;
|
||||
Some((layer1_block, layer1_address))
|
||||
}
|
||||
_ if address < N6 => {
|
||||
let address = address - N5;
|
||||
let block_index = (address) / (max_per_block ^ 6);
|
||||
let layer6_block = read_datablock(list.sextuple_indirect_block_address[block_index as usize], sb, bd);
|
||||
let layer6_address = address / (max_per_block ^ 5);
|
||||
let mut buf: [u8; 8] = [0; 8];
|
||||
buf.copy_from_slice(&layer6_block[(layer6_address * 8) as usize..(layer6_address * 8 + 8) as usize]);
|
||||
let layer5_block = u64::from_be_bytes(buf);
|
||||
let layer5_address = (address % (max_per_block ^ 5)) / (max_per_block ^ 4);
|
||||
let layer5_block = read_datablock(layer5_block, sb, bd);
|
||||
let mut buf: [u8; 8] = [0; 8];
|
||||
buf.copy_from_slice(&layer5_block[(layer5_address * 8) as usize..(layer5_address * 8 + 8) as usize]);
|
||||
let layer4_block = u64::from_be_bytes(buf);
|
||||
let layer4_address = (address % (max_per_block ^ 4)) / (max_per_block ^ 3);
|
||||
let layer4_block = read_datablock(layer4_block, sb, bd);
|
||||
let mut buf: [u8; 8] = [0; 8];
|
||||
buf.copy_from_slice(&layer4_block[(layer4_address * 8) as usize..(layer4_address * 8 + 8) as usize]);
|
||||
let layer3_block = u64::from_be_bytes(buf);
|
||||
let layer3_address = (address % (max_per_block ^ 3)) / (max_per_block ^ 2);
|
||||
let layer3_block = read_datablock(layer3_block, sb, bd);
|
||||
let mut buf: [u8; 8] = [0; 8];
|
||||
buf.copy_from_slice(&layer3_block[(layer3_address * 8) as usize..(layer3_address * 8 + 8) as usize]);
|
||||
let layer2_block = u64::from_be_bytes(buf);
|
||||
let layer2_address = (address % (max_per_block ^ 2)) / max_per_block;
|
||||
let layer2_block = read_datablock(layer2_block, sb, bd);
|
||||
let mut buf: [u8; 8] = [0; 8];
|
||||
buf.copy_from_slice(&layer2_block[(layer2_address * 8) as usize..(layer2_address * 8 + 8) as usize]);
|
||||
let layer1_block = u64::from_be_bytes(buf);
|
||||
let layer1_address = address % max_per_block;
|
||||
Some((layer1_block, layer1_address))
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Resizes an inode to the given size.
|
||||
/// # Safety
|
||||
/// unsafe because it does not journal the write, and does not update any other metadata.
|
||||
|
||||
/// Creates a journal entry for a single block write operation.
|
||||
/// Should be safe to call at anytime, and shouldn't corrupt anything if the system crashes.
|
||||
/// Returns None if the journal is full, or if the block device cannot be written to.
|
||||
|
@ -447,7 +524,7 @@ pub fn schedule_single_block_write(sb: &Superblock, bd: &mut dyn BlockDevice, co
|
|||
|
||||
/// Creates a journal entry for a multi block write operation.
|
||||
/// Should be safe to call at anytime, and shouldn't corrupt anything if the system crashes.
|
||||
/// Returns None if the journal is full, or if the block device cannot be written to.
|
||||
/// Returns None if the journal is full, if the block device cannot be written to, or if you're somehow trying to write over 2105000 terabytes of data.
|
||||
/// Returns the journal entry index if successful.
|
||||
pub fn schedule_multi_block_write(sb: &Superblock, bd: &mut dyn BlockDevice, containing_inode_index: Index, datablock_start: Index, datablock_count: Index, data: &[u8]) -> Option<Index> {
|
||||
let entry_index = next_journal_position(sb, bd)?;
|
||||
|
@ -514,148 +591,314 @@ pub fn schedule_multi_block_write(sb: &Superblock, bd: &mut dyn BlockDevice, con
|
|||
|
||||
// create a list block
|
||||
let mut list_block = ListBlock {
|
||||
using_indirect_blocks: datablock_count > 12,
|
||||
direct_block_addresses: [0; 12],
|
||||
count: 0,
|
||||
direct_block_addresses: [0; 32],
|
||||
single_indirect_block_address: [0; 32],
|
||||
double_indirect_block_address: [0; 32],
|
||||
triple_indirect_block_address: [0; 32],
|
||||
quadruple_indirect_block_address: [0; 32],
|
||||
quintuple_indirect_block_address: [0; 32],
|
||||
sextuple_indirect_block_address: [0; 32],
|
||||
};
|
||||
|
||||
let mut old_list_block = ListBlock {
|
||||
using_indirect_blocks: false,
|
||||
direct_block_addresses: [0; 12],
|
||||
count: 0,
|
||||
direct_block_addresses: [0; 32],
|
||||
single_indirect_block_address: [0; 32],
|
||||
double_indirect_block_address: [0; 32],
|
||||
triple_indirect_block_address: [0; 32],
|
||||
quadruple_indirect_block_address: [0; 32],
|
||||
quintuple_indirect_block_address: [0; 32],
|
||||
sextuple_indirect_block_address: [0; 32],
|
||||
};
|
||||
|
||||
let mut indirect_blocks_waiting_for_allocation_to_be_set = Vec::new();
|
||||
|
||||
// if using indirect blocks, only fill out the first (12 - 3) = 9 entries
|
||||
// otherwise, fill out all 12 entries
|
||||
if list_block.using_indirect_blocks {
|
||||
list_block.direct_block_addresses[..9].copy_from_slice(&allocated_blocks[..9]);
|
||||
// if using indirect blocks, only fill out the dba
|
||||
// otherwise, have fun!
|
||||
if datablock_count > 32 {
|
||||
list_block.direct_block_addresses.copy_from_slice(&allocated_blocks[..32]);
|
||||
list_block.count = 32;
|
||||
|
||||
// if using indirect blocks, fit the remaining entries into the indirect blocks
|
||||
// layout is u64 count followed by u64 addresses
|
||||
let max_addresses_per_block = (sb.block_size as usize - core::mem::size_of::<u64>()) / (core::mem::size_of::<u64>() * 2);
|
||||
let mut indirect_block_count = (datablock_count - 9) / max_addresses_per_block as u64;
|
||||
// if the count is not a multiple of the max addresses per block, add one
|
||||
if (datablock_count - 9) % max_addresses_per_block as u64 != 0 {
|
||||
indirect_block_count += 1;
|
||||
}
|
||||
// if the count is over 3, we'll need to use nested indirect blocks
|
||||
// calculate how many layers of indirect blocks we'll need,
|
||||
// filling max_addresses per block until we have less than max_addresses_per_block left
|
||||
// this will be the amount of layers required to store the data
|
||||
let depth = {
|
||||
let mut depth = 0;
|
||||
let mut remaining = indirect_block_count;
|
||||
while remaining > max_addresses_per_block as u64 {
|
||||
remaining -= max_addresses_per_block as u64;
|
||||
depth += 1;
|
||||
// set the indirect blocks
|
||||
let max_per_block = sb.block_size as u64 / 8;
|
||||
let N = max_per_block * 32;
|
||||
let N2 = N * N;
|
||||
let N3 = N2 * N;
|
||||
let N4 = N3 * N;
|
||||
let N5 = N4 * N;
|
||||
let N6 = N5 * N;
|
||||
// figure out how many blocks we need for all indirect blocks
|
||||
let mut indirect_blocks_needed = 0;
|
||||
// can we fit them all in the 32 single indirect blocks?
|
||||
let dba_count = datablock_count - 32;
|
||||
// enclosed in brackets so that you can collapse it in the IDE (:
|
||||
{
|
||||
if dba_count < N {
|
||||
// yes we can
|
||||
// how many indirect blocks do we need?
|
||||
indirect_blocks_needed = (dba_count / max_per_block) + 1;
|
||||
} else if dba_count < N2 {
|
||||
// no, but we can fit it in the double indirect blocks
|
||||
// first, fill up the single indirect blocks
|
||||
indirect_blocks_needed = N / max_per_block;
|
||||
let datablocks_left = dba_count - N;
|
||||
// how many double indirect blocks do we need?
|
||||
indirect_blocks_needed += (datablocks_left / N) + 1;
|
||||
// how many single indirect blocks do we need?
|
||||
indirect_blocks_needed += (datablocks_left / max_per_block) + 1;
|
||||
} else if dba_count < N3 {
|
||||
// this fills up the single and double indirect blocks
|
||||
indirect_blocks_needed = N / max_per_block; // 32 single indirect blocks
|
||||
indirect_blocks_needed += N2 / N;
|
||||
let datablocks_left = dba_count - N2;
|
||||
// how many triple indirect blocks do we need?
|
||||
indirect_blocks_needed += (datablocks_left / N2) + 1;
|
||||
// how many double indirect blocks do we need?
|
||||
indirect_blocks_needed += (datablocks_left / N) + 1;
|
||||
// how many single indirect blocks do we need?
|
||||
indirect_blocks_needed += (datablocks_left / max_per_block) + 1;
|
||||
} else if dba_count < N4 {
|
||||
// this fills up the single, double, and triple indirect blocks
|
||||
indirect_blocks_needed = N / max_per_block;
|
||||
indirect_blocks_needed += N2 / N;
|
||||
indirect_blocks_needed += N3 / N2;
|
||||
let datablocks_left = dba_count - N3;
|
||||
// how many quadruple indirect blocks do we need?
|
||||
indirect_blocks_needed += (datablocks_left / N3) + 1;
|
||||
// how many triple indirect blocks do we need?
|
||||
indirect_blocks_needed += (datablocks_left / N2) + 1;
|
||||
// how many double indirect blocks do we need?
|
||||
indirect_blocks_needed += (datablocks_left / N) + 1;
|
||||
// how many single indirect blocks do we need?
|
||||
indirect_blocks_needed += (datablocks_left / max_per_block) + 1;
|
||||
} else if dba_count < N5 {
|
||||
// this fills up the single, double, triple, and quadruple indirect blocks
|
||||
indirect_blocks_needed = N / max_per_block;
|
||||
indirect_blocks_needed += N2 / N;
|
||||
indirect_blocks_needed += N3 / N2;
|
||||
indirect_blocks_needed += N4 / N3;
|
||||
let datablocks_left = dba_count - N4;
|
||||
// how many quintuple indirect blocks do we need?
|
||||
indirect_blocks_needed += (datablocks_left / N4) + 1;
|
||||
// how many quadruple indirect blocks do we need?
|
||||
indirect_blocks_needed += (datablocks_left / N3) + 1;
|
||||
// how many triple indirect blocks do we need?
|
||||
indirect_blocks_needed += (datablocks_left / N2) + 1;
|
||||
// how many double indirect blocks do we need?
|
||||
indirect_blocks_needed += (datablocks_left / N) + 1;
|
||||
// how many single indirect blocks do we need?
|
||||
indirect_blocks_needed += (datablocks_left / max_per_block) + 1;
|
||||
} else if dba_count < N6 {
|
||||
// this fills up the single, double, triple, quadruple, and quintuple indirect blocks
|
||||
indirect_blocks_needed = N / max_per_block;
|
||||
indirect_blocks_needed += N2 / N;
|
||||
indirect_blocks_needed += N3 / N2;
|
||||
indirect_blocks_needed += N4 / N3;
|
||||
indirect_blocks_needed += N5 / N4;
|
||||
let datablocks_left = dba_count - N5;
|
||||
// how many sextuple indirect blocks do we need?
|
||||
indirect_blocks_needed += (datablocks_left / N5) + 1;
|
||||
// how many quintuple indirect blocks do we need?
|
||||
indirect_blocks_needed += (datablocks_left / N4) + 1;
|
||||
// how many quadruple indirect blocks do we need?
|
||||
indirect_blocks_needed += (datablocks_left / N3) + 1;
|
||||
// how many triple indirect blocks do we need?
|
||||
indirect_blocks_needed += (datablocks_left / N2) + 1;
|
||||
// how many double indirect blocks do we need?
|
||||
indirect_blocks_needed += (datablocks_left / N) + 1;
|
||||
// how many single indirect blocks do we need?
|
||||
indirect_blocks_needed += (datablocks_left / max_per_block) + 1;
|
||||
} else {
|
||||
// congratulations, you've attempted to write around 2105000 terabytes of data
|
||||
return None;
|
||||
}
|
||||
depth
|
||||
};
|
||||
}
|
||||
|
||||
// allocate the indirect blocks
|
||||
let indirect_blocks = find_count_unallocated_datablocks(sb, bd, indirect_block_count as usize + (depth * max_addresses_per_block))?;
|
||||
for i in 0..(indirect_block_count as usize + (depth * max_addresses_per_block)) {
|
||||
list_block.direct_block_addresses[9 + i] = indirect_blocks[i];
|
||||
indirect_blocks_waiting_for_allocation_to_be_set.push(indirect_blocks[i]);
|
||||
}
|
||||
let indirect_blocks = find_count_unallocated_datablocks(sb, bd, indirect_blocks_needed as usize)?;
|
||||
|
||||
// write the indirect blocks
|
||||
let mut indirect_block_data = vec![0; core::mem::size_of::<u64>() * max_addresses_per_block];
|
||||
let mut indirect_blocks_from_previous_layer = VecDeque::new();
|
||||
let mut indirect_blocks_from_previous_layer_alt = VecDeque::new();
|
||||
let mut using_alt = false;
|
||||
let mut acc: VecDeque<u64> = VecDeque::new(); // how much each previous layer has had
|
||||
let mut acc_alt: VecDeque<u64> = VecDeque::new(); // how much each previous layer has had
|
||||
for i in 0..(indirect_block_count as usize + (depth * max_addresses_per_block)) {
|
||||
// we will write the indirect blocks that contain the data blocks first
|
||||
// then we will write the indirect blocks that contain the indirect blocks
|
||||
// fill with data
|
||||
let mut i = 0;
|
||||
let mut taken = 0;
|
||||
let data = &allocated_blocks[32..];
|
||||
|
||||
// are we writing the indirect blocks that contain the data blocks?
|
||||
let writing_data_blocks = i < indirect_block_count as usize;
|
||||
if writing_data_blocks {
|
||||
let count = if i == (indirect_block_count - 1) as usize { // if we're at the last block, not all of the addresses will be used
|
||||
(datablock_count - 9) % max_addresses_per_block as u64
|
||||
} else {
|
||||
max_addresses_per_block as u64 // otherwise, all of the addresses will be used
|
||||
};
|
||||
// add count
|
||||
unsafe { core::ptr::write(indirect_block_data.as_mut_ptr() as *mut u64, count); }
|
||||
// add addresses
|
||||
for j in 0..count {
|
||||
unsafe { core::ptr::write((indirect_block_data.as_mut_ptr() as *mut u64).add(8 + j as usize), allocated_blocks[9 + i * max_addresses_per_block + j as usize]); }
|
||||
// once again enclosed so that you can collapse it in the IDE (:
|
||||
{
|
||||
fn fillwithdata_1(
|
||||
sb: &Superblock, bd: &mut dyn BlockDevice, i: &mut u64, data: &[Index],
|
||||
block_size: usize, max_per_block: u64, indirect_blocks: &mut Vec<Index>,
|
||||
taken: &mut usize, dbas: &mut [Index], max: usize) -> bool {
|
||||
for block1 in 0..max {
|
||||
if *i >= data.len() as u64 {
|
||||
break;
|
||||
}
|
||||
let mut buf = vec![0u8; block_size];
|
||||
let mut j = 0;
|
||||
while j < max_per_block {
|
||||
let index = *i % max_per_block;
|
||||
if *i >= data.len() as u64 {
|
||||
break;
|
||||
}
|
||||
buf[index as usize * 8..(index as usize + 1) * 8].copy_from_slice(&data[*i as usize].to_be_bytes());
|
||||
*i += 1;
|
||||
j += 1;
|
||||
}
|
||||
if !unsafe { write_datablock(indirect_blocks[*taken], sb, bd, &buf) } {
|
||||
return false;
|
||||
}
|
||||
*taken += 1;
|
||||
dbas[block1] = indirect_blocks[*taken - 1];
|
||||
}
|
||||
|
||||
// write the indirect block
|
||||
if !unsafe { write_datablock(indirect_blocks[i], sb, bd, &indirect_block_data) } {
|
||||
true
|
||||
}
|
||||
|
||||
// single indirect blocks
|
||||
if !fillwithdata_1(sb, bd, &mut i, data, sb.block_size as usize, max_per_block,
|
||||
&mut indirect_blocks_waiting_for_allocation_to_be_set, &mut taken,
|
||||
&mut list_block.single_indirect_block_address, 32) {
|
||||
return None;
|
||||
}
|
||||
|
||||
// double indirect blocks
|
||||
for block2 in 0..32 {
|
||||
if i >= data.len() as u64 {
|
||||
break;
|
||||
}
|
||||
let mut list = vec![0u64; max_per_block as usize];
|
||||
if !fillwithdata_1(sb, bd, &mut i, data, sb.block_size as usize, max_per_block,
|
||||
&mut indirect_blocks_waiting_for_allocation_to_be_set, &mut taken,
|
||||
&mut list, max_per_block as usize) {
|
||||
return None;
|
||||
}
|
||||
|
||||
indirect_blocks_from_previous_layer.push_back(indirect_blocks[i]);
|
||||
acc.push_back(count);
|
||||
} else {
|
||||
// we're writing the indirect blocks that contain the indirect blocks
|
||||
if !using_alt {
|
||||
|
||||
// write addresses from front of indirect_blocks_from_previous_layer
|
||||
let count = if indirect_blocks_from_previous_layer.len() > max_addresses_per_block - 8 {
|
||||
max_addresses_per_block - 8
|
||||
} else {
|
||||
indirect_blocks_from_previous_layer.len()
|
||||
};
|
||||
// add count
|
||||
unsafe { core::ptr::write(indirect_block_data.as_mut_ptr() as *mut u64, count as u64); }
|
||||
// add addresses
|
||||
for j in 0..count {
|
||||
// get acc value
|
||||
let acc_val = acc.pop_front().unwrap_or(0);
|
||||
unsafe { core::ptr::write((indirect_block_data.as_mut_ptr() as *mut u64).add(8 + (j * 16)), acc_val); }
|
||||
unsafe { core::ptr::write((indirect_block_data.as_mut_ptr() as *mut u64).add(8 + 8 + (j * 16)), indirect_blocks_from_previous_layer.pop_front().unwrap_or(0)); }
|
||||
}
|
||||
|
||||
// write the indirect block
|
||||
if !unsafe { write_datablock(indirect_blocks[i], sb, bd, &indirect_block_data) } {
|
||||
return None;
|
||||
}
|
||||
|
||||
// add the indirect block to the back of indirect_blocks_from_previous_layer_alt
|
||||
indirect_blocks_from_previous_layer_alt.push_back(indirect_blocks[i]);
|
||||
acc_alt.push_back(count as u64);
|
||||
|
||||
// if indirect_blocks_from_previous_layer is empty, switch to using_alt
|
||||
if indirect_blocks_from_previous_layer.is_empty() {
|
||||
using_alt = true;
|
||||
}
|
||||
} else {
|
||||
// write addresses from front of indirect_blocks_from_previous_layer_alt
|
||||
let count = if indirect_blocks_from_previous_layer_alt.len() > max_addresses_per_block - 8 {
|
||||
max_addresses_per_block - 8
|
||||
} else {
|
||||
indirect_blocks_from_previous_layer_alt.len()
|
||||
};
|
||||
// add count
|
||||
unsafe { core::ptr::write(indirect_block_data.as_mut_ptr() as *mut u64, count as u64); }
|
||||
// add addresses
|
||||
for j in 0..count {
|
||||
// get acc value
|
||||
let acc_val = acc_alt.pop_front().unwrap_or(0);
|
||||
unsafe { core::ptr::write((indirect_block_data.as_mut_ptr() as *mut u64).add(8 + (j * 16)), acc_val); }
|
||||
unsafe { core::ptr::write((indirect_block_data.as_mut_ptr() as *mut u64).add(8 + 8 + (j * 16)), indirect_blocks_from_previous_layer_alt.pop_front().unwrap_or(0)); }
|
||||
}
|
||||
|
||||
// write the indirect block
|
||||
if !unsafe { write_datablock(indirect_blocks[i], sb, bd, &indirect_block_data) } {
|
||||
return None;
|
||||
}
|
||||
|
||||
// add the indirect block to the back of indirect_blocks_from_previous_layer
|
||||
indirect_blocks_from_previous_layer.push_back(indirect_blocks[i]);
|
||||
acc.push_back(count as u64);
|
||||
|
||||
// if indirect_blocks_from_previous_layer_alt is empty, switch to using_alt
|
||||
if indirect_blocks_from_previous_layer_alt.is_empty() {
|
||||
using_alt = false;
|
||||
}
|
||||
let buf = list.iter().map(|x| x.to_be_bytes()).flatten().collect::<Vec<u8>>();
|
||||
if !unsafe { write_datablock(indirect_blocks[taken], sb, bd, &buf) } {
|
||||
return None;
|
||||
}
|
||||
taken += 1;
|
||||
list_block.double_indirect_block_address[block2 as usize] = indirect_blocks[taken - 1];
|
||||
}
|
||||
|
||||
// triple indirect blocks
|
||||
fn fillwithdata_2(
|
||||
sb: &Superblock, bd: &mut dyn BlockDevice, i: &mut u64, data: &[Index],
|
||||
block_size: usize, max_per_block: u64, indirect_blocks: &mut Vec<Index>,
|
||||
taken: &mut usize, dbas: &mut [Index], max: usize) -> bool {
|
||||
for block3 in 0..32 {
|
||||
if *i >= data.len() as u64 {
|
||||
break;
|
||||
}
|
||||
let mut buf = vec![0u8; sb.block_size as usize];
|
||||
for block2 in 0..max_per_block {
|
||||
if *i >= data.len() as u64 {
|
||||
break;
|
||||
}
|
||||
let mut buf2 = vec![0u64; max_per_block as usize];
|
||||
fillwithdata_1(sb, bd, i, data, block_size, max_per_block,
|
||||
indirect_blocks, taken,
|
||||
&mut buf2, max_per_block as usize);
|
||||
let buf2 = buf2.iter().map(|x| x.to_be_bytes()).flatten().collect::<Vec<u8>>();
|
||||
if !unsafe { write_datablock(indirect_blocks[*taken], sb, bd, &buf2) } {
|
||||
return false;
|
||||
}
|
||||
*taken += 1;
|
||||
buf[block2 as usize * 8..(block2 as usize + 1) * 8].copy_from_slice(&indirect_blocks[*taken - 1].to_be_bytes());
|
||||
}
|
||||
if !unsafe { write_datablock(indirect_blocks[*taken], sb, bd, &buf) } {
|
||||
return false;
|
||||
}
|
||||
*taken += 1;
|
||||
dbas[block3 as usize] = indirect_blocks[*taken - 1];
|
||||
}
|
||||
true
|
||||
}
|
||||
fillwithdata_2(sb, bd, &mut i, data, sb.block_size as usize, max_per_block,
|
||||
&mut indirect_blocks_waiting_for_allocation_to_be_set, &mut taken,
|
||||
&mut list_block.triple_indirect_block_address, 32);
|
||||
|
||||
// quadruple indirect blocks
|
||||
for block4 in 0..32 {
|
||||
if i >= data.len() as u64 {
|
||||
break;
|
||||
}
|
||||
let mut list = vec![0u64; max_per_block as usize];
|
||||
fillwithdata_2(sb, bd, &mut i, data, sb.block_size as usize, max_per_block,
|
||||
&mut indirect_blocks_waiting_for_allocation_to_be_set, &mut taken,
|
||||
&mut list, max_per_block as usize);
|
||||
let buf = list.iter().map(|x| x.to_be_bytes()).flatten().collect::<Vec<u8>>();
|
||||
if !unsafe { write_datablock(indirect_blocks[taken], sb, bd, &buf) } {
|
||||
return None;
|
||||
}
|
||||
taken += 1;
|
||||
list_block.quadruple_indirect_block_address[block4 as usize] = indirect_blocks[taken - 1];
|
||||
}
|
||||
|
||||
// quintuple indirect blocks
|
||||
for block5 in 0..32 {
|
||||
if i >= data.len() as u64 {
|
||||
break;
|
||||
}
|
||||
let mut list = vec![0u8; max_per_block as usize];
|
||||
for block4 in 0..max_per_block {
|
||||
if i >= data.len() as u64 {
|
||||
break;
|
||||
}
|
||||
let mut buf = vec![0u64; max_per_block as usize];
|
||||
fillwithdata_2(sb, bd, &mut i, data, sb.block_size as usize, max_per_block,
|
||||
&mut indirect_blocks_waiting_for_allocation_to_be_set, &mut taken,
|
||||
&mut buf, max_per_block as usize);
|
||||
let buf = buf.iter().map(|x| x.to_be_bytes()).flatten().collect::<Vec<u8>>();
|
||||
if !unsafe { write_datablock(indirect_blocks[taken], sb, bd, &buf) } {
|
||||
return None;
|
||||
}
|
||||
taken += 1;
|
||||
list[block4 as usize * 8..(block4 as usize + 1) * 8].copy_from_slice(&indirect_blocks[taken - 1].to_be_bytes());
|
||||
}
|
||||
if !unsafe { write_datablock(indirect_blocks[taken], sb, bd, &buf) } {
|
||||
return None;
|
||||
}
|
||||
taken += 1;
|
||||
list_block.quintuple_indirect_block_address[block5 as usize] = indirect_blocks[taken - 1];
|
||||
}
|
||||
|
||||
// sextuple indirect blocks
|
||||
for block6 in 0..32 {
|
||||
if i >= data.len() as u64 {
|
||||
break;
|
||||
}
|
||||
let mut list = vec![0u8; max_per_block as usize];
|
||||
for block5 in 0..max_per_block {
|
||||
if i >= data.len() as u64 {
|
||||
break;
|
||||
}
|
||||
let mut buf = vec![0u8; max_per_block as usize];
|
||||
for block4 in 0..max_per_block {
|
||||
if i >= data.len() as u64 {
|
||||
break;
|
||||
}
|
||||
let mut buf2 = vec![0u64; max_per_block as usize];
|
||||
fillwithdata_2(sb, bd, &mut i, data, sb.block_size as usize, max_per_block,
|
||||
&mut indirect_blocks_waiting_for_allocation_to_be_set, &mut taken,
|
||||
&mut buf2, max_per_block as usize);
|
||||
let buf2 = buf2.iter().map(|x| x.to_be_bytes()).flatten().collect::<Vec<u8>>();
|
||||
if !unsafe { write_datablock(indirect_blocks[taken], sb, bd, &buf2) } {
|
||||
return None;
|
||||
}
|
||||
taken += 1;
|
||||
buf[block4 as usize * 8..(block4 as usize + 1) * 8].copy_from_slice(&indirect_blocks[taken - 1].to_be_bytes());
|
||||
}
|
||||
if !unsafe { write_datablock(indirect_blocks[taken], sb, bd, &buf) } {
|
||||
return None;
|
||||
}
|
||||
taken += 1;
|
||||
list[block5 as usize * 8..(block5 as usize + 1) * 8].copy_from_slice(&indirect_blocks[taken - 1].to_be_bytes());
|
||||
}
|
||||
if !unsafe { write_datablock(indirect_blocks[taken], sb, bd, &buf) } {
|
||||
return None;
|
||||
}
|
||||
taken += 1;
|
||||
list_block.sextuple_indirect_block_address[block6 as usize] = indirect_blocks[taken - 1];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -664,8 +907,7 @@ pub fn schedule_multi_block_write(sb: &Superblock, bd: &mut dyn BlockDevice, con
|
|||
|
||||
// read target inode, and write the old list block
|
||||
let target_inode = read_inode(containing_inode_index, sb, bd)?;
|
||||
old_list_block.using_indirect_blocks = target_inode.flags & InodeFlags::INDIRECT as u32 != 0;
|
||||
old_list_block.direct_block_addresses = target_inode.direct_block_addresses;
|
||||
old_list_block = target_inode.listblock;
|
||||
|
||||
// write the list blocks
|
||||
let buf = [0; core::mem::size_of::<ListBlock>()];
|
||||
|
@ -827,10 +1069,7 @@ pub fn flush_single_block_write(sb: &Superblock, bd: &mut dyn BlockDevice, entry
|
|||
return false;
|
||||
}
|
||||
} else {
|
||||
if inode.flags & InodeFlags::INDIRECT as u32 == 0 {
|
||||
// inode doesn't have indirect blocks, this entry is corrupt
|
||||
return false;
|
||||
}
|
||||
let conversion_needed = inode.flags & InodeFlags::INDIRECT as u32 == 0;
|
||||
|
||||
// figure out which indirect block we need to write to (either 1, 2, or 3)
|
||||
// range 12..(12*2) is indirect block 1
|
||||
|
@ -1383,7 +1622,6 @@ pub fn journaled_write_data(sb: &Superblock, bd: &mut dyn BlockDevice, inode: In
|
|||
return JournaledWriteResult::PotentialFilesystemCorruption;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
JournaledWriteResult::Success
|
||||
|
|
110
src/structs.rs
110
src/structs.rs
|
@ -7,7 +7,7 @@ pub const MAGIC: u64 = 0x766170554653;
|
|||
|
||||
/// # Superblock
|
||||
/// The primary struct of a VapUFS filesystem, contains metadata about the filesystem.
|
||||
/// Located at byte offset 1024 of the block device.
|
||||
/// Located at byte offset 2048 of the block device.
|
||||
/// All values are big-endian unless otherwise specified.
|
||||
/// Directly after (i.e. the next block after) the Superblock are the free data blocks bitmap and the free inodes bitmap.
|
||||
/// Free data blocks bitmap is data_block_count / 8 bytes long (rounded up).
|
||||
|
@ -17,7 +17,7 @@ pub const MAGIC: u64 = 0x766170554653;
|
|||
pub struct Superblock {
|
||||
/// magic number that identifies the Superblock as a valid VapUFS filesystem
|
||||
pub magic: u64,
|
||||
/// size of each block in bytes, must be *at least* the size of the superblock without the bitmaps
|
||||
/// size of each block in bytes, must be *at least* 2048 bytes
|
||||
pub block_size: u32,
|
||||
/// location of first data block in blocks
|
||||
pub first_data_block: Index,
|
||||
|
@ -197,36 +197,10 @@ pub struct Inode {
|
|||
pub deletion_time: Timestamp,
|
||||
/// Flags field, see `InodeFlags`
|
||||
pub flags: u32,
|
||||
/// Direct-Block-Addresses, last three are indirect if `InodeFlags::INDIRECT` is set
|
||||
/// Indirect blocks are Indexes to other blocks, their contents are a u64 count "N" followed by
|
||||
/// for each entry...
|
||||
/// is_data: bool (true if data block, false if another indirect block)
|
||||
/// depth: u56 (in total, how many indirect blocks are pointed to if this isn't data, and how many indirect blocks do they point to if they have indirect blocks)
|
||||
/// ptr: u64 (if is_data, then this is a data block, otherwise it is an indirect block)
|
||||
/// both direct and indirect are pointers to data blocks, starting from data block 0
|
||||
/// ====
|
||||
/// these pointers can be addressed via a u64 in the following way:
|
||||
/// if i < 12, then it refers to a direct block in this array (undefined behaviour if indirect is set and i > 9)
|
||||
/// if i == 12, then it refers to the first index found by going to the first indirect block, and recursing through each found indirect block until the first data block is found.
|
||||
/// if i == 13, then it refers to the second index found by going to the first indirect block, and recursing through each found indirect block until the second data block is found.
|
||||
/// ==
|
||||
/// the algorithm for finding the nth data block is as follows:
|
||||
/// if n < 12, then it is the nth direct block
|
||||
/// if n >= 12...
|
||||
/// let mut n = n - 12;
|
||||
/// let mut block_i = n / (block_size - 8);
|
||||
/// // block_i is how many indirect blocks we need to traverse to get to the indirect block that contains the nth data block
|
||||
/// let mut current_block = self.direct_block_addresses[12];
|
||||
/// while not found...
|
||||
/// // read block, if not data then check depth,
|
||||
/// // if depth implies that this indirect block could contain the nth data block, then recurse
|
||||
/// // otherwise, subtract the depth from n, and continue
|
||||
/// ====
|
||||
/// ideally, this should not take up too much storage space, while allowing for a large number of blocks to be addressed with minimal performance impact
|
||||
pub direct_block_addresses: [Index; 12],
|
||||
/// listblock for storing data block addresses
|
||||
pub listblock: ListBlock,
|
||||
/// CRC32 checksum of this inode
|
||||
pub checksum: u32,
|
||||
// 172 bytes used so far
|
||||
}
|
||||
|
||||
impl Inode {
|
||||
|
@ -246,9 +220,7 @@ impl Inode {
|
|||
self.last_inode_modification_time = u64::from_be(self.last_inode_modification_time);
|
||||
self.deletion_time = u64::from_be(self.deletion_time);
|
||||
self.flags = u32::from_be(self.flags);
|
||||
for i in 0..12 {
|
||||
self.direct_block_addresses[i] = u64::from_be(self.direct_block_addresses[i]);
|
||||
}
|
||||
self.listblock.convert_big_endian_to_native();
|
||||
self.checksum = u32::from_be(self.checksum);
|
||||
}
|
||||
}
|
||||
|
@ -269,9 +241,7 @@ impl Inode {
|
|||
self.last_inode_modification_time = u64::to_be(self.last_inode_modification_time);
|
||||
self.deletion_time = u64::to_be(self.deletion_time);
|
||||
self.flags = u32::to_be(self.flags);
|
||||
for i in 0..12 {
|
||||
self.direct_block_addresses[i] = u64::to_be(self.direct_block_addresses[i]);
|
||||
}
|
||||
self.listblock.convert_native_to_big_endian();
|
||||
self.checksum = u32::to_be(self.checksum);
|
||||
}
|
||||
}
|
||||
|
@ -306,8 +276,18 @@ impl Inode {
|
|||
pub enum InodeFlags {
|
||||
/// File is corrupted
|
||||
CORRUPT = 1 << 0,
|
||||
/// File uses indirect blocks
|
||||
INDIRECT = 1 << 1,
|
||||
/// File uses Single Indirect Block
|
||||
INDIRECT1 = 1 << 1,
|
||||
/// File uses Double Indirect Block
|
||||
INDIRECT2 = 1 << 2,
|
||||
/// File uses Triple Indirect Block
|
||||
INDIRECT3 = 1 << 3,
|
||||
/// File uses Quadruple Indirect Block
|
||||
INDIRECT4 = 1 << 4,
|
||||
/// File uses Quintuple Indirect Block
|
||||
INDIRECT5 = 1 << 5,
|
||||
/// File uses Sextuple Indirect Block
|
||||
INDIRECT6 = 1 << 6,
|
||||
}
|
||||
|
||||
/// # JournalEntry
|
||||
|
@ -400,8 +380,15 @@ pub struct JournalBlockWrite {
|
|||
/// target inode number
|
||||
pub target_inode: Index,
|
||||
/// target block number (if target is a data block, this will be the index in the inode's direct block array;
|
||||
/// if greater than 12, the indirect block this points to (i / 12) will be used, and the index in that block will be i % 12)
|
||||
/// (if target is an inode, this field will be ignored)
|
||||
/// if greater than 32, see the following:
|
||||
/// let N = maximum number of pointers in an indirect block
|
||||
/// (beginning...count)
|
||||
/// 32..N: single indirect block
|
||||
/// 32+N..N^2: double indirect block
|
||||
/// 32+N^2..N^3: triple indirect block
|
||||
/// 32+N^3..N^4: quadruple indirect block
|
||||
/// 32+N^4..N^5: quintuple indirect block
|
||||
/// 32+N^5..N^6: sextuple indirect block
|
||||
pub target_block: Index,
|
||||
/// actual data block number, unused if target is an inode
|
||||
pub real_target_block: Index,
|
||||
|
@ -558,11 +545,28 @@ pub enum JMWFlags {
|
|||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct ListBlock {
|
||||
pub using_indirect_blocks: bool,
|
||||
/// Direct-Block-Addresses, last three are indirect if `using_indirect_blocks` is set
|
||||
/// Indirect blocks are Indexes to other blocks, their contents are a u64 count "N" followed by N u64 indexes
|
||||
/// both are pointers to data blocks, starting from data block 0
|
||||
pub direct_block_addresses: [Index; 12],
|
||||
/// Count of blocks used
|
||||
pub count: Index,
|
||||
/// Direct-Block-Addresses
|
||||
pub direct_block_addresses: [Index; 32],
|
||||
/// Single Indirect-Block-Address
|
||||
/// Indirect blocks are Indexes to other blocks, their contents are N u64 data pointers
|
||||
pub single_indirect_block_address: [Index; 32],
|
||||
/// Double Indirect-Block-Address
|
||||
/// Double indirect blocks are Indexes to other blocks, their contents are N u64 indirect block pointers (they point to single indirect blocks)
|
||||
pub double_indirect_block_address: [Index; 32],
|
||||
/// Triple Indirect-Block-Address
|
||||
/// Triple indirect blocks are Indexes to other blocks, their contents are N u64 double indirect block pointers (they point to double indirect blocks)
|
||||
pub triple_indirect_block_address: [Index; 32],
|
||||
/// Quadruple Indirect-Block-Address
|
||||
/// Quadruple indirect blocks are Indexes to other blocks, their contents are N u64 triple indirect block pointers (they point to triple indirect blocks)
|
||||
pub quadruple_indirect_block_address: [Index; 32],
|
||||
/// Quintuple Indirect-Block-Address
|
||||
/// Quintuple indirect blocks are Indexes to other blocks, their contents are N u64 quadruple indirect block pointers (they point to quadruple indirect blocks)
|
||||
pub quintuple_indirect_block_address: [Index; 32],
|
||||
/// Sextuple Indirect-Block-Address
|
||||
/// Sextuple indirect blocks are Indexes to other blocks, their contents are N u64 quintuple indirect block pointers (they point to quintuple indirect blocks)
|
||||
pub sextuple_indirect_block_address: [Index; 32],
|
||||
}
|
||||
|
||||
impl ListBlock {
|
||||
|
@ -570,8 +574,14 @@ impl ListBlock {
|
|||
pub fn convert_big_endian_to_native(&mut self) {
|
||||
#[cfg(target_endian = "little")]
|
||||
{
|
||||
for i in 0..12 {
|
||||
for i in 0..32 {
|
||||
self.direct_block_addresses[i] = u64::from_be(self.direct_block_addresses[i]);
|
||||
self.single_indirect_block_address[i] = u64::from_be(self.single_indirect_block_address[i]);
|
||||
self.double_indirect_block_address[i] = u64::from_be(self.double_indirect_block_address[i]);
|
||||
self.triple_indirect_block_address[i] = u64::from_be(self.triple_indirect_block_address[i]);
|
||||
self.quadruple_indirect_block_address[i] = u64::from_be(self.quadruple_indirect_block_address[i]);
|
||||
self.quintuple_indirect_block_address[i] = u64::from_be(self.quintuple_indirect_block_address[i]);
|
||||
self.sextuple_indirect_block_address[i] = u64::from_be(self.sextuple_indirect_block_address[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -580,8 +590,14 @@ impl ListBlock {
|
|||
pub fn convert_native_to_big_endian(&mut self) {
|
||||
#[cfg(target_endian = "little")]
|
||||
{
|
||||
for i in 0..12 {
|
||||
for i in 0..32 {
|
||||
self.direct_block_addresses[i] = u64::to_be(self.direct_block_addresses[i]);
|
||||
self.single_indirect_block_address[i] = u64::to_be(self.single_indirect_block_address[i]);
|
||||
self.double_indirect_block_address[i] = u64::to_be(self.double_indirect_block_address[i]);
|
||||
self.triple_indirect_block_address[i] = u64::to_be(self.triple_indirect_block_address[i]);
|
||||
self.quadruple_indirect_block_address[i] = u64::to_be(self.quadruple_indirect_block_address[i]);
|
||||
self.quintuple_indirect_block_address[i] = u64::to_be(self.quintuple_indirect_block_address[i]);
|
||||
self.sextuple_indirect_block_address[i] = u64::to_be(self.sextuple_indirect_block_address[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue