Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+1 −5
Original line number Diff line number Diff line
@@ -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))
+37 −27
Original line number Diff line number Diff line
@@ -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;
+1 −0
Original line number Diff line number Diff line
@@ -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
+2 −4
Original line number Diff line number Diff line
@@ -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;