On Thu, Oct 17, 2019 at 07:56:15PM +0200, Christoph Hellwig wrote: > 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@xxxxxx> > Reviewed-by: Dave Chinner <dchinner@xxxxxxxxxx> Looks ok, Reviewed-by: Darrick J. Wong <darrick.wong@xxxxxxxxxx> --D > --- > fs/xfs/xfs_aops.c | 73 +++++++++++++++++++++++++++-------------------- > 1 file changed, 42 insertions(+), 31 deletions(-) > > diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c > index 91899de2be09..c29ef69d1e51 100644 > --- a/fs/xfs/xfs_aops.c > +++ b/fs/xfs/xfs_aops.c > @@ -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); > } > } > -- > 2.20.1 >