wmmemload: Read memory correctly with Linux kernel version >= 3.14.
Beginning with Linux kernel version 3.14, a new MemAvailable line appears in /proc/meminfo[1]. This caused wmmemload to look for Cached and Buffers one line off of their correct location. The problem was reported in [2]. [1] https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=34e431b0ae398fc54ea69ff85ec700722c9da773 [2] https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=749216
This commit is contained in:
		
							parent
							
								
									ea2cf286ef
								
							
						
					
					
						commit
						52b638616c
					
				
					 1 changed files with 30 additions and 6 deletions
				
			
		| 
						 | 
					@ -28,7 +28,11 @@
 | 
				
			||||||
#include <sys/utsname.h>
 | 
					#include <sys/utsname.h>
 | 
				
			||||||
#include "mem.h"
 | 
					#include "mem.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int isnewformat; /* for kernel 2.5.1 or later */
 | 
					static enum {
 | 
				
			||||||
 | 
						BEFORE_2_5_1,
 | 
				
			||||||
 | 
						BETWEEN_2_5_1_AND_3_14,
 | 
				
			||||||
 | 
						AFTER_3_14
 | 
				
			||||||
 | 
					} format;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef DEBUG
 | 
					#ifdef DEBUG
 | 
				
			||||||
#  define INLINE_STATIC static
 | 
					#  define INLINE_STATIC static
 | 
				
			||||||
| 
						 | 
					@ -47,12 +51,17 @@ void mem_init(void)
 | 
				
			||||||
		perror("uname()");
 | 
							perror("uname()");
 | 
				
			||||||
	sscanf(un.release, "%d.%d.%d", &version, &patchlevel, &sublevel);
 | 
						sscanf(un.release, "%d.%d.%d", &version, &patchlevel, &sublevel);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* new format ? (kernel >= 2.5.1pre?) */
 | 
						/* new format ? (kernel >= 3.14 or 2.5.1pre?) */
 | 
				
			||||||
	/* see linux/fs/proc/proc_misc.c */
 | 
						/* see linux/fs/proc/proc_misc.c */
 | 
				
			||||||
	if ((version == 2 && patchlevel >= 5 && sublevel >= 1) ||
 | 
						/* or linux/fs/proc/meminfo.c */
 | 
				
			||||||
 | 
						if ((version == 3 && patchlevel >= 14) || version > 3)
 | 
				
			||||||
 | 
							format = AFTER_3_14;
 | 
				
			||||||
 | 
						else if ((version == 2 && patchlevel >= 5 && sublevel >= 1) ||
 | 
				
			||||||
	    (version == 2 && patchlevel >= 6 && sublevel >= 0) ||
 | 
						    (version == 2 && patchlevel >= 6 && sublevel >= 0) ||
 | 
				
			||||||
	    version > 2)
 | 
						    version > 2)
 | 
				
			||||||
		isnewformat = 1;
 | 
							format = BETWEEN_2_5_1_AND_3_14;
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							format = BEFORE_2_5_1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -104,7 +113,8 @@ void mem_getusage(int *per_mem, int *per_swap, const struct mem_options *opts)
 | 
				
			||||||
	buffer[len] = '\0';
 | 
						buffer[len] = '\0';
 | 
				
			||||||
	p = buffer;
 | 
						p = buffer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!isnewformat) {
 | 
						switch (format) {
 | 
				
			||||||
 | 
						case (BEFORE_2_5_1):
 | 
				
			||||||
		/* skip 3 lines */
 | 
							/* skip 3 lines */
 | 
				
			||||||
		for (i = 0; i < 3; i++)
 | 
							for (i = 0; i < 3; i++)
 | 
				
			||||||
			p = skip_line(p);
 | 
								p = skip_line(p);
 | 
				
			||||||
| 
						 | 
					@ -115,7 +125,9 @@ void mem_getusage(int *per_mem, int *per_swap, const struct mem_options *opts)
 | 
				
			||||||
		mbuffer = strtoul(p, &p, 0); p = skip_multiple_token(p, 2);
 | 
							mbuffer = strtoul(p, &p, 0); p = skip_multiple_token(p, 2);
 | 
				
			||||||
		mcached = strtoul(p, &p, 0); p = skip_multiple_token(p, 2);
 | 
							mcached = strtoul(p, &p, 0); p = skip_multiple_token(p, 2);
 | 
				
			||||||
		scached = strtoul(p, &p, 0);
 | 
							scached = strtoul(p, &p, 0);
 | 
				
			||||||
	} else {
 | 
							break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						case (BETWEEN_2_5_1_AND_3_14):
 | 
				
			||||||
		p = skip_token(p);
 | 
							p = skip_token(p);
 | 
				
			||||||
		/* examine each line of file */
 | 
							/* examine each line of file */
 | 
				
			||||||
		mtotal  = strtoul(p, &p, 0); p = skip_multiple_token(p, 2);
 | 
							mtotal  = strtoul(p, &p, 0); p = skip_multiple_token(p, 2);
 | 
				
			||||||
| 
						 | 
					@ -123,6 +135,18 @@ void mem_getusage(int *per_mem, int *per_swap, const struct mem_options *opts)
 | 
				
			||||||
		mbuffer = strtoul(p, &p, 0); p = skip_multiple_token(p, 2);
 | 
							mbuffer = strtoul(p, &p, 0); p = skip_multiple_token(p, 2);
 | 
				
			||||||
		mcached = strtoul(p, &p, 0); p = skip_multiple_token(p, 2);
 | 
							mcached = strtoul(p, &p, 0); p = skip_multiple_token(p, 2);
 | 
				
			||||||
		scached = strtoul(p, &p, 0);
 | 
							scached = strtoul(p, &p, 0);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						case (AFTER_3_14):
 | 
				
			||||||
 | 
							p = skip_token(p);
 | 
				
			||||||
 | 
							/* examine each line of file */
 | 
				
			||||||
 | 
							mtotal  = strtoul(p, &p, 0); p = skip_multiple_token(p, 2);
 | 
				
			||||||
 | 
							mfree   = strtoul(p, &p, 0);
 | 
				
			||||||
 | 
							p = skip_multiple_token(p, 5); /* skip MemAvailable line */
 | 
				
			||||||
 | 
							mbuffer = strtoul(p, &p, 0); p = skip_multiple_token(p, 2);
 | 
				
			||||||
 | 
							mcached = strtoul(p, &p, 0); p = skip_multiple_token(p, 2);
 | 
				
			||||||
 | 
							scached = strtoul(p, &p, 0);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue