Use list_head infra-structure for buffer's log items list
authorCarlos Maiolino <cmaiolino@redhat.com>
Wed, 24 Jan 2018 21:38:49 +0000 (13:38 -0800)
committerDarrick J. Wong <darrick.wong@oracle.com>
Mon, 29 Jan 2018 15:27:22 +0000 (07:27 -0800)
Now that buffer's b_fspriv has been split, just replace the current
singly linked list of xfs_log_items, by the list_head infrastructure.

Also, remove the xfs_log_item argument from xfs_buf_resubmit_failed_buffers(),
there is no need for this argument, once the log items can be walked
through the list_head in the buffer.

Signed-off-by: Carlos Maiolino <cmaiolino@redhat.com>
Reviewed-by: Bill O'Donnell <billodo@redhat.com>
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
[darrick: minor style cleanups]
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
fs/xfs/xfs_buf.c
fs/xfs/xfs_buf.h
fs/xfs/xfs_buf_item.c
fs/xfs/xfs_buf_item.h
fs/xfs/xfs_dquot_item.c
fs/xfs/xfs_inode.c
fs/xfs/xfs_inode_item.c
fs/xfs/xfs_log.c
fs/xfs/xfs_trans.h

index 0820c1c..d1da2ee 100644 (file)
@@ -236,6 +236,7 @@ _xfs_buf_alloc(
        init_completion(&bp->b_iowait);
        INIT_LIST_HEAD(&bp->b_lru);
        INIT_LIST_HEAD(&bp->b_list);
+       INIT_LIST_HEAD(&bp->b_li_list);
        sema_init(&bp->b_sema, 0); /* held, no waiters */
        spin_lock_init(&bp->b_lock);
        XB_SET_OWNER(bp);
index 6fcba75..2f4c914 100644 (file)
@@ -177,7 +177,7 @@ typedef struct xfs_buf {
        xfs_buf_iodone_t        b_iodone;       /* I/O completion function */
        struct completion       b_iowait;       /* queue for I/O waiters */
        void                    *b_log_item;
-       struct xfs_log_item     *b_li_list;
+       struct list_head        b_li_list;      /* Log items list head */
        struct xfs_trans        *b_transp;
        struct page             **b_pages;      /* array of page pointers */
        struct page             *b_page_array[XB_PAGES]; /* inline pages */
index 8354fab..270ddb4 100644 (file)
@@ -457,7 +457,7 @@ xfs_buf_item_unpin(
                if (bip->bli_flags & XFS_BLI_STALE_INODE) {
                        xfs_buf_do_callbacks(bp);
                        bp->b_log_item = NULL;
-                       bp->b_li_list = NULL;
+                       list_del_init(&bp->b_li_list);
                        bp->b_iodone = NULL;
                } else {
                        spin_lock(&ailp->xa_lock);
@@ -955,13 +955,12 @@ xfs_buf_item_relse(
        xfs_buf_t       *bp)
 {
        struct xfs_buf_log_item *bip = bp->b_log_item;
-       struct xfs_log_item     *lip = bp->b_li_list;
 
        trace_xfs_buf_item_relse(bp, _RET_IP_);
        ASSERT(!(bip->bli_item.li_flags & XFS_LI_IN_AIL));
 
        bp->b_log_item = NULL;
-       if (lip == NULL)
+       if (list_empty(&bp->b_li_list))
                bp->b_iodone = NULL;
 
        xfs_buf_rele(bp);
@@ -982,18 +981,10 @@ xfs_buf_attach_iodone(
        void            (*cb)(xfs_buf_t *, xfs_log_item_t *),
        xfs_log_item_t  *lip)
 {
-       xfs_log_item_t  *head_lip;
-
        ASSERT(xfs_buf_islocked(bp));
 
        lip->li_cb = cb;
-       head_lip = bp->b_li_list;
-       if (head_lip) {
-               lip->li_bio_list = head_lip->li_bio_list;
-               head_lip->li_bio_list = lip;
-       } else {
-               bp->b_li_list = lip;
-       }
+       list_add_tail(&lip->li_bio_list, &bp->b_li_list);
 
        ASSERT(bp->b_iodone == NULL ||
               bp->b_iodone == xfs_buf_iodone_callbacks);
@@ -1003,12 +994,12 @@ xfs_buf_attach_iodone(
 /*
  * We can have many callbacks on a buffer. Running the callbacks individually
  * can cause a lot of contention on the AIL lock, so we allow for a single
- * callback to be able to scan the remaining lip->li_bio_list for other items
- * of the same type and callback to be processed in the first call.
+ * callback to be able to scan the remaining items in bp->b_li_list for other
+ * items of the same type and callback to be processed in the first call.
  *
  * As a result, the loop walking the callback list below will also modify the
  * list. it removes the first item from the list and then runs the callback.
- * The loop then restarts from the new head of the list. This allows the
+ * The loop then restarts from the new first item int the list. This allows the
  * callback to scan and modify the list attached to the buffer and we don't
  * have to care about maintaining a next item pointer.
  */
@@ -1025,16 +1016,17 @@ xfs_buf_do_callbacks(
                lip->li_cb(bp, lip);
        }
 
-       while ((lip = bp->b_li_list) != NULL) {
-               bp->b_li_list = lip->li_bio_list;
-               ASSERT(lip->li_cb != NULL);
+       while (!list_empty(&bp->b_li_list)) {
+               lip = list_first_entry(&bp->b_li_list, struct xfs_log_item,
+                                      li_bio_list);
+
                /*
-                * Clear the next pointer so we don't have any
+                * Remove the item from the list, so we don't have any
                 * confusion if the item is added to another buf.
                 * Don't touch the log item after calling its
                 * callback, because it could have freed itself.
                 */
-               lip->li_bio_list = NULL;
+               list_del_init(&lip->li_bio_list);
                lip->li_cb(bp, lip);
        }
 }
@@ -1051,8 +1043,7 @@ STATIC void
 xfs_buf_do_callbacks_fail(
        struct xfs_buf          *bp)
 {
-       struct xfs_log_item     *lip = bp->b_li_list;
-       struct xfs_log_item     *next;
+       struct xfs_log_item     *lip;
        struct xfs_ail          *ailp;
 
        /*
@@ -1060,13 +1051,14 @@ xfs_buf_do_callbacks_fail(
         * and xfs_buf_iodone_callback_error, and they have no IO error
         * callbacks. Check only for items in b_li_list.
         */
-       if (lip == NULL)
+       if (list_empty(&bp->b_li_list))
                return;
 
+       lip = list_first_entry(&bp->b_li_list, struct xfs_log_item,
+                       li_bio_list);
        ailp = lip->li_ailp;
        spin_lock(&ailp->xa_lock);
-       for (; lip; lip = next) {
-               next = lip->li_bio_list;
+       list_for_each_entry(lip, &bp->b_li_list, li_bio_list) {
                if (lip->li_ops->iop_error)
                        lip->li_ops->iop_error(lip, bp);
        }
@@ -1078,7 +1070,7 @@ xfs_buf_iodone_callback_error(
        struct xfs_buf          *bp)
 {
        struct xfs_buf_log_item *bip = bp->b_log_item;
-       struct xfs_log_item     *lip = bp->b_li_list;
+       struct xfs_log_item     *lip;
        struct xfs_mount        *mp;
        static ulong            lasttime;
        static xfs_buftarg_t    *lasttarg;
@@ -1089,7 +1081,9 @@ xfs_buf_iodone_callback_error(
         * log_item list might be empty. Get the mp from the available
         * xfs_log_item
         */
-       mp = bip ? bip->bli_item.li_mountp : lip->li_mountp;
+       lip = list_first_entry_or_null(&bp->b_li_list, struct xfs_log_item,
+                                      li_bio_list);
+       mp = lip ? lip->li_mountp : bip->bli_item.li_mountp;
 
        /*
         * If we've already decided to shutdown the filesystem because of
@@ -1200,7 +1194,7 @@ xfs_buf_iodone_callbacks(
 
        xfs_buf_do_callbacks(bp);
        bp->b_log_item = NULL;
-       bp->b_li_list = NULL;
+       list_del_init(&bp->b_li_list);
        bp->b_iodone = NULL;
        xfs_buf_ioend(bp);
 }
@@ -1245,10 +1239,9 @@ xfs_buf_iodone(
 bool
 xfs_buf_resubmit_failed_buffers(
        struct xfs_buf          *bp,
-       struct xfs_log_item     *lip,
        struct list_head        *buffer_list)
 {
-       struct xfs_log_item     *next;
+       struct xfs_log_item     *lip;
 
        /*
         * Clear XFS_LI_FAILED flag from all items before resubmit
@@ -1256,10 +1249,8 @@ xfs_buf_resubmit_failed_buffers(
         * XFS_LI_FAILED set/clear is protected by xa_lock, caller  this
         * function already have it acquired
         */
-       for (; lip; lip = next) {
-               next = lip->li_bio_list;
+       list_for_each_entry(lip, &bp->b_li_list, li_bio_list)
                xfs_clear_li_failed(lip);
-       }
 
        /* Add this buffer back to the delayed write list */
        return xfs_buf_delwri_queue(bp, buffer_list);
index 0febfbb..643f53d 100644 (file)
@@ -71,7 +71,6 @@ void  xfs_buf_attach_iodone(struct xfs_buf *,
 void   xfs_buf_iodone_callbacks(struct xfs_buf *);
 void   xfs_buf_iodone(struct xfs_buf *, struct xfs_log_item *);
 bool   xfs_buf_resubmit_failed_buffers(struct xfs_buf *,
-                                       struct xfs_log_item *,
                                        struct list_head *);
 
 extern kmem_zone_t     *xfs_buf_item_zone;
index 51ee848..96eaa69 100644 (file)
@@ -176,7 +176,7 @@ xfs_qm_dquot_logitem_push(
                if (!xfs_buf_trylock(bp))
                        return XFS_ITEM_LOCKED;
 
-               if (!xfs_buf_resubmit_failed_buffers(bp, lip, buffer_list))
+               if (!xfs_buf_resubmit_failed_buffers(bp, buffer_list))
                        rval = XFS_ITEM_FLUSHING;
 
                xfs_buf_unlock(bp);
index 8a3ff63..c66effc 100644 (file)
@@ -2214,7 +2214,7 @@ xfs_ifree_cluster(
        xfs_buf_t               *bp;
        xfs_inode_t             *ip;
        xfs_inode_log_item_t    *iip;
-       xfs_log_item_t          *lip;
+       struct xfs_log_item     *lip;
        struct xfs_perag        *pag;
        xfs_ino_t               inum;
 
@@ -2272,8 +2272,7 @@ xfs_ifree_cluster(
                 * stale first, we will not attempt to lock them in the loop
                 * below as the XFS_ISTALE flag will be set.
                 */
-               lip = bp->b_li_list;
-               while (lip) {
+               list_for_each_entry(lip, &bp->b_li_list, li_bio_list) {
                        if (lip->li_type == XFS_LI_INODE) {
                                iip = (xfs_inode_log_item_t *)lip;
                                ASSERT(iip->ili_logged == 1);
@@ -2283,7 +2282,6 @@ xfs_ifree_cluster(
                                                        &iip->ili_item.li_lsn);
                                xfs_iflags_set(iip->ili_inode, XFS_ISTALE);
                        }
-                       lip = lip->li_bio_list;
                }
 
 
@@ -3649,7 +3647,7 @@ xfs_iflush_int(
        /* generate the checksum. */
        xfs_dinode_calc_crc(mp, dip);
 
-       ASSERT(bp->b_li_list != NULL);
+       ASSERT(!list_empty(&bp->b_li_list));
        ASSERT(bp->b_iodone != NULL);
        return 0;
 
index 9937360..ddfc2c8 100644 (file)
@@ -521,7 +521,7 @@ xfs_inode_item_push(
                if (!xfs_buf_trylock(bp))
                        return XFS_ITEM_LOCKED;
 
-               if (!xfs_buf_resubmit_failed_buffers(bp, lip, buffer_list))
+               if (!xfs_buf_resubmit_failed_buffers(bp, buffer_list))
                        rval = XFS_ITEM_FLUSHING;
 
                xfs_buf_unlock(bp);
@@ -712,37 +712,23 @@ xfs_iflush_done(
        struct xfs_log_item     *lip)
 {
        struct xfs_inode_log_item *iip;
-       struct xfs_log_item     *blip;
-       struct xfs_log_item     *next;
-       struct xfs_log_item     *prev;
+       struct xfs_log_item     *blip, *n;
        struct xfs_ail          *ailp = lip->li_ailp;
        int                     need_ail = 0;
+       LIST_HEAD(tmp);
 
        /*
         * Scan the buffer IO completions for other inodes being completed and
         * attach them to the current inode log item.
         */
-       blip = bp->b_li_list;
-       prev = NULL;
-       while (blip != NULL) {
-               if (blip->li_cb != xfs_iflush_done) {
-                       prev = blip;
-                       blip = blip->li_bio_list;
-                       continue;
-               }
 
-               /* remove from list */
-               next = blip->li_bio_list;
-               if (!prev) {
-                       bp->b_li_list = next;
-               } else {
-                       prev->li_bio_list = next;
-               }
+       list_add_tail(&lip->li_bio_list, &tmp);
 
-               /* add to current list */
-               blip->li_bio_list = lip->li_bio_list;
-               lip->li_bio_list = blip;
+       list_for_each_entry_safe(blip, n, &bp->b_li_list, li_bio_list) {
+               if (lip->li_cb != xfs_iflush_done)
+                       continue;
 
+               list_move_tail(&blip->li_bio_list, &tmp);
                /*
                 * while we have the item, do the unlocked check for needing
                 * the AIL lock.
@@ -751,8 +737,6 @@ xfs_iflush_done(
                if ((iip->ili_logged && blip->li_lsn == iip->ili_flush_lsn) ||
                    (blip->li_flags & XFS_LI_FAILED))
                        need_ail++;
-
-               blip = next;
        }
 
        /* make sure we capture the state of the initial inode. */
@@ -775,7 +759,7 @@ xfs_iflush_done(
 
                /* this is an opencoded batch version of xfs_trans_ail_delete */
                spin_lock(&ailp->xa_lock);
-               for (blip = lip; blip; blip = blip->li_bio_list) {
+               list_for_each_entry(blip, &tmp, li_bio_list) {
                        if (INODE_ITEM(blip)->ili_logged &&
                            blip->li_lsn == INODE_ITEM(blip)->ili_flush_lsn)
                                mlip_changed |= xfs_ail_delete_one(ailp, blip);
@@ -801,15 +785,14 @@ xfs_iflush_done(
         * ili_last_fields bits now that we know that the data corresponding to
         * them is safely on disk.
         */
-       for (blip = lip; blip; blip = next) {
-               next = blip->li_bio_list;
-               blip->li_bio_list = NULL;
-
+       list_for_each_entry_safe(blip, n, &tmp, li_bio_list) {
+               list_del_init(&blip->li_bio_list);
                iip = INODE_ITEM(blip);
                iip->ili_logged = 0;
                iip->ili_last_fields = 0;
                xfs_ifunlock(iip->ili_inode);
        }
+       list_del(&tmp);
 }
 
 /*
index 20483b6..3e5ba1e 100644 (file)
@@ -1047,6 +1047,7 @@ xfs_log_item_init(
 
        INIT_LIST_HEAD(&item->li_ail);
        INIT_LIST_HEAD(&item->li_cil);
+       INIT_LIST_HEAD(&item->li_bio_list);
 }
 
 /*
index 815b53d..9d542df 100644 (file)
@@ -50,7 +50,7 @@ typedef struct xfs_log_item {
        uint                            li_type;        /* item type */
        uint                            li_flags;       /* misc flags */
        struct xfs_buf                  *li_buf;        /* real buffer pointer */
-       struct xfs_log_item             *li_bio_list;   /* buffer item list */
+       struct list_head                li_bio_list;    /* buffer item list */
        void                            (*li_cb)(struct xfs_buf *,
                                                 struct xfs_log_item *);
                                                        /* buffer item iodone */