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

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
...@@ -116,6 +116,22 @@ xfs_destroy_ioend( ...@@ -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. * Fast and loose check if this write could update the on-disk inode size.
*/ */
...@@ -230,7 +246,6 @@ STATIC void ...@@ -230,7 +246,6 @@ STATIC void
xfs_end_ioend( xfs_end_ioend(
struct xfs_ioend *ioend) struct xfs_ioend *ioend)
{ {
struct list_head ioend_list;
struct xfs_inode *ip = XFS_I(ioend->io_inode); struct xfs_inode *ip = XFS_I(ioend->io_inode);
xfs_off_t offset = ioend->io_offset; xfs_off_t offset = ioend->io_offset;
size_t size = ioend->io_size; size_t size = ioend->io_size;
...@@ -275,16 +290,7 @@ xfs_end_ioend( ...@@ -275,16 +290,7 @@ xfs_end_ioend(
done: done:
if (ioend->io_append_trans) if (ioend->io_append_trans)
error = xfs_setfilesize_ioend(ioend, error); error = xfs_setfilesize_ioend(ioend, error);
list_replace_init(&ioend->io_list, &ioend_list); xfs_destroy_ioends(ioend, error);
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);
}
memalloc_nofs_restore(nofs_flag); memalloc_nofs_restore(nofs_flag);
} }
...@@ -333,17 +339,18 @@ xfs_ioend_try_merge( ...@@ -333,17 +339,18 @@ xfs_ioend_try_merge(
struct xfs_ioend *ioend, struct xfs_ioend *ioend,
struct list_head *more_ioends) 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)) { while ((next = list_first_entry_or_null(more_ioends, struct xfs_ioend,
next_ioend = list_first_entry(more_ioends, struct xfs_ioend, io_list))) {
io_list); if (!xfs_ioend_can_merge(ioend, next))
if (!xfs_ioend_can_merge(ioend, next_ioend))
break; break;
list_move_tail(&next_ioend->io_list, &ioend->io_list); list_move_tail(&next->io_list, &ioend->io_list);
ioend->io_size += next_ioend->io_size; ioend->io_size += next->io_size;
if (next_ioend->io_append_trans) if (next->io_append_trans)
xfs_ioend_merge_append_transactions(ioend, next_ioend); xfs_ioend_merge_append_transactions(ioend, next);
} }
} }
...@@ -366,29 +373,33 @@ xfs_ioend_compare( ...@@ -366,29 +373,33 @@ xfs_ioend_compare(
return 0; 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. */ /* Finish all pending io completions. */
void void
xfs_end_io( xfs_end_io(
struct work_struct *work) 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 xfs_ioend *ioend;
struct list_head completion_list; struct list_head tmp;
unsigned long flags; unsigned long flags;
ip = container_of(work, struct xfs_inode, i_ioend_work);
spin_lock_irqsave(&ip->i_ioend_lock, flags); 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); spin_unlock_irqrestore(&ip->i_ioend_lock, flags);
list_sort(NULL, &completion_list, xfs_ioend_compare); xfs_sort_ioends(&tmp);
while ((ioend = list_first_entry_or_null(&tmp, struct xfs_ioend,
while (!list_empty(&completion_list)) { io_list))) {
ioend = list_first_entry(&completion_list, struct xfs_ioend,
io_list);
list_del_init(&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); xfs_end_ioend(ioend);
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment