aboutsummaryrefslogtreecommitdiffstats
path: root/fs/9p
diff options
context:
space:
mode:
authorEric Van Hensbergen <ericvh@gmail.com>2007-02-11 14:21:39 -0500
committerEric Van Hensbergen <ericvh@gmail.com>2007-02-18 11:16:10 -0500
commite03abc0c963a31cb07dfbc07c7d85d75e0d13cf4 (patch)
tree1840001bde4a7f9f01d39dd09baf7d7b04e95706 /fs/9p
parent2c0463a9ae8751547c39302aeb31c6cef16b5df4 (diff)
9p: implement optional loose read cache
While cacheing is generally frowned upon in the 9p world, it has its place -- particularly in situations where the remote file system is exclusive and/or read-only. The vacfs views of venti content addressable store are a real-world instance of such a situation. To facilitate higher performance for these workloads (and eventually use the fscache patches), we have enabled a "loose" cache mode which does not attempt to maintain any form of consistency on the page-cache or dcache. This results in over two orders of magnitude performance improvement for cacheable block reads in the Bonnie benchmark. The more aggressive use of the dcache also seems to improve metadata operational performance. Signed-off-by: Eric Van Hensbergen <ericvh@gmail.com>
Diffstat (limited to 'fs/9p')
-rw-r--r--fs/9p/fid.c3
-rw-r--r--fs/9p/v9fs.c9
-rw-r--r--fs/9p/v9fs.h9
-rw-r--r--fs/9p/v9fs_vfs.h2
-rw-r--r--fs/9p/vfs_addr.c2
-rw-r--r--fs/9p/vfs_dentry.c26
-rw-r--r--fs/9p/vfs_file.c18
-rw-r--r--fs/9p/vfs_inode.c20
8 files changed, 82 insertions, 7 deletions
diff --git a/fs/9p/fid.c b/fs/9p/fid.c
index a9b6301a04fc..90419715c7e9 100644
--- a/fs/9p/fid.c
+++ b/fs/9p/fid.c
@@ -136,7 +136,8 @@ struct v9fs_fid *v9fs_fid_lookup(struct dentry *dentry)
136} 136}
137 137
138/** 138/**
139 * v9fs_fid_clone - lookup the fid for a dentry, clone a private copy and release it 139 * v9fs_fid_clone - lookup the fid for a dentry, clone a private copy and
140 * release it
140 * @dentry: dentry to look for fid in 141 * @dentry: dentry to look for fid in
141 * 142 *
142 * find a fid in the dentry and then clone to a new private fid 143 * find a fid in the dentry and then clone to a new private fid
diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c
index d9b561ba5e58..6ad6f192b6e4 100644
--- a/fs/9p/v9fs.c
+++ b/fs/9p/v9fs.c
@@ -53,6 +53,8 @@ enum {
53 Opt_uname, Opt_remotename, 53 Opt_uname, Opt_remotename,
54 /* Options that take no arguments */ 54 /* Options that take no arguments */
55 Opt_legacy, Opt_nodevmap, Opt_unix, Opt_tcp, Opt_fd, 55 Opt_legacy, Opt_nodevmap, Opt_unix, Opt_tcp, Opt_fd,
56 /* Cache options */
57 Opt_cache_loose,
56 /* Error token */ 58 /* Error token */
57 Opt_err 59 Opt_err
58}; 60};
@@ -76,6 +78,8 @@ static match_table_t tokens = {
76 {Opt_fd, "fd"}, 78 {Opt_fd, "fd"},
77 {Opt_legacy, "noextend"}, 79 {Opt_legacy, "noextend"},
78 {Opt_nodevmap, "nodevmap"}, 80 {Opt_nodevmap, "nodevmap"},
81 {Opt_cache_loose, "cache=loose"},
82 {Opt_cache_loose, "loose"},
79 {Opt_err, NULL} 83 {Opt_err, NULL}
80}; 84};
81 85
@@ -106,6 +110,7 @@ static void v9fs_parse_options(char *options, struct v9fs_session_info *v9ses)
106 v9ses->debug = 0; 110 v9ses->debug = 0;
107 v9ses->rfdno = ~0; 111 v9ses->rfdno = ~0;
108 v9ses->wfdno = ~0; 112 v9ses->wfdno = ~0;
113 v9ses->cache = 0;
109 114
110 if (!options) 115 if (!options)
111 return; 116 return;
@@ -121,7 +126,6 @@ static void v9fs_parse_options(char *options, struct v9fs_session_info *v9ses)
121 "integer field, but no integer?\n"); 126 "integer field, but no integer?\n");
122 continue; 127 continue;
123 } 128 }
124
125 } 129 }
126 switch (token) { 130 switch (token) {
127 case Opt_port: 131 case Opt_port:
@@ -169,6 +173,9 @@ static void v9fs_parse_options(char *options, struct v9fs_session_info *v9ses)
169 case Opt_nodevmap: 173 case Opt_nodevmap:
170 v9ses->nodev = 1; 174 v9ses->nodev = 1;
171 break; 175 break;
176 case Opt_cache_loose:
177 v9ses->cache = CACHE_LOOSE;
178 break;
172 default: 179 default:
173 continue; 180 continue;
174 } 181 }
diff --git a/fs/9p/v9fs.h b/fs/9p/v9fs.h
index c134d104cb28..820bf5ca35d8 100644
--- a/fs/9p/v9fs.h
+++ b/fs/9p/v9fs.h
@@ -47,7 +47,7 @@ struct v9fs_session_info {
47 unsigned int afid; /* authentication fid */ 47 unsigned int afid; /* authentication fid */
48 unsigned int rfdno; /* read file descriptor number */ 48 unsigned int rfdno; /* read file descriptor number */
49 unsigned int wfdno; /* write file descriptor number */ 49 unsigned int wfdno; /* write file descriptor number */
50 50 unsigned int cache; /* cache mode */
51 51
52 char *name; /* user name to mount as */ 52 char *name; /* user name to mount as */
53 char *remotename; /* name of remote hierarchy being mounted */ 53 char *remotename; /* name of remote hierarchy being mounted */
@@ -73,6 +73,13 @@ enum {
73 PROTO_FD, 73 PROTO_FD,
74}; 74};
75 75
76/* possible values of ->cache */
77/* eventually support loose, tight, time, session, default always none */
78enum {
79 CACHE_NONE, /* default */
80 CACHE_LOOSE, /* no consistency */
81};
82
76extern struct dentry *v9fs_debugfs_root; 83extern struct dentry *v9fs_debugfs_root;
77 84
78int v9fs_session_init(struct v9fs_session_info *, const char *, char *); 85int v9fs_session_init(struct v9fs_session_info *, const char *, char *);
diff --git a/fs/9p/v9fs_vfs.h b/fs/9p/v9fs_vfs.h
index 450b0c1b385e..8ada4c5c5d70 100644
--- a/fs/9p/v9fs_vfs.h
+++ b/fs/9p/v9fs_vfs.h
@@ -40,8 +40,10 @@
40extern struct file_system_type v9fs_fs_type; 40extern struct file_system_type v9fs_fs_type;
41extern const struct address_space_operations v9fs_addr_operations; 41extern const struct address_space_operations v9fs_addr_operations;
42extern const struct file_operations v9fs_file_operations; 42extern const struct file_operations v9fs_file_operations;
43extern const struct file_operations v9fs_cached_file_operations;
43extern const struct file_operations v9fs_dir_operations; 44extern const struct file_operations v9fs_dir_operations;
44extern struct dentry_operations v9fs_dentry_operations; 45extern struct dentry_operations v9fs_dentry_operations;
46extern struct dentry_operations v9fs_cached_dentry_operations;
45 47
46struct inode *v9fs_get_inode(struct super_block *sb, int mode); 48struct inode *v9fs_get_inode(struct super_block *sb, int mode);
47ino_t v9fs_qid2ino(struct v9fs_qid *qid); 49ino_t v9fs_qid2ino(struct v9fs_qid *qid);
diff --git a/fs/9p/vfs_addr.c b/fs/9p/vfs_addr.c
index cc24abf232d5..bed48fa96521 100644
--- a/fs/9p/vfs_addr.c
+++ b/fs/9p/vfs_addr.c
@@ -63,6 +63,8 @@ static int v9fs_vfs_readpage(struct file *filp, struct page *page)
63 int total = 0; 63 int total = 0;
64 int result = 0; 64 int result = 0;
65 65
66 dprintk(DEBUG_VFS, "\n");
67
66 buffer = kmap(page); 68 buffer = kmap(page);
67 do { 69 do {
68 if (count < rsize) 70 if (count < rsize)
diff --git a/fs/9p/vfs_dentry.c b/fs/9p/vfs_dentry.c
index 062daa6000ab..ddffd8aa902d 100644
--- a/fs/9p/vfs_dentry.c
+++ b/fs/9p/vfs_dentry.c
@@ -53,10 +53,31 @@
53static int v9fs_dentry_delete(struct dentry *dentry) 53static int v9fs_dentry_delete(struct dentry *dentry)
54{ 54{
55 dprintk(DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry); 55 dprintk(DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry);
56
56 return 1; 57 return 1;
57} 58}
58 59
59/** 60/**
61 * v9fs_cached_dentry_delete - called when dentry refcount equals 0
62 * @dentry: dentry in question
63 *
64 * Only return 1 if our inode is invalid. Only non-synthetic files
65 * (ones without mtime == 0) should be calling this function.
66 *
67 */
68
69static int v9fs_cached_dentry_delete(struct dentry *dentry)
70{
71 struct inode *inode = dentry->d_inode;
72 dprintk(DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry);
73
74 if(!inode)
75 return 1;
76
77 return 0;
78}
79
80/**
60 * v9fs_dentry_release - called when dentry is going to be freed 81 * v9fs_dentry_release - called when dentry is going to be freed
61 * @dentry: dentry that is being release 82 * @dentry: dentry that is being release
62 * 83 *
@@ -87,6 +108,11 @@ void v9fs_dentry_release(struct dentry *dentry)
87 } 108 }
88} 109}
89 110
111struct dentry_operations v9fs_cached_dentry_operations = {
112 .d_delete = v9fs_cached_dentry_delete,
113 .d_release = v9fs_dentry_release,
114};
115
90struct dentry_operations v9fs_dentry_operations = { 116struct dentry_operations v9fs_dentry_operations = {
91 .d_delete = v9fs_dentry_delete, 117 .d_delete = v9fs_dentry_delete,
92 .d_release = v9fs_dentry_release, 118 .d_release = v9fs_dentry_release,
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c
index 6c78343cf690..653dfa5b2531 100644
--- a/fs/9p/vfs_file.c
+++ b/fs/9p/vfs_file.c
@@ -79,6 +79,13 @@ int v9fs_file_open(struct inode *inode, struct file *file)
79 vfid->filp = file; 79 vfid->filp = file;
80 kfree(fcall); 80 kfree(fcall);
81 81
82 if((vfid->qid.version) && (v9ses->cache)) {
83 dprintk(DEBUG_VFS, "cached");
84 /* enable cached file options */
85 if(file->f_op == &v9fs_file_operations)
86 file->f_op = &v9fs_cached_file_operations;
87 }
88
82 return 0; 89 return 0;
83 90
84Clunk_Fid: 91Clunk_Fid:
@@ -238,6 +245,17 @@ v9fs_file_write(struct file *filp, const char __user * data,
238 return total; 245 return total;
239} 246}
240 247
248const struct file_operations v9fs_cached_file_operations = {
249 .llseek = generic_file_llseek,
250 .read = do_sync_read,
251 .aio_read = generic_file_aio_read,
252 .write = v9fs_file_write,
253 .open = v9fs_file_open,
254 .release = v9fs_dir_release,
255 .lock = v9fs_file_lock,
256 .mmap = generic_file_mmap,
257};
258
241const struct file_operations v9fs_file_operations = { 259const struct file_operations v9fs_file_operations = {
242 .llseek = generic_file_llseek, 260 .llseek = generic_file_llseek,
243 .read = v9fs_file_read, 261 .read = v9fs_file_read,
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index 5cf22134826b..124a085d1f2e 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -504,7 +504,10 @@ v9fs_vfs_create(struct inode *dir, struct dentry *dentry, int mode,
504 goto error; 504 goto error;
505 } 505 }
506 506
507 dentry->d_op = &v9fs_dentry_operations; 507 if(v9ses->cache)
508 dentry->d_op = &v9fs_cached_dentry_operations;
509 else
510 dentry->d_op = &v9fs_dentry_operations;
508 d_instantiate(dentry, inode); 511 d_instantiate(dentry, inode);
509 512
510 if (nd && nd->flags & LOOKUP_OPEN) { 513 if (nd && nd->flags & LOOKUP_OPEN) {
@@ -589,7 +592,10 @@ static int v9fs_vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
589 goto error; 592 goto error;
590 } 593 }
591 594
592 dentry->d_op = &v9fs_dentry_operations; 595 if(v9ses->cache)
596 dentry->d_op = &v9fs_cached_dentry_operations;
597 else
598 dentry->d_op = &v9fs_dentry_operations;
593 d_instantiate(dentry, inode); 599 d_instantiate(dentry, inode);
594 return 0; 600 return 0;
595 601
@@ -626,7 +632,6 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
626 632
627 sb = dir->i_sb; 633 sb = dir->i_sb;
628 v9ses = v9fs_inode2v9ses(dir); 634 v9ses = v9fs_inode2v9ses(dir);
629 dentry->d_op = &v9fs_dentry_operations;
630 dirfid = v9fs_fid_lookup(dentry->d_parent); 635 dirfid = v9fs_fid_lookup(dentry->d_parent);
631 636
632 if(IS_ERR(dirfid)) 637 if(IS_ERR(dirfid))
@@ -697,6 +702,10 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
697 702
698 fid->qid = fcall->params.rstat.stat.qid; 703 fid->qid = fcall->params.rstat.stat.qid;
699 v9fs_stat2inode(&fcall->params.rstat.stat, inode, inode->i_sb); 704 v9fs_stat2inode(&fcall->params.rstat.stat, inode, inode->i_sb);
705 if((fid->qid.version)&&(v9ses->cache))
706 dentry->d_op = &v9fs_cached_dentry_operations;
707 else
708 dentry->d_op = &v9fs_dentry_operations;
700 709
701 d_add(dentry, inode); 710 d_add(dentry, inode);
702 kfree(fcall); 711 kfree(fcall);
@@ -1184,7 +1193,10 @@ static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry,
1184 goto free_vfid; 1193 goto free_vfid;
1185 } 1194 }
1186 1195
1187 dentry->d_op = &v9fs_dentry_operations; 1196 if(v9ses->cache)
1197 dentry->d_op = &v9fs_cached_dentry_operations;
1198 else
1199 dentry->d_op = &v9fs_dentry_operations;
1188 d_instantiate(dentry, inode); 1200 d_instantiate(dentry, inode);
1189 return 0; 1201 return 0;
1190 1202