Support read on the client side

This commit is contained in:
Olivier 'reivilibre' 2022-01-22 11:28:07 +00:00
parent 9c8659f75a
commit b23202f39a
3 changed files with 45 additions and 26 deletions

View File

@ -11,13 +11,13 @@ use std::future::Future;
use crate::Requester;
use anyhow::{anyhow, Context};
use fuser::consts::FOPEN_DIRECT_IO;
use olivefs_common::error_codes::ENOENT;
use olivefs_common::messages::{DataResponse, DirectoryEntry, OpenMode, VnodeId};
use std::os::raw::c_int;
use std::path::Path;
use std::sync::Arc;
use std::time::{Duration, SystemTime};
use fuser::consts::FOPEN_DIRECT_IO;
use tokio::sync::RwLock;
pub mod encryption;
@ -380,37 +380,40 @@ impl Filesystem for OliveFilesystem {
fn read(
&mut self,
_req: &Request<'_>,
ino: u64,
_ino: u64,
fh: u64,
offset: i64,
size: u32,
flags: i32,
lock_owner: Option<u64>,
_flags: i32,
_lock_owner: Option<u64>,
reply: ReplyData,
) {
warn!(
"[Not Implemented] read(ino: {:#x?}, fh: {}, offset: {}, size: {}, \
flags: {:#x?}, lock_owner: {:?})",
ino, fh, offset, size, flags, lock_owner
// If you don't open files in direct I/O, the kernel caches things and uses the length from
// getattr — but potentially we want to allow the size to change on the server
// and not fall over, so we have to use direct I/O mode.
let requester = self.requester.clone();
let file_handle: u32 = fh.try_into().unwrap();
self.spawn_with_error_handler(
async move {
match requester.read(file_handle, offset, size).await? {
DataResponse::Success(data) => {
reply.data(&data);
}
DataResponse::Error { code, message } => {
warn!(
"read(fn: {:#x?}, offset: {:?}, size: {:?}) failed: {:?}",
file_handle, offset, size, message
);
reply.error(code as c_int);
}
}
Ok(())
},
"read",
);
// TODO There seems to be a bug here, but it only seems to occur on the first read of a file
// but oddly not after restarting olivefs....
// reply.data(&[42]);
// TODO searching online, it seems like making files get opened in direct I/O mode is the
// probable solution. Otherwise the kernel caches things and uses the length from
// getattr — but potentially we want to allow the size to change on the server
// and not fall over?
if offset == 0 {
reply.data(&[42]);
} else {
reply.data(&[]);
}
//reply.error(ENOSYS);
}
/// Write data.

View File

@ -197,4 +197,19 @@ impl Requester {
.command(&DataCommand::ReleaseFile { file_handle })
.await
}
pub async fn read(
&self,
file_handle: u32,
offset: i64,
size: u32,
) -> anyhow::Result<DataResponse<Vec<u8>>> {
self.internal
.command(&DataCommand::ReadFile {
file_handle,
offset,
size,
})
.await
}
}

View File

@ -45,6 +45,7 @@ pub enum DataCommand {
Lookup { dir_vnode: VnodeId, name: String },
OpenFile { vnode: VnodeId, mode: OpenMode },
ReleaseFile { file_handle: u32 },
ReadFile { file_handle: u32, offset: i64, size: u32 },
}
pub trait DataResponseBase: Serialize + DeserializeOwned + Debug + Clone + 'static {}