Commit f6d335c0 authored by Al Viro's avatar Al Viro Committed by Al Viro

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: default avatarAl Viro <viro@zeniv.linux.org.uk>
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
parent 4403158b
...@@ -189,13 +189,9 @@ static struct page *afs_dir_get_page(struct inode *dir, unsigned long index, ...@@ -189,13 +189,9 @@ static struct page *afs_dir_get_page(struct inode *dir, unsigned long index,
struct key *key) struct key *key)
{ {
struct page *page; struct page *page;
struct file file = {
.private_data = key,
};
_enter("{%lu},%lu", dir->i_ino, index); _enter("{%lu},%lu", dir->i_ino, index);
page = read_mapping_page(dir->i_mapping, index, &file); page = read_cache_page(dir->i_mapping, index, afs_page_filler, key);
if (!IS_ERR(page)) { if (!IS_ERR(page)) {
kmap(page); kmap(page);
if (!PageChecked(page)) if (!PageChecked(page))
......
...@@ -121,34 +121,19 @@ static void afs_file_readpage_read_complete(struct page *page, ...@@ -121,34 +121,19 @@ static void afs_file_readpage_read_complete(struct page *page,
#endif #endif
/* /*
* AFS read page from file, directory or symlink * read page from file, directory or symlink, given a key to use
*/ */
static int afs_readpage(struct file *file, struct page *page) int afs_page_filler(void *data, struct page *page)
{ {
struct afs_vnode *vnode; struct inode *inode = page->mapping->host;
struct inode *inode; struct afs_vnode *vnode = AFS_FS_I(inode);
struct key *key; struct key *key = data;
size_t len; size_t len;
off_t offset; off_t offset;
int ret; int ret;
inode = page->mapping->host;
if (file) {
key = file->private_data;
ASSERT(key != NULL);
} else {
key = afs_request_key(AFS_FS_S(inode->i_sb)->volume->cell);
if (IS_ERR(key)) {
ret = PTR_ERR(key);
goto error_nokey;
}
}
_enter("{%x},{%lu},{%lu}", key_serial(key), inode->i_ino, page->index); _enter("{%x},{%lu},{%lu}", key_serial(key), inode->i_ino, page->index);
vnode = AFS_FS_I(inode);
BUG_ON(!PageLocked(page)); BUG_ON(!PageLocked(page));
ret = -ESTALE; ret = -ESTALE;
...@@ -214,31 +199,56 @@ static int afs_readpage(struct file *file, struct page *page) ...@@ -214,31 +199,56 @@ static int afs_readpage(struct file *file, struct page *page)
unlock_page(page); unlock_page(page);
} }
if (!file)
key_put(key);
_leave(" = 0"); _leave(" = 0");
return 0; return 0;
error: error:
SetPageError(page); SetPageError(page);
unlock_page(page); unlock_page(page);
if (!file)
key_put(key);
error_nokey:
_leave(" = %d", ret); _leave(" = %d", ret);
return ret; return ret;
} }
/*
* read page from file, directory or symlink, given a file to nominate the key
* to be used
*/
static int afs_readpage(struct file *file, struct page *page)
{
struct key *key;
int ret;
if (file) {
key = file->private_data;
ASSERT(key != NULL);
ret = afs_page_filler(key, page);
} else {
struct inode *inode = page->mapping->host;
key = afs_request_key(AFS_FS_S(inode->i_sb)->volume->cell);
if (IS_ERR(key)) {
ret = PTR_ERR(key);
} else {
ret = afs_page_filler(key, page);
key_put(key);
}
}
return ret;
}
/* /*
* read a set of pages * read a set of pages
*/ */
static int afs_readpages(struct file *file, struct address_space *mapping, static int afs_readpages(struct file *file, struct address_space *mapping,
struct list_head *pages, unsigned nr_pages) struct list_head *pages, unsigned nr_pages)
{ {
struct key *key = file->private_data;
struct afs_vnode *vnode; struct afs_vnode *vnode;
int ret = 0; int ret = 0;
_enter(",{%lu},,%d", mapping->host->i_ino, nr_pages); _enter("{%d},{%lu},,%d",
key_serial(key), mapping->host->i_ino, nr_pages);
ASSERT(key != NULL);
vnode = AFS_FS_I(mapping->host); vnode = AFS_FS_I(mapping->host);
if (vnode->flags & AFS_VNODE_DELETED) { if (vnode->flags & AFS_VNODE_DELETED) {
...@@ -279,7 +289,7 @@ static int afs_readpages(struct file *file, struct address_space *mapping, ...@@ -279,7 +289,7 @@ static int afs_readpages(struct file *file, struct address_space *mapping,
} }
/* load the missing pages from the network */ /* load the missing pages from the network */
ret = read_cache_pages(mapping, pages, (void *) afs_readpage, file); ret = read_cache_pages(mapping, pages, afs_page_filler, key);
_leave(" = %d [netting]", ret); _leave(" = %d [netting]", ret);
return ret; return ret;
......
...@@ -494,6 +494,7 @@ extern const struct file_operations afs_file_operations; ...@@ -494,6 +494,7 @@ extern const struct file_operations afs_file_operations;
extern int afs_open(struct inode *, struct file *); extern int afs_open(struct inode *, struct file *);
extern int afs_release(struct inode *, struct file *); extern int afs_release(struct inode *, struct file *);
extern int afs_page_filler(void *, struct page *);
/* /*
* flock.c * flock.c
......
...@@ -49,9 +49,6 @@ static unsigned long afs_mntpt_expiry_timeout = 10 * 60; ...@@ -49,9 +49,6 @@ static unsigned long afs_mntpt_expiry_timeout = 10 * 60;
*/ */
int afs_mntpt_check_symlink(struct afs_vnode *vnode, struct key *key) int afs_mntpt_check_symlink(struct afs_vnode *vnode, struct key *key)
{ {
struct file file = {
.private_data = key,
};
struct page *page; struct page *page;
size_t size; size_t size;
char *buf; char *buf;
...@@ -61,7 +58,8 @@ int afs_mntpt_check_symlink(struct afs_vnode *vnode, struct key *key) ...@@ -61,7 +58,8 @@ int afs_mntpt_check_symlink(struct afs_vnode *vnode, struct key *key)
vnode->fid.vid, vnode->fid.vnode, vnode->fid.unique); vnode->fid.vid, vnode->fid.vnode, vnode->fid.unique);
/* read the contents of the symlink into the pagecache */ /* read the contents of the symlink into the pagecache */
page = read_mapping_page(AFS_VNODE_TO_I(vnode)->i_mapping, 0, &file); page = read_cache_page(AFS_VNODE_TO_I(vnode)->i_mapping, 0,
afs_page_filler, key);
if (IS_ERR(page)) { if (IS_ERR(page)) {
ret = PTR_ERR(page); ret = PTR_ERR(page);
goto out; goto out;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment