blk-mq-cpu.c 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. #include <linux/kernel.h>
  2. #include <linux/module.h>
  3. #include <linux/init.h>
  4. #include <linux/blkdev.h>
  5. #include <linux/list.h>
  6. #include <linux/llist.h>
  7. #include <linux/smp.h>
  8. #include <linux/cpu.h>
  9. #include <linux/blk-mq.h>
  10. #include "blk-mq.h"
  11. static LIST_HEAD(blk_mq_cpu_notify_list);
  12. static DEFINE_SPINLOCK(blk_mq_cpu_notify_lock);
  13. static int blk_mq_main_cpu_notify(struct notifier_block *self,
  14. unsigned long action, void *hcpu)
  15. {
  16. unsigned int cpu = (unsigned long) hcpu;
  17. struct blk_mq_cpu_notifier *notify;
  18. spin_lock(&blk_mq_cpu_notify_lock);
  19. list_for_each_entry(notify, &blk_mq_cpu_notify_list, list)
  20. notify->notify(notify->data, action, cpu);
  21. spin_unlock(&blk_mq_cpu_notify_lock);
  22. return NOTIFY_OK;
  23. }
  24. static void blk_mq_cpu_notify(void *data, unsigned long action,
  25. unsigned int cpu)
  26. {
  27. if (action == CPU_DEAD || action == CPU_DEAD_FROZEN) {
  28. /*
  29. * If the CPU goes away, ensure that we run any pending
  30. * completions.
  31. */
  32. struct llist_node *node;
  33. struct request *rq;
  34. local_irq_disable();
  35. node = llist_del_all(&per_cpu(ipi_lists, cpu));
  36. while (node) {
  37. struct llist_node *next = node->next;
  38. rq = llist_entry(node, struct request, ll_list);
  39. __blk_mq_end_io(rq, rq->errors);
  40. node = next;
  41. }
  42. local_irq_enable();
  43. }
  44. }
  45. static struct notifier_block __cpuinitdata blk_mq_main_cpu_notifier = {
  46. .notifier_call = blk_mq_main_cpu_notify,
  47. };
  48. void blk_mq_register_cpu_notifier(struct blk_mq_cpu_notifier *notifier)
  49. {
  50. BUG_ON(!notifier->notify);
  51. spin_lock(&blk_mq_cpu_notify_lock);
  52. list_add_tail(&notifier->list, &blk_mq_cpu_notify_list);
  53. spin_unlock(&blk_mq_cpu_notify_lock);
  54. }
  55. void blk_mq_unregister_cpu_notifier(struct blk_mq_cpu_notifier *notifier)
  56. {
  57. spin_lock(&blk_mq_cpu_notify_lock);
  58. list_del(&notifier->list);
  59. spin_unlock(&blk_mq_cpu_notify_lock);
  60. }
  61. void blk_mq_init_cpu_notifier(struct blk_mq_cpu_notifier *notifier,
  62. void (*fn)(void *, unsigned long, unsigned int),
  63. void *data)
  64. {
  65. notifier->notify = fn;
  66. notifier->data = data;
  67. }
  68. static struct blk_mq_cpu_notifier __cpuinitdata cpu_notifier = {
  69. .notify = blk_mq_cpu_notify,
  70. };
  71. void __init blk_mq_cpu_init(void)
  72. {
  73. register_hotcpu_notifier(&blk_mq_main_cpu_notifier);
  74. blk_mq_register_cpu_notifier(&cpu_notifier);
  75. }