+#ifdef CONFIG_BLOCK
+
+#define blk_to_logical(inode, blk) (blk << (inode)->i_blkbits)
+#define logical_to_blk(inode, offset) (offset >> (inode)->i_blkbits);
+
+/**
+ * __generic_block_fiemap - FIEMAP for block based inodes (no locking)
+ * @inode - the inode to map
+ * @arg - the pointer to userspace where we copy everything to
+ * @get_block - the fs's get_block function
+ *
+ * This does FIEMAP for block based inodes. Basically it will just loop
+ * through get_block until we hit the number of extents we want to map, or we
+ * go past the end of the file and hit a hole.
+ *
+ * If it is possible to have data blocks beyond a hole past @inode->i_size, then
+ * please do not use this function, it will stop at the first unmapped block
+ * beyond i_size.
+ *
+ * If you use this function directly, you need to do your own locking. Use
+ * generic_block_fiemap if you want the locking done for you.
+ */
+
+int __generic_block_fiemap(struct inode *inode,
+ struct fiemap_extent_info *fieinfo, u64 start,
+ u64 len, get_block_t *get_block)
+{
+ struct buffer_head tmp;
+ unsigned int start_blk;
+ long long length = 0, map_len = 0;
+ u64 logical = 0, phys = 0, size = 0;
+ u32 flags = FIEMAP_EXTENT_MERGED;
+ int ret = 0, past_eof = 0, whole_file = 0;
+
+ if ((ret = fiemap_check_flags(fieinfo, FIEMAP_FLAG_SYNC)))
+ return ret;
+
+ start_blk = logical_to_blk(inode, start);
+
+ length = (long long)min_t(u64, len, i_size_read(inode));
+ if (length < len)
+ whole_file = 1;
+
+ map_len = length;
+
+ do {
+ /*
+ * we set b_size to the total size we want so it will map as
+ * many contiguous blocks as possible at once
+ */
+ memset(&tmp, 0, sizeof(struct buffer_head));
+ tmp.b_size = map_len;
+
+ ret = get_block(inode, start_blk, &tmp, 0);
+ if (ret)
+ break;
+
+ /* HOLE */
+ if (!buffer_mapped(&tmp)) {
+ length -= blk_to_logical(inode, 1);
+ start_blk++;
+
+ /*
+ * we want to handle the case where there is an
+ * allocated block at the front of the file, and then
+ * nothing but holes up to the end of the file properly,
+ * to make sure that extent at the front gets properly
+ * marked with FIEMAP_EXTENT_LAST
+ */
+ if (!past_eof &&
+ blk_to_logical(inode, start_blk) >=
+ blk_to_logical(inode, 0)+i_size_read(inode))
+ past_eof = 1;
+
+ /*
+ * first hole after going past the EOF, this is our
+ * last extent
+ */
+ if (past_eof && size) {
+ flags = FIEMAP_EXTENT_MERGED|FIEMAP_EXTENT_LAST;
+ ret = fiemap_fill_next_extent(fieinfo, logical,
+ phys, size,
+ flags);
+ break;
+ }
+
+ /* if we have holes up to/past EOF then we're done */
+ if (length <= 0 || past_eof)
+ break;
+ } else {
+ /*
+ * we have gone over the length of what we wanted to
+ * map, and it wasn't the entire file, so add the extent
+ * we got last time and exit.
+ *
+ * This is for the case where say we want to map all the
+ * way up to the second to the last block in a file, but
+ * the last block is a hole, making the second to last
+ * block FIEMAP_EXTENT_LAST. In this case we want to
+ * see if there is a hole after the second to last block
+ * so we can mark it properly. If we found data after
+ * we exceeded the length we were requesting, then we
+ * are good to go, just add the extent to the fieinfo
+ * and break
+ */
+ if (length <= 0 && !whole_file) {
+ ret = fiemap_fill_next_extent(fieinfo, logical,
+ phys, size,
+ flags);
+ break;
+ }
+
+ /*
+ * if size != 0 then we know we already have an extent
+ * to add, so add it.
+ */
+ if (size) {
+ ret = fiemap_fill_next_extent(fieinfo, logical,
+ phys, size,
+ flags);
+ if (ret)
+ break;
+ }
+
+ logical = blk_to_logical(inode, start_blk);
+ phys = blk_to_logical(inode, tmp.b_blocknr);
+ size = tmp.b_size;
+ flags = FIEMAP_EXTENT_MERGED;
+
+ length -= tmp.b_size;
+ start_blk += logical_to_blk(inode, size);
+
+ /*
+ * If we are past the EOF, then we need to make sure as
+ * soon as we find a hole that the last extent we found
+ * is marked with FIEMAP_EXTENT_LAST
+ */
+ if (!past_eof &&
+ logical+size >=
+ blk_to_logical(inode, 0)+i_size_read(inode))
+ past_eof = 1;
+ }
+ cond_resched();
+ } while (1);
+
+ /* if ret is 1 then we just hit the end of the extent array */
+ if (ret == 1)
+ ret = 0;
+
+ return ret;
+}
+EXPORT_SYMBOL(__generic_block_fiemap);
+
+/**
+ * generic_block_fiemap - FIEMAP for block based inodes
+ * @inode: The inode to map
+ * @fieinfo: The mapping information
+ * @start: The initial block to map
+ * @len: The length of the extect to attempt to map
+ * @get_block: The block mapping function for the fs
+ *
+ * Calls __generic_block_fiemap to map the inode, after taking
+ * the inode's mutex lock.
+ */
+
+int generic_block_fiemap(struct inode *inode,
+ struct fiemap_extent_info *fieinfo, u64 start,
+ u64 len, get_block_t *get_block)
+{
+ int ret;
+ mutex_lock(&inode->i_mutex);
+ ret = __generic_block_fiemap(inode, fieinfo, start, len, get_block);
+ mutex_unlock(&inode->i_mutex);
+ return ret;
+}
+EXPORT_SYMBOL(generic_block_fiemap);
+
+#endif /* CONFIG_BLOCK */
+
+/*
+ * This provides compatibility with legacy XFS pre-allocation ioctls
+ * which predate the fallocate syscall.
+ *
+ * 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)
+{
+ struct inode *inode = filp->f_path.dentry->d_inode;
+ struct space_resv 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 += filp->f_pos;
+ break;
+ case SEEK_END:
+ sr.l_start += i_size_read(inode);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return do_fallocate(filp, FALLOC_FL_KEEP_SIZE, sr.l_start, sr.l_len);
+}
+