Theoretically support sending GetAttr commands to the server

This commit is contained in:
Olivier 'reivilibre' 2022-01-20 18:33:22 +00:00
parent a298b42672
commit 45cbd2d0db
4 changed files with 71 additions and 12 deletions

View File

@ -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"] }

View File

@ -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<Fut>(&self, future: Fut, name: &'static str)
where
Fut: Future<Output = anyhow::Result<()>> + Send + 'static,
{
self.tokio_runtime.spawn(async move {
if let Err(error) = future.await {
error!("Error in {}: {:?}", name, error);
}
});
}
}

View File

@ -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<R: DeserializeOwned>(
&mut self,
&self,
command: &DataCommand,
) -> anyhow::Result<DataResponse<R>> {
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<DataResponse<()>> {
todo!()
pub async fn getattr(&self, vnode: VnodeId) -> anyhow::Result<DataResponse<FileMetadata>> {
self.internal.command(&DataCommand::GetAttr { vnode }).await
}
}

View File

@ -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<FileType> for FileKind {
fn from(filetype: FileType) -> Self {
@ -29,3 +28,25 @@ impl Into<FileType> for FileKind {
}
}
}
impl Into<FileAttr> 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,
}
}
}