Skip to contentSkip to conversation

9p: add readahead support for loose mode

RFC PATCH In review Eric Van Hensbergen 3 participants 3 messages Sep 14, 2007 – Sep 16, 2007

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

RFC PATCH 1/1 9p: add readahead support for loose mode

This patch adds readpages support in support of readahead when using loose cache mode. It substantially increases performance for certain workloads.

---
 fs/9p/v9fs.c            |    2 +-
 fs/9p/vfs_addr.c        |   98 ++++++++++++++++++++++++++++++++++++++++++----
 include/net/9p/client.h |    3 +-
 net/9p/client.c         |   82 +++++++++++++++++++++++++--------------
 4 files changed, 143 insertions(+), 42 deletions(-)
fs/9p/v9fs.c +1 -1
index 89ee0ba..ca97404 100644
@@ -131,7 +131,7 @@ static void v9fs_parse_options(struct v9fs_session_info *v9ses)
 	char *s, *e;
 
 	/* setup defaults */
-	v9ses->maxdata = 8192;
+	v9ses->maxdata = (64*1024);
 	v9ses->afid = ~0;
 	v9ses->debug = 0;
 	v9ses->cache = 0;
fs/9p/vfs_addr.c +89 -9

128 lines not on this page · raw message

include/net/9p/client.h +1 -2
index 9b9221a..6f17d0a 100644
@@ -67,8 +67,7 @@ int p9_client_fcreate(struct p9_fid *fid, char *name, u32 perm, int mode,
 							char *extension);
 int p9_client_clunk(struct p9_fid *fid);
 int p9_client_remove(struct p9_fid *fid);
-int p9_client_read(struct p9_fid *fid, char *data, u64 offset, u32 count);
-int p9_client_readn(struct p9_fid *fid, char *data, u64 offset, u32 count);
+int p9_client_readv(struct p9_fid *fid, struct kvec *kv, u64 offset, u32 count);
 int p9_client_write(struct p9_fid *fid, char *data, u64 offset, u32 count);
 int p9_client_uread(struct p9_fid *fid, char __user *data, u64 offset,
 								u32 count);
net/9p/client.c +52 -30

118 lines not on this page · raw message

Signature · 1 line
1.5.3.rc7
#1 lore raw
Quoted 20 lines · On Fri, 14 Sep 2007 11:02:40 -0500 Eric Van Hensbergen <[email protected]> wrote:
fs/9p/vfs_addr.c +20 -0
+	list_for_each_entry_reverse(tmp_page, page_list, lru) {
+		BUG_ON(count > num_pages);
+		if (add_to_page_cache(tmp_page, mapping,
+					tmp_page->index, GFP_KERNEL)) {
+			page_cache_release(tmp_page);
+			continue;
+		}
+
+		kv[count].iov_base = kmap(tmp_page);
+		kv[count].iov_len = PAGE_CACHE_SIZE;
+		count++;
+	}
+
+	read_size = count * PAGE_CACHE_SIZE;
+	if (!read_size)
+		goto cleanup;
+
+	retval = p9_client_readv(fid, kv, offset, count);
+
+cleanup:

fs/9p/vfs_addr.c line 149

Quoted 10 lines
fs/9p/vfs_addr.c +10 -0
+	list_for_each_safe(p, n, page_list) {
+		tmp_page = list_entry(p, struct page, lru);
+		list_del(&tmp_page->lru);
+		if (!pagevec_add(&lru_pvec, tmp_page))
+			__pagevec_lru_add(&lru_pvec);
+		kunmap(tmp_page);
+		flush_dcache_page(tmp_page);
+		SetPageUptodate(tmp_page);
+		unlock_page(tmp_page);
+	}

eww, kmap. Large amounts of them, apparently.

Be aware that kmap is a) slow and b) deadlockable. The latter happens when multiple tasks want to take more than one kmap simultaneously: they all wait for someone else to release one. Your code here seems especially vulnerable to this.

Nick had a kmap-speedup patchset a while back which addressed a) but I don't know if it addressed the deadlock. But that patch seemed to die.

Strongly recommend that the code be reworked to use kmap_atomic()

#2 lore raw
Quoted 9 lines · On Sat, 15 Sep 2007 03:41:26 -0700 Andrew Morton <[email protected]>…

eww, kmap. Large amounts of them, apparently.

Be aware that kmap is a) slow and b) deadlockable. The latter happens when multiple tasks want to take more than one kmap simultaneously: they all wait for someone else to release one. Your code here seems especially vulnerable to this.

Nick had a kmap-speedup patchset a while back which addressed a) but I don't know if it addressed the deadlock. But that patch seemed to die.

That would've been me.

What I did to address b) is to pre-allocate each kmap user a second kmap slot. Of course this isn't water-tight either.

These patches are part of -rt, I could respin against mainline if there is interest.