|
@@ -610,7 +610,7 @@ mod private {
|
|
impl<C, A> LocalFs<C, A> {
|
|
impl<C, A> LocalFs<C, A> {
|
|
/// The maximum number of directory entries that can be returned in any given call to
|
|
/// The maximum number of directory entries that can be returned in any given call to
|
|
/// `read_dir`.
|
|
/// `read_dir`.
|
|
- const DIR_ENTRY_LIMIT: usize = 1024;
|
|
|
|
|
|
+ const READ_DIR_LIMIT: usize = 1024;
|
|
}
|
|
}
|
|
|
|
|
|
impl<C: Creds + 'static, A: Authorizer> LocalFs<C, A> {
|
|
impl<C: Creds + 'static, A: Authorizer> LocalFs<C, A> {
|
|
@@ -626,8 +626,13 @@ mod private {
|
|
let root_principal = writecap.root_principal();
|
|
let root_principal = writecap.root_principal();
|
|
|
|
|
|
// Initialize the superblock.
|
|
// Initialize the superblock.
|
|
- let mut sb_block =
|
|
|
|
- Self::open_superblock(&btdir, creds.clone(), root_block_path.clone())?;
|
|
|
|
|
|
+ let mut sb_block = Self::open_superblock(
|
|
|
|
+ &btdir,
|
|
|
|
+ creds.clone(),
|
|
|
|
+ root_block_path.clone(),
|
|
|
|
+ &root_principal,
|
|
|
|
+ true,
|
|
|
|
+ )?;
|
|
let sb = Superblock {
|
|
let sb = Superblock {
|
|
generation,
|
|
generation,
|
|
next_inode: AtomicU64::new(SpecInodes::FirstFree.into()),
|
|
next_inode: AtomicU64::new(SpecInodes::FirstFree.into()),
|
|
@@ -705,8 +710,13 @@ mod private {
|
|
let writecap = creds.writecap().ok_or(BlockError::MissingWritecap)?;
|
|
let writecap = creds.writecap().ok_or(BlockError::MissingWritecap)?;
|
|
let root_block_path = writecap.root_block_path();
|
|
let root_block_path = writecap.root_block_path();
|
|
let root_principal = writecap.root_principal();
|
|
let root_principal = writecap.root_principal();
|
|
- let mut sb_block =
|
|
|
|
- Self::open_superblock(&btdir, creds.clone(), root_block_path.clone())?;
|
|
|
|
|
|
+ let mut sb_block = Self::open_superblock(
|
|
|
|
+ &btdir,
|
|
|
|
+ creds.clone(),
|
|
|
|
+ root_block_path.clone(),
|
|
|
|
+ &root_principal,
|
|
|
|
+ false,
|
|
|
|
+ )?;
|
|
let sb: Superblock = read_from(&mut sb_block)?;
|
|
let sb: Superblock = read_from(&mut sb_block)?;
|
|
let root_block = Self::open_block(
|
|
let root_block = Self::open_block(
|
|
&btdir,
|
|
&btdir,
|
|
@@ -760,16 +770,60 @@ mod private {
|
|
})
|
|
})
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ fn make_path<P: AsRef<Path>>(parent: P, file_name: &str) -> PathBuf {
|
|
|
|
+ let mut path =
|
|
|
|
+ PathBuf::with_capacity(parent.as_ref().as_os_str().len() + 1 + file_name.len() + 1);
|
|
|
|
+ path.push(parent);
|
|
|
|
+ path.push(&file_name[..2]);
|
|
|
|
+ path.push(&file_name[2..]);
|
|
|
|
+ path
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ fn hex_encode(src: &[u8]) -> Result<String> {
|
|
|
|
+ use std::fmt::Write;
|
|
|
|
+ let mut string = String::with_capacity(2 * src.len());
|
|
|
|
+ for byte in src.iter() {
|
|
|
|
+ write!(string, "{byte:02x}")?;
|
|
|
|
+ }
|
|
|
|
+ Ok(string)
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ fn ensure_parent_created(path: &Path) -> Result<()> {
|
|
|
|
+ let dir = path.ancestors().nth(1).unwrap();
|
|
|
|
+ if let Err(err) = std::fs::create_dir(dir) {
|
|
|
|
+ match err.kind() {
|
|
|
|
+ io::ErrorKind::AlreadyExists => Ok(()),
|
|
|
|
+ _ => Err(err.into()),
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ Ok(())
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
fn open_superblock<P: AsRef<Path>>(
|
|
fn open_superblock<P: AsRef<Path>>(
|
|
btdir: P,
|
|
btdir: P,
|
|
creds: C,
|
|
creds: C,
|
|
block_path: BlockPath,
|
|
block_path: BlockPath,
|
|
|
|
+ root_principal: &Principal,
|
|
|
|
+ create_new: bool,
|
|
) -> Result<Accessor<FileBlock<C>>> {
|
|
) -> Result<Accessor<FileBlock<C>>> {
|
|
- let path = btdir.as_ref().join("super.blk");
|
|
|
|
|
|
+ const HASH: HashKind = HashKind::Sha2_256;
|
|
|
|
+ let mut buf = [0u8; HASH.len()];
|
|
|
|
+ HASH.digest(
|
|
|
|
+ &mut buf,
|
|
|
|
+ [
|
|
|
|
+ SpecInodes::Sb.value().to_le_bytes().as_slice(),
|
|
|
|
+ root_principal.as_slice(),
|
|
|
|
+ ]
|
|
|
|
+ .into_iter(),
|
|
|
|
+ )?;
|
|
|
|
+ let hex_str = Self::hex_encode(&buf)?;
|
|
|
|
+ let path = Self::make_path(btdir, &hex_str);
|
|
|
|
+ Self::ensure_parent_created(&path)?;
|
|
let file = std::fs::OpenOptions::new()
|
|
let file = std::fs::OpenOptions::new()
|
|
.read(true)
|
|
.read(true)
|
|
.write(true)
|
|
.write(true)
|
|
- .create(true)
|
|
|
|
|
|
+ .create_new(create_new)
|
|
.open(path)?;
|
|
.open(path)?;
|
|
let block = BlockOpenOptions::new()
|
|
let block = BlockOpenOptions::new()
|
|
.with_creds(creds)
|
|
.with_creds(creds)
|
|
@@ -780,15 +834,6 @@ mod private {
|
|
Ok(block)
|
|
Ok(block)
|
|
}
|
|
}
|
|
|
|
|
|
- fn hex_encode(src: &[u8]) -> Result<String> {
|
|
|
|
- use std::fmt::Write;
|
|
|
|
- let mut string = String::with_capacity(2 * src.len());
|
|
|
|
- for byte in src.iter() {
|
|
|
|
- write!(string, "{byte:02x}")?;
|
|
|
|
- }
|
|
|
|
- Ok(string)
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
/// Returns the path to the file storing the given inode's data.
|
|
/// Returns the path to the file storing the given inode's data.
|
|
fn block_path<P: AsRef<Path>>(
|
|
fn block_path<P: AsRef<Path>>(
|
|
parent: P,
|
|
parent: P,
|
|
@@ -802,12 +847,7 @@ mod private {
|
|
[inode.to_le_bytes().as_slice(), inode_key].into_iter(),
|
|
[inode.to_le_bytes().as_slice(), inode_key].into_iter(),
|
|
)?;
|
|
)?;
|
|
let hex_str = Self::hex_encode(&buf)?;
|
|
let hex_str = Self::hex_encode(&buf)?;
|
|
- let mut path =
|
|
|
|
- PathBuf::with_capacity(parent.as_ref().as_os_str().len() + 1 + hex_str.len() + 1);
|
|
|
|
- path.push(parent);
|
|
|
|
- path.push(&hex_str[..2]);
|
|
|
|
- path.push(&hex_str[2..]);
|
|
|
|
- Ok(path)
|
|
|
|
|
|
+ Ok(Self::make_path(parent, &hex_str))
|
|
}
|
|
}
|
|
|
|
|
|
fn open_block<P: AsRef<Path>>(
|
|
fn open_block<P: AsRef<Path>>(
|
|
@@ -820,13 +860,7 @@ mod private {
|
|
inode_key: &[u8],
|
|
inode_key: &[u8],
|
|
) -> Result<Accessor<FileBlock<C>>> {
|
|
) -> Result<Accessor<FileBlock<C>>> {
|
|
let path = Self::block_path(&btdir, inode, inode_hash, inode_key)?;
|
|
let path = Self::block_path(&btdir, inode, inode_hash, inode_key)?;
|
|
- let dir = path.ancestors().nth(1).unwrap();
|
|
|
|
- if let Err(err) = std::fs::create_dir(dir) {
|
|
|
|
- match err.kind() {
|
|
|
|
- io::ErrorKind::AlreadyExists => (),
|
|
|
|
- _ => return Err(err.into()),
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
|
|
+ Self::ensure_parent_created(&path)?;
|
|
let file = std::fs::OpenOptions::new()
|
|
let file = std::fs::OpenOptions::new()
|
|
.read(true)
|
|
.read(true)
|
|
.write(true)
|
|
.write(true)
|
|
@@ -1507,7 +1541,7 @@ mod private {
|
|
owner.assert_eq(from)?;
|
|
owner.assert_eq(from)?;
|
|
let dir = handle_value.directory()?;
|
|
let dir = handle_value.directory()?;
|
|
let state: usize = state.try_into()?;
|
|
let state: usize = state.try_into()?;
|
|
- let server_limit = Self::DIR_ENTRY_LIMIT.min(dir.num_entries() - state);
|
|
|
|
|
|
+ let server_limit = Self::READ_DIR_LIMIT.min(dir.num_entries() - state);
|
|
let entries_len = if limit > 0 {
|
|
let entries_len = if limit > 0 {
|
|
server_limit.min(limit as usize)
|
|
server_limit.min(limit as usize)
|
|
} else {
|
|
} else {
|