Blame view
fs/9p/cache.c
10.4 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 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
/** * 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; P9_DPRINTK(P9_DEBUG_FSC, "session %p buf %p size %u", v9ses, buffer, bufmax); if (v9ses->cachetag) klen = strlen(v9ses->cachetag); if (klen > bufmax) return 0; memcpy(buffer, v9ses->cachetag, klen); P9_DPRINTK(P9_DEBUG_FSC, "cache session tag %s", v9ses->cachetag); return klen; } const struct fscache_cookie_def v9fs_cache_session_index_def = { |
a78ce05d5 fs/9p: Add v9fs_i... |
78 79 80 |
.name = "9P.session", .type = FSCACHE_COOKIE_TYPE_INDEX, .get_key = v9fs_cache_session_get_key, |
60e78d2c9 9p: Add fscache s... |
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
}; 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); P9_DPRINTK(P9_DEBUG_FSC, "session %p get cookie %p", v9ses, v9ses->fscache); } void v9fs_cache_session_put_cookie(struct v9fs_session_info *v9ses) { P9_DPRINTK(P9_DEBUG_FSC, "session %p put cookie %p", v9ses, v9ses->fscache); 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... |
108 |
const struct v9fs_inode *v9inode = cookie_netfs_data; |
fd2421f54 fs/9p: When doing... |
109 |
memcpy(buffer, &v9inode->qid.path, sizeof(v9inode->qid.path)); |
a78ce05d5 fs/9p: Add v9fs_i... |
110 |
P9_DPRINTK(P9_DEBUG_FSC, "inode %p get key %llu", &v9inode->vfs_inode, |
fd2421f54 fs/9p: When doing... |
111 112 |
v9inode->qid.path); return sizeof(v9inode->qid.path); |
60e78d2c9 9p: Add fscache s... |
113 114 115 116 117 |
} static void v9fs_cache_inode_get_attr(const void *cookie_netfs_data, uint64_t *size) { |
a78ce05d5 fs/9p: Add v9fs_i... |
118 119 |
const struct v9fs_inode *v9inode = cookie_netfs_data; *size = i_size_read(&v9inode->vfs_inode); |
60e78d2c9 9p: Add fscache s... |
120 |
|
a78ce05d5 fs/9p: Add v9fs_i... |
121 |
P9_DPRINTK(P9_DEBUG_FSC, "inode %p get attr %llu", &v9inode->vfs_inode, |
60e78d2c9 9p: Add fscache s... |
122 123 124 125 126 127 |
*size); } static uint16_t v9fs_cache_inode_get_aux(const void *cookie_netfs_data, void *buffer, uint16_t buflen) { |
a78ce05d5 fs/9p: Add v9fs_i... |
128 |
const struct v9fs_inode *v9inode = cookie_netfs_data; |
fd2421f54 fs/9p: When doing... |
129 |
memcpy(buffer, &v9inode->qid.version, sizeof(v9inode->qid.version)); |
a78ce05d5 fs/9p: Add v9fs_i... |
130 |
P9_DPRINTK(P9_DEBUG_FSC, "inode %p get aux %u", &v9inode->vfs_inode, |
fd2421f54 fs/9p: When doing... |
131 132 |
v9inode->qid.version); return sizeof(v9inode->qid.version); |
60e78d2c9 9p: Add fscache s... |
133 134 135 136 137 138 139 |
} 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... |
140 |
const struct v9fs_inode *v9inode = cookie_netfs_data; |
60e78d2c9 9p: Add fscache s... |
141 |
|
fd2421f54 fs/9p: When doing... |
142 |
if (buflen != sizeof(v9inode->qid.version)) |
60e78d2c9 9p: Add fscache s... |
143 |
return FSCACHE_CHECKAUX_OBSOLETE; |
fd2421f54 fs/9p: When doing... |
144 145 |
if (memcmp(buffer, &v9inode->qid.version, sizeof(v9inode->qid.version))) |
60e78d2c9 9p: Add fscache s... |
146 147 148 149 150 151 152 |
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... |
153 |
struct v9fs_inode *v9inode = cookie_netfs_data; |
60e78d2c9 9p: Add fscache s... |
154 155 156 157 158 159 160 161 |
struct pagevec pvec; pgoff_t first; int loop, nr_pages; pagevec_init(&pvec, 0); first = 0; for (;;) { |
a78ce05d5 fs/9p: Add v9fs_i... |
162 |
nr_pages = pagevec_lookup(&pvec, v9inode->vfs_inode.i_mapping, |
60e78d2c9 9p: Add fscache s... |
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 |
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... |
191 |
struct v9fs_inode *v9inode; |
60e78d2c9 9p: Add fscache s... |
192 193 194 195 |
struct v9fs_session_info *v9ses; if (!S_ISREG(inode->i_mode)) return; |
a78ce05d5 fs/9p: Add v9fs_i... |
196 197 |
v9inode = V9FS_I(inode); if (v9inode->fscache) |
60e78d2c9 9p: Add fscache s... |
198 199 200 |
return; v9ses = v9fs_inode2v9ses(inode); |
a78ce05d5 fs/9p: Add v9fs_i... |
201 |
v9inode->fscache = fscache_acquire_cookie(v9ses->fscache, |
60e78d2c9 9p: Add fscache s... |
202 |
&v9fs_cache_inode_index_def, |
a78ce05d5 fs/9p: Add v9fs_i... |
203 |
v9inode); |
60e78d2c9 9p: Add fscache s... |
204 205 |
P9_DPRINTK(P9_DEBUG_FSC, "inode %p get cookie %p", inode, |
a78ce05d5 fs/9p: Add v9fs_i... |
206 |
v9inode->fscache); |
60e78d2c9 9p: Add fscache s... |
207 208 209 210 |
} void v9fs_cache_inode_put_cookie(struct inode *inode) { |
a78ce05d5 fs/9p: Add v9fs_i... |
211 |
struct v9fs_inode *v9inode = V9FS_I(inode); |
60e78d2c9 9p: Add fscache s... |
212 |
|
a78ce05d5 fs/9p: Add v9fs_i... |
213 |
if (!v9inode->fscache) |
60e78d2c9 9p: Add fscache s... |
214 215 |
return; P9_DPRINTK(P9_DEBUG_FSC, "inode %p put cookie %p", inode, |
a78ce05d5 fs/9p: Add v9fs_i... |
216 |
v9inode->fscache); |
60e78d2c9 9p: Add fscache s... |
217 |
|
a78ce05d5 fs/9p: Add v9fs_i... |
218 219 |
fscache_relinquish_cookie(v9inode->fscache, 0); v9inode->fscache = NULL; |
60e78d2c9 9p: Add fscache s... |
220 221 222 223 |
} void v9fs_cache_inode_flush_cookie(struct inode *inode) { |
a78ce05d5 fs/9p: Add v9fs_i... |
224 |
struct v9fs_inode *v9inode = V9FS_I(inode); |
60e78d2c9 9p: Add fscache s... |
225 |
|
a78ce05d5 fs/9p: Add v9fs_i... |
226 |
if (!v9inode->fscache) |
60e78d2c9 9p: Add fscache s... |
227 228 |
return; P9_DPRINTK(P9_DEBUG_FSC, "inode %p flush cookie %p", inode, |
a78ce05d5 fs/9p: Add v9fs_i... |
229 |
v9inode->fscache); |
60e78d2c9 9p: Add fscache s... |
230 |
|
a78ce05d5 fs/9p: Add v9fs_i... |
231 232 |
fscache_relinquish_cookie(v9inode->fscache, 1); v9inode->fscache = NULL; |
60e78d2c9 9p: Add fscache s... |
233 234 235 236 |
} void v9fs_cache_inode_set_cookie(struct inode *inode, struct file *filp) { |
a78ce05d5 fs/9p: Add v9fs_i... |
237 |
struct v9fs_inode *v9inode = V9FS_I(inode); |
60e78d2c9 9p: Add fscache s... |
238 |
struct p9_fid *fid; |
a78ce05d5 fs/9p: Add v9fs_i... |
239 |
if (!v9inode->fscache) |
60e78d2c9 9p: Add fscache s... |
240 |
return; |
a78ce05d5 fs/9p: Add v9fs_i... |
241 |
spin_lock(&v9inode->fscache_lock); |
60e78d2c9 9p: Add fscache s... |
242 243 244 245 246 |
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... |
247 |
spin_unlock(&v9inode->fscache_lock); |
60e78d2c9 9p: Add fscache s... |
248 249 250 251 |
} void v9fs_cache_inode_reset_cookie(struct inode *inode) { |
a78ce05d5 fs/9p: Add v9fs_i... |
252 |
struct v9fs_inode *v9inode = V9FS_I(inode); |
60e78d2c9 9p: Add fscache s... |
253 254 |
struct v9fs_session_info *v9ses; struct fscache_cookie *old; |
a78ce05d5 fs/9p: Add v9fs_i... |
255 |
if (!v9inode->fscache) |
60e78d2c9 9p: Add fscache s... |
256 |
return; |
a78ce05d5 fs/9p: Add v9fs_i... |
257 |
old = v9inode->fscache; |
60e78d2c9 9p: Add fscache s... |
258 |
|
a78ce05d5 fs/9p: Add v9fs_i... |
259 260 |
spin_lock(&v9inode->fscache_lock); fscache_relinquish_cookie(v9inode->fscache, 1); |
60e78d2c9 9p: Add fscache s... |
261 262 |
v9ses = v9fs_inode2v9ses(inode); |
a78ce05d5 fs/9p: Add v9fs_i... |
263 |
v9inode->fscache = fscache_acquire_cookie(v9ses->fscache, |
60e78d2c9 9p: Add fscache s... |
264 |
&v9fs_cache_inode_index_def, |
a78ce05d5 fs/9p: Add v9fs_i... |
265 |
v9inode); |
60e78d2c9 9p: Add fscache s... |
266 |
P9_DPRINTK(P9_DEBUG_FSC, "inode %p revalidating cookie old %p new %p", |
a78ce05d5 fs/9p: Add v9fs_i... |
267 |
inode, old, v9inode->fscache); |
60e78d2c9 9p: Add fscache s... |
268 |
|
a78ce05d5 fs/9p: Add v9fs_i... |
269 |
spin_unlock(&v9inode->fscache_lock); |
60e78d2c9 9p: Add fscache s... |
270 271 272 273 274 |
} int __v9fs_fscache_release_page(struct page *page, gfp_t gfp) { struct inode *inode = page->mapping->host; |
a78ce05d5 fs/9p: Add v9fs_i... |
275 |
struct v9fs_inode *v9inode = V9FS_I(inode); |
60e78d2c9 9p: Add fscache s... |
276 |
|
a78ce05d5 fs/9p: Add v9fs_i... |
277 |
BUG_ON(!v9inode->fscache); |
60e78d2c9 9p: Add fscache s... |
278 |
|
a78ce05d5 fs/9p: Add v9fs_i... |
279 |
return fscache_maybe_release_page(v9inode->fscache, page, gfp); |
60e78d2c9 9p: Add fscache s... |
280 281 282 283 284 |
} void __v9fs_fscache_invalidate_page(struct page *page) { struct inode *inode = page->mapping->host; |
a78ce05d5 fs/9p: Add v9fs_i... |
285 |
struct v9fs_inode *v9inode = V9FS_I(inode); |
60e78d2c9 9p: Add fscache s... |
286 |
|
a78ce05d5 fs/9p: Add v9fs_i... |
287 |
BUG_ON(!v9inode->fscache); |
60e78d2c9 9p: Add fscache s... |
288 289 |
if (PageFsCache(page)) { |
a78ce05d5 fs/9p: Add v9fs_i... |
290 |
fscache_wait_on_page_write(v9inode->fscache, page); |
60e78d2c9 9p: Add fscache s... |
291 |
BUG_ON(!PageLocked(page)); |
a78ce05d5 fs/9p: Add v9fs_i... |
292 |
fscache_uncache_page(v9inode->fscache, page); |
60e78d2c9 9p: Add fscache s... |
293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 |
} } 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... |
315 |
const struct v9fs_inode *v9inode = V9FS_I(inode); |
60e78d2c9 9p: Add fscache s... |
316 317 |
P9_DPRINTK(P9_DEBUG_FSC, "inode %p page %p", inode, page); |
a78ce05d5 fs/9p: Add v9fs_i... |
318 |
if (!v9inode->fscache) |
60e78d2c9 9p: Add fscache s... |
319 |
return -ENOBUFS; |
a78ce05d5 fs/9p: Add v9fs_i... |
320 |
ret = fscache_read_or_alloc_page(v9inode->fscache, |
60e78d2c9 9p: Add fscache s... |
321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 |
page, v9fs_vfs_readpage_complete, NULL, GFP_KERNEL); switch (ret) { case -ENOBUFS: case -ENODATA: P9_DPRINTK(P9_DEBUG_FSC, "page/inode not in cache %d", ret); return 1; case 0: P9_DPRINTK(P9_DEBUG_FSC, "BIO submitted"); return ret; default: P9_DPRINTK(P9_DEBUG_FSC, "ret %d", ret); 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... |
352 |
const struct v9fs_inode *v9inode = V9FS_I(inode); |
60e78d2c9 9p: Add fscache s... |
353 354 |
P9_DPRINTK(P9_DEBUG_FSC, "inode %p pages %u", inode, *nr_pages); |
a78ce05d5 fs/9p: Add v9fs_i... |
355 |
if (!v9inode->fscache) |
60e78d2c9 9p: Add fscache s... |
356 |
return -ENOBUFS; |
a78ce05d5 fs/9p: Add v9fs_i... |
357 |
ret = fscache_read_or_alloc_pages(v9inode->fscache, |
60e78d2c9 9p: Add fscache s... |
358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 |
mapping, pages, nr_pages, v9fs_vfs_readpage_complete, NULL, mapping_gfp_mask(mapping)); switch (ret) { case -ENOBUFS: case -ENODATA: P9_DPRINTK(P9_DEBUG_FSC, "pages/inodes not in cache %d", ret); return 1; case 0: BUG_ON(!list_empty(pages)); BUG_ON(*nr_pages != 0); P9_DPRINTK(P9_DEBUG_FSC, "BIO submitted"); return ret; default: P9_DPRINTK(P9_DEBUG_FSC, "ret %d", ret); 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... |
386 |
const struct v9fs_inode *v9inode = V9FS_I(inode); |
60e78d2c9 9p: Add fscache s... |
387 388 |
P9_DPRINTK(P9_DEBUG_FSC, "inode %p page %p", inode, page); |
a78ce05d5 fs/9p: Add v9fs_i... |
389 |
ret = fscache_write_page(v9inode->fscache, page, GFP_KERNEL); |
60e78d2c9 9p: Add fscache s... |
390 391 392 393 |
P9_DPRINTK(P9_DEBUG_FSC, "ret = %d", ret); if (ret != 0) v9fs_uncache_page(inode, page); } |
2efda7998 fs/9p: [fscache] ... |
394 395 396 397 398 399 |
/* * 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... |
400 |
const struct v9fs_inode *v9inode = V9FS_I(inode); |
2efda7998 fs/9p: [fscache] ... |
401 402 |
P9_DPRINTK(P9_DEBUG_FSC, "inode %p page %p", inode, page); if (PageFsCache(page)) |
a78ce05d5 fs/9p: Add v9fs_i... |
403 |
fscache_wait_on_page_write(v9inode->fscache, page); |
2efda7998 fs/9p: [fscache] ... |
404 |
} |