@@ -1537,6 +1537,26 @@ xfs_log_item_in_current_chkpt(
return lip->li_seq == cil->xc_ctx->sequence;
}
+/*
+ * 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;
+
+ down_write(&cil->xc_ctx_lock);
+ /* move stuff on dead CPU to context */
+ up_write(&cil->xc_ctx_lock);
+}
+
/*
* Perform initial CIL structure initialisation.
*/
@@ -1560,6 +1580,11 @@ xlog_cil_init(
if (!cil->xc_push_wq)
goto out_destroy_cil;
+ cil->xc_log = log;
+ cil->xc_pcp = alloc_percpu(struct xlog_cil_pcp);
+ if (!cil->xc_pcp)
+ goto out_destroy_wq;
+
INIT_LIST_HEAD(&cil->xc_cil);
INIT_LIST_HEAD(&cil->xc_committing);
spin_lock_init(&cil->xc_cil_lock);
@@ -1568,14 +1593,14 @@ xlog_cil_init(
init_rwsem(&cil->xc_ctx_lock);
init_waitqueue_head(&cil->xc_start_wait);
init_waitqueue_head(&cil->xc_commit_wait);
- cil->xc_log = log;
log->l_cilp = cil;
ctx = xlog_cil_ctx_alloc();
xlog_cil_ctx_switch(cil, ctx);
-
return 0;
+out_destroy_wq:
+ destroy_workqueue(cil->xc_push_wq);
out_destroy_cil:
kmem_free(cil);
return -ENOMEM;
@@ -1595,6 +1620,7 @@ xlog_cil_destroy(
ASSERT(list_empty(&cil->xc_cil));
ASSERT(test_bit(XLOG_CIL_EMPTY, &cil->xc_flags));
+ free_percpu(cil->xc_pcp);
destroy_workqueue(cil->xc_push_wq);
kmem_free(cil);
}
@@ -231,6 +231,14 @@ struct xfs_cil_ctx {
struct work_struct push_work;
};
+/*
+ * Per-cpu CIL tracking items
+ */
+struct xlog_cil_pcp {
+ struct list_head busy_extents;
+ struct list_head log_items;
+};
+
/*
* Committed Item List structure
*
@@ -266,6 +274,11 @@ struct xfs_cil {
wait_queue_head_t xc_start_wait;
xfs_csn_t xc_current_sequence;
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 */
@@ -647,4 +660,9 @@ xlog_valid_lsn(
return valid;
}
+/*
+ * CIL CPU dead notifier
+ */
+void xlog_cil_pcp_dead(struct xlog *log, unsigned int cpu);
+
#endif /* __XFS_LOG_PRIV_H__ */
@@ -2185,6 +2185,7 @@ xfs_cpu_dead(
list_for_each_entry_safe(mp, n, &xfs_mount_list, m_mount_list) {
spin_unlock(&xfs_mount_list_lock);
xfs_inodegc_cpu_dead(mp, cpu);
+ xlog_cil_pcp_dead(mp->m_log, cpu);
spin_lock(&xfs_mount_list_lock);
}
spin_unlock(&xfs_mount_list_lock);