aboutsummaryrefslogtreecommitdiffstats
path: root/fs/udf/file.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/udf/file.c')
-rw-r--r--fs/udf/file.c66
1 files changed, 37 insertions, 29 deletions
diff --git a/fs/udf/file.c b/fs/udf/file.c
index 4b6a46ccbf46..66b9e7e7e4c5 100644
--- a/fs/udf/file.c
+++ b/fs/udf/file.c
@@ -34,7 +34,6 @@
34#include <linux/errno.h> 34#include <linux/errno.h>
35#include <linux/smp_lock.h> 35#include <linux/smp_lock.h>
36#include <linux/pagemap.h> 36#include <linux/pagemap.h>
37#include <linux/quotaops.h>
38#include <linux/buffer_head.h> 37#include <linux/buffer_head.h>
39#include <linux/aio.h> 38#include <linux/aio.h>
40 39
@@ -144,50 +143,60 @@ static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
144 return retval; 143 return retval;
145} 144}
146 145
147int udf_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, 146long udf_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
148 unsigned long arg)
149{ 147{
148 struct inode *inode = filp->f_dentry->d_inode;
150 long old_block, new_block; 149 long old_block, new_block;
151 int result = -EINVAL; 150 int result = -EINVAL;
152 151
152 lock_kernel();
153
153 if (file_permission(filp, MAY_READ) != 0) { 154 if (file_permission(filp, MAY_READ) != 0) {
154 udf_debug("no permission to access inode %lu\n", 155 udf_debug("no permission to access inode %lu\n", inode->i_ino);
155 inode->i_ino); 156 result = -EPERM;
156 return -EPERM; 157 goto out;
157 } 158 }
158 159
159 if (!arg) { 160 if (!arg) {
160 udf_debug("invalid argument to udf_ioctl\n"); 161 udf_debug("invalid argument to udf_ioctl\n");
161 return -EINVAL; 162 result = -EINVAL;
163 goto out;
162 } 164 }
163 165
164 switch (cmd) { 166 switch (cmd) {
165 case UDF_GETVOLIDENT: 167 case UDF_GETVOLIDENT:
166 if (copy_to_user((char __user *)arg, 168 if (copy_to_user((char __user *)arg,
167 UDF_SB(inode->i_sb)->s_volume_ident, 32)) 169 UDF_SB(inode->i_sb)->s_volume_ident, 32))
168 return -EFAULT; 170 result = -EFAULT;
169 else 171 else
170 return 0; 172 result = 0;
173 goto out;
171 case UDF_RELOCATE_BLOCKS: 174 case UDF_RELOCATE_BLOCKS:
172 if (!capable(CAP_SYS_ADMIN)) 175 if (!capable(CAP_SYS_ADMIN)) {
173 return -EACCES; 176 result = -EACCES;
174 if (get_user(old_block, (long __user *)arg)) 177 goto out;
175 return -EFAULT; 178 }
179 if (get_user(old_block, (long __user *)arg)) {
180 result = -EFAULT;
181 goto out;
182 }
176 result = udf_relocate_blocks(inode->i_sb, 183 result = udf_relocate_blocks(inode->i_sb,
177 old_block, &new_block); 184 old_block, &new_block);
178 if (result == 0) 185 if (result == 0)
179 result = put_user(new_block, (long __user *)arg); 186 result = put_user(new_block, (long __user *)arg);
180 return result; 187 goto out;
181 case UDF_GETEASIZE: 188 case UDF_GETEASIZE:
182 result = put_user(UDF_I(inode)->i_lenEAttr, (int __user *)arg); 189 result = put_user(UDF_I(inode)->i_lenEAttr, (int __user *)arg);
183 break; 190 goto out;
184 case UDF_GETEABLOCK: 191 case UDF_GETEABLOCK:
185 result = copy_to_user((char __user *)arg, 192 result = copy_to_user((char __user *)arg,
186 UDF_I(inode)->i_ext.i_data, 193 UDF_I(inode)->i_ext.i_data,
187 UDF_I(inode)->i_lenEAttr) ? -EFAULT : 0; 194 UDF_I(inode)->i_lenEAttr) ? -EFAULT : 0;
188 break; 195 goto out;
189 } 196 }
190 197
198out:
199 unlock_kernel();
191 return result; 200 return result;
192} 201}
193 202
@@ -207,40 +216,39 @@ static int udf_release_file(struct inode *inode, struct file *filp)
207const struct file_operations udf_file_operations = { 216const struct file_operations udf_file_operations = {
208 .read = do_sync_read, 217 .read = do_sync_read,
209 .aio_read = generic_file_aio_read, 218 .aio_read = generic_file_aio_read,
210 .ioctl = udf_ioctl, 219 .unlocked_ioctl = udf_ioctl,
211 .open = dquot_file_open, 220 .open = generic_file_open,
212 .mmap = generic_file_mmap, 221 .mmap = generic_file_mmap,
213 .write = do_sync_write, 222 .write = do_sync_write,
214 .aio_write = udf_file_aio_write, 223 .aio_write = udf_file_aio_write,
215 .release = udf_release_file, 224 .release = udf_release_file,
216 .fsync = simple_fsync, 225 .fsync = generic_file_fsync,
217 .splice_read = generic_file_splice_read, 226 .splice_read = generic_file_splice_read,
218 .llseek = generic_file_llseek, 227 .llseek = generic_file_llseek,
219}; 228};
220 229
221int udf_setattr(struct dentry *dentry, struct iattr *iattr) 230static int udf_setattr(struct dentry *dentry, struct iattr *attr)
222{ 231{
223 struct inode *inode = dentry->d_inode; 232 struct inode *inode = dentry->d_inode;
224 int error; 233 int error;
225 234
226 error = inode_change_ok(inode, iattr); 235 error = inode_change_ok(inode, attr);
227 if (error) 236 if (error)
228 return error; 237 return error;
229 238
230 if (iattr->ia_valid & ATTR_SIZE) 239 if ((attr->ia_valid & ATTR_SIZE) &&
231 dquot_initialize(inode); 240 attr->ia_size != i_size_read(inode)) {
232 241 error = vmtruncate(inode, attr->ia_size);
233 if ((iattr->ia_valid & ATTR_UID && iattr->ia_uid != inode->i_uid) ||
234 (iattr->ia_valid & ATTR_GID && iattr->ia_gid != inode->i_gid)) {
235 error = dquot_transfer(inode, iattr);
236 if (error) 242 if (error)
237 return error; 243 return error;
238 } 244 }
239 245
240 return inode_setattr(inode, iattr); 246 setattr_copy(inode, attr);
247 mark_inode_dirty(inode);
248 return 0;
241} 249}
242 250
243const struct inode_operations udf_file_inode_operations = { 251const struct inode_operations udf_file_inode_operations = {
244 .truncate = udf_truncate,
245 .setattr = udf_setattr, 252 .setattr = udf_setattr,
253 .truncate = udf_truncate,
246}; 254};