From 3c18aac1663fbdb459e4f92a5fa35845b47e5c1e Mon Sep 17 00:00:00 2001 From: Jun Ouyang Date: Tue, 26 Mar 2024 00:10:25 +0800 Subject: [PATCH 01/10] feat(ofs): support lseek and copy_file_range rename2 --- bin/ofs/src/fuse.rs | 90 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/bin/ofs/src/fuse.rs b/bin/ofs/src/fuse.rs index 40df1b041e77..c93ebb63ce9a 100644 --- a/bin/ofs/src/fuse.rs +++ b/bin/ofs/src/fuse.rs @@ -638,6 +638,96 @@ impl PathFilesystem for Fuse { entries: relative_paths.chain(children).skip(offset as usize).boxed(), }) } + async fn rename2( + &self, + req: Request, + origin_parent: &OsStr, + origin_name: &OsStr, + parent: &OsStr, + name: &OsStr, + _flags: u32, + ) -> Result<()> { + log::debug!( + "rename2(origin_parent={:?}, origin_name={:?}, parent={:?}, name={:?})", + origin_parent, + origin_name, + parent, + name + ); + self.rename(req, origin_parent, origin_name, parent, name) + .await + } + + async fn lseek( + &self, + _req: Request, + path: Option<&OsStr>, + _fh: u64, + offset: u64, + whence: u32, + ) -> Result { + log::debug!("lseek(path={:?}, fh={}, offset={}, whence={})", path, _fh, offset, whence); + + let whence = whence as i32; + + let offset = if whence == libc::SEEK_CUR || whence == libc::SEEK_SET { + offset + } else if whence == libc::SEEK_END { + let metadata = self + .op + .stat(&path.unwrap().to_string_lossy()) + .await + .map_err(opendal_error2errno)?; + let content_size = metadata.content_length(); + + if content_size >= offset as _ { + content_size as u64 - offset + } else { + 0 + } + } else { + return Err(libc::EINVAL.into()); + }; + + Ok(ReplyLSeek { offset }) + } + + + async fn copy_file_range( + &self, + req: Request, + from_path: Option<&OsStr>, + fh_in: u64, + offset_in: u64, + to_path: Option<&OsStr>, + fh_out: u64, + offset_out: u64, + length: u64, + flags: u64, + ) -> Result { + log::debug!( + "copy_file_range(from_path={:?}, fh_in={}, offset_in={}, to_path={:?}, fh_out={}, offset_out={}, length={}, flags={})", + from_path, + fh_in, + offset_in, + to_path, + fh_out, + offset_out, + length, + flags + ); + let data = self + .read(req, from_path, fh_in, offset_in, length as _) + .await?; + + let ReplyWrite { written } = self + .write(req, to_path, fh_out, offset_out, &data.data, flags as _) + .await?; + + Ok(ReplyCopyFileRange { + copied: u64::from(written), + }) + } } const fn entry_mode2file_type(mode: EntryMode) -> FileType { From 9dd1a76b69791a62f4f38c0d3b32dd72f29c02d7 Mon Sep 17 00:00:00 2001 From: Jun Ouyang Date: Tue, 26 Mar 2024 01:08:24 +0800 Subject: [PATCH 02/10] feat(ofs): support getattr --- bin/ofs/src/fuse.rs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/bin/ofs/src/fuse.rs b/bin/ofs/src/fuse.rs index c93ebb63ce9a..af1e04e66b74 100644 --- a/bin/ofs/src/fuse.rs +++ b/bin/ofs/src/fuse.rs @@ -24,6 +24,8 @@ use std::time::Duration; use std::time::SystemTime; use bytes::Bytes; + + use fuse3::path::prelude::*; use fuse3::Errno; use fuse3::Result; @@ -208,7 +210,8 @@ impl PathFilesystem for Fuse { fh, set_attr ); - Err(libc::EOPNOTSUPP.into()) + + self.getattr(_req, path, fh, 0).await } async fn symlink( @@ -666,7 +669,13 @@ impl PathFilesystem for Fuse { offset: u64, whence: u32, ) -> Result { - log::debug!("lseek(path={:?}, fh={}, offset={}, whence={})", path, _fh, offset, whence); + log::debug!( + "lseek(path={:?}, fh={}, offset={}, whence={})", + path, + _fh, + offset, + whence + ); let whence = whence as i32; @@ -679,7 +688,7 @@ impl PathFilesystem for Fuse { .await .map_err(opendal_error2errno)?; let content_size = metadata.content_length(); - + if content_size >= offset as _ { content_size as u64 - offset } else { @@ -692,7 +701,6 @@ impl PathFilesystem for Fuse { Ok(ReplyLSeek { offset }) } - async fn copy_file_range( &self, req: Request, From b922415599df8b5e6f64dde5e9f93da22b387cb7 Mon Sep 17 00:00:00 2001 From: Jun Ouyang Date: Tue, 26 Mar 2024 10:13:14 +0800 Subject: [PATCH 03/10] feat(ofs): fix code --- bin/ofs/src/fuse.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/bin/ofs/src/fuse.rs b/bin/ofs/src/fuse.rs index af1e04e66b74..9211b821feb1 100644 --- a/bin/ofs/src/fuse.rs +++ b/bin/ofs/src/fuse.rs @@ -665,18 +665,24 @@ impl PathFilesystem for Fuse { &self, _req: Request, path: Option<&OsStr>, - _fh: u64, + fh: u64, offset: u64, whence: u32, ) -> Result { log::debug!( "lseek(path={:?}, fh={}, offset={}, whence={})", path, - _fh, + fh, offset, whence ); + let file = self.get_opened_file(FileKey::try_from(fh)?, path)?; + + if !file.is_read && !file.is_write { + Err(Errno::from(libc::EACCES))?; + } + let whence = whence as i32; let offset = if whence == libc::SEEK_CUR || whence == libc::SEEK_SET { From 12f081e4b7972de81a690c692580f0bc7af8652b Mon Sep 17 00:00:00 2001 From: Jun Ouyang Date: Tue, 26 Mar 2024 23:09:29 +0800 Subject: [PATCH 04/10] feat(ofs): fix code --- bin/ofs/src/fuse.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/bin/ofs/src/fuse.rs b/bin/ofs/src/fuse.rs index 9211b821feb1..dd2e21be5bee 100644 --- a/bin/ofs/src/fuse.rs +++ b/bin/ofs/src/fuse.rs @@ -25,7 +25,6 @@ use std::time::SystemTime; use bytes::Bytes; - use fuse3::path::prelude::*; use fuse3::Errno; use fuse3::Result; @@ -735,7 +734,7 @@ impl PathFilesystem for Fuse { .await?; let ReplyWrite { written } = self - .write(req, to_path, fh_out, offset_out, &data.data, flags as _) + .write(req, to_path, fh_out, offset_out, &data.data, 0, flags as _) .await?; Ok(ReplyCopyFileRange { From 8b39497bcc87308d8e1e6f8fc3abfb4202d568c2 Mon Sep 17 00:00:00 2001 From: Jun Ouyang Date: Wed, 27 Mar 2024 10:10:13 +0800 Subject: [PATCH 05/10] feat(ofs): fix code --- bin/ofs/src/fuse.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bin/ofs/src/fuse.rs b/bin/ofs/src/fuse.rs index dd2e21be5bee..51e19378247f 100644 --- a/bin/ofs/src/fuse.rs +++ b/bin/ofs/src/fuse.rs @@ -676,15 +676,15 @@ impl PathFilesystem for Fuse { whence ); + let whence = whence as i32; + let file = self.get_opened_file(FileKey::try_from(fh)?, path)?; if !file.is_read && !file.is_write { Err(Errno::from(libc::EACCES))?; } - let whence = whence as i32; - - let offset = if whence == libc::SEEK_CUR || whence == libc::SEEK_SET { + let offset = if whence == libc::SEEK_SET { offset } else if whence == libc::SEEK_END { let metadata = self @@ -700,7 +700,7 @@ impl PathFilesystem for Fuse { 0 } } else { - return Err(libc::EINVAL.into()); + return Err(libc::ENOSYS.into()); }; Ok(ReplyLSeek { offset }) From d0dce485584365f8e61ea23a58ff8fe8d0b1e920 Mon Sep 17 00:00:00 2001 From: Jun Ouyang Date: Wed, 27 Mar 2024 17:12:47 +0800 Subject: [PATCH 06/10] feat(ofs): fix code --- bin/ofs/src/fuse.rs | 52 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 47 insertions(+), 5 deletions(-) diff --git a/bin/ofs/src/fuse.rs b/bin/ofs/src/fuse.rs index 51e19378247f..fc4b8efd0c3b 100644 --- a/bin/ofs/src/fuse.rs +++ b/bin/ofs/src/fuse.rs @@ -20,6 +20,7 @@ use std::ffi::OsString; use std::num::NonZeroU32; use std::ops::Deref; use std::path::PathBuf; +use std::sync::RwLock; use std::time::Duration; use std::time::SystemTime; @@ -47,6 +48,7 @@ struct OpenedFile { is_read: bool, is_write: bool, is_append: bool, + offset: u64, } #[derive(Debug, Clone, Copy)] @@ -73,7 +75,7 @@ pub(super) struct Fuse { op: Operator, gid: u32, uid: u32, - opened_files: Slab, + opened_files: Slab>, } impl Fuse { @@ -114,6 +116,8 @@ impl Fuse { .as_ref() .ok_or(Errno::from(libc::ENOENT))? .deref() + .read() + .unwrap() .clone(); if matches!(path, Some(path) if path != file.path) { log::trace!( @@ -126,6 +130,34 @@ impl Fuse { Ok(file) } + + // Set opened file offset + fn set_opened_file_offset( + &self, + key: FileKey, + path: Option<&OsStr>, + offset: u64, + ) -> Result<()> { + let binding = self.opened_files.get(key.0); + let mut file = binding + .as_ref() + .ok_or(Errno::from(libc::ENOENT))? + .deref() + .write() + .unwrap(); + if matches!(path, Some(path) if path != file.path) { + log::trace!( + "set_opened_file: path not match: path={:?}, file={:?}", + path, + file.path + ); + Err(Errno::from(libc::EBADF))?; + } + + file.offset = offset; + + Ok(()) + } } impl PathFilesystem for Fuse { @@ -171,6 +203,7 @@ impl PathFilesystem for Fuse { self.opened_files .get(FileKey::try_from(fh).ok()?.0) .as_ref() + .and_then(|f| f.read().ok()) .map(|f| f.path.clone()) }); @@ -371,12 +404,13 @@ impl PathFilesystem for Fuse { let key = self .opened_files - .insert(OpenedFile { + .insert(RwLock::new(OpenedFile { path: path.into(), is_read, is_write, is_append: flags & libc::O_APPEND as u32 != 0, - }) + offset: 0, + })) .ok_or(Errno::from(libc::EBUSY))?; Ok(ReplyCreated { @@ -409,6 +443,7 @@ impl PathFilesystem for Fuse { let file = self .opened_files .take(FileKey::try_from(fh)?.0) + .map(|f| f.read().unwrap().clone()) .ok_or(Errno::from(libc::EBADF))?; if matches!(path, Some(ref p) if p != &file.path) { Err(Errno::from(libc::EBADF))?; @@ -424,12 +459,13 @@ impl PathFilesystem for Fuse { let key = self .opened_files - .insert(OpenedFile { + .insert(RwLock::new(OpenedFile { path: path.into(), is_read, is_write, is_append: flags & libc::O_APPEND as u32 != 0, - }) + offset: 0, + })) .ok_or(Errno::from(libc::EBUSY))?; Ok(ReplyOpen { @@ -467,6 +503,8 @@ impl PathFilesystem for Fuse { .await .map_err(opendal_error2errno)?; + self.set_opened_file_offset(FileKey::try_from(fh)?, path, offset + data.len() as u64)?; + Ok(ReplyData { data: data.into() }) } @@ -507,6 +545,8 @@ impl PathFilesystem for Fuse { .await .map_err(opendal_error2errno)?; + self.set_opened_file_offset(FileKey::try_from(fh)?, path, offset + data.len() as u64)?; + Ok(ReplyWrite { written: data.len() as _, }) @@ -686,6 +726,8 @@ impl PathFilesystem for Fuse { let offset = if whence == libc::SEEK_SET { offset + } else if whence == libc::SEEK_CUR { + file.offset + offset } else if whence == libc::SEEK_END { let metadata = self .op From 677dd20e0299f7f2afe5cefa7b3031a0ecab85b1 Mon Sep 17 00:00:00 2001 From: Jun Ouyang Date: Wed, 27 Mar 2024 17:28:05 +0800 Subject: [PATCH 07/10] feat(ofs): fix code --- bin/ofs/src/fuse.rs | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/bin/ofs/src/fuse.rs b/bin/ofs/src/fuse.rs index fc4b8efd0c3b..cb22c6448b6b 100644 --- a/bin/ofs/src/fuse.rs +++ b/bin/ofs/src/fuse.rs @@ -110,15 +110,17 @@ impl Fuse { // Get opened file and check given path fn get_opened_file(&self, key: FileKey, path: Option<&OsStr>) -> Result { - let file = self + let file = match self .opened_files .get(key.0) .as_ref() .ok_or(Errno::from(libc::ENOENT))? .deref() - .read() - .unwrap() - .clone(); + .read() { + Ok(file) => file.clone(), + Err(_) => Err(Errno::from(libc::EBADF))?, + }; + if matches!(path, Some(path) if path != file.path) { log::trace!( "get_opened_file: path not match: path={:?}, file={:?}", @@ -138,13 +140,16 @@ impl Fuse { path: Option<&OsStr>, offset: u64, ) -> Result<()> { + let binding = self.opened_files.get(key.0); - let mut file = binding + let mut file = match binding .as_ref() .ok_or(Errno::from(libc::ENOENT))? .deref() - .write() - .unwrap(); + .write() { + Ok(file) => file, + Err(_) => Err(Errno::from(libc::EBADF))?, + }; if matches!(path, Some(path) if path != file.path) { log::trace!( "set_opened_file: path not match: path={:?}, file={:?}", From ef2200b368b3bf2573c24ad41af0d545ffa21a25 Mon Sep 17 00:00:00 2001 From: Jun Ouyang Date: Wed, 27 Mar 2024 17:30:10 +0800 Subject: [PATCH 08/10] feat(ofs): fix code --- bin/ofs/src/fuse.rs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/bin/ofs/src/fuse.rs b/bin/ofs/src/fuse.rs index cb22c6448b6b..6324d41845bd 100644 --- a/bin/ofs/src/fuse.rs +++ b/bin/ofs/src/fuse.rs @@ -116,9 +116,10 @@ impl Fuse { .as_ref() .ok_or(Errno::from(libc::ENOENT))? .deref() - .read() { - Ok(file) => file.clone(), - Err(_) => Err(Errno::from(libc::EBADF))?, + .read() + { + Ok(file) => file.clone(), + Err(_) => Err(Errno::from(libc::EBADF))?, }; if matches!(path, Some(path) if path != file.path) { @@ -140,15 +141,15 @@ impl Fuse { path: Option<&OsStr>, offset: u64, ) -> Result<()> { - let binding = self.opened_files.get(key.0); let mut file = match binding .as_ref() .ok_or(Errno::from(libc::ENOENT))? .deref() - .write() { - Ok(file) => file, - Err(_) => Err(Errno::from(libc::EBADF))?, + .write() + { + Ok(file) => file, + Err(_) => Err(Errno::from(libc::EBADF))?, }; if matches!(path, Some(path) if path != file.path) { log::trace!( From 93f8f750461a216bbbcf2739aae4fe182d32ebb3 Mon Sep 17 00:00:00 2001 From: Jun Ouyang Date: Wed, 27 Mar 2024 18:38:34 +0800 Subject: [PATCH 09/10] feat(ofs): fix code --- bin/ofs/src/fuse.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/bin/ofs/src/fuse.rs b/bin/ofs/src/fuse.rs index 6324d41845bd..a3aaf6fe10a6 100644 --- a/bin/ofs/src/fuse.rs +++ b/bin/ofs/src/fuse.rs @@ -354,6 +354,10 @@ impl PathFilesystem for Fuse { name ); + if !self.op.info().full_capability().rename { + return Err(Errno::from(libc::EACCES))?; + } + let origin_path = PathBuf::from(origin_parent).join(origin_name); let path = PathBuf::from(parent).join(name); From f8c02dc24d1f609002bea5515d63c8394ef1dcfa Mon Sep 17 00:00:00 2001 From: Jun Ouyang Date: Wed, 27 Mar 2024 18:58:17 +0800 Subject: [PATCH 10/10] feat(ofs): fix code --- bin/ofs/src/fuse.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/ofs/src/fuse.rs b/bin/ofs/src/fuse.rs index a3aaf6fe10a6..c8bb50dbc6fd 100644 --- a/bin/ofs/src/fuse.rs +++ b/bin/ofs/src/fuse.rs @@ -355,7 +355,7 @@ impl PathFilesystem for Fuse { ); if !self.op.info().full_capability().rename { - return Err(Errno::from(libc::EACCES))?; + return Err(Errno::from(libc::ENOTSUP))?; } let origin_path = PathBuf::from(origin_parent).join(origin_name);