__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));
            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
 
 #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
 
 
  * 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;
                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,
                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);
 
 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;
 
                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;
 
                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);
 
 extern int
 xfs_ioc_space(
        struct file             *filp,
-       unsigned int            cmd,
        xfs_flock64_t           *bf);
 
 int
 
        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);
 
 };
 
 #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 |         \
 
 
 /* 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);