diff options
Diffstat (limited to 'fs/afs/file.c')
-rw-r--r-- | fs/afs/file.c | 124 |
1 files changed, 76 insertions, 48 deletions
diff --git a/fs/afs/file.c b/fs/afs/file.c index b17634541f67..ae256498f4f7 100644 --- a/fs/afs/file.c +++ b/fs/afs/file.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* file.c: AFS filesystem file handling | 1 | /* AFS filesystem file handling |
2 | * | 2 | * |
3 | * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved. | 3 | * Copyright (C) 2002, 2007 Red Hat, Inc. All Rights Reserved. |
4 | * Written by David Howells (dhowells@redhat.com) | 4 | * Written by David Howells (dhowells@redhat.com) |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or | 6 | * This program is free software; you can redistribute it and/or |
@@ -15,22 +15,25 @@ | |||
15 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
16 | #include <linux/fs.h> | 16 | #include <linux/fs.h> |
17 | #include <linux/pagemap.h> | 17 | #include <linux/pagemap.h> |
18 | #include "volume.h" | ||
19 | #include "vnode.h" | ||
20 | #include <rxrpc/call.h> | ||
21 | #include "internal.h" | 18 | #include "internal.h" |
22 | 19 | ||
23 | #if 0 | ||
24 | static int afs_file_open(struct inode *inode, struct file *file); | ||
25 | static int afs_file_release(struct inode *inode, struct file *file); | ||
26 | #endif | ||
27 | |||
28 | static int afs_file_readpage(struct file *file, struct page *page); | 20 | static int afs_file_readpage(struct file *file, struct page *page); |
29 | static void afs_file_invalidatepage(struct page *page, unsigned long offset); | 21 | static void afs_file_invalidatepage(struct page *page, unsigned long offset); |
30 | static int afs_file_releasepage(struct page *page, gfp_t gfp_flags); | 22 | static int afs_file_releasepage(struct page *page, gfp_t gfp_flags); |
31 | 23 | ||
24 | const struct file_operations afs_file_operations = { | ||
25 | .open = afs_open, | ||
26 | .release = afs_release, | ||
27 | .llseek = generic_file_llseek, | ||
28 | .read = do_sync_read, | ||
29 | .aio_read = generic_file_aio_read, | ||
30 | .mmap = generic_file_readonly_mmap, | ||
31 | .sendfile = generic_file_sendfile, | ||
32 | }; | ||
33 | |||
32 | const struct inode_operations afs_file_inode_operations = { | 34 | const struct inode_operations afs_file_inode_operations = { |
33 | .getattr = afs_inode_getattr, | 35 | .getattr = afs_inode_getattr, |
36 | .permission = afs_permission, | ||
34 | }; | 37 | }; |
35 | 38 | ||
36 | const struct address_space_operations afs_fs_aops = { | 39 | const struct address_space_operations afs_fs_aops = { |
@@ -40,7 +43,48 @@ const struct address_space_operations afs_fs_aops = { | |||
40 | .invalidatepage = afs_file_invalidatepage, | 43 | .invalidatepage = afs_file_invalidatepage, |
41 | }; | 44 | }; |
42 | 45 | ||
43 | /*****************************************************************************/ | 46 | /* |
47 | * open an AFS file or directory and attach a key to it | ||
48 | */ | ||
49 | int afs_open(struct inode *inode, struct file *file) | ||
50 | { | ||
51 | struct afs_vnode *vnode = AFS_FS_I(inode); | ||
52 | struct key *key; | ||
53 | int ret; | ||
54 | |||
55 | _enter("{%x:%x},", vnode->fid.vid, vnode->fid.vnode); | ||
56 | |||
57 | key = afs_request_key(vnode->volume->cell); | ||
58 | if (IS_ERR(key)) { | ||
59 | _leave(" = %ld [key]", PTR_ERR(key)); | ||
60 | return PTR_ERR(key); | ||
61 | } | ||
62 | |||
63 | ret = afs_validate(vnode, key); | ||
64 | if (ret < 0) { | ||
65 | _leave(" = %d [val]", ret); | ||
66 | return ret; | ||
67 | } | ||
68 | |||
69 | file->private_data = key; | ||
70 | _leave(" = 0"); | ||
71 | return 0; | ||
72 | } | ||
73 | |||
74 | /* | ||
75 | * release an AFS file or directory and discard its key | ||
76 | */ | ||
77 | int afs_release(struct inode *inode, struct file *file) | ||
78 | { | ||
79 | struct afs_vnode *vnode = AFS_FS_I(inode); | ||
80 | |||
81 | _enter("{%x:%x},", vnode->fid.vid, vnode->fid.vnode); | ||
82 | |||
83 | key_put(file->private_data); | ||
84 | _leave(" = 0"); | ||
85 | return 0; | ||
86 | } | ||
87 | |||
44 | /* | 88 | /* |
45 | * deal with notification that a page was read from the cache | 89 | * deal with notification that a page was read from the cache |
46 | */ | 90 | */ |
@@ -58,10 +102,9 @@ static void afs_file_readpage_read_complete(void *cookie_data, | |||
58 | SetPageUptodate(page); | 102 | SetPageUptodate(page); |
59 | unlock_page(page); | 103 | unlock_page(page); |
60 | 104 | ||
61 | } /* end afs_file_readpage_read_complete() */ | 105 | } |
62 | #endif | 106 | #endif |
63 | 107 | ||
64 | /*****************************************************************************/ | ||
65 | /* | 108 | /* |
66 | * deal with notification that a page was written to the cache | 109 | * deal with notification that a page was written to the cache |
67 | */ | 110 | */ |
@@ -74,41 +117,38 @@ static void afs_file_readpage_write_complete(void *cookie_data, | |||
74 | _enter("%p,%p,%p,%d", cookie_data, page, data, error); | 117 | _enter("%p,%p,%p,%d", cookie_data, page, data, error); |
75 | 118 | ||
76 | unlock_page(page); | 119 | unlock_page(page); |
77 | 120 | } | |
78 | } /* end afs_file_readpage_write_complete() */ | ||
79 | #endif | 121 | #endif |
80 | 122 | ||
81 | /*****************************************************************************/ | ||
82 | /* | 123 | /* |
83 | * AFS read page from file (or symlink) | 124 | * AFS read page from file (or symlink) |
84 | */ | 125 | */ |
85 | static int afs_file_readpage(struct file *file, struct page *page) | 126 | static int afs_file_readpage(struct file *file, struct page *page) |
86 | { | 127 | { |
87 | struct afs_rxfs_fetch_descriptor desc; | ||
88 | #ifdef AFS_CACHING_SUPPORT | ||
89 | struct cachefs_page *pageio; | ||
90 | #endif | ||
91 | struct afs_vnode *vnode; | 128 | struct afs_vnode *vnode; |
92 | struct inode *inode; | 129 | struct inode *inode; |
130 | struct key *key; | ||
131 | size_t len; | ||
132 | off_t offset; | ||
93 | int ret; | 133 | int ret; |
94 | 134 | ||
95 | inode = page->mapping->host; | 135 | inode = page->mapping->host; |
96 | 136 | ||
97 | _enter("{%lu},{%lu}", inode->i_ino, page->index); | 137 | ASSERT(file != NULL); |
138 | key = file->private_data; | ||
139 | ASSERT(key != NULL); | ||
140 | |||
141 | _enter("{%x},{%lu},{%lu}", key_serial(key), inode->i_ino, page->index); | ||
98 | 142 | ||
99 | vnode = AFS_FS_I(inode); | 143 | vnode = AFS_FS_I(inode); |
100 | 144 | ||
101 | BUG_ON(!PageLocked(page)); | 145 | BUG_ON(!PageLocked(page)); |
102 | 146 | ||
103 | ret = -ESTALE; | 147 | ret = -ESTALE; |
104 | if (vnode->flags & AFS_VNODE_DELETED) | 148 | if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) |
105 | goto error; | 149 | goto error; |
106 | 150 | ||
107 | #ifdef AFS_CACHING_SUPPORT | 151 | #ifdef AFS_CACHING_SUPPORT |
108 | ret = cachefs_page_get_private(page, &pageio, GFP_NOIO); | ||
109 | if (ret < 0) | ||
110 | goto error; | ||
111 | |||
112 | /* is it cached? */ | 152 | /* is it cached? */ |
113 | ret = cachefs_read_or_alloc_page(vnode->cache, | 153 | ret = cachefs_read_or_alloc_page(vnode->cache, |
114 | page, | 154 | page, |
@@ -132,26 +172,19 @@ static int afs_file_readpage(struct file *file, struct page *page) | |||
132 | case -ENOBUFS: | 172 | case -ENOBUFS: |
133 | case -ENODATA: | 173 | case -ENODATA: |
134 | default: | 174 | default: |
135 | desc.fid = vnode->fid; | 175 | offset = page->index << PAGE_CACHE_SHIFT; |
136 | desc.offset = page->index << PAGE_CACHE_SHIFT; | 176 | len = min_t(size_t, i_size_read(inode) - offset, PAGE_SIZE); |
137 | desc.size = min((size_t) (inode->i_size - desc.offset), | ||
138 | (size_t) PAGE_SIZE); | ||
139 | desc.buffer = kmap(page); | ||
140 | |||
141 | clear_page(desc.buffer); | ||
142 | 177 | ||
143 | /* read the contents of the file from the server into the | 178 | /* read the contents of the file from the server into the |
144 | * page */ | 179 | * page */ |
145 | ret = afs_vnode_fetch_data(vnode, &desc); | 180 | ret = afs_vnode_fetch_data(vnode, key, offset, len, page); |
146 | kunmap(page); | ||
147 | if (ret < 0) { | 181 | if (ret < 0) { |
148 | if (ret==-ENOENT) { | 182 | if (ret == -ENOENT) { |
149 | _debug("got NOENT from server" | 183 | _debug("got NOENT from server" |
150 | " - marking file deleted and stale"); | 184 | " - marking file deleted and stale"); |
151 | vnode->flags |= AFS_VNODE_DELETED; | 185 | set_bit(AFS_VNODE_DELETED, &vnode->flags); |
152 | ret = -ESTALE; | 186 | ret = -ESTALE; |
153 | } | 187 | } |
154 | |||
155 | #ifdef AFS_CACHING_SUPPORT | 188 | #ifdef AFS_CACHING_SUPPORT |
156 | cachefs_uncache_page(vnode->cache, page); | 189 | cachefs_uncache_page(vnode->cache, page); |
157 | #endif | 190 | #endif |
@@ -178,16 +211,13 @@ static int afs_file_readpage(struct file *file, struct page *page) | |||
178 | _leave(" = 0"); | 211 | _leave(" = 0"); |
179 | return 0; | 212 | return 0; |
180 | 213 | ||
181 | error: | 214 | error: |
182 | SetPageError(page); | 215 | SetPageError(page); |
183 | unlock_page(page); | 216 | unlock_page(page); |
184 | |||
185 | _leave(" = %d", ret); | 217 | _leave(" = %d", ret); |
186 | return ret; | 218 | return ret; |
219 | } | ||
187 | 220 | ||
188 | } /* end afs_file_readpage() */ | ||
189 | |||
190 | /*****************************************************************************/ | ||
191 | /* | 221 | /* |
192 | * get a page cookie for the specified page | 222 | * get a page cookie for the specified page |
193 | */ | 223 | */ |
@@ -202,10 +232,9 @@ int afs_cache_get_page_cookie(struct page *page, | |||
202 | 232 | ||
203 | _leave(" = %d", ret); | 233 | _leave(" = %d", ret); |
204 | return ret; | 234 | return ret; |
205 | } /* end afs_cache_get_page_cookie() */ | 235 | } |
206 | #endif | 236 | #endif |
207 | 237 | ||
208 | /*****************************************************************************/ | ||
209 | /* | 238 | /* |
210 | * invalidate part or all of a page | 239 | * invalidate part or all of a page |
211 | */ | 240 | */ |
@@ -240,9 +269,8 @@ static void afs_file_invalidatepage(struct page *page, unsigned long offset) | |||
240 | } | 269 | } |
241 | 270 | ||
242 | _leave(" = %d", ret); | 271 | _leave(" = %d", ret); |
243 | } /* end afs_file_invalidatepage() */ | 272 | } |
244 | 273 | ||
245 | /*****************************************************************************/ | ||
246 | /* | 274 | /* |
247 | * release a page and cleanup its private data | 275 | * release a page and cleanup its private data |
248 | */ | 276 | */ |
@@ -267,4 +295,4 @@ static int afs_file_releasepage(struct page *page, gfp_t gfp_flags) | |||
267 | 295 | ||
268 | _leave(" = 0"); | 296 | _leave(" = 0"); |
269 | return 0; | 297 | return 0; |
270 | } /* end afs_file_releasepage() */ | 298 | } |