[RFC][PATCH] page->mapping clarification [1/3] base functions

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Rebased to 2.6.23-rc6-mm1 and reflected comments.
Not so aggresive as previous version.
(I'm not in a hurry if -mm is busy.)

Any comments are welcome.

Thanks,
-Kame
==
A clarification of page <-> fs interface (page cache).

At first, each FS has to access to struct page->mapping directly.
But it's not just pointer. (we use special 1bit enconding for anon.)

Although there is historical consensus that page->mapping points to its inode's
address space, I think adding some neat helper functon is not bad.

This patch adds page-cache.h which containes page<->address_space<->inode
function which is required (used) by subsystems.

Following functions are added

 * page_mapping_cache() ... returns address space if a page is page cache
 * page_mapping_anon()  ... returns anon_vma if a page is anonymous page.
 * page_is_pagecache()  ... returns true if a page is page-cache.
 * page_inode()         ... returns inode which a page-cache belongs to.
 * is_page_consistent() ... returns true if a page is still valid page cache 

Followings are moved 
 * page_mapping()       ... returns swapper_space or address_space a page is on.
			    (from mm.h)
 * page_index()         ... returns position of a page in its inode
			    (from mm.h)
 * remove_mapping()     ... a safe routine to remove page->mapping from page.
			    (from swap.h)

Changelog V1 -> V2:
 - for 2.6.23-rc6-mm1.
 - use bool type.
 - moved related functions to page-cache.h
 - renamed some functions.

Signed-off-by: KAMEZAWA Hiroyuki <[email protected]>

---
 include/linux/fs.h         |    6 +-
 include/linux/mm.h         |   40 ---------------
 include/linux/page-cache.h |  118 +++++++++++++++++++++++++++++++++++++++++++++
 include/linux/swap.h       |    1 
 4 files changed, 123 insertions(+), 42 deletions(-)

Index: linux-2.6.23-rc6-mm1/include/linux/page-cache.h
===================================================================
--- /dev/null
+++ linux-2.6.23-rc6-mm1/include/linux/page-cache.h
@@ -0,0 +1,118 @@
+#ifndef _LINUX_PAGE_CACHE_H
+#define _LINUX_PAGE_CACHE_H
+#ifdef __KERNEL__
+
+#include <linux/mm.h>
+#include <linux/fs.h>
+#include <linux/rmap.h>
+/*
+ * This file defines interface function among page-cache and FS.
+ *
+ * page_mapping()       ... returns swapper_space or address_space a page is on.
+ *                          Will be used by routines walks by LRU.
+ * page_mapping_cache() ... returns address space if a page is page cache
+ *                          Will be used by FS.
+ * page_mapping_anon()  ... returns anon_vma if a page is anonymous page.
+ *                          Will be used by VM subsystem
+ * page_is_pagecache()  ... returns true if a page is page-cache.
+ * page_inode()         ... returns inode which a page-cache belongs to.
+ * page_index()         ... returns position of a page in its inode
+ * is_page_consistent() ... returns true if a page is still valid on specified
+ *                          address space.
+ * remove_mapping()     ... a safe routine to remove page->mapping from page.
+ */
+extern  struct address_space swapper_space;
+
+/*
+ * On an anonymous page mapped into a user virtual memory area,
+ * page->mapping points to its anon_vma, not to a struct address_space;
+ * with the PAGE_MAPPING_ANON bit set to distinguish it.
+ *
+ * Please note that, confusingly, "page_mapping" refers to the inode
+ * address_space which maps the page from disk; whereas "page_mapped"
+ * refers to user virtual address space into which the page is mapped.
+ */
+#define PAGE_MAPPING_ANON       1
+
+static inline bool PageAnon(struct page *page)
+{
+	return (((unsigned long)page->mapping & PAGE_MAPPING_ANON) != 0);
+}
+
+static inline struct anon_vma *page_mapping_anon(struct page *page)
+{
+	if (!page->mapping || !PageAnon(page))
+		return NULL;
+	return (struct anon_vma *)
+		((unsigned long)page->mapping - PAGE_MAPPING_ANON);
+}
+
+static inline struct address_space *page_mapping_cache(struct page *page)
+{
+	if (!page->mapping || PageAnon(page))
+		return NULL;
+	return page->mapping;
+}
+
+/*
+ * Automatically detect 'what the page is' and returns address_space.
+ *
+ * If page is swap cache, returns &swapper_space.
+ * If page is page cache, returns inode's address space it belongs to
+ * If page is anon, returns NULL.
+ */
+
+static inline struct address_space *page_mapping(struct page *page)
+{
+	struct address_space *mapping = page->mapping;
+
+	VM_BUG_ON(PageSlab(page));
+	if (unlikely(PageSwapCache(page)))
+		mapping = &swapper_space;
+#ifdef CONFIG_SLUB
+	else if (unlikely(PageSlab(page)))
+		mapping = NULL;
+#endif
+        else if (unlikely((unsigned long)mapping & PAGE_MAPPING_ANON))
+		mapping = NULL;
+        return mapping;
+
+}
+
+static inline bool page_is_pagecache(struct page *page)
+{
+	return (page_mapping_cache(page) != NULL);
+}
+
+static inline struct inode *page_inode(struct page *page)
+{
+	if (!page_is_pagecache(page))
+		return NULL;
+	return page_mapping_cache(page)->host;
+}
+/*
+ * Return the pagecache index of the passed page.  Regular pagecache pages
+ * use ->index whereas swapcache pages use ->private
+ */
+static inline pgoff_t page_index(struct page *page)
+{
+	if (unlikely(PageSwapCache(page)))
+		return page_private(page);
+	return page->index;
+}
+
+/*
+ * Returns true if a page is belongs to mapping.
+ */
+static inline bool
+is_page_consistent(struct page *page, struct address_space *mapping)
+{
+	struct address_space *check = page_mapping_cache(page);
+	return (check == mapping);
+}
+
+/* defined in mm/vmscan.c. Must be called under lock_page(). */
+extern int remove_mapping(struct address_space *mapping, struct page *page);
+
+#endif /* __KERNEL__ */
+#endif /* _LINUX_PAGE_CACHE_H */
Index: linux-2.6.23-rc6-mm1/include/linux/mm.h
===================================================================
--- linux-2.6.23-rc6-mm1.orig/include/linux/mm.h
+++ linux-2.6.23-rc6-mm1/include/linux/mm.h
@@ -550,46 +550,6 @@ void page_address_init(void);
 #endif
 
 /*
- * On an anonymous page mapped into a user virtual memory area,
- * page->mapping points to its anon_vma, not to a struct address_space;
- * with the PAGE_MAPPING_ANON bit set to distinguish it.
- *
- * Please note that, confusingly, "page_mapping" refers to the inode
- * address_space which maps the page from disk; whereas "page_mapped"
- * refers to user virtual address space into which the page is mapped.
- */
-#define PAGE_MAPPING_ANON	1
-
-extern struct address_space swapper_space;
-static inline struct address_space *page_mapping(struct page *page)
-{
-	struct address_space *mapping = page->mapping;
-
-	VM_BUG_ON(PageSlab(page));
-	if (unlikely(PageSwapCache(page)))
-		mapping = &swapper_space;
-	else if (unlikely((unsigned long)mapping & PAGE_MAPPING_ANON))
-		mapping = NULL;
-	return mapping;
-}
-
-static inline int PageAnon(struct page *page)
-{
-	return ((unsigned long)page->mapping & PAGE_MAPPING_ANON) != 0;
-}
-
-/*
- * Return the pagecache index of the passed page.  Regular pagecache pages
- * use ->index whereas swapcache pages use ->private
- */
-static inline pgoff_t page_index(struct page *page)
-{
-	if (unlikely(PageSwapCache(page)))
-		return page_private(page);
-	return page->index;
-}
-
-/*
  * The atomic page->_mapcount, like _count, starts from -1:
  * so that transitions both from it and to it can be tracked,
  * using atomic_inc_and_test and atomic_add_negative(-1).
Index: linux-2.6.23-rc6-mm1/include/linux/fs.h
===================================================================
--- linux-2.6.23-rc6-mm1.orig/include/linux/fs.h
+++ linux-2.6.23-rc6-mm1/include/linux/fs.h
@@ -517,12 +517,16 @@ struct address_space {
 	struct list_head	private_list;	/* ditto */
 	struct address_space	*assoc_mapping;	/* ditto */
 } __attribute__((aligned(sizeof(long))));
+
+
+#include <linux/page-cache.h>
+
+
 	/*
 	 * On most architectures that alignment is already the case; but
 	 * must be enforced here for CRIS, to let the least signficant bit
 	 * of struct page's "mapping" pointer be used for PAGE_MAPPING_ANON.
 	 */
-
 struct block_device {
 	dev_t			bd_dev;  /* not a kdev_t - it's a search key */
 	struct inode *		bd_inode;	/* will die */
Index: linux-2.6.23-rc6-mm1/include/linux/swap.h
===================================================================
--- linux-2.6.23-rc6-mm1.orig/include/linux/swap.h
+++ linux-2.6.23-rc6-mm1/include/linux/swap.h
@@ -196,7 +196,6 @@ extern unsigned long try_to_free_mem_con
 extern int __isolate_lru_page(struct page *page, int mode);
 extern unsigned long shrink_all_memory(unsigned long nr_pages);
 extern int vm_swappiness;
-extern int remove_mapping(struct address_space *mapping, struct page *page);
 extern long vm_total_pages;
 
 #ifdef CONFIG_NUMA

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux