aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs
diff options
context:
space:
mode:
authorSuresh Jayaraman <sjayaraman@suse.de>2010-07-05 08:43:00 -0400
committerSteve French <sfrench@us.ibm.com>2010-08-02 08:40:36 -0400
commit85f2d6b44d7e83bdeab87df910127c6f296866cf (patch)
tree238389c1726e212a80336551809b44b0bbedec38 /fs/cifs
parent9451a9a52f91a4c171cfaca2f6d7a2ce91867b8d (diff)
cifs: FS-Cache page management
Takes care of invalidation and release of FS-Cache marked pages and also invalidation of the FsCache page flag when the inode is removed. Signed-off-by: Suresh Jayaraman <sjayaraman@suse.de> Acked-by: David Howells <dhowells@redhat.com> Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs/cifs')
-rw-r--r--fs/cifs/cache.c31
-rw-r--r--fs/cifs/file.c20
-rw-r--r--fs/cifs/fscache.c26
-rw-r--r--fs/cifs/fscache.h16
4 files changed, 93 insertions, 0 deletions
diff --git a/fs/cifs/cache.c b/fs/cifs/cache.c
index b2649cfd3a04..224d7bbd1fcc 100644
--- a/fs/cifs/cache.c
+++ b/fs/cifs/cache.c
@@ -290,6 +290,36 @@ fscache_checkaux cifs_fscache_inode_check_aux(void *cookie_netfs_data,
290 return FSCACHE_CHECKAUX_OKAY; 290 return FSCACHE_CHECKAUX_OKAY;
291} 291}
292 292
293static void cifs_fscache_inode_now_uncached(void *cookie_netfs_data)
294{
295 struct cifsInodeInfo *cifsi = cookie_netfs_data;
296 struct pagevec pvec;
297 pgoff_t first;
298 int loop, nr_pages;
299
300 pagevec_init(&pvec, 0);
301 first = 0;
302
303 cFYI(1, "cifs inode 0x%p now uncached", cifsi);
304
305 for (;;) {
306 nr_pages = pagevec_lookup(&pvec,
307 cifsi->vfs_inode.i_mapping, first,
308 PAGEVEC_SIZE - pagevec_count(&pvec));
309 if (!nr_pages)
310 break;
311
312 for (loop = 0; loop < nr_pages; loop++)
313 ClearPageFsCache(pvec.pages[loop]);
314
315 first = pvec.pages[nr_pages - 1]->index + 1;
316
317 pvec.nr = nr_pages;
318 pagevec_release(&pvec);
319 cond_resched();
320 }
321}
322
293const struct fscache_cookie_def cifs_fscache_inode_object_def = { 323const struct fscache_cookie_def cifs_fscache_inode_object_def = {
294 .name = "CIFS.uniqueid", 324 .name = "CIFS.uniqueid",
295 .type = FSCACHE_COOKIE_TYPE_DATAFILE, 325 .type = FSCACHE_COOKIE_TYPE_DATAFILE,
@@ -297,4 +327,5 @@ const struct fscache_cookie_def cifs_fscache_inode_object_def = {
297 .get_attr = cifs_fscache_inode_get_attr, 327 .get_attr = cifs_fscache_inode_get_attr,
298 .get_aux = cifs_fscache_inode_get_aux, 328 .get_aux = cifs_fscache_inode_get_aux,
299 .check_aux = cifs_fscache_inode_check_aux, 329 .check_aux = cifs_fscache_inode_check_aux,
330 .now_uncached = cifs_fscache_inode_now_uncached,
300}; 331};
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index d302d941f9ac..f677ede766d1 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -2267,6 +2267,22 @@ out:
2267 return rc; 2267 return rc;
2268} 2268}
2269 2269
2270static int cifs_release_page(struct page *page, gfp_t gfp)
2271{
2272 if (PagePrivate(page))
2273 return 0;
2274
2275 return cifs_fscache_release_page(page, gfp);
2276}
2277
2278static void cifs_invalidate_page(struct page *page, unsigned long offset)
2279{
2280 struct cifsInodeInfo *cifsi = CIFS_I(page->mapping->host);
2281
2282 if (offset == 0)
2283 cifs_fscache_invalidate_page(page, &cifsi->vfs_inode);
2284}
2285
2270static void 2286static void
2271cifs_oplock_break(struct slow_work *work) 2287cifs_oplock_break(struct slow_work *work)
2272{ 2288{
@@ -2340,6 +2356,8 @@ const struct address_space_operations cifs_addr_ops = {
2340 .write_begin = cifs_write_begin, 2356 .write_begin = cifs_write_begin,
2341 .write_end = cifs_write_end, 2357 .write_end = cifs_write_end,
2342 .set_page_dirty = __set_page_dirty_nobuffers, 2358 .set_page_dirty = __set_page_dirty_nobuffers,
2359 .releasepage = cifs_release_page,
2360 .invalidatepage = cifs_invalidate_page,
2343 /* .sync_page = cifs_sync_page, */ 2361 /* .sync_page = cifs_sync_page, */
2344 /* .direct_IO = */ 2362 /* .direct_IO = */
2345}; 2363};
@@ -2356,6 +2374,8 @@ const struct address_space_operations cifs_addr_ops_smallbuf = {
2356 .write_begin = cifs_write_begin, 2374 .write_begin = cifs_write_begin,
2357 .write_end = cifs_write_end, 2375 .write_end = cifs_write_end,
2358 .set_page_dirty = __set_page_dirty_nobuffers, 2376 .set_page_dirty = __set_page_dirty_nobuffers,
2377 .releasepage = cifs_release_page,
2378 .invalidatepage = cifs_invalidate_page,
2359 /* .sync_page = cifs_sync_page, */ 2379 /* .sync_page = cifs_sync_page, */
2360 /* .direct_IO = */ 2380 /* .direct_IO = */
2361}; 2381};
diff --git a/fs/cifs/fscache.c b/fs/cifs/fscache.c
index 6c8d96758ddb..5dd935280049 100644
--- a/fs/cifs/fscache.c
+++ b/fs/cifs/fscache.c
@@ -124,3 +124,29 @@ void cifs_fscache_reset_inode_cookie(struct inode *inode)
124 cifsi->fscache, old); 124 cifsi->fscache, old);
125 } 125 }
126} 126}
127
128int cifs_fscache_release_page(struct page *page, gfp_t gfp)
129{
130 if (PageFsCache(page)) {
131 struct inode *inode = page->mapping->host;
132 struct cifsInodeInfo *cifsi = CIFS_I(inode);
133
134 cFYI(1, "CIFS: fscache release page (0x%p/0x%p)",
135 page, cifsi->fscache);
136 if (!fscache_maybe_release_page(cifsi->fscache, page, gfp))
137 return 0;
138 }
139
140 return 1;
141}
142
143void __cifs_fscache_invalidate_page(struct page *page, struct inode *inode)
144{
145 struct cifsInodeInfo *cifsi = CIFS_I(inode);
146 struct fscache_cookie *cookie = cifsi->fscache;
147
148 cFYI(1, "CIFS: fscache invalidatepage (0x%p/0x%p)", page, cookie);
149 fscache_wait_on_page_write(cookie, page);
150 fscache_uncache_page(cookie, page);
151}
152
diff --git a/fs/cifs/fscache.h b/fs/cifs/fscache.h
index 1008f4050835..5e18a21eee9d 100644
--- a/fs/cifs/fscache.h
+++ b/fs/cifs/fscache.h
@@ -48,6 +48,16 @@ extern void cifs_fscache_release_inode_cookie(struct inode *);
48extern void cifs_fscache_set_inode_cookie(struct inode *, struct file *); 48extern void cifs_fscache_set_inode_cookie(struct inode *, struct file *);
49extern void cifs_fscache_reset_inode_cookie(struct inode *); 49extern void cifs_fscache_reset_inode_cookie(struct inode *);
50 50
51extern void __cifs_fscache_invalidate_page(struct page *, struct inode *);
52extern int cifs_fscache_release_page(struct page *page, gfp_t gfp);
53
54static inline void cifs_fscache_invalidate_page(struct page *page,
55 struct inode *inode)
56{
57 if (PageFsCache(page))
58 __cifs_fscache_invalidate_page(page, inode);
59}
60
51#else /* CONFIG_CIFS_FSCACHE */ 61#else /* CONFIG_CIFS_FSCACHE */
52static inline int cifs_fscache_register(void) { return 0; } 62static inline int cifs_fscache_register(void) { return 0; }
53static inline void cifs_fscache_unregister(void) {} 63static inline void cifs_fscache_unregister(void) {}
@@ -64,7 +74,13 @@ static inline void cifs_fscache_release_inode_cookie(struct inode *inode) {}
64static inline void cifs_fscache_set_inode_cookie(struct inode *inode, 74static inline void cifs_fscache_set_inode_cookie(struct inode *inode,
65 struct file *filp) {} 75 struct file *filp) {}
66static inline void cifs_fscache_reset_inode_cookie(struct inode *inode) {} 76static inline void cifs_fscache_reset_inode_cookie(struct inode *inode) {}
77static inline void cifs_fscache_release_page(struct page *page, gfp_t gfp)
78{
79 return 1; /* May release page */
80}
67 81
82static inline int cifs_fscache_invalidate_page(struct page *page,
83 struct inode *) {}
68 84
69#endif /* CONFIG_CIFS_FSCACHE */ 85#endif /* CONFIG_CIFS_FSCACHE */
70 86