[AF_RXRPC]: Make the in-kernel AFS filesystem use AF_RXRPC.
[safe/jmp/linux-2.6] / fs / afs / file.c
1 /* AFS filesystem file handling
2  *
3  * Copyright (C) 2002, 2007 Red Hat, Inc. All Rights Reserved.
4  * Written by David Howells (dhowells@redhat.com)
5  *
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.
10  */
11
12 #include <linux/kernel.h>
13 #include <linux/module.h>
14 #include <linux/init.h>
15 #include <linux/slab.h>
16 #include <linux/fs.h>
17 #include <linux/pagemap.h>
18 #include "internal.h"
19
20 #if 0
21 static int afs_file_open(struct inode *inode, struct file *file);
22 static int afs_file_release(struct inode *inode, struct file *file);
23 #endif
24
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);
28
29 const struct inode_operations afs_file_inode_operations = {
30         .getattr        = afs_inode_getattr,
31 };
32
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,
38 };
39
40 /*
41  * deal with notification that a page was read from the cache
42  */
43 #ifdef AFS_CACHING_SUPPORT
44 static void afs_file_readpage_read_complete(void *cookie_data,
45                                             struct page *page,
46                                             void *data,
47                                             int error)
48 {
49         _enter("%p,%p,%p,%d", cookie_data, page, data, error);
50
51         if (error)
52                 SetPageError(page);
53         else
54                 SetPageUptodate(page);
55         unlock_page(page);
56
57 }
58 #endif
59
60 /*
61  * deal with notification that a page was written to the cache
62  */
63 #ifdef AFS_CACHING_SUPPORT
64 static void afs_file_readpage_write_complete(void *cookie_data,
65                                              struct page *page,
66                                              void *data,
67                                              int error)
68 {
69         _enter("%p,%p,%p,%d", cookie_data, page, data, error);
70
71         unlock_page(page);
72 }
73 #endif
74
75 /*
76  * AFS read page from file (or symlink)
77  */
78 static int afs_file_readpage(struct file *file, struct page *page)
79 {
80         struct afs_vnode *vnode;
81         struct inode *inode;
82         size_t len;
83         off_t offset;
84         int ret;
85
86         inode = page->mapping->host;
87
88         _enter("{%lu},{%lu}", inode->i_ino, page->index);
89
90         vnode = AFS_FS_I(inode);
91
92         BUG_ON(!PageLocked(page));
93
94         ret = -ESTALE;
95         if (test_bit(AFS_VNODE_DELETED, &vnode->flags))
96                 goto error;
97
98 #ifdef AFS_CACHING_SUPPORT
99         /* is it cached? */
100         ret = cachefs_read_or_alloc_page(vnode->cache,
101                                          page,
102                                          afs_file_readpage_read_complete,
103                                          NULL,
104                                          GFP_KERNEL);
105 #else
106         ret = -ENOBUFS;
107 #endif
108
109         switch (ret) {
110                 /* read BIO submitted and wb-journal entry found */
111         case 1:
112                 BUG(); // TODO - handle wb-journal match
113
114                 /* read BIO submitted (page in cache) */
115         case 0:
116                 break;
117
118                 /* no page available in cache */
119         case -ENOBUFS:
120         case -ENODATA:
121         default:
122                 offset = page->index << PAGE_CACHE_SHIFT;
123                 len = min_t(size_t, i_size_read(inode) - offset, PAGE_SIZE);
124
125                 /* read the contents of the file from the server into the
126                  * page */
127                 ret = afs_vnode_fetch_data(vnode, offset, len, page);
128                 if (ret < 0) {
129                         if (ret == -ENOENT) {
130                                 _debug("got NOENT from server"
131                                        " - marking file deleted and stale");
132                                 set_bit(AFS_VNODE_DELETED, &vnode->flags);
133                                 ret = -ESTALE;
134                         }
135 #ifdef AFS_CACHING_SUPPORT
136                         cachefs_uncache_page(vnode->cache, page);
137 #endif
138                         goto error;
139                 }
140
141                 SetPageUptodate(page);
142
143 #ifdef AFS_CACHING_SUPPORT
144                 if (cachefs_write_page(vnode->cache,
145                                        page,
146                                        afs_file_readpage_write_complete,
147                                        NULL,
148                                        GFP_KERNEL) != 0
149                     ) {
150                         cachefs_uncache_page(vnode->cache, page);
151                         unlock_page(page);
152                 }
153 #else
154                 unlock_page(page);
155 #endif
156         }
157
158         _leave(" = 0");
159         return 0;
160
161 error:
162         SetPageError(page);
163         unlock_page(page);
164         _leave(" = %d", ret);
165         return ret;
166 }
167
168 /*
169  * get a page cookie for the specified page
170  */
171 #ifdef AFS_CACHING_SUPPORT
172 int afs_cache_get_page_cookie(struct page *page,
173                               struct cachefs_page **_page_cookie)
174 {
175         int ret;
176
177         _enter("");
178         ret = cachefs_page_get_private(page,_page_cookie, GFP_NOIO);
179
180         _leave(" = %d", ret);
181         return ret;
182 }
183 #endif
184
185 /*
186  * invalidate part or all of a page
187  */
188 static void afs_file_invalidatepage(struct page *page, unsigned long offset)
189 {
190         int ret = 1;
191
192         _enter("{%lu},%lu", page->index, offset);
193
194         BUG_ON(!PageLocked(page));
195
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);
200 #endif
201
202                 /* We release buffers only if the entire page is being
203                  * invalidated.
204                  * The get_block cached value has been unconditionally
205                  * invalidated, so real IO is not possible anymore.
206                  */
207                 if (offset == 0) {
208                         BUG_ON(!PageLocked(page));
209
210                         ret = 0;
211                         if (!PageWriteback(page))
212                                 ret = page->mapping->a_ops->releasepage(page,
213                                                                         0);
214                         /* possibly should BUG_ON(!ret); - neilb */
215                 }
216         }
217
218         _leave(" = %d", ret);
219 }
220
221 /*
222  * release a page and cleanup its private data
223  */
224 static int afs_file_releasepage(struct page *page, gfp_t gfp_flags)
225 {
226         struct cachefs_page *pageio;
227
228         _enter("{%lu},%x", page->index, gfp_flags);
229
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);
234 #endif
235
236                 pageio = (struct cachefs_page *) page_private(page);
237                 set_page_private(page, 0);
238                 ClearPagePrivate(page);
239
240                 kfree(pageio);
241         }
242
243         _leave(" = 0");
244         return 0;
245 }