Windows: сбой системного вызова FlushFileBuffers на подключенном сетевом диске - PullRequest
0 голосов
/ 19 июня 2019

fsync Состояния документа

Вызов fsync () не обязательно гарантирует, что запись в каталоге, содержащем файл, также достигла диска. Для этого явный fsync () в дескрипторе файла для каталога также необходимо.

Я пытаюсь синхронизировать каталог с подключенным сетевым диском с помощью SMB в Windows, аналогично тому, что fsync делает в Linux.

Следующий фрагмент кода 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

Я также заметил, что системный вызов flushfilebuffers завершается неудачно с Invalid Device Request для сетевого подключенного диска

Untitled

Итак, вопрос в том, как синхронизировать каталог в Windows? Или буферизованный ввод / вывод окна принципиально отличается от POSIX, и нам не нужно очищать каталог, когда файл внутри него модифицируется?

1 Ответ

0 голосов
/ 20 июня 2019

Короткий ответ на мой вопрос: нет возможности синхронизировать каталоги в Windows с помощью системных вызовов. FlushFileBuffers работает для файлов и томов, НЕ для каталогов .

Чтение https://social.msdn.microsoft.com/Forums/Windowsdesktop/en-US/847a735b-f21a-4be2-880b-12660e5b98b4/flushfilebuffers-system-call-fails-on-network-mapped-drive и https://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/0e0b734b-2b73-414d-8833-8d2eed7043f6/sync-directories-on-windows для более подробной информации.

...