F2FS.txt 3.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. SQLite's OS layer contains the following definitions used in F2FS related
  2. calls:
  3. #define F2FS_IOCTL_MAGIC 0xf5
  4. #define F2FS_IOC_START_ATOMIC_WRITE _IO(F2FS_IOCTL_MAGIC, 1)
  5. #define F2FS_IOC_COMMIT_ATOMIC_WRITE _IO(F2FS_IOCTL_MAGIC, 2)
  6. #define F2FS_IOC_START_VOLATILE_WRITE _IO(F2FS_IOCTL_MAGIC, 3)
  7. #define F2FS_IOC_ABORT_VOLATILE_WRITE _IO(F2FS_IOCTL_MAGIC, 5)
  8. #define F2FS_IOC_GET_FEATURES _IOR(F2FS_IOCTL_MAGIC, 12, u32)
  9. #define F2FS_FEATURE_ATOMIC_WRITE 0x0004
  10. After opening a database file on Linux (including Android), SQLite determines
  11. whether or not a file supports F2FS atomic commits as follows:
  12. u32 flags = 0;
  13. rc = ioctl(fd, F2FS_IOC_GET_FEATURES, &flags);
  14. if( rc==0 && (flags & F2FS_FEATURE_ATOMIC_WRITE) ){
  15. /* File supports F2FS atomic commits */
  16. }else{
  17. /* File does NOT support F2FS atomic commits */
  18. }
  19. where "fd" is the file-descriptor open on the database file.
  20. Usually, when writing to a database file that supports atomic commits, SQLite
  21. accumulates the entire transaction in heap memory, deferring all writes to the
  22. db file until the transaction is committed.
  23. When it is time to commit a transaction on a file that supports atomic
  24. commits, SQLite does:
  25. /* Take an F_WRLCK lock on the database file. This prevents any other
  26. ** SQLite clients from reading or writing the file until the lock
  27. ** is released. */
  28. rc = fcntl(fd, F_SETLK, ...);
  29. if( rc!=0 ) goto failed;
  30. rc = ioctl(fd, F2FS_IOC_START_ATOMIC_WRITE);
  31. if( rc!=0 ) goto fallback_to_legacy_journal_commit;
  32. foreach (dirty page){
  33. rc = write(fd, ...dirty page...);
  34. if( rc!=0 ){
  35. ioctl(fd, F2FS_IOC_ABORT_VOLATILE_WRITE);
  36. goto fallback_to_legacy_journal_commit;
  37. }
  38. }
  39. rc = ioctl(fd, F2FS_IOC_COMMIT_ATOMIC_WRITE);
  40. if( rc!=0 ){
  41. ioctl(fd, F2FS_IOC_ABORT_VOLATILE_WRITE);
  42. goto fallback_to_legacy_journal_commit;
  43. }
  44. /* If we get there, the transaction has been successfully
  45. ** committed to persistent storage. The following call
  46. ** relinquishes the F_WRLCK lock. */
  47. fcntl(fd, F_SETLK, ...);
  48. Assumptions:
  49. 1. After either of the F2FS_IOC_ABORT_VOLATILE_WRITE calls return,
  50. the database file is in the state that it was in before
  51. F2FS_IOC_START_ATOMIC_WRITE was invoked. Even if the ioctl()
  52. fails - we're ignoring the return code.
  53. This is true regardless of the type of error that occurred in
  54. ioctl() or write().
  55. 2. If the system fails before the F2FS_IOC_COMMIT_ATOMIC_WRITE is
  56. completed, then following a reboot the database file is in the
  57. state that it was in before F2FS_IOC_START_ATOMIC_WRITE was invoked.
  58. Or, if the write was commited right before the system failed, in a
  59. state indicating that all write() calls were successfully committed
  60. to persistent storage before the failure occurred.
  61. 3. If the process crashes before the F2FS_IOC_COMMIT_ATOMIC_WRITE is
  62. completed then the file is automatically restored to the state that
  63. it was in before F2FS_IOC_START_ATOMIC_WRITE was called. This occurs
  64. before the posix advisory lock is automatically dropped - there is
  65. no chance that another client will be able to read the file in a
  66. half-committed state before the rollback operation occurs.