diff options
author | Markos Fountoulakis <44345837+mfundul@users.noreply.github.com> | 2019-06-03 15:26:16 +0300 |
---|---|---|
committer | Chris Akritidis <43294513+cakrit@users.noreply.github.com> | 2019-06-03 14:26:16 +0200 |
commit | dee923850b3ff9b921ed657fe5f8736732b06645 (patch) | |
tree | b4a33127fb11cc04968e558658d99160391b54f3 | |
parent | 5a89b3f934a2f327888655d3f9fb45a09eaa67d7 (diff) |
Support falling back to buffered I/O when direct I/O is unavailable (#6174)
-rw-r--r-- | database/engine/datafile.c | 20 | ||||
-rw-r--r-- | database/engine/journalfile.c | 20 | ||||
-rw-r--r-- | database/engine/rrdenginelib.c | 42 | ||||
-rw-r--r-- | database/engine/rrdenginelib.h | 1 |
4 files changed, 47 insertions, 36 deletions
diff --git a/database/engine/datafile.c b/database/engine/datafile.c index 2d17d05e42..9262805c81 100644 --- a/database/engine/datafile.c +++ b/database/engine/datafile.c @@ -100,18 +100,10 @@ int create_data_file(struct rrdengine_datafile *datafile) char path[1024]; generate_datafilepath(datafile, path, sizeof(path)); - fd = uv_fs_open(NULL, &req, path, O_DIRECT | O_CREAT | O_RDWR | O_TRUNC, - S_IRUSR | S_IWUSR, NULL); + fd = open_file_direct_io(path, O_CREAT | O_RDWR | O_TRUNC, &file); if (fd < 0) { fatal("uv_fs_fsopen: %s", uv_strerror(fd)); } - assert(req.result >= 0); - file = req.result; - uv_fs_req_cleanup(&req); -#ifdef __APPLE__ - info("Disabling OS X caching for file \"%s\".", path); - fcntl(fd, F_NOCACHE, 1); -#endif ret = posix_memalign((void *)&superblock, RRDFILE_ALIGNMENT, sizeof(*superblock)); if (unlikely(ret)) { @@ -187,20 +179,12 @@ static int load_data_file(struct rrdengine_datafile *datafile) char path[1024]; generate_datafilepath(datafile, path, sizeof(path)); - fd = uv_fs_open(NULL, &req, path, O_DIRECT | O_RDWR, S_IRUSR | S_IWUSR, NULL); + fd = open_file_direct_io(path, O_RDWR, &file); if (fd < 0) { /* if (UV_ENOENT != fd) */ error("uv_fs_fsopen: %s", uv_strerror(fd)); - uv_fs_req_cleanup(&req); return fd; } - assert(req.result >= 0); - file = req.result; - uv_fs_req_cleanup(&req); -#ifdef __APPLE__ - info("Disabling OS X caching for file \"%s\".", path); - fcntl(fd, F_NOCACHE, 1); -#endif info("Initializing data file \"%s\".", path); ret = check_file_properties(file, &file_size, sizeof(struct rrdeng_df_sb)); diff --git a/database/engine/journalfile.c b/database/engine/journalfile.c index e85b09cfda..9b14c914df 100644 --- a/database/engine/journalfile.c +++ b/database/engine/journalfile.c @@ -146,18 +146,10 @@ int create_journal_file(struct rrdengine_journalfile *journalfile, struct rrdeng char path[1024]; generate_journalfilepath(datafile, path, sizeof(path)); - fd = uv_fs_open(NULL, &req, path, O_DIRECT | O_CREAT | O_RDWR | O_TRUNC, - S_IRUSR | S_IWUSR, NULL); + fd = open_file_direct_io(path, O_CREAT | O_RDWR | O_TRUNC, &file); if (fd < 0) { fatal("uv_fs_fsopen: %s", uv_strerror(fd)); } - assert(req.result >= 0); - file = req.result; - uv_fs_req_cleanup(&req); -#ifdef __APPLE__ - info("Disabling OS X caching for file \"%s\".", path); - fcntl(fd, F_NOCACHE, 1); -#endif ret = posix_memalign((void *)&superblock, RRDFILE_ALIGNMENT, sizeof(*superblock)); if (unlikely(ret)) { @@ -411,20 +403,12 @@ int load_journal_file(struct rrdengine_instance *ctx, struct rrdengine_journalfi char path[1024]; generate_journalfilepath(datafile, path, sizeof(path)); - fd = uv_fs_open(NULL, &req, path, O_DIRECT | O_RDWR, S_IRUSR | S_IWUSR, NULL); + fd = open_file_direct_io(path, O_RDWR, &file); if (fd < 0) { /* if (UV_ENOENT != fd) */ error("uv_fs_fsopen: %s", uv_strerror(fd)); - uv_fs_req_cleanup(&req); return fd; } - assert(req.result >= 0); - file = req.result; - uv_fs_req_cleanup(&req); -#ifdef __APPLE__ - info("Disabling OS X caching for file \"%s\".", path); - fcntl(fd, F_NOCACHE, 1); -#endif info("Loading journal file \"%s\".", path); ret = check_file_properties(file, &file_size, sizeof(struct rrdeng_df_sb)); diff --git a/database/engine/rrdenginelib.c b/database/engine/rrdenginelib.c index 176a01dcc1..0523d54e7e 100644 --- a/database/engine/rrdenginelib.c +++ b/database/engine/rrdenginelib.c @@ -78,6 +78,48 @@ int check_file_properties(uv_file file, uint64_t *file_size, size_t min_size) return 0; } +/* + * Tries to open a file in direct I/O mode, falls back to buffered mode if not possible. + * Returns UV error number that is < 0 on failure. + * On success sets (*file) to be the uv_file that was opened. + */ +int open_file_direct_io(char *path, int flags, uv_file *file) +{ + uv_fs_t req; + int fd, current_flags, direct; + + for (direct = 1 ; direct >= 0 ; --direct) { +#ifdef __APPLE__ + /* Apple OS does not support O_DIRECT */ + direct = 0; +#endif + current_flags = flags; + if (direct) { + current_flags |= O_DIRECT; + } + fd = uv_fs_open(NULL, &req, path, current_flags, S_IRUSR | S_IWUSR, NULL); + if (fd < 0) { + if ((direct) && (UV_EINVAL == fd)) { + error("File \"%s\" does not support direct I/O, falling back to buffered I/O.", path); + } else { + error("Failed to open file \"%s\".", path); + return fd; + } + } else { + assert(req.result >= 0); + *file = req.result; +#ifdef __APPLE__ + info("Disabling OS X caching for file \"%s\".", path); + fcntl(fd, F_NOCACHE, 1); +#endif + --direct; /* break the loop */ + } + uv_fs_req_cleanup(&req); + } + + return fd; +} + char *get_rrdeng_statistics(struct rrdengine_instance *ctx, char *str, size_t size) { struct page_cache *pg_cache; diff --git a/database/engine/rrdenginelib.h b/database/engine/rrdenginelib.h index 5873e47234..c71cdd1220 100644 --- a/database/engine/rrdenginelib.h +++ b/database/engine/rrdenginelib.h @@ -93,6 +93,7 @@ static inline void crc32set(void *crcp, uLong crc) extern void print_page_cache_descr(struct rrdeng_page_descr *page_cache_descr); extern void print_page_descr(struct rrdeng_page_descr *descr); extern int check_file_properties(uv_file file, uint64_t *file_size, size_t min_size); +extern int open_file_direct_io(char *path, int flags, uv_file *file); extern char *get_rrdeng_statistics(struct rrdengine_instance *ctx, char *str, size_t size); #endif /* NETDATA_RRDENGINELIB_H */
\ No newline at end of file |