58
58
#define KPAGEFLAGS "/proc/kpageflags"
59
59
#define MODULES "/proc/modules"
60
60
#define HUGEPAGESINFO "/sys/kernel/mm/hugepages"
61
+ #define DENTRYINFO "/proc/sys/fs/dentry-state"
62
+ #define INODEINFO "/proc/sys/fs/inode-nr"
61
63
62
64
/*
63
65
* System files to control reclamation and compaction
64
66
*/
65
67
#define RESCALE_WMARK "/proc/sys/vm/watermark_scale_factor"
66
68
#define COMPACT_PATH_FORMAT "/sys/devices/system/node/node%d/compact"
69
+ #define VFS_CACHE_PRESSURE "/proc/sys/vm/vfs_cache_pressure"
67
70
68
71
/*
69
72
* System files to control negative dentries
76
79
#define CONFIG_FILE1 "/etc/sysconfig/adaptivemmd"
77
80
#define CONFIG_FILE2 "/etc/default/adaptivemmd"
78
81
82
+ #define FS_FIELDS 2
79
83
#define MAX_NUMANODES 1024
80
84
81
85
#define MAX_VERBOSE 5
82
86
#define MAX_AGGRESSIVE 3
83
87
#define MAX_NEGDENTRY 100
84
88
89
+ #define MAX_VFS_CACHE_PRESSURE 1000
90
+ #define MIN_VFS_CACHE_PRESSURE 3
91
+
85
92
/*
86
93
* Number of consecutive samples showing growth in unaccounted memory
87
94
* that will trigger memory leak warning
91
98
/* Minimum % change in meminfo numbers to trigger warnings */
92
99
#define MEM_TRIGGER_DELTA 10
93
100
101
+ int MAX (unsigned long a , unsigned long b ) { return ((a ) > (b ) ? a : b ); }
102
+ int MIN (unsigned long a , unsigned long b ) { return ((a ) < (b ) ? a : b ); }
103
+
94
104
unsigned long min_wmark [MAX_NUMANODES ], low_wmark [MAX_NUMANODES ];
95
105
unsigned long high_wmark [MAX_NUMANODES ], managed_pages [MAX_NUMANODES ];
96
106
unsigned long total_free_pages , total_cache_pages , total_hugepages , base_psize ;
97
107
long compaction_rate , reclaim_rate ;
98
108
struct lsq_struct page_lsq [MAX_NUMANODES ][MAX_ORDER ];
109
+ struct lsq_struct fs_lsq [FS_FIELDS ];
99
110
int dry_run ;
100
111
int debug_mode , verbose , del_lock = 0 ;
101
112
unsigned long maxgap ;
102
113
int aggressiveness = 2 ;
103
114
int periodicity , skip_dmazone ;
104
115
int neg_dentry_pct = 15 ; /* default is 1.5% */
116
+ int prefer_object_caching = 1 ;
105
117
106
118
/* Flags to enable various modules */
107
119
bool memory_pressure_check_enabled = true;
@@ -127,7 +139,6 @@ unsigned int mywsf;
127
139
*/
128
140
int max_compaction_order = MAX_ORDER - 4 ;
129
141
130
-
131
142
/*
132
143
* Clean up before exiting
133
144
*/
@@ -185,6 +196,14 @@ void log_msg(int level, char *fmt, ...)
185
196
va_end (args );
186
197
}
187
198
199
+ static inline unsigned long get_msecs (struct timespec * spec )
200
+ {
201
+ if (!spec )
202
+ return -1 ;
203
+
204
+ return (unsigned long )((spec -> tv_sec * 1000 ) + (spec -> tv_nsec / 1000 ));
205
+ }
206
+
188
207
/*
189
208
* Initiate memory compactiomn in the kernel on a given node.
190
209
*/
@@ -519,6 +538,95 @@ void rescale_maxwsf()
519
538
log_warn ("Failed to compute reasonable WSF, %ld, total pages %ld, reclaimable pages %ld" , new_wsf , total_managed , reclaimable_pages );
520
539
}
521
540
541
+ int parse_fs_files (char * path , unsigned long * data )
542
+ {
543
+ FILE * fp = NULL ;
544
+ char line [80 ];
545
+
546
+ fp = fopen (path , "r" );
547
+ if (!fp )
548
+ return -1 ;
549
+
550
+ if (fgets (line , sizeof (line ), fp ) != NULL )
551
+ sscanf (line , "%lu\n" , data );
552
+ else {
553
+ fclose (fp );
554
+ return -1 ;
555
+ }
556
+
557
+ fclose (fp );
558
+ return 0 ;
559
+ }
560
+
561
+ int set_vfs_cache_pressure (unsigned long new_cache_pressure )
562
+ {
563
+ int fd ;
564
+ char scaled_cache_pressure [20 ];
565
+
566
+ sprintf (scaled_cache_pressure , "%ld\n" , new_cache_pressure );
567
+ if ((fd = open (VFS_CACHE_PRESSURE , O_WRONLY )) == -1 ) {
568
+ log_err ("Failed to open " VFS_CACHE_PRESSURE " (%s)" , strerror (errno ));
569
+ return -1 ;
570
+ }
571
+
572
+ if (write (fd , scaled_cache_pressure , strlen (scaled_cache_pressure )) < 0 ) {
573
+ log_err ("Failed to write to " VFS_CACHE_PRESSURE " (%s)" , strerror (errno ));
574
+ return -1 ;
575
+ }
576
+
577
+ log_info (1 , "New vfs_cache_pressure = %ld" , new_cache_pressure );
578
+ return 0 ;
579
+ }
580
+
581
+ /*
582
+ * rescale vm.vfs_cache_pressure value based on current memory trends
583
+ */
584
+ void rescale_vfs_cache_pressure ()
585
+ {
586
+ struct timespec spec ;
587
+ unsigned long curr_inodes ;
588
+ unsigned long curr_dentries ;
589
+ unsigned long curr_vfs_cache_pressure ;
590
+ long long dentry_m , inode_m ;
591
+ long long dentry_c , inode_c ;
592
+
593
+ if (parse_fs_files (VFS_CACHE_PRESSURE , & curr_vfs_cache_pressure ) ||
594
+ parse_fs_files (INODEINFO , & curr_inodes ) ||
595
+ parse_fs_files (DENTRYINFO , & curr_dentries ))
596
+ return ;
597
+
598
+ clock_gettime (CLOCK_MONOTONIC_RAW , & spec );
599
+
600
+ if (lsq_fit (& fs_lsq [0 ], curr_dentries ,
601
+ (long long )get_msecs (& spec ),& dentry_m , & dentry_c ) ||
602
+ lsq_fit (& fs_lsq [1 ], curr_inodes ,
603
+ (long long )get_msecs (& spec ), & inode_m , & inode_c ))
604
+ return ;
605
+ /*
606
+ * adjust vm.vfs_cache_pressure based on the
607
+ * growth of cached inode and dentry objects
608
+ */
609
+ if (prefer_object_caching ) {
610
+ if ((dentry_m > 0 || inode_m > 0 ) &&
611
+ curr_vfs_cache_pressure > MIN_VFS_CACHE_PRESSURE ) {
612
+ set_vfs_cache_pressure (curr_vfs_cache_pressure * 0.9 );
613
+ } else if ((dentry_m < 0 || inode_m < 0 ) &&
614
+ curr_vfs_cache_pressure < MAX_VFS_CACHE_PRESSURE )
615
+ set_vfs_cache_pressure (MIN (MAX_VFS_CACHE_PRESSURE ,
616
+ curr_vfs_cache_pressure * 1.1 ));
617
+ } else {
618
+ if ((dentry_m > 0 || inode_m > 0 ) &&
619
+ curr_vfs_cache_pressure < MAX_VFS_CACHE_PRESSURE ) {
620
+ set_vfs_cache_pressure (MIN (MAX_VFS_CACHE_PRESSURE ,
621
+ curr_vfs_cache_pressure * 1.1 ));
622
+ } else if ((dentry_m < 0 || inode_m < 0 ) &&
623
+ curr_vfs_cache_pressure > MIN_VFS_CACHE_PRESSURE )
624
+ set_vfs_cache_pressure (curr_vfs_cache_pressure * 0.9 );
625
+ }
626
+
627
+ return ;
628
+ }
629
+
522
630
/*
523
631
* Get the number of pages stolen by kswapd from /proc/vmstat.
524
632
*/
@@ -783,14 +891,6 @@ void rescale_watermarks(int scale_up)
783
891
close (fd );
784
892
}
785
893
786
- static inline unsigned long get_msecs (struct timespec * spec )
787
- {
788
- if (!spec )
789
- return -1 ;
790
-
791
- return (unsigned long )((spec -> tv_sec * 1000 ) + (spec -> tv_nsec / 1000 ));
792
- }
793
-
794
894
/*
795
895
* check_permissions() - Check all required permissions for this program to
796
896
* run successfully
@@ -1596,8 +1696,7 @@ void check_memory_pressure(bool init)
1596
1696
1597
1697
/*
1598
1698
* one_time_initializations() - Initialize settings that are set once at
1599
- * adaptivemmd startup
1600
- *
1699
+ * adaptivemmd startup
1601
1700
*/
1602
1701
void one_time_initializations ()
1603
1702
{
@@ -1631,6 +1730,7 @@ void one_time_initializations()
1631
1730
#define OPT_NEG_DENTRY1 "NEG-DENTRY-CAP"
1632
1731
#define OPT_NEG_DENTRY2 "NEG_DENTRY_CAP"
1633
1732
#define OPT_ENB_MEMLEAK "ENABLE_MEMLEAK_CHECK"
1733
+ #define OPT_PREFER_OBJECT_CACHING "PREFER_OBJECT_CACHING"
1634
1734
1635
1735
int parse_config ()
1636
1736
{
@@ -1728,6 +1828,8 @@ int parse_config()
1728
1828
neg_dentry_pct = val ;
1729
1829
} else if (strncmp (token , OPT_ENB_MEMLEAK , sizeof (OPT_ENB_MEMLEAK )) == 0 )
1730
1830
memleak_check_enabled = ((val == 0 )?false:true);
1831
+ else if (strncmp (token , OPT_PREFER_OBJECT_CACHING , sizeof (OPT_PREFER_OBJECT_CACHING )) == 0 )
1832
+ prefer_object_caching = val ;
1731
1833
else {
1732
1834
log_err ("Error in configuration file at token \"%s\". Proceeding with defaults" , token );
1733
1835
break ;
@@ -1908,7 +2010,6 @@ int main(int argc, char **argv)
1908
2010
base_psize = getpagesize ()/1024 ;
1909
2011
1910
2012
pr_info ("adaptivemmd " VERSION " started (verbose=%d, aggressiveness=%d, maxgap=%d)" , verbose , aggressiveness , maxgap );
1911
-
1912
2013
one_time_initializations ();
1913
2014
1914
2015
while (1 ) {
@@ -1927,9 +2028,9 @@ int main(int argc, char **argv)
1927
2028
updates_for_hugepages (retval );
1928
2029
if (maxgap == 0 )
1929
2030
rescale_maxwsf ();
1930
-
1931
2031
check_memory_pressure (false);
1932
2032
check_memory_leak (false);
2033
+ rescale_vfs_cache_pressure ();
1933
2034
1934
2035
sleep (periodicity );
1935
2036
}
0 commit comments