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