Support falling back to buffered I/O when direct I/O is unavailable (#6174)
Markos Fountoulakis committed
Jun 3, 2019 at 15:26 UTC
dee923850b3ff9b921ed657fe5f8736732b06645
4 files changed
+47
-36
database/engine/datafile.c
+2
-18
@@ -100,18 +100,10 @@ int create_data_file(struct rrdengine_datafile *datafile)
100
char path[1024];
101
102
generate_datafilepath(datafile, path, sizeof(path));
103
- fd = uv_fs_open(NULL, &req, path, O_DIRECT | O_CREAT | O_RDWR | O_TRUNC,
104
- S_IRUSR | S_IWUSR, NULL);
103
+ fd = open_file_direct_io(path, O_CREAT | O_RDWR | O_TRUNC, &file);
104
if (fd < 0) {
105
fatal("uv_fs_fsopen: %s", uv_strerror(fd));
106
}
108
- assert(req.result >= 0);
109
- file = req.result;
110
- uv_fs_req_cleanup(&req);
111
-#ifdef __APPLE__
112
- info("Disabling OS X caching for file \"%s\".", path);
113
- fcntl(fd, F_NOCACHE, 1);
114
-#endif
107
108
ret = posix_memalign((void *)&superblock, RRDFILE_ALIGNMENT, sizeof(*superblock));
109
if (unlikely(ret)) {
@@ -187,20 +179,12 @@ static int load_data_file(struct rrdengine_datafile *datafile)
179
char path[1024];
180
181
generate_datafilepath(datafile, path, sizeof(path));
190
- fd = uv_fs_open(NULL, &req, path, O_DIRECT | O_RDWR, S_IRUSR | S_IWUSR, NULL);
182
+ fd = open_file_direct_io(path, O_RDWR, &file);
183
if (fd < 0) {
184
/* if (UV_ENOENT != fd) */
185
error("uv_fs_fsopen: %s", uv_strerror(fd));
194
- uv_fs_req_cleanup(&req);
186
return fd;
187
}
197
- assert(req.result >= 0);
198
- file = req.result;
199
- uv_fs_req_cleanup(&req);
200
-#ifdef __APPLE__
201
- info("Disabling OS X caching for file \"%s\".", path);
202
- fcntl(fd, F_NOCACHE, 1);
203
-#endif
188
info("Initializing data file \"%s\".", path);
189
190
ret = check_file_properties(file, &file_size, sizeof(struct rrdeng_df_sb));
database/engine/journalfile.c
+2
-18
@@ -146,18 +146,10 @@ int create_journal_file(struct rrdengine_journalfile *journalfile, struct rrdeng
146
char path[1024];
147
148
generate_journalfilepath(datafile, path, sizeof(path));
149
- fd = uv_fs_open(NULL, &req, path, O_DIRECT | O_CREAT | O_RDWR | O_TRUNC,
150
- S_IRUSR | S_IWUSR, NULL);
149
+ fd = open_file_direct_io(path, O_CREAT | O_RDWR | O_TRUNC, &file);
150
if (fd < 0) {
151
fatal("uv_fs_fsopen: %s", uv_strerror(fd));
152
}
154
- assert(req.result >= 0);
155
- file = req.result;
156
- uv_fs_req_cleanup(&req);
157
-#ifdef __APPLE__
158
- info("Disabling OS X caching for file \"%s\".", path);
159
- fcntl(fd, F_NOCACHE, 1);
160
-#endif
153
154
ret = posix_memalign((void *)&superblock, RRDFILE_ALIGNMENT, sizeof(*superblock));
155
if (unlikely(ret)) {
@@ -411,20 +403,12 @@ int load_journal_file(struct rrdengine_instance *ctx, struct rrdengine_journalfi
403
char path[1024];
404
405
generate_journalfilepath(datafile, path, sizeof(path));
414
- fd = uv_fs_open(NULL, &req, path, O_DIRECT | O_RDWR, S_IRUSR | S_IWUSR, NULL);
406
+ fd = open_file_direct_io(path, O_RDWR, &file);
407
if (fd < 0) {
408
/* if (UV_ENOENT != fd) */
409
error("uv_fs_fsopen: %s", uv_strerror(fd));
418
- uv_fs_req_cleanup(&req);
410
return fd;
411
}
421
- assert(req.result >= 0);
422
- file = req.result;
423
- uv_fs_req_cleanup(&req);
424
-#ifdef __APPLE__
425
- info("Disabling OS X caching for file \"%s\".", path);
426
- fcntl(fd, F_NOCACHE, 1);
427
-#endif
412
info("Loading journal file \"%s\".", path);
413
414
ret = check_file_properties(file, &file_size, sizeof(struct rrdeng_df_sb));
database/engine/rrdenginelib.c
+42
@@ -78,6 +78,48 @@ int check_file_properties(uv_file file, uint64_t *file_size, size_t min_size)
78
return 0;
79
}
80
81
+/*
82
+ * Tries to open a file in direct I/O mode, falls back to buffered mode if not possible.
83
+ * Returns UV error number that is < 0 on failure.
84
+ * On success sets (*file) to be the uv_file that was opened.
85
+ */
86
+int open_file_direct_io(char *path, int flags, uv_file *file)
87
+{
88
+ uv_fs_t req;
89
+ int fd, current_flags, direct;
90
+
91
+ for (direct = 1 ; direct >= 0 ; --direct) {
92
+#ifdef __APPLE__
93
+ /* Apple OS does not support O_DIRECT */
94
+ direct = 0;
95
+#endif
96
+ current_flags = flags;
97
+ if (direct) {
98
+ current_flags |= O_DIRECT;
99
+ }
100
+ fd = uv_fs_open(NULL, &req, path, current_flags, S_IRUSR | S_IWUSR, NULL);
101
+ if (fd < 0) {
102
+ if ((direct) && (UV_EINVAL == fd)) {
103
+ error("File \"%s\" does not support direct I/O, falling back to buffered I/O.", path);
104
+ } else {
105
+ error("Failed to open file \"%s\".", path);
106
+ return fd;
107
+ }
108
+ } else {
109
+ assert(req.result >= 0);
110
+ *file = req.result;
111
+#ifdef __APPLE__
112
+ info("Disabling OS X caching for file \"%s\".", path);
113
+ fcntl(fd, F_NOCACHE, 1);
114
+#endif
115
+ --direct; /* break the loop */
116
+ }
117
+ uv_fs_req_cleanup(&req);
118
+ }
119
+
120
+ return fd;
121
+}
122
+
123
char *get_rrdeng_statistics(struct rrdengine_instance *ctx, char *str, size_t size)
124
{
125
struct page_cache *pg_cache;
database/engine/rrdenginelib.h
+1
@@ -93,6 +93,7 @@ static inline void crc32set(void *crcp, uLong crc)
93
extern void print_page_cache_descr(struct rrdeng_page_descr *page_cache_descr);
94
extern void print_page_descr(struct rrdeng_page_descr *descr);
95
extern int check_file_properties(uv_file file, uint64_t *file_size, size_t min_size);
96
+extern int open_file_direct_io(char *path, int flags, uv_file *file);
97
extern char *get_rrdeng_statistics(struct rrdengine_instance *ctx, char *str, size_t size);
98
99
#endif /* NETDATA_RRDENGINELIB_H */
\ No newline at end of file