struct xlog_cil_pcp     *cilpcp;
        int                     cpu;
 
-       for_each_online_cpu(cpu) {
+       for_each_cpu(cpu, &ctx->cil_pcpmask) {
                cilpcp = per_cpu_ptr(cil->xc_pcp, cpu);
 
                ctx->ticket->t_curr_res += cilpcp->space_reserved;
        if (!test_and_clear_bit(XLOG_CIL_PCP_SPACE, &cil->xc_flags))
                return;
 
-       for_each_online_cpu(cpu) {
+       /*
+        * We can race with other cpus setting cil_pcpmask.  However, we've
+        * atomically cleared PCP_SPACE which forces other threads to add to
+        * the global space used count.  cil_pcpmask is a superset of cilpcp
+        * structures that could have a nonzero space_used.
+        */
+       for_each_cpu(cpu, &ctx->cil_pcpmask) {
                int     old, prev;
 
                cilpcp = per_cpu_ptr(cil->xc_pcp, cpu);
        int                     iovhdr_res = 0, split_res = 0, ctx_res = 0;
        int                     space_used;
        int                     order;
+       unsigned int            cpu_nr;
        struct xlog_cil_pcp     *cilpcp;
 
        ASSERT(tp);
         * can't be scheduled away between split sample/update operations that
         * are done without outside locking to serialise them.
         */
-       cilpcp = get_cpu_ptr(cil->xc_pcp);
+       cpu_nr = get_cpu();
+       cilpcp = this_cpu_ptr(cil->xc_pcp);
+
+       /* Tell the future push that there was work added by this CPU. */
+       if (!cpumask_test_cpu(cpu_nr, &ctx->cil_pcpmask))
+               cpumask_test_and_set_cpu(cpu_nr, &ctx->cil_pcpmask);
 
        /*
         * We need to take the CIL checkpoint unit reservation on the first
                        continue;
                list_add_tail(&lip->li_cil, &cilpcp->log_items);
        }
-       put_cpu_ptr(cilpcp);
+       put_cpu();
 
        /*
         * If we've overrun the reservation, dump the tx details before we move
        return 0;
 }
 
-/*
- * Move dead percpu state to the relevant CIL context structures.
- *
- * We have to lock the CIL context here to ensure that nothing is modifying
- * the percpu state, either addition or removal. Both of these are done under
- * the CIL context lock, so grabbing that exclusively here will ensure we can
- * safely drain the cilpcp for the CPU that is dying.
- */
-void
-xlog_cil_pcp_dead(
-       struct xlog             *log,
-       unsigned int            cpu)
-{
-       struct xfs_cil          *cil = log->l_cilp;
-       struct xlog_cil_pcp     *cilpcp = per_cpu_ptr(cil->xc_pcp, cpu);
-       struct xfs_cil_ctx      *ctx;
-
-       down_write(&cil->xc_ctx_lock);
-       ctx = cil->xc_ctx;
-       if (ctx->ticket)
-               ctx->ticket->t_curr_res += cilpcp->space_reserved;
-       cilpcp->space_reserved = 0;
-
-       if (!list_empty(&cilpcp->log_items))
-               list_splice_init(&cilpcp->log_items, &ctx->log_items);
-       if (!list_empty(&cilpcp->busy_extents))
-               list_splice_init(&cilpcp->busy_extents, &ctx->busy_extents);
-       atomic_add(cilpcp->space_used, &ctx->space_used);
-       cilpcp->space_used = 0;
-       up_write(&cil->xc_ctx_lock);
-}
-
 /*
  * Perform initial CIL structure initialisation.
  */
 
        struct work_struct      discard_endio_work;
        struct work_struct      push_work;
        atomic_t                order_id;
+
+       /*
+        * CPUs that could have added items to the percpu CIL data.  Access is
+        * coordinated with xc_ctx_lock.
+        */
+       struct cpumask          cil_pcpmask;
 };
 
 /*
        wait_queue_head_t       xc_push_wait;   /* background push throttle */
 
        void __percpu           *xc_pcp;        /* percpu CIL structures */
-#ifdef CONFIG_HOTPLUG_CPU
-       struct list_head        xc_pcp_list;
-#endif
 } ____cacheline_aligned_in_smp;
 
 /* xc_flags bit values */
        return p;
 }
 
-/*
- * CIL CPU dead notifier
- */
-void xlog_cil_pcp_dead(struct xlog *log, unsigned int cpu);
-
 #endif /* __XFS_LOG_PRIV_H__ */