From 45cbd2d0db81625e1307a4b81ac5500251da40ad Mon Sep 17 00:00:00 2001 From: Olivier 'reivilibre Date: Thu, 20 Jan 2022 18:33:22 +0000 Subject: [PATCH] Theoretically support sending GetAttr commands to the server --- olivefs/Cargo.toml | 2 +- olivefs/src/filesystem.rs | 46 +++++++++++++++++-- olivefs/src/requester.rs | 8 ++-- olivefs_common/src/messages/messages_fuser.rs | 27 +++++++++-- 4 files changed, 71 insertions(+), 12 deletions(-) diff --git a/olivefs/Cargo.toml b/olivefs/Cargo.toml index e88bd76..5721ed2 100644 --- a/olivefs/Cargo.toml +++ b/olivefs/Cargo.toml @@ -36,4 +36,4 @@ fuser = "0.10.0" libc = "0.2.112" # Common -olivefs_common = { path = "../olivefs_common" } +olivefs_common = { path = "../olivefs_common", features = ["fuser"] } diff --git a/olivefs/src/filesystem.rs b/olivefs/src/filesystem.rs index d096156..77579f4 100644 --- a/olivefs/src/filesystem.rs +++ b/olivefs/src/filesystem.rs @@ -4,10 +4,13 @@ use fuser::{ ReplyStatfs, ReplyWrite, ReplyXattr, Request, TimeOrNow, }; use libc::{ENOSYS, EPERM}; -use log::{debug, warn}; +use log::{debug, error, warn}; use std::ffi::OsStr; +use std::future::Future; use crate::Requester; +use anyhow::Context; +use olivefs_common::messages::{DataResponse, VnodeId}; use std::os::raw::c_int; use std::path::Path; use std::sync::Arc; @@ -31,7 +34,7 @@ impl Filesystem for OliveFilesystem { /// Initialize filesystem. /// Called before any other filesystem method. /// The kernel module connection can be configured using the KernelConfig object - fn init(&mut self, req: &Request<'_>, _config: &mut KernelConfig) -> Result<(), c_int> { + fn init(&mut self, _req: &Request<'_>, _config: &mut KernelConfig) -> Result<(), c_int> { // TODO config has some interesting values. Ok(()) } @@ -92,8 +95,30 @@ impl Filesystem for OliveFilesystem { /// Get file attributes. fn getattr(&mut self, _req: &Request<'_>, ino: u64, reply: ReplyAttr) { - warn!("[Not Implemented] getattr(ino: {:#x?})", ino); - reply.error(ENOSYS); + let requester = self.requester.clone(); + + self.spawn_with_error_handler( + async move { + let vnode = VnodeId( + ino.try_into() + .context("Converting u64 inode to u32 VnodeId.")?, + ); + + match requester.getattr(vnode).await? { + DataResponse::Success(file_metadata) => { + let file_attr = file_metadata.into(); + reply.attr(&Duration::from_secs(5), &file_attr); + } + DataResponse::Error { code, message } => { + warn!("getattr(ino: {:#x?}) failed: {:?}", ino, message); + reply.error(code as c_int); + } + } + + Ok(()) + }, + "getattr", + ); } /// Set file attributes. @@ -729,3 +754,16 @@ impl Filesystem for OliveFilesystem { reply.error(ENOSYS); } } + +impl OliveFilesystem { + pub fn spawn_with_error_handler(&self, future: Fut, name: &'static str) + where + Fut: Future> + Send + 'static, + { + self.tokio_runtime.spawn(async move { + if let Err(error) = future.await { + error!("Error in {}: {:?}", name, error); + } + }); + } +} diff --git a/olivefs/src/requester.rs b/olivefs/src/requester.rs index 80baa7f..5cf558e 100644 --- a/olivefs/src/requester.rs +++ b/olivefs/src/requester.rs @@ -12,7 +12,7 @@ use std::str::FromStr; use std::sync::Arc; use olivefs_common::io::read_file; -use olivefs_common::messages::{DataCommand, DataResponse, VnodeId}; +use olivefs_common::messages::{DataCommand, DataResponse, FileMetadata, VnodeId}; use olivefs_common::networking::{ hello_handshake, read_bare_message, send_bare_message, ALPN_PROTOCOL, }; @@ -122,7 +122,7 @@ impl RequesterInternal { } pub async fn command( - &mut self, + &self, command: &DataCommand, ) -> anyhow::Result> { self.with_stream(|mut tx, mut rx| async { @@ -141,7 +141,7 @@ impl Requester { Requester { internal } } - pub async fn getattr(&mut self, _vnode: VnodeId) -> anyhow::Result> { - todo!() + pub async fn getattr(&self, vnode: VnodeId) -> anyhow::Result> { + self.internal.command(&DataCommand::GetAttr { vnode }).await } } diff --git a/olivefs_common/src/messages/messages_fuser.rs b/olivefs_common/src/messages/messages_fuser.rs index 6a0a73e..a6361d3 100644 --- a/olivefs_common/src/messages/messages_fuser.rs +++ b/olivefs_common/src/messages/messages_fuser.rs @@ -1,6 +1,5 @@ -use crate::messages::FileKind; -use fuser::FileType; -use std::fs::FileType; +use crate::messages::{FileKind, FileMetadata}; +use fuser::{FileAttr, FileType}; impl From for FileKind { fn from(filetype: FileType) -> Self { @@ -29,3 +28,25 @@ impl Into for FileKind { } } } + +impl Into for FileMetadata { + fn into(self) -> FileAttr { + FileAttr { + ino: self.ino.0 as u64, + size: self.size, + blocks: self.blocks, + atime: self.atime, + mtime: self.mtime, + ctime: self.ctime, + crtime: self.ctime, + kind: self.kind.into(), + perm: self.perm, + nlink: self.nlink, + uid: self.uid, + gid: self.gid, + rdev: self.rdev, + blksize: self.blksize, + flags: 0, + } + } +}