forked from Minki/linux
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:
parent
9afe1d5c14
commit
837a6e7f5c
@ -481,10 +481,13 @@ struct space_resv_32 {
|
||||
};
|
||||
|
||||
#define FS_IOC_RESVSP_32 _IOW ('X', 40, struct space_resv_32)
|
||||
#define FS_IOC_UNRESVSP_32 _IOW ('X', 41, struct space_resv_32)
|
||||
#define FS_IOC_RESVSP64_32 _IOW ('X', 42, struct space_resv_32)
|
||||
#define FS_IOC_UNRESVSP64_32 _IOW ('X', 43, struct space_resv_32)
|
||||
#define FS_IOC_ZERO_RANGE_32 _IOW ('X', 57, struct space_resv_32)
|
||||
|
||||
/* just account for different alignment */
|
||||
static int compat_ioctl_preallocate(struct file *file,
|
||||
static int compat_ioctl_preallocate(struct file *file, int mode,
|
||||
struct space_resv_32 __user *p32)
|
||||
{
|
||||
struct space_resv __user *p = compat_alloc_user_space(sizeof(*p));
|
||||
@ -498,7 +501,7 @@ static int compat_ioctl_preallocate(struct file *file,
|
||||
copy_in_user(&p->l_pad, &p32->l_pad, 4*sizeof(u32)))
|
||||
return -EFAULT;
|
||||
|
||||
return ioctl_preallocate(file, p);
|
||||
return ioctl_preallocate(file, mode, p);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -1022,12 +1025,30 @@ COMPAT_SYSCALL_DEFINE3(ioctl, unsigned int, fd, unsigned int, cmd,
|
||||
#if defined(CONFIG_IA64) || defined(CONFIG_X86_64)
|
||||
case FS_IOC_RESVSP_32:
|
||||
case FS_IOC_RESVSP64_32:
|
||||
error = compat_ioctl_preallocate(f.file, compat_ptr(arg));
|
||||
error = compat_ioctl_preallocate(f.file, 0, compat_ptr(arg));
|
||||
goto out_fput;
|
||||
case FS_IOC_UNRESVSP_32:
|
||||
case FS_IOC_UNRESVSP64_32:
|
||||
error = compat_ioctl_preallocate(f.file, FALLOC_FL_PUNCH_HOLE,
|
||||
compat_ptr(arg));
|
||||
goto out_fput;
|
||||
case FS_IOC_ZERO_RANGE_32:
|
||||
error = compat_ioctl_preallocate(f.file, FALLOC_FL_ZERO_RANGE,
|
||||
compat_ptr(arg));
|
||||
goto out_fput;
|
||||
#else
|
||||
case FS_IOC_RESVSP:
|
||||
case FS_IOC_RESVSP64:
|
||||
error = ioctl_preallocate(f.file, compat_ptr(arg));
|
||||
error = ioctl_preallocate(f.file, 0, compat_ptr(arg));
|
||||
goto out_fput;
|
||||
case FS_IOC_UNRESVSP:
|
||||
case FS_IOC_UNRESVSP64:
|
||||
error = ioctl_preallocate(f.file, FALLOC_FL_PUNCH_HOLE,
|
||||
compat_ptr(arg));
|
||||
goto out_fput;
|
||||
case FS_IOC_ZERO_RANGE:
|
||||
error = ioctl_preallocate(f.file, FALLOC_FL_ZERO_RANGE,
|
||||
compat_ptr(arg));
|
||||
goto out_fput;
|
||||
#endif
|
||||
|
||||
|
12
fs/ioctl.c
12
fs/ioctl.c
@ -466,7 +466,7 @@ EXPORT_SYMBOL(generic_block_fiemap);
|
||||
* Only the l_start, l_len and l_whence fields of the 'struct space_resv'
|
||||
* are used here, rest are ignored.
|
||||
*/
|
||||
int ioctl_preallocate(struct file *filp, void __user *argp)
|
||||
int ioctl_preallocate(struct file *filp, int mode, void __user *argp)
|
||||
{
|
||||
struct inode *inode = file_inode(filp);
|
||||
struct space_resv sr;
|
||||
@ -487,7 +487,8 @@ int ioctl_preallocate(struct file *filp, void __user *argp)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return vfs_fallocate(filp, FALLOC_FL_KEEP_SIZE, sr.l_start, sr.l_len);
|
||||
return vfs_fallocate(filp, mode | FALLOC_FL_KEEP_SIZE, sr.l_start,
|
||||
sr.l_len);
|
||||
}
|
||||
|
||||
static int file_ioctl(struct file *filp, unsigned int cmd,
|
||||
@ -503,7 +504,12 @@ static int file_ioctl(struct file *filp, unsigned int cmd,
|
||||
return put_user(i_size_read(inode) - filp->f_pos, p);
|
||||
case FS_IOC_RESVSP:
|
||||
case FS_IOC_RESVSP64:
|
||||
return ioctl_preallocate(filp, p);
|
||||
return ioctl_preallocate(filp, 0, p);
|
||||
case FS_IOC_UNRESVSP:
|
||||
case FS_IOC_UNRESVSP64:
|
||||
return ioctl_preallocate(filp, FALLOC_FL_PUNCH_HOLE, p);
|
||||
case FS_IOC_ZERO_RANGE:
|
||||
return ioctl_preallocate(filp, FALLOC_FL_ZERO_RANGE, p);
|
||||
}
|
||||
|
||||
return vfs_ioctl(filp, cmd, arg);
|
||||
|
@ -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,48 +634,11 @@ 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);
|
||||
@ -686,14 +648,7 @@ xfs_ioc_space(
|
||||
|
||||
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 (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);
|
||||
|
@ -9,7 +9,6 @@
|
||||
extern int
|
||||
xfs_ioc_space(
|
||||
struct file *filp,
|
||||
unsigned int cmd,
|
||||
xfs_flock64_t *bf);
|
||||
|
||||
int
|
||||
|
@ -557,16 +557,13 @@ xfs_file_compat_ioctl(
|
||||
case XFS_IOC_ALLOCSP_32:
|
||||
case XFS_IOC_FREESP_32:
|
||||
case XFS_IOC_ALLOCSP64_32:
|
||||
case XFS_IOC_FREESP64_32:
|
||||
case XFS_IOC_RESVSP64_32:
|
||||
case XFS_IOC_UNRESVSP64_32:
|
||||
case XFS_IOC_ZERO_RANGE_32: {
|
||||
case XFS_IOC_FREESP64_32: {
|
||||
struct xfs_flock64 bf;
|
||||
|
||||
if (xfs_compat_flock64_copyin(&bf, arg))
|
||||
return -EFAULT;
|
||||
cmd = _NATIVE_IOC(cmd, struct xfs_flock64);
|
||||
return xfs_ioc_space(filp, cmd, &bf);
|
||||
return xfs_ioc_space(filp, &bf);
|
||||
}
|
||||
case XFS_IOC_FSGEOMETRY_V1_32:
|
||||
return xfs_compat_ioc_fsgeometry_v1(mp, arg);
|
||||
|
@ -20,7 +20,10 @@ struct space_resv {
|
||||
};
|
||||
|
||||
#define FS_IOC_RESVSP _IOW('X', 40, struct space_resv)
|
||||
#define FS_IOC_UNRESVSP _IOW('X', 41, struct space_resv)
|
||||
#define FS_IOC_RESVSP64 _IOW('X', 42, struct space_resv)
|
||||
#define FS_IOC_UNRESVSP64 _IOW('X', 43, struct space_resv)
|
||||
#define FS_IOC_ZERO_RANGE _IOW('X', 57, struct space_resv)
|
||||
|
||||
#define FALLOC_FL_SUPPORTED_MASK (FALLOC_FL_KEEP_SIZE | \
|
||||
FALLOC_FL_PUNCH_HOLE | \
|
||||
|
@ -2547,7 +2547,7 @@ extern int finish_no_open(struct file *file, struct dentry *dentry);
|
||||
|
||||
/* fs/ioctl.c */
|
||||
|
||||
extern int ioctl_preallocate(struct file *filp, void __user *argp);
|
||||
extern int ioctl_preallocate(struct file *filp, int mode, void __user *argp);
|
||||
|
||||
/* fs/dcache.c */
|
||||
extern void __init vfs_caches_init_early(void);
|
||||
|
Loading…
Reference in New Issue
Block a user