]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
xfs: use a list_head for iclog callbacks
authorChristoph Hellwig <hch@lst.de>
Sat, 29 Jun 2019 02:27:34 +0000 (19:27 -0700)
committerDarrick J. Wong <darrick.wong@oracle.com>
Sat, 29 Jun 2019 02:27:34 +0000 (19:27 -0700)
Replace the hand grown linked list handling and cil context attachment
with the standard list_head structure.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Brian Foster <bfoster@redhat.com>
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
fs/xfs/xfs_log.c
fs/xfs/xfs_log.h
fs/xfs/xfs_log_cil.c
fs/xfs/xfs_log_priv.h

index aa2bd0847dfa4c5f0be1d86168c341e6f4f01c49..0f849b4095d645681cb5dc03dc7d2e89fd879060 100644 (file)
@@ -533,32 +533,6 @@ xfs_log_done(
        return lsn;
 }
 
-/*
- * Attaches a new iclog I/O completion callback routine during
- * transaction commit.  If the log is in error state, a non-zero
- * return code is handed back and the caller is responsible for
- * executing the callback at an appropriate time.
- */
-int
-xfs_log_notify(
-       struct xlog_in_core     *iclog,
-       xfs_log_callback_t      *cb)
-{
-       int     abortflg;
-
-       spin_lock(&iclog->ic_callback_lock);
-       abortflg = (iclog->ic_state & XLOG_STATE_IOERROR);
-       if (!abortflg) {
-               ASSERT_ALWAYS((iclog->ic_state == XLOG_STATE_ACTIVE) ||
-                             (iclog->ic_state == XLOG_STATE_WANT_SYNC));
-               cb->cb_next = NULL;
-               *(iclog->ic_callback_tail) = cb;
-               iclog->ic_callback_tail = &(cb->cb_next);
-       }
-       spin_unlock(&iclog->ic_callback_lock);
-       return abortflg;
-}
-
 int
 xfs_log_release_iclog(
        struct xfs_mount        *mp,
@@ -1473,7 +1447,7 @@ xlog_alloc_log(
                iclog->ic_log = log;
                atomic_set(&iclog->ic_refcnt, 0);
                spin_lock_init(&iclog->ic_callback_lock);
-               iclog->ic_callback_tail = &(iclog->ic_callback);
+               INIT_LIST_HEAD(&iclog->ic_callbacks);
                iclog->ic_datap = (char *)iclog->ic_data + log->l_iclog_hsize;
 
                init_waitqueue_head(&iclog->ic_force_wait);
@@ -2552,7 +2526,7 @@ xlog_state_clean_log(
                if (iclog->ic_state == XLOG_STATE_DIRTY) {
                        iclog->ic_state = XLOG_STATE_ACTIVE;
                        iclog->ic_offset       = 0;
-                       ASSERT(iclog->ic_callback == NULL);
+                       ASSERT(list_empty_careful(&iclog->ic_callbacks));
                        /*
                         * If the number of ops in this iclog indicate it just
                         * contains the dummy transaction, we can
@@ -2648,7 +2622,6 @@ xlog_state_do_callback(
        xlog_in_core_t     *iclog;
        xlog_in_core_t     *first_iclog;        /* used to know when we've
                                                 * processed all iclogs once */
-       xfs_log_callback_t *cb, *cb_next;
        int                flushcnt = 0;
        xfs_lsn_t          lowest_lsn;
        int                ioerrors;    /* counter: iclogs with errors */
@@ -2759,7 +2732,7 @@ xlog_state_do_callback(
                                 */
                                ASSERT(XFS_LSN_CMP(atomic64_read(&log->l_last_sync_lsn),
                                        be64_to_cpu(iclog->ic_header.h_lsn)) <= 0);
-                               if (iclog->ic_callback)
+                               if (!list_empty_careful(&iclog->ic_callbacks))
                                        atomic64_set(&log->l_last_sync_lsn,
                                                be64_to_cpu(iclog->ic_header.h_lsn));
 
@@ -2776,26 +2749,20 @@ xlog_state_do_callback(
                         * callbacks being added.
                         */
                        spin_lock(&iclog->ic_callback_lock);
-                       cb = iclog->ic_callback;
-                       while (cb) {
-                               iclog->ic_callback_tail = &(iclog->ic_callback);
-                               iclog->ic_callback = NULL;
-                               spin_unlock(&iclog->ic_callback_lock);
+                       while (!list_empty(&iclog->ic_callbacks)) {
+                               LIST_HEAD(tmp);
 
-                               /* perform callbacks in the order given */
-                               for (; cb; cb = cb_next) {
-                                       cb_next = cb->cb_next;
-                                       cb->cb_func(cb->cb_arg, aborted);
-                               }
+                               list_splice_init(&iclog->ic_callbacks, &tmp);
+
+                               spin_unlock(&iclog->ic_callback_lock);
+                               xlog_cil_process_committed(&tmp, aborted);
                                spin_lock(&iclog->ic_callback_lock);
-                               cb = iclog->ic_callback;
                        }
 
                        loopdidcallbacks++;
                        funcdidcallbacks++;
 
                        spin_lock(&log->l_icloglock);
-                       ASSERT(iclog->ic_callback == NULL);
                        spin_unlock(&iclog->ic_callback_lock);
                        if (!(iclog->ic_state & XLOG_STATE_IOERROR))
                                iclog->ic_state = XLOG_STATE_DIRTY;
index 4450a2a26a1ad167064b23ee62fbbce25790805e..f27b1cb8f3c7cc0da5008da273fc5ae63a6aa0c4 100644 (file)
@@ -6,6 +6,8 @@
 #ifndef        __XFS_LOG_H__
 #define __XFS_LOG_H__
 
+struct xfs_cil_ctx;
+
 struct xfs_log_vec {
        struct xfs_log_vec      *lv_next;       /* next lv in build list */
        int                     lv_niovecs;     /* number of iovecs in lv */
@@ -71,16 +73,6 @@ xlog_copy_iovec(struct xfs_log_vec *lv, struct xfs_log_iovec **vecp,
        return buf;
 }
 
-/*
- * Structure used to pass callback function and the function's argument
- * to the log manager.
- */
-typedef struct xfs_log_callback {
-       struct xfs_log_callback *cb_next;
-       void                    (*cb_func)(void *, bool);
-       void                    *cb_arg;
-} xfs_log_callback_t;
-
 /*
  * By comparing each component, we don't have to worry about extra
  * endian issues in treating two 32 bit numbers as one 64 bit number
@@ -129,8 +121,6 @@ int xfs_log_mount_cancel(struct xfs_mount *);
 xfs_lsn_t xlog_assign_tail_lsn(struct xfs_mount *mp);
 xfs_lsn_t xlog_assign_tail_lsn_locked(struct xfs_mount *mp);
 void     xfs_log_space_wake(struct xfs_mount *mp);
-int      xfs_log_notify(struct xlog_in_core    *iclog,
-                        struct xfs_log_callback *callback_entry);
 int      xfs_log_release_iclog(struct xfs_mount *mp,
                         struct xlog_in_core     *iclog);
 int      xfs_log_reserve(struct xfs_mount *mp,
@@ -148,6 +138,7 @@ void          xfs_log_ticket_put(struct xlog_ticket *ticket);
 
 void   xfs_log_commit_cil(struct xfs_mount *mp, struct xfs_trans *tp,
                                xfs_lsn_t *commit_lsn, bool regrant);
+void   xlog_cil_process_committed(struct list_head *list, bool aborted);
 bool   xfs_log_item_in_current_chkpt(struct xfs_log_item *lip);
 
 void   xfs_log_work_queue(struct xfs_mount *mp);
index 4cb459f21ad41f49b3489c5cc43d75c632c011e3..f1855d8ab1f1dd793edc9adc0741b4730109bd50 100644 (file)
@@ -577,10 +577,9 @@ xlog_discard_busy_extents(
  */
 static void
 xlog_cil_committed(
-       void    *args,
-       bool    abort)
+       struct xfs_cil_ctx      *ctx,
+       bool                    abort)
 {
-       struct xfs_cil_ctx      *ctx = args;
        struct xfs_mount        *mp = ctx->cil->xc_log->l_mp;
 
        /*
@@ -615,6 +614,20 @@ xlog_cil_committed(
                kmem_free(ctx);
 }
 
+void
+xlog_cil_process_committed(
+       struct list_head        *list,
+       bool                    aborted)
+{
+       struct xfs_cil_ctx      *ctx;
+
+       while ((ctx = list_first_entry_or_null(list,
+                       struct xfs_cil_ctx, iclog_entry))) {
+               list_del(&ctx->iclog_entry);
+               xlog_cil_committed(ctx, aborted);
+       }
+}
+
 /*
  * Push the Committed Item List to the log. If @push_seq flag is zero, then it
  * is a background flush and so we can chose to ignore it. Otherwise, if the
@@ -836,12 +849,15 @@ xlog_cil_push(
        if (commit_lsn == -1)
                goto out_abort;
 
-       /* attach all the transactions w/ busy extents to iclog */
-       ctx->log_cb.cb_func = xlog_cil_committed;
-       ctx->log_cb.cb_arg = ctx;
-       error = xfs_log_notify(commit_iclog, &ctx->log_cb);
-       if (error)
+       spin_lock(&commit_iclog->ic_callback_lock);
+       if (commit_iclog->ic_state & XLOG_STATE_IOERROR) {
+               spin_unlock(&commit_iclog->ic_callback_lock);
                goto out_abort;
+       }
+       ASSERT_ALWAYS(commit_iclog->ic_state == XLOG_STATE_ACTIVE ||
+                     commit_iclog->ic_state == XLOG_STATE_WANT_SYNC);
+       list_add_tail(&ctx->iclog_entry, &commit_iclog->ic_callbacks);
+       spin_unlock(&commit_iclog->ic_callback_lock);
 
        /*
         * now the checkpoint commit is complete and we've attached the
index a20f5e919a2672cebac65ebc8c2da1dee1dae258..8acacbc514aa83916398587655198fb89c0df9a6 100644 (file)
@@ -10,7 +10,6 @@ struct xfs_buf;
 struct xlog;
 struct xlog_ticket;
 struct xfs_mount;
-struct xfs_log_callback;
 
 /*
  * Flags for log structure
@@ -179,8 +178,6 @@ typedef struct xlog_ticket {
  * - ic_forcewait is used to implement synchronous forcing of the iclog to disk.
  * - ic_next is the pointer to the next iclog in the ring.
  * - ic_log is a pointer back to the global log structure.
- * - ic_callback is a linked list of callback function/argument pairs to be
- *     called after an iclog finishes writing.
  * - ic_size is the full size of the log buffer, minus the cycle headers.
  * - ic_io_size is the size of the currently pending log buffer write, which
  *     might be smaller than ic_size
@@ -193,7 +190,7 @@ typedef struct xlog_ticket {
  * structure cacheline aligned. The following fields can be contended on
  * by independent processes:
  *
- *     - ic_callback_*
+ *     - ic_callbacks
  *     - ic_refcnt
  *     - fields protected by the global l_icloglock
  *
@@ -215,8 +212,7 @@ typedef struct xlog_in_core {
 
        /* Callback structures need their own cacheline */
        spinlock_t              ic_callback_lock ____cacheline_aligned_in_smp;
-       struct xfs_log_callback *ic_callback;
-       struct xfs_log_callback **ic_callback_tail;
+       struct list_head        ic_callbacks;
 
        /* reference counts need their own cacheline */
        atomic_t                ic_refcnt ____cacheline_aligned_in_smp;
@@ -249,7 +245,7 @@ struct xfs_cil_ctx {
        int                     space_used;     /* aggregate size of regions */
        struct list_head        busy_extents;   /* busy extents in chkpt */
        struct xfs_log_vec      *lv_chain;      /* logvecs being pushed */
-       struct xfs_log_callback log_cb;         /* completion callback hook. */
+       struct list_head        iclog_entry;
        struct list_head        committing;     /* ctx committing list */
        struct work_struct      discard_endio_work;
 };