-1

fsyncドキュメントの状態

fsync() を呼び出しても、ファイルを含むディレクトリ内のエントリがディスクに到達したことは必ずしも保証されません。そのためには、ディレクトリのファイル記述子に対する明示的な fsync() も必要です。

Linuxで行うのと同様に、WindowsでSMBを使用してディレクトリをネットワークマップドライブに同期しようとしてfsyncいます。

次の 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)
}

プログラムは失敗します

Z:\\smb-test Incorrect function.

MSDN は、渡されるハンドルはファイルまたはボリュームのいずれかのハンドルである必要があると述べていますが、ディレクトリについては何も述べていません。 https://docs.microsoft.com/en-us/windows/desktop/api/FileAPI/nf-fileapi-flushfilebuffers

また、FlushFileBuffers は、ディレクトリ ハンドルを受け入れる関数としてリストされていません https://docs.microsoft.com/en-us/windows/desktop/fileio/obtaining-a-handle-to-a-directory

Invalid Device Requestまた、ネットワークにマップされたドライブで flushfilebuffers システム コールが失敗することにも気付きました

無題

問題は、Windows でディレクトリを同期するにはどうすればよいかということです。それとも、ウィンドウのバッファリングされた I/O は POSIX とは根本的に異なり、ディレクトリ内のファイルが変更されたときにディレクトリをフラッシュする必要はありませんか?

4

1 に答える 1