From 3078f10d43d834b0498358fe0accb565191b7020 Mon Sep 17 00:00:00 2001 From: Paul Gofman Date: Tue, 9 Jun 2020 20:00:07 +0300 Subject: [PATCH] ntdll: Perform fsync() in client for files and directories. Fixes stuttering in Assetto Corsa Competizione (multiplayer mode). Signed-off-by: Paul Gofman Signed-off-by: Alexandre Julliard --- dlls/ntdll/file.c | 10 +++++++++- dlls/ntdll/tests/file.c | 21 +++++++++++++++++++++ server/file.c | 14 +------------- 3 files changed, 31 insertions(+), 14 deletions(-) diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c index 1b70e473676..aba7b608f69 100644 --- a/dlls/ntdll/file.c +++ b/dlls/ntdll/file.c @@ -3584,7 +3584,15 @@ NTSTATUS WINAPI NtFlushBuffersFile( HANDLE hFile, IO_STATUS_BLOCK *io ) if (ret == STATUS_ACCESS_DENIED) ret = unix_funcs->server_get_unix_fd( hFile, FILE_APPEND_DATA, &fd, &needs_close, &type, NULL ); - if (!ret && type == FD_TYPE_SERIAL) + if (!ret && (type == FD_TYPE_FILE || type == FD_TYPE_DIR)) + { + if (fsync(fd)) + ret = FILE_GetNtStatus(); + + io->u.Status = ret; + io->Information = 0; + } + else if (!ret && type == FD_TYPE_SERIAL) { ret = COMM_FlushBuffersFile( fd ); } diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c index 1d0682a6334..184b7cdad59 100644 --- a/dlls/ntdll/tests/file.c +++ b/dlls/ntdll/tests/file.c @@ -4860,14 +4860,26 @@ static void test_flush_buffers_file(void) status = pNtFlushBuffersFile(hfile, (IO_STATUS_BLOCK *)0xdeadbeaf); ok(status == STATUS_ACCESS_VIOLATION, "expected STATUS_ACCESS_VIOLATION, got %#x.\n", status); + io_status_block.Information = 0xdeadbeef; + io_status_block.Status = 0xdeadbeef; status = pNtFlushBuffersFile(hfile, &io_status_block); ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x.\n", status); + ok(io_status_block.Status == STATUS_SUCCESS, "Got unexpected io_status_block.Status %#x.\n", + io_status_block.Status); + ok(!io_status_block.Information, "Got unexpected io_status_block.Information %#lx.\n", + io_status_block.Information); status = pNtFlushBuffersFile(hfileread, &io_status_block); ok(status == STATUS_ACCESS_DENIED, "expected STATUS_ACCESS_DENIED, got %#x.\n", status); + io_status_block.Information = 0xdeadbeef; + io_status_block.Status = 0xdeadbeef; status = pNtFlushBuffersFile(NULL, &io_status_block); ok(status == STATUS_INVALID_HANDLE, "expected STATUS_INVALID_HANDLE, got %#x.\n", status); + ok(io_status_block.Status == 0xdeadbeef, "Got unexpected io_status_block.Status %#x.\n", + io_status_block.Status); + ok(io_status_block.Information == 0xdeadbeef, "Got unexpected io_status_block.Information %#lx.\n", + io_status_block.Information); CloseHandle(hfileread); CloseHandle(hfile); @@ -4878,6 +4890,15 @@ static void test_flush_buffers_file(void) status = pNtFlushBuffersFile(hfile, &io_status_block); ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x.\n", status); + io_status_block.Information = 0xdeadbeef; + io_status_block.Status = 0xdeadbeef; + status = pNtFlushBuffersFile((HANDLE)0xdeadbeef, &io_status_block); + ok(status == STATUS_INVALID_HANDLE, "expected STATUS_INVALID_HANDLE, got %#x.\n", status); + ok(io_status_block.Status == 0xdeadbeef, "Got unexpected io_status_block.Status %#x.\n", + io_status_block.Status); + ok(io_status_block.Information == 0xdeadbeef, "Got unexpected io_status_block.Information %#lx.\n", + io_status_block.Information); + CloseHandle(hfile); DeleteFileA(buffer); } diff --git a/server/file.c b/server/file.c index bce202138e0..38260cfd2b3 100644 --- a/server/file.c +++ b/server/file.c @@ -75,7 +75,6 @@ static struct list *file_get_kernel_obj_list( struct object *obj ); static void file_destroy( struct object *obj ); static int file_get_poll_events( struct fd *fd ); -static int file_flush( struct fd *fd, struct async *async ); static enum server_fd_type file_get_fd_type( struct fd *fd ); static const struct object_ops file_ops = @@ -108,7 +107,7 @@ static const struct fd_ops file_fd_ops = file_get_fd_type, /* get_fd_type */ no_fd_read, /* read */ no_fd_write, /* write */ - file_flush, /* flush */ + no_fd_flush, /* flush */ default_fd_get_file_info, /* get_file_info */ no_fd_get_volume_info, /* get_volume_info */ default_fd_ioctl, /* ioctl */ @@ -296,17 +295,6 @@ static int file_get_poll_events( struct fd *fd ) return events; } -static int file_flush( struct fd *fd, struct async *async ) -{ - int unix_fd = get_unix_fd( fd ); - if (unix_fd != -1 && fsync( unix_fd ) == -1) - { - file_set_error(); - return 0; - } - return 1; -} - static enum server_fd_type file_get_fd_type( struct fd *fd ) { struct file *file = get_fd_user( fd );