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

Commit ecfea3f0 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Darrick J. Wong
Browse files

xfs: split xfs_bmap_shift_extents



Have a separate helper for insert vs collapse, as this prepares us for
simplifying the code in the next patches.

Also changed the done output argument to a bool intead of int for both
new functions.

Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
parent 6b18af0d
Loading
Loading
Loading
Loading
+135 −62
Original line number Diff line number Diff line
@@ -5700,57 +5700,151 @@ xfs_bmse_shift_one(
	return xfs_rmap_map_extent(mp, dfops, ip, whichfork, &new);
}

int
xfs_bmap_collapse_extents(
	struct xfs_trans	*tp,
	struct xfs_inode	*ip,
	xfs_fileoff_t		*next_fsb,
	xfs_fileoff_t		offset_shift_fsb,
	bool			*done,
	xfs_fileoff_t		stop_fsb,
	xfs_fsblock_t		*firstblock,
	struct xfs_defer_ops	*dfops)
{
	int			whichfork = XFS_DATA_FORK;
	struct xfs_mount	*mp = ip->i_mount;
	struct xfs_ifork	*ifp = XFS_IFORK_PTR(ip, whichfork);
	struct xfs_btree_cur	*cur = NULL;
	struct xfs_bmbt_irec	got;
	xfs_extnum_t		current_ext;
	xfs_extnum_t		total_extents;
	xfs_extnum_t		stop_extent;
	int			error = 0;
	int			logflags = 0;

	if (unlikely(XFS_TEST_ERROR(
	    (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS &&
	     XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE),
	     mp, XFS_ERRTAG_BMAPIFORMAT))) {
		XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, mp);
		return -EFSCORRUPTED;
	}

	if (XFS_FORCED_SHUTDOWN(mp))
		return -EIO;

	ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL));

	if (!(ifp->if_flags & XFS_IFEXTENTS)) {
		error = xfs_iread_extents(tp, ip, whichfork);
		if (error)
			return error;
	}

	if (ifp->if_flags & XFS_IFBROOT) {
		cur = xfs_bmbt_init_cursor(mp, tp, ip, whichfork);
		cur->bc_private.b.firstblock = *firstblock;
		cur->bc_private.b.dfops = dfops;
		cur->bc_private.b.flags = 0;
	}

	/*
	 * There may be delalloc extents in the data fork before the range we
	 * are collapsing out, so we cannot use the count of real extents here.
	 * Instead we have to calculate it from the incore fork.
	 */
	total_extents = xfs_iext_count(ifp);
	if (total_extents == 0) {
		*done = true;
		goto del_cursor;
	}

	/*
 * Shift extent records to the left/right to cover/create a hole.
	 * Look up the extent index for the fsb where we start shifting. We can
	 * henceforth iterate with current_ext as extent list changes are locked
	 * out via ilock.
	 *
 * @stop_fsb specifies the file offset at which to stop shift and the
 * file offset where we've left off is returned in @next_fsb. @offset_shift_fsb
 * is the length by which each extent is shifted. If there is no hole to shift
 * the extents into, this will be considered invalid operation and we abort
 * immediately.
	 * If next_fsb lies in a hole beyond which there are no extents we are
	 * done.
	 */
	if (!xfs_iext_lookup_extent(ip, ifp, *next_fsb, &current_ext, &got)) {
		*done = true;
		goto del_cursor;
	}

	stop_extent = total_extents;
	if (current_ext >= stop_extent) {
		error = -EIO;
		goto del_cursor;
	}

	error = xfs_bmse_shift_one(ip, whichfork, offset_shift_fsb,
				   &current_ext, &got, cur, &logflags,
				   SHIFT_LEFT, dfops);
	if (error)
		goto del_cursor;
	/*
	 * If there was an extent merge during the shift, the extent
	 * count can change. Update the total and grade the next record.
	 */
	total_extents = xfs_iext_count(ifp);
	stop_extent = total_extents;
	if (current_ext == stop_extent) {
		*done = true;
		goto del_cursor;
	}
	xfs_iext_get_extent(ifp, current_ext, &got);

	if (!*done)
		*next_fsb = got.br_startoff;

del_cursor:
	if (cur)
		xfs_btree_del_cursor(cur,
			error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR);

	if (logflags)
		xfs_trans_log_inode(tp, ip, logflags);

	return error;
}

int
xfs_bmap_shift_extents(
xfs_bmap_insert_extents(
	struct xfs_trans	*tp,
	struct xfs_inode	*ip,
	xfs_fileoff_t		*next_fsb,
	xfs_fileoff_t		offset_shift_fsb,
	int			*done,
	bool			*done,
	xfs_fileoff_t		stop_fsb,
	xfs_fsblock_t		*firstblock,
	struct xfs_defer_ops	*dfops,
	enum shift_direction	direction)
	struct xfs_defer_ops	*dfops)
{
	struct xfs_btree_cur		*cur = NULL;
	struct xfs_bmbt_irec            got;
	int			whichfork = XFS_DATA_FORK;
	struct xfs_mount	*mp = ip->i_mount;
	struct xfs_ifork		*ifp;
	struct xfs_ifork	*ifp = XFS_IFORK_PTR(ip, whichfork);
	struct xfs_btree_cur	*cur = NULL;
	struct xfs_bmbt_irec	got, s;
	xfs_extnum_t		current_ext;
	xfs_extnum_t		total_extents;
	xfs_extnum_t		stop_extent;
	int			error = 0;
	int				whichfork = XFS_DATA_FORK;
	int			logflags = 0;

	if (unlikely(XFS_TEST_ERROR(
	    (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS &&
	     XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE),
	     mp, XFS_ERRTAG_BMAPIFORMAT))) {
		XFS_ERROR_REPORT("xfs_bmap_shift_extents",
				 XFS_ERRLEVEL_LOW, mp);
		XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, mp);
		return -EFSCORRUPTED;
	}

	if (XFS_FORCED_SHUTDOWN(mp))
		return -EIO;

	ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL));
	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
	ASSERT(direction == SHIFT_LEFT || direction == SHIFT_RIGHT);
	ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL));

	ifp = XFS_IFORK_PTR(ip, whichfork);
	if (!(ifp->if_flags & XFS_IFEXTENTS)) {
		/* Read in all the extents */
		error = xfs_iread_extents(tp, ip, whichfork);
		if (error)
			return error;
@@ -5770,7 +5864,7 @@ xfs_bmap_shift_extents(
	 */
	total_extents = xfs_iext_count(ifp);
	if (total_extents == 0) {
		*done = 1;
		*done = true;
		goto del_cursor;
	}

@@ -5778,12 +5872,10 @@ xfs_bmap_shift_extents(
	 * In case of first right shift, we need to initialize next_fsb
	 */
	if (*next_fsb == NULLFSBLOCK) {
		ASSERT(direction == SHIFT_RIGHT);

		current_ext = total_extents - 1;
		xfs_iext_get_extent(ifp, current_ext, &got);
		if (stop_fsb > got.br_startoff) {
			*done = 1;
			*done = true;
			goto del_cursor;
		}
		*next_fsb = got.br_startoff;
@@ -5798,15 +5890,12 @@ xfs_bmap_shift_extents(
		 */
		if (!xfs_iext_lookup_extent(ip, ifp, *next_fsb, &current_ext,
				&got)) {
			*done = 1;
			*done = true;
			goto del_cursor;
		}
	}

	/* Lookup the extent index at which we have to stop */
	if (direction == SHIFT_RIGHT) {
		struct xfs_bmbt_irec s;

	xfs_iext_lookup_extent(ip, ifp, stop_fsb, &stop_extent, &s);
	/* Make stop_extent exclusive of shift range */
	stop_extent--;
@@ -5814,30 +5903,14 @@ xfs_bmap_shift_extents(
		error = -EIO;
		goto del_cursor;
	}
	} else {
		stop_extent = total_extents;
		if (current_ext >= stop_extent) {
			error = -EIO;
			goto del_cursor;
		}
	}

	error = xfs_bmse_shift_one(ip, whichfork, offset_shift_fsb,
				   &current_ext, &got, cur, &logflags,
				   direction, dfops);
				   SHIFT_RIGHT, dfops);
	if (error)
		goto del_cursor;
	/*
	 * If there was an extent merge during the shift, the extent
	 * count can change. Update the total and grade the next record.
	 */
	if (direction == SHIFT_LEFT) {
		total_extents = xfs_iext_count(ifp);
		stop_extent = total_extents;
	}

	if (current_ext == stop_extent) {
		*done = 1;
		*done = true;
		goto del_cursor;
	}
	xfs_iext_get_extent(ifp, current_ext, &got);
+7 −3
Original line number Diff line number Diff line
@@ -228,10 +228,14 @@ int xfs_bmap_del_extent_delay(struct xfs_inode *ip, int whichfork,
void	xfs_bmap_del_extent_cow(struct xfs_inode *ip, xfs_extnum_t *idx,
		struct xfs_bmbt_irec *got, struct xfs_bmbt_irec *del);
uint	xfs_default_attroffset(struct xfs_inode *ip);
int	xfs_bmap_shift_extents(struct xfs_trans *tp, struct xfs_inode *ip,
int	xfs_bmap_collapse_extents(struct xfs_trans *tp, struct xfs_inode *ip,
		xfs_fileoff_t *next_fsb, xfs_fileoff_t offset_shift_fsb,
		int *done, xfs_fileoff_t stop_fsb, xfs_fsblock_t *firstblock,
		struct xfs_defer_ops *dfops, enum shift_direction direction);
		bool *done, xfs_fileoff_t stop_fsb, xfs_fsblock_t *firstblock,
		struct xfs_defer_ops *dfops);
int	xfs_bmap_insert_extents(struct xfs_trans *tp, struct xfs_inode *ip,
		xfs_fileoff_t *next_fsb, xfs_fileoff_t offset_shift_fsb,
		bool *done, xfs_fileoff_t stop_fsb, xfs_fsblock_t *firstblock,
		struct xfs_defer_ops *dfops);
int	xfs_bmap_split_extent(struct xfs_inode *ip, xfs_fileoff_t split_offset);
int	xfs_bmapi_reserve_delalloc(struct xfs_inode *ip, int whichfork,
		xfs_fileoff_t off, xfs_filblks_t len, xfs_filblks_t prealloc,
+6 −8
Original line number Diff line number Diff line
@@ -1322,7 +1322,6 @@ xfs_collapse_file_space(
	xfs_off_t		offset,
	xfs_off_t		len)
{
	int			done = 0;
	struct xfs_mount	*mp = ip->i_mount;
	struct xfs_trans	*tp;
	int			error;
@@ -1332,6 +1331,7 @@ xfs_collapse_file_space(
	xfs_fileoff_t		next_fsb = XFS_B_TO_FSB(mp, offset + len);
	xfs_fileoff_t		shift_fsb = XFS_B_TO_FSB(mp, len);
	uint			resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0);
	bool			done = false;

	ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL));
	trace_xfs_collapse_file_space(ip);
@@ -1359,9 +1359,8 @@ xfs_collapse_file_space(
		xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);

		xfs_defer_init(&dfops, &first_block);
		error = xfs_bmap_shift_extents(tp, ip, &next_fsb, shift_fsb,
				&done, stop_fsb, &first_block, &dfops,
				SHIFT_LEFT);
		error = xfs_bmap_collapse_extents(tp, ip, &next_fsb, shift_fsb,
				&done, stop_fsb, &first_block, &dfops);
		if (error)
			goto out_bmap_cancel;

@@ -1406,7 +1405,7 @@ xfs_insert_file_space(
	xfs_fileoff_t		stop_fsb = XFS_B_TO_FSB(mp, offset);
	xfs_fileoff_t		next_fsb = NULLFSBLOCK;
	xfs_fileoff_t		shift_fsb = XFS_B_TO_FSB(mp, len);
	int			done = 0;
	bool			done = false;

	ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL));
	trace_xfs_insert_file_space(ip);
@@ -1433,9 +1432,8 @@ xfs_insert_file_space(
		xfs_ilock(ip, XFS_ILOCK_EXCL);
		xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
		xfs_defer_init(&dfops, &first_block);
		error = xfs_bmap_shift_extents(tp, ip, &next_fsb, shift_fsb,
				&done, stop_fsb, &first_block, &dfops,
				SHIFT_RIGHT);
		error = xfs_bmap_insert_extents(tp, ip, &next_fsb, shift_fsb,
				&done, stop_fsb, &first_block, &dfops);
		if (error)
			goto out_bmap_cancel;