diff options
author | Al Viro <viro@ZenIV.linux.org.uk> | 2010-05-21 10:27:09 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2010-05-21 18:31:28 -0400 |
commit | f6d335c08df48b318187a087c9c38ba3d416e115 (patch) | |
tree | ccee5ad0c46fea4c34d435d5d869f43394dd9a81 | |
parent | 4403158ba295c8e36f6736b1bb12d0f7e1923dac (diff) |
AFS: Don't put struct file on the stack
Don't put struct file on the stack as it takes up quite a lot of space
and violates lifetime rules for struct file.
Rather than calling afs_readpage() indirectly from the directory routines by
way of read_mapping_page(), split afs_readpage() to have afs_page_filler()
that's given a key instead of a file and call read_cache_page(), specifying the
new function directly. Use it in afs_readpages() as well.
Also make use of this in afs_mntpt_check_symlink() too for the same reason.
Reported-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: David Howells <dhowells@redhat.com>
-rw-r--r-- | fs/afs/dir.c | 6 | ||||
-rw-r--r-- | fs/afs/file.c | 64 | ||||
-rw-r--r-- | fs/afs/internal.h | 1 | ||||
-rw-r--r-- | fs/afs/mntpt.c | 6 |
4 files changed, 41 insertions, 36 deletions
diff --git a/fs/afs/dir.c b/fs/afs/dir.c index adc1cb771b57..b42d5cc1d6d2 100644 --- a/fs/afs/dir.c +++ b/fs/afs/dir.c | |||
@@ -189,13 +189,9 @@ static struct page *afs_dir_get_page(struct inode *dir, unsigned long index, | |||
189 | struct key *key) | 189 | struct key *key) |
190 | { | 190 | { |
191 | struct page *page; | 191 | struct page *page; |
192 | struct file file = { | ||
193 | .private_data = key, | ||
194 | }; | ||
195 | |||
196 | _enter("{%lu},%lu", dir->i_ino, index); | 192 | _enter("{%lu},%lu", dir->i_ino, index); |
197 | 193 | ||
198 | page = read_mapping_page(dir->i_mapping, index, &file); | 194 | page = read_cache_page(dir->i_mapping, index, afs_page_filler, key); |
199 | if (!IS_ERR(page)) { | 195 | if (!IS_ERR(page)) { |
200 | kmap(page); | 196 | kmap(page); |
201 | if (!PageChecked(page)) | 197 | if (!PageChecked(page)) |
diff --git a/fs/afs/file.c b/fs/afs/file.c index 0df9bc2b724d..14d89fa58fee 100644 --- a/fs/afs/file.c +++ b/fs/afs/file.c | |||
@@ -121,34 +121,19 @@ static void afs_file_readpage_read_complete(struct page *page, | |||
121 | #endif | 121 | #endif |
122 | 122 | ||
123 | /* | 123 | /* |
124 | * AFS read page from file, directory or symlink | 124 | * read page from file, directory or symlink, given a key to use |
125 | */ | 125 | */ |
126 | static int afs_readpage(struct file *file, struct page *page) | 126 | int afs_page_filler(void *data, struct page *page) |
127 | { | 127 | { |
128 | struct afs_vnode *vnode; | 128 | struct inode *inode = page->mapping->host; |
129 | struct inode *inode; | 129 | struct afs_vnode *vnode = AFS_FS_I(inode); |
130 | struct key *key; | 130 | struct key *key = data; |
131 | size_t len; | 131 | size_t len; |
132 | off_t offset; | 132 | off_t offset; |
133 | int ret; | 133 | int ret; |
134 | 134 | ||
135 | inode = page->mapping->host; | ||
136 | |||
137 | if (file) { | ||
138 | key = file->private_data; | ||
139 | ASSERT(key != NULL); | ||
140 | } else { | ||
141 | key = afs_request_key(AFS_FS_S(inode->i_sb)->volume->cell); | ||
142 | if (IS_ERR(key)) { | ||
143 | ret = PTR_ERR(key); | ||
144 | goto error_nokey; | ||
145 | } | ||
146 | } | ||
147 | |||
148 | _enter("{%x},{%lu},{%lu}", key_serial(key), inode->i_ino, page->index); | 135 | _enter("{%x},{%lu},{%lu}", key_serial(key), inode->i_ino, page->index); |
149 | 136 | ||
150 | vnode = AFS_FS_I(inode); | ||
151 | |||
152 | BUG_ON(!PageLocked(page)); | 137 | BUG_ON(!PageLocked(page)); |
153 | 138 | ||
154 | ret = -ESTALE; | 139 | ret = -ESTALE; |
@@ -214,31 +199,56 @@ static int afs_readpage(struct file *file, struct page *page) | |||
214 | unlock_page(page); | 199 | unlock_page(page); |
215 | } | 200 | } |
216 | 201 | ||
217 | if (!file) | ||
218 | key_put(key); | ||
219 | _leave(" = 0"); | 202 | _leave(" = 0"); |
220 | return 0; | 203 | return 0; |
221 | 204 | ||
222 | error: | 205 | error: |
223 | SetPageError(page); | 206 | SetPageError(page); |
224 | unlock_page(page); | 207 | unlock_page(page); |
225 | if (!file) | ||
226 | key_put(key); | ||
227 | error_nokey: | ||
228 | _leave(" = %d", ret); | 208 | _leave(" = %d", ret); |
229 | return ret; | 209 | return ret; |
230 | } | 210 | } |
231 | 211 | ||
232 | /* | 212 | /* |
213 | * read page from file, directory or symlink, given a file to nominate the key | ||
214 | * to be used | ||
215 | */ | ||
216 | static int afs_readpage(struct file *file, struct page *page) | ||
217 | { | ||
218 | struct key *key; | ||
219 | int ret; | ||
220 | |||
221 | if (file) { | ||
222 | key = file->private_data; | ||
223 | ASSERT(key != NULL); | ||
224 | ret = afs_page_filler(key, page); | ||
225 | } else { | ||
226 | struct inode *inode = page->mapping->host; | ||
227 | key = afs_request_key(AFS_FS_S(inode->i_sb)->volume->cell); | ||
228 | if (IS_ERR(key)) { | ||
229 | ret = PTR_ERR(key); | ||
230 | } else { | ||
231 | ret = afs_page_filler(key, page); | ||
232 | key_put(key); | ||
233 | } | ||
234 | } | ||
235 | return ret; | ||
236 | } | ||
237 | |||
238 | /* | ||
233 | * read a set of pages | 239 | * read a set of pages |
234 | */ | 240 | */ |
235 | static int afs_readpages(struct file *file, struct address_space *mapping, | 241 | static int afs_readpages(struct file *file, struct address_space *mapping, |
236 | struct list_head *pages, unsigned nr_pages) | 242 | struct list_head *pages, unsigned nr_pages) |
237 | { | 243 | { |
244 | struct key *key = file->private_data; | ||
238 | struct afs_vnode *vnode; | 245 | struct afs_vnode *vnode; |
239 | int ret = 0; | 246 | int ret = 0; |
240 | 247 | ||
241 | _enter(",{%lu},,%d", mapping->host->i_ino, nr_pages); | 248 | _enter("{%d},{%lu},,%d", |
249 | key_serial(key), mapping->host->i_ino, nr_pages); | ||
250 | |||
251 | ASSERT(key != NULL); | ||
242 | 252 | ||
243 | vnode = AFS_FS_I(mapping->host); | 253 | vnode = AFS_FS_I(mapping->host); |
244 | if (vnode->flags & AFS_VNODE_DELETED) { | 254 | if (vnode->flags & AFS_VNODE_DELETED) { |
@@ -279,7 +289,7 @@ static int afs_readpages(struct file *file, struct address_space *mapping, | |||
279 | } | 289 | } |
280 | 290 | ||
281 | /* load the missing pages from the network */ | 291 | /* load the missing pages from the network */ |
282 | ret = read_cache_pages(mapping, pages, (void *) afs_readpage, file); | 292 | ret = read_cache_pages(mapping, pages, afs_page_filler, key); |
283 | 293 | ||
284 | _leave(" = %d [netting]", ret); | 294 | _leave(" = %d [netting]", ret); |
285 | return ret; | 295 | return ret; |
diff --git a/fs/afs/internal.h b/fs/afs/internal.h index a10f2582844f..807f284cc75e 100644 --- a/fs/afs/internal.h +++ b/fs/afs/internal.h | |||
@@ -494,6 +494,7 @@ extern const struct file_operations afs_file_operations; | |||
494 | 494 | ||
495 | extern int afs_open(struct inode *, struct file *); | 495 | extern int afs_open(struct inode *, struct file *); |
496 | extern int afs_release(struct inode *, struct file *); | 496 | extern int afs_release(struct inode *, struct file *); |
497 | extern int afs_page_filler(void *, struct page *); | ||
497 | 498 | ||
498 | /* | 499 | /* |
499 | * flock.c | 500 | * flock.c |
diff --git a/fs/afs/mntpt.c b/fs/afs/mntpt.c index b3feddc4f7d6..a9e23039ea34 100644 --- a/fs/afs/mntpt.c +++ b/fs/afs/mntpt.c | |||
@@ -49,9 +49,6 @@ static unsigned long afs_mntpt_expiry_timeout = 10 * 60; | |||
49 | */ | 49 | */ |
50 | int afs_mntpt_check_symlink(struct afs_vnode *vnode, struct key *key) | 50 | int afs_mntpt_check_symlink(struct afs_vnode *vnode, struct key *key) |
51 | { | 51 | { |
52 | struct file file = { | ||
53 | .private_data = key, | ||
54 | }; | ||
55 | struct page *page; | 52 | struct page *page; |
56 | size_t size; | 53 | size_t size; |
57 | char *buf; | 54 | char *buf; |
@@ -61,7 +58,8 @@ int afs_mntpt_check_symlink(struct afs_vnode *vnode, struct key *key) | |||
61 | vnode->fid.vid, vnode->fid.vnode, vnode->fid.unique); | 58 | vnode->fid.vid, vnode->fid.vnode, vnode->fid.unique); |
62 | 59 | ||
63 | /* read the contents of the symlink into the pagecache */ | 60 | /* read the contents of the symlink into the pagecache */ |
64 | page = read_mapping_page(AFS_VNODE_TO_I(vnode)->i_mapping, 0, &file); | 61 | page = read_cache_page(AFS_VNODE_TO_I(vnode)->i_mapping, 0, |
62 | afs_page_filler, key); | ||
65 | if (IS_ERR(page)) { | 63 | if (IS_ERR(page)) { |
66 | ret = PTR_ERR(page); | 64 | ret = PTR_ERR(page); |
67 | goto out; | 65 | goto out; |