From: "Roy Huang" <royhuang9@gmail.com>
To: Aubrey <aubreylee@gmail.com>
Cc: "Nick Piggin" <nickpiggin@yahoo.com.au>,
"Andrew Morton" <akpm@osdl.org>,
"Linus Torvalds" <torvalds@osdl.org>,
"Hua Zhong" <hzhong@gmail.com>, "Hugh Dickins" <hugh@veritas.com>,
linux-kernel@vger.kernel.org, hch@infradead.org,
kenneth.w.chen@intel.com, mjt@tls.msk.ru
Subject: Re: O_DIRECT question
Date: Thu, 11 Jan 2007 16:05:16 +0800 [thread overview]
Message-ID: <afe668f90701110005ya2e8187pc6604c5aad24cc84@mail.gmail.com> (raw)
In-Reply-To: <6d6a94c50701102354l7ab41a3bp4761566204f1d992@mail.gmail.com>
On a embedded systerm, limiting page cache can relieve memory
fragmentation. There is a patch against 2.6.19, which limit every
opened file page cache and total pagecache. When the limit reach, it
will release the page cache overrun the limit.
Index: include/linux/pagemap.h
===================================================================
--- include/linux/pagemap.h (revision 2628)
+++ include/linux/pagemap.h (working copy)
@@ -12,6 +12,7 @@
#include <asm/uaccess.h>
#include <linux/gfp.h>
+extern int total_pagecache_limit;
/*
* Bits in mapping->flags. The lower __GFP_BITS_SHIFT bits are the page
* allocation mode flags.
Index: include/linux/fs.h
===================================================================
--- include/linux/fs.h (revision 2628)
+++ include/linux/fs.h (working copy)
@@ -444,6 +444,10 @@
spinlock_t private_lock; /* for use by the address_space */
struct list_head private_list; /* ditto */
struct address_space *assoc_mapping; /* ditto */
+#ifdef CONFIG_LIMIT_PAGECACHE
+ unsigned long pages_limit;
+ struct list_head page_head;
+#endif
} __attribute__((aligned(sizeof(long))));
/*
* On most architectures that alignment is already the case; but
Index: include/linux/mm.h
===================================================================
--- include/linux/mm.h (revision 2628)
+++ include/linux/mm.h (working copy)
@@ -231,6 +231,9 @@
#else
#define VM_BUG_ON(condition) do { } while(0)
#endif
+#ifdef CONFIG_LIMIT_PAGECACHE
+ struct list_head page_list;
+#endif
/*
* Methods to modify the page usage count.
@@ -1030,7 +1033,21 @@
/* mm/page-writeback.c */
int write_one_page(struct page *page, int wait);
+/* possible outcome of pageout() */
+typedef enum {
+ /* failed to write page out, page is locked */
+ PAGE_KEEP,
+ /* move page to the active list, page is locked */
+ PAGE_ACTIVATE,
+ /* page has been sent to the disk successfully, page is unlocked */
+ PAGE_SUCCESS,
+ /* page is clean and locked */
+ PAGE_CLEAN,
+} pageout_t;
+
+pageout_t pageout(struct page *page, struct address_space *mapping);
+
/* readahead.c */
#define VM_MAX_READAHEAD 128 /* kbytes */
#define VM_MIN_READAHEAD 16 /* kbytes (includes current page) */
Index: init/Kconfig
===================================================================
--- init/Kconfig (revision 2628)
+++ init/Kconfig (working copy)
@@ -419,6 +419,19 @@
option replaces shmem and tmpfs with the much simpler ramfs code,
which may be appropriate on small systems without swap.
+config LIMIT_PAGECACHE
+ bool "Limit page caches" if EMBEDDED
+
+config PAGECACHE_LIMIT
+ int "Page cache limit for every file in page unit"
+ depends on LIMIT_PAGECACHE
+ default 32
+
+config PAGECACHE_LIMIT_TOTAL
+ int "Total page cache limit in MB unit"
+ depends on LIMIT_PAGECACHE
+ default 10
+
choice
prompt "Page frame management algorithm"
default BUDDY
Index: fs/inode.c
===================================================================
--- fs/inode.c (revision 2628)
+++ fs/inode.c (working copy)
@@ -205,6 +205,10 @@
INIT_LIST_HEAD(&inode->inotify_watches);
mutex_init(&inode->inotify_mutex);
#endif
+#ifdef CONFIG_LIMIT_PAGECACHE
+ INIT_LIST_HEAD(&inode->i_data.page_head);
+ inode->i_data.pages_limit = CONFIG_PAGECACHE_LIMIT;
+#endif
}
EXPORT_SYMBOL(inode_init_once);
Index: mm/filemap.c
===================================================================
--- mm/filemap.c (revision 2628)
+++ mm/filemap.c (working copy)
@@ -18,6 +18,7 @@
#include <linux/capability.h>
#include <linux/kernel_stat.h>
#include <linux/mm.h>
+#include <linux/mm_inline.h>
#include <linux/swap.h>
#include <linux/mman.h>
#include <linux/pagemap.h>
@@ -30,6 +31,9 @@
#include <linux/security.h>
#include <linux/syscalls.h>
#include <linux/cpuset.h>
+#include <linux/rmap.h>
+#include <linux/buffer_head.h>
+#include <linux/page-flags.h>
#include "filemap.h"
#include "internal.h"
@@ -119,6 +123,9 @@
radix_tree_delete(&mapping->page_tree, page->index);
page->mapping = NULL;
mapping->nrpages--;
+#ifdef CONFIG_LIMIT_PAGECACHE
+ list_del_init(&page->page_list);
+#endif
__dec_zone_page_state(page, NR_FILE_PAGES);
}
@@ -169,6 +176,96 @@
return 0;
}
+#ifdef CONFIG_LIMIT_PAGECACHE
+static void balance_cache(struct address_space *mapping)
+{
+ /* Release half of the pages */
+ int count ;
+ int nr_released = 0;
+ struct page *page;
+ struct zone *zone= NULL;
+ struct pagevec freed_pvec;
+ struct list_head ret_list;
+
+ count = mapping->nrpages /2;
+ pagevec_init(&freed_pvec, 0);
+ INIT_LIST_HEAD(&ret_list);
+ lru_add_drain();
+ while(count-->0) {
+ page = list_entry(mapping->page_head.prev, struct page, page_list);
+ zone = page_zone(page);
+ TestClearPageLRU(page);
+ if (PageActive(page))
+ del_page_from_active_list(zone, page);
+ else
+ del_page_from_inactive_list(zone, page);
+
+ list_del_init(&page->page_list); /* Remove from current process's
page list */
+ get_page(page);
+
+ if (TestSetPageLocked(page))
+ goto __keep;
+ if (PageWriteback(page))
+ goto __keep_locked;
+ if (page_referenced(page, 1))
+ goto __keep_locked;
+ if (PageDirty(page)) {
+ switch(pageout(page, mapping)) {
+ case PAGE_KEEP:
+ case PAGE_ACTIVATE:
+ goto __keep_locked;
+ case PAGE_SUCCESS:
+ if (PageWriteback(page) || PageDirty(page))
+ goto __keep;
+ if (TestSetPageLocked(page))
+ goto __keep;
+ if (PageDirty(page) || PageWriteback(page))
+ goto __keep_locked;
+ case PAGE_CLEAN:
+ ;
+ }
+ }
+
+ if (PagePrivate(page) && !try_to_release_page(page, GFP_KERNEL))
+ goto __keep_locked;
+ if (!remove_mapping(mapping, page))
+ goto __keep_locked;
+
+ unlock_page(page);
+ nr_released++;
+ /* This page maybe in Active LRU */
+ ClearPageActive(page);
+ ClearPageUptodate(page);
+ if (!pagevec_add(&freed_pvec, page))
+ __pagevec_release_nonlru(&freed_pvec);
+ continue;
+__keep_locked:
+ unlock_page(page);
+__keep:
+ SetPageLRU(page);
+ if (PageActive(page)) {
+ add_page_to_active_list(zone, page);
+ } else {
+ add_page_to_inactive_list(zone, page);
+ }
+
+ list_add(&page->page_list, &ret_list);
+ }
+ while(!list_empty(&ret_list)) {
+ page = list_entry(ret_list.prev, struct page, page_list);
+ list_move_tail(&page->page_list, &mapping->page_head);
+ put_page(page);
+ }
+ if (pagevec_count(&freed_pvec))
+ __pagevec_release_nonlru(&freed_pvec);
+
+ if (global_page_state(NR_FILE_PAGES) > total_pagecache_limit)
+ if (zone) {
+ wakeup_kswapd(zone, 0);
+ }
+}
+#endif
+
/**
* __filemap_fdatawrite_range - start writeback on mapping dirty pages in range
* @mapping: address space structure to write
@@ -448,6 +545,10 @@
page->mapping = mapping;
page->index = offset;
mapping->nrpages++;
+#ifdef CONFIG_LIMIT_PAGECACHE
+ list_add(&page->page_list, &mapping->page_head);
+#endif
+
__inc_zone_page_state(page, NR_FILE_PAGES);
}
write_unlock_irq(&mapping->tree_lock);
@@ -1085,6 +1186,10 @@
page_cache_release(cached_page);
if (filp)
file_accessed(filp);
+#ifdef CONFIG_LIMIT_PAGECACHE
+ if (mapping->nrpages >= mapping->pages_limit)
+ balance_cache(mapping);
+#endif
}
EXPORT_SYMBOL(do_generic_mapping_read);
@@ -2195,6 +2300,11 @@
if (cached_page)
page_cache_release(cached_page);
+#ifdef CONFIG_LIMIT_PAGECACHE
+ if (mapping->nrpages >= mapping->pages_limit)
+ balance_cache(mapping);
+#endif
+
/*
* For now, when the user asks for O_SYNC, we'll actually give O_DSYNC
*/
Index: mm/vmscan.c
===================================================================
--- mm/vmscan.c (revision 2628)
+++ mm/vmscan.c (working copy)
@@ -116,6 +116,7 @@
static LIST_HEAD(shrinker_list);
static DECLARE_RWSEM(shrinker_rwsem);
+int total_pagecache_limit = CONFIG_PAGECACHE_LIMIT_TOTAL * 1024 / 4;
/*
* Add a shrinker callback to be called from the vm
@@ -292,23 +293,11 @@
unlock_page(page);
}
-/* possible outcome of pageout() */
-typedef enum {
- /* failed to write page out, page is locked */
- PAGE_KEEP,
- /* move page to the active list, page is locked */
- PAGE_ACTIVATE,
- /* page has been sent to the disk successfully, page is unlocked */
- PAGE_SUCCESS,
- /* page is clean and locked */
- PAGE_CLEAN,
-} pageout_t;
-
/*
* pageout is called by shrink_page_list() for each dirty page.
* Calls ->writepage().
*/
-static pageout_t pageout(struct page *page, struct address_space *mapping)
+pageout_t pageout(struct page *page, struct address_space *mapping)
{
/*
* If the page is dirty, only perform writeback if that write
@@ -1328,7 +1317,11 @@
order = pgdat->kswapd_max_order;
}
finish_wait(&pgdat->kswapd_wait, &wait);
- balance_pgdat(pgdat, order);
+ if (global_page_state(NR_FILE_PAGES) >= total_pagecache_limit)
+ balance_pgdat(pgdat, (global_page_state(NR_FILE_PAGES) \
+ - total_pagecache_limit), order);
+ else
+ balance_pgdat(pgdat, order);
}
return 0;
}
@@ -1344,8 +1337,10 @@
return;
pgdat = zone->zone_pgdat;
- if (zone_watermark_ok(zone, order, zone->pages_low, 0, 0))
- return;
+ if (zone_watermark_ok(zone, order, zone->pages_low, 0, 0)) {
+ if (global_page_state(NR_FILE_PAGES) < total_pagecache_limit)
+ return;
+ }
if (pgdat->kswapd_max_order < order)
pgdat->kswapd_max_order = order;
if (!cpuset_zone_allowed(zone, __GFP_HARDWALL))
next prev parent reply other threads:[~2007-01-11 8:05 UTC|newest]
Thread overview: 130+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-01-11 2:57 Aubrey
2007-01-11 3:05 ` Linus Torvalds
2007-01-11 3:15 ` Linus Torvalds
2007-01-11 6:09 ` Nick Piggin
2007-01-11 15:50 ` Linus Torvalds
2007-01-11 16:19 ` Aubrey
2007-01-16 3:41 ` Jörn Engel
2007-01-11 16:23 ` bert hubert
2007-01-11 16:52 ` Xavier Bestel
2007-01-11 17:04 ` Linus Torvalds
2007-01-11 18:41 ` Trond Myklebust
2007-01-11 19:00 ` Linus Torvalds
2007-01-11 19:49 ` Trond Myklebust
2007-01-12 17:03 ` Viktor
2007-01-20 16:19 ` Denis Vlasenko
2007-01-22 15:52 ` Phillip Susi
2007-01-11 5:50 ` Aubrey
2007-01-11 6:06 ` Andrew Morton
2007-01-11 6:45 ` Aubrey
2007-01-11 6:57 ` Andrew Morton
2007-01-11 7:05 ` Nick Piggin
2007-01-11 7:54 ` Aubrey
2007-01-11 8:05 ` Roy Huang [this message]
2007-01-11 16:45 ` Linus Torvalds
2007-01-17 4:29 ` Aubrey Li
2007-01-12 2:12 ` Aubrey
2007-01-12 2:47 ` Nick Piggin
2007-01-12 3:59 ` Roy Huang
2007-01-11 8:12 ` Nick Piggin
2007-01-11 8:49 ` Roy Huang
2007-01-11 9:09 ` Nick Piggin
2007-01-12 2:48 ` Bill Davidsen
2007-01-12 4:30 ` Nick Piggin
2007-01-12 4:46 ` Linus Torvalds
2007-01-12 4:56 ` Nick Piggin
2007-01-12 4:58 ` Nick Piggin
2007-01-12 5:18 ` Linus Torvalds
2007-01-12 5:22 ` Aubrey
2007-01-12 14:59 ` Bill Davidsen
2007-01-13 4:51 ` Nick Piggin
2007-01-11 6:16 ` Alexander Shishkin
2007-01-11 6:57 ` Aubrey
2007-01-11 12:13 ` Viktor
2007-01-11 15:53 ` Phillip Susi
2007-01-11 16:20 ` Linus Torvalds
2007-01-11 17:13 ` Michael Tokarev
2007-01-11 23:01 ` Phillip Susi
2007-01-11 23:06 ` Hua Zhong
2007-01-12 15:21 ` Phillip Susi
2007-01-20 16:36 ` Denis Vlasenko
2007-01-20 20:55 ` Michael Tokarev
2007-01-20 23:05 ` Denis Vlasenko
2007-01-21 12:09 ` Michael Tokarev
2007-01-21 20:02 ` Denis Vlasenko
2007-01-22 16:17 ` Phillip Susi
2007-01-24 21:15 ` Denis Vlasenko
2007-01-25 15:44 ` Phillip Susi
2007-01-25 17:38 ` Denis Vlasenko
2007-01-25 19:28 ` Phillip Susi
2007-01-25 19:52 ` Denis Vlasenko
2007-01-25 20:03 ` Phillip Susi
2007-01-25 20:45 ` Michael Tokarev
2007-01-25 21:11 ` Denis Vlasenko
2007-01-26 16:02 ` Mark Lord
2007-01-26 16:52 ` Viktor
2007-01-26 16:58 ` Phillip Susi
2007-01-26 17:05 ` Phillip Susi
2007-01-26 23:16 ` Denis Vlasenko
2007-02-06 20:39 ` Pavel Machek
2007-01-26 18:23 ` Bill Davidsen
2007-01-26 23:35 ` Denis Vlasenko
2007-01-28 15:18 ` Bill Davidsen
2007-01-28 17:03 ` Denis Vlasenko
2007-01-29 15:43 ` Phillip Susi
2007-01-29 17:00 ` Andrea Arcangeli
2007-01-30 0:05 ` Denis Vlasenko
[not found] ` <45BE7D99.70200@cfl.rr.com>
[not found] ` <20070130023056.GN8030@opteron.random>
[not found] ` <45BF65E3.6070102@cfl.rr.com>
[not found] ` <20070130164806.GQ8030@opteron.random>
2007-01-30 18:50 ` Phillip Susi
2007-01-30 19:57 ` Andrea Arcangeli
2007-01-30 20:06 ` Andrea Arcangeli
2007-01-30 23:07 ` Phillip Susi
2007-01-31 2:28 ` Andrea Arcangeli
2007-01-31 9:37 ` Michael Tokarev
2007-01-26 15:53 ` Bill Davidsen
2007-01-11 17:42 ` Alan
2007-01-11 18:00 ` Linus Torvalds
2007-01-12 7:57 ` dean gaudet
2007-01-12 15:27 ` Phillip Susi
2007-01-12 18:06 ` Linus Torvalds
2007-01-12 20:23 ` Chris Mason
2007-01-12 20:46 ` Michael Tokarev
2007-01-12 20:52 ` Michael Tokarev
2007-01-12 21:03 ` Michael Tokarev
2007-01-12 21:17 ` Linus Torvalds
2007-01-12 21:54 ` Michael Tokarev
2007-01-12 22:09 ` Linus Torvalds
2007-01-12 22:26 ` Michael Tokarev
2007-01-12 22:35 ` Erik Andersen
2007-01-12 22:47 ` Andrew Morton
2007-01-14 9:11 ` Nate Diller
2007-01-20 16:45 ` Denis Vlasenko
2007-01-22 1:47 ` Andrea Arcangeli
2007-01-13 20:07 ` Bill Davidsen
2007-01-13 20:27 ` Michael Tokarev
2007-01-14 15:39 ` Bill Davidsen
2007-01-12 21:39 ` Disk Cache, Was: " Zan Lynx
2007-01-12 22:10 ` Michael Tokarev
2007-01-15 12:11 ` Helge Hafting
2007-01-12 16:59 ` Viktor
2007-01-11 12:45 ` Erik Mouw
2007-01-11 4:51 ` Andrew Morton
2007-01-11 5:06 ` Gerrit Huizenga
2007-01-11 16:09 ` Badari Pulavarty
2007-01-11 12:34 ` linux-os (Dick Johnson)
2007-01-11 13:06 ` Martin Mares
2007-01-11 14:15 ` Jens Axboe
2007-01-12 2:13 ` Bill Davidsen
2007-01-17 14:27 Alex Tomas
2007-01-22 15:59 Al Boldi
[not found] <7BYkO-5OV-17@gated-at.bofh.it>
[not found] ` <7BYul-6gz-5@gated-at.bofh.it>
[not found] ` <7C18X-1zo-5@gated-at.bofh.it>
[not found] ` <7C1iw-22q-7@gated-at.bofh.it>
[not found] ` <7C1Vb-2Ny-3@gated-at.bofh.it>
[not found] ` <7C256-2ZR-27@gated-at.bofh.it>
[not found] ` <7C2eE-3rT-15@gated-at.bofh.it>
[not found] ` <7C31d-4qb-11@gated-at.bofh.it>
[not found] ` <7C3kj-55E-9@gated-at.bofh.it>
2007-01-11 13:20 ` Bodo Eggert
[not found] ` <7C74B-2A4-23@gated-at.bofh.it>
[not found] ` <7CaYA-mT-19@gated-at.bofh.it>
[not found] ` <7Cpuz-64X-1@gated-at.bofh.it>
[not found] ` <7Cz0T-4PH-17@gated-at.bofh.it>
[not found] ` <7CBcl-86B-9@gated-at.bofh.it>
[not found] ` <7CBvH-52-9@gated-at.bofh.it>
[not found] ` <7CBFn-hw-1@gated-at.bofh.it>
[not found] ` <7CBP1-KI-3@gated-at.bofh.it>
[not found] ` <7CBYG-WK-3@gated-at.bofh.it>
2007-01-13 16:53 ` Bodo Eggert
2007-01-13 19:30 ` Bill Davidsen
2007-01-14 18:51 ` Bodo Eggert
[not found] ` <7CXmz-88G-29@gated-at.bofh.it>
[not found] ` <7CXFR-8vZ-15@gated-at.bofh.it>
[not found] ` <7DfMP-2ak-19@gated-at.bofh.it>
2007-01-14 19:39 ` Bodo Eggert
[not found] ` <7DyYK-6lE-3@gated-at.bofh.it>
2007-01-16 20:26 ` Bodo Eggert
2007-01-17 5:55 ` Arjan van de Ven
2007-01-17 22:36 ` Bodo Eggert
[not found] ` <7HkaQ-2Nb-9@gated-at.bofh.it>
[not found] ` <7HDZP-Pv-1@gated-at.bofh.it>
[not found] ` <7HIPV-8kp-35@gated-at.bofh.it>
2007-01-27 14:01 ` Bodo Eggert
2007-01-27 14:14 ` Denis Vlasenko
2007-01-28 15:30 ` Bill Davidsen
2007-01-28 17:18 ` Denis Vlasenko
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=afe668f90701110005ya2e8187pc6604c5aad24cc84@mail.gmail.com \
--to=royhuang9@gmail.com \
--cc=akpm@osdl.org \
--cc=aubreylee@gmail.com \
--cc=hch@infradead.org \
--cc=hugh@veritas.com \
--cc=hzhong@gmail.com \
--cc=kenneth.w.chen@intel.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mjt@tls.msk.ru \
--cc=nickpiggin@yahoo.com.au \
--cc=torvalds@osdl.org \
/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®