1 /* AFS filesystem file handling
3 * Copyright (C) 2002, 2007 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
12 #include <linux/kernel.h>
13 #include <linux/module.h>
14 #include <linux/init.h>
15 #include <linux/slab.h>
17 #include <linux/pagemap.h>
21 static int afs_file_open(struct inode *inode, struct file *file);
22 static int afs_file_release(struct inode *inode, struct file *file);
25 static int afs_file_readpage(struct file *file, struct page *page);
26 static void afs_file_invalidatepage(struct page *page, unsigned long offset);
27 static int afs_file_releasepage(struct page *page, gfp_t gfp_flags);
29 const struct inode_operations afs_file_inode_operations = {
30 .getattr = afs_inode_getattr,
33 const struct address_space_operations afs_fs_aops = {
34 .readpage = afs_file_readpage,
35 .set_page_dirty = __set_page_dirty_nobuffers,
36 .releasepage = afs_file_releasepage,
37 .invalidatepage = afs_file_invalidatepage,
41 * deal with notification that a page was read from the cache
43 #ifdef AFS_CACHING_SUPPORT
44 static void afs_file_readpage_read_complete(void *cookie_data,
49 _enter("%p,%p,%p,%d", cookie_data, page, data, error);
54 SetPageUptodate(page);
61 * deal with notification that a page was written to the cache
63 #ifdef AFS_CACHING_SUPPORT
64 static void afs_file_readpage_write_complete(void *cookie_data,
69 _enter("%p,%p,%p,%d", cookie_data, page, data, error);
76 * AFS read page from file (or symlink)
78 static int afs_file_readpage(struct file *file, struct page *page)
80 struct afs_vnode *vnode;
86 inode = page->mapping->host;
88 _enter("{%lu},{%lu}", inode->i_ino, page->index);
90 vnode = AFS_FS_I(inode);
92 BUG_ON(!PageLocked(page));
95 if (test_bit(AFS_VNODE_DELETED, &vnode->flags))
98 #ifdef AFS_CACHING_SUPPORT
100 ret = cachefs_read_or_alloc_page(vnode->cache,
102 afs_file_readpage_read_complete,
110 /* read BIO submitted and wb-journal entry found */
112 BUG(); // TODO - handle wb-journal match
114 /* read BIO submitted (page in cache) */
118 /* no page available in cache */
122 offset = page->index << PAGE_CACHE_SHIFT;
123 len = min_t(size_t, i_size_read(inode) - offset, PAGE_SIZE);
125 /* read the contents of the file from the server into the
127 ret = afs_vnode_fetch_data(vnode, offset, len, page);
129 if (ret == -ENOENT) {
130 _debug("got NOENT from server"
131 " - marking file deleted and stale");
132 set_bit(AFS_VNODE_DELETED, &vnode->flags);
135 #ifdef AFS_CACHING_SUPPORT
136 cachefs_uncache_page(vnode->cache, page);
141 SetPageUptodate(page);
143 #ifdef AFS_CACHING_SUPPORT
144 if (cachefs_write_page(vnode->cache,
146 afs_file_readpage_write_complete,
150 cachefs_uncache_page(vnode->cache, page);
164 _leave(" = %d", ret);
169 * get a page cookie for the specified page
171 #ifdef AFS_CACHING_SUPPORT
172 int afs_cache_get_page_cookie(struct page *page,
173 struct cachefs_page **_page_cookie)
178 ret = cachefs_page_get_private(page,_page_cookie, GFP_NOIO);
180 _leave(" = %d", ret);
186 * invalidate part or all of a page
188 static void afs_file_invalidatepage(struct page *page, unsigned long offset)
192 _enter("{%lu},%lu", page->index, offset);
194 BUG_ON(!PageLocked(page));
196 if (PagePrivate(page)) {
197 #ifdef AFS_CACHING_SUPPORT
198 struct afs_vnode *vnode = AFS_FS_I(page->mapping->host);
199 cachefs_uncache_page(vnode->cache,page);
202 /* We release buffers only if the entire page is being
204 * The get_block cached value has been unconditionally
205 * invalidated, so real IO is not possible anymore.
208 BUG_ON(!PageLocked(page));
211 if (!PageWriteback(page))
212 ret = page->mapping->a_ops->releasepage(page,
214 /* possibly should BUG_ON(!ret); - neilb */
218 _leave(" = %d", ret);
222 * release a page and cleanup its private data
224 static int afs_file_releasepage(struct page *page, gfp_t gfp_flags)
226 struct cachefs_page *pageio;
228 _enter("{%lu},%x", page->index, gfp_flags);
230 if (PagePrivate(page)) {
231 #ifdef AFS_CACHING_SUPPORT
232 struct afs_vnode *vnode = AFS_FS_I(page->mapping->host);
233 cachefs_uncache_page(vnode->cache, page);
236 pageio = (struct cachefs_page *) page_private(page);
237 set_page_private(page, 0);
238 ClearPagePrivate(page);