readability patch for 2.1.109 mm/filemap.c

Bill Hawes (whawes@star.net)
Fri, 17 Jul 1998 14:09:19 -0400


This is a multi-part message in MIME format.
--------------F1C6C2B8DB9F4C09C7A9A41E
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

I've attached a patch to rework the shrink_mmap() code to improve its
readability. It splits out the code for releasing a page into an inline
shrink_one_page(), which helps clarify the logic for selecting the pages
in shrink_mmap().

The patch also moves the code for removing a page from the inode cache
into a remove_inode_page() routine. This operation is now performed in a
number of places in the kernel, and I think it would be better to define
a function for it.

I know that we're in a code freeze for 2.1, but I hope you're still
interested in small patches to simplify and polish the code.

Regards,
Bill
--------------F1C6C2B8DB9F4C09C7A9A41E
Content-Type: text/plain; charset=us-ascii; name="mm_filemap109-patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="mm_filemap109-patch"

--- linux-2.1.109/include/linux/mm.h.old Fri Jul 17 09:34:42 1998
+++ linux-2.1.109/include/linux/mm.h Fri Jul 17 10:19:21 1998
@@ -298,6 +298,7 @@
extern int do_munmap(unsigned long, size_t);

/* filemap.c */
+extern void remove_inode_page(struct page *);
extern unsigned long page_unuse(struct page *);
extern int shrink_mmap(int, int);
extern void truncate_inode_pages(struct inode *, unsigned long);
--- linux-2.1.109/mm/filemap.c.old Fri Jul 17 09:10:45 1998
+++ linux-2.1.109/mm/filemap.c Fri Jul 17 10:19:21 1998
@@ -117,12 +117,98 @@
}
}

+/*
+ * Remove a page from the page cache and free it.
+ */
+void remove_inode_page(struct page *page)
+{
+ remove_page_from_hash_queue(page);
+ remove_page_from_inode_queue(page);
+ __free_page(page);
+}
+
+/*
+ * Check whether we can free this page.
+ */
+static inline int shrink_one_page(struct page *page, int gfp_mask)
+{
+ struct buffer_head *tmp, *bh;
+
+ if (PageLocked(page))
+ goto next;
+ if ((gfp_mask & __GFP_DMA) && !PageDMA(page))
+ goto next;
+ /* First of all, regenerate the page's referenced bit
+ * from any buffers in the page
+ */
+ bh = page->buffers;
+ if (bh) {
+ tmp = bh;
+ do {
+ if (buffer_touched(tmp)) {
+ clear_bit(BH_Touched, &tmp->b_state);
+ set_bit(PG_referenced, &page->flags);
+ }
+ tmp = tmp->b_this_page;
+ } while (tmp != bh);
+
+ /* Refuse to swap out all buffer pages */
+ if ((buffermem >> PAGE_SHIFT) * 100 < (buffer_mem.min_percent * num_physpages))
+ goto next;
+ }
+
+ /* We can't throw away shared pages, but we do mark
+ them as referenced. This relies on the fact that
+ no page is currently in both the page cache and the
+ buffer cache; we'd have to modify the following
+ test to allow for that case. */
+
+ switch (atomic_read(&page->count)) {
+ case 1:
+ /* is it a swap-cache or page-cache page? */
+ if (page->inode) {
+ if (test_and_clear_bit(PG_referenced, &page->flags)) {
+ touch_page(page);
+ break;
+ }
+ age_page(page);
+ if (page->age)
+ break;
+ if (page_cache_size * 100 < (page_cache.min_percent * num_physpages))
+ break;
+ if (PageSwapCache(page)) {
+ delete_from_swap_cache(page);
+ return 1;
+ }
+ remove_inode_page(page);
+ return 1;
+ }
+ /* It's not a cache page, so we don't do aging.
+ * If it has been referenced recently, don't free it */
+ if (test_and_clear_bit(PG_referenced, &page->flags))
+ break;
+
+ /* is it a buffer cache page? */
+ if ((gfp_mask & __GFP_IO) && bh && try_to_free_buffer(bh, &bh, 6))
+ return 1;
+ break;
+
+ default:
+ /* more than one user: we can't throw it away */
+ set_bit(PG_referenced, &page->flags);
+ /* fall through */
+ case 0:
+ /* nothing */
+ }
+next:
+ return 0;
+}
+
int shrink_mmap(int priority, int gfp_mask)
{
static unsigned long clock = 0;
- struct page * page;
unsigned long limit = num_physpages;
- struct buffer_head *tmp, *bh;
+ struct page * page;
int count_max, count_min;

count_max = (limit<<2) >> (priority>>1);
@@ -130,76 +216,11 @@

page = mem_map + clock;
do {
+ if (shrink_one_page(page, gfp_mask))
+ return 1;
count_max--;
if (page->inode || page->buffers)
count_min--;
-
- if (PageLocked(page))
- goto next;
- if ((gfp_mask & __GFP_DMA) && !PageDMA(page))
- goto next;
- /* First of all, regenerate the page's referenced bit
- from any buffers in the page */
- bh = page->buffers;
- if (bh) {
- tmp = bh;
- do {
- if (buffer_touched(tmp)) {
- clear_bit(BH_Touched, &tmp->b_state);
- set_bit(PG_referenced, &page->flags);
- }
- tmp = tmp->b_this_page;
- } while (tmp != bh);
-
- /* Refuse to swap out all buffer pages */
- if ((buffermem >> PAGE_SHIFT) * 100 < (buffer_mem.min_percent * num_physpages))
- goto next;
- }
-
- /* We can't throw away shared pages, but we do mark
- them as referenced. This relies on the fact that
- no page is currently in both the page cache and the
- buffer cache; we'd have to modify the following
- test to allow for that case. */
-
- switch (atomic_read(&page->count)) {
- case 1:
- /* is it a swap-cache or page-cache page? */
- if (page->inode) {
- if (test_and_clear_bit(PG_referenced, &page->flags)) {
- touch_page(page);
- break;
- }
- age_page(page);
- if (page->age || page_cache_size * 100 < (page_cache.min_percent * num_physpages))
- break;
- if (PageSwapCache(page)) {
- delete_from_swap_cache(page);
- return 1;
- }
- remove_page_from_hash_queue(page);
- remove_page_from_inode_queue(page);
- __free_page(page);
- return 1;
- }
- /* It's not a cache page, so we don't do aging.
- * If it has been referenced recently, don't free it */
- if (test_and_clear_bit(PG_referenced, &page->flags))
- break;
-
- /* is it a buffer cache page? */
- if ((gfp_mask & __GFP_IO) && bh && try_to_free_buffer(bh, &bh, 6))
- return 1;
- break;
-
- default:
- /* more than one users: we can't throw it away */
- set_bit(PG_referenced, &page->flags);
- /* fall through */
- case 0:
- /* nothing */
- }
-next:
page++;
clock++;
if (clock >= limit) {
@@ -226,9 +247,7 @@
return count;
if (PageSwapCache(page))
panic ("Doing a normal page_unuse of a swap cache page");
- remove_page_from_hash_queue(page);
- remove_page_from_inode_queue(page);
- __free_page(page);
+ remove_inode_page(page);
return 1;
}

--------------F1C6C2B8DB9F4C09C7A9A41E--

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.altern.org/andrebalsa/doc/lkml-faq.html