case FIONBIO:
        case FIOASYNC:
        case FIOQSIZE:
 -              break;
 -
 -#if defined(CONFIG_IA64) || defined(CONFIG_X86_64)
 +      case FS_IOC_FIEMAP:
 +      case FIGETBSZ:
 +      case FICLONERANGE:
 +      case FIDEDUPERANGE:
 +              goto found_handler;
 +      /*
 +       * The next group is the stuff handled inside file_ioctl().
 +       * For regular files these never reach ->ioctl(); for
 +       * devices, sockets, etc. they do and one (FIONREAD) is
 +       * even accepted in some cases.  In all those cases
 +       * argument has the same type, so we can handle these
 +       * here, shunting them towards do_vfs_ioctl().
 +       * ->compat_ioctl() will never see any of those.
 +       */
 +      /* pointer argument, never actually handled by ->ioctl() */
 +      case FIBMAP:
 +              goto found_handler;
 +      /* handled by some ->ioctl(); always a pointer to int */
 +      case FIONREAD:
 +              goto found_handler;
-       /* these two get messy on amd64 due to alignment differences */
++      /* these get messy on amd64 due to alignment differences */
 +#if 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, 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;
 +              goto found_handler;
  #endif
  
 -      case FICLONE:
 -      case FICLONERANGE:
 -      case FIDEDUPERANGE:
 -      case FS_IOC_FIEMAP:
 -              goto do_ioctl;
 -
 -      case FIBMAP:
 -      case FIGETBSZ:
 -      case FIONREAD:
 -              if (S_ISREG(file_inode(f.file)->i_mode))
 -                      break;
 -              /*FALL THROUGH*/
 -
        default:
                if (f.file->f_op->compat_ioctl) {
                        error = f.file->f_op->compat_ioctl(f.file, cmd, arg);
 
                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);
  }
  
- int compat_ioctl_preallocate(struct file *file,
 +/* on ia32 l_start is on a 32-bit boundary */
 +#if defined CONFIG_COMPAT && defined(CONFIG_X86_64)
 +/* just account for different alignment */
-       return vfs_fallocate(file, FALLOC_FL_KEEP_SIZE, sr.l_start, sr.l_len);
++int compat_ioctl_preallocate(struct file *file, int mode,
 +                              struct space_resv_32 __user *argp)
 +{
 +      struct inode *inode = file_inode(file);
 +      struct space_resv_32 sr;
 +
 +      if (copy_from_user(&sr, argp, sizeof(sr)))
 +              return -EFAULT;
 +
 +      switch (sr.l_whence) {
 +      case SEEK_SET:
 +              break;
 +      case SEEK_CUR:
 +              sr.l_start += file->f_pos;
 +              break;
 +      case SEEK_END:
 +              sr.l_start += i_size_read(inode);
 +              break;
 +      default:
 +              return -EINVAL;
 +      }
 +
++      return vfs_fallocate(file, mode | FALLOC_FL_KEEP_SIZE, sr.l_start, sr.l_len);
 +}
 +#endif
 +
  static int file_ioctl(struct file *filp, unsigned int cmd,
                unsigned long arg)
  {
 
                                         FALLOC_FL_INSERT_RANGE |       \
                                         FALLOC_FL_UNSHARE_RANGE)
  
- #define FS_IOC_RESVSP_32              _IOW ('X', 40, struct space_resv_32)
 +/* on ia32 l_start is on a 32-bit boundary */
 +#if defined(CONFIG_X86_64)
 +struct space_resv_32 {
 +      __s16           l_type;
 +      __s16           l_whence;
 +      __s64           l_start __attribute__((packed));
 +                      /* len == 0 means until end of file */
 +      __s64           l_len __attribute__((packed));
 +      __s32           l_sysid;
 +      __u32           l_pid;
 +      __s32           l_pad[4];       /* reserve area */
 +};
 +
- int compat_ioctl_preallocate(struct file *, struct space_resv_32 __user *);
++#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)
 +
++int compat_ioctl_preallocate(struct file *, int, struct space_resv_32 __user *);
 +
 +#endif
 +
  #endif /* _FALLOC_H_ */