Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 83aee9e4 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Ben Myers
Browse files

xfs: simplify the fallocate path



Call xfs_alloc_file_space or xfs_free_file_space directly from
xfs_file_fallocate instead of going through xfs_change_file_space.

This simplified the code by removing the unessecary marshalling of the
arguments into an xfs_flock64_t structure and allows removing checks that
are already done in the VFS code.

Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarDave Chinner <dchinner@redhat.com>
Signed-off-by: default avatarBen Myers <bpm@sgi.com>
parent 5f8aca8b
Loading
Loading
Loading
Loading
+4 −35
Original line number Original line Diff line number Diff line
@@ -965,28 +965,9 @@ xfs_free_eofblocks(
	return error;
	return error;
}
}


/*
int
 * xfs_alloc_file_space()
 *      This routine allocates disk space for the given file.
 *
 *	If alloc_type == 0, this request is for an ALLOCSP type
 *	request which will change the file size.  In this case, no
 *	DMAPI event will be generated by the call.  A TRUNCATE event
 *	will be generated later by xfs_setattr.
 *
 *	If alloc_type != 0, this request is for a RESVSP type
 *	request, and a DMAPI DM_EVENT_WRITE will be generated if the
 *	lower block boundary byte address is less than the file's
 *	length.
 *
 * RETURNS:
 *       0 on success
 *      errno on error
 *
 */
STATIC int
xfs_alloc_file_space(
xfs_alloc_file_space(
	xfs_inode_t		*ip,
	struct xfs_inode	*ip,
	xfs_off_t		offset,
	xfs_off_t		offset,
	xfs_off_t		len,
	xfs_off_t		len,
	int			alloc_type)
	int			alloc_type)
@@ -1231,21 +1212,9 @@ xfs_zero_remaining_bytes(
	return error;
	return error;
}
}


/*
int
 * xfs_free_file_space()
 *      This routine frees disk space for the given file.
 *
 *	This routine is only called by xfs_change_file_space
 *	for an UNRESVSP type call.
 *
 * RETURNS:
 *       0 on success
 *      errno on error
 *
 */
STATIC int
xfs_free_file_space(
xfs_free_file_space(
	xfs_inode_t		*ip,
	struct xfs_inode	*ip,
	xfs_off_t		offset,
	xfs_off_t		offset,
	xfs_off_t		len)
	xfs_off_t		len)
{
{
+4 −0
Original line number Original line Diff line number Diff line
@@ -96,6 +96,10 @@ int xfs_bmap_last_extent(struct xfs_trans *tp, struct xfs_inode *ip,
int	xfs_change_file_space(struct xfs_inode *ip, int cmd,
int	xfs_change_file_space(struct xfs_inode *ip, int cmd,
			      xfs_flock64_t *bf, xfs_off_t offset,
			      xfs_flock64_t *bf, xfs_off_t offset,
			      int attr_flags);
			      int attr_flags);
int	xfs_alloc_file_space(struct xfs_inode *ip, xfs_off_t offset,
			     xfs_off_t len, int alloc_type);
int	xfs_free_file_space(struct xfs_inode *ip, xfs_off_t offset,
			    xfs_off_t len);


/* EOF block manipulation functions */
/* EOF block manipulation functions */
bool	xfs_can_free_eofblocks(struct xfs_inode *ip, bool force);
bool	xfs_can_free_eofblocks(struct xfs_inode *ip, bool force);
+48 −28
Original line number Original line Diff line number Diff line
@@ -811,38 +811,58 @@ xfs_file_fallocate(
	loff_t			len)
	loff_t			len)
{
{
	struct inode		*inode = file_inode(file);
	struct inode		*inode = file_inode(file);
	struct xfs_inode	*ip = XFS_I(inode);
	struct xfs_trans	*tp;
	long			error;
	long			error;
	loff_t			new_size = 0;
	loff_t			new_size = 0;
	xfs_flock64_t	bf;
	xfs_inode_t	*ip = XFS_I(inode);
	int		cmd = XFS_IOC_RESVSP;
	int		attr_flags = 0;


	if (!S_ISREG(inode->i_mode))
		return -EINVAL;
	if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE))
	if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE))
		return -EOPNOTSUPP;
		return -EOPNOTSUPP;


	bf.l_whence = 0;
	bf.l_start = offset;
	bf.l_len = len;

	xfs_ilock(ip, XFS_IOLOCK_EXCL);
	xfs_ilock(ip, XFS_IOLOCK_EXCL);

	if (mode & FALLOC_FL_PUNCH_HOLE) {
	if (mode & FALLOC_FL_PUNCH_HOLE)
		error = xfs_free_file_space(ip, offset, len);
		cmd = XFS_IOC_UNRESVSP;
		if (error)

			goto out_unlock;
	/* check the new inode size is valid before allocating */
	} else {
		if (!(mode & FALLOC_FL_KEEP_SIZE) &&
		if (!(mode & FALLOC_FL_KEEP_SIZE) &&
		    offset + len > i_size_read(inode)) {
		    offset + len > i_size_read(inode)) {
			new_size = offset + len;
			new_size = offset + len;
		error = inode_newsize_ok(inode, new_size);
			error = -inode_newsize_ok(inode, new_size);
			if (error)
			if (error)
				goto out_unlock;
				goto out_unlock;
		}
		}


	if (file->f_flags & O_DSYNC)
		error = xfs_alloc_file_space(ip, offset, len,
		attr_flags |= XFS_ATTR_SYNC;
					     XFS_BMAPI_PREALLOC);
		if (error)
			goto out_unlock;
	}

	tp = xfs_trans_alloc(ip->i_mount, XFS_TRANS_WRITEID);
	error = xfs_trans_reserve(tp, &M_RES(ip->i_mount)->tr_writeid, 0, 0);
	if (error) {
		xfs_trans_cancel(tp, 0);
		goto out_unlock;
	}

	xfs_ilock(ip, XFS_ILOCK_EXCL);
	xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
	ip->i_d.di_mode &= ~S_ISUID;
	if (ip->i_d.di_mode & S_IXGRP)
		ip->i_d.di_mode &= ~S_ISGID;


	error = -xfs_change_file_space(ip, cmd, &bf, 0, attr_flags);
	if (!(mode & FALLOC_FL_PUNCH_HOLE))
		ip->i_d.di_flags |= XFS_DIFLAG_PREALLOC;

	xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);

	if (file->f_flags & O_DSYNC)
		xfs_trans_set_sync(tp);
	error = xfs_trans_commit(tp, 0);
	if (error)
	if (error)
		goto out_unlock;
		goto out_unlock;


@@ -852,12 +872,12 @@ xfs_file_fallocate(


		iattr.ia_valid = ATTR_SIZE;
		iattr.ia_valid = ATTR_SIZE;
		iattr.ia_size = new_size;
		iattr.ia_size = new_size;
		error = -xfs_setattr_size(ip, &iattr);
		error = xfs_setattr_size(ip, &iattr);
	}
	}


out_unlock:
out_unlock:
	xfs_iunlock(ip, XFS_IOLOCK_EXCL);
	xfs_iunlock(ip, XFS_IOLOCK_EXCL);
	return error;
	return -error;
}
}