summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlejandro Soto <alejandro@34project.org>2022-01-06 08:18:58 -0600
committerAlejandro Soto <alejandro@34project.org>2022-01-06 08:18:58 -0600
commitb3a9082a8b81c28ef81dbaaffe171f646b1f2777 (patch)
treed878ad0185657eff76426888d46420b48e47725b
parenta65325e15844f880132a69b447e4aec983cb30ab (diff)
Implement Fsync/Fsyncdir
-rw-r--r--examples/passthrough.rs40
-rw-r--r--src/io.rs2
-rw-r--r--src/ops/mod.rs2
-rw-r--r--src/ops/rw.rs52
-rw-r--r--src/proto.rs6
-rw-r--r--src/session.rs12
6 files changed, 96 insertions, 18 deletions
diff --git a/examples/passthrough.rs b/examples/passthrough.rs
index 7115fb1..2837d81 100644
--- a/examples/passthrough.rs
+++ b/examples/passthrough.rs
@@ -12,7 +12,7 @@ use std::{
};
use blown_fuse::{
- io::{Attrs, Entry, EntryType, Gid, Known, Mode, OpenFlags, Stat, Uid},
+ io::{Attrs, Entry, EntryType, FsyncFlags, Gid, Known, Mode, OpenFlags, Stat, Uid},
mount::mount_sync,
ops,
session::{Dispatch, Start},
@@ -135,6 +135,16 @@ impl Passthrough {
reply.blob(&target)
}
+ async fn symlink<'o>(&mut self, (request, reply): Op<'o, ops::Symlink>) -> Done<'o> {
+ let (reply, inode) = reply.and_then(self.known(request.ino()))?;
+ let path = inode.path.join(request.name());
+
+ let (reply, ()) = reply.and_then(fs::symlink(request.target(), &path).await)?;
+ let (reply, metadata) = reply.and_then(fs::symlink_metadata(&path).await)?;
+
+ reply.known(New(&mut self.known, Inode::new(path, metadata)), Ttl::MAX)
+ }
+
async fn mkdir<'o>(&mut self, (request, reply): Op<'o, ops::Mkdir>) -> Done<'o> {
let (reply, inode) = reply.and_then(self.known(request.ino()))?;
let path = inode.path.join(request.name());
@@ -161,16 +171,6 @@ impl Passthrough {
reply.ok()
}
- async fn symlink<'o>(&mut self, (request, reply): Op<'o, ops::Symlink>) -> Done<'o> {
- let (reply, inode) = reply.and_then(self.known(request.ino()))?;
- let path = inode.path.join(request.name());
-
- let (reply, ()) = reply.and_then(fs::symlink(request.target(), &path).await)?;
- let (reply, metadata) = reply.and_then(fs::symlink_metadata(&path).await)?;
-
- reply.known(New(&mut self.known, Inode::new(path, metadata)), Ttl::MAX)
- }
-
async fn open<'o>(&mut self, (request, reply): Op<'o, ops::Open>) -> Done<'o> {
let (reply, inode) = reply.and_then(self.known(request.ino()))?;
let options = {
@@ -230,6 +230,21 @@ impl Passthrough {
reply.ok()
}
+ async fn fsync<'o>(&mut self, (request, reply): Op<'o, ops::Fsync>) -> Done<'o> {
+ let (reply, file) = reply.and_then(self.open_files.get(request.handle()))?;
+ let (reply, ()) = {
+ let result = if request.flags().contains(FsyncFlags::FDATASYNC) {
+ file.handle.sync_data().await
+ } else {
+ file.handle.sync_all().await
+ };
+
+ reply.and_then(result)?
+ };
+
+ reply.ok()
+ }
+
async fn opendir<'o>(&mut self, (request, reply): Op<'o, ops::Opendir>) -> Done<'o> {
let (reply, inode) = reply.and_then(self.known(request.ino()))?;
let (mut reply, mut stream) = reply.and_then(fs::read_dir(&inode.path).await)?;
@@ -375,15 +390,16 @@ async fn main_loop(session: Start, mut fs: Passthrough) -> FuseResult<()> {
Forget(forget) => fs.forget(forget.op()?),
Getattr(getattr) => fs.getattr(getattr.op()?),
Readlink(readlink) => fs.readlink(readlink.op()?).await,
+ Symlink(symlink) => fs.symlink(symlink.op()?).await,
Mkdir(mkdir) => fs.mkdir(mkdir.op()?).await,
Unlink(unlink) => fs.unlink(unlink.op()?).await,
Rmdir(rmdir) => fs.rmdir(rmdir.op()?).await,
- Symlink(symlink) => fs.symlink(symlink.op()?).await,
//TODO: Link
Open(open) => fs.open(open.op()?).await,
Read(read) => fs.read(read.op()?).await,
Write(write) => fs.write(write.op()?).await,
Release(release) => fs.release(release.op()?),
+ Fsync(fsync) => fs.fsync(fsync.op()?).await,
Opendir(opendir) => fs.opendir(opendir.op()?).await,
Readdir(readdir) => fs.readdir(readdir.op()?).await,
Releasedir(releasedir) => fs.releasedir(releasedir.op()?),
diff --git a/src/io.rs b/src/io.rs
index 7124fda..9ec3214 100644
--- a/src/io.rs
+++ b/src/io.rs
@@ -19,6 +19,8 @@ pub use nix::{
unistd::{AccessFlags, Gid, Pid, Uid},
};
+pub use proto::FsyncFlags;
+
pub enum Interruptible<'o, O: Operation<'o>, T> {
Completed(Reply<'o, O>, T),
Interrupted(Done<'o>),
diff --git a/src/ops/mod.rs b/src/ops/mod.rs
index bc486b1..de13ac6 100644
--- a/src/ops/mod.rs
+++ b/src/ops/mod.rs
@@ -15,7 +15,7 @@ pub use dir::{BufferedReaddir, Lookup, Readdir};
pub use entry::{Forget, Getattr, Link, Mkdir, Rmdir, Symlink, Unlink};
pub use global::{Init, Statfs};
pub use open::{Access, Open, Opendir, Release, Releasedir};
-pub use rw::{Flush, Read, Readlink, Write};
+pub use rw::{Flush, Fsync, Fsyncdir, Read, Readlink, Write};
pub use xattr::{Getxattr, Listxattr, Removexattr, Setxattr};
mod dir;
diff --git a/src/ops/rw.rs b/src/ops/rw.rs
index cf2e286..4f5bad4 100644
--- a/src/ops/rw.rs
+++ b/src/ops/rw.rs
@@ -1,14 +1,18 @@
use super::{
- traits::{ReplyGather, ReplyOk, RequestData, RequestHandle, RequestOffset, RequestSize},
+ traits::{
+ ReplyGather, ReplyOk, RequestData, RequestFlags, RequestHandle, RequestOffset, RequestSize,
+ },
FromRequest,
};
-use crate::{private_trait::Sealed, proto, Done, Operation, Reply, Request};
+use crate::{io::FsyncFlags, private_trait::Sealed, proto, Done, Operation, Reply, Request};
pub enum Readlink {}
pub enum Read {}
pub enum Write {}
+pub enum Fsync {}
pub enum Flush {}
+pub enum Fsyncdir {}
pub struct WriteState {
size: u32,
@@ -21,7 +25,9 @@ pub trait ReplyAll<'o>: Operation<'o> {
impl Sealed for Readlink {}
impl Sealed for Read {}
impl Sealed for Write {}
+impl Sealed for Fsync {}
impl Sealed for Flush {}
+impl Sealed for Fsyncdir {}
impl<'o> Operation<'o> for Readlink {
type RequestBody = ();
@@ -38,11 +44,21 @@ impl<'o> Operation<'o> for Write {
type ReplyState = WriteState;
}
+impl<'o> Operation<'o> for Fsync {
+ type RequestBody = &'o proto::FsyncIn;
+ type ReplyState = ();
+}
+
impl<'o> Operation<'o> for Flush {
type RequestBody = &'o proto::FlushIn;
type ReplyState = ();
}
+impl<'o> Operation<'o> for Fsyncdir {
+ type RequestBody = &'o proto::FsyncdirIn;
+ type ReplyState = ();
+}
+
impl<'o> ReplyGather<'o> for Readlink {}
impl<'o> RequestHandle<'o> for Read {
@@ -93,6 +109,22 @@ impl<'o> ReplyAll<'o> for Write {
}
}
+impl<'o> RequestHandle<'o> for Fsync {
+ fn handle(request: &Request<'o, Self>) -> u64 {
+ request.body.fh
+ }
+}
+
+impl<'o> RequestFlags<'o> for Fsync {
+ type Flags = FsyncFlags;
+
+ fn flags(request: &Request<'o, Self>) -> Self::Flags {
+ FsyncFlags::from_bits_truncate(request.body.fsync_flags)
+ }
+}
+
+impl<'o> ReplyOk<'o> for Fsync {}
+
impl<'o> RequestHandle<'o> for Flush {
fn handle(request: &Request<'o, Self>) -> u64 {
request.body.fh
@@ -101,6 +133,22 @@ impl<'o> RequestHandle<'o> for Flush {
impl<'o> ReplyOk<'o> for Flush {}
+impl<'o> RequestHandle<'o> for Fsyncdir {
+ fn handle(request: &Request<'o, Self>) -> u64 {
+ request.body.fsync_in.fh
+ }
+}
+
+impl<'o> RequestFlags<'o> for Fsyncdir {
+ type Flags = FsyncFlags;
+
+ fn flags(request: &Request<'o, Self>) -> Self::Flags {
+ FsyncFlags::from_bits_truncate(request.body.fsync_in.fsync_flags)
+ }
+}
+
+impl<'o> ReplyOk<'o> for Fsyncdir {}
+
impl<'o> FromRequest<'o, Write> for WriteState {
fn from_request(request: &Request<'o, Write>) -> Self {
let (body, data) = request.body;
diff --git a/src/proto.rs b/src/proto.rs
index 2d53fe6..7e81201 100644
--- a/src/proto.rs
+++ b/src/proto.rs
@@ -332,6 +332,12 @@ pub struct FsyncIn {
pub padding: u32,
}
+bitflags! {
+ pub struct FsyncFlags: u32 {
+ const FDATASYNC = 1 << 0;
+ }
+}
+
#[derive(Pod, Zeroable, Copy, Clone)]
#[repr(C)]
pub struct SetxattrIn {
diff --git a/src/session.rs b/src/session.rs
index 696d97a..7c4172b 100644
--- a/src/session.rs
+++ b/src/session.rs
@@ -59,16 +59,17 @@ pub enum Dispatch<'o> {
Forget(Incoming<'o, ops::Forget>),
Getattr(Incoming<'o, ops::Getattr>),
Readlink(Incoming<'o, ops::Readlink>),
+ Symlink(Incoming<'o, ops::Symlink>),
Mkdir(Incoming<'o, ops::Mkdir>),
Unlink(Incoming<'o, ops::Unlink>),
Rmdir(Incoming<'o, ops::Rmdir>),
- Symlink(Incoming<'o, ops::Symlink>),
Link(Incoming<'o, ops::Link>),
Open(Incoming<'o, ops::Open>),
Read(Incoming<'o, ops::Read>),
Write(Incoming<'o, ops::Write>),
Statfs(Incoming<'o, ops::Statfs>),
Release(Incoming<'o, ops::Release>),
+ Fsync(Incoming<'o, ops::Fsync>),
Setxattr(Incoming<'o, ops::Setxattr>),
Getxattr(Incoming<'o, ops::Getxattr>),
Listxattr(Incoming<'o, ops::Listxattr>),
@@ -77,6 +78,7 @@ pub enum Dispatch<'o> {
Opendir(Incoming<'o, ops::Opendir>),
Readdir(Incoming<'o, ops::Readdir>),
Releasedir(Incoming<'o, ops::Releasedir>),
+ Fsyncdir(Incoming<'o, ops::Fsyncdir>),
Access(Incoming<'o, ops::Access>),
}
@@ -257,16 +259,17 @@ impl<'o> Dispatch<'o> {
Forget(incoming) => incoming.common,
Getattr(incoming) => incoming.common,
Readlink(incoming) => incoming.common,
+ Symlink(incoming) => incoming.common,
Mkdir(incoming) => incoming.common,
Unlink(incoming) => incoming.common,
Rmdir(incoming) => incoming.common,
- Symlink(incoming) => incoming.common,
Link(incoming) => incoming.common,
Open(incoming) => incoming.common,
Read(incoming) => incoming.common,
Write(incoming) => incoming.common,
Statfs(incoming) => incoming.common,
Release(incoming) => incoming.common,
+ Fsync(incoming) => incoming.common,
Setxattr(incoming) => incoming.common,
Getxattr(incoming) => incoming.common,
Listxattr(incoming) => incoming.common,
@@ -275,6 +278,7 @@ impl<'o> Dispatch<'o> {
Opendir(incoming) => incoming.common,
Readdir(incoming) => incoming.common,
Releasedir(incoming) => incoming.common,
+ Fsyncdir(incoming) => incoming.common,
Access(incoming) => incoming.common,
};
@@ -342,16 +346,17 @@ impl Endpoint<'_> {
Forget => dispatch!(Forget),
Getattr => dispatch!(Getattr),
Readlink => dispatch!(Readlink),
+ Symlink => dispatch!(Symlink),
Mkdir => dispatch!(Mkdir),
Unlink => dispatch!(Unlink),
Rmdir => dispatch!(Rmdir),
- Symlink => dispatch!(Symlink),
Link => dispatch!(Link),
Open => dispatch!(Open),
Read => dispatch!(Read),
Write => dispatch!(Write),
Statfs => dispatch!(Statfs),
Release => dispatch!(Release),
+ Fsync => dispatch!(Fsync),
Setxattr => dispatch!(Setxattr),
Getxattr => dispatch!(Getxattr),
Listxattr => dispatch!(Listxattr),
@@ -360,6 +365,7 @@ impl Endpoint<'_> {
Opendir => dispatch!(Opendir),
Readdir => dispatch!(Readdir),
Releasedir => dispatch!(Releasedir),
+ Fsyncdir => dispatch!(Fsyncdir),
Access => dispatch!(Access),
BatchForget => dispatch!(Forget),
ReaddirPlus => dispatch!(Readdir),