diff options
author | Eric Van Hensbergen <ericvh@gmail.com> | 2007-02-11 14:21:39 -0500 |
---|---|---|
committer | Eric Van Hensbergen <ericvh@gmail.com> | 2007-02-18 11:16:10 -0500 |
commit | e03abc0c963a31cb07dfbc07c7d85d75e0d13cf4 (patch) | |
tree | 1840001bde4a7f9f01d39dd09baf7d7b04e95706 /fs | |
parent | 2c0463a9ae8751547c39302aeb31c6cef16b5df4 (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')
-rw-r--r-- | fs/9p/fid.c | 3 | ||||
-rw-r--r-- | fs/9p/v9fs.c | 9 | ||||
-rw-r--r-- | fs/9p/v9fs.h | 9 | ||||
-rw-r--r-- | fs/9p/v9fs_vfs.h | 2 | ||||
-rw-r--r-- | fs/9p/vfs_addr.c | 2 | ||||
-rw-r--r-- | fs/9p/vfs_dentry.c | 26 | ||||
-rw-r--r-- | fs/9p/vfs_file.c | 18 | ||||
-rw-r--r-- | fs/9p/vfs_inode.c | 20 |
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 */ | ||
78 | enum { | ||
79 | CACHE_NONE, /* default */ | ||
80 | CACHE_LOOSE, /* no consistency */ | ||
81 | }; | ||
82 | |||
76 | extern struct dentry *v9fs_debugfs_root; | 83 | extern struct dentry *v9fs_debugfs_root; |
77 | 84 | ||
78 | int v9fs_session_init(struct v9fs_session_info *, const char *, char *); | 85 | int 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 @@ | |||
40 | extern struct file_system_type v9fs_fs_type; | 40 | extern struct file_system_type v9fs_fs_type; |
41 | extern const struct address_space_operations v9fs_addr_operations; | 41 | extern const struct address_space_operations v9fs_addr_operations; |
42 | extern const struct file_operations v9fs_file_operations; | 42 | extern const struct file_operations v9fs_file_operations; |
43 | extern const struct file_operations v9fs_cached_file_operations; | ||
43 | extern const struct file_operations v9fs_dir_operations; | 44 | extern const struct file_operations v9fs_dir_operations; |
44 | extern struct dentry_operations v9fs_dentry_operations; | 45 | extern struct dentry_operations v9fs_dentry_operations; |
46 | extern struct dentry_operations v9fs_cached_dentry_operations; | ||
45 | 47 | ||
46 | struct inode *v9fs_get_inode(struct super_block *sb, int mode); | 48 | struct inode *v9fs_get_inode(struct super_block *sb, int mode); |
47 | ino_t v9fs_qid2ino(struct v9fs_qid *qid); | 49 | ino_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 @@ | |||
53 | static int v9fs_dentry_delete(struct dentry *dentry) | 53 | static 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 | |||
69 | static 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 | ||
111 | struct dentry_operations v9fs_cached_dentry_operations = { | ||
112 | .d_delete = v9fs_cached_dentry_delete, | ||
113 | .d_release = v9fs_dentry_release, | ||
114 | }; | ||
115 | |||
90 | struct dentry_operations v9fs_dentry_operations = { | 116 | struct 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 | ||
84 | Clunk_Fid: | 91 | Clunk_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 | ||
248 | const 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 | |||
241 | const struct file_operations v9fs_file_operations = { | 259 | const 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 | ||