diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/cifs/cache.c | 31 | ||||
-rw-r--r-- | fs/cifs/file.c | 20 | ||||
-rw-r--r-- | fs/cifs/fscache.c | 26 | ||||
-rw-r--r-- | fs/cifs/fscache.h | 16 |
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 | ||
293 | static 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 | |||
293 | const struct fscache_cookie_def cifs_fscache_inode_object_def = { | 323 | const 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 | ||
2270 | static 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 | |||
2278 | static 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 | |||
2270 | static void | 2286 | static void |
2271 | cifs_oplock_break(struct slow_work *work) | 2287 | cifs_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 | |||
128 | int 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 | |||
143 | void __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 *); | |||
48 | extern void cifs_fscache_set_inode_cookie(struct inode *, struct file *); | 48 | extern void cifs_fscache_set_inode_cookie(struct inode *, struct file *); |
49 | extern void cifs_fscache_reset_inode_cookie(struct inode *); | 49 | extern void cifs_fscache_reset_inode_cookie(struct inode *); |
50 | 50 | ||
51 | extern void __cifs_fscache_invalidate_page(struct page *, struct inode *); | ||
52 | extern int cifs_fscache_release_page(struct page *page, gfp_t gfp); | ||
53 | |||
54 | static 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 */ |
52 | static inline int cifs_fscache_register(void) { return 0; } | 62 | static inline int cifs_fscache_register(void) { return 0; } |
53 | static inline void cifs_fscache_unregister(void) {} | 63 | static inline void cifs_fscache_unregister(void) {} |
@@ -64,7 +74,13 @@ static inline void cifs_fscache_release_inode_cookie(struct inode *inode) {} | |||
64 | static inline void cifs_fscache_set_inode_cookie(struct inode *inode, | 74 | static inline void cifs_fscache_set_inode_cookie(struct inode *inode, |
65 | struct file *filp) {} | 75 | struct file *filp) {} |
66 | static inline void cifs_fscache_reset_inode_cookie(struct inode *inode) {} | 76 | static inline void cifs_fscache_reset_inode_cookie(struct inode *inode) {} |
77 | static inline void cifs_fscache_release_page(struct page *page, gfp_t gfp) | ||
78 | { | ||
79 | return 1; /* May release page */ | ||
80 | } | ||
67 | 81 | ||
82 | static 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 | ||