]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
fs: add generic UNRESVSP and ZERO_RANGE ioctl handlers
authorChristoph Hellwig <hch@lst.de>
Fri, 25 Oct 2019 05:26:02 +0000 (22:26 -0700)
committerDarrick J. Wong <darrick.wong@oracle.com>
Mon, 28 Oct 2019 15:37:55 +0000 (08:37 -0700)
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>
fs/compat_ioctl.c
fs/ioctl.c
fs/xfs/xfs_ioctl.c
fs/xfs/xfs_ioctl.h
fs/xfs/xfs_ioctl32.c
include/linux/falloc.h
include/linux/fs.h

index a7ec2d3dff9282bf6e8fbc2c29e2f8e0301efb39..62e530814cef9ac563d6e75f8974e6254ec08e06 100644 (file)
@@ -480,11 +480,14 @@ struct space_resv_32 {
        __s32           l_pad[4];       /* reserve area */
 };
 
-#define FS_IOC_RESVSP_32               _IOW ('X', 40, 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
 
index fef3a6bf7c78dd2e6dc8587ae4837f9d4e35cf1c..55c7cfb0e59967a8c2d93ebd0c1dbc2a3c69b4f7 100644 (file)
@@ -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);
index 2f26417405a5c022cccf03ef6a27be802043b74f..e897d5363d010748e60259bd95ca72d31ab20692 100644 (file)
@@ -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);
index 654c0bb1bcf8981c1f863ec315a409c0906365c3..25ef178cbb74829074cae1c72bd5a156dd4b8608 100644 (file)
@@ -9,7 +9,6 @@
 extern int
 xfs_ioc_space(
        struct file             *filp,
-       unsigned int            cmd,
        xfs_flock64_t           *bf);
 
 int
index 257b7caf7fed6d9cd884a599b6cc45e1b77a5ce3..3c0d518e1039ee510585a78e12aba99b9dab5f79 100644 (file)
@@ -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);
index 674d59f4d6ce581b8c713ab1615e6de7b096ca8c..f5c73f0ec22d7c683511959c121035999c9cc835 100644 (file)
@@ -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 |         \
index e0d909d357634bb26a9adfa65ddbcc9bce5364f6..2b5692207c1dc02bc1bfce44a4d5c0fabcb881e6 100644 (file)
@@ -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);