* are safe.  We don't really care if non-io related
         * fields change.
         */
-
-       xfs_tosspages(ip, 0, -1, FI_REMAPF);
+       truncate_pagecache_range(VFS_I(ip), 0, -1);
 
        tp = xfs_trans_alloc(mp, XFS_TRANS_SWAPEXT);
        if ((error = xfs_trans_reserve(tp, 0,
 
  * note: all filemap functions return negative error codes. These
  * need to be inverted before returning to the xfs core functions.
  */
-void
-xfs_tosspages(
-       xfs_inode_t     *ip,
-       xfs_off_t       first,
-       xfs_off_t       last,
-       int             fiopt)
-{
-       /* can't toss partial tail pages, so mask them out */
-       last &= ~(PAGE_SIZE - 1);
-       truncate_inode_pages_range(VFS_I(ip)->i_mapping, first, last - 1);
-}
-
 int
 xfs_flushinval_pages(
        xfs_inode_t     *ip,
 
        xfs_fsize_t     fsize;
        int             setprealloc;
        xfs_off_t       startoffset;
-       xfs_off_t       llen;
+       xfs_off_t       end;
        xfs_trans_t     *tp;
        struct iattr    iattr;
        int             prealloc_type;
                return XFS_ERROR(EINVAL);
        }
 
-       llen = bf->l_len > 0 ? bf->l_len - 1 : bf->l_len;
+       /*
+        * 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_RESVSP:
+       case XFS_IOC_RESVSP64:
+       case XFS_IOC_UNRESVSP:
+       case XFS_IOC_UNRESVSP64:
+               if (bf->l_len <= 0)
+                       return XFS_ERROR(EINVAL);
+               break;
+       default:
+               bf->l_len = 0;
+               break;
+       }
 
        if (bf->l_start < 0 ||
            bf->l_start > mp->m_super->s_maxbytes ||
-           bf->l_start + llen < 0 ||
-           bf->l_start + llen > mp->m_super->s_maxbytes)
+           bf->l_start + bf->l_len < 0 ||
+           bf->l_start + bf->l_len >= mp->m_super->s_maxbytes)
                return XFS_ERROR(EINVAL);
 
        bf->l_whence = 0;
        switch (cmd) {
        case XFS_IOC_ZERO_RANGE:
                prealloc_type |= XFS_BMAPI_CONVERT;
-               xfs_tosspages(ip, startoffset, startoffset + bf->l_len, 0);
+               end = round_down(startoffset + bf->l_len, PAGE_SIZE) - 1;
+               if (startoffset > end)
+                       truncate_pagecache_range(VFS_I(ip), startoffset, end);
                /* FALLTHRU */
        case XFS_IOC_RESVSP:
        case XFS_IOC_RESVSP64:
 
 int xfs_attr_remove(struct xfs_inode *dp, const unsigned char *name, int flags);
 int xfs_attr_list(struct xfs_inode *dp, char *buffer, int bufsize,
                int flags, struct attrlist_cursor_kern *cursor);
-void xfs_tosspages(struct xfs_inode *inode, xfs_off_t first,
-               xfs_off_t last, int fiopt);
 int xfs_flushinval_pages(struct xfs_inode *ip, xfs_off_t first,
                xfs_off_t last, int fiopt);
 int xfs_flush_pages(struct xfs_inode *ip, xfs_off_t first,