From: Dave Chinner <dchinner@xxxxxxxxxx> Provision space in the block device for preallocated file space when userspace asks for it. Make sure to do this outside of transaction context so it can fail without causing a filesystem shutdown. XXX: async provisioning submission/completion interface would be really useful here.... Signed-off-by: Dave Chinner <dchinner@xxxxxxxxxx> --- fs/xfs/xfs_bmap_util.c | 42 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 37 insertions(+), 5 deletions(-) diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c index fcefab687285..5dddd1e7bc47 100644 --- a/fs/xfs/xfs_bmap_util.c +++ b/fs/xfs/xfs_bmap_util.c @@ -772,6 +772,37 @@ xfs_free_eofblocks( return error; } +static int +xfs_bmap_provision_blocks( + struct xfs_inode *ip, + struct xfs_bmbt_irec *imap, + int nimaps) +{ + struct xfs_mount *mp = ip->i_mount; + struct xfs_buftarg *target; + int i; + + if (!xfs_is_provisioning_blocks(mp)) + return 0; + + target = xfs_inode_buftarg(ip); + if (!target->bt_needs_provisioning) + return 0; + + for (i = 0; i < nimaps; i++) { + int error; + + error = blkdev_issue_provision(target->bt_bdev, + XFS_FSB_TO_DADDR(mp, imap->br_startblock), + XFS_FSB_TO_BB(mp, imap->br_blockcount), + GFP_KERNEL, 0); + ASSERT(error != -EOPNOTSUPP); + if (error) + return error; + } + return 0; +} + int xfs_alloc_file_space( struct xfs_inode *ip, @@ -780,7 +811,6 @@ xfs_alloc_file_space( { xfs_mount_t *mp = ip->i_mount; xfs_off_t count; - xfs_filblks_t allocated_fsb; xfs_filblks_t allocatesize_fsb; xfs_extlen_t extsz, temp; xfs_fileoff_t startoffset_fsb; @@ -884,15 +914,17 @@ xfs_alloc_file_space( if (error) break; - allocated_fsb = imapp->br_blockcount; - if (nimaps == 0) { error = -ENOSPC; break; } - startoffset_fsb += allocated_fsb; - allocatesize_fsb -= allocated_fsb; + error = xfs_bmap_provision_blocks(ip, imapp, nimaps); + if (error) + break; + + startoffset_fsb += imapp->br_blockcount; + allocatesize_fsb -= imapp->br_blockcount; } return error;