Skip to content

Commit 6b758d2

Browse files
jiangliubergwolf
authored andcommitted
ptfs: refine code style with more comments
Refine code style with more comments. Signed-off-by: Jiang Liu <[email protected]>
1 parent ed27ca3 commit 6b758d2

File tree

3 files changed

+51
-54
lines changed

3 files changed

+51
-54
lines changed

src/passthrough/file_handle.rs

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ use crate::passthrough::PassthroughFs;
2020

2121
/// An arbitrary maximum size for CFileHandle::f_handle.
2222
///
23-
/// According to Linux ABI, struct file_handle has a flexible array member 'f_handle', but it's
24-
/// hard-coded here for simplicity.
23+
/// According to Linux ABI, struct file_handle has a flexible array member 'f_handle', with
24+
/// maximum value of 128 bytes defined in file include/linux/exportfs.h
2525
pub const MAX_HANDLE_SIZE: usize = 128;
2626

2727
/// Dynamically allocated array.
@@ -209,6 +209,12 @@ impl FileHandle {
209209
let needed = c_fh.wrapper.as_fam_struct_ref().handle_bytes as usize;
210210
let mut c_fh = CFileHandle::new(needed);
211211

212+
// name_to_handle_at() does not trigger a mount when the final component of the pathname is
213+
// an automount point. When a filesystem supports both file handles and automount points,
214+
// a name_to_handle_at() call on an automount point will return with error EOVERFLOW
215+
// without having increased handle_bytes. This can happen since Linux 4.13 with NFS
216+
// when accessing a directory which is on a separate filesystem on the server. In this case,
217+
// the automount can be triggered by adding a "/" to the end of the pathname.
212218
let ret = unsafe {
213219
name_to_handle_at(
214220
dir_fd,
@@ -286,7 +292,7 @@ impl FileHandle {
286292
mount_fds: &MountFds,
287293
flags: libc::c_int,
288294
) -> io::Result<File> {
289-
let mount_fds_locked = mount_fds.map.read().unwrap();
295+
let mount_fds_locked = mount_fds.get_map();
290296
let mount_file = mount_fds_locked.get(&self.mnt_id).ok_or_else(|| {
291297
error!(
292298
"open_with_mount_fds: mnt_id {:?} is not found.",
@@ -314,12 +320,10 @@ impl MountFds {
314320
MountFds::default()
315321
}
316322

317-
#[allow(dead_code)]
318323
pub fn get_map(&self) -> RwLockReadGuard<'_, HashMap<u64, std::fs::File>> {
319324
self.map.read().unwrap()
320325
}
321326

322-
#[allow(dead_code)]
323327
pub fn get_map_mut(&self) -> RwLockWriteGuard<'_, HashMap<u64, std::fs::File>> {
324328
self.map.write().unwrap()
325329
}
@@ -334,7 +338,7 @@ impl MountFds {
334338
where
335339
F: FnOnce(RawFd, libc::c_int, u32) -> io::Result<File>,
336340
{
337-
if self.map.read().unwrap().contains_key(&mnt_id) {
341+
if self.get_map().contains_key(&mnt_id) {
338342
return Ok(());
339343
}
340344

@@ -386,7 +390,7 @@ impl MountFds {
386390
libc::O_RDONLY | libc::O_NOFOLLOW | libc::O_CLOEXEC,
387391
st.st_mode,
388392
)?;
389-
self.map.write().unwrap().insert(mnt_id, file);
393+
self.get_map_mut().insert(mnt_id, file);
390394

391395
Ok(())
392396
}

src/passthrough/inode_store.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ pub struct InodeStore {
1515
}
1616

1717
impl InodeStore {
18+
/// Insert an inode into the manager
19+
///
20+
/// The caller needs to ensure that no inode with the same key exists, otherwise the old inode
21+
/// will get lost.
1822
pub fn insert(&mut self, data: Arc<InodeData>) {
1923
self.by_ids.insert(data.altkey, data.inode);
2024
if let FileOrHandle::Handle(handle) = &data.file_or_handle {
@@ -23,6 +27,7 @@ impl InodeStore {
2327
self.data.insert(data.inode, data);
2428
}
2529

30+
/// Remove an inode from the manager, keeping the (key, ino) mapping if `remove_data_only` is true.
2631
pub fn remove(&mut self, inode: &Inode, remove_data_only: bool) -> Option<Arc<InodeData>> {
2732
let data = self.data.remove(inode);
2833
if remove_data_only {

src/passthrough/mod.rs

Lines changed: 35 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -27,34 +27,32 @@ use std::sync::atomic::{AtomicBool, AtomicU32, AtomicU64, AtomicU8, Ordering};
2727
use std::sync::{Arc, Mutex, MutexGuard, RwLock, RwLockWriteGuard};
2828
use std::time::Duration;
2929

30-
use vm_memory::ByteValued;
30+
use vm_memory::{bitmap::BitmapSlice, ByteValued};
3131

32+
use self::file_handle::{FileHandle, MountFds};
33+
use self::inode_store::InodeStore;
3234
use crate::abi::fuse_abi as fuse;
3335
use crate::abi::fuse_abi::Opcode;
3436
use crate::api::filesystem::Entry;
3537
use crate::api::{
3638
validate_path_component, BackendFileSystem, CURRENT_DIR_CSTR, EMPTY_CSTR, PARENT_DIR_CSTR,
3739
PROC_SELF_FD_CSTR, SLASH_ASCII, VFS_MAX_INO,
3840
};
39-
use crate::passthrough::inode_store::InodeStore;
40-
use crate::BitmapSlice;
4141

4242
#[cfg(feature = "async-io")]
4343
mod async_io;
4444
mod file_handle;
4545
mod inode_store;
4646
mod sync_io;
4747

48-
use file_handle::{FileHandle, MountFds};
49-
5048
type Inode = u64;
5149
type Handle = u64;
5250

5351
/// Maximum host inode number supported by passthroughfs
54-
pub const MAX_HOST_INO: u64 = 0x7fff_ffff_ffff;
52+
const MAX_HOST_INO: u64 = 0x7fff_ffff_ffff;
5553

5654
/// the 56th bit used to set the inode to 1 indicates virtual inode
57-
pub const USE_VIRTUAL_INODE_MASK: u64 = 1 << 55;
55+
const VIRTUAL_INODE_FLAG: u64 = 1 << 55;
5856

5957
/// Used to form a pair of dev and mntid as the key of the map
6058
#[derive(Clone, Copy, Default, PartialOrd, Ord, PartialEq, Eq, Debug)]
@@ -83,10 +81,9 @@ impl UniqueInodeGenerator {
8381
}
8482

8583
fn get_unique_inode(&self, alt_key: &InodeAltKey) -> io::Result<libc::ino64_t> {
86-
let id: DevMntIDPair = DevMntIDPair(alt_key.dev, alt_key.mnt);
87-
let mut id_map_guard = self.dev_mntid_map.lock().unwrap();
88-
8984
let unique_id = {
85+
let id: DevMntIDPair = DevMntIDPair(alt_key.dev, alt_key.mnt);
86+
let mut id_map_guard = self.dev_mntid_map.lock().unwrap();
9087
match id_map_guard.entry(id) {
9188
btree_map::Entry::Occupied(v) => *v.get(),
9289
btree_map::Entry::Vacant(v) => {
@@ -112,7 +109,7 @@ impl UniqueInodeGenerator {
112109
format!("the virtual inode excess {}", MAX_HOST_INO),
113110
));
114111
}
115-
self.next_virtual_inode.fetch_add(1, Ordering::Relaxed) | USE_VIRTUAL_INODE_MASK
112+
self.next_virtual_inode.fetch_add(1, Ordering::Relaxed) | VIRTUAL_INODE_FLAG
116113
};
117114

118115
Ok((unique_id as u64) << 47 | inode)
@@ -464,34 +461,34 @@ impl FromStr for CachePolicy {
464461
/// Options that configure the behavior of the passthrough fuse file system.
465462
#[derive(Debug, Clone, Eq, PartialEq)]
466463
pub struct Config {
464+
/// How long the FUSE client should consider file and directory attributes to be valid. If the
465+
/// attributes of a file or directory can only be modified by the FUSE client (i.e., the file
466+
/// system has exclusive access), then this should be set to a large value.
467+
///
468+
/// The default value for this option is 5 seconds.
469+
pub attr_timeout: Duration,
470+
467471
/// How long the FUSE client should consider directory entries to be valid. If the contents of a
468472
/// directory can only be modified by the FUSE client (i.e., the file system has exclusive
469473
/// access), then this should be a large value.
470474
///
471475
/// The default value for this option is 5 seconds.
472476
pub entry_timeout: Duration,
473477

474-
/// How long the FUSE client should consider file and directory attributes to be valid. If the
475-
/// attributes of a file or directory can only be modified by the FUSE client (i.e., the file
476-
/// system has exclusive access), then this should be set to a large value.
477-
///
478-
/// The default value for this option is 5 seconds.
479-
pub attr_timeout: Duration,
478+
/// Same as `attr_timeout`, override `attr_timeout` config, but only take effect on directories
479+
/// when specified. This is useful to set different timeouts for directories and regular files.
480+
pub dir_attr_timeout: Option<Duration>,
480481

481482
/// Same as `entry_timeout`, override `entry_timeout` config, but only take effect on
482483
/// directories when specified. This is useful to set different timeouts for directories and
483484
/// regular files.
484485
pub dir_entry_timeout: Option<Duration>,
485486

486-
/// Same as `attr_timeout`, override `attr_timeout` config, but only take effect on directories
487-
/// when specified. This is useful to set different timeouts for directories and regular files.
488-
pub dir_attr_timeout: Option<Duration>,
489-
490487
/// The caching policy the file system should use. See the documentation of `CachePolicy` for
491488
/// more details.
492489
pub cache_policy: CachePolicy,
493490

494-
/// Whether the file system should enabled writeback caching. This can improve performance as it
491+
/// Whether the file system should enable writeback caching. This can improve performance as it
495492
/// allows the FUSE client to cache and coalesce multiple writes before sending them to the file
496493
/// system. However, enabling this option can increase the risk of data corruption if the file
497494
/// contents can change without the knowledge of the FUSE client (i.e., the server does **NOT**
@@ -792,23 +789,14 @@ impl<S: BitmapSlice + Send + Sync> PassthroughFs<S> {
792789
return Err(io::Error::last_os_error());
793790
}
794791

795-
// Safe because we know buf len
796-
unsafe {
797-
buf.set_len(buf_read as usize);
798-
}
792+
// Safe because we trust the value returned by kernel.
793+
unsafe { buf.set_len(buf_read as usize) };
794+
buf.shrink_to_fit();
799795

800-
if (buf_read as usize) < buf.capacity() {
801-
buf.shrink_to_fit();
802-
803-
return Ok(PathBuf::from(OsString::from_vec(buf)));
804-
}
805-
806-
error!(
807-
"fuse: readlinkat return value {} is greater than libc::PATH_MAX({})",
808-
buf_read,
809-
libc::PATH_MAX
810-
);
811-
Err(io::Error::from_raw_os_error(libc::EOVERFLOW))
796+
// Be careful:
797+
// - readlink() does not append a terminating null byte to buf
798+
// - OsString instances are not NUL terminated
799+
return Ok(PathBuf::from(OsString::from_vec(buf)));
812800
}
813801

814802
/// Get the file pathname corresponding to the Inode
@@ -1320,6 +1308,15 @@ macro_rules! scoped_cred {
13201308
scoped_cred!(ScopedUid, libc::uid_t, libc::SYS_setresuid);
13211309
scoped_cred!(ScopedGid, libc::gid_t, libc::SYS_setresgid);
13221310

1311+
fn set_creds(
1312+
uid: libc::uid_t,
1313+
gid: libc::gid_t,
1314+
) -> io::Result<(Option<ScopedUid>, Option<ScopedGid>)> {
1315+
// We have to change the gid before we change the uid because if we change the uid first then we
1316+
// lose the capability to change the gid. However changing back can happen in any order.
1317+
ScopedGid::new(gid).and_then(|gid| Ok((ScopedUid::new(uid)?, gid)))
1318+
}
1319+
13231320
struct CapFsetid {}
13241321

13251322
impl Drop for CapFsetid {
@@ -1345,15 +1342,6 @@ fn drop_cap_fsetid() -> io::Result<Option<CapFsetid>> {
13451342
Ok(Some(CapFsetid {}))
13461343
}
13471344

1348-
fn set_creds(
1349-
uid: libc::uid_t,
1350-
gid: libc::gid_t,
1351-
) -> io::Result<(Option<ScopedUid>, Option<ScopedGid>)> {
1352-
// We have to change the gid before we change the uid because if we change the uid first then we
1353-
// lose the capability to change the gid. However changing back can happen in any order.
1354-
ScopedGid::new(gid).and_then(|gid| Ok((ScopedUid::new(uid)?, gid)))
1355-
}
1356-
13571345
fn ebadf() -> io::Error {
13581346
io::Error::from_raw_os_error(libc::EBADF)
13591347
}

0 commit comments

Comments
 (0)