123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173 |
- #define _FASTWRITER_DEFAULT_C
- #define _GNU_SOURCE
- #define _XOPEN_SOURCE 600
- #define _POSIX_C_SOURCE 200112L
- #define _LARGEFILE64_SOURCE
- #include "config.h"
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
- #include <limits.h>
- #include <errno.h>
- #include <pthread.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <sys/time.h>
- #include <fcntl.h>
- #ifdef HAVE_LINUX_FALLOC_H
- # include <linux/falloc.h>
- #endif /* HAVE_LINUX_FALLOC_H */
- #include "fastwriter.h"
- #include "private.h"
- #include "sysinfo.h"
- #include "default.h"
- #define SYNC_MODE
- #define HAVE_FALLOCATE
- #define EXT4_WRITEBLOCK 4194304
- #define EXT4_PREALLOCATE 1073741824
- typedef struct {
- int fd;
-
- size_t prior_size; /**< original size of file */
- size_t preallocated; /**< preallocated bytes */
-
- size_t wr_block; /**< minimal block of data to write */
- size_t pa_block; /**< preallocation setp */
- } fastwriter_default_t;
- int fastwriter_default_open(fastwriter_t *fw, const char *name, fastwriter_flags_t flags) {
- int err;
- char fs[16];
- int open_flags = (O_CREAT|O_WRONLY|O_NOATIME|O_LARGEFILE);
- int open_mode = (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
- #ifdef SYNC_MODE
- open_flags |= O_DIRECT;//|O_SYNC;
- #endif /* SYNC_MODE */
-
- fastwriter_default_t *ctx;
- err = get_file_fs(name, sizeof(fs) - 1, fs);
- if (err) return err;
-
- ctx = (fastwriter_default_t*)malloc(sizeof(fastwriter_default_t));
- if (!ctx) return ENOMEM;
- memset(ctx, 0, sizeof(fastwriter_default_t));
- fw->ctx = ctx;
- if (!strcmp(fs, "raw")) {
- ctx->wr_block = EXT4_WRITEBLOCK;
- ctx->pa_block = 0;
- } else if (!strcmp(fs, "ext4")) {
- ctx->wr_block = EXT4_WRITEBLOCK;
- ctx->pa_block = EXT4_PREALLOCATE;
- } else if (!strcmp(fs, "btrfs")) {
- ctx->wr_block = EXT4_WRITEBLOCK;
- ctx->pa_block = EXT4_PREALLOCATE;
- } else if (!strcmp(fs, "xfs")) {
- ctx->wr_block = EXT4_WRITEBLOCK;
- ctx->pa_block = EXT4_PREALLOCATE;
- } else {
- ctx->wr_block = EXT4_WRITEBLOCK;
- ctx->pa_block = 0;
- }
-
- if (flags&FASTWRITER_FLAGS_OVERWRITE)
- open_flags |= O_TRUNC;
- ctx->fd = open(name, open_flags, open_mode);
- if (ctx->fd < 0) return errno;
- ctx->prior_size = 0;
-
- #ifndef HAVE_LINUX_FALLOC_H
- if (((open_flags&FASTWRITER_FLAGS_OVERWRITE)==0)&&(strcmp(fs, "raw"))) {
- ctx->prior_size = lseek(ctx->fd, 0, SEEK_END);
- }
- #endif /* HAVE_LINUX_FALLOC_H */
- ctx->preallocated = 0;
- return 0;
- }
- void fastwriter_default_close(fastwriter_t *fw) {
- if (fw->ctx) {
- fastwriter_default_t *ctx = (fastwriter_default_t*)fw->ctx;
- if (ctx->fd >= 0) {
- #ifndef HAVE_LINUX_FALLOC_H
- if (ctx->prior_size) {
- ftrucate(ctx->fd, ctx->prior_size + fw->written);
- }
- #endif /* HAVE_LINUX_FALLOC_H */
- close(ctx->fd);
- }
-
- free(ctx);
- fw->ctx = NULL;
- }
- }
- int fastwriter_default_write(fastwriter_t *fw, fastwriter_write_flags_t flags, size_t size, void *data, size_t *written) {
- size_t sum = 0;
- ssize_t res;
- fastwriter_default_t *ctx = (fastwriter_default_t*)fw->ctx;
-
- if ((flags&FASTWRITER_WRITE_FLAG_FORCE)==0) {
- if (size < ctx->wr_block) {
- *written = 0;
- return 0;
- }
-
- size -= size % ctx->wr_block;
- }
- if ((ctx->pa_block)&&((fw->written + size) > ctx->preallocated)) {
- #ifdef HAVE_LINUX_FALLOC_H
- if (fallocate(ctx->fd, FALLOC_FL_KEEP_SIZE, ctx->preallocated, ctx->pa_block)) {
- #else /* HAVE_LINUX_FALLOC_H */
- if (posix_fallocate(ctx->fd, ctx->preallocated, ctx->pa_block)) {
- #endif /* HAVE_LINUX_FALLOC_H */
- ctx->pa_block = 0;
- } else {
- ctx->preallocated += ctx->pa_block;
- }
- }
-
- do {
- res = write(ctx->fd, data, size);
- if (res < 0) {
- *written = sum;
- return errno;
- }
-
- sum += res;
- } while (sum < size);
- #ifdef SYNC_MODE
- posix_fadvise(ctx->fd, fw->written, size, POSIX_FADV_DONTNEED);
- #endif /* SYNC_MODE */
-
- *written = size;
- return 0;
- }
|