From: KOSAKI Motohiro <kosaki.motohiro@gmail.com>
To: Dan Merillat <dan.merillat@gmail.com>
Cc: linux-kernel@vger.kernel.org, Rik van Riel <riel@redhat.com>,
Norbert Preining <preining@logic.at>,
Tomasz Chmielewski <mangoo@wpkg.org>,
Sven-Haegar Koch <haegar@sdinet.de>,
Dave Chinner <david@fromorbit.com>
Subject: Re: Linux 2.6.31 - very swap-happy with plenty of free RAM
Date: Thu, 19 Nov 2009 23:36:04 +0900 [thread overview]
Message-ID: <2f11576a0911190636vd21069bv2fe4f22a57b3d333@mail.gmail.com> (raw)
In-Reply-To: <c0c067900911172356n2717ce9dn8a4231345903fde6@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 3366 bytes --]
Hi Dan,
2009/11/18 Dan Merillat <dan.merillat@gmail.com>:
> procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu----
> r b swpd free buff cache si so bi bo in cs us sy id wa
> 1 1 0 774404 49644 1713932 0 0 8 44 2680 5105 23 42 0 35
> 2 1 0 774900 49448 1713668 0 0 8 28 2870 5101 22 41 0 36
>
> swapon /dev/vg1/swap
>
> 2 2 34460 770808 47824 1709852 0 34460 952 34472 3174 5601 21 48 2 29
> 1 1 129716 759904 47460 1699364 0 95316 272 95532 3093 5641 16 49 7 29
> 1 4 196728 756680 47436 1693616 64 67080 92 67104 2980 5569 18 49 24 8
> 2 1 246212 754076 47396 1689240 32 49652 220 49760 3241 5405 19 51 1 29
> 2 3 282404 791648 47272 1686252 16 36284 240 36392 3088 6281 18 52 9 22
> 1 4 299464 847200 47260 1685208 324 17296 324 17320 3190 6199 23 46 0 30
> 2 5 302316 854384 47256 1685884 944 3804 1948 3812 2723 5297 20 45 5 31
> 11 3 303436 861700 47384 1686400 1188 1900 2084 1912 2615 4593 21 51 9 20
> swapoff -a
> 2 6 301740 863436 47384 1687048 1860 4 2368 128 2541 4591 21 63 0 15
> 3 4 300076 865916 47384 1687604 1672 0 2120 156 2673 5208 19 63 0 18
> 2 5 297676 866288 47380 1687988 2396 0 2668 188 2632 5259 17 70 2 12
> 2 2 295556 866784 47380 1687956 2352 0 2352 0 2621 5316 16 72 9 4
> 5 5 293168 867156 47384 1688120 2344 0 2344 20 2651 5469 18 79 0 4
> 2 4 291108 870504 47396 1688260 2036 0 2172 160 2381 4817 15 67 0 18
> 3 3 289416 870612 47400 1688476 2028 0 2260 148 2602 5214 18 69 0 13
> 3 3 287528 871928 47400 1688556 1928 0 2136 0 2470 5096 19 68 3 10
> 2 4 285740 873896 47408 1688892 2352 0 2764 172 2490 5194 18 66 0 17
>
> 1.7gb of disk cache, 750 meg of free RAM, and it swaps out 300meg in a
> matter of seconds when given access to a swapfile, then thrashes the
> disk like crazy because that RAM was actively in use. From an
> interactivity standpoint the machine is unusable - 1-2 second pauses
> on mouse movement, 10-15 seconds for the window manager to change
> window focus, keypresses take 1-2 seconds to show up, etc. When I
> issue a swapoff it takes 10-15 minutes for it to slowly pull it all
> back in - once it's done I run fine.
>
> The machine has 4gb of RAM (64bit), and runs 3 VMware VMs with a total
> of 1024mb allocated to them. VMware uses file-backed RAM (for some
> ungodly stupid reason) which is on a separate spindle (/dev/sdb) from
> swap (/dev/sda). I've got one VM pointed to a file-backed RAM on a
> tmpfs (512mb) that's probably got quite a bit of memory activity.
>
> The other main RAM hogs are the usual suspects - firefox, Xorg,
> thunderbird, openoffice, pidgin, etc, the usual junk on a busy Linux
> desktop.
>
> All the sysctl tuneables should be defaults, there's no distro or
> local changes to any vm settings (mmap_min_addr=0 for Wine,
> shmmax=256mb, some ipv6 tweaks)
>
> Ideas on where to start looking? If this is a vmware issue I'll take
> it to them.
Umm, very strange.
I made two debug patch. can you please apply it and post following
command output?
% cat /proc/meminfo
% cat /proc/vmstat
% cat /proc/zoneinfo
# cat /proc/filecache | sort -nr -k3 |head -30
[-- Attachment #2: proc-filecache-v2.patch --]
[-- Type: application/octet-stream, Size: 10880 bytes --]
diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
index 94b9f20..bad2506 100644
--- a/Documentation/filesystems/proc.txt
+++ b/Documentation/filesystems/proc.txt
@@ -414,6 +414,7 @@ Table 1-5: Kernel info in /proc
driver Various drivers grouped here, currently rtc (2.4)
execdomains Execdomains, related to security (2.4)
fb Frame Buffer devices (2.4)
+ filecache Query/drop in-memory file cache
fs File system parameters, currently nfs/exports (2.4)
ide Directory containing info about the IDE subsystem
interrupts Interrupt usage
@@ -770,6 +771,39 @@ Provides counts of softirq handlers serviced since boot time, for each cpu.
HRTIMER: 0 0 0 0
RCU: 1678 1769 2178 2250
+..............................................................................
+
+filecache:
+
+Provides access to the in-memory file cache.
+
+To list an index of all cached files:
+
+ cat /proc/filecache
+
+The output looks like:
+
+ # filecache 1.0
+ # ino size cached cached% state refcnt dev file
+ 1026334 91 92 100 -- 66 03:02(hda2) /lib/ld-2.3.6.so
+ 233608 1242 972 78 -- 66 03:02(hda2) /lib/tls/libc-2.3.6.so
+ 65203 651 476 73 -- 1 03:02(hda2) /bin/bash
+ 1026445 261 160 61 -- 10 03:02(hda2) /lib/libncurses.so.5.5
+ 235427 10 12 100 -- 44 03:02(hda2) /lib/tls/libdl-2.3.6.so
+
+
+ ino: inode number
+ size: inode size in KB
+ cached: cached size in KB
+ cached%: percent of file data cached
+ state1: '-' clean; 'd' metadata dirty; 'D' data dirty
+ state2: '-' unlocked; 'L' locked, normally indicates file being written out
+ refcnt: file reference count, it's an in-kernel one, not exactly open count
+ dev: major:minor numbers in hex, followed by a descriptive device name
+ file: file path _inside_ the filesystem. There are several special names:
+ '(noname)': the file name is not available
+ '(03:02)': the file is a block device file of major:minor
+ '...(deleted)': the named file has been deleted from the disk
1.3 IDE devices in /proc/ide
----------------------------
diff --git a/fs/dcache.c b/fs/dcache.c
index ddd1986..fa1c3ce 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -1927,7 +1927,11 @@ char *__d_path(const struct path *path, struct path *root,
if (dentry == root->dentry && vfsmnt == root->mnt)
break;
- if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) {
+
+ if (!vfsmnt) {
+ if (IS_ROOT(dentry))
+ break;
+ } else if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) {
/* Global root? */
if (vfsmnt->mnt_parent == vfsmnt) {
goto global_root;
diff --git a/fs/proc/Makefile b/fs/proc/Makefile
index 11a7b5c..c532d59 100644
--- a/fs/proc/Makefile
+++ b/fs/proc/Makefile
@@ -19,6 +19,7 @@ proc-y += stat.o
proc-y += uptime.o
proc-y += version.o
proc-y += softirqs.o
+proc-y += filecache.o
proc-$(CONFIG_PROC_SYSCTL) += proc_sysctl.o
proc-$(CONFIG_NET) += proc_net.o
proc-$(CONFIG_PROC_KCORE) += kcore.o
diff --git a/fs/proc/filecache.c b/fs/proc/filecache.c
new file mode 100644
index 0000000..0ca121c
--- /dev/null
+++ b/fs/proc/filecache.c
@@ -0,0 +1,334 @@
+/*
+ * fs/proc/filecache.c
+ *
+ * Copyright (C) 2006, 2007 Fengguang Wu <wfg@mail.ustc.edu.cn>
+ * Copyright (C) 2009 KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/radix-tree.h>
+#include <linux/page-flags.h>
+#include <linux/pagevec.h>
+#include <linux/pagemap.h>
+#include <linux/vmalloc.h>
+#include <linux/writeback.h>
+#include <linux/buffer_head.h>
+#include <linux/parser.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/file.h>
+#include <linux/namei.h>
+#include <linux/module.h>
+#include <linux/backing-dev.h>
+
+#include <asm/uaccess.h>
+
+/* Internal buffer sizes. The larger the more effcient. */
+#define SBUF_SIZE (128<<10)
+#define IWIN_PAGE_ORDER 3
+#define IWIN_SIZE ((PAGE_SIZE<<IWIN_PAGE_ORDER) / sizeof(struct inode *))
+
+struct fcache_read_state {
+ /* inode at last pos */
+ struct {
+ unsigned long pos;
+ struct inode *inode;
+ } ipos;
+
+ /* inode window */
+ struct {
+ unsigned long cursor;
+ unsigned long origin;
+ unsigned long size;
+ struct inode **inodes;
+ } iwin;
+};
+
+static int may_show_inode(struct fcache_read_state *s, struct inode *inode)
+{
+ if (!atomic_read(&inode->i_count))
+ return 0;
+ if (inode->i_state & (I_FREEING|I_CLEAR|I_WILL_FREE))
+ return 0;
+ if (!inode->i_mapping)
+ return 0;
+
+ if (!inode->i_mapping->nrpages)
+ return 0;
+
+ if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
+ S_ISLNK(inode->i_mode) || S_ISBLK(inode->i_mode)))
+ return 0;
+
+ return 1;
+}
+
+/*
+ * Full: there are more data following.
+ */
+static int iwin_full(struct fcache_read_state *s)
+{
+ return !s->iwin.cursor ||
+ s->iwin.cursor > s->iwin.origin + s->iwin.size;
+}
+
+static int iwin_push(struct fcache_read_state *s, struct inode *inode)
+{
+ if (!may_show_inode(s, inode))
+ return 0;
+
+ s->iwin.cursor++;
+
+ if (s->iwin.size >= IWIN_SIZE)
+ return 1;
+
+ if (s->iwin.cursor > s->iwin.origin)
+ s->iwin.inodes[s->iwin.size++] = inode;
+ return 0;
+}
+
+/*
+ * Travease the inode lists in order - newest first.
+ * And fill @s->iwin.inodes with inodes positioned in [@pos, @pos+IWIN_SIZE).
+ */
+static int iwin_fill(struct fcache_read_state *s, unsigned long pos)
+{
+ struct inode *inode;
+ struct backing_dev_info *bdi;
+
+ s->iwin.origin = pos;
+ s->iwin.cursor = 0;
+ s->iwin.size = 0;
+
+ spin_lock_bh(&bdi_lock);
+ list_for_each_entry(bdi, &bdi_list, bdi_list) {
+ list_for_each_entry(inode, &bdi->wb.b_dirty, i_list) {
+ if (iwin_push(s, inode))
+ goto out_full_unlock;
+ }
+ list_for_each_entry(inode, &bdi->wb.b_io, i_list) {
+ if (iwin_push(s, inode))
+ goto out_full_unlock;
+ }
+ }
+ spin_unlock_bh(&bdi_lock);
+
+ list_for_each_entry(inode, &inode_in_use, i_list) {
+ if (iwin_push(s, inode))
+ goto out_full;
+ ;
+ }
+
+ list_for_each_entry(inode, &inode_unused, i_list) {
+ if (iwin_push(s, inode))
+ goto out_full;
+ }
+
+ return 0;
+
+out_full_unlock:
+ spin_unlock_bh(&bdi_lock);
+out_full:
+ return 1;
+}
+
+static struct inode* iwin_inode(struct fcache_read_state *s, unsigned long pos)
+{
+ if ((iwin_full(s) && pos >= s->iwin.origin + s->iwin.size)
+ || pos < s->iwin.origin)
+ iwin_fill(s, pos);
+
+ if (pos >= s->iwin.cursor)
+ return NULL;
+
+ s->ipos.pos = pos;
+ s->ipos.inode = s->iwin.inodes[pos - s->iwin.origin];
+ BUG_ON(!s->ipos.inode);
+
+ return s->ipos.inode;
+}
+
+static void show_inode(struct seq_file *m, struct inode *inode)
+{
+ char state[] = "--"; /* dirty, locked */
+ struct dentry *dentry;
+ unsigned long size = DIV_ROUND_UP(i_size_read(inode), PAGE_SIZE);
+ unsigned long nrpages;
+ int percent = 0;
+ int refcnt;
+ int len;
+
+ if (inode->i_mapping)
+ nrpages = inode->i_mapping->nrpages;
+ else {
+ nrpages = 0;
+ WARN_ON(1);
+ }
+
+ if (size)
+ percent = 100 * nrpages / size;
+
+ if (inode->i_state & (I_DIRTY_DATASYNC|I_DIRTY_PAGES))
+ state[0] = 'D';
+ else if (inode->i_state & I_DIRTY_SYNC)
+ state[0] = 'd';
+
+ if (inode->i_state & I_LOCK)
+ state[1] = 'L';
+
+ refcnt = 0;
+ list_for_each_entry(dentry, &inode->i_dentry, d_alias) {
+ refcnt += atomic_read(&dentry->d_count);
+ }
+
+ seq_printf(m, "%10lu %10lu %8lu %7d %6d %5s %02x:%02x(%.5s)%n",
+ inode->i_ino,
+ size << (PAGE_CACHE_SHIFT - 10),
+ nrpages << (PAGE_CACHE_SHIFT - 10),
+ percent,
+ refcnt,
+ state,
+ MAJOR(inode->i_sb->s_dev),
+ MINOR(inode->i_sb->s_dev),
+ inode->i_sb->s_id,
+ &len);
+
+ seq_printf(m, "%*c", 65 - len, ' ');
+
+ seq_printf(m, "%.7o ",
+ inode->i_mode);
+
+ if (list_empty(&inode->i_dentry)) {
+ if (!atomic_read(&inode->i_count))
+ seq_puts(m, "(noname)\n");
+ else
+ seq_printf(m, "(%02x:%02x)\n",
+ imajor(inode), iminor(inode));
+ } else {
+ struct path path = {
+ .mnt = NULL,
+ .dentry = list_entry(inode->i_dentry.next,
+ struct dentry, d_alias)
+ };
+
+ seq_path(m, &path, "\t\n\\");
+ seq_putc(m, '\n');
+ }
+}
+
+static int ii_show(struct seq_file *m, void *v)
+{
+ unsigned long index = *(loff_t *) v;
+ struct fcache_read_state *s = m->private;
+ struct inode *inode;
+
+ if (index == 0) {
+ seq_puts(m, "# ino size cached cached% "
+ "refcnt state dev mode file\n");
+ }
+
+ inode = iwin_inode(s, index);
+ show_inode(m, inode);
+
+ return 0;
+}
+
+static void *ii_start(struct seq_file *m, loff_t *pos)
+{
+ struct fcache_read_state *s = m->private;
+
+ s->iwin.size = 0;
+ s->iwin.inodes = (struct inode **)
+ __get_free_pages(GFP_KERNEL, IWIN_PAGE_ORDER);
+ if (!s->iwin.inodes)
+ return NULL;
+
+ spin_lock(&inode_lock);
+
+ return iwin_inode(s, *pos) ? pos : NULL;
+}
+
+static void *ii_next(struct seq_file *m, void *v, loff_t *pos)
+{
+ struct fcache_read_state *s = m->private;
+
+ (*pos)++;
+ return iwin_inode(s, *pos) ? pos : NULL;
+}
+
+static void ii_stop(struct seq_file *m, void *v)
+{
+ struct fcache_read_state *s = m->private;
+
+ if (!s->iwin.inodes)
+ return; /* we don't have inode_lock */
+
+ spin_unlock(&inode_lock);
+ free_pages((unsigned long) s->iwin.inodes, IWIN_PAGE_ORDER);
+}
+
+static struct seq_operations ii_op = {
+ .start = ii_start,
+ .next = ii_next,
+ .stop = ii_stop,
+ .show = ii_show,
+};
+
+/*
+ * Proc file operations.
+ */
+static int filecache_open(struct inode *inode, struct file *proc_file)
+{
+ struct seq_file *m;
+ struct fcache_read_state *s;
+ int ret;
+
+ s = kmalloc(sizeof(*s), GFP_KERNEL);
+ if (!s) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ ret = seq_open(proc_file, &ii_op);
+ if (ret) {
+ kfree(s);
+ goto out;
+ }
+
+ m = proc_file->private_data;
+ m->private = s;
+
+out:
+ return ret;
+}
+
+static int filecache_release(struct inode *inode, struct file *proc_file)
+{
+ struct seq_file *seq = proc_file->private_data;
+ struct fcache_read_state *s = seq ? seq->private : NULL;
+ int ret;
+
+ kfree(s);
+ ret = seq_release(inode, proc_file);
+ return ret;
+}
+
+static struct file_operations proc_filecache_fops = {
+ .open = filecache_open,
+ .release = filecache_release,
+ .read = seq_read,
+ .llseek = seq_lseek,
+};
+
+
+static __init int filecache_init(void)
+{
+ proc_create("filecache", 0600, NULL, &proc_filecache_fops);
+ return 0;
+}
+module_init(filecache_init);
[-- Attachment #3: 0001-Add-recent-rotated-scanned-info-to-proc-zoneinfo.patch --]
[-- Type: application/octet-stream, Size: 1049 bytes --]
From 53d1d55e95591891102cd7f1c3404f447e83dfd0 Mon Sep 17 00:00:00 2001
From: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
Date: Thu, 19 Nov 2009 23:19:39 +0900
Subject: [PATCH] Add recent-rotated/scanned info to /proc/zoneinfo
Signed-off-by: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
---
mm/vmstat.c | 11 +++++++++++
1 files changed, 11 insertions(+), 0 deletions(-)
diff --git a/mm/vmstat.c b/mm/vmstat.c
index 889254f..9bf9451 100644
--- a/mm/vmstat.c
+++ b/mm/vmstat.c
@@ -765,6 +765,17 @@ static void zoneinfo_show_print(struct seq_file *m, pg_data_t *pgdat,
zone->prev_priority,
zone->zone_start_pfn,
zone->inactive_ratio);
+
+ seq_printf(m,
+ "\n recent_rotated_anon: %lu"
+ "\n recent_scanned_anon: %lu"
+ "\n recent_rotated_file: %lu"
+ "\n recent_scanned_file: %lu",
+ zone->reclaim_stat.recent_rotated[0],
+ zone->reclaim_stat.recent_scanned[0],
+ zone->reclaim_stat.recent_rotated[1],
+ zone->reclaim_stat.recent_scanned[1]);
+
seq_putc(m, '\n');
}
--
1.6.2.5
next prev parent reply other threads:[~2009-11-19 14:36 UTC|newest]
Thread overview: 26+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-10-05 1:16 complete IO hang since a few kernel revision Norbert Preining
2009-10-05 2:57 ` Ulrich Lukas
2009-10-05 8:33 ` Norbert Preining
2009-10-06 2:00 ` Robert Hancock
2009-10-06 2:05 ` Norbert Preining
2009-10-06 7:11 ` Mike Galbraith
2009-10-06 7:16 ` Norbert Preining
2009-10-06 7:44 ` Mike Galbraith
2009-10-10 19:06 ` Petr Titěra
2009-11-18 7:56 ` Linux 2.6.31 - very swap-happy with plenty of free RAM Dan Merillat
2009-11-18 15:22 ` Rik van Riel
2009-11-18 15:48 ` Norbert Preining
2009-11-19 14:36 ` KOSAKI Motohiro [this message]
2009-11-25 23:13 ` Dan Merillat
2009-11-26 1:54 ` Rik van Riel
2009-12-03 4:16 ` Dan Merillat
2009-12-07 20:49 ` Dan Merillat
2009-12-09 20:48 ` Henrique de Moraes Holschuh
2009-12-09 21:18 ` Rik van Riel
2009-11-18 21:45 Tomasz Chmielewski
2009-11-19 0:40 ` Dan Merillat
2009-11-19 1:09 ` Sven-Haegar Koch
2009-11-19 1:38 ` Dave Chinner
2009-11-19 6:43 ` Tomasz Chmielewski
2009-11-23 21:57 ` Dan Merillat
2009-11-27 1:56 ` Bill Davidsen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=2f11576a0911190636vd21069bv2fe4f22a57b3d333@mail.gmail.com \
--to=kosaki.motohiro@gmail.com \
--cc=dan.merillat@gmail.com \
--cc=david@fromorbit.com \
--cc=haegar@sdinet.de \
--cc=linux-kernel@vger.kernel.org \
--cc=mangoo@wpkg.org \
--cc=preining@logic.at \
--cc=riel@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®