authfs: use RwLock instead of Mutex
Bug: 220386264
Test: Observed faster parallel file reads (at least not much slower,
possibly due to lock contention), with prototype of multithread
support.
Change-Id: I3126932f9b3c769756ec1123e4746d3d1de88a1e
diff --git a/authfs/src/fusefs.rs b/authfs/src/fusefs.rs
index 5bc25b0..82b8501 100644
--- a/authfs/src/fusefs.rs
+++ b/authfs/src/fusefs.rs
@@ -33,7 +33,7 @@
use std::os::unix::ffi::OsStrExt;
use std::path::{Component, Path, PathBuf};
use std::sync::atomic::{AtomicU64, Ordering};
-use std::sync::{Arc, Mutex};
+use std::sync::{Arc, RwLock};
use std::time::Duration;
use crate::common::{divide_roundup, ChunkedSizeIter, CHUNK_SIZE};
@@ -188,7 +188,7 @@
pub struct AuthFs {
/// Table for `Inode` to `InodeState` lookup. This needs to be `Sync` to be used in
/// `fuse::worker::start_message_loop`.
- inode_table: Mutex<BTreeMap<Inode, InodeState>>,
+ inode_table: RwLock<BTreeMap<Inode, InodeState>>,
/// The next available inode number.
next_inode: AtomicU64,
@@ -200,7 +200,7 @@
///
/// Currently, no code locks `dir_handle_table` and `inode_table` at the same time to avoid
/// deadlock.
- dir_handle_table: Mutex<DirHandleTable>,
+ dir_handle_table: RwLock<DirHandleTable>,
/// The next available handle number.
next_handle: AtomicU64,
@@ -222,9 +222,9 @@
);
AuthFs {
- inode_table: Mutex::new(inode_table),
+ inode_table: RwLock::new(inode_table),
next_inode: AtomicU64::new(ROOT_INODE + 1),
- dir_handle_table: Mutex::new(BTreeMap::new()),
+ dir_handle_table: RwLock::new(BTreeMap::new()),
next_handle: AtomicU64::new(1),
remote_fs_stats_reader,
}
@@ -321,7 +321,7 @@
where
F: FnOnce(&AuthFsEntry) -> io::Result<R>,
{
- let inode_table = self.inode_table.lock().unwrap();
+ let inode_table = self.inode_table.read().unwrap();
handle_inode_locked(&inode_table, inode, |inode_state| handle_fn(&inode_state.entry))
}
@@ -343,7 +343,7 @@
where
F: FnOnce(&mut AuthFsEntry, &Path, Inode) -> io::Result<AuthFsEntry>,
{
- let mut inode_table = self.inode_table.lock().unwrap();
+ let mut inode_table = self.inode_table.write().unwrap();
let (new_inode, new_file_entry) = handle_inode_mut_locked(
&mut inode_table,
&parent_inode,
@@ -368,7 +368,7 @@
dir_entries: Vec<AuthFsDirEntry>,
) -> io::Result<(Option<Handle>, FuseOpenOptions)> {
let handle = self.next_handle.fetch_add(1, Ordering::Relaxed);
- let mut dir_handle_table = self.dir_handle_table.lock().unwrap();
+ let mut dir_handle_table = self.dir_handle_table.write().unwrap();
if let btree_map::Entry::Vacant(value) = dir_handle_table.entry(handle) {
value.insert(Arc::new(dir_entries));
Ok((Some(handle), FuseOpenOptions::empty()))
@@ -511,7 +511,7 @@
}
fn lookup(&self, _ctx: Context, parent: Inode, name: &CStr) -> io::Result<Entry> {
- let mut inode_table = self.inode_table.lock().unwrap();
+ let mut inode_table = self.inode_table.write().unwrap();
// Look up the entry's inode number in parent directory.
let inode =
@@ -566,7 +566,7 @@
}
fn forget(&self, _ctx: Context, inode: Self::Inode, count: u64) {
- let mut inode_table = self.inode_table.lock().unwrap();
+ let mut inode_table = self.inode_table.write().unwrap();
let delete_now = handle_inode_mut_locked(
&mut inode_table,
&inode,
@@ -764,7 +764,7 @@
_handle: Option<Handle>,
valid: SetattrValid,
) -> io::Result<(libc::stat64, Duration)> {
- let mut inode_table = self.inode_table.lock().unwrap();
+ let mut inode_table = self.inode_table.write().unwrap();
handle_inode_mut_locked(&mut inode_table, &inode, |InodeState { entry, .. }| match entry {
AuthFsEntry::VerifiedNew { editor, attr } => {
check_unsupported_setattr_request(valid)?;
@@ -879,7 +879,7 @@
}
fn unlink(&self, _ctx: Context, parent: Self::Inode, name: &CStr) -> io::Result<()> {
- let mut inode_table = self.inode_table.lock().unwrap();
+ let mut inode_table = self.inode_table.write().unwrap();
handle_inode_mut_locked(
&mut inode_table,
&parent,
@@ -906,7 +906,7 @@
}
fn rmdir(&self, _ctx: Context, parent: Self::Inode, name: &CStr) -> io::Result<()> {
- let mut inode_table = self.inode_table.lock().unwrap();
+ let mut inode_table = self.inode_table.write().unwrap();
// Check before actual removal, with readonly borrow.
handle_inode_locked(&inode_table, &parent, |inode_state| match &inode_state.entry {
@@ -962,7 +962,7 @@
_size: u32,
offset: u64,
) -> io::Result<Self::DirIter> {
- let dir_handle_table = self.dir_handle_table.lock().unwrap();
+ let dir_handle_table = self.dir_handle_table.read().unwrap();
if let Some(entry) = dir_handle_table.get(&handle) {
Ok(DirEntriesSnapshotIterator {
snapshot: entry.clone(),
@@ -980,7 +980,7 @@
_flags: u32,
handle: Self::Handle,
) -> io::Result<()> {
- let mut dir_handle_table = self.dir_handle_table.lock().unwrap();
+ let mut dir_handle_table = self.dir_handle_table.write().unwrap();
if dir_handle_table.remove(&handle).is_none() {
unreachable!("Unknown directory handle {}, inode {}", handle, inode);
}
@@ -1008,7 +1008,7 @@
st.f_bfree = st.f_bavail;
st.f_ffree = st.f_favail;
// Number of inodes on the filesystem
- st.f_files = self.inode_table.lock().unwrap().len() as u64;
+ st.f_files = self.inode_table.read().unwrap().len() as u64;
Ok(st)
}