summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs/udf/dir.c2
-rw-r--r--fs/udf/file.c43
-rw-r--r--fs/udf/udfdecl.h3
3 files changed, 29 insertions, 19 deletions
diff --git a/fs/udf/dir.c b/fs/udf/dir.c
index f0f2a436251e..3a84455c2a77 100644
--- a/fs/udf/dir.c
+++ b/fs/udf/dir.c
@@ -209,6 +209,6 @@ static int udf_readdir(struct file *filp, void *dirent, filldir_t filldir)
const struct file_operations udf_dir_operations = {
.read = generic_read_dir,
.readdir = udf_readdir,
- .ioctl = udf_ioctl,
+ .unlocked_ioctl = udf_ioctl,
.fsync = simple_fsync,
};
diff --git a/fs/udf/file.c b/fs/udf/file.c
index 4b6a46ccbf46..83092fb025e2 100644
--- a/fs/udf/file.c
+++ b/fs/udf/file.c
@@ -37,6 +37,7 @@
#include <linux/quotaops.h>
#include <linux/buffer_head.h>
#include <linux/aio.h>
+#include <linux/smp_lock.h>
#include "udf_i.h"
#include "udf_sb.h"
@@ -144,50 +145,60 @@ static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
return retval;
}
-int udf_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
- unsigned long arg)
+long udf_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
+ struct inode *inode = filp->f_dentry->d_inode;
long old_block, new_block;
int result = -EINVAL;
+ lock_kernel();
+
if (file_permission(filp, MAY_READ) != 0) {
- udf_debug("no permission to access inode %lu\n",
- inode->i_ino);
- return -EPERM;
+ udf_debug("no permission to access inode %lu\n", inode->i_ino);
+ result = -EPERM;
+ goto out;
}
if (!arg) {
udf_debug("invalid argument to udf_ioctl\n");
- return -EINVAL;
+ result = -EINVAL;
+ goto out;
}
switch (cmd) {
case UDF_GETVOLIDENT:
if (copy_to_user((char __user *)arg,
UDF_SB(inode->i_sb)->s_volume_ident, 32))
- return -EFAULT;
+ result = -EFAULT;
else
- return 0;
+ result = 0;
+ goto out;
case UDF_RELOCATE_BLOCKS:
- if (!capable(CAP_SYS_ADMIN))
- return -EACCES;
- if (get_user(old_block, (long __user *)arg))
- return -EFAULT;
+ if (!capable(CAP_SYS_ADMIN)) {
+ result = -EACCES;
+ goto out;
+ }
+ if (get_user(old_block, (long __user *)arg)) {
+ result = -EFAULT;
+ goto out;
+ }
result = udf_relocate_blocks(inode->i_sb,
old_block, &new_block);
if (result == 0)
result = put_user(new_block, (long __user *)arg);
- return result;
+ goto out;
case UDF_GETEASIZE:
result = put_user(UDF_I(inode)->i_lenEAttr, (int __user *)arg);
- break;
+ goto out;
case UDF_GETEABLOCK:
result = copy_to_user((char __user *)arg,
UDF_I(inode)->i_ext.i_data,
UDF_I(inode)->i_lenEAttr) ? -EFAULT : 0;
- break;
+ goto out;
}
+out:
+ unlock_kernel();
return result;
}
@@ -207,7 +218,7 @@ static int udf_release_file(struct inode *inode, struct file *filp)
const struct file_operations udf_file_operations = {
.read = do_sync_read,
.aio_read = generic_file_aio_read,
- .ioctl = udf_ioctl,
+ .unlocked_ioctl = udf_ioctl,
.open = dquot_file_open,
.mmap = generic_file_mmap,
.write = do_sync_write,
diff --git a/fs/udf/udfdecl.h b/fs/udf/udfdecl.h
index 702a1148e702..9079ff7d6255 100644
--- a/fs/udf/udfdecl.h
+++ b/fs/udf/udfdecl.h
@@ -130,8 +130,7 @@ extern int udf_write_fi(struct inode *inode, struct fileIdentDesc *,
uint8_t *, uint8_t *);
/* file.c */
-extern int udf_ioctl(struct inode *, struct file *, unsigned int,
- unsigned long);
+extern long udf_ioctl(struct file *, unsigned int, unsigned long);
extern int udf_setattr(struct dentry *dentry, struct iattr *iattr);
/* inode.c */
extern struct inode *udf_iget(struct super_block *, struct kernel_lb_addr *);