[RFC 2/4] cleancache: make get_page async possible

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

 



Make cleancache get_page support async page fetch. Just normal page read,
cleancache unlock the page after page fetch is finished.

But we don't support IO error from cleancache get_page. That is if cleancache
get_page fails, we can't fallback to normal page read.

Signed-off-by: Shaohua Li <shli@xxxxxxxxxx>
---
 drivers/xen/tmem.c         |    8 +++++---
 fs/btrfs/extent_io.c       |   10 ++++++++--
 fs/mpage.c                 |   15 ++++++++++++---
 include/linux/cleancache.h |   11 +++++++----
 mm/cleancache.c            |    5 +++--
 5 files changed, 35 insertions(+), 14 deletions(-)

Index: linux/fs/btrfs/extent_io.c
===================================================================
--- linux.orig/fs/btrfs/extent_io.c	2013-09-26 21:21:14.530330681 +0800
+++ linux/fs/btrfs/extent_io.c	2013-09-26 21:21:14.522330771 +0800
@@ -2530,6 +2530,12 @@ readpage_ok:
 	bio_put(bio);
 }
 
+static void extent_end_get_page(struct page *page, int err)
+{
+	SetPageUptodate(page);
+	unlock_page(page);
+}
+
 /*
  * this allocates from the btrfs_bioset.  We're returning a bio right now
  * but you can call btrfs_io_bio for the appropriate container_of magic
@@ -2770,10 +2776,10 @@ static int __do_readpage(struct extent_i
 
 	end = page_end;
 	if (!PageUptodate(page)) {
-		if (cleancache_get_page(page) == 0) {
+		if (cleancache_get_page(page, extent_end_get_page) == 0) {
 			BUG_ON(blocksize != PAGE_SIZE);
 			unlock_extent(tree, start, end);
-			goto out;
+			return 0;
 		}
 	}
 
Index: linux/fs/mpage.c
===================================================================
--- linux.orig/fs/mpage.c	2013-09-26 21:21:14.530330681 +0800
+++ linux/fs/mpage.c	2013-09-26 21:21:14.522330771 +0800
@@ -71,6 +71,14 @@ static void mpage_end_io(struct bio *bio
 	bio_put(bio);
 }
 
+static void mpage_end_get_page(struct page *page, int err)
+{
+	/* We don't support IO error so far */
+	WARN_ON(err);
+	SetPageUptodate(page);
+	unlock_page(page);
+}
+
 static struct bio *mpage_bio_submit(int rw, struct bio *bio)
 {
 	bio->bi_end_io = mpage_end_io;
@@ -273,9 +281,10 @@ do_mpage_readpage(struct bio *bio, struc
 	}
 
 	if (fully_mapped && blocks_per_page == 1 && !PageUptodate(page) &&
-	    cleancache_get_page(page) == 0) {
-		SetPageUptodate(page);
-		goto confused;
+	    cleancache_get_page(page, mpage_end_get_page) == 0) {
+		if (bio)
+			bio = mpage_bio_submit(READ, bio);
+		goto out;
 	}
 
 	/*
Index: linux/include/linux/cleancache.h
===================================================================
--- linux.orig/include/linux/cleancache.h	2013-09-26 21:21:14.530330681 +0800
+++ linux/include/linux/cleancache.h	2013-09-26 21:21:14.526330726 +0800
@@ -25,7 +25,8 @@ struct cleancache_ops {
 	int (*init_fs)(size_t);
 	int (*init_shared_fs)(char *uuid, size_t);
 	int (*get_page)(int, struct cleancache_filekey,
-			pgoff_t, struct page *);
+			pgoff_t, struct page *,
+			void (*end_get_page)(struct page *, int err));
 	void (*put_page)(int, struct cleancache_filekey,
 			pgoff_t, struct page *);
 	void (*invalidate_page)(int, struct cleancache_filekey, pgoff_t);
@@ -37,7 +38,8 @@ extern struct cleancache_ops *
 	cleancache_register_ops(struct cleancache_ops *ops);
 extern void __cleancache_init_fs(struct super_block *);
 extern void __cleancache_init_shared_fs(char *, struct super_block *);
-extern int  __cleancache_get_page(struct page *);
+extern int  __cleancache_get_page(struct page *,
+	void (*end_get_page)(struct page *page, int err));
 extern void __cleancache_put_page(struct page *);
 extern void __cleancache_invalidate_page(struct address_space *, struct page *);
 extern void __cleancache_invalidate_inode(struct address_space *);
@@ -84,12 +86,13 @@ static inline void cleancache_init_share
 		__cleancache_init_shared_fs(uuid, sb);
 }
 
-static inline int cleancache_get_page(struct page *page)
+static inline int cleancache_get_page(struct page *page,
+	void (*end_get_page)(struct page *page, int err))
 {
 	int ret = -1;
 
 	if (cleancache_enabled && cleancache_fs_enabled(page))
-		ret = __cleancache_get_page(page);
+		ret = __cleancache_get_page(page, end_get_page);
 	return ret;
 }
 
Index: linux/mm/cleancache.c
===================================================================
--- linux.orig/mm/cleancache.c	2013-09-26 21:21:14.530330681 +0800
+++ linux/mm/cleancache.c	2013-09-26 21:21:14.526330726 +0800
@@ -225,7 +225,8 @@ static int get_poolid_from_fake(int fake
  * a backend is registered and whether the sb->cleancache_poolid
  * is correct.
  */
-int __cleancache_get_page(struct page *page)
+int __cleancache_get_page(struct page *page,
+	void (*end_get_page)(struct page *page, int err))
 {
 	int ret = -1;
 	int pool_id;
@@ -248,7 +249,7 @@ int __cleancache_get_page(struct page *p
 
 	if (pool_id >= 0)
 		ret = cleancache_ops->get_page(pool_id,
-				key, page->index, page);
+				key, page->index, page, end_get_page);
 	if (ret == 0)
 		cleancache_succ_gets++;
 	else
Index: linux/drivers/xen/tmem.c
===================================================================
--- linux.orig/drivers/xen/tmem.c	2013-09-26 21:21:14.530330681 +0800
+++ linux/drivers/xen/tmem.c	2013-09-26 21:21:14.526330726 +0800
@@ -184,7 +184,8 @@ static void tmem_cleancache_put_page(int
 }
 
 static int tmem_cleancache_get_page(int pool, struct cleancache_filekey key,
-				    pgoff_t index, struct page *page)
+				    pgoff_t index, struct page *page,
+				    void (*end_get_page)(struct page *, int))
 {
 	u32 ind = (u32) index;
 	struct tmem_oid oid = *(struct tmem_oid *)&key;
@@ -197,9 +198,10 @@ static int tmem_cleancache_get_page(int
 	if (ind != index)
 		return -1;
 	ret = xen_tmem_get_page((u32)pool, oid, ind, pfn);
-	if (ret == 1)
+	if (ret == 1) {
+		end_get_page(page, 0);
 		return 0;
-	else
+	} else
 		return -1;
 }
 

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@xxxxxxxxx.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@xxxxxxxxx";> email@xxxxxxxxx </a>




[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Bugtraq]     [Linux]     [Linux OMAP]     [Linux MIPS]     [ECOS]     [Asterisk Internet PBX]     [Linux API]