default.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. #define _FASTWRITER_DEFAULT_C
  2. #define _GNU_SOURCE
  3. #define _XOPEN_SOURCE 600
  4. #define _POSIX_C_SOURCE 200112L
  5. #define _LARGEFILE64_SOURCE
  6. #include "config.h"
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #include <unistd.h>
  11. #include <limits.h>
  12. #include <errno.h>
  13. #include <pthread.h>
  14. #include <sys/types.h>
  15. #include <sys/stat.h>
  16. #include <sys/time.h>
  17. #include <fcntl.h>
  18. #ifdef HAVE_LINUX_FALLOC_H
  19. # include <linux/falloc.h>
  20. #endif /* HAVE_LINUX_FALLOC_H */
  21. #include "fastwriter.h"
  22. #include "private.h"
  23. #include "sysinfo.h"
  24. #define SYNC_MODE
  25. #define HAVE_FALLOCATE
  26. #define EXT4_WRITEBLOCK 4194304
  27. #define EXT4_PREALLOCATE 1073741824
  28. typedef struct {
  29. int fd;
  30. size_t prior_size; /**< original size of file */
  31. size_t preallocated; /**< preallocated bytes */
  32. size_t wr_block; /**< minimal block of data to write */
  33. size_t pa_block; /**< preallocation setp */
  34. } fastwriter_default_t;
  35. int fastwriter_open_default(fastwriter_t *fw, const char *name, fastwriter_flags_t flags) {
  36. int err;
  37. char fs[16];
  38. int open_flags = (O_CREAT|O_WRONLY|O_NOATIME|O_LARGEFILE);
  39. int open_mode = (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
  40. #ifdef SYNC_MODE
  41. open_flags |= O_DIRECT;//|O_SYNC;
  42. #endif /* SYNC_MODE */
  43. fastwriter_default_t *ctx;
  44. err = get_file_fs(name, sizeof(fs) - 1, fs);
  45. if (err) return err;
  46. ctx = (fastwriter_default_t*)malloc(sizeof(fastwriter_default_t));
  47. if (!ctx) return ENOMEM;
  48. memset(ctx, 0, sizeof(fastwriter_default_t));
  49. fw->ctx = ctx;
  50. if (!strcmp(fs, "raw")) {
  51. ctx->wr_block = EXT4_WRITEBLOCK;
  52. ctx->pa_block = 0;
  53. } else if (!strcmp(fs, "ext4")) {
  54. ctx->wr_block = EXT4_WRITEBLOCK;
  55. ctx->pa_block = EXT4_PREALLOCATE;
  56. } else if (!strcmp(fs, "btrfs")) {
  57. ctx->wr_block = EXT4_WRITEBLOCK;
  58. ctx->pa_block = EXT4_PREALLOCATE;
  59. } else if (!strcmp(fs, "xfs")) {
  60. ctx->wr_block = EXT4_WRITEBLOCK;
  61. ctx->pa_block = EXT4_PREALLOCATE;
  62. } else {
  63. ctx->wr_block = EXT4_WRITEBLOCK;
  64. ctx->pa_block = 0;
  65. }
  66. if (flags&FASTWRITER_FLAGS_OVERWRITE)
  67. open_flags |= O_TRUNC;
  68. ctx->fd = open(name, open_flags, open_mode);
  69. if (ctx->fd < 0) return errno;
  70. ctx->prior_size = 0;
  71. #ifndef HAVE_LINUX_FALLOC_H
  72. if (((open_flags&FASTWRITER_FLAGS_OVERWRITE)==0)&&(strcmp(fs, "raw"))) {
  73. ctx->prior_size = lseek(ctx->fd, 0, SEEK_END);
  74. }
  75. #endif /* HAVE_LINUX_FALLOC_H */
  76. ctx->preallocated = 0;
  77. return 0;
  78. }
  79. void fastwriter_close_default(fastwriter_t *fw) {
  80. if (fw->ctx) {
  81. fastwriter_default_t *ctx = (fastwriter_default_t*)fw->ctx;
  82. if (ctx->fd >= 0) {
  83. #ifndef HAVE_LINUX_FALLOC_H
  84. if (ctx->prior_size) {
  85. ftrucate(ctx->fd, ctx->prior_size + fw->written);
  86. }
  87. #endif /* HAVE_LINUX_FALLOC_H */
  88. close(ctx->fd);
  89. }
  90. free(ctx);
  91. fw->ctx = NULL;
  92. }
  93. }
  94. int fastwriter_write_default(fastwriter_t *fw, fastwriter_write_flags_t flags, size_t size, void *data, size_t *written) {
  95. size_t sum = 0;
  96. ssize_t res;
  97. fastwriter_default_t *ctx = (fastwriter_default_t*)fw->ctx;
  98. if ((flags&FASTWRITER_WRITE_FLAG_FORCE)==0) {
  99. if (size < ctx->wr_block) {
  100. *written = 0;
  101. return 0;
  102. }
  103. size -= size % ctx->wr_block;
  104. }
  105. if ((ctx->pa_block)&&((fw->written + size) > ctx->preallocated)) {
  106. #ifdef HAVE_LINUX_FALLOC_H
  107. if (fallocate(ctx->fd, FALLOC_FL_KEEP_SIZE, ctx->preallocated, ctx->pa_block)) {
  108. #else /* HAVE_LINUX_FALLOC_H */
  109. if (posix_fallocate(ctx->fd, ctx->preallocated, ctx->pa_block)) {
  110. #endif /* HAVE_LINUX_FALLOC_H */
  111. ctx->pa_block = 0;
  112. } else {
  113. ctx->preallocated += ctx->pa_block;
  114. }
  115. }
  116. do {
  117. res = write(ctx->fd, data, size);
  118. if (res < 0) {
  119. *written = sum;
  120. return errno;
  121. }
  122. sum += res;
  123. } while (sum < size);
  124. #ifdef SYNC_MODE
  125. posix_fadvise(ctx->fd, fw->written, size, POSIX_FADV_DONTNEED);
  126. #endif /* SYNC_MODE */
  127. *written = size;
  128. return 0;
  129. }