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

Signed-off-by: Christoph Hellwig <h...@lst.de>
---
 fs/xfs/xfs_aops.c | 66 ++++++++++++++++++++++++++---------------------
 1 file changed, 36 insertions(+), 30 deletions(-)

diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c
index acbd73976067..5d302ebe2a33 100644
--- a/fs/xfs/xfs_aops.c
+++ b/fs/xfs/xfs_aops.c
@@ -121,6 +121,19 @@ 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_pop(&tmp, struct xfs_ioend, io_list)))
+               xfs_destroy_ioend(ioend, error);
+}
+
 /*
  * Fast and loose check if this write could update the on-disk inode size.
  */
@@ -173,7 +186,6 @@ xfs_end_ioend(
        struct xfs_ioend        *ioend)
 {
        unsigned int            nofs_flag = memalloc_nofs_save();
-       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;
@@ -207,16 +219,7 @@ xfs_end_ioend(
        if (!error && xfs_ioend_is_append(ioend))
                error = xfs_setfilesize(ip, offset, size);
 done:
-       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);
 }
 
@@ -246,15 +249,16 @@ 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;
+               list_move_tail(&next->io_list, &ioend->io_list);
+               ioend->io_size += next->io_size;
        }
 }
 
@@ -277,29 +281,31 @@ 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);
-               list_del_init(&ioend->io_list);
-               xfs_ioend_try_merge(ioend, &completion_list);
+       xfs_sort_ioends(&tmp);
+       while ((ioend = list_pop(&tmp, struct xfs_ioend, io_list))) {
+               xfs_ioend_try_merge(ioend, &tmp);
                xfs_end_ioend(ioend);
        }
 }
-- 
2.20.1

Reply via email to