blk-softirq.c 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. /*
  2. * Functions related to softirq rq completions
  3. */
  4. #include <linux/kernel.h>
  5. #include <linux/module.h>
  6. #include <linux/init.h>
  7. #include <linux/bio.h>
  8. #include <linux/blkdev.h>
  9. #include <linux/interrupt.h>
  10. #include <linux/cpu.h>
  11. #include "blk.h"
  12. static DEFINE_PER_CPU(struct list_head, blk_cpu_done);
  13. static int __cpuinit blk_cpu_notify(struct notifier_block *self,
  14. unsigned long action, void *hcpu)
  15. {
  16. /*
  17. * If a CPU goes away, splice its entries to the current CPU
  18. * and trigger a run of the softirq
  19. */
  20. if (action == CPU_DEAD || action == CPU_DEAD_FROZEN) {
  21. int cpu = (unsigned long) hcpu;
  22. local_irq_disable();
  23. list_splice_init(&per_cpu(blk_cpu_done, cpu),
  24. &__get_cpu_var(blk_cpu_done));
  25. raise_softirq_irqoff(BLOCK_SOFTIRQ);
  26. local_irq_enable();
  27. }
  28. return NOTIFY_OK;
  29. }
  30. static struct notifier_block blk_cpu_notifier __cpuinitdata = {
  31. .notifier_call = blk_cpu_notify,
  32. };
  33. /*
  34. * splice the completion data to a local structure and hand off to
  35. * process_completion_queue() to complete the requests
  36. */
  37. static void blk_done_softirq(struct softirq_action *h)
  38. {
  39. struct list_head *cpu_list, local_list;
  40. local_irq_disable();
  41. cpu_list = &__get_cpu_var(blk_cpu_done);
  42. list_replace_init(cpu_list, &local_list);
  43. local_irq_enable();
  44. while (!list_empty(&local_list)) {
  45. struct request *rq;
  46. rq = list_entry(local_list.next, struct request, donelist);
  47. list_del_init(&rq->donelist);
  48. rq->q->softirq_done_fn(rq);
  49. }
  50. }
  51. /**
  52. * blk_complete_request - end I/O on a request
  53. * @req: the request being processed
  54. *
  55. * Description:
  56. * Ends all I/O on a request. It does not handle partial completions,
  57. * unless the driver actually implements this in its completion callback
  58. * through requeueing. The actual completion happens out-of-order,
  59. * through a softirq handler. The user must have registered a completion
  60. * callback through blk_queue_softirq_done().
  61. **/
  62. void blk_complete_request(struct request *req)
  63. {
  64. struct list_head *cpu_list;
  65. unsigned long flags;
  66. BUG_ON(!req->q->softirq_done_fn);
  67. local_irq_save(flags);
  68. cpu_list = &__get_cpu_var(blk_cpu_done);
  69. list_add_tail(&req->donelist, cpu_list);
  70. raise_softirq_irqoff(BLOCK_SOFTIRQ);
  71. local_irq_restore(flags);
  72. }
  73. EXPORT_SYMBOL(blk_complete_request);
  74. int __init blk_softirq_init(void)
  75. {
  76. int i;
  77. for_each_possible_cpu(i)
  78. INIT_LIST_HEAD(&per_cpu(blk_cpu_done, i));
  79. open_softirq(BLOCK_SOFTIRQ, blk_done_softirq);
  80. register_hotcpu_notifier(&blk_cpu_notifier);
  81. return 0;
  82. }
  83. subsys_initcall(blk_softirq_init);