简体   繁体   English

Windows:FlushFileBuffers 系统调用在网络映射驱动器上失败

[英]Windows: FlushFileBuffers system call fails on network mapped drive

fsync doc states fsync文档状态

Calling fsync() does not necessarily ensure that the entry in the directory containing the file has also reached disk.调用 fsync() 不一定确保包含文件的目录中的条目也已到达磁盘。 For that an explicit fsync() on a file descriptor for the directory is also needed.为此,还需要在目录的文件描述符上显式 fsync()。

I'm trying to sync a directory to the network mapped drive using SMB on windows, similar to what fsync does on Linux.我正在尝试在 Windows 上使用 SMB 将目录同步到网络映射驱动器,类似于fsync在 Linux 上所做的。

The following go code snippet which works fine if the directory is stored on a local drive but fails if it is on a network mapped folder.如果目录存储在本地驱动器上,以下 go 代码片段可以正常工作,但如果它位于网络映射文件夹上,则失败。

func main() {
    dir := "Z:\\smb-test" // Path to network mapped drive
    f, err := openDir(dir)
    if err != nil {
        log.Fatal(err)
    }
    // Works fine if the path is located on a local disk but
    // fails if the directory is on a network mapped drive
    if err := f.Sync(); err != nil {
        log.Fatal(err)
    }
    if err := f.Close(); err != nil {
        log.Fatal(err)
    }
}

func openDir(path string) (*os.File, error) {
    fd, err := openDirWin(path)
    if err != nil {
        return nil, err
    }
    return os.NewFile(uintptr(fd), path), nil
}

func openDirWin(path string) (fd syscall.Handle, err error) {
    pathp, err := syscall.UTF16PtrFromString(path)
    if err != nil {
        return syscall.InvalidHandle, err
    }
    access := uint32(syscall.GENERIC_READ | syscall.GENERIC_WRITE)
    sharemode := uint32(syscall.FILE_SHARE_READ | syscall.FILE_SHARE_WRITE)
    createmode := uint32(syscall.OPEN_EXISTING)
    fl := uint32(syscall.FILE_FLAG_BACKUP_SEMANTICS)
    return syscall.CreateFile(pathp, access, sharemode, nil, createmode, fl, 0)
}

The program fails with程序失败

Z:\\smb-test Incorrect function.

MSDN states that the handle passed in should either be a handle to a file, or to a volume, but says nothing about directories. MSDN 声明传入的句柄应该是文件或卷的句柄,但没有说明目录。 https://docs.microsoft.com/en-us/windows/desktop/api/FileAPI/nf-fileapi-flushfilebuffers https://docs.microsoft.com/en-us/windows/desktop/api/FileAPI/nf-fileapi-flushfilebuffers

And FlushFileBuffers is not listed as a function that accepts directory handles https://docs.microsoft.com/en-us/windows/desktop/fileio/obtaining-a-handle-to-a-directory并且 FlushFileBuffers 没有被列为接受目录句柄的函数https://docs.microsoft.com/en-us/windows/desktop/fileio/obtaining-a-handle-to-a-directory

I also noticed the flushfilebuffers system call fails with Invalid Device Request for a network mapped drive我还注意到flushfilebuffers 系统调用因网络映射驱动器的Invalid Device Request而失败

无标题

So the question is how do I sync a directory on windows?所以问题是如何在 Windows 上同步目录? Or is window's buffered I/O fundamentally different from POSIX and we don't need to flush a directory when a file inside it is modified?还是窗口的缓冲 I/O 与 POSIX 根本不同,我们不需要在修改目录中的文件时刷新目录?

The short answer to my question is there's no way to sync directories on windows using system calls.我的问题的简短回答是无法使用系统调用在 Windows 上同步目录。 FlushFileBuffers works for files and volumes, NOT Directories . FlushFileBuffers适用于文件和卷, FlushFileBuffers适用于Directories

Read https://social.msdn.microsoft.com/Forums/Windowsdesktop/en-US/847a735b-f21a-4be2-880b-12660e5b98b4/flushfilebuffers-system-call-fails-on-network-mapped-drive and https://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/0e0b734b-2b73-414d-8833-8d2eed7043f6/sync-directories-on-windows for more details.阅读https://social.msdn.microsoft.com/Forums/Windowsdesktop/en-US/847a735b-f21a-4be2-880b-12660e5b98b4/flushfilebuffers-system-call-fails-on-network-mapped-drivehttps:// /social.msdn.microsoft.com/Forums/windowsdesktop/en-US/0e0b734b-2b73-414d-8833-8d2eed7043f6/sync-directories-on-windows了解更多详情。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM