VFS: Make more complete truncate operation available to CacheFiles
Make a more complete truncate operation available to CacheFiles (including security checks and suchlike) so that it can use this to clear invalidated cache files. Signed-off-by: David Howells <dhowells@redhat.com> Acked-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
		
					parent
					
						
							
								ef778e7ae6
							
						
					
				
			
			
				commit
				
					
						a02de96085
					
				
			
		
					 2 changed files with 28 additions and 23 deletions
				
			
		
							
								
								
									
										50
									
								
								fs/open.c
									
										
									
									
									
								
							
							
						
						
									
										50
									
								
								fs/open.c
									
										
									
									
									
								
							| 
						 | 
					@ -61,33 +61,22 @@ int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static long do_sys_truncate(const char __user *pathname, loff_t length)
 | 
					long vfs_truncate(struct path *path, loff_t length)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct path path;
 | 
					 | 
				
			||||||
	struct inode *inode;
 | 
						struct inode *inode;
 | 
				
			||||||
	int error;
 | 
						long error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	error = -EINVAL;
 | 
						inode = path->dentry->d_inode;
 | 
				
			||||||
	if (length < 0)	/* sorry, but loff_t says... */
 | 
					 | 
				
			||||||
		goto out;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	error = user_path(pathname, &path);
 | 
					 | 
				
			||||||
	if (error)
 | 
					 | 
				
			||||||
		goto out;
 | 
					 | 
				
			||||||
	inode = path.dentry->d_inode;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* For directories it's -EISDIR, for other non-regulars - -EINVAL */
 | 
						/* For directories it's -EISDIR, for other non-regulars - -EINVAL */
 | 
				
			||||||
	error = -EISDIR;
 | 
					 | 
				
			||||||
	if (S_ISDIR(inode->i_mode))
 | 
						if (S_ISDIR(inode->i_mode))
 | 
				
			||||||
		goto dput_and_out;
 | 
							return -EISDIR;
 | 
				
			||||||
 | 
					 | 
				
			||||||
	error = -EINVAL;
 | 
					 | 
				
			||||||
	if (!S_ISREG(inode->i_mode))
 | 
						if (!S_ISREG(inode->i_mode))
 | 
				
			||||||
		goto dput_and_out;
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	error = mnt_want_write(path.mnt);
 | 
						error = mnt_want_write(path->mnt);
 | 
				
			||||||
	if (error)
 | 
						if (error)
 | 
				
			||||||
		goto dput_and_out;
 | 
							goto out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	error = inode_permission(inode, MAY_WRITE);
 | 
						error = inode_permission(inode, MAY_WRITE);
 | 
				
			||||||
	if (error)
 | 
						if (error)
 | 
				
			||||||
| 
						 | 
					@ -111,19 +100,34 @@ static long do_sys_truncate(const char __user *pathname, loff_t length)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	error = locks_verify_truncate(inode, NULL, length);
 | 
						error = locks_verify_truncate(inode, NULL, length);
 | 
				
			||||||
	if (!error)
 | 
						if (!error)
 | 
				
			||||||
		error = security_path_truncate(&path);
 | 
							error = security_path_truncate(path);
 | 
				
			||||||
	if (!error)
 | 
						if (!error)
 | 
				
			||||||
		error = do_truncate(path.dentry, length, 0, NULL);
 | 
							error = do_truncate(path->dentry, length, 0, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
put_write_and_out:
 | 
					put_write_and_out:
 | 
				
			||||||
	put_write_access(inode);
 | 
						put_write_access(inode);
 | 
				
			||||||
mnt_drop_write_and_out:
 | 
					mnt_drop_write_and_out:
 | 
				
			||||||
	mnt_drop_write(path.mnt);
 | 
						mnt_drop_write(path->mnt);
 | 
				
			||||||
dput_and_out:
 | 
					 | 
				
			||||||
	path_put(&path);
 | 
					 | 
				
			||||||
out:
 | 
					out:
 | 
				
			||||||
	return error;
 | 
						return error;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL_GPL(vfs_truncate);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static long do_sys_truncate(const char __user *pathname, loff_t length)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct path path;
 | 
				
			||||||
 | 
						int error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (length < 0)	/* sorry, but loff_t says... */
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						error = user_path(pathname, &path);
 | 
				
			||||||
 | 
						if (!error) {
 | 
				
			||||||
 | 
							error = vfs_truncate(&path, length);
 | 
				
			||||||
 | 
							path_put(&path);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return error;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SYSCALL_DEFINE2(truncate, const char __user *, path, long, length)
 | 
					SYSCALL_DEFINE2(truncate, const char __user *, path, long, length)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1999,6 +1999,7 @@ struct filename {
 | 
				
			||||||
	bool			separate; /* should "name" be freed? */
 | 
						bool			separate; /* should "name" be freed? */
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern long vfs_truncate(struct path *, loff_t);
 | 
				
			||||||
extern int do_truncate(struct dentry *, loff_t start, unsigned int time_attrs,
 | 
					extern int do_truncate(struct dentry *, loff_t start, unsigned int time_attrs,
 | 
				
			||||||
		       struct file *filp);
 | 
							       struct file *filp);
 | 
				
			||||||
extern int do_fallocate(struct file *file, int mode, loff_t offset,
 | 
					extern int do_fallocate(struct file *file, int mode, loff_t offset,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue