summaryrefslogtreecommitdiffstats
path: root/database/engine
diff options
context:
space:
mode:
authorMarkos Fountoulakis <44345837+mfundul@users.noreply.github.com>2019-06-03 15:26:16 +0300
committerChris Akritidis <43294513+cakrit@users.noreply.github.com>2019-06-03 14:26:16 +0200
commitdee923850b3ff9b921ed657fe5f8736732b06645 (patch)
treeb4a33127fb11cc04968e558658d99160391b54f3 /database/engine
parent5a89b3f934a2f327888655d3f9fb45a09eaa67d7 (diff)
Support falling back to buffered I/O when direct I/O is unavailable (#6174)
Diffstat (limited to 'database/engine')
-rw-r--r--database/engine/datafile.c20
-rw-r--r--database/engine/journalfile.c20
-rw-r--r--database/engine/rrdenginelib.c42
-rw-r--r--database/engine/rrdenginelib.h1
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