Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-udf-2.6

* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-udf-2.6:
  udf: BKL ioctl pushdown
This commit is contained in:
Linus Torvalds 2010-05-21 11:17:43 -07:00
commit d515e86e63
3 changed files with 29 additions and 19 deletions

View File

@ -209,6 +209,6 @@ static int udf_readdir(struct file *filp, void *dirent, filldir_t filldir)
const struct file_operations udf_dir_operations = { const struct file_operations udf_dir_operations = {
.read = generic_read_dir, .read = generic_read_dir,
.readdir = udf_readdir, .readdir = udf_readdir,
.ioctl = udf_ioctl, .unlocked_ioctl = udf_ioctl,
.fsync = simple_fsync, .fsync = simple_fsync,
}; };

View File

@ -37,6 +37,7 @@
#include <linux/quotaops.h> #include <linux/quotaops.h>
#include <linux/buffer_head.h> #include <linux/buffer_head.h>
#include <linux/aio.h> #include <linux/aio.h>
#include <linux/smp_lock.h>
#include "udf_i.h" #include "udf_i.h"
#include "udf_sb.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; return retval;
} }
int udf_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, long udf_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
unsigned long arg)
{ {
struct inode *inode = filp->f_dentry->d_inode;
long old_block, new_block; long old_block, new_block;
int result = -EINVAL; int result = -EINVAL;
lock_kernel();
if (file_permission(filp, MAY_READ) != 0) { if (file_permission(filp, MAY_READ) != 0) {
udf_debug("no permission to access inode %lu\n", udf_debug("no permission to access inode %lu\n", inode->i_ino);
inode->i_ino); result = -EPERM;
return -EPERM; goto out;
} }
if (!arg) { if (!arg) {
udf_debug("invalid argument to udf_ioctl\n"); udf_debug("invalid argument to udf_ioctl\n");
return -EINVAL; result = -EINVAL;
goto out;
} }
switch (cmd) { switch (cmd) {
case UDF_GETVOLIDENT: case UDF_GETVOLIDENT:
if (copy_to_user((char __user *)arg, if (copy_to_user((char __user *)arg,
UDF_SB(inode->i_sb)->s_volume_ident, 32)) UDF_SB(inode->i_sb)->s_volume_ident, 32))
return -EFAULT; result = -EFAULT;
else else
return 0; result = 0;
goto out;
case UDF_RELOCATE_BLOCKS: case UDF_RELOCATE_BLOCKS:
if (!capable(CAP_SYS_ADMIN)) if (!capable(CAP_SYS_ADMIN)) {
return -EACCES; result = -EACCES;
if (get_user(old_block, (long __user *)arg)) goto out;
return -EFAULT; }
if (get_user(old_block, (long __user *)arg)) {
result = -EFAULT;
goto out;
}
result = udf_relocate_blocks(inode->i_sb, result = udf_relocate_blocks(inode->i_sb,
old_block, &new_block); old_block, &new_block);
if (result == 0) if (result == 0)
result = put_user(new_block, (long __user *)arg); result = put_user(new_block, (long __user *)arg);
return result; goto out;
case UDF_GETEASIZE: case UDF_GETEASIZE:
result = put_user(UDF_I(inode)->i_lenEAttr, (int __user *)arg); result = put_user(UDF_I(inode)->i_lenEAttr, (int __user *)arg);
break; goto out;
case UDF_GETEABLOCK: case UDF_GETEABLOCK:
result = copy_to_user((char __user *)arg, result = copy_to_user((char __user *)arg,
UDF_I(inode)->i_ext.i_data, UDF_I(inode)->i_ext.i_data,
UDF_I(inode)->i_lenEAttr) ? -EFAULT : 0; UDF_I(inode)->i_lenEAttr) ? -EFAULT : 0;
break; goto out;
} }
out:
unlock_kernel();
return result; return result;
} }
@ -207,7 +218,7 @@ static int udf_release_file(struct inode *inode, struct file *filp)
const struct file_operations udf_file_operations = { const struct file_operations udf_file_operations = {
.read = do_sync_read, .read = do_sync_read,
.aio_read = generic_file_aio_read, .aio_read = generic_file_aio_read,
.ioctl = udf_ioctl, .unlocked_ioctl = udf_ioctl,
.open = dquot_file_open, .open = dquot_file_open,
.mmap = generic_file_mmap, .mmap = generic_file_mmap,
.write = do_sync_write, .write = do_sync_write,

View File

@ -130,8 +130,7 @@ extern int udf_write_fi(struct inode *inode, struct fileIdentDesc *,
uint8_t *, uint8_t *); uint8_t *, uint8_t *);
/* file.c */ /* file.c */
extern int udf_ioctl(struct inode *, struct file *, unsigned int, extern long udf_ioctl(struct file *, unsigned int, unsigned long);
unsigned long);
extern int udf_setattr(struct dentry *dentry, struct iattr *iattr); extern int udf_setattr(struct dentry *dentry, struct iattr *iattr);
/* inode.c */ /* inode.c */
extern struct inode *udf_iget(struct super_block *, struct kernel_lb_addr *); extern struct inode *udf_iget(struct super_block *, struct kernel_lb_addr *);