小组成员:谢瑞阳、徐翔宇
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

38 lines
1.3 KiB

leveldb: Fix PosixWritableFile::Sync() on Apple systems. Apple doesn't follow POSIX specifications for fsync(). Instead, fsync() guarantees to flush the buffer cache to the device, which means the data will survive kernel panics, but may not survive power outages. Applications that need stronger guarantees (like databases) need to use fcntl(F_FULLFSYNC). This CL switches PosixWritableFile::Sync() to get the stronger guarantees on Apple systems. The improved implementation follows the same principles as SQLite [1] and node.js [2]. Research for the fcntl() to fsync() fallback strategy: Apple's released source code at https://opensource.apple.com/ shows at least three different error codes being returned when a filesystem does not support F_FULLFSYNC. fcntl() is implemented in xnu-4903.221.2 in bsd/kern/kern_descrip.c, where it delegates to fcntl_nocancel(). The documentation for fcntl_nocancel() mentions error codes for some operations, but does not include F_FULLFSYNC. The F_FULLSYNC branch in fcntl_nocancel() calls VNOP_IOCTL(_, F_FULLSYNC, NULL, 0, _), whose return value sets the error code. VNOP_IOCTL() is implemented in bsd/vfs/kpi_vfs.c and calls the ioctl function in the vnode's operation vector. The per-filesystem function names follow the pattern _vnop_ioctl() for all the instances in opensource code: {hfs,msdosfs,nfs,ntfs,smbfs,webdav,zfs}_vnop_ioctl(). hfs-407.30.1, msdosfs-229.200.3, and nfs in xnu-4903.221.2 handle F_FULLFSYNC. ntfs-94.200.1 and smb-759.40.1 do not handle F_FULLFSYNC, and the default branch returns ENOSUP. webdav-380.200.1 also does not handle F_FULLFSYNC, but the default branch returns EINVAL. zfs-59 also does not handle F_FULLSYNC, and its default branch returns ENOTTY. From a different angle, Apple's ntfs-94.200.1 includes utility code that uses fcntl(F_FULLFSYNC) and falls back to fsync() just like we do, supporting the hypothesis that there is no good way to detect lack of F_FULLFSYNC support. Also, Apple's fcntl() man page [3] does not mention a way to detect lack of F_FULLFSYNC support. [1] https://www.sqlite.org/src/doc/trunk/src/os_unix.c [2] https://github.com/libuv/libuv/blob/master/src/unix/fs.c [3] https://developer.apple.com/library/archive/documentatiVon/System/Conceptual/ManPages_iPhoneOS/man2/fcntl.2.html Tested: https://travis-ci.org/pwnall/leveldb/builds/477318498 TAP global presubmit ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=228593729
6 years ago
  1. // Copyright 2017 The LevelDB Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file. See the AUTHORS file for names of contributors.
  4. #ifndef STORAGE_LEVELDB_PORT_PORT_CONFIG_H_
  5. #define STORAGE_LEVELDB_PORT_PORT_CONFIG_H_
  6. // Define to 1 if you have a definition for fdatasync() in <unistd.h>.
  7. #if !defined(HAVE_FDATASYNC)
  8. #cmakedefine01 HAVE_FDATASYNC
  9. #endif // !defined(HAVE_FDATASYNC)
  10. // Define to 1 if you have a definition for F_FULLFSYNC in <fcntl.h>.
  11. #if !defined(HAVE_FULLFSYNC)
  12. #cmakedefine01 HAVE_FULLFSYNC
  13. #endif // !defined(HAVE_FULLFSYNC)
  14. // Define to 1 if you have a definition for O_CLOEXEC in <fcntl.h>.
  15. #if !defined(HAVE_O_CLOEXEC)
  16. #cmakedefine01 HAVE_O_CLOEXEC
  17. #endif // !defined(HAVE_O_CLOEXEC)
  18. // Define to 1 if you have Google CRC32C.
  19. #if !defined(HAVE_CRC32C)
  20. #cmakedefine01 HAVE_CRC32C
  21. #endif // !defined(HAVE_CRC32C)
  22. // Define to 1 if you have Google Snappy.
  23. #if !defined(HAVE_SNAPPY)
  24. #cmakedefine01 HAVE_SNAPPY
  25. #endif // !defined(HAVE_SNAPPY)
  26. // Define to 1 if your processor stores words with the most significant byte
  27. // first (like Motorola and SPARC, unlike Intel and VAX).
  28. #if !defined(LEVELDB_IS_BIG_ENDIAN)
  29. #cmakedefine01 LEVELDB_IS_BIG_ENDIAN
  30. #endif // !defined(LEVELDB_IS_BIG_ENDIAN)
  31. #endif // STORAGE_LEVELDB_PORT_PORT_CONFIG_H_