Skip to content

Commit 984dd82

Browse files
zyfjeffimeoer
authored andcommitted
Fix: unable to perform sync on directory
when no_open=false, no_opendir=true, we can't execute the sync command on the directory, because fsyncdir uses get_data to get the handle of the directory, but no_open=false, so it will go to the handle map to find it, but in fact this is a directory, and the no_opendir is true, so it is not in the handle map, It needs to be reopened. we should use get_dirdata replace get_data Signed-off-by: tianqian.zyf <tianqian.zyf@alibaba-inc.com>
1 parent ebdadfa commit 984dd82

File tree

2 files changed

+31
-17
lines changed

2 files changed

+31
-17
lines changed

src/passthrough/sync_io.rs

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use std::sync::Arc;
1515
use std::time::Duration;
1616

1717
use super::os_compat::LinuxDirent64;
18-
use super::util::stat_fd;
18+
use super::util::{stat_fd, sync_fd};
1919
use super::*;
2020
use crate::abi::fuse_abi::{CreateIn, Opcode, FOPEN_IN_KILL_SUIDGID, WRITE_KILL_PRIV};
2121
#[cfg(any(feature = "vhost-user-fs", feature = "virtiofs"))]
@@ -1074,30 +1074,19 @@ impl<S: BitmapSlice + Send + Sync> FileSystem for PassthroughFs<S> {
10741074
) -> io::Result<()> {
10751075
let data = self.get_data(handle, inode, libc::O_RDONLY)?;
10761076
let fd = data.borrow_fd();
1077-
1078-
// Safe because this doesn't modify any memory and we check the return value.
1079-
let res = unsafe {
1080-
if datasync {
1081-
libc::fdatasync(fd.as_raw_fd())
1082-
} else {
1083-
libc::fsync(fd.as_raw_fd())
1084-
}
1085-
};
1086-
if res == 0 {
1087-
Ok(())
1088-
} else {
1089-
Err(io::Error::last_os_error())
1090-
}
1077+
sync_fd(&fd, datasync)
10911078
}
10921079

10931080
fn fsyncdir(
10941081
&self,
1095-
ctx: &Context,
1082+
_ctx: &Context,
10961083
inode: Inode,
10971084
datasync: bool,
10981085
handle: Handle,
10991086
) -> io::Result<()> {
1100-
self.fsync(ctx, inode, datasync, handle)
1087+
let data = self.get_dirdata(handle, inode, libc::O_RDONLY)?;
1088+
let fd = data.borrow_fd();
1089+
sync_fd(&fd, datasync)
11011090
}
11021091

11031092
fn access(&self, ctx: &Context, inode: Inode, mask: u32) -> io::Result<()> {
@@ -1630,4 +1619,13 @@ mod tests {
16301619
let statfs = fs.statfs(&ctx, ROOT_ID).unwrap();
16311620
assert_eq!(statfs.f_namemax, 255);
16321621
}
1622+
1623+
#[test]
1624+
fn test_fsync_dir() {
1625+
let (fs, _source) = prepare_fs_tmpdir();
1626+
let ctx = prepare_context();
1627+
fs.no_opendir.store(true, Ordering::Relaxed);
1628+
1629+
assert!(fs.fsyncdir(&ctx, ROOT_ID, false, 0).is_ok());
1630+
}
16331631
}

src/passthrough/util.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,22 @@ pub fn eperm() -> io::Error {
225225
io::Error::from_raw_os_error(libc::EPERM)
226226
}
227227

228+
pub fn sync_fd(fd: &impl AsRawFd, datasync: bool) -> io::Result<()> {
229+
// Safe because this doesn't modify any memory and we check the return value.
230+
let res = unsafe {
231+
if datasync {
232+
libc::fdatasync(fd.as_raw_fd())
233+
} else {
234+
libc::fsync(fd.as_raw_fd())
235+
}
236+
};
237+
if res == 0 {
238+
Ok(())
239+
} else {
240+
Err(io::Error::last_os_error())
241+
}
242+
}
243+
228244
#[cfg(test)]
229245
mod tests {
230246
use super::*;

0 commit comments

Comments
 (0)