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

xfs: refactor the ioend merging code



Introduce two nicely abstracted helper, which can be moved to the iomap
code later.  Also use list_first_entry_or_null to simplify the code a
bit.

Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarDave Chinner <dchinner@redhat.com>
Reviewed-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
parent 4e087a3b
Loading
Loading
Loading
Loading
+42 −31
Original line number Diff line number Diff line
@@ -116,6 +116,22 @@ xfs_destroy_ioend(
	}
}

static void
xfs_destroy_ioends(
	struct xfs_ioend	*ioend,
	int			error)
{
	struct list_head	tmp;

	list_replace_init(&ioend->io_list, &tmp);
	xfs_destroy_ioend(ioend, error);
	while ((ioend = list_first_entry_or_null(&tmp, struct xfs_ioend,
			io_list))) {
		list_del_init(&ioend->io_list);
		xfs_destroy_ioend(ioend, error);
	}
}

/*
 * Fast and loose check if this write could update the on-disk inode size.
 */
@@ -230,7 +246,6 @@ STATIC void
xfs_end_ioend(
	struct xfs_ioend	*ioend)
{
	struct list_head	ioend_list;
	struct xfs_inode	*ip = XFS_I(ioend->io_inode);
	xfs_off_t		offset = ioend->io_offset;
	size_t			size = ioend->io_size;
@@ -275,16 +290,7 @@ xfs_end_ioend(
done:
	if (ioend->io_append_trans)
		error = xfs_setfilesize_ioend(ioend, error);
	list_replace_init(&ioend->io_list, &ioend_list);
	xfs_destroy_ioend(ioend, error);

	while (!list_empty(&ioend_list)) {
		ioend = list_first_entry(&ioend_list, struct xfs_ioend,
				io_list);
		list_del_init(&ioend->io_list);
		xfs_destroy_ioend(ioend, error);
	}

	xfs_destroy_ioends(ioend, error);
	memalloc_nofs_restore(nofs_flag);
}

@@ -333,17 +339,18 @@ xfs_ioend_try_merge(
	struct xfs_ioend	*ioend,
	struct list_head	*more_ioends)
{
	struct xfs_ioend	*next_ioend;
	struct xfs_ioend	*next;

	INIT_LIST_HEAD(&ioend->io_list);

	while (!list_empty(more_ioends)) {
		next_ioend = list_first_entry(more_ioends, struct xfs_ioend,
				io_list);
		if (!xfs_ioend_can_merge(ioend, next_ioend))
	while ((next = list_first_entry_or_null(more_ioends, struct xfs_ioend,
			io_list))) {
		if (!xfs_ioend_can_merge(ioend, next))
			break;
		list_move_tail(&next_ioend->io_list, &ioend->io_list);
		ioend->io_size += next_ioend->io_size;
		if (next_ioend->io_append_trans)
			xfs_ioend_merge_append_transactions(ioend, next_ioend);
		list_move_tail(&next->io_list, &ioend->io_list);
		ioend->io_size += next->io_size;
		if (next->io_append_trans)
			xfs_ioend_merge_append_transactions(ioend, next);
	}
}

@@ -366,29 +373,33 @@ xfs_ioend_compare(
	return 0;
}

static void
xfs_sort_ioends(
	struct list_head	*ioend_list)
{
	list_sort(NULL, ioend_list, xfs_ioend_compare);
}

/* Finish all pending io completions. */
void
xfs_end_io(
	struct work_struct	*work)
{
	struct xfs_inode	*ip;
	struct xfs_inode	*ip =
		container_of(work, struct xfs_inode, i_ioend_work);
	struct xfs_ioend	*ioend;
	struct list_head	completion_list;
	struct list_head	tmp;
	unsigned long		flags;

	ip = container_of(work, struct xfs_inode, i_ioend_work);

	spin_lock_irqsave(&ip->i_ioend_lock, flags);
	list_replace_init(&ip->i_ioend_list, &completion_list);
	list_replace_init(&ip->i_ioend_list, &tmp);
	spin_unlock_irqrestore(&ip->i_ioend_lock, flags);

	list_sort(NULL, &completion_list, xfs_ioend_compare);

	while (!list_empty(&completion_list)) {
		ioend = list_first_entry(&completion_list, struct xfs_ioend,
				io_list);
	xfs_sort_ioends(&tmp);
	while ((ioend = list_first_entry_or_null(&tmp, struct xfs_ioend,
			io_list))) {
		list_del_init(&ioend->io_list);
		xfs_ioend_try_merge(ioend, &completion_list);
		xfs_ioend_try_merge(ioend, &tmp);
		xfs_end_ioend(ioend);
	}
}