Skip to content
22 changes: 17 additions & 5 deletions os/StarryOS/kernel/src/syscall/fs/io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -317,18 +317,30 @@ pub fn sys_fdatasync(fd: c_int) -> AxResult<isize> {
Err(AxError::from(LinuxError::EINVAL))
}

pub fn sys_sync_file_range(fd: c_int, _offset: i64, _nbytes: i64, _flags: u32) -> AxResult<isize> {
debug!("sys_sync_file_range <= fd: {fd}");
pub fn sys_sync_file_range(fd: c_int, offset: i64, nbytes: i64, flags: u32) -> AxResult<isize> {
debug!("sys_sync_file_range <= fd: {fd}, flags: {flags:#x}");
const SYNC_FILE_RANGE_WAIT_BEFORE: u32 = 1;
const SYNC_FILE_RANGE_WRITE: u32 = 2;
const SYNC_FILE_RANGE_WAIT_AFTER: u32 = 4;
const SYNC_FILE_RANGE_ALL: u32 =
SYNC_FILE_RANGE_WAIT_BEFORE | SYNC_FILE_RANGE_WRITE | SYNC_FILE_RANGE_WAIT_AFTER;
if offset < 0 || nbytes < 0 {
return Err(AxError::from(LinuxError::EINVAL));
}
if (flags & !SYNC_FILE_RANGE_ALL) != 0 {
return Err(AxError::from(LinuxError::EINVAL));
}
// sync_file_range(2) is an advisory hint to initiate writeback for a
// byte range. Until range-based writeback is implemented, keep this as
// a no-op after basic fd validation rather than turning it into a
// stronger whole-file fdatasync-style flush (matches the advisory
// nature documented in the man page). Invalid fds still surface the
// underlying error (EBADF). Directory fds are accepted to match fsync.
match File::from_fd(fd) {
Ok(_) | Err(AxError::IsADirectory) => Ok(0),
Err(e) => Err(e),
let any = get_file_like(fd)?;
if any.downcast_ref::<File>().is_none() && any.downcast_ref::<Directory>().is_none() {
return Err(AxError::from(LinuxError::ESPIPE));
Comment thread
date727 marked this conversation as resolved.
}
Ok(0)
}

pub fn sys_fadvise64(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,19 @@
* 测试文件系统修复:
* 1. fsync 对目录 fd 应返回成功 (Linux 允许)
* 2. fdatasync 对目录 fd 应返回成功
* 3. sync_file_range 应返回成功 (建议性优化)
* 3. 非法 fd 应返回 EBADF
* 4. pipe fd 应返回 EINVAL
* 5. socket fd 应返回 EINVAL
* 6. sync_file_range 应返回成功 (建议性优化)
*/

#include "test_framework.h"
#include <fcntl.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/types.h>

int main(void)
{
Expand Down Expand Up @@ -40,7 +45,41 @@ int main(void)
unlink("/tmp/starry_fsync_test/file");
}

/* Test 3: sync_file_range */
/* Test 3: invalid fd handling */
{
CHECK_ERR(fsync(-1), EBADF, "fsync on invalid fd -> EBADF");
CHECK_ERR(fdatasync(-1), EBADF, "fdatasync on invalid fd -> EBADF");
}

/* Test 4: fsync on pipe -> EINVAL (Linux behavior) */
{
int pfd[2];
CHECK(pipe(pfd) == 0, "create pipe for fsync EINVAL");
if (pfd[0] >= 0) {
CHECK_ERR(fsync(pfd[0]), EINVAL, "fsync on pipe -> EINVAL");
CHECK_ERR(fdatasync(pfd[0]), EINVAL, "fdatasync on pipe -> EINVAL");
close(pfd[0]);
}
if (pfd[1] >= 0) {
close(pfd[1]);
}
}

/* Test 5: fsync on socket -> EINVAL (Linux behavior) */
{
int sfd[2];
CHECK(socketpair(AF_UNIX, SOCK_STREAM, 0, sfd) == 0, "create socketpair for fsync EINVAL");
if (sfd[0] >= 0) {
CHECK_ERR(fsync(sfd[0]), EINVAL, "fsync on socket -> EINVAL");
CHECK_ERR(fdatasync(sfd[0]), EINVAL, "fdatasync on socket -> EINVAL");
close(sfd[0]);
}
if (sfd[1] >= 0) {
close(sfd[1]);
}
}

/* Test 6: sync_file_range */
{
int fd = open("/tmp/starry_fsync_test/sfrfile", O_RDWR | O_CREAT | O_TRUNC, 0644);
CHECK(fd >= 0, "create file for sync_file_range");
Expand All @@ -50,6 +89,14 @@ int main(void)
* SYNC_FILE_RANGE_WRITE = 2 */
long rc = syscall(SYS_sync_file_range, fd, 0, 29, 2);
CHECK(rc == 0, "sync_file_range returns 0");
CHECK_RET(syscall(SYS_sync_file_range, fd, 0, 29, 0), 0,
"sync_file_range flags==0 -> success");
CHECK_ERR(syscall(SYS_sync_file_range, fd, 0, 29, 0x8000), EINVAL,
"sync_file_range invalid flags -> EINVAL");
CHECK_ERR(syscall(SYS_sync_file_range, fd, (off_t)-1, 29, 2), EINVAL,
"sync_file_range negative offset -> EINVAL");
CHECK_ERR(syscall(SYS_sync_file_range, fd, 0, (off_t)-1, 2), EINVAL,
"sync_file_range negative nbytes -> EINVAL");
close(fd);
unlink("/tmp/starry_fsync_test/sfrfile");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ static volatile int g_running = 1;
static volatile int g_shmid = -1;
static volatile int g_deadlock_detected = 0;
static volatile int g_shmat_started = 0;
static volatile int g_threads_done = 0;

/* Thread stack size */
#define STACK_SIZE (64 * 1024)
Expand Down Expand Up @@ -90,7 +91,7 @@ static int watchdog_thread(void *arg) {

for (int i = 0; i < SHM_ALARM_SEC * 10; i++) {
usleep(100000);
if (!g_running) {
if (g_threads_done) {
return 0;
}
}
Expand Down Expand Up @@ -160,6 +161,7 @@ int main(void)
waitpid(tid1, &status, __WALL);
waitpid(tid2, &status, __WALL);
waitpid(tid3, &status, __WALL);
g_threads_done = 1;
Comment thread
date727 marked this conversation as resolved.

CHECK(!g_deadlock_detected, "no deadlock detected");
} else {
Expand Down