mirror of
https://github.com/torvalds/linux.git
synced 2024-11-22 20:22:09 +00:00
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: 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>
This commit is contained in:
parent
4e087a3b31
commit
433dad94ec
@ -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;
|
||||
|
||||
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))
|
||||
INIT_LIST_HEAD(&ioend->io_list);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user