allow memory mode ram to use KSM; fixes #2284
Costa Tsaousis (ktsaou) committed
Jun 7, 2017 at 01:55 UTC
90b99fcf0f40eee4dd9ded629a453eb242e46fd2
4 files changed
+117
-85
src/common.c
+98
-78
@@ -943,105 +943,125 @@ inline char *trim_all(char *buffer) {
943
return buffer;
944
}
945
946
-void *mymmap(const char *filename, size_t size, int flags, int ksm) {
947
-#ifndef MADV_MERGEABLE
948
- (void)ksm;
949
-#endif
950
- static int log_madvise_1 = 1;
951
-#ifdef MADV_MERGEABLE
952
- static int log_madvise_2 = 1, log_madvise_3 = 1;
953
-#endif
954
- void *mem = NULL;
955
-
956
- errno = 0;
946
+static int memory_file_open(const char *filename, size_t size) {
947
int fd = open(filename, O_RDWR | O_CREAT | O_NOATIME, 0664);
948
if (fd != -1) {
949
if (lseek(fd, size, SEEK_SET) == (off_t) size) {
950
if (write(fd, "", 1) == 1) {
951
if (ftruncate(fd, size))
952
error("Cannot truncate file '%s' to size %zu. Will use the larger file.", filename, size);
953
+ }
954
+ else error("Cannot write to file '%s' at position %zu.", filename, size);
955
+ }
956
+ else error("Cannot seek file '%s' to size %zu.", filename, size);
957
+ }
958
+ else error("Cannot create/open file '%s'.", filename);
959
964
-#ifdef MADV_MERGEABLE
965
- if (flags & MAP_SHARED || !enable_ksm || !ksm) {
966
-#endif
967
- mem = mmap(NULL, size, PROT_READ | PROT_WRITE, flags, fd, 0);
968
- if (mem == MAP_FAILED) {
969
- error("Cannot allocate SHARED memory for file '%s'.", filename);
970
- mem = NULL;
971
- }
972
- else {
960
+ return fd;
961
+}
962
+
963
+// mmap_shared is used for memory mode = map
964
+static void *memory_file_mmap(const char *filename, size_t size, int flags) {
965
+ static int log_madvise = 1;
966
+
967
+ int fd = -1;
968
+ if(filename) {
969
+ fd = memory_file_open(filename, size);
970
+ if(fd == -1) return MAP_FAILED;
971
+ }
972
+
973
+ void *mem = mmap(NULL, size, PROT_READ | PROT_WRITE, flags, fd, 0);
974
+ if (mem != MAP_FAILED) {
975
#ifdef NETDATA_LOG_ALLOCATIONS
974
- mmap_accounting(size);
976
+ mmap_accounting(size);
977
#endif
976
- int advise = MADV_SEQUENTIAL | MADV_DONTFORK;
977
- if (flags & MAP_SHARED) advise |= MADV_WILLNEED;
978
-
979
- if (madvise(mem, size, advise) != 0 && log_madvise_1) {
980
- error("Cannot advise the kernel about the memory usage of file '%s'.", filename);
981
- log_madvise_1--;
982
- }
983
- }
978
+ int advise = MADV_SEQUENTIAL | MADV_DONTFORK;
979
+ if (flags & MAP_SHARED) advise |= MADV_WILLNEED;
980
+
981
+ if (madvise(mem, size, advise) != 0 && log_madvise) {
982
+ error("Cannot advise the kernel about shared memory usage.");
983
+ log_madvise--;
984
+ }
985
+ }
986
+
987
+ if(fd != -1)
988
+ close(fd);
989
+
990
+ return mem;
991
+}
992
+
993
#ifdef MADV_MERGEABLE
985
- }
986
- else {
987
-/*
988
- // test - load the file into memory
989
- mem = calloc(1, size);
990
- if(mem) {
991
- if(lseek(fd, 0, SEEK_SET) == 0) {
992
- if(read(fd, mem, size) != (ssize_t)size)
993
- error("Cannot read from file '%s'", filename);
994
- }
995
- else
996
- error("Cannot seek to beginning of file '%s'.", filename);
997
- }
998
-*/
999
- mem = mmap(NULL, size, PROT_READ | PROT_WRITE, flags | MAP_ANONYMOUS, -1, 0);
1000
- if (mem == MAP_FAILED) {
1001
- error("Cannot allocate PRIVATE ANONYMOUS memory for KSM for file '%s'.", filename);
1002
- mem = NULL;
1003
- }
1004
- else {
994
+static void *memory_file_mmap_ksm(const char *filename, size_t size, int flags) {
995
+ static int log_madvise_2 = 1, log_madvise_3 = 1;
996
+
997
+ int fd = -1;
998
+ if(filename) {
999
+ fd = memory_file_open(filename, size);
1000
+ if(fd == -1) return MAP_FAILED;
1001
+ }
1002
+
1003
+ void *mem = mmap(NULL, size, PROT_READ | PROT_WRITE, flags | MAP_ANONYMOUS, -1, 0);
1004
+ if (mem != MAP_FAILED) {
1005
#ifdef NETDATA_LOG_ALLOCATIONS
1006
- mmap_accounting(size);
1007
-#endif
1008
- if (lseek(fd, 0, SEEK_SET) == 0) {
1009
- if (read(fd, mem, size) != (ssize_t) size)
1010
- error("Cannot read from file '%s'", filename);
1011
- } else
1012
- error("Cannot seek to beginning of file '%s'.", filename);
1013
-
1014
- // don't use MADV_SEQUENTIAL|MADV_DONTFORK, they disable MADV_MERGEABLE
1015
- if (madvise(mem, size, MADV_SEQUENTIAL | MADV_DONTFORK) != 0 && log_madvise_2) {
1016
- error("Cannot advise the kernel about the memory usage (MADV_SEQUENTIAL|MADV_DONTFORK) of file '%s'.",
1017
- filename);
1018
- log_madvise_2--;
1019
- }
1020
-
1021
- if (madvise(mem, size, MADV_MERGEABLE) != 0 && log_madvise_3) {
1022
- error("Cannot advise the kernel about the memory usage (MADV_MERGEABLE) of file '%s'.",
1023
- filename);
1024
- log_madvise_3--;
1025
- }
1026
- }
1027
- }
1006
+ mmap_accounting(size);
1007
#endif
1008
+ if(fd != -1) {
1009
+ if (lseek(fd, 0, SEEK_SET) == 0) {
1010
+ if (read(fd, mem, size) != (ssize_t) size)
1011
+ error("Cannot read from file '%s'", filename);
1012
+ }
1013
+ else error("Cannot seek to beginning of file '%s'.", filename);
1014
+
1015
+ // don't use MADV_SEQUENTIAL|MADV_DONTFORK, they disable MADV_MERGEABLE
1016
+ if (madvise(mem, size, MADV_SEQUENTIAL | MADV_DONTFORK) != 0 && log_madvise_2) {
1017
+ error("Cannot advise the kernel about the memory usage (MADV_SEQUENTIAL|MADV_DONTFORK) of file '%s'.", filename);
1018
+ log_madvise_2--;
1019
+ }
1020
+
1021
+ if (madvise(mem, size, MADV_MERGEABLE) != 0 && log_madvise_3) {
1022
+ error("Cannot advise the kernel about the memory usage (MADV_MERGEABLE) of file '%s'.", filename);
1023
+ log_madvise_3--;
1024
}
1030
- else
1031
- error("Cannot write to file '%s' at position %zu.", filename, size);
1025
}
1033
- else
1034
- error("Cannot seek file '%s' to size %zu.", filename, size);
1026
+ }
1027
1028
+ if(fd != -1)
1029
close(fd);
1037
- }
1030
+
1031
+ return mem;
1032
+}
1033
+#else
1034
+static void *memory_file_mmap_ksm(const char *filename, size_t size, int flags) {
1035
+
1036
+ if(filename)
1037
+ return memory_file_mmap(filename, size, flags);
1038
+
1039
+ // when KSM is not available and no filename is given (memory mode = ram),
1040
+ // we just report failure
1041
+ return MAP_FAILED;
1042
+}
1043
+#endif
1044
+
1045
+void *mymmap(const char *filename, size_t size, int flags, int ksm) {
1046
+ void *mem = NULL;
1047
+
1048
+ if (filename && (flags & MAP_SHARED || !enable_ksm || !ksm))
1049
+ // memory mode = map | save
1050
+ // when KSM is not enabled
1051
+ // MAP_SHARED is used for memory mode = map (no KSM possible)
1052
+ mem = memory_file_mmap(filename, size, flags);
1053
+
1054
else
1039
- error("Cannot create/open file '%s'.", filename);
1055
+ // memory mode = save | ram
1056
+ // when KSM is enabled
1057
+ // for memory mode = ram, the filename is NULL
1058
+ mem = memory_file_mmap_ksm(filename, size, flags);
1059
1060
+ if(mem == MAP_FAILED) return NULL;
1061
return mem;
1062
}
1063
1044
-int savememory(const char *filename, void *mem, size_t size) {
1064
+int memory_file_save(const char *filename, void *mem, size_t size) {
1065
char tmpfilename[FILENAME_MAX + 1];
1066
1067
snprintfz(tmpfilename, FILENAME_MAX, "%s.%ld.tmp", filename, (long) getpid());
src/common.h
+1
-1
@@ -271,7 +271,7 @@ extern void freez(void *ptr);
271
extern void json_escape_string(char *dst, const char *src, size_t size);
272
273
extern void *mymmap(const char *filename, size_t size, int flags, int ksm);
274
-extern int savememory(const char *filename, void *mem, size_t size);
274
+extern int memory_file_save(const char *filename, void *mem, size_t size);
275
276
extern int fd_is_valid(int fd);
277
src/rrddim.c
+8
-2
@@ -71,8 +71,14 @@ RRDDIM *rrddim_add_custom(RRDSET *st, const char *id, const char *name, collecte
71
rrdset_strncpyz_name(filename, id, FILENAME_MAX);
72
snprintfz(fullfilename, FILENAME_MAX, "%s/%s.db", st->cache_dir, filename);
73
74
- if(memory_mode == RRD_MEMORY_MODE_SAVE || memory_mode == RRD_MEMORY_MODE_MAP) {
75
- rd = (RRDDIM *)mymmap(fullfilename, size, ((memory_mode == RRD_MEMORY_MODE_MAP) ? MAP_SHARED : MAP_PRIVATE), 1);
74
+ if(memory_mode == RRD_MEMORY_MODE_SAVE || memory_mode == RRD_MEMORY_MODE_MAP || memory_mode == RRD_MEMORY_MODE_RAM) {
75
+ rd = (RRDDIM *)mymmap(
76
+ (memory_mode == RRD_MEMORY_MODE_RAM)?NULL:fullfilename
77
+ , size
78
+ , ((memory_mode == RRD_MEMORY_MODE_MAP) ? MAP_SHARED : MAP_PRIVATE)
79
+ , 1
80
+ );
81
+
82
if(likely(rd)) {
83
// we have a file mapped for rd
84
src/rrdset.c
+10
-4
@@ -294,14 +294,14 @@ void rrdset_save(RRDSET *st) {
294
295
if(st->rrd_memory_mode == RRD_MEMORY_MODE_SAVE) {
296
debug(D_RRD_STATS, "Saving stats '%s' to '%s'.", st->name, st->cache_filename);
297
- savememory(st->cache_filename, st, st->memsize);
297
+ memory_file_save(st->cache_filename, st, st->memsize);
298
}
299
300
RRDDIM *rd;
301
rrddim_foreach_read(rd, st) {
302
if(likely(rd->rrd_memory_mode == RRD_MEMORY_MODE_SAVE)) {
303
debug(D_RRD_STATS, "Saving dimension '%s' to '%s'.", rd->name, rd->cache_filename);
304
- savememory(rd->cache_filename, rd, rd->memsize);
304
+ memory_file_save(rd->cache_filename, rd, rd->memsize);
305
}
306
}
307
}
@@ -421,8 +421,14 @@ RRDSET *rrdset_create_custom(
421
debug(D_RRD_CALLS, "Creating RRD_STATS for '%s.%s'.", type, id);
422
423
snprintfz(fullfilename, FILENAME_MAX, "%s/main.db", cache_dir);
424
- if(memory_mode == RRD_MEMORY_MODE_SAVE || memory_mode == RRD_MEMORY_MODE_MAP) {
425
- st = (RRDSET *) mymmap(fullfilename, size, ((memory_mode == RRD_MEMORY_MODE_MAP) ? MAP_SHARED : MAP_PRIVATE), 0);
424
+ if(memory_mode == RRD_MEMORY_MODE_SAVE || memory_mode == RRD_MEMORY_MODE_MAP || memory_mode == RRD_MEMORY_MODE_RAM) {
425
+ st = (RRDSET *) mymmap(
426
+ (memory_mode == RRD_MEMORY_MODE_RAM)?NULL:fullfilename
427
+ , size
428
+ , ((memory_mode == RRD_MEMORY_MODE_MAP) ? MAP_SHARED : MAP_PRIVATE)
429
+ , 0
430
+ );
431
+
432
if(st) {
433
memset(&st->avl, 0, sizeof(avl));
434
memset(&st->avlname, 0, sizeof(avl));