Skip to content

Commit

Permalink
xfs: refactor the ioend merging code
Browse files Browse the repository at this point in the history
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: Christoph Hellwig <hch@lst.de>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
  • Loading branch information
Christoph Hellwig authored and Darrick J. Wong committed Oct 21, 2019
1 parent 4e087a3 commit 433dad9
Showing 1 changed file with 42 additions and 31 deletions.
73 changes: 42 additions & 31 deletions fs/xfs/xfs_aops.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}

Expand Down Expand Up @@ -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);
}
}

Expand All @@ -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);
}
}
Expand Down

0 comments on commit 433dad9

Please sign in to comment.