aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2012-12-20 16:52:36 -0500
committerDavid Howells <dhowells@redhat.com>2012-12-20 17:05:41 -0500
commita02de9608595c8ef649ef03ae735b0b45e3d4396 (patch)
treeca411825ecc8a30b70d869244a7e9412d0728486 /fs
parentef778e7ae67cd426c30cad43378b908f5eb0bad5 (diff)
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>
Diffstat (limited to 'fs')
-rw-r--r--fs/open.c50
1 files changed, 27 insertions, 23 deletions
diff --git a/fs/open.c b/fs/open.c
index 182d8667b7bd..c819bbdab47f 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -61,33 +61,22 @@ int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
61 return ret; 61 return ret;
62} 62}
63 63
64static long do_sys_truncate(const char __user *pathname, loff_t length) 64long vfs_truncate(struct path *path, loff_t length)
65{ 65{
66 struct path path;
67 struct inode *inode; 66 struct inode *inode;
68 int error; 67 long error;
69
70 error = -EINVAL;
71 if (length < 0) /* sorry, but loff_t says... */
72 goto out;
73 68
74 error = user_path(pathname, &path); 69 inode = path->dentry->d_inode;
75 if (error)
76 goto out;
77 inode = path.dentry->d_inode;
78 70
79 /* For directories it's -EISDIR, for other non-regulars - -EINVAL */ 71 /* For directories it's -EISDIR, for other non-regulars - -EINVAL */
80 error = -EISDIR;
81 if (S_ISDIR(inode->i_mode)) 72 if (S_ISDIR(inode->i_mode))
82 goto dput_and_out; 73 return -EISDIR;
83
84 error = -EINVAL;
85 if (!S_ISREG(inode->i_mode)) 74 if (!S_ISREG(inode->i_mode))
86 goto dput_and_out; 75 return -EINVAL;
87 76
88 error = mnt_want_write(path.mnt); 77 error = mnt_want_write(path->mnt);
89 if (error) 78 if (error)
90 goto dput_and_out; 79 goto out;
91 80
92 error = inode_permission(inode, MAY_WRITE); 81 error = inode_permission(inode, MAY_WRITE);
93 if (error) 82 if (error)
@@ -111,19 +100,34 @@ static long do_sys_truncate(const char __user *pathname, loff_t length)
111 100
112 error = locks_verify_truncate(inode, NULL, length); 101 error = locks_verify_truncate(inode, NULL, length);
113 if (!error) 102 if (!error)
114 error = security_path_truncate(&path); 103 error = security_path_truncate(path);
115 if (!error) 104 if (!error)
116 error = do_truncate(path.dentry, length, 0, NULL); 105 error = do_truncate(path->dentry, length, 0, NULL);
117 106
118put_write_and_out: 107put_write_and_out:
119 put_write_access(inode); 108 put_write_access(inode);
120mnt_drop_write_and_out: 109mnt_drop_write_and_out:
121 mnt_drop_write(path.mnt); 110 mnt_drop_write(path->mnt);
122dput_and_out:
123 path_put(&path);
124out: 111out:
125 return error; 112 return error;
126} 113}
114EXPORT_SYMBOL_GPL(vfs_truncate);
115
116static long do_sys_truncate(const char __user *pathname, loff_t length)
117{
118 struct path path;
119 int error;
120
121 if (length < 0) /* sorry, but loff_t says... */
122 return -EINVAL;
123
124 error = user_path(pathname, &path);
125 if (!error) {
126 error = vfs_truncate(&path, length);
127 path_put(&path);
128 }
129 return error;
130}
127 131
128SYSCALL_DEFINE2(truncate, const char __user *, path, long, length) 132SYSCALL_DEFINE2(truncate, const char __user *, path, long, length)
129{ 133{