diff options
Diffstat (limited to 'fs/udf/file.c')
| -rw-r--r-- | fs/udf/file.c | 47 | 
1 files changed, 29 insertions, 18 deletions
diff --git a/fs/udf/file.c b/fs/udf/file.c index 4b6a46ccbf46..0660280aa180 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,13 +218,13 @@ 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,  	.aio_write		= udf_file_aio_write,  	.release		= udf_release_file, -	.fsync			= simple_fsync, +	.fsync			= generic_file_fsync,  	.splice_read		= generic_file_splice_read,  	.llseek			= generic_file_llseek,  }; @@ -227,7 +238,7 @@ int udf_setattr(struct dentry *dentry, struct iattr *iattr)  	if (error)  		return error; -	if (iattr->ia_valid & ATTR_SIZE) +	if (is_quota_modification(inode, iattr))  		dquot_initialize(inode);  	if ((iattr->ia_valid & ATTR_UID && iattr->ia_uid != inode->i_uid) ||  |