Blame view
fs/9p/cache.c
10.3 KB
60e78d2c9 9p: Add fscache s... |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
/* * V9FS cache definitions. * * Copyright (C) 2009 by Abhishek Kulkarni <adkulkar@umail.iu.edu> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to: * Free Software Foundation * 51 Franklin Street, Fifth Floor * Boston, MA 02111-1301 USA * */ #include <linux/jiffies.h> #include <linux/file.h> |
5a0e3ad6a include cleanup: ... |
25 |
#include <linux/slab.h> |
60e78d2c9 9p: Add fscache s... |
26 27 28 29 30 31 32 33 34 |
#include <linux/stat.h> #include <linux/sched.h> #include <linux/fs.h> #include <net/9p/9p.h> #include "v9fs.h" #include "cache.h" #define CACHETAG_LEN 11 |
60e78d2c9 9p: Add fscache s... |
35 36 37 38 |
struct fscache_netfs v9fs_cache_netfs = { .name = "9p", .version = 0, }; |
60e78d2c9 9p: Add fscache s... |
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
/** * v9fs_random_cachetag - Generate a random tag to be associated * with a new cache session. * * The value of jiffies is used for a fairly randomly cache tag. */ static int v9fs_random_cachetag(struct v9fs_session_info *v9ses) { v9ses->cachetag = kmalloc(CACHETAG_LEN, GFP_KERNEL); if (!v9ses->cachetag) return -ENOMEM; return scnprintf(v9ses->cachetag, CACHETAG_LEN, "%lu", jiffies); } static uint16_t v9fs_cache_session_get_key(const void *cookie_netfs_data, void *buffer, uint16_t bufmax) { struct v9fs_session_info *v9ses; uint16_t klen = 0; v9ses = (struct v9fs_session_info *)cookie_netfs_data; |
5d3851530 9p: Reduce object... |
63 64 65 |
p9_debug(P9_DEBUG_FSC, "session %p buf %p size %u ", v9ses, buffer, bufmax); |
60e78d2c9 9p: Add fscache s... |
66 67 68 69 70 71 72 73 |
if (v9ses->cachetag) klen = strlen(v9ses->cachetag); if (klen > bufmax) return 0; memcpy(buffer, v9ses->cachetag, klen); |
5d3851530 9p: Reduce object... |
74 75 |
p9_debug(P9_DEBUG_FSC, "cache session tag %s ", v9ses->cachetag); |
60e78d2c9 9p: Add fscache s... |
76 77 78 79 |
return klen; } const struct fscache_cookie_def v9fs_cache_session_index_def = { |
a78ce05d5 fs/9p: Add v9fs_i... |
80 81 82 |
.name = "9P.session", .type = FSCACHE_COOKIE_TYPE_INDEX, .get_key = v9fs_cache_session_get_key, |
60e78d2c9 9p: Add fscache s... |
83 84 85 86 87 88 89 90 91 92 93 |
}; void v9fs_cache_session_get_cookie(struct v9fs_session_info *v9ses) { /* If no cache session tag was specified, we generate a random one. */ if (!v9ses->cachetag) v9fs_random_cachetag(v9ses); v9ses->fscache = fscache_acquire_cookie(v9fs_cache_netfs.primary_index, &v9fs_cache_session_index_def, v9ses); |
5d3851530 9p: Reduce object... |
94 95 96 |
p9_debug(P9_DEBUG_FSC, "session %p get cookie %p ", v9ses, v9ses->fscache); |
60e78d2c9 9p: Add fscache s... |
97 98 99 100 |
} void v9fs_cache_session_put_cookie(struct v9fs_session_info *v9ses) { |
5d3851530 9p: Reduce object... |
101 102 103 |
p9_debug(P9_DEBUG_FSC, "session %p put cookie %p ", v9ses, v9ses->fscache); |
60e78d2c9 9p: Add fscache s... |
104 105 106 107 108 109 110 111 |
fscache_relinquish_cookie(v9ses->fscache, 0); v9ses->fscache = NULL; } static uint16_t v9fs_cache_inode_get_key(const void *cookie_netfs_data, void *buffer, uint16_t bufmax) { |
a78ce05d5 fs/9p: Add v9fs_i... |
112 |
const struct v9fs_inode *v9inode = cookie_netfs_data; |
fd2421f54 fs/9p: When doing... |
113 |
memcpy(buffer, &v9inode->qid.path, sizeof(v9inode->qid.path)); |
5d3851530 9p: Reduce object... |
114 115 116 |
p9_debug(P9_DEBUG_FSC, "inode %p get key %llu ", &v9inode->vfs_inode, v9inode->qid.path); |
fd2421f54 fs/9p: When doing... |
117 |
return sizeof(v9inode->qid.path); |
60e78d2c9 9p: Add fscache s... |
118 119 120 121 122 |
} static void v9fs_cache_inode_get_attr(const void *cookie_netfs_data, uint64_t *size) { |
a78ce05d5 fs/9p: Add v9fs_i... |
123 124 |
const struct v9fs_inode *v9inode = cookie_netfs_data; *size = i_size_read(&v9inode->vfs_inode); |
60e78d2c9 9p: Add fscache s... |
125 |
|
5d3851530 9p: Reduce object... |
126 127 128 |
p9_debug(P9_DEBUG_FSC, "inode %p get attr %llu ", &v9inode->vfs_inode, *size); |
60e78d2c9 9p: Add fscache s... |
129 130 131 132 133 |
} static uint16_t v9fs_cache_inode_get_aux(const void *cookie_netfs_data, void *buffer, uint16_t buflen) { |
a78ce05d5 fs/9p: Add v9fs_i... |
134 |
const struct v9fs_inode *v9inode = cookie_netfs_data; |
fd2421f54 fs/9p: When doing... |
135 |
memcpy(buffer, &v9inode->qid.version, sizeof(v9inode->qid.version)); |
5d3851530 9p: Reduce object... |
136 137 138 |
p9_debug(P9_DEBUG_FSC, "inode %p get aux %u ", &v9inode->vfs_inode, v9inode->qid.version); |
fd2421f54 fs/9p: When doing... |
139 |
return sizeof(v9inode->qid.version); |
60e78d2c9 9p: Add fscache s... |
140 141 142 143 144 145 146 |
} static enum fscache_checkaux v9fs_cache_inode_check_aux(void *cookie_netfs_data, const void *buffer, uint16_t buflen) { |
a78ce05d5 fs/9p: Add v9fs_i... |
147 |
const struct v9fs_inode *v9inode = cookie_netfs_data; |
60e78d2c9 9p: Add fscache s... |
148 |
|
fd2421f54 fs/9p: When doing... |
149 |
if (buflen != sizeof(v9inode->qid.version)) |
60e78d2c9 9p: Add fscache s... |
150 |
return FSCACHE_CHECKAUX_OBSOLETE; |
fd2421f54 fs/9p: When doing... |
151 152 |
if (memcmp(buffer, &v9inode->qid.version, sizeof(v9inode->qid.version))) |
60e78d2c9 9p: Add fscache s... |
153 154 155 156 157 158 159 |
return FSCACHE_CHECKAUX_OBSOLETE; return FSCACHE_CHECKAUX_OKAY; } static void v9fs_cache_inode_now_uncached(void *cookie_netfs_data) { |
a78ce05d5 fs/9p: Add v9fs_i... |
160 |
struct v9fs_inode *v9inode = cookie_netfs_data; |
60e78d2c9 9p: Add fscache s... |
161 162 163 164 165 166 167 168 |
struct pagevec pvec; pgoff_t first; int loop, nr_pages; pagevec_init(&pvec, 0); first = 0; for (;;) { |
a78ce05d5 fs/9p: Add v9fs_i... |
169 |
nr_pages = pagevec_lookup(&pvec, v9inode->vfs_inode.i_mapping, |
60e78d2c9 9p: Add fscache s... |
170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 |
first, PAGEVEC_SIZE - pagevec_count(&pvec)); if (!nr_pages) break; for (loop = 0; loop < nr_pages; loop++) ClearPageFsCache(pvec.pages[loop]); first = pvec.pages[nr_pages - 1]->index + 1; pvec.nr = nr_pages; pagevec_release(&pvec); cond_resched(); } } const struct fscache_cookie_def v9fs_cache_inode_index_def = { .name = "9p.inode", .type = FSCACHE_COOKIE_TYPE_DATAFILE, .get_key = v9fs_cache_inode_get_key, .get_attr = v9fs_cache_inode_get_attr, .get_aux = v9fs_cache_inode_get_aux, .check_aux = v9fs_cache_inode_check_aux, .now_uncached = v9fs_cache_inode_now_uncached, }; void v9fs_cache_inode_get_cookie(struct inode *inode) { |
a78ce05d5 fs/9p: Add v9fs_i... |
198 |
struct v9fs_inode *v9inode; |
60e78d2c9 9p: Add fscache s... |
199 200 201 202 |
struct v9fs_session_info *v9ses; if (!S_ISREG(inode->i_mode)) return; |
a78ce05d5 fs/9p: Add v9fs_i... |
203 204 |
v9inode = V9FS_I(inode); if (v9inode->fscache) |
60e78d2c9 9p: Add fscache s... |
205 206 207 |
return; v9ses = v9fs_inode2v9ses(inode); |
a78ce05d5 fs/9p: Add v9fs_i... |
208 |
v9inode->fscache = fscache_acquire_cookie(v9ses->fscache, |
60e78d2c9 9p: Add fscache s... |
209 |
&v9fs_cache_inode_index_def, |
a78ce05d5 fs/9p: Add v9fs_i... |
210 |
v9inode); |
60e78d2c9 9p: Add fscache s... |
211 |
|
5d3851530 9p: Reduce object... |
212 213 214 |
p9_debug(P9_DEBUG_FSC, "inode %p get cookie %p ", inode, v9inode->fscache); |
60e78d2c9 9p: Add fscache s... |
215 216 217 218 |
} void v9fs_cache_inode_put_cookie(struct inode *inode) { |
a78ce05d5 fs/9p: Add v9fs_i... |
219 |
struct v9fs_inode *v9inode = V9FS_I(inode); |
60e78d2c9 9p: Add fscache s... |
220 |
|
a78ce05d5 fs/9p: Add v9fs_i... |
221 |
if (!v9inode->fscache) |
60e78d2c9 9p: Add fscache s... |
222 |
return; |
5d3851530 9p: Reduce object... |
223 224 225 |
p9_debug(P9_DEBUG_FSC, "inode %p put cookie %p ", inode, v9inode->fscache); |
60e78d2c9 9p: Add fscache s... |
226 |
|
a78ce05d5 fs/9p: Add v9fs_i... |
227 228 |
fscache_relinquish_cookie(v9inode->fscache, 0); v9inode->fscache = NULL; |
60e78d2c9 9p: Add fscache s... |
229 230 231 232 |
} void v9fs_cache_inode_flush_cookie(struct inode *inode) { |
a78ce05d5 fs/9p: Add v9fs_i... |
233 |
struct v9fs_inode *v9inode = V9FS_I(inode); |
60e78d2c9 9p: Add fscache s... |
234 |
|
a78ce05d5 fs/9p: Add v9fs_i... |
235 |
if (!v9inode->fscache) |
60e78d2c9 9p: Add fscache s... |
236 |
return; |
5d3851530 9p: Reduce object... |
237 238 239 |
p9_debug(P9_DEBUG_FSC, "inode %p flush cookie %p ", inode, v9inode->fscache); |
60e78d2c9 9p: Add fscache s... |
240 |
|
a78ce05d5 fs/9p: Add v9fs_i... |
241 242 |
fscache_relinquish_cookie(v9inode->fscache, 1); v9inode->fscache = NULL; |
60e78d2c9 9p: Add fscache s... |
243 244 245 246 |
} void v9fs_cache_inode_set_cookie(struct inode *inode, struct file *filp) { |
a78ce05d5 fs/9p: Add v9fs_i... |
247 |
struct v9fs_inode *v9inode = V9FS_I(inode); |
60e78d2c9 9p: Add fscache s... |
248 |
struct p9_fid *fid; |
a78ce05d5 fs/9p: Add v9fs_i... |
249 |
if (!v9inode->fscache) |
60e78d2c9 9p: Add fscache s... |
250 |
return; |
a78ce05d5 fs/9p: Add v9fs_i... |
251 |
spin_lock(&v9inode->fscache_lock); |
60e78d2c9 9p: Add fscache s... |
252 253 254 255 256 |
fid = filp->private_data; if ((filp->f_flags & O_ACCMODE) != O_RDONLY) v9fs_cache_inode_flush_cookie(inode); else v9fs_cache_inode_get_cookie(inode); |
a78ce05d5 fs/9p: Add v9fs_i... |
257 |
spin_unlock(&v9inode->fscache_lock); |
60e78d2c9 9p: Add fscache s... |
258 259 260 261 |
} void v9fs_cache_inode_reset_cookie(struct inode *inode) { |
a78ce05d5 fs/9p: Add v9fs_i... |
262 |
struct v9fs_inode *v9inode = V9FS_I(inode); |
60e78d2c9 9p: Add fscache s... |
263 264 |
struct v9fs_session_info *v9ses; struct fscache_cookie *old; |
a78ce05d5 fs/9p: Add v9fs_i... |
265 |
if (!v9inode->fscache) |
60e78d2c9 9p: Add fscache s... |
266 |
return; |
a78ce05d5 fs/9p: Add v9fs_i... |
267 |
old = v9inode->fscache; |
60e78d2c9 9p: Add fscache s... |
268 |
|
a78ce05d5 fs/9p: Add v9fs_i... |
269 270 |
spin_lock(&v9inode->fscache_lock); fscache_relinquish_cookie(v9inode->fscache, 1); |
60e78d2c9 9p: Add fscache s... |
271 272 |
v9ses = v9fs_inode2v9ses(inode); |
a78ce05d5 fs/9p: Add v9fs_i... |
273 |
v9inode->fscache = fscache_acquire_cookie(v9ses->fscache, |
60e78d2c9 9p: Add fscache s... |
274 |
&v9fs_cache_inode_index_def, |
a78ce05d5 fs/9p: Add v9fs_i... |
275 |
v9inode); |
5d3851530 9p: Reduce object... |
276 277 278 |
p9_debug(P9_DEBUG_FSC, "inode %p revalidating cookie old %p new %p ", inode, old, v9inode->fscache); |
60e78d2c9 9p: Add fscache s... |
279 |
|
a78ce05d5 fs/9p: Add v9fs_i... |
280 |
spin_unlock(&v9inode->fscache_lock); |
60e78d2c9 9p: Add fscache s... |
281 282 283 284 285 |
} int __v9fs_fscache_release_page(struct page *page, gfp_t gfp) { struct inode *inode = page->mapping->host; |
a78ce05d5 fs/9p: Add v9fs_i... |
286 |
struct v9fs_inode *v9inode = V9FS_I(inode); |
60e78d2c9 9p: Add fscache s... |
287 |
|
a78ce05d5 fs/9p: Add v9fs_i... |
288 |
BUG_ON(!v9inode->fscache); |
60e78d2c9 9p: Add fscache s... |
289 |
|
a78ce05d5 fs/9p: Add v9fs_i... |
290 |
return fscache_maybe_release_page(v9inode->fscache, page, gfp); |
60e78d2c9 9p: Add fscache s... |
291 292 293 294 295 |
} void __v9fs_fscache_invalidate_page(struct page *page) { struct inode *inode = page->mapping->host; |
a78ce05d5 fs/9p: Add v9fs_i... |
296 |
struct v9fs_inode *v9inode = V9FS_I(inode); |
60e78d2c9 9p: Add fscache s... |
297 |
|
a78ce05d5 fs/9p: Add v9fs_i... |
298 |
BUG_ON(!v9inode->fscache); |
60e78d2c9 9p: Add fscache s... |
299 300 |
if (PageFsCache(page)) { |
a78ce05d5 fs/9p: Add v9fs_i... |
301 |
fscache_wait_on_page_write(v9inode->fscache, page); |
60e78d2c9 9p: Add fscache s... |
302 |
BUG_ON(!PageLocked(page)); |
a78ce05d5 fs/9p: Add v9fs_i... |
303 |
fscache_uncache_page(v9inode->fscache, page); |
60e78d2c9 9p: Add fscache s... |
304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 |
} } static void v9fs_vfs_readpage_complete(struct page *page, void *data, int error) { if (!error) SetPageUptodate(page); unlock_page(page); } /** * __v9fs_readpage_from_fscache - read a page from cache * * Returns 0 if the pages are in cache and a BIO is submitted, * 1 if the pages are not in cache and -error otherwise. */ int __v9fs_readpage_from_fscache(struct inode *inode, struct page *page) { int ret; |
a78ce05d5 fs/9p: Add v9fs_i... |
326 |
const struct v9fs_inode *v9inode = V9FS_I(inode); |
60e78d2c9 9p: Add fscache s... |
327 |
|
5d3851530 9p: Reduce object... |
328 329 |
p9_debug(P9_DEBUG_FSC, "inode %p page %p ", inode, page); |
a78ce05d5 fs/9p: Add v9fs_i... |
330 |
if (!v9inode->fscache) |
60e78d2c9 9p: Add fscache s... |
331 |
return -ENOBUFS; |
a78ce05d5 fs/9p: Add v9fs_i... |
332 |
ret = fscache_read_or_alloc_page(v9inode->fscache, |
60e78d2c9 9p: Add fscache s... |
333 334 335 336 337 338 339 |
page, v9fs_vfs_readpage_complete, NULL, GFP_KERNEL); switch (ret) { case -ENOBUFS: case -ENODATA: |
5d3851530 9p: Reduce object... |
340 341 |
p9_debug(P9_DEBUG_FSC, "page/inode not in cache %d ", ret); |
60e78d2c9 9p: Add fscache s... |
342 343 |
return 1; case 0: |
5d3851530 9p: Reduce object... |
344 345 |
p9_debug(P9_DEBUG_FSC, "BIO submitted "); |
60e78d2c9 9p: Add fscache s... |
346 347 |
return ret; default: |
5d3851530 9p: Reduce object... |
348 349 |
p9_debug(P9_DEBUG_FSC, "ret %d ", ret); |
60e78d2c9 9p: Add fscache s... |
350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 |
return ret; } } /** * __v9fs_readpages_from_fscache - read multiple pages from cache * * Returns 0 if the pages are in cache and a BIO is submitted, * 1 if the pages are not in cache and -error otherwise. */ int __v9fs_readpages_from_fscache(struct inode *inode, struct address_space *mapping, struct list_head *pages, unsigned *nr_pages) { int ret; |
a78ce05d5 fs/9p: Add v9fs_i... |
367 |
const struct v9fs_inode *v9inode = V9FS_I(inode); |
60e78d2c9 9p: Add fscache s... |
368 |
|
5d3851530 9p: Reduce object... |
369 370 |
p9_debug(P9_DEBUG_FSC, "inode %p pages %u ", inode, *nr_pages); |
a78ce05d5 fs/9p: Add v9fs_i... |
371 |
if (!v9inode->fscache) |
60e78d2c9 9p: Add fscache s... |
372 |
return -ENOBUFS; |
a78ce05d5 fs/9p: Add v9fs_i... |
373 |
ret = fscache_read_or_alloc_pages(v9inode->fscache, |
60e78d2c9 9p: Add fscache s... |
374 375 376 377 378 379 380 |
mapping, pages, nr_pages, v9fs_vfs_readpage_complete, NULL, mapping_gfp_mask(mapping)); switch (ret) { case -ENOBUFS: case -ENODATA: |
5d3851530 9p: Reduce object... |
381 382 |
p9_debug(P9_DEBUG_FSC, "pages/inodes not in cache %d ", ret); |
60e78d2c9 9p: Add fscache s... |
383 384 385 386 |
return 1; case 0: BUG_ON(!list_empty(pages)); BUG_ON(*nr_pages != 0); |
5d3851530 9p: Reduce object... |
387 388 |
p9_debug(P9_DEBUG_FSC, "BIO submitted "); |
60e78d2c9 9p: Add fscache s... |
389 390 |
return ret; default: |
5d3851530 9p: Reduce object... |
391 392 |
p9_debug(P9_DEBUG_FSC, "ret %d ", ret); |
60e78d2c9 9p: Add fscache s... |
393 394 395 396 397 398 399 400 401 402 403 404 |
return ret; } } /** * __v9fs_readpage_to_fscache - write a page to the cache * */ void __v9fs_readpage_to_fscache(struct inode *inode, struct page *page) { int ret; |
a78ce05d5 fs/9p: Add v9fs_i... |
405 |
const struct v9fs_inode *v9inode = V9FS_I(inode); |
60e78d2c9 9p: Add fscache s... |
406 |
|
5d3851530 9p: Reduce object... |
407 408 |
p9_debug(P9_DEBUG_FSC, "inode %p page %p ", inode, page); |
a78ce05d5 fs/9p: Add v9fs_i... |
409 |
ret = fscache_write_page(v9inode->fscache, page, GFP_KERNEL); |
5d3851530 9p: Reduce object... |
410 411 |
p9_debug(P9_DEBUG_FSC, "ret = %d ", ret); |
60e78d2c9 9p: Add fscache s... |
412 413 414 |
if (ret != 0) v9fs_uncache_page(inode, page); } |
2efda7998 fs/9p: [fscache] ... |
415 416 417 418 419 420 |
/* * wait for a page to complete writing to the cache */ void __v9fs_fscache_wait_on_page_write(struct inode *inode, struct page *page) { |
a78ce05d5 fs/9p: Add v9fs_i... |
421 |
const struct v9fs_inode *v9inode = V9FS_I(inode); |
5d3851530 9p: Reduce object... |
422 423 |
p9_debug(P9_DEBUG_FSC, "inode %p page %p ", inode, page); |
2efda7998 fs/9p: [fscache] ... |
424 |
if (PageFsCache(page)) |
a78ce05d5 fs/9p: Add v9fs_i... |
425 |
fscache_wait_on_page_write(v9inode->fscache, page); |
2efda7998 fs/9p: [fscache] ... |
426 |
} |