)]}'
{
  "commit": "d519c8d9ccb7956e61a55ce3a0fd6a25f42cbb33",
  "tree": "affe708b15bf3c73cb7487d6c6d7d6dace565002",
  "parents": [
    "20ca9b3f4c6dfa0af8dd5b18a64df17eb994b54d"
  ],
  "author": {
    "name": "Harry Ciao",
    "email": "qingtao.cao@windriver.com",
    "time": "Tue Dec 23 13:57:16 2008 -0800"
  },
  "committer": {
    "name": "Linus Torvalds",
    "email": "torvalds@linux-foundation.org",
    "time": "Tue Dec 23 15:58:21 2008 -0800"
  },
  "message": "edac: fix edac core deadlock when removing a device\n\nWhen deleting an edac device, we have to wait for its edac_dev.work to be\ncompleted before deleting the whole edac_dev structure.  Since we have no\nidea which work in current edac_poller\u0027s workqueue is the work we are\nconerned about, we wait for all work in the edac_poller\u0027s workqueue to be\nproceseed.  This is done via flush_cpu_workqueue() which inserts a\nwq_barrier into the tail of the workqueue and then sleeping on the\ncompletion of this wq_barrier.  The edac_poller will wake up sleepers when\nit is found.\n\nEDAC core creates only one kernel worker thread, edac_poller, to run the\nworks of all current edac devices.  They share the same callback function\nof edac_device_workq_function(), which would grab the mutex of\ndevice_ctls_mutex first before it checks the device.  This is exactly\nwhere edac_poller and rmmod would have a great chance to deadlock.\n\nIn below call trace of rmmod \u003e ... \u003e\nedac_device_del_device \u003e\nedac_device_workq_teardown \u003e flush_workqueue \u003e flush_cpu_workqueue,\n\ndevice_ctls_mutex would have already been grabbed by\nedac_device_del_device().  So, on one hand rmmod would sleep on the\ncompletion of a wq_barrier, holding device_ctls_mutex; on the other hand\nedac_poller would be blocked on the same mutex when it\u0027s running any one\nof works of existing edac evices(Note, this edac_dev.work is likely to be\ntotally irrelevant to the one that is being removed right now)and never\nwould have a chance to run the work of above wq_barrier to wake rmmod up.\n\nedac_device_workq_teardown() should not be called within the critical\nregion of device_ctls_mutex.  Just like is done in edac_pci_del_device()\nand edac_mc_del_mc(), where edac_pci_workq_teardown() and\nedac_mc_workq_teardown() are called after related mutex are released.\n\nMoreover, an edac_dev.work should check first if it is being removed.  If\nthis is the case, then it should bail out immediately.  Since not all of\nexisting edac devices are to be removed, this \"shutting flag\" should be\ncontained to edac device being removed.  The current edac_dev.op_state can\nbe used to serve this purpose.\n\nThe original deadlock problem and the solution have been witnessed and\ntested on actual hardware.  Without the solution, rmmod an edac driver\nwould result in below deadlock:\n\nroot@localhost:/root\u003e rmmod mv64x60_edac\nEDAC DEBUG: mv64x60_dma_err_remove()\nEDAC DEBUG: edac_device_del_device()\nEDAC DEBUG: find_edac_device_by_dev()\n\n(hang for a moment)\n\nINFO: task edac-poller:2030 blocked for more than 120 seconds.\n\"echo 0 \u003e /proc/sys/kernel/hung_task_timeout_secs\" disables this message.\nedac-poller   D 00000000     0  2030      2\nCall Trace:\n[df159dc0] [c0071e3c] free_hot_cold_page+0x17c/0x304 (unreliable)\n[df159e80] [c000a024] __switch_to+0x6c/0xa0\n[df159ea0] [c03587d8] schedule+0x2f4/0x4d8\n[df159f00] [c03598a8] __mutex_lock_slowpath+0xa0/0x174\n[df159f40] [e1030434] edac_device_workq_function+0x28/0xd8 [edac_core]\n[df159f60] [c003beb4] run_workqueue+0x114/0x218\n[df159f90] [c003c674] worker_thread+0x5c/0xc8\n[df159fd0] [c004106c] kthread+0x5c/0xa0\n[df159ff0] [c0013538] original_kernel_thread+0x44/0x60\nINFO: task rmmod:2062 blocked for more than 120 seconds.\n\"echo 0 \u003e /proc/sys/kernel/hung_task_timeout_secs\" disables this message.\nrmmod         D 0ff2c9fc     0  2062   1839\nCall Trace:\n[df119c00] [c0437a74] 0xc0437a74 (unreliable)\n[df119cc0] [c000a024] __switch_to+0x6c/0xa0\n[df119ce0] [c03587d8] schedule+0x2f4/0x4d8\n[df119d40] [c03591dc] schedule_timeout+0xb0/0xf4\n\nSigned-off-by: Linus Torvalds \u003ctorvalds@linux-foundation.org\u003e\n",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "5fcd3d89c75d91cda65acd42fe34be8d987e9c67",
      "old_mode": 33188,
      "old_path": "drivers/edac/edac_device.c",
      "new_id": "4041e91432837b2d2cc9b898e10f04f20cc778ce",
      "new_mode": 33188,
      "new_path": "drivers/edac/edac_device.c"
    }
  ]
}
