lkml.org 
[lkml]   [1997]   [Dec]   [17]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
SubjectMemory usage maps into /proc/memmap and /proc/mempages
Hi!

Marnix Coppens presented stand-alone module usable for listing memory
usage in very nice way. I think that this is really nice, that it
could be simply compiled into kernel, and maybe even merged into
official tree. What do you think? (I did not make it CONFIG_
option. Do you think that it should be?)

Pavel

diff -urN -x .dep* -x .hdep* -x *.[oas] -x *~ -x #* -x *CVS* -x *.orig -x *.rej -x *.old -x .menu* -x asm -x local.h -x System.map -x autoconf.h -x compile.h -x version.h -x .version -x defkeymap.c -x uni_hash.tbl -x zImage -x vmlinu?* -x TAGS -x bootsect -x *RCS* -x conmakehash -x map -x build -x build -x configure -x *target* clean/fs/proc/Makefile linux/fs/proc/Makefile
--- clean/fs/proc/Makefile Sat Aug 16 18:53:08 1997
+++ linux/fs/proc/Makefile Tue Dec 16 11:30:02 1997
@@ -9,7 +9,7 @@

O_TARGET := proc.o
O_OBJS := inode.o root.o base.o generic.o mem.o link.o fd.o array.o \
- kmsg.o scsi.o proc_tty.o
+ kmsg.o scsi.o proc_tty.o memmap.o
ifdef CONFIG_OMIRR
O_OBJS := $(O_OBJS) omirr.o
endif
diff -urN -x .dep* -x .hdep* -x *.[oas] -x *~ -x #* -x *CVS* -x *.orig -x *.rej -x *.old -x .menu* -x asm -x local.h -x System.map -x autoconf.h -x compile.h -x version.h -x .version -x defkeymap.c -x uni_hash.tbl -x zImage -x vmlinu?* -x TAGS -x bootsect -x *RCS* -x conmakehash -x map -x build -x build -x configure -x *target* clean/fs/proc/memmap.c linux/fs/proc/memmap.c
--- clean/fs/proc/memmap.c Thu Jan 1 01:00:00 1970
+++ linux/fs/proc/memmap.c Tue Dec 16 12:28:39 1997
@@ -0,0 +1,240 @@
+/*
+ * memmap.c, a module to examine the state of the physical memory.
+ * This will register two files /proc/memmap and /proc/mempages.
+ *
+ * Copyright (C) 1997 Marnix Coppens
+ *
+ * Modified for usage under 2.1.72 by Craig Schlenter <craig@is.co.za>
+ *
+ * Making possible to be non-modular, more verbosity, and making possible
+ * for other parts of kernel (magic sysrrq) (not done, yet) to call this
+ * by Pavel Machek <pavel@atrey.karlin.mff.cuni.cz>
+ *
+ * /proc/memmap shows one character per physical page as follows:
+ * 'X' for reserved, 'b' for buffers, 'c' for cached, 'u' for used and '.' for free (and more).
+ * The number of these should match the output of 'free' or /proc/meminfo,
+ * with this difference that 'u' doesn't include 'b' or 'c'.
+ * The number of reserved bytes matches the amount of memory used by the
+ * kernel as reported at boot time. The output is 32 characters at a line,
+ * so that every line describes 128 KB of physical memory.
+ *
+ * /proc/mempages shows a more detailed description of every physical page
+ * that is non-free (and non-reserved). The output can be one of the following:
+ * 02ba5000 00001000 1 c 00000000 0 03:02 14284
+ * 02ba6000 00000000 1 u
+ * 02ba7000 0000f000 1 c 02cb8b18 2 03:02 54908
+ * 02ba8000 00003000 1 b
+ * where the fields are (see also include/linux/mm.h):
+ * 1) physical address.
+ * 2) page offset.
+ * 3) page reference count.
+ * 4) state (as above, but without 'f' or 'R').
+ * 5) pointer to memory mapping (vm_area_struct); if non-zero, this is also
+ * a physical address and the corresponding page will show up as 'u'.
+ * 6) inode reference count.
+ * 7,8) device and inode number. With the use of dentries in recent kernels (2.1.xx),
+ * this will become the inode's filename.
+ */
+
+/*
+ * compile as a stand-alone module with:
+ * gcc -c memmap.c -O2 -pipe -fomit-frame-pointer -Wall -DMODULE -D__KERNEL__ -DLINUX
+ *
+ * Or, for 2.1.72:
+gcc -D__KERNEL__ -I/usr/src/linux/include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe -fno-strength-reduce -m486 -DCPU=486 -DMODULE -DMODVERSIONS -include /usr/src/linux/include/linux/modversions.h -DEXPORT_SYMTAB -c memmap.c
+ */
+
+#include <linux/mm.h>
+#include <linux/proc_fs.h>
+#include <linux/module.h>
+#include <asm/uaccess.h>
+
+#define MEMMAP_LINE_SHIFT 8
+#define MEMMAP_LINE_LENGTH (1 << MEMMAP_LINE_SHIFT)
+#define MEMMAP_LINE_CUTOFF (32 + 1)
+#define MEMMAP_LINE_MAX (4*MEMMAP_LINE_CUTOFF)
+
+static char line[MEMMAP_LINE_MAX];
+
+char
+page_get_description( struct page *page )
+{
+ if (atomic_read(&page->count))
+ {
+ if (page->buffers)
+ return 'b'; /* buffers */
+ if (page->inode)
+ return 'c'; /* cached */
+ if (PageSlab(page))
+ return 's'; /* slab */
+ if (PageSwapCache(page))
+ return 'w'; /* swap cache */
+ return 'u'; /* used */
+ }
+ if (PageReserved(page))
+ return 'X'; /* reserved */
+ return '.'; /* free */
+}
+
+
+static ssize_t proc_memmap_read(struct file * file, char * buf,
+ size_t count, loff_t *ppos)
+{
+ /* struct inode * inode = file->f_dentry->d_inode; */
+ char c;
+ int column, idx;
+ char *obuf;
+ struct page *page, *endpage;
+
+ if (count < 0)
+ return -EINVAL;
+
+ MOD_INC_USE_COUNT;
+
+ column = file->f_pos & (MEMMAP_LINE_LENGTH - 1);
+ page = mem_map + (file->f_pos >> MEMMAP_LINE_SHIFT);
+ endpage = mem_map + MAP_NR(high_memory);
+ idx = 0;
+ obuf = buf;
+ while (count--)
+ {
+ if (++column == MEMMAP_LINE_CUTOFF)
+ {
+ c = '\n';
+ column = 0;
+ }
+ else if (page >= endpage)
+ break;
+ else
+ c = page_get_description(page++);
+
+ line[idx++] = c;
+ if (idx == MEMMAP_LINE_MAX)
+ {
+ copy_to_user(buf, line, MEMMAP_LINE_MAX);
+ buf += MEMMAP_LINE_MAX;
+ idx = 0;
+ }
+ }
+ if (idx)
+ {
+ copy_to_user(buf, line, idx);
+ buf += idx;
+ }
+ file->f_pos = ((page - mem_map) << MEMMAP_LINE_SHIFT) + column;
+
+ MOD_DEC_USE_COUNT;
+
+ return (buf - obuf);
+}
+
+static ssize_t proc_mempages_read(struct file * file, char * buf,
+ size_t count, loff_t *ppos)
+{
+ /* struct inode * inode = file->f_dentry->d_inode; */
+ mem_map_t *page, *endpage;
+ struct inode *inomem;
+ char *obuf;
+ int column, len, idx;
+
+ if (count < 0)
+ return -EINVAL;
+
+ MOD_INC_USE_COUNT;
+
+ column = file->f_pos & (MEMMAP_LINE_LENGTH - 1);
+ page = mem_map + (file->f_pos >> MEMMAP_LINE_SHIFT);
+ endpage = mem_map + MAP_NR(high_memory);
+ obuf = buf;
+ while (count && (page < endpage))
+ {
+ if (!atomic_read(&page->count))
+ {
+ page++;
+ continue;
+ }
+ len = sprintf(line, "%08lx %08lx %3d %5d ",
+ page->map_nr << 12,
+ page->offset,
+ atomic_read(&page->count),
+ page->age);
+ line[len++] = PageLocked(page)?'L':'.';
+ line[len++] = PageError(page)?'E':'.';
+ line[len++] = PageReferenced(page)?'R':'.';
+ line[len++] = PageUptodate(page)?'U':'.';
+ line[len++] = PageFreeAfter(page)?'f':'.';
+ line[len++] = PageDecrAfter(page)?'a':'.';
+ line[len++] = PageSwapUnlockAfter(page)?'u':'.';
+ line[len++] = PageDMA(page)?'d':'.';
+ line[len++] = PageSlab(page)?'S':'.';
+ line[len++] = PageSwapCache(page)?'W':'.';
+
+ line[len++] = ' ';
+ line[len++] = page_get_description( page );
+ if ((inomem = page->inode) != 0)
+ {
+ len += sprintf(line + len, " %08lx %3d %s %lu",
+ (unsigned long) inomem->i_mmap,
+ inomem->i_count,
+ kdevname(inomem->i_dev), inomem->i_ino);
+ }
+
+ line[len++] = '\n';
+ if (column < len)
+ {
+ idx = len - column;
+ if (idx > count)
+ idx = count;
+ copy_to_user(buf, line + column, idx);
+ buf += idx;
+ count -= idx;
+ column += idx;
+ }
+ if (column >= len)
+ {
+ column = 0;
+ page++;
+ }
+ }
+ file->f_pos = ((page - mem_map) << MEMMAP_LINE_SHIFT) + column;
+
+ MOD_DEC_USE_COUNT;
+
+ return (buf - obuf);
+}
+
+struct file_operations proc_memmap_operations = {
+ NULL, /* lseek - default */
+ proc_memmap_read, /* read */
+ NULL, /* write - bad */
+ NULL, /* readdir */
+ NULL, /* poll - default */
+ NULL, /* ioctl - default */
+ NULL, /* mmap */
+ NULL, /* no special open code */
+ NULL, /* no special release code */
+ NULL /* can't fsync */
+};
+
+struct file_operations proc_mempages_operations = {
+ NULL, /* lseek - default */
+ proc_mempages_read, /* read */
+ NULL, /* write - bad */
+ NULL, /* readdir */
+ NULL, /* poll - default */
+ NULL, /* ioctl - default */
+ NULL, /* mmap */
+ NULL, /* no special open code */
+ NULL, /* no special release code */
+ NULL /* can't fsync */
+};
+
+struct inode_operations proc_memmap_inode_operations = {
+ &proc_memmap_operations,
+ 0,
+};
+
+struct inode_operations proc_mempages_inode_operations = {
+ &proc_mempages_operations,
+ 0,
+};
diff -urN -x .dep* -x .hdep* -x *.[oas] -x *~ -x #* -x *CVS* -x *.orig -x *.rej -x *.old -x .menu* -x asm -x local.h -x System.map -x autoconf.h -x compile.h -x version.h -x .version -x defkeymap.c -x uni_hash.tbl -x zImage -x vmlinu?* -x TAGS -x bootsect -x *RCS* -x conmakehash -x map -x build -x build -x configure -x *target* clean/fs/proc/root.c linux/fs/proc/root.c
--- clean/fs/proc/root.c Sun Oct 12 19:16:37 1997
+++ linux/fs/proc/root.c Tue Dec 16 11:40:59 1997
@@ -563,6 +563,16 @@
S_IFREG | S_IRUGO, 1, 0, 0,
0, &proc_array_inode_operations
};
+static struct proc_dir_entry proc_memmap = {
+ 0, 6, "memmap",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+ 0, &proc_memmap_inode_operations, 0,
+};
+static struct proc_dir_entry proc_mempages = {
+ 0, 8, "mempages",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+ 0, &proc_mempages_inode_operations, 0,
+};
#ifdef CONFIG_OMIRR
static struct proc_dir_entry proc_root_omirr = {
PROC_OMIRR, 5, "omirr",
@@ -645,6 +655,8 @@
proc_register(&proc_root, &proc_root_hardware);
#endif
proc_register(&proc_root, &proc_root_slab);
+ proc_register(&proc_root, &proc_memmap);
+ proc_register(&proc_root, &proc_mempages);

if (prof_shift) {
proc_register(&proc_root, &proc_root_profile);
--- clean/include/linux/proc_fs.h Sun Dec 14 23:30:51 1997
+++ linux/include/linux/proc_fs.h Tue Dec 16 15:25:15 1997
@@ -367,7 +367,8 @@
#endif
extern struct inode_operations proc_omirr_inode_operations;
extern struct inode_operations proc_ppc_htab_inode_operations;
-
+extern struct inode_operations proc_memmap_inode_operations;
+extern struct inode_operations proc_mempages_inode_operations;
#endif

/*
--
I'm really pavel@atrey.karlin.mff.cuni.cz. Pavel
Look at http://atrey.karlin.mff.cuni.cz/~pavel/ ;-).

\
 
 \ /
  Last update: 2005-03-22 13:40    [from the cache]
©2003-2011 Jasper Spaans