fs: add generic UNRESVSP and ZERO_RANGE ioctl handlers
These use the same scheme as the pre-existing mapping of the XFS RESVP ioctls to ->falloc, so just extend it and remove the XFS implementation. Signed-off-by: Christoph Hellwig <hch@lst.de> [darrick: fix compile error on s390] Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
This commit is contained in:

committed by
Darrick J. Wong

parent
9afe1d5c14
commit
837a6e7f5c
@@ -588,13 +588,12 @@ xfs_attrmulti_by_handle(
|
||||
int
|
||||
xfs_ioc_space(
|
||||
struct file *filp,
|
||||
unsigned int cmd,
|
||||
xfs_flock64_t *bf)
|
||||
{
|
||||
struct inode *inode = file_inode(filp);
|
||||
struct xfs_inode *ip = XFS_I(inode);
|
||||
struct iattr iattr;
|
||||
enum xfs_prealloc_flags flags = 0;
|
||||
enum xfs_prealloc_flags flags = XFS_PREALLOC_CLEAR;
|
||||
uint iolock = XFS_IOLOCK_EXCL | XFS_MMAPLOCK_EXCL;
|
||||
int error;
|
||||
|
||||
@@ -635,65 +634,21 @@ xfs_ioc_space(
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
/*
|
||||
* length of <= 0 for resv/unresv/zero is invalid. length for
|
||||
* alloc/free is ignored completely and we have no idea what userspace
|
||||
* might have set it to, so set it to zero to allow range
|
||||
* checks to pass.
|
||||
*/
|
||||
switch (cmd) {
|
||||
case XFS_IOC_ZERO_RANGE:
|
||||
case XFS_IOC_UNRESVSP:
|
||||
case XFS_IOC_UNRESVSP64:
|
||||
if (bf->l_len <= 0) {
|
||||
error = -EINVAL;
|
||||
goto out_unlock;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
bf->l_len = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (bf->l_start < 0 ||
|
||||
bf->l_start > inode->i_sb->s_maxbytes ||
|
||||
bf->l_start + bf->l_len < 0 ||
|
||||
bf->l_start + bf->l_len >= inode->i_sb->s_maxbytes) {
|
||||
if (bf->l_start < 0 || bf->l_start > inode->i_sb->s_maxbytes) {
|
||||
error = -EINVAL;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
switch (cmd) {
|
||||
case XFS_IOC_ZERO_RANGE:
|
||||
flags |= XFS_PREALLOC_SET;
|
||||
error = xfs_zero_file_space(ip, bf->l_start, bf->l_len);
|
||||
break;
|
||||
case XFS_IOC_UNRESVSP:
|
||||
case XFS_IOC_UNRESVSP64:
|
||||
error = xfs_free_file_space(ip, bf->l_start, bf->l_len);
|
||||
break;
|
||||
case XFS_IOC_ALLOCSP:
|
||||
case XFS_IOC_ALLOCSP64:
|
||||
case XFS_IOC_FREESP:
|
||||
case XFS_IOC_FREESP64:
|
||||
flags |= XFS_PREALLOC_CLEAR;
|
||||
if (bf->l_start > XFS_ISIZE(ip)) {
|
||||
error = xfs_alloc_file_space(ip, XFS_ISIZE(ip),
|
||||
bf->l_start - XFS_ISIZE(ip), 0);
|
||||
if (error)
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
iattr.ia_valid = ATTR_SIZE;
|
||||
iattr.ia_size = bf->l_start;
|
||||
|
||||
error = xfs_vn_setattr_size(file_dentry(filp), &iattr);
|
||||
break;
|
||||
default:
|
||||
ASSERT(0);
|
||||
error = -EINVAL;
|
||||
if (bf->l_start > XFS_ISIZE(ip)) {
|
||||
error = xfs_alloc_file_space(ip, XFS_ISIZE(ip),
|
||||
bf->l_start - XFS_ISIZE(ip), 0);
|
||||
if (error)
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
iattr.ia_valid = ATTR_SIZE;
|
||||
iattr.ia_size = bf->l_start;
|
||||
error = xfs_vn_setattr_size(file_dentry(filp), &iattr);
|
||||
if (error)
|
||||
goto out_unlock;
|
||||
|
||||
@@ -2113,16 +2068,13 @@ xfs_file_ioctl(
|
||||
return xfs_ioc_setlabel(filp, mp, arg);
|
||||
case XFS_IOC_ALLOCSP:
|
||||
case XFS_IOC_FREESP:
|
||||
case XFS_IOC_UNRESVSP:
|
||||
case XFS_IOC_ALLOCSP64:
|
||||
case XFS_IOC_FREESP64:
|
||||
case XFS_IOC_UNRESVSP64:
|
||||
case XFS_IOC_ZERO_RANGE: {
|
||||
case XFS_IOC_FREESP64: {
|
||||
xfs_flock64_t bf;
|
||||
|
||||
if (copy_from_user(&bf, arg, sizeof(bf)))
|
||||
return -EFAULT;
|
||||
return xfs_ioc_space(filp, cmd, &bf);
|
||||
return xfs_ioc_space(filp, &bf);
|
||||
}
|
||||
case XFS_IOC_DIOINFO: {
|
||||
struct xfs_buftarg *target = xfs_inode_buftarg(ip);
|
||||
|
Reference in New Issue
Block a user