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>
This commit is contained in:
parent
4403158ba2
commit
f6d335c08d
4 changed files with 41 additions and 36 deletions
|
@ -189,13 +189,9 @@ static struct page *afs_dir_get_page(struct inode *dir, unsigned long index,
|
|||
struct key *key)
|
||||
{
|
||||
struct page *page;
|
||||
struct file file = {
|
||||
.private_data = key,
|
||||
};
|
||||
|
||||
_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)) {
|
||||
kmap(page);
|
||||
if (!PageChecked(page))
|
||||
|
|
|
@ -121,34 +121,19 @@ static void afs_file_readpage_read_complete(struct page *page,
|
|||
#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;
|
||||
struct key *key;
|
||||
struct inode *inode = page->mapping->host;
|
||||
struct afs_vnode *vnode = AFS_FS_I(inode);
|
||||
struct key *key = data;
|
||||
size_t len;
|
||||
off_t offset;
|
||||
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);
|
||||
|
||||
vnode = AFS_FS_I(inode);
|
||||
|
||||
BUG_ON(!PageLocked(page));
|
||||
|
||||
ret = -ESTALE;
|
||||
|
@ -214,31 +199,56 @@ static int afs_readpage(struct file *file, struct page *page)
|
|||
unlock_page(page);
|
||||
}
|
||||
|
||||
if (!file)
|
||||
key_put(key);
|
||||
_leave(" = 0");
|
||||
return 0;
|
||||
|
||||
error:
|
||||
SetPageError(page);
|
||||
unlock_page(page);
|
||||
if (!file)
|
||||
key_put(key);
|
||||
error_nokey:
|
||||
_leave(" = %d", 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
|
||||
*/
|
||||
static int afs_readpages(struct file *file, struct address_space *mapping,
|
||||
struct list_head *pages, unsigned nr_pages)
|
||||
{
|
||||
struct key *key = file->private_data;
|
||||
struct afs_vnode *vnode;
|
||||
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);
|
||||
if (vnode->flags & AFS_VNODE_DELETED) {
|
||||
|
@ -279,7 +289,7 @@ static int afs_readpages(struct file *file, struct address_space *mapping,
|
|||
}
|
||||
|
||||
/* 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);
|
||||
return ret;
|
||||
|
|
|
@ -494,6 +494,7 @@ extern const struct file_operations afs_file_operations;
|
|||
|
||||
extern int afs_open(struct inode *, struct file *);
|
||||
extern int afs_release(struct inode *, struct file *);
|
||||
extern int afs_page_filler(void *, struct page *);
|
||||
|
||||
/*
|
||||
* flock.c
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
struct file file = {
|
||||
.private_data = key,
|
||||
};
|
||||
struct page *page;
|
||||
size_t size;
|
||||
char *buf;
|
||||
|
@ -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);
|
||||
|
||||
/* 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)) {
|
||||
ret = PTR_ERR(page);
|
||||
goto out;
|
||||
|
|
Loading…
Reference in a new issue